* Re: [PATCH 46/61] mpc885ads: Rework initialization.
From: Scott Wood @ 2007-07-18 19:31 UTC (permalink / raw)
To: Vitaly Bordug; +Cc: linuxppc-dev
In-Reply-To: <20070718222455.423ee0ba@localhost.localdomain>
Vitaly Bordug wrote:
>>The conflict is in register space, not pins -- why would the smc1
>>pins matter?
>
> ok, I may have confused this with something else.
Possibly the conflict between FEC2 and SMC2 (which is still done via
kconfig option)?
-Scott
^ permalink raw reply
* Re: Gdbserver syscall clobber
From: Bill Gatliff @ 2007-07-18 17:42 UTC (permalink / raw)
To: gdb, linuxppc-embedded
In-Reply-To: <20070716155348.GA5281@caradoc.them.org>
[-- Attachment #1: Type: text/plain, Size: 2843 bytes --]
Daniel Jacobowitz wrote:
> On Mon, Jul 16, 2007 at 10:43:41AM -0500, Bill Gatliff wrote:
>
>> recv(4, 0x7ffffd60, 1, 0) = ? ERESTARTSYS (To be restarted)
>> --- SIGIO (I/O possible) @ 0 (0) ---
>> syscall_4294966784(0xa, 0x7ffffd34, 0x1, 0, 0x1008a3c7, 0x1008b5a3, 0x1008b5a4,
>>
>
> That's -512, a.k.a. the errno value used by syscall restarting. I'd
> say your glibc does not obey the restartable syscall convention used
> by your kernel, and when it tries to restart the syscall the errno
> value is not being replaced by the syscall number. Check the assembly
> for recv.
>
>
Very good catch! Thanks soooo much. Here's the code, from my libc.a:
00000000 <__libc_recv>:
0: 94 21 ff d0 stwu r1,-48(r1)
4: 90 61 00 14 stw r3,20(r1)
8: 90 81 00 18 stw r4,24(r1)
c: 90 a1 00 1c stw r5,28(r1)
10: 90 c1 00 20 stw r6,32(r1)
14: 81 42 00 0c lwz r10,12(r2)
18: 2c 0a 00 00 cmpwi r10,0
1c: 40 82 00 20 bne- 3c <__libc_recv+0x3c>
20: 38 60 00 0a li r3,10
24: 38 81 00 14 addi r4,r1,20
28: 38 00 00 66 li r0,102
2c: 44 00 00 02 sc
30: 38 21 00 30 addi r1,r1,48
34: 4c a3 00 20 bnslr+
38: 48 00 00 00 b 38 <__libc_recv+0x38>
Again, this is 603e on linux-2.4.16 glibc-2.2.5 gcc-2.95.3. (Odd, I
can't seem to find this function in a statically-linked gdbserver, nor
any reference to it in the gdbserver-6.5 source code).
On the kernel side:
_GLOBAL(DoSyscall)
...
blrl /* Call handler */
.globl ret_from_syscall_1
ret_from_syscall_1:
20: stw r3,RESULT(r1) /* Save result */
li r10,-_LAST_ERRNO
cmpl 0,r3,r10
blt 30f
neg r3,r3
cmpi 0,r3,ERESTARTNOHAND
bne 22f
li r3,EINTR
22: lwz r10,_CCR(r1) /* Set SO bit in CR */
oris r10,r10,0x1000
stw r10,_CCR(r1)
30: stw r3,GPR3(r1) /* Update return value */
b ret_from_except
...
ret_from_except:
...
lwz r3,_CCR(r1)
...
mtcrf 0xFF,r3
...
RFI
Now, I'm a little rusty on PPC asm (I've been doing a lot of ARM
lately), but it looks to me like the kernel is setting bit 0 in CR0
(oris r10, r10, 0x1000) a.k.a LT, but the user side is looking at CR0
(bnslr+) bit 3 a.k.a. SO. Or maybe the other way around, I'm not sure
after reading Sections 1.2 and 2.1 of the Programming Environments manual.
Or am I misinterpreting something? I must be, this is well-trodden code
I'm thinking...
The readchar() in gdbserver's remote-utils.c just calls read() on the
file descriptor for the socket. Still trying to track that code down...
b.g.
--
Bill Gatliff
bgat@billgatliff.com
[-- Attachment #2: Type: text/html, Size: 5471 bytes --]
^ permalink raw reply
* Re: [PATCH 06/61] 8xx: Don't call non-existent Soft_emulate_8xx from SoftwareEmulation.
From: Scott Wood @ 2007-07-18 19:52 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <71A8ECC1-931F-42AE-98B1-A4B90E4B5980@kernel.crashing.org>
Kumar Gala wrote:
> I don't see any reason to break people that might not have updated
> their toolchains.
Full math emulation is still an option...
> There is no reason for us to drop a feature like
> this w/o some additional warning.
...as is arch/ppc, whose remaining life expectancy can serve as the
warning period.
-Scott
^ permalink raw reply
* Re: can anyone help me to test my ac97 driver
From: Joachim Förster @ 2007-07-18 20:01 UTC (permalink / raw)
To: linuxppc-embedded
In-Reply-To: <165516780.1952051184304174471.JavaMail.coremail@bj163app130.163.com>
[-- Attachment #1: Type: text/plain, Size: 1476 bytes --]
Hi silicom,
On Fri, 2007-07-13 at 13:22 +0800, silicom wrote:
> I have a simple oss ac97 playback driver for xilinx ml403 and
> linux2.6.17 kernel,but when I test it with a *.wav file with sample
> rate 44.1k, there is much noisy, and I want to know whether there's
> problem with my ml403 board or ac97 driver,could anyone be kind to
> help me test it on your board or point out my problem?
Today I took some time and tried to compile your driver, but one of the
first things I saw was that there is a file missing: "xac97_l.h". I
think, it contains your "low level" functions. If you post the file, and
I have some time, I'll test your driver and what it does on the board,
which I have available.
Furthermore your driver depends on xbasic_types.c/h, xio.c/h, which some
people might not have, too ... especially xio.c/h (in my
experience ;-) ) ...
In my last mail (last week) I announced my driver for the AC97
Controller of Xilinx and said that I'm going to release/post it. Since
then, I worked on it once more and now it seems to be pretty stable and
usable (playback support). I added capture support, too.
[Capturing basically works, but there is a problem with higher rates and
ALSA not reading from the intermediate buffer anymore ... not yet
investigated.]
My driver will be published on a website soon. I'll post the link as
soon as possible. Meanwhile, if you or anyone want to try it, just mail
me (JOFT@gmx.de).
Joachim
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 191 bytes --]
^ permalink raw reply
* Re: [PATCH 53/61] 82xx: Set NOT_COHERENT_CACHE on 8272 with PCI.
From: Scott Wood @ 2007-07-18 20:08 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev, David Gibson
In-Reply-To: <F5E8139F-E8DA-4C41-8B90-E727FD4E346C@kernel.crashing.org>
Kumar Gala wrote:
> On Jul 17, 2007, at 10:28 PM, David Gibson wrote:
>> Hrm... I for one would be a lot more comfortable with this patch if
>> you had a theoretical explanation for why it's necessary, in addition
>> to the "seems to fix things".
Sure, so would I; I just wanted to point out the issue, and make
available a quick fix for anyone else that might be having problems.
My theoretical explanation is that the hardware is broken. :-P
> I agree w/David. Have you tried turning on the CPU_FTR_NEED_COHERENT?
> Take a look at include/asm-powerpc/cputable.h and search for the
> reference to CONFIG_PPC_83xx.
OK, that appears to work as well.
-Scott
^ permalink raw reply
* Re: [patch 14/14] Bamboo zImage wrapper
From: Josh Boyer @ 2007-07-18 20:11 UTC (permalink / raw)
To: Milton Miller; +Cc: ppcdev
In-Reply-To: <1184781073.16299.29.camel@weaponx.rchland.ibm.com>
On Wed, 2007-07-18 at 12:51 -0500, Josh Boyer wrote:
> > Is there some reason they should not all be merged into this one
> > platform file?
>
> "they" meaning what?
>
> > I can understand wanting the dcr fixups as a library, but lets wait to
> > do the file splits until there are actually users. Its also easier to
> > see what's going to called when all the platform ops are filled in at
> > one spot, not spread over multiple files.
>
> I copied this from Ebony. There are multiple users already. You have
> two parts. The truly common stuff in 4xx.c and the board specific
> wrappers that do the things needed for the board.
>
> You've thoroughly confused me.
Some discussion on IRC cleared this up. Milton was suggesting I merge
the treeboot-bamboo.c and bamboo.c files together. I'm avoiding that
because I do plan on creating a cuboot Bamboo target soon.
There is a method to my madness usually.
josh
^ permalink raw reply
* Re: compile error if CONFIG_BLOCK not enabled related to linux/ide.h include
From: Bartlomiej Zolnierkiewicz @ 2007-07-18 20:44 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev, linux-kernel, linux-ide
In-Reply-To: <162F0B67-44AB-4955-873A-150224C128CB@kernel.crashing.org>
On Wednesday 18 July 2007, Kumar Gala wrote:
>
> On Jul 18, 2007, at 5:47 AM, Bartlomiej Zolnierkiewicz wrote:
>
> >
> > Hi,
> >
> > On Wednesday 18 July 2007, Kumar Gala wrote:
> >> M: bzolnier@gmail.com
> >> L: linux-ide@vger.kernel.org
> >>
> >> We get the following compile error if CONFIG_BLOCK isn't enabled:
> >>
> >> CC arch/powerpc/kernel/setup_32.o
> >> In file included from arch/powerpc/kernel/setup_32.c:14:
> >> include/linux/ide.h:558: error: expected specifier-qualifier-list
> >> before 'request_queue_t'
> >> include/linux/ide.h:696: warning: 'struct request' declared inside
> >> parameter list
> >> include/linux/ide.h:696: warning: its scope is only this
> >> definition or declaration, which is probably not what you want
> >> include/linux/ide.h:820: warning: 'struct request' declared inside
> >> parameter list
> >> include/linux/ide.h:853: error: field 'wrq' has incomplete type
> >> include/linux/ide.h:1205: error: expected ')' before '*' token
> >> make[1]: *** [arch/powerpc/kernel/setup_32.o] Error 1
> >> make: *** [arch/powerpc/kernel] Error 2
> >
> > include/linux/ide.h is exclusively for IDE subsystem
> >
> >> What I'm trying to figure out is if include/linux/ide.h should be
> >> wrapped
> >> in a #if defined(CONFIG_IDE) || defined(CONFIG_IDE_MODULE) or if
> >> there is
> >> some other desired way to handle this.
> >
> > Plese remove <linux/ide.h> include, there doesn't seem to be any
> > piece of
> > code in arch/powerpc/kernel/setup_32.c which needs it anyway.
>
> Its needed for:
>
> struct ide_machdep_calls ppc_ide_md;
>
> which gets defined in asm/ide.h which needs linux/ide.h for the defn
> of ide_init_hwif.
Ah, this is a PPC special case.
In this case I think the best solution for now is to just add #ifdefs
(the proper/clean solution would be adding IDE host drivers for PPC
platforms needing special handling).
Thanks,
Bart
^ permalink raw reply
* Re: Memory Corruption in Linux kernel MPC8347 revision 3
From: Bhupender Saharan @ 2007-07-18 21:14 UTC (permalink / raw)
To: Boris Shteinbock; +Cc: linuxppc-embedded
In-Reply-To: <1184683343.3337.57.camel@localhost.localdomain>
[-- Attachment #1: Type: text/plain, Size: 8452 bytes --]
Hi Boris,
When you are running the memory test make sure Data cahe and Instruction
caches are enabled.
Also check your BAT setting, there also Cache enable BIT shall be set.
As the burst transcation will happen only when cache is enabled.
How abt ECC...?
Bhupi
On 7/17/07, Boris Shteinbock <borish@batm.co.il> wrote:
>
> Hi Everyone.
> I am working on the Linux port for MPC8347 revision 3 custom build board
> with DDR2 memory.
>
> I've successfully ported U-boot (latest git) and the kernel itself,
> however during kernel boot I am encountering serious memory corruption
> errors. The log for one of the examples is at the bottom of this
> message.
>
> Basically, the corruption is always happening somewhere at memory
> management intensive tasks such as networking, JFFS2 mounting etc.
>
> As far as I can see, it is not related to some specific driver, because
> even it happens even at kernel configured at absolute minimum, ( console
> serial driver only and even without it)
> The place of the corruption depends on kernel configuration.
>
> The DDR2 memory controller is configured correctly as far as I can tell,
> since :
> 1. DDR2 controller register values are taken from VxWorks bootrom
> that works on this board without any problems.
> 2. u-boot mtest passes successfully
> 3. u-boot alternative mtest passes successfully
> 4. My own custom mem tests in u-boot pass successfully
> 5. If I manage two boot the board into shell prompt (with absolute
> minimum configuration) memtester application is also successful.
>
> The minimum configuration that is one I am able to boot into shell is a
> kernel configured with serial console and small busybox JFFS2 file
> system in the flash. In this configuration, the boot fails the first
> time JFFS2 root FS is mounted. However it does boot after reset.
>
> I've tried different kernels with the same results starting from, I
> think, 2.6.16 up to 2.6.22
> I tried the kernel that is provided by Freescale for 834x reference
> boards. ( with my board support of course)
>
> I tried booting both OF flat trees (powerpc) and bd_t based builds (ppc)
>
> I've also tried all memory management options :
> SLAB, SLOB and SLUB (in the latest kernel). They all failed at some
> point of time, so the assumption is that the problem is not in the
> memory management facilities.
>
> The board manufacturer swears that DDR2 memory controller values are
> correct and should work perfectly.
>
> So now I almost out of options and I am seeking your help.
> Any type of input on this issue would be greatly appreciated.
>
> Thanks,
> Boris
>
> PS. Note that an below example represents failure during DHCP
> autoconfiguration. However the similar error happens even when
> networking is disabled completely. just in a different place.
>
> => bootm
> ## Booting image at 00400000 ...
> Image Name: Linux-.6.21.5
> Created: 2007-07-10 14:20:19 UTC
> Image Type: PowerPC Linux Kernel Image (gzip compressed)
> Data Size: 898361 Bytes = 877.3 kB
> Load Address: 00000000
> Entry Point: 00000000
> Verifying Checksum ... OK
> Uncompressing Kernel Image ... OK
> ## Current stack ends at 0x07FA3CF8 => set upper limit to 0x00800000
> ## cmdline at 0x007FFF00 ... 0x007FFF41
> bd address = 0x07FA3FBC
> memstart = 0x00000000
> memsize = 0x08000000
> flashstart = 0xFE000000
> flashsize = 0x02000000
> flashoffset = 0x00033000
> sramstart = 0x00000000
> sramsize = 0x00000000
> bootflags = 0x00000001
> intfreq = 528 MHz
> busfreq = 264 MHz
> ethaddr = 00:04:9F:EF:23:35
> eth1addr = 00:E0:0C:00:7E:25
> IP addr = 10.2.222.20
> baudrate = 115200 bps
> No initrd
> ## Transferring control to Linux (at address 00000000) ...
> !!!! of_flat_tree = 00000000
> Booting without OF Flat tree
> Linux version .6.21.5 (me@localhost) (gcc version
> 4.0.0 (DENX ELDK 4.1 4.0.0)) #24 Tue Jul 10 17:20:09 IDT 2007
> Zone PFN ranges:
> DMA 0 -> 32768
> Normal 32768 -> 32768
> early_node_map[1] active PFN ranges
> 0: 0 -> 32768
> Built 1 zonelists. Total pages: 32512
> Kernel command line: console=ttyS0,115200 root=/dev/mtdblock1
> rootfstype=jffs2 ip=dhcp
> IPIC (128 IRQ sources, 8 External IRQs) at fe000700
> PID hash table entries: 512 (order: 9, 2048 bytes)
> Dentry cache hash table entries: 16384 (order: 4, 65536 bytes)
> Inode-cache hash table entries: 8192 (order: 3, 32768 bytes)
> Memory: 127744k available (1584k kernel code, 444k data, 84k init, 0k
> highmem)
> Mount-cache hash table entries: 512
> NET: Registered protocol family 16
> Setup MTD partitions
> Generic PHY: Registered new driver
> NET: Registered protocol family 2
> IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
> TCP established hash table entries: 4096 (order: 3, 32768 bytes)
> TCP bind hash table entries: 4096 (order: 2, 16384 bytes)
> TCP: Hash tables configured (established 4096 bind 4096)
> TCP reno registered
> JFFS2 version 2.2. (NAND) (C) 2001-2006 Red Hat, Inc.
> io scheduler noop registered
> io scheduler anticipatory registered (default)
> io scheduler deadline registered
> io scheduler cfq registered
> Serial: 8250/16550 driver $Revision: 1.90 $ 2 ports, IRQ sharing
> disabled
> serial8250.0: ttyS0 at MMIO 0xe0004500 (irq = 9) is a 16550A
> serial8250.0: ttyS1 at MMIO 0xe0004600 (irq = 10) is a 16550A
> Gianfar MII Bus: probed
> eth0: Gianfar Ethernet Controller Version 1.2, 00:04:9f:ef:23:35
> eth0: Running with NAPI disabled
> eth0: 64/64 RX/TX BD ring size
> Broadcom BCM5241: Registered new driver
> physmap platform flash device: 02000000 at fe000000
> physmap-flash.0: Found 1 x16 devices at 0x0 in 8-bit bank
> Amd/Fujitsu Extended Query Table at 0x0040
> physmap-flash.0: CFI does not contain boot bank location. Assuming top.
> number of CFI chips: 1
> cfi_cmdset_0002: Disabling erase-suspend-program due to code brokenness.
> cmdlinepart partition parsing not available
> RedBoot partition parsing not available
> Using physmap partition information
> Creating 2 MTD partitions on "physmap-flash.0":
> 0x00000000-0x00100000 : "uboot"
> 0x00100000-0x02000000 : "rootfs"
> IPv4 over IPv4 tunneling driver
> GRE over IPv4 tunneling driver
> TCP cubic registered
> NET: Registered protocol family 1
> NET: Registered protocol family 17
> !!!! Gianfar init_phy. phy_id = 0:01
> !!!! phy_attach. phy_id = 0:01
> !!!! phy_attach device found. phy_id = 0:01
> Sending DHCP requests .<3>slab: Internal list corruption detected in
> cache 'files_cache'(21), slabp c0344000(16). Hexdump:
>
> 000: 00 10 01 00 00 20 02 00 00 00 00 70 c0 34 40 70
> 010: 00 00 00 10 00 00 ff 10 00 00 00 00 ff ff ff fe
> 020: ff ff ff fe ff ff ff fe ff ff ff fe ff ff ff fe
> 030: ff ff ff fe ff ff ff fe ff ff ff fe ff ff ff fe
> 040: ff ff ff fe ff ff ff fe ff ff ff fe ff ff ff fe
> 050: ff ff ff fe ff ff ff fe ff ff ff fd 00 00 00 11
> 060: 00 00 00 12 00 00 00 13 00 00 00 14 ff ff ff ff
> ------------[ cut here ]------------
> kernel BUG at mm/slab.c:2936!
> Oops: Exception in kernel mode, sig: 5 [#1]
> NIP: C0050F80 LR: C0050F80 CTR: 00000000
> REGS: c034fe00 TRAP: 0700 Not tainted (.6.21.5)
> MSR: 00021032 <ME,IR,DR> CR: 24004002 XER: 00000000
> TASK = c032a3c0[3] 'events/0' THREAD: c034e000
> GPR00: C0050F80 C034FEB0 C032A3C0 00000001 00000DF5 FFFFFFFF C00F5B54
> 00000010
> GPR08: C01D0000 C01E0000 00000DF5 00000DF5 00000000 00F1C5DB 07FFD000
> FFFFFFFF
> GPR16: 00000001 00000000 00000000 00800000 00000000 007FFF00 00000000
> C033DAA0
> GPR24: C0339C90 00000007 00000000 C01B0000 C01B0000 C0344000 C033DAA0
> 00000070
> NIP [C0050F80] check_slabp+0xe4/0x11c
> LR [C0050F80] check_slabp+0xe4/0x11c
> Call Trace:
> [C034FEB0] [C0050F80] check_slabp+0xe4/0x11c (unreliable)
> [C034FED0] [C0051450] free_block+0x88/0x138
> [C034FF00] [C0052188] drain_array+0xa0/0xe0
> [C034FF20] [C0052228] cache_reap+0x60/0x144
> [C034FF40] [C00257B0] run_workqueue+0xd0/0x170
> [C034FF60] [C0025960] worker_thread+0x110/0x144
> [C034FFC0] [C00298E4] kthread+0x74/0xb0
> [C034FFF0] [C0005F38] kernel_thread+0x44/0x60
> Instruction dump:
> 387b6538 7c9df8ae 4bfc2b49 3bff0001 813e0020 5529103a 3929001c 7f9f4840
> 419cffcc 3c60c01b 3863336c 4bfc2b25 <0fe00000> 48000000 80030020
> 2f800000
>
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
>
[-- Attachment #2: Type: text/html, Size: 10299 bytes --]
^ permalink raw reply
* Re: [PATCH] Add StorCenter DTS first draft.
From: Benjamin Herrenschmidt @ 2007-07-18 21:54 UTC (permalink / raw)
To: Segher Boessenkool; +Cc: linuxppc-dev, Jon Loeliger
In-Reply-To: <5F6EB5F7-C5AE-437F-9DF1-22FE38D7A841@kernel.crashing.org>
On Wed, 2007-07-18 at 18:13 +0200, Segher Boessenkool wrote:
> >> + PowerPC,603e { /* Really 8241 */
> >> + device_type = "cpu";
> >> + reg = <0>;
> >> + clock-frequency = <d# 200000000>; /* Hz */
> >> + timebase-frequency = <d# 33333333>; /* Hz */
> >> + bus-frequency = <0>;
> >> + /* Following required by dtc but not used */
> >> + i-cache-line-size = <0>;
> >> + d-cache-line-size = <0>;
> >> + i-cache-size = <4000>;
> >> + d-cache-size = <4000>;
> >> + };
> >
> > The 32 bits kernel may not be using those yet, but it will. 64 bits
> > does
> > already and I plan to merge those bits at one point.
>
> Hrm, what does it use it for? Are you going to require
> all other defined CPU properties as well (like the PowerPC
> binding does)?
Cache line size is used by the kernel on ppc64 for things like clearing
memory (to get the stride between subsequent dcbz) or flushing the
cache :-) It's also passed on to userland.
If it's absent from the device-tree, we default to the values in the
cputable, but if you're going to put the properties in the tree, don't
put a 0 in there. As it is, the day I make the 64 bits code common, your
DT will break unless I special case "0".
Ben.
^ permalink raw reply
* [PATCH] fix future firmware feature fixups function failure
From: Michael Neuling @ 2007-07-18 21:56 UTC (permalink / raw)
To: Arnd Bergmann; +Cc: paulus, linuxppc-dev
In-Reply-To: <200707111329.51580.arnd@arndb.de>
Move firmware feature initialisation from pSeries_init_early to the
earlier pSeries_probe_hypertas so they are initialised before firmware
feature fixups are applied.
Currently firmware feature sections are only used for iSeries which
initialises the these features much earlier. This is a bug in waiting
on pSeries.
Also adds some whitespace fixups.
Signed-off-by: Michael Neuling <mikey@neuling.org>
---
> > There are two possibly solutions I see in the long run:
> >=20
> > =A0- We could set the FW features earlier on pseries, though that is a bit
> > annoying because that means doing it before the device-tree is
> > unflattened.
> >=20
> > =A0- We could constraint lmb_alloc to the first segment until the FW fixup
> > occurs, either within lmb_alloc itself, or fixup the callers such as
> > unflatten_device_tree, to pass an explicit limit.
> >=20
> > What do you think ?
>
> If I'm understanding this right, the first solution should be something
> along the lines of the patch below (not tested), which even removes
> more lines than it adds. It doesn't seem that annoying to me, and it
> makes sense to assume that the fw_features are set up after returning
> from the ppc_md probe.
I've cleaned this up and got it booting. Seems to be doing the right
things as I can see fw feature sections being correctly NOPed out now
after boot.
I've booted with pseries_defconfig and ppc64_defconfig.
Arnd, I've added a signed off by me, but it but this probably needs an
explicit one from you also before it heads up.
Mikey
arch/powerpc/platforms/pseries/firmware.c | 19 +++----------------
arch/powerpc/platforms/pseries/pseries.h | 2 +-
arch/powerpc/platforms/pseries/setup.c | 17 +++++++++++------
3 files changed, 15 insertions(+), 23 deletions(-)
Index: linux-2.6-ozlabs/arch/powerpc/platforms/pseries/firmware.c
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/platforms/pseries/firmware.c
+++ linux-2.6-ozlabs/arch/powerpc/platforms/pseries/firmware.c
@@ -66,24 +66,13 @@ firmware_features_table[FIRMWARE_MAX_FEA
* device-tree/ibm,hypertas-functions. Ultimately this functionality may
* be moved into prom.c prom_init().
*/
-void __init fw_feature_init(void)
+void __init fw_feature_init(const char *hypertas, unsigned long len)
{
- struct device_node *dn;
- const char *hypertas, *s;
- int len, i;
+ const char *s;
+ int i;
DBG(" -> fw_feature_init()\n");
- dn = of_find_node_by_path("/rtas");
- if (dn == NULL) {
- printk(KERN_ERR "WARNING! Cannot find RTAS in device-tree!\n");
- goto out;
- }
-
- hypertas = of_get_property(dn, "ibm,hypertas-functions", &len);
- if (hypertas == NULL)
- goto out;
-
for (s = hypertas; s < hypertas + len; s += strlen(s) + 1) {
for (i = 0; i < FIRMWARE_MAX_FEATURES; i++) {
/* check value against table of strings */
@@ -98,7 +87,5 @@ void __init fw_feature_init(void)
}
}
-out:
- of_node_put(dn);
DBG(" <- fw_feature_init()\n");
}
Index: linux-2.6-ozlabs/arch/powerpc/platforms/pseries/pseries.h
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/platforms/pseries/pseries.h
+++ linux-2.6-ozlabs/arch/powerpc/platforms/pseries/pseries.h
@@ -10,7 +10,7 @@
#ifndef _PSERIES_PSERIES_H
#define _PSERIES_PSERIES_H
-extern void __init fw_feature_init(void);
+extern void __init fw_feature_init(const char *hypertas, unsigned long len);
struct pt_regs;
Index: linux-2.6-ozlabs/arch/powerpc/platforms/pseries/setup.c
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/platforms/pseries/setup.c
+++ linux-2.6-ozlabs/arch/powerpc/platforms/pseries/setup.c
@@ -320,8 +320,6 @@ static void __init pSeries_init_early(vo
{
DBG(" -> pSeries_init_early()\n");
- fw_feature_init();
-
if (firmware_has_feature(FW_FEATURE_LPAR))
find_udbg_vterm();
@@ -343,14 +341,21 @@ static int __init pSeries_probe_hypertas
const char *uname, int depth,
void *data)
{
+ const char *hypertas;
+ unsigned long len;
+
if (depth != 1 ||
(strcmp(uname, "rtas") != 0 && strcmp(uname, "rtas@0") != 0))
- return 0;
+ return 0;
+
+ hypertas = of_get_flat_dt_prop(node, "ibm,hypertas-functions", &len);
+ if (!hypertas)
+ return 1;
- if (of_get_flat_dt_prop(node, "ibm,hypertas-functions", NULL) != NULL)
- powerpc_firmware_features |= FW_FEATURE_LPAR;
+ powerpc_firmware_features |= FW_FEATURE_LPAR;
+ fw_feature_init(hypertas, len);
- return 1;
+ return 1;
}
static int __init pSeries_probe(void)
^ permalink raw reply
* Re: [RFC 0/3] lro: Generic Large Receive Offload for TCP traffic (IPv6)
From: David Miller @ 2007-07-18 22:23 UTC (permalink / raw)
To: ossthema
Cc: tklein, themann, netdev, linux-kernel, hch, linuxppc-dev, raisch,
meder, stefan.roscher
In-Reply-To: <200707181501.00163.ossthema@de.ibm.com>
From: Jan-Bernd Themann <ossthema@de.ibm.com>
Date: Wed, 18 Jul 2007 15:00:59 +0200
> Hi,
>
> I suggest we keep the interface open for IPv6 support by adding
> an additional parameter but first just get IPv4 support only
> into the kernel. IPv6 support can then incrementially be added.
> Would that be ok?
I guess so.
^ permalink raw reply
* Re: [PATCH 1/4] ibmveth: Enable TCP checksum offload
From: Jeff Garzik @ 2007-07-18 22:32 UTC (permalink / raw)
To: Brian King; +Cc: linuxppc-dev, rcjenn, santil, netdev
In-Reply-To: <11846854701127-patch-mail.ibm.com>
Brian King wrote:
> This patchset enables TCP checksum offload support for IPV4
> on ibmveth. This completely eliminates the generation and checking of
> the checksum for packets that are completely virtual and never
> touch a physical network. A simple TCP_STREAM netperf run on
> a virtual network with maximum mtu set yielded a ~30% increase
> in throughput. This feature is enabled by default on systems that
> support it, but can be disabled with a module option.
>
> Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
this should be controllable purely via ethtool...
> diff -puN drivers/net/ibmveth.c~ibmveth_csum_offload drivers/net/ibmveth.c
> --- linux-2.6/drivers/net/ibmveth.c~ibmveth_csum_offload 2007-07-12 08:27:47.000000000 -0500
> +++ linux-2.6-bjking1/drivers/net/ibmveth.c 2007-07-12 09:35:55.000000000 -0500
> @@ -47,6 +47,8 @@
> #include <linux/mm.h>
> #include <linux/ethtool.h>
> #include <linux/proc_fs.h>
> +#include <linux/in.h>
> +#include <linux/ip.h>
> #include <asm/semaphore.h>
> #include <asm/hvcall.h>
> #include <asm/atomic.h>
> @@ -103,12 +105,15 @@ static struct proc_dir_entry *ibmveth_pr
>
> static const char ibmveth_driver_name[] = "ibmveth";
> static const char ibmveth_driver_string[] = "IBM i/pSeries Virtual Ethernet Driver";
> +static unsigned int ibmveth_csum_offload = 1;
> #define ibmveth_driver_version "1.03"
>
> MODULE_AUTHOR("Santiago Leon <santil@us.ibm.com>");
> MODULE_DESCRIPTION("IBM i/pSeries Virtual Ethernet Driver");
> MODULE_LICENSE("GPL");
> MODULE_VERSION(ibmveth_driver_version);
> +module_param_named(csum_offload, ibmveth_csum_offload, uint, 0);
> +MODULE_PARM_DESC(csum_offload, "Checksum offload (0/1). Default: 1");
>
> /* simple methods of getting data from the current rxq entry */
> static inline int ibmveth_rxq_pending_buffer(struct ibmveth_adapter *adapter)
> @@ -131,6 +136,11 @@ static inline int ibmveth_rxq_frame_leng
> return (adapter->rx_queue.queue_addr[adapter->rx_queue.index].length);
> }
>
> +static inline int ibmveth_rxq_csum_good(struct ibmveth_adapter *adapter)
> +{
> + return (adapter->rx_queue.queue_addr[adapter->rx_queue.index].csum_good);
> +}
> +
> /* setup the initial settings for a buffer pool */
> static void ibmveth_init_buffer_pool(struct ibmveth_buff_pool *pool, u32 pool_index, u32 pool_size, u32 buff_size, u32 pool_active)
> {
> @@ -684,6 +694,24 @@ static int ibmveth_start_xmit(struct sk_
> desc[0].fields.length, DMA_TO_DEVICE);
> desc[0].fields.valid = 1;
>
> + if (skb->ip_summed == CHECKSUM_PARTIAL &&
> + ip_hdr(skb)->protocol != IPPROTO_TCP && skb_checksum_help(skb)) {
> + ibmveth_error_printk("tx: failed to checksum packet\n");
> + tx_dropped++;
> + goto out;
> + }
> +
> + if (skb->ip_summed == CHECKSUM_PARTIAL) {
> + unsigned char *buf = skb_transport_header(skb) + skb->csum_offset;
> +
> + desc[0].fields.no_csum = 1;
> + desc[0].fields.csum_good = 1;
> +
> + /* Need to zero out the checksum */
> + buf[0] = 0;
> + buf[1] = 0;
> + }
> +
> if(dma_mapping_error(desc[0].fields.address)) {
> ibmveth_error_printk("tx: unable to map initial fragment\n");
> tx_map_failed++;
> @@ -702,6 +730,10 @@ static int ibmveth_start_xmit(struct sk_
> frag->size, DMA_TO_DEVICE);
> desc[curfrag+1].fields.length = frag->size;
> desc[curfrag+1].fields.valid = 1;
> + if (skb->ip_summed == CHECKSUM_PARTIAL) {
> + desc[curfrag+1].fields.no_csum = 1;
> + desc[curfrag+1].fields.csum_good = 1;
> + }
>
> if(dma_mapping_error(desc[curfrag+1].fields.address)) {
> ibmveth_error_printk("tx: unable to map fragment %d\n", curfrag);
> @@ -792,7 +824,11 @@ static int ibmveth_poll(struct net_devic
> } else {
> int length = ibmveth_rxq_frame_length(adapter);
> int offset = ibmveth_rxq_frame_offset(adapter);
> + int csum_good = ibmveth_rxq_csum_good(adapter);
> +
> skb = ibmveth_rxq_get_buffer(adapter);
> + if (csum_good)
> + skb->ip_summed = CHECKSUM_UNNECESSARY;
>
> ibmveth_rxq_harvest_buffer(adapter);
>
> @@ -962,8 +998,10 @@ static void ibmveth_poll_controller(stru
> static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
> {
> int rc, i;
> + long ret;
> struct net_device *netdev;
> struct ibmveth_adapter *adapter = NULL;
> + union ibmveth_illan_attributes set_attr, ret_attr;
>
> unsigned char *mac_addr_p;
> unsigned int *mcastFilterSize_p;
> @@ -1058,6 +1096,26 @@ static int __devinit ibmveth_probe(struc
>
> ibmveth_debug_printk("registering netdev...\n");
>
> + if (ibmveth_csum_offload) {
> + ret = h_illan_attributes(dev->unit_address, 0, 0, &ret_attr.desc);
> +
> + if (ret == H_SUCCESS && !ret_attr.fields.active_trunk &&
> + !ret_attr.fields.trunk_priority &&
> + ret_attr.fields.csum_offload_padded_pkt_support) {
> + set_attr.desc = 0;
> + set_attr.fields.tcp_csum_offload_ipv4 = 1;
> +
> + ret = h_illan_attributes(dev->unit_address, 0, set_attr.desc,
> + &ret_attr.desc);
> +
> + if (ret == H_SUCCESS)
> + netdev->features |= NETIF_F_IP_CSUM;
> + else
> + ret = h_illan_attributes(dev->unit_address, set_attr.desc,
> + 0, &ret_attr.desc);
> + }
> + }
> +
> rc = register_netdev(netdev);
>
> if(rc) {
> diff -puN drivers/net/ibmveth.h~ibmveth_csum_offload drivers/net/ibmveth.h
> --- linux-2.6/drivers/net/ibmveth.h~ibmveth_csum_offload 2007-07-12 08:27:47.000000000 -0500
> +++ linux-2.6-bjking1/drivers/net/ibmveth.h 2007-07-12 09:32:54.000000000 -0500
> @@ -67,6 +67,21 @@ static inline long h_send_logical_lan(un
> return rc;
> }
>
> +static inline long h_illan_attributes(unsigned long unit_address,
> + unsigned long reset_mask, unsigned long set_mask,
> + unsigned long *ret_attributes)
> +{
> + long rc;
> + unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
> +
> + rc = plpar_hcall(H_ILLAN_ATTRIBUTES, retbuf, unit_address,
> + reset_mask, set_mask);
> +
> + *ret_attributes = retbuf[0];
> +
> + return rc;
> +}
> +
> #define h_multicast_ctrl(ua, cmd, mac) \
> plpar_hcall_norets(H_MULTICAST_CTRL, ua, cmd, mac)
>
> @@ -144,7 +159,9 @@ struct ibmveth_adapter {
> struct ibmveth_buf_desc_fields {
> u32 valid : 1;
> u32 toggle : 1;
> - u32 reserved : 6;
> + u32 reserved : 4;
> + u32 no_csum : 1;
> + u32 csum_good : 1;
> u32 length : 24;
> u32 address;
> };
> @@ -154,10 +171,30 @@ union ibmveth_buf_desc {
> struct ibmveth_buf_desc_fields fields;
> };
>
> +struct ibmveth_illan_attributes_fields {
> + u32 reserved;
> + u32 reserved2 : 18;
> + u32 csum_offload_padded_pkt_support : 1;
> + u32 reserved3 : 1;
> + u32 trunk_priority : 4;
> + u32 reserved4 : 5;
> + u32 tcp_csum_offload_ipv6 : 1;
> + u32 tcp_csum_offload_ipv4 : 1;
> + u32 active_trunk : 1;
> +};
> +
> +union ibmveth_illan_attributes {
> + u64 desc;
> + struct ibmveth_illan_attributes_fields fields;
> +};
> +
> struct ibmveth_rx_q_entry {
> u16 toggle : 1;
> u16 valid : 1;
> - u16 reserved : 14;
> + u16 reserved : 4;
> + u16 no_csum : 1;
> + u16 csum_good : 1;
> + u16 reserved2 : 8;
> u16 offset;
As a general rule, it would be nice to start moving away from bitfields
in this driver
^ permalink raw reply
* Re: [PATCH 2/4] ibmveth: Implement ethtool hooks to enable/disable checksum offload
From: Jeff Garzik @ 2007-07-18 22:33 UTC (permalink / raw)
To: Brian King; +Cc: linuxppc-dev, rcjenn, santil, netdev
In-Reply-To: <200707171517.l6HFHwf2015030@d03av04.boulder.ibm.com>
Brian King wrote:
> This patch adds the appropriate ethtool hooks to allow for enabling/disabling
> of hypervisor assisted checksum offload for TCP.
>
> Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
> ---
>
> linux-2.6-bjking1/drivers/net/ibmveth.c | 120 +++++++++++++++++++++++++++++++-
> linux-2.6-bjking1/drivers/net/ibmveth.h | 1
> 2 files changed, 119 insertions(+), 2 deletions(-)
ACK. As noted in previous email, with this, module option is not needed
^ permalink raw reply
* Re: [PATCH 4/4] ibmveth: Add ethtool driver stats hooks
From: Jeff Garzik @ 2007-07-18 22:34 UTC (permalink / raw)
To: Brian King; +Cc: linuxppc-dev, rcjenn, santil, netdev
In-Reply-To: <200707171518.l6HFICqM006034@d03av02.boulder.ibm.com>
Brian King wrote:
> Add ethtool hooks to ibmveth to retrieve driver statistics.
>
>
ACK patches 3-4
^ permalink raw reply
* Re: [PATCH] PHY fixed driver: rework release path and update phy_id notation
From: Jeff Garzik @ 2007-07-18 22:35 UTC (permalink / raw)
To: Vitaly Bordug; +Cc: linuxppc-dev, linux-kernel, netdev
In-Reply-To: <20070717000723.8144.19520.stgit@localhost.localdomain>
Vitaly Bordug wrote:
> device_bind_driver() error code returning has been fixed.
> release() function has been written, so that to free resources
> in correct way; the release path is now clean.
>
> Before the rework, it used to cause
> Device 'fixed@100:1' does not have a release() function, it is broken
> and must be fixed.
> BUG: at drivers/base/core.c:104 device_release()
>
> Call Trace:
> [<ffffffff802ec380>] kobject_cleanup+0x53/0x7e
> [<ffffffff802ec3ab>] kobject_release+0x0/0x9
> [<ffffffff802ecf3f>] kref_put+0x74/0x81
> [<ffffffff8035493b>] fixed_mdio_register_device+0x230/0x265
> [<ffffffff80564d31>] fixed_init+0x1f/0x35
> [<ffffffff802071a4>] init+0x147/0x2fb
> [<ffffffff80223b6e>] schedule_tail+0x36/0x92
> [<ffffffff8020a678>] child_rip+0xa/0x12
> [<ffffffff80311714>] acpi_ds_init_one_object+0x0/0x83
> [<ffffffff8020705d>] init+0x0/0x2fb
> [<ffffffff8020a66e>] child_rip+0x0/0x12
>
>
> Also changed the notation of the fixed phy definition on
> mdio bus to the form of <speed>+<duplex> to make it able to be used by
> gianfar and ucc_geth that define phy_id strictly as "%d:%d" and cleaned up
> the whitespace issues.
>
> Signed-off-by: Vitaly Bordug <vitb@kernel.crashing.org>
>
> ---
>
> drivers/net/phy/Kconfig | 14 ++
> drivers/net/phy/fixed.c | 310 ++++++++++++++++++++++++-----------------------
> 2 files changed, 169 insertions(+), 155 deletions(-)
>
> diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
> index dd09011..432c210 100644
> --- a/drivers/net/phy/Kconfig
> +++ b/drivers/net/phy/Kconfig
> @@ -76,4 +76,18 @@ config FIXED_MII_100_FDX
> bool "Emulation for 100M Fdx fixed PHY behavior"
> depends on FIXED_PHY
>
> +config FIXED_MII_1000_FDX
> + bool "Emulation for 1000M Fdx fixed PHY behavior"
> + depends on FIXED_PHY
> +
> +config FIXED_MII_AMNT
> + int "Number of emulated PHYs to allocate "
> + depends on FIXED_PHY
> + default "1"
> + ---help---
> + Sometimes it is required to have several independent emulated
> + PHYs on the bus (in case of multi-eth but phy-less HW for instance).
> + This control will have specified number allocated for each fixed
> + PHY type enabled.
addition of new config options etc. should be in a separate patch from
the fix, since they are separate logical changes
^ permalink raw reply
* Re: [PATCH] eHEA: Fix bonding support
From: Jeff Garzik @ 2007-07-18 22:39 UTC (permalink / raw)
To: Thomas Klein
Cc: Thomas Klein, Jan-Bernd Themann, netdev, linux-kernel,
Christoph Raisch, Stefan Roscher, linux-ppc, Jan-Bernd Themann,
Marcus Eder
In-Reply-To: <200707181734.09278.osstklei@de.ibm.com>
Thomas Klein wrote:
> The driver didn't allow an interface's MAC address to be modified if the
> respective interface wasn't setup - a failing Hcall was the result. Thus
> bonding wasn't usable. The fix moves the failing Hcall which was registering
> a MAC address for the reception of BC packets in firmware from the port up
> and down functions to the port resources setup functions. Additionally the
> missing update of the last_rx member of the netdev structure was added.
>
> Signed-off-by: Thomas Klein <tklein@de.ibm.com>
>
> ---
> drivers/net/ehea/ehea.h | 2 +-
> drivers/net/ehea/ehea_main.c | 37 +++++++++++++++++++------------------
> 2 files changed, 20 insertions(+), 19 deletions(-)
applied
^ permalink raw reply
* Re: [PATCH] fix future firmware feature fixups function failure
From: Arnd Bergmann @ 2007-07-18 22:54 UTC (permalink / raw)
To: Michael Neuling; +Cc: paulus, linuxppc-dev
In-Reply-To: <24414.1184795792@neuling.org>
On Wednesday 18 July 2007, Michael Neuling wrote:
> Move firmware feature initialisation from pSeries_init_early to the
> earlier pSeries_probe_hypertas so they are initialised before firmware
> feature fixups are applied.
>=20
> Currently firmware feature sections are only used for iSeries which
> initialises the these features much earlier. =A0This is a bug in waiting
> on pSeries.
>=20
> Also adds some whitespace fixups.
>=20
> Signed-off-by: Michael Neuling <mikey@neuling.org>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Haven't tested it myself, but it certainly looks good to me. It does
require reverting your previous patch though, are you submitting the
reversal patch as well?
Arnd <><
^ permalink raw reply
* Re: [patch 1/3] ps3: Disk Storage Driver
From: Andrew Morton @ 2007-07-18 23:36 UTC (permalink / raw)
To: Geert Uytterhoeven, Andy Whitcroft
Cc: Jens Axboe, James E.J. Bottomley, linux-scsi, linux-kernel,
Alessandro Rubini, linuxppc-dev, Paul Mackerras, Jens Axboe
In-Reply-To: <20070716162206.392129000@pademelon.sonytel.be>
On Mon, 16 Jul 2007 18:15:40 +0200
Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com> wrote:
> From: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
>
> Add a Disk Storage Driver for the PS3:
Your patchset significantly hits powerpc, scsi and block. So who gets to
merge this? Jens? James? Paul?
Me, I guess ;)
> - Implemented as a block device driver with a dynamic major
> - Disk names (and partitions) are of the format ps3d%c(%u)
> - Uses software scatter-gather with a 64 KiB bounce buffer as the hypervisor
> doesn't support scatter-gather
>
> ...
>
> --- /dev/null
> +++ b/drivers/block/ps3disk.c
> @@ -0,0 +1,624 @@
> +/*
> + * PS3 Disk Storage Driver
> + *
> + * Copyright (C) 2007 Sony Computer Entertainment Inc.
> + * Copyright 2007 Sony Corp.
> + *
> + * 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; version 2 of the License.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> + */
> +
> +#include <linux/ata.h>
> +#include <linux/blkdev.h>
> +
> +#include <asm/lv1call.h>
> +#include <asm/ps3stor.h>
> +#include <asm/firmware.h>
> +
> +
> +#define DEVICE_NAME "ps3disk"
> +
> +#define BOUNCE_SIZE (64*1024)
> +
> +#define PS3DISK_MAX_DISKS 16
> +#define PS3DISK_MINORS 16
> +
> +#define KERNEL_SECTOR_SIZE 512
Sigh. We have at least ten separate definitions of SECTOR_SIZE< none of
them in the right place. Cleanup opportunity for someone.
> +
> +#define PS3DISK_NAME "ps3d%c"
> +
> +
> +struct ps3disk_private {
> + spinlock_t lock; /* Request queue spinlock */
> + struct request_queue *queue;
> + struct gendisk *gendisk;
> + unsigned int blocking_factor;
> + struct request *req;
> + u64 raw_capacity;
> + unsigned char model[ATA_ID_PROD_LEN+1];
> +};
> +#define ps3disk_priv(dev) ((dev)->sbd.core.driver_data)
hm, this code has "ata" all over it and actually uses a libata #define (at
least) but there is no Kconfig dependency on ATA. Fair enough, I guess,
but a bit funny-looking.
> +static void ps3disk_scatter_gather(struct ps3_storage_device *dev,
> + struct request *req, int gather)
> +{
> + unsigned int sectors = 0, offset = 0;
> + struct bio *bio;
> + sector_t sector;
> + struct bio_vec *bvec;
> + unsigned int i = 0, j;
> + size_t size;
> + void *buf;
> +
> + rq_for_each_bio(bio, req) {
> + sector = bio->bi_sector;
> + dev_dbg(&dev->sbd.core,
> + "%s:%u: bio %u: %u segs %u sectors from %lu\n",
> + __func__, __LINE__, i, bio_segments(bio),
> + bio_sectors(bio), sector);
> + bio_for_each_segment(bvec, bio, j) {
> + size = bio_cur_sectors(bio)*KERNEL_SECTOR_SIZE;
> + buf = __bio_kmap_atomic(bio, j, KM_IRQ0);
> + if (gather)
> + memcpy(dev->bounce_buf+offset, buf, size);
> + else
> + memcpy(buf, dev->bounce_buf+offset, size);
> + offset += size;
> + flush_kernel_dcache_page(bio_iovec_idx(bio, j)->bv_page);
> + __bio_kunmap_atomic(bio, KM_IRQ0);
> + }
> + sectors += bio_sectors(bio);
> + i++;
> + }
> +}
Local variable `sectors' doesn't do anything.
> +static int ps3disk_submit_request_sg(struct ps3_storage_device *dev,
> + struct request *req)
> +{
> + struct ps3disk_private *priv = ps3disk_priv(dev);
> + int write = rq_data_dir(req), res;
> + const char *op = write ? "write" : "read";
> + u64 start_sector, sectors;
> + unsigned int region_id = dev->regions[dev->region_idx].id;
So we're ignoring the sector_t stuff. I guess it's 64-bit only. Still, it
might be nice to use sector_t for consistency, readability and possible
future 32-bitness?
> +#ifdef DEBUG
> + unsigned int n = 0;
> + struct bio *bio;
> + rq_for_each_bio(bio, req)
> + n++;
I'm surprised that the block core doesn't have a helper to count the number
of bios in a request.
Please prefer to put a blank line between end-of-locals and start-of-code.
> + dev_dbg(&dev->sbd.core,
> + "%s:%u: %s req has %u bios for %lu sectors %lu hard sectors\n",
> + __func__, __LINE__, op, n, req->nr_sectors,
> + req->hard_nr_sectors);
> +#endif
> +
> + start_sector = req->sector*priv->blocking_factor;
> + sectors = req->nr_sectors*priv->blocking_factor;
s/*/ * /. checkpatch missed this.
I suspect you didn't run cehckpatch anyway.
Please run checkpatch.
> + dev_dbg(&dev->sbd.core, "%s:%u: %s %lu sectors starting at %lu\n",
> + __func__, __LINE__, op, sectors, start_sector);
> +
> + if (write) {
> + ps3disk_scatter_gather(dev, req, 1);
> +
> + res = lv1_storage_write(dev->sbd.dev_id, region_id,
> + start_sector, sectors, 0,
> + dev->bounce_lpar, &dev->tag);
> + } else {
> + res = lv1_storage_read(dev->sbd.dev_id, region_id,
> + start_sector, sectors, 0,
> + dev->bounce_lpar, &dev->tag);
> + }
> + if (res) {
> + dev_err(&dev->sbd.core, "%s:%u: %s failed %d\n", __func__,
> + __LINE__, op, res);
> + end_request(req, 0);
> + return 0;
> + }
> +
> + priv->req = req;
> + return 1;
> +}
> +
>
> ...
>
> +
> +/* ATA helpers copied from drivers/ata/libata-core.c */
ooh, bad person.
> +static void swap_buf_le16(u16 *buf, unsigned int buf_words)
> +{
> +#ifdef __BIG_ENDIAN
> + unsigned int i;
> +
> + for (i = 0; i < buf_words; i++)
> + buf[i] = le16_to_cpu(buf[i]);
> +#endif /* __BIG_ENDIAN */
> +}
> +
> +static u64 ata_id_n_sectors(const u16 *id)
> +{
> + if (ata_id_has_lba(id)) {
> + if (ata_id_has_lba48(id))
> + return ata_id_u64(id, 100);
> + else
> + return ata_id_u32(id, 60);
> + } else {
> + if (ata_id_current_chs_valid(id))
> + return ata_id_u32(id, 57);
> + else
> + return id[1] * id[3] * id[6];
> + }
> +}
> +
> +static void ata_id_string(const u16 *id, unsigned char *s, unsigned int ofs,
> + unsigned int len)
> +{
> + unsigned int c;
> +
> + while (len > 0) {
> + c = id[ofs] >> 8;
> + *s = c;
> + s++;
> +
> + c = id[ofs] & 0xff;
> + *s = c;
> + s++;
> +
> + ofs++;
> + len -= 2;
> + }
> +}
> +
> +static void ata_id_c_string(const u16 *id, unsigned char *s, unsigned int ofs,
> + unsigned int len)
> +{
> + unsigned char *p;
> +
> + WARN_ON(!(len & 1));
> +
> + ata_id_string(id, s, ofs, len - 1);
> +
> + p = s + strnlen(s, len - 1);
> + while (p > s && p[-1] == ' ')
> + p--;
> + *p = '\0';
> +}
> +
>
> ...
>
> +static unsigned long ps3disk_mask;
> +
> +static int __devinit ps3disk_probe(struct ps3_system_bus_device *_dev)
> +{
> + struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
> + struct ps3disk_private *priv;
> + int error;
> + unsigned int devidx;
> + struct request_queue *queue;
> + struct gendisk *gendisk;
> +
> + if (dev->blk_size < KERNEL_SECTOR_SIZE) {
> + dev_err(&dev->sbd.core,
> + "%s:%u: cannot handle block size %lu\n", __func__,
> + __LINE__, dev->blk_size);
> + return -EINVAL;
> + }
> +
> + BUILD_BUG_ON(PS3DISK_MAX_DISKS > BITS_PER_LONG);
> + devidx = find_first_zero_bit(&ps3disk_mask, PS3DISK_MAX_DISKS);
> + if (devidx >= PS3DISK_MAX_DISKS) {
> + dev_err(&dev->sbd.core, "%s:%u: Too many disks\n", __func__,
> + __LINE__);
> + return -ENOSPC;
> + }
> + __set_bit(devidx, &ps3disk_mask);
> +
> + priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> + if (!priv) {
> + error = -ENOMEM;
> + goto fail;
> + }
> +
> + ps3disk_priv(dev) = priv;
> + spin_lock_init(&priv->lock);
> +
> + dev->bounce_size = BOUNCE_SIZE;
> + dev->bounce_buf = kmalloc(BOUNCE_SIZE, GFP_DMA);
> + if (!dev->bounce_buf) {
> + error = -ENOMEM;
> + goto fail_free_priv;
> + }
> +
> + error = ps3stor_setup(dev, ps3disk_interrupt);
> + if (error)
> + goto fail_free_bounce;
> +
> + ps3disk_identify(dev);
ps3disk_identify() can return an error?
> + queue = blk_init_queue(ps3disk_request, &priv->lock);
> + if (!queue) {
> + dev_err(&dev->sbd.core, "%s:%u: blk_init_queue failed\n",
> + __func__, __LINE__);
> + error = -ENOMEM;
> + goto fail_teardown;
> + }
> +
> + priv->queue = queue;
> + queue->queuedata = dev;
> +
> + blk_queue_bounce_limit(queue, BLK_BOUNCE_HIGH);
> +
> + blk_queue_max_sectors(queue, dev->bounce_size/KERNEL_SECTOR_SIZE);
> + blk_queue_segment_boundary(queue, -1UL);
> + blk_queue_dma_alignment(queue, dev->blk_size-1);
> + blk_queue_hardsect_size(queue, dev->blk_size);
> +
> + blk_queue_issue_flush_fn(queue, ps3disk_issue_flush);
> + blk_queue_ordered(queue, QUEUE_ORDERED_DRAIN_FLUSH,
> + ps3disk_prepare_flush);
> +
> + blk_queue_max_phys_segments(queue, -1);
> + blk_queue_max_hw_segments(queue, -1);
> + blk_queue_max_segment_size(queue, dev->bounce_size);
> +
> + gendisk = alloc_disk(PS3DISK_MINORS);
> + if (!gendisk) {
> + dev_err(&dev->sbd.core, "%s:%u: alloc_disk failed\n", __func__,
> + __LINE__);
> + error = -ENOMEM;
> + goto fail_cleanup_queue;
> + }
> +
> + priv->gendisk = gendisk;
> + gendisk->major = ps3disk_major;
> + gendisk->first_minor = devidx * PS3DISK_MINORS;
> + gendisk->fops = &ps3disk_fops;
> + gendisk->queue = queue;
> + gendisk->private_data = dev;
> + gendisk->driverfs_dev = &dev->sbd.core;
> + snprintf(gendisk->disk_name, sizeof(gendisk->disk_name), PS3DISK_NAME,
> + devidx+'a');
> + priv->blocking_factor = dev->blk_size/KERNEL_SECTOR_SIZE;
> + set_capacity(gendisk,
> + dev->regions[dev->region_idx].size*priv->blocking_factor);
> +
> + dev_info(&dev->sbd.core,
> + "%s is a %s (%lu MiB total, %lu MiB for OtherOS)\n",
> + gendisk->disk_name, priv->model, priv->raw_capacity >> 11,
> + get_capacity(gendisk) >> 11);
> +
> + add_disk(gendisk);
> + return 0;
> +
> +fail_cleanup_queue:
> + blk_cleanup_queue(queue);
> +fail_teardown:
> + ps3stor_teardown(dev);
> +fail_free_bounce:
> + kfree(dev->bounce_buf);
> +fail_free_priv:
> + kfree(priv);
> + ps3disk_priv(dev) = NULL;
> +fail:
> + __clear_bit(devidx, &ps3disk_mask);
> + return error;
> +}
> +
> +static int ps3disk_remove(struct ps3_system_bus_device *_dev)
> +{
> + struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
> + struct ps3disk_private *priv = ps3disk_priv(dev);
> +
> + __clear_bit(priv->gendisk->first_minor / PS3DISK_MINORS,
> + &ps3disk_mask);
I see no locking here which makes this __clear_bit and the above __set_bit
non-racy?
> + del_gendisk(priv->gendisk);
> + blk_cleanup_queue(priv->queue);
> + put_disk(priv->gendisk);
> + dev_notice(&dev->sbd.core, "Synchronizing disk cache\n");
> + ps3disk_sync_cache(dev);
> + ps3stor_teardown(dev);
> + kfree(dev->bounce_buf);
> + kfree(priv);
> + ps3disk_priv(dev) = NULL;
I suspect this nulling here will just hide any bugs? If we're going to
write anything there, probably 0xdeadbeef would be better?
> + return 0;
> +}
> +
^ permalink raw reply
* [PATCH] [updated] PHY fixed driver: rework release path and update phy_id notation
From: Vitaly Bordug @ 2007-07-18 23:38 UTC (permalink / raw)
To: Jeff Garzik; +Cc: linuxppc-dev, linux-kernel, netdev
device_bind_driver() error code returning has been fixed.
release() function has been written, so that to free resources
in correct way; the release path is now clean.
Before the rework, it used to cause
Device 'fixed@100:1' does not have a release() function, it is broken
and must be fixed.
BUG: at drivers/base/core.c:104 device_release()
Call Trace:
[<ffffffff802ec380>] kobject_cleanup+0x53/0x7e
[<ffffffff802ec3ab>] kobject_release+0x0/0x9
[<ffffffff802ecf3f>] kref_put+0x74/0x81
[<ffffffff8035493b>] fixed_mdio_register_device+0x230/0x265
[<ffffffff80564d31>] fixed_init+0x1f/0x35
[<ffffffff802071a4>] init+0x147/0x2fb
[<ffffffff80223b6e>] schedule_tail+0x36/0x92
[<ffffffff8020a678>] child_rip+0xa/0x12
[<ffffffff80311714>] acpi_ds_init_one_object+0x0/0x83
[<ffffffff8020705d>] init+0x0/0x2fb
[<ffffffff8020a66e>] child_rip+0x0/0x12
Also changed the notation of the fixed phy definition on
mdio bus to the form of <speed>+<duplex> to make it able to be used by
gianfar and ucc_geth that define phy_id strictly as "%d:%d" and cleaned up
the whitespace issues.
Signed-off-by: Vitaly Bordug <vitb@kernel.crashing.org>
---
drivers/net/phy/Kconfig | 14 ++
drivers/net/phy/fixed.c | 310 +++++++++++++++++++++++----------------------
include/linux/phy_fixed.h | 38 ++++++
3 files changed, 207 insertions(+), 155 deletions(-)
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index dd09011..432c210 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -76,4 +76,18 @@ config FIXED_MII_100_FDX
bool "Emulation for 100M Fdx fixed PHY behavior"
depends on FIXED_PHY
+config FIXED_MII_1000_FDX
+ bool "Emulation for 1000M Fdx fixed PHY behavior"
+ depends on FIXED_PHY
+
+config FIXED_MII_AMNT
+ int "Number of emulated PHYs to allocate "
+ depends on FIXED_PHY
+ default "1"
+ ---help---
+ Sometimes it is required to have several independent emulated
+ PHYs on the bus (in case of multi-eth but phy-less HW for instance).
+ This control will have specified number allocated for each fixed
+ PHY type enabled.
+
endif # PHYLIB
diff --git a/drivers/net/phy/fixed.c b/drivers/net/phy/fixed.c
index bb96691..5619182 100644
--- a/drivers/net/phy/fixed.c
+++ b/drivers/net/phy/fixed.c
@@ -30,53 +30,31 @@
#include <linux/mii.h>
#include <linux/ethtool.h>
#include <linux/phy.h>
+#include <linux/phy_fixed.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
-#define MII_REGS_NUM 7
-
-/*
- The idea is to emulate normal phy behavior by responding with
- pre-defined values to mii BMCR read, so that read_status hook could
- take all the needed info.
-*/
-
-struct fixed_phy_status {
- u8 link;
- u16 speed;
- u8 duplex;
-};
-
-/*-----------------------------------------------------------------------------
- * Private information hoder for mii_bus
- *-----------------------------------------------------------------------------*/
-struct fixed_info {
- u16 *regs;
- u8 regs_num;
- struct fixed_phy_status phy_status;
- struct phy_device *phydev; /* pointer to the container */
- /* link & speed cb */
- int(*link_update)(struct net_device*, struct fixed_phy_status*);
-
-};
+/* we need to track the allocated pointers in order to free them on exit */
+static struct fixed_info *fixed_phy_ptrs[CONFIG_FIXED_MII_AMNT*MAX_PHY_AMNT];
/*-----------------------------------------------------------------------------
* If something weird is required to be done with link/speed,
* network driver is able to assign a function to implement this.
* May be useful for PHY's that need to be software-driven.
*-----------------------------------------------------------------------------*/
-int fixed_mdio_set_link_update(struct phy_device* phydev,
- int(*link_update)(struct net_device*, struct fixed_phy_status*))
+int fixed_mdio_set_link_update(struct phy_device *phydev,
+ int (*link_update) (struct net_device *,
+ struct fixed_phy_status *))
{
struct fixed_info *fixed;
- if(link_update == NULL)
+ if (link_update == NULL)
return -EINVAL;
- if(phydev) {
- if(phydev->bus) {
+ if (phydev) {
+ if (phydev->bus) {
fixed = phydev->bus->priv;
fixed->link_update = link_update;
return 0;
@@ -84,54 +62,64 @@ int fixed_mdio_set_link_update(struct phy_device* phydev,
}
return -EINVAL;
}
+
EXPORT_SYMBOL(fixed_mdio_set_link_update);
+struct fixed_info *fixed_mdio_get_phydev (int phydev_ind)
+{
+ if (phydev_ind >= MAX_PHY_AMNT)
+ return NULL;
+ return fixed_phy_ptrs[phydev_ind];
+}
+
+EXPORT_SYMBOL(fixed_mdio_get_phydev);
+
/*-----------------------------------------------------------------------------
* This is used for updating internal mii regs from the status
*-----------------------------------------------------------------------------*/
-#if defined(CONFIG_FIXED_MII_100_FDX) || defined(CONFIG_FIXED_MII_10_FDX)
+#if defined(CONFIG_FIXED_MII_100_FDX) || defined(CONFIG_FIXED_MII_10_FDX) || defined(CONFIG_FIXED_MII_1000_FDX)
static int fixed_mdio_update_regs(struct fixed_info *fixed)
{
u16 *regs = fixed->regs;
u16 bmsr = 0;
u16 bmcr = 0;
- if(!regs) {
+ if (!regs) {
printk(KERN_ERR "%s: regs not set up", __FUNCTION__);
return -EINVAL;
}
- if(fixed->phy_status.link)
+ if (fixed->phy_status.link)
bmsr |= BMSR_LSTATUS;
- if(fixed->phy_status.duplex) {
+ if (fixed->phy_status.duplex) {
bmcr |= BMCR_FULLDPLX;
- switch ( fixed->phy_status.speed ) {
+ switch (fixed->phy_status.speed) {
case 100:
bmsr |= BMSR_100FULL;
bmcr |= BMCR_SPEED100;
- break;
+ break;
case 10:
bmsr |= BMSR_10FULL;
- break;
+ break;
}
} else {
- switch ( fixed->phy_status.speed ) {
+ switch (fixed->phy_status.speed) {
case 100:
bmsr |= BMSR_100HALF;
bmcr |= BMCR_SPEED100;
- break;
+ break;
case 10:
bmsr |= BMSR_100HALF;
- break;
+ break;
}
}
- regs[MII_BMCR] = bmcr;
- regs[MII_BMSR] = bmsr | 0x800; /*we are always capable of 10 hdx*/
+ regs[MII_BMCR] = bmcr;
+ regs[MII_BMSR] = bmsr | 0x800; /*we are always capable of 10 hdx */
return 0;
}
@@ -141,29 +129,30 @@ static int fixed_mii_read(struct mii_bus *bus, int phy_id, int location)
struct fixed_info *fixed = bus->priv;
/* if user has registered link update callback, use it */
- if(fixed->phydev)
- if(fixed->phydev->attached_dev) {
- if(fixed->link_update) {
+ if (fixed->phydev)
+ if (fixed->phydev->attached_dev) {
+ if (fixed->link_update) {
fixed->link_update(fixed->phydev->attached_dev,
- &fixed->phy_status);
+ &fixed->phy_status);
fixed_mdio_update_regs(fixed);
}
- }
+ }
if ((unsigned int)location >= fixed->regs_num)
return -1;
return fixed->regs[location];
}
-static int fixed_mii_write(struct mii_bus *bus, int phy_id, int location, u16 val)
+static int fixed_mii_write(struct mii_bus *bus, int phy_id, int location,
+ u16 val)
{
- /* do nothing for now*/
+ /* do nothing for now */
return 0;
}
static int fixed_mii_reset(struct mii_bus *bus)
{
- /*nothing here - no way/need to reset it*/
+ /*nothing here - no way/need to reset it */
return 0;
}
#endif
@@ -171,8 +160,8 @@ static int fixed_mii_reset(struct mii_bus *bus)
static int fixed_config_aneg(struct phy_device *phydev)
{
/* :TODO:03/13/2006 09:45:37 PM::
- The full autoneg funcionality can be emulated,
- but no need to have anything here for now
+ The full autoneg funcionality can be emulated,
+ but no need to have anything here for now
*/
return 0;
}
@@ -182,59 +171,79 @@ static int fixed_config_aneg(struct phy_device *phydev)
* match will never return true...
*-----------------------------------------------------------------------------*/
static struct phy_driver fixed_mdio_driver = {
- .name = "Fixed PHY",
- .features = PHY_BASIC_FEATURES,
- .config_aneg = fixed_config_aneg,
- .read_status = genphy_read_status,
- .driver = { .owner = THIS_MODULE,},
+ .name = "Fixed PHY",
+#ifdef CONFIG_FIXED_MII_1000_FDX
+ .features = PHY_GBIT_FEATURES,
+#else
+ .features = PHY_BASIC_FEATURES,
+#endif
+ .config_aneg = fixed_config_aneg,
+ .read_status = genphy_read_status,
+ .driver = { .owner = THIS_MODULE, },
};
+static void fixed_mdio_release(struct device *dev)
+{
+ struct phy_device *phydev = container_of(dev, struct phy_device, dev);
+ struct mii_bus *bus = phydev->bus;
+ struct fixed_info *fixed = bus->priv;
+
+ kfree(phydev);
+ kfree(bus->dev);
+ kfree(bus);
+ kfree(fixed->regs);
+ kfree(fixed);
+}
+
/*-----------------------------------------------------------------------------
* This func is used to create all the necessary stuff, bind
* the fixed phy driver and register all it on the mdio_bus_type.
- * speed is either 10 or 100, duplex is boolean.
+ * speed is either 10 or 100 or 1000, duplex is boolean.
* number is used to create multiple fixed PHYs, so that several devices can
* utilize them simultaneously.
+ *
+ * The device on mdio bus will look like [bus_id]:[phy_id],
+ * bus_id = number
+ * phy_id = speed+duplex.
*-----------------------------------------------------------------------------*/
-#if defined(CONFIG_FIXED_MII_100_FDX) || defined(CONFIG_FIXED_MII_10_FDX)
-static int fixed_mdio_register_device(int number, int speed, int duplex)
+#if defined(CONFIG_FIXED_MII_100_FDX) || defined(CONFIG_FIXED_MII_10_FDX) || defined(CONFIG_FIXED_MII_1000_FDX)
+struct fixed_info *fixed_mdio_register_device(
+ int bus_id, int speed, int duplex, u8 phy_id)
{
struct mii_bus *new_bus;
struct fixed_info *fixed;
struct phy_device *phydev;
- int err = 0;
+ int err;
- struct device* dev = kzalloc(sizeof(struct device), GFP_KERNEL);
+ struct device *dev = kzalloc(sizeof(struct device), GFP_KERNEL);
- if (NULL == dev)
- return -ENOMEM;
+ if (dev == NULL)
+ goto err_dev_alloc;
new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
- if (NULL == new_bus) {
- kfree(dev);
- return -ENOMEM;
- }
+ if (new_bus == NULL)
+ goto err_bus_alloc;
+
fixed = kzalloc(sizeof(struct fixed_info), GFP_KERNEL);
- if (NULL == fixed) {
- kfree(dev);
- kfree(new_bus);
- return -ENOMEM;
- }
+ if (fixed == NULL)
+ goto err_fixed_alloc;
+
+ fixed->regs = kzalloc(MII_REGS_NUM * sizeof(int), GFP_KERNEL);
+ if (NULL == fixed->regs)
+ goto err_fixed_regs_alloc;
- fixed->regs = kzalloc(MII_REGS_NUM*sizeof(int), GFP_KERNEL);
fixed->regs_num = MII_REGS_NUM;
fixed->phy_status.speed = speed;
fixed->phy_status.duplex = duplex;
fixed->phy_status.link = 1;
- new_bus->name = "Fixed MII Bus",
- new_bus->read = &fixed_mii_read,
- new_bus->write = &fixed_mii_write,
- new_bus->reset = &fixed_mii_reset,
-
- /*set up workspace*/
+ new_bus->name = "Fixed MII Bus";
+ new_bus->read = &fixed_mii_read;
+ new_bus->write = &fixed_mii_write;
+ new_bus->reset = &fixed_mii_reset;
+ /*set up workspace */
fixed_mdio_update_regs(fixed);
new_bus->priv = fixed;
@@ -243,119 +252,110 @@ static int fixed_mdio_register_device(int number, int speed, int duplex)
/* create phy_device and register it on the mdio bus */
phydev = phy_device_create(new_bus, 0, 0);
+ if (phydev == NULL)
+ goto err_phy_dev_create;
/*
- Put the phydev pointer into the fixed pack so that bus read/write code could
- be able to access for instance attached netdev. Well it doesn't have to do
- so, only in case of utilizing user-specified link-update...
+ * Put the phydev pointer into the fixed pack so that bus read/write
+ * code could be able to access for instance attached netdev. Well it
+ * doesn't have to do so, only in case of utilizing user-specified
+ * link-update...
*/
- fixed->phydev = phydev;
- if(NULL == phydev) {
- err = -ENOMEM;
- goto device_create_fail;
- }
+ fixed->phydev = phydev;
+ phydev->speed = speed;
+ phydev->duplex = duplex;
phydev->irq = PHY_IGNORE_INTERRUPT;
phydev->dev.bus = &mdio_bus_type;
- if(number)
- snprintf(phydev->dev.bus_id, BUS_ID_SIZE,
- "fixed_%d@%d:%d", number, speed, duplex);
- else
- snprintf(phydev->dev.bus_id, BUS_ID_SIZE,
- "fixed@%d:%d", speed, duplex);
- phydev->bus = new_bus;
+ snprintf(phydev->dev.bus_id, BUS_ID_SIZE,
+ PHY_ID_FMT, bus_id, phy_id);
- err = device_register(&phydev->dev);
- if(err) {
- printk(KERN_ERR "Phy %s failed to register\n",
- phydev->dev.bus_id);
- goto bus_register_fail;
- }
+ phydev->bus = new_bus;
- /*
- the mdio bus has phy_id match... In order not to do it
- artificially, we are binding the driver here by hand;
- it will be the same for all the fixed phys anyway.
- */
phydev->dev.driver = &fixed_mdio_driver.driver;
-
+ phydev->dev.release = fixed_mdio_release;
err = phydev->dev.driver->probe(&phydev->dev);
- if(err < 0) {
- printk(KERN_ERR "Phy %s: problems with fixed driver\n",phydev->dev.bus_id);
- goto probe_fail;
+ if (err < 0) {
+ printk(KERN_ERR "Phy %s: problems with fixed driver\n",
+ phydev->dev.bus_id);
+ goto err_out;
}
+ err = device_register(&phydev->dev);
+ if (err) {
+ printk(KERN_ERR "Phy %s failed to register\n",
+ phydev->dev.bus_id);
+ goto err_out;
+ }
+ //phydev->state = PHY_RUNNING; /* make phy go up quick, but in 10Mbit/HDX
+ return fixed;
- err = device_bind_driver(&phydev->dev);
- if (err)
- goto probe_fail;
-
- return 0;
-
-probe_fail:
- device_unregister(&phydev->dev);
-bus_register_fail:
+err_out:
kfree(phydev);
-device_create_fail:
- kfree(dev);
- kfree(new_bus);
+err_phy_dev_create:
+ kfree(fixed->regs);
+err_fixed_regs_alloc:
kfree(fixed);
+err_fixed_alloc:
+ kfree(new_bus);
+err_bus_alloc:
+ kfree(dev);
+err_dev_alloc:
+
+ return NULL;
- return err;
}
#endif
-
MODULE_DESCRIPTION("Fixed PHY device & driver for PAL");
MODULE_AUTHOR("Vitaly Bordug");
MODULE_LICENSE("GPL");
static int __init fixed_init(void)
{
-#if 0
- int ret;
- int duplex = 0;
-#endif
-
- /* register on the bus... Not expected to be matched with anything there... */
+ int cnt = 0;
+ int i;
+/* register on the bus... Not expected to be matched
+ * with anything there...
+ *
+ */
phy_driver_register(&fixed_mdio_driver);
- /* So let the fun begin...
- We will create several mdio devices here, and will bound the upper
- driver to them.
-
- Then the external software can lookup the phy bus by searching
- fixed@speed:duplex, e.g. fixed@100:1, to be connected to the
- virtual 100M Fdx phy.
-
- In case several virtual PHYs required, the bus_id will be in form
- fixed_<num>@<speed>:<duplex>, which make it able even to define
- driver-specific link control callback, if for instance PHY is completely
- SW-driven.
-
- */
-
-#ifdef CONFIG_FIXED_MII_DUPLEX
-#if 0
- duplex = 1;
-#endif
+/* We will create several mdio devices here, and will bound the upper
+ * driver to them.
+ *
+ * Then the external software can lookup the phy bus by searching
+ * for 0:101, to be connected to the virtual 100M Fdx phy.
+ *
+ * In case several virtual PHYs required, the bus_id will be in form
+ * [num]:[duplex]+[speed], which make it able even to define
+ * driver-specific link control callback, if for instance PHY is
+ * completely SW-driven.
+ */
+ for (i=1; i <= CONFIG_FIXED_MII_AMNT; i++) {
+#ifdef CONFIG_FIXED_MII_1000_FDX
+ fixed_phy_ptrs[cnt++] = fixed_mdio_register_device(0, 1000, 1, i);
#endif
-
#ifdef CONFIG_FIXED_MII_100_FDX
- fixed_mdio_register_device(0, 100, 1);
+ fixed_phy_ptrs[cnt++] = fixed_mdio_register_device(1, 100, 1, i);
#endif
-
#ifdef CONFIG_FIXED_MII_10_FDX
- fixed_mdio_register_device(0, 10, 1);
+ fixed_phy_ptrs[cnt++] = fixed_mdio_register_device(2, 10, 1, i);
#endif
+ }
+
return 0;
}
static void __exit fixed_exit(void)
{
+ int i;
+
phy_driver_unregister(&fixed_mdio_driver);
- /* :WARNING:02/18/2006 04:32:40 AM:: Cleanup all the created stuff */
+ for (i=0; i < MAX_PHY_AMNT; i++)
+ if ( fixed_phy_ptrs[i] )
+ device_unregister(&fixed_phy_ptrs[i]->phydev->dev);
}
module_init(fixed_init);
diff --git a/include/linux/phy_fixed.h b/include/linux/phy_fixed.h
new file mode 100644
index 0000000..04ba70d
--- /dev/null
+++ b/include/linux/phy_fixed.h
@@ -0,0 +1,38 @@
+#ifndef __PHY_FIXED_H
+#define __PHY_FIXED_H
+
+#define MII_REGS_NUM 29
+
+/* max number of virtual phy stuff */
+#define MAX_PHY_AMNT 10
+/*
+ The idea is to emulate normal phy behavior by responding with
+ pre-defined values to mii BMCR read, so that read_status hook could
+ take all the needed info.
+*/
+
+struct fixed_phy_status {
+ u8 link;
+ u16 speed;
+ u8 duplex;
+};
+
+/*-----------------------------------------------------------------------------
+ * Private information hoder for mii_bus
+ *-----------------------------------------------------------------------------*/
+struct fixed_info {
+ u16 *regs;
+ u8 regs_num;
+ struct fixed_phy_status phy_status;
+ struct phy_device *phydev; /* pointer to the container */
+ /* link & speed cb */
+ int (*link_update) (struct net_device *, struct fixed_phy_status *);
+
+};
+
+
+int fixed_mdio_set_link_update(struct phy_device *,
+ int (*link_update) (struct net_device *, struct fixed_phy_status *));
+struct fixed_info *fixed_mdio_get_phydev (int phydev_ind);
+
+#endif /* __PHY_FIXED_H */
^ permalink raw reply related
* Re: [patch 2/3] ps3: BD/DVD/CD-ROM Storage Driver
From: Andrew Morton @ 2007-07-18 23:43 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Jens Axboe, James E.J. Bottomley, linux-scsi, linux-kernel,
Alessandro Rubini, linuxppc-dev, Paul Mackerras
In-Reply-To: <20070716162206.529280000@pademelon.sonytel.be>
On Mon, 16 Jul 2007 18:15:41 +0200
Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com> wrote:
> From: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
>
> Add a BD/DVD/CD-ROM Storage Driver for the PS3:
> - Implemented as a SCSI device driver
> - Uses software scatter-gather with a 64 KiB bounce buffer as the hypervisor
> doesn't support scatter-gather
>
> --- /dev/null
> +++ b/drivers/scsi/ps3rom.c
> @@ -0,0 +1,538 @@
> +/*
> + * PS3 BD/DVD/CD-ROM Storage Driver
> + *
> + * Copyright (C) 2007 Sony Computer Entertainment Inc.
> + * Copyright 2007 Sony Corp.
> + *
> + * 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; version 2 of the License.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> + */
> +
> +#include <linux/cdrom.h>
> +#include <linux/highmem.h>
> +
> +#include <scsi/scsi.h>
> +#include <scsi/scsi_cmnd.h>
> +#include <scsi/scsi_dbg.h>
> +#include <scsi/scsi_device.h>
> +#include <scsi/scsi_host.h>
> +
> +#include <asm/lv1call.h>
> +#include <asm/ps3stor.h>
> +
> +
> +#define DEVICE_NAME "ps3rom"
> +
> +#define BOUNCE_SIZE (64*1024)
> +
> +#define PS3ROM_MAX_SECTORS (BOUNCE_SIZE / CD_FRAMESIZE)
> +
> +
> +struct ps3rom_private {
> + struct ps3_storage_device *dev;
> + struct scsi_cmnd *curr_cmd;
> +};
> +#define ps3rom_priv(dev) ((dev)->sbd.core.driver_data)
> +
Someone should invent a keyboard which delivers an electric shock when the
operator types "#define". In the meanwhile, I get to do the honours.
Please don't implement in a macro anything which can be implemented in C.
> +
> +#define LV1_STORAGE_SEND_ATAPI_COMMAND (1)
> +
> +struct lv1_atapi_cmnd_block {
> + u8 pkt[32]; /* packet command block */
> + u32 pktlen; /* should be 12 for ATAPI 8020 */
> + u32 blocks;
> + u32 block_size;
> + u32 proto; /* transfer mode */
> + u32 in_out; /* transfer direction */
> + u64 buffer; /* parameter except command block */
> + u32 arglen; /* length above */
> +};
> +
> +enum lv1_atapi_proto {
> + NON_DATA_PROTO = 0,
> + PIO_DATA_IN_PROTO = 1,
> + PIO_DATA_OUT_PROTO = 2,
> + DMA_PROTO = 3
> +};
> +
>
> ...
>
> +/*
> + * copy data from device into scatter/gather buffer
> + */
> +static int fill_from_dev_buffer(struct scsi_cmnd *cmd, const void *buf)
> +{
> + int k, req_len, act_len, len, active;
> + void *kaddr;
> + struct scatterlist *sgpnt;
> + unsigned int buflen;
> +
> + buflen = cmd->request_bufflen;
> + if (!buflen)
> + return 0;
> +
> + if (!cmd->request_buffer)
> + return -1;
> +
> + sgpnt = cmd->request_buffer;
> + active = 1;
> + for (k = 0, req_len = 0, act_len = 0; k < cmd->use_sg; ++k, ++sgpnt) {
> + if (active) {
> + kaddr = kmap_atomic(sgpnt->page, KM_IRQ0);
> + if (!kaddr)
> + return -1;
kmap_atomic() cannot fail. On i386, at least. If it can fail on any other
arch then we have a biiiiig problem. (Multiple instances of this)
> + len = sgpnt->length;
> + if ((req_len + len) > buflen) {
> + active = 0;
> + len = buflen - req_len;
> + }
> + memcpy(kaddr + sgpnt->offset, buf + req_len, len);
> + flush_kernel_dcache_page(sgpnt->page);
> + kunmap_atomic(kaddr, KM_IRQ0);
> + act_len += len;
> + }
> + req_len += sgpnt->length;
> + }
> + cmd->resid = req_len - act_len;
> + return 0;
> +}
> +
^ permalink raw reply
* [PATCH] tg3: add PCI error recovery support
From: Linas Vepstas @ 2007-07-18 23:48 UTC (permalink / raw)
To: Michael Chan
Cc: cjlarsen, netdev, linuxppc-dev, daisyc, tsenglin, linux-pci,
strosake, wenxiong
Add support for PCI Error Recovery for the tg3 ethernet
device driver. The general principles of operation are
described in Documentation/pci-error-recovery.txt
Other drivers having similar structure include e100,
e1000, ixgb, s2io, ipr, sym53c8xx_2, and lpfc
Signed-off-by: Linas Vepstas <linas@austin.ibm.com>
Cc: Michael Chan <mchan@broadcom.com>
----
Michael, you are listed as the tg3 maintainer; could you
please forward upstream if you agree?
Tested on the PCI-E version of this adapter, on power6,
for 85 (artificial) error injections (overnight) while
ftp'ing dvd iso images over the link. Worked well.
drivers/net/tg3.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 107 insertions(+), 1 deletion(-)
Index: linux-2.6.22-git2/drivers/net/tg3.c
===================================================================
--- linux-2.6.22-git2.orig/drivers/net/tg3.c 2007-07-17 11:07:30.000000000 -0500
+++ linux-2.6.22-git2/drivers/net/tg3.c 2007-07-18 15:10:09.000000000 -0500
@@ -64,7 +64,7 @@
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "3.77"
+#define DRV_MODULE_VERSION "3.77-a"
#define DRV_MODULE_RELDATE "May 31, 2007"
#define TG3_DEF_MAC_MODE 0
@@ -12126,11 +12126,117 @@ out:
return err;
}
+/**
+ * tg3_io_error_detected - called when PCI error is detected
+ * @pdev: Pointer to PCI device
+ * @state: The current pci connection state
+ *
+ * This function is called after a PCI bus error affecting
+ * this device has been detected.
+ */
+static pci_ers_result_t tg3_io_error_detected(struct pci_dev *pdev,
+ pci_channel_state_t state)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct tg3 *tp = netdev_priv(netdev);
+ struct device *dev = &netdev->dev;
+
+ dev_info(dev, "PCI I/O error detected on %s\n", netdev->name);
+
+ if (!netif_running(netdev))
+ return PCI_ERS_RESULT_NEED_RESET;
+
+ /* Want to make sure that the reset task doesn't run */
+ cancel_work_sync(&tp->reset_task);
+ tg3_netif_stop(tp);
+ del_timer_sync(&tp->timer);
+ netif_device_detach(netdev);
+ pci_disable_device(pdev);
+
+ if (state == pci_channel_io_perm_failure) {
+ /* avoid hang in dev_close() with rtnl_lock held */
+ netif_poll_enable(netdev);
+ return PCI_ERS_RESULT_DISCONNECT;
+ }
+ return PCI_ERS_RESULT_NEED_RESET;
+}
+
+/**
+ * tg3_io_slot_reset - called after the pci bus has been reset.
+ * @pdev: Pointer to PCI device
+ *
+ * Restart the card from scratch, as if from a cold-boot.
+ * At this point, the card has exprienced a hard reset,
+ * followed by fixups by BIOS, and has its config space
+ * set up identically to what it was at cold boot.
+ */
+static pci_ers_result_t tg3_io_slot_reset(struct pci_dev *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct tg3 *tp = netdev_priv(netdev);
+ int err;
+
+ if (!netif_running(netdev))
+ return PCI_ERS_RESULT_RECOVERED;
+
+ if (pci_enable_device(pdev)) {
+ printk(KERN_ERR "tg3: %s: "
+ "Cannot re-enable PCI device after reset.\n", netdev->name);
+ return PCI_ERS_RESULT_DISCONNECT;
+ }
+
+ pci_set_master(pdev);
+ pci_restore_state(tp->pdev);
+ netif_device_attach(netdev);
+
+ tg3_full_lock(tp, 0);
+ tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE;
+ err = tg3_restart_hw(tp, 1);
+ tg3_full_unlock(tp);
+ if (err) {
+ printk(KERN_ERR "tg3: %s: "
+ "Cannot restart hardware after reset.\n", netdev->name);
+ return PCI_ERS_RESULT_DISCONNECT;
+ }
+
+ return PCI_ERS_RESULT_RECOVERED;
+}
+
+/**
+ * tg3_io_resume - called when traffic can start flowing again.
+ * @pdev: Pointer to PCI device
+ *
+ * This callback is called when the error recovery driver tells
+ * us that its OK to resume normal operation.
+ */
+static void tg3_io_resume(struct pci_dev *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct tg3 *tp = netdev_priv(netdev);
+
+ if (!netif_running(netdev))
+ return;
+
+ netif_wake_queue(netdev);
+
+ tp->timer.expires = jiffies + tp->timer_offset;
+ add_timer(&tp->timer);
+
+ tg3_netif_start(tp);
+}
+
+static struct pci_error_handlers tg3_err_handler = {
+ .error_detected = tg3_io_error_detected,
+ .slot_reset = tg3_io_slot_reset,
+ .resume = tg3_io_resume,
+};
+
static struct pci_driver tg3_driver = {
.name = DRV_MODULE_NAME,
.id_table = tg3_pci_tbl,
.probe = tg3_init_one,
.remove = __devexit_p(tg3_remove_one),
+ .err_handler = &tg3_err_handler,
.suspend = tg3_suspend,
.resume = tg3_resume
};
^ permalink raw reply
* Re: [patch 3/3] ps3: FLASH ROM Storage Driver
From: Andrew Morton @ 2007-07-18 23:52 UTC (permalink / raw)
To: Geert Uytterhoeven, Andy Whitcroft
Cc: Jens Axboe, James E.J. Bottomley, linux-scsi, linux-kernel,
Alessandro Rubini, linuxppc-dev, Paul Mackerras
In-Reply-To: <20070716162206.723142000@pademelon.sonytel.be>
On Mon, 16 Jul 2007 18:15:42 +0200
Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com> wrote:
> From: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
>
> Add a FLASH ROM Storage Driver for the PS3:
> - Implemented as a misc character device driver
> - Uses a fixed 256 KiB buffer allocated from boot memory as the hypervisor
> requires the writing of aligned 256 KiB blocks
>
> --- /dev/null
> +++ b/drivers/char/ps3flash.c
> @@ -0,0 +1,429 @@
> +/*
> + * PS3 FLASH ROM Storage Driver
> + *
> + * Copyright (C) 2007 Sony Computer Entertainment Inc.
> + * Copyright 2007 Sony Corp.
> + *
> + * 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; version 2 of the License.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> + */
> +
> +#include <linux/fs.h>
> +#include <linux/miscdevice.h>
> +#include <linux/uaccess.h>
> +
> +#include <asm/lv1call.h>
> +#include <asm/ps3stor.h>
> +
> +
> +#define DEVICE_NAME "ps3flash"
> +
> +#define FLASH_BLOCK_SIZE (256*1024)
> +
> +
> +struct ps3flash_private {
> + struct mutex mutex; /* Bounce buffer mutex */
> +};
> +#define ps3flash_priv(dev) ((dev)->sbd.core.driver_data)
bzzzt!
> +static loff_t ps3flash_llseek(struct file *file, loff_t offset, int origin)
> +{
> + struct ps3_storage_device *dev = ps3flash_dev;
> + u64 size = dev->regions[dev->region_idx].size*dev->blk_size;
> +
> + switch (origin) {
> + case 1:
> + offset += file->f_pos;
> + break;
> + case 2:
> + offset += size;
> + break;
> + }
> + if (offset < 0)
> + return -EINVAL;
> +
> + file->f_pos = offset;
> + return file->f_pos;
> +}
lseek implementations usually need locking. file->f_mapping->host->i_mutex
would be typical.
That locking mostly protects 64-bit f_pos on 32-bit architectures so you
can perahps kinda get away with it here. However the code is a bit racy
even on 64-bit, for silly userspace.
That being said, I'd have thought that you could use one of our many
generic lseek library fucntions here, or even an newly-exported
block_llseek(). That assumes that i_size is correct, which I trust is the
case.
> +static ssize_t ps3flash_read(struct file *file, char __user *buf, size_t count,
> + loff_t *pos)
> +{
> + struct ps3_storage_device *dev = ps3flash_dev;
> + struct ps3flash_private *priv = ps3flash_priv(dev);
> + u64 size, start_sector, end_sector, offset;
> + ssize_t sectors_read;
> + size_t remaining, n;
> +
> + dev_dbg(&dev->sbd.core,
> + "%s:%u: Reading %zu bytes at position %lld to user 0x%p\n",
> + __func__, __LINE__, count, *pos, buf);
> +
> + size = dev->regions[dev->region_idx].size*dev->blk_size;
> + if (*pos >= size || !count)
> + return 0;
> +
> + if (*pos+count > size) {
> + dev_dbg(&dev->sbd.core,
> + "%s:%u Truncating count from %zu to %llu\n", __func__,
> + __LINE__, count, size - *pos);
> + count = size - *pos;
> + }
> +
> + start_sector = do_div_llr(*pos, dev->blk_size, &offset);
> + end_sector = DIV_ROUND_UP(*pos+count, dev->blk_size);
> +
> + remaining = count;
> + do {
> + mutex_lock(&priv->mutex);
> +
> + sectors_read = ps3flash_read_sectors(dev, start_sector,
> + end_sector-start_sector,
> + 0);
> + if (sectors_read < 0) {
> + mutex_unlock(&priv->mutex);
> + return sectors_read;
> + }
> +
> + n = min(remaining, sectors_read*dev->blk_size-offset);
> + dev_dbg(&dev->sbd.core,
> + "%s:%u: copy %lu bytes from 0x%p to user 0x%p\n",
> + __func__, __LINE__, n, dev->bounce_buf+offset, buf);
> + if (copy_to_user(buf, dev->bounce_buf+offset, n)) {
> + mutex_unlock(&priv->mutex);
> + return -EFAULT;
> + }
> +
> + mutex_unlock(&priv->mutex);
> +
> + *pos += n;
> + buf += n;
> + remaining -= n;
> + start_sector += sectors_read;
> + offset = 0;
> + } while (remaining > 0);
> +
> + return count;
> +}
There are several nasty deeply-embedded return points in this function.
> +static ssize_t ps3flash_write(struct file *file, const char __user *buf,
> + size_t count, loff_t *pos)
> +{
> + struct ps3_storage_device *dev = ps3flash_dev;
> + struct ps3flash_private *priv = ps3flash_priv(dev);
> + u64 size, chunk_sectors, start_write_sector, end_write_sector,
> + end_read_sector, start_read_sector, head, tail, offset;
> + ssize_t res;
> + size_t remaining, n;
> + unsigned int sec_off;
> +
> + dev_dbg(&dev->sbd.core,
> + "%s:%u: Writing %zu bytes at position %lld from user 0x%p\n",
> + __func__, __LINE__, count, *pos, buf);
> +
> + size = dev->regions[dev->region_idx].size*dev->blk_size;
> + if (*pos >= size || !count)
> + return 0;
> +
> + if (*pos+count > size) {
checkpatch missed stuff here.
> + dev_dbg(&dev->sbd.core,
> + "%s:%u Truncating count from %zu to %llu\n", __func__,
> + __LINE__, count, size - *pos);
> + count = size - *pos;
> + }
> +
> + chunk_sectors = dev->bounce_size / dev->blk_size;
> +
> + start_write_sector = do_div_llr(*pos, dev->bounce_size, &offset) *
> + chunk_sectors;
It's strange to see a do_div_llr() in the middle of all this 64-bit-only
code. Could use / and %?
> + end_write_sector = DIV_ROUND_UP(*pos+count, dev->bounce_size) *
> + chunk_sectors;
> +
> + end_read_sector = DIV_ROUND_UP(*pos, dev->blk_size);
> + start_read_sector = (*pos+count) / dev->blk_size;
> +
> + /*
> + * As we have to write in 256 KiB chunks, while we can read in blk_size
> + * (usually 512 bytes) chunks, we perform the following steps:
> + * 1. Read from start_write_sector to end_read_sector ("head")
> + * 2. Read from start_read_sector to end_write_sector ("tail")
> + * 3. Copy data to buffer
> + * 4. Write from start_write_sector to end_write_sector
> + * All of this is complicated by using only one 256 KiB bounce buffer.
> + */
> +
> + head = end_read_sector-start_write_sector;
> + tail = end_write_sector-start_read_sector;
checkpatch missed this too.
> + remaining = count;
> + do {
> + mutex_lock(&priv->mutex);
> +
> + if (end_read_sector >= start_read_sector) {
> + /* Merge head and tail */
> + dev_dbg(&dev->sbd.core,
> + "Merged head and tail: %lu sectors at %lu\n",
> + chunk_sectors, start_write_sector);
> + res = ps3flash_read_sectors(dev, start_write_sector,
> + chunk_sectors, 0);
> + if (res < 0)
> + goto fail;
> + } else {
> + if (head) {
> + /* Read head */
> + dev_dbg(&dev->sbd.core,
> + "head: %lu sectors at %lu\n", head,
> + start_write_sector);
> + res = ps3flash_read_sectors(dev,
> + start_write_sector,
> + head, 0);
> + if (res < 0)
> + goto fail;
> + }
> + if (start_read_sector <
> + start_write_sector+chunk_sectors) {
> + /* Read tail */
> + dev_dbg(&dev->sbd.core,
> + "tail: %lu sectors at %lu\n", tail,
> + start_read_sector);
> + sec_off = start_read_sector-start_write_sector;
> + res = ps3flash_read_sectors(dev,
> + start_read_sector,
> + tail, sec_off);
> + if (res < 0)
> + goto fail;
> + }
> + }
> +
> + n = min(remaining, dev->bounce_size-offset);
> + dev_dbg(&dev->sbd.core,
> + "%s:%u: copy %lu bytes from user 0x%p to 0x%p\n",
> + __func__, __LINE__, n, buf, dev->bounce_buf+offset);
> + if (copy_from_user(dev->bounce_buf+offset, buf, n)) {
> + res = -EFAULT;
> + goto fail;
> + }
> +
> + res = ps3flash_write_chunk(dev, start_write_sector);
> + if (res < 0)
> + goto fail;
> +
> + mutex_unlock(&priv->mutex);
> +
> + *pos += n;
> + buf += n;
> + remaining -= n;
> + start_write_sector += chunk_sectors;
> + head = 0;
> + offset = 0;
> + } while (remaining > 0);
> +
> + return count;
> +
> +fail:
> + mutex_unlock(&priv->mutex);
> + return res;
> +}
>
> ...
>
> +static int __devinit ps3flash_probe(struct ps3_system_bus_device *_dev)
> +{
> + struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
> + struct ps3flash_private *priv;
> + int error;
> + unsigned long tmp;
> +
> + tmp = dev->regions[dev->region_idx].start*dev->blk_size;
> + if (tmp % FLASH_BLOCK_SIZE) {
> + dev_err(&dev->sbd.core,
> + "%s:%u region start %lu is not aligned\n", __func__,
> + __LINE__, tmp);
> + return -EINVAL;
> + }
> + tmp = dev->regions[dev->region_idx].size*dev->blk_size;
> + if (tmp % FLASH_BLOCK_SIZE) {
> + dev_err(&dev->sbd.core,
> + "%s:%u region size %lu is not aligned\n", __func__,
> + __LINE__, tmp);
> + return -EINVAL;
> + }
> +
> + /* use static buffer, kmalloc cannot allocate 256 KiB */
> + if (!ps3flash_bounce_buffer.address)
> + return -ENODEV;
> +
> + if (ps3flash_dev) {
> + dev_err(&dev->sbd.core,
> + "Only one FLASH device is supported\n");
> + return -EBUSY;
> + }
> +
> + ps3flash_dev = dev;
> +
> + priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> + if (!priv) {
> + error = -ENOMEM;
> + goto fail;
> + }
> +
> + ps3flash_priv(dev) = priv;
> + mutex_init(&priv->mutex);
> +
> + dev->bounce_size = ps3flash_bounce_buffer.size;
> + dev->bounce_buf = ps3flash_bounce_buffer.address;
> +
> + error = ps3stor_setup(dev, ps3flash_interrupt);
> + if (error)
> + goto fail_free_priv;
> +
> + ps3flash_misc.parent = &dev->sbd.core;
> + error = misc_register(&ps3flash_misc);
> + if (error) {
> + dev_err(&dev->sbd.core, "%s:%u: misc_register failed %d\n",
> + __func__, __LINE__, error);
> + goto fail_teardown;
> + }
> +
> + dev_info(&dev->sbd.core, "%s:%u: registered misc device %d\n",
> + __func__, __LINE__, ps3flash_misc.minor);
> + return 0;
> +
> +fail_teardown:
> + ps3stor_teardown(dev);
> +fail_free_priv:
> + kfree(priv);
> + ps3flash_priv(dev) = NULL;
> +fail:
> + ps3flash_dev = NULL;
> + return error;
> +}
> +
^ permalink raw reply
* Re: [PATCH 56/61] 82xx: Add pq2fads board support.
From: Arnd Bergmann @ 2007-07-18 23:54 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <20070718013615.GB15238@ld0162-tx32.am.freescale.net>
On Wednesday 18 July 2007, Scott Wood wrote:
> +static void __init pq2fads_setup_arch(void)
> +{
> + struct device_node *np;
> + struct resource r;
> + u32 *bcsr;
bcsr should be __iomem, right? Did you run your code through sparse?
Arnd <><
^ permalink raw reply
* Re: [PATCH 51/61] cpm_uart: Be an of_platform device when using arch/powerpc.
From: Arnd Bergmann @ 2007-07-18 23:59 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <20070718013606.GW15238@ld0162-tx32.am.freescale.net>
On Wednesday 18 July 2007, Scott Wood wrote:
> +
> +static struct of_device_id cpm_uart_match[] =3D {
> +=A0=A0=A0=A0=A0=A0=A0{
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0.compatible =3D "fsl,cpm-ua=
rt",
> +=A0=A0=A0=A0=A0=A0=A0},
> +=A0=A0=A0=A0=A0=A0=A0{}
> =A0};
> +
I guess it's fine as it is, but it might be nicer if you change
this to have separate entries for scc and smc, and then pass
different values though of_device_id->data into the probe()
function.
Not sure if it makes much difference at all, but that's what
I did in the of_serial driver.
Arnd <><
^ permalink raw reply
* Re: [PATCH] Treat ISI faults as read faults on classic 32-bit PowerPC
From: Paul Mackerras @ 2007-07-19 0:00 UTC (permalink / raw)
To: Segher Boessenkool; +Cc: linuxppc-dev, Johannes Berg
In-Reply-To: <11847726193856-git-send-email-segher@kernel.crashing.org>
Segher Boessenkool writes:
> Some old software on ppc32 executes from pages it hasn't marked
> executable. Since "classic" hardware doesn't distinguish between
> execute and read accesses, the do_page_fault() code shouldn't
> either. This makes glibc-2.2 work again on such hardware.
>
> Signed-off-by: Segher Boessenkool <segher@kernel.crashing.org>
> Cc: Scott Wood <scottwood@freescale.com>
> Cc: Johannes Berg <johannes@sipsolutions.net>
> ---
> [Resend again, ozlabs' greylisting doesn't like me at all.]
>
> Tested by Scott on 32-bit, glibc-2.2.5 and glibc-2.3.3 (no new
> failures and problem solved), and by Johannes on his glibc-2.4
> "---p" testcase. Could use testing on ppc64 and BookE too, for
> good measure.
Hmmm. The dangling else clauses are pretty gross, and in fact we have
the same problem on POWER3 and RS64 processors (to be fair, we had
the problem before and didn't notice, but we should still fix it).
How about this instead? Could people test it please? (Note that
CPU_FTR_NOEXECUTE is 0 in 32-bit kernels.)
Paul.
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 0ece513..99c3093 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -283,7 +283,13 @@ good_area:
/* protection fault */
if (error_code & DSISR_PROTFAULT)
goto bad_area;
- if (!(vma->vm_flags & VM_EXEC))
+ /*
+ * Allow execution from readable areas if the MMU does not
+ * provide separate controls over reading and executing.
+ */
+ if (!(vma->vm_flags & VM_EXEC) &&
+ (cpu_has_feature(CPU_FTR_NOEXECUTE) ||
+ !(vma->vm_flags & (VM_READ | VM_WRITE))))
goto bad_area;
#else
pte_t *ptep;
^ permalink raw reply related
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