LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: ppc32: Rework power management take #3
From: Wolfram Quester @ 2005-06-02 13:05 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev list, debian-powerpc@lists.debian.org
In-Reply-To: <3db27390050530145939d260e4@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 1517 bytes --]

Hi,


On Mon, May 30, 2005 at 11:59:14PM +0200, Mickael Royer wrote:
> Hi Ben
> 
> > Ok, the patch is now getting "good enough" for wider testing. It applies
> > on current "git" tree (or 2.6.12-rc6 when/if that is ever released).
> 
> I have just tested your patch with the 2.5.12-rc5-git5 on the new powerbook 12".
> And yes, the suspend to disk works very well, even if X is running (I
> report my problem with X and the suspend to disk with a 2.6.12-rc4 in
> another discussion).
> It is really good. 
> 
> Thanks for your good job Ben. 
> 
> Mickael
> 
> On 5/30/05, Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:
> > Ok, the patch is now getting "good enough" for wider testing. It applies
> > on current "git" tree (or 2.6.12-rc6 when/if that is ever released). It
> > requires one other patch to be applied first:
> > 
> > http://gate.crashing.org/~benh/ppc32-remove-macserial.diff
> > 
> > The PM patch itself can be found at:
> > 
> > http://gate.crashing.org/~benh/ppc32-rework-pm.diff
> > 
> > This patch completely reworks both suspend-to-ram and suspend-to-disk
> > support on PowerMac:
[...snip...]

Today I applied the two mentioned patches to rc5-git6. There were quite
a lot of offsets and one time fuzz 2 (hunk 10 in via-pm.c). But still I
get a freeze on my PowerBook6,2 (12", 1Ghz from Dec. 2004) when I
suspend to disk from X. If I suspend from tty1 the first time, the
following suspends work well even from X.

Thanks for your work,

Wolfi

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* RE : RE : copy_from_user( ) problem...help
From: Garcia Jérémie @ 2005-06-02 13:00 UTC (permalink / raw)
  To: Jeff.Fellin; +Cc: linuxppc-dev

Ok Jeff. Thanks a lot for your help and let me congratulate you for your =
answer's quality.
Really you're a treasure for people like me.=20
Nevertheless, I tried another way using ioctl() and that works very well =
and with your explanations
I understand now why. So it's all process context related.

Have a nice day and thks again, sincerly
J=E9r=E9mie



-------- Message d'origine--------
De: Jeff.Fellin@rflelect.com [mailto:Jeff.Fellin@rflelect.com]
Date: jeu. 02/06/2005 14:21
=C0: Garcia J=E9r=E9mie
Objet : RE : copy_from_user( ) problem...help
=20

Jeff Fellin
RFL Electronics
Jeff.Fellin@rflelect.com
973 334-3100, x 327


                                                                         =
                                             =20
                      Garcia J=E9r=E9mie                                 =
                                                 =20
                      <GARCIAJ@3il.fr>         To:       =
<Jeff.Fellin@rflelect.com>                                   =20
                                               cc:                       =
                                             =20
                      06/02/2005 04:27         Subject:  RE : =
copy_from_user( ) problem...help                        =20
                                                                         =
                                             =20
                                                                         =
                                             =20




I'm sorry to be such a newbie in Linux, but I don't understand why the
problem
would be process-related.
      As described in Linux Kernel Development by Robert Love under =
Process
Management, section
      Process Context: When a process a system call it enters kernel =
state.
At this point the
      kernel is said to be "executing on behalf of the user process" and =
is
in process context.

      The kernel is not a self-executing process. It only executes on
interrupts or user process
      requests. When executing on user process request, the only visible
user space is the user
      address space of the process invoking the system call. Not all =
user
processes are
      addressable.

Cause the copy_from_user() just needs an user-space address whatever is =
the
process. Isn't it
what I do here?
      Yes, it needs a user-space address, at the address is dereferenced
using the current             processes address mapping. In your example =
of
a small process all of it's addresses
      would probably exist in any other process. However, for the kernel =
to
reference the
      address space of a process not executing the system call requires
finding the page
      table of the process and then decoding the address to the physical
address, mapping that
      address into the kernel, and copying the data into the kernel.


So how would that kernel routine be usable?
      The routine is usable, but only within the context of the current
process, not an
      arbitary process. See Chapter 4, System calls for more reasons.

Could you give me a little more explanations? And could you tell me if =
what
I want to do
is possible using that way and what I missed?
      I hope the above and references are sufficient explanation. There =
is
no possible method
      to pass addresses from different processes into the kernel. You =
must
always obey the
      Process Context concept. Others have suggested methods to resolve
this issue via sysfs,
      which is also described in Rober Love's book. I suggest you =
purchase
this and read it
      before continuing.


-------- Message d'origine--------
De: Jeff.Fellin@rflelect.com [mailto:Jeff.Fellin@rflelect.com]
Date: mer. 01/06/2005 16:48
=C0: Garcia J=E9r=E9mie
Objet : Re: copy_from_user( ) problem...help


Jeremie,
The Address you give is to the user process to your kernel is an address =
in
the insmod
process, which is the actual user process your module is referencing. =
You
can verify this
by printing out the process id's in your user command, and the
current->pid, in your module.
They should be different, and the current->pid in your module should be =
the
PID of the insmod
command.

Jeff Felline insmod
RFL Electronics
Jeff.Fellin@rflelect.com
973 334-3100, x 327



                      Garcia J=E9r=E9mie

                      <GARCIAJ@3il.fr>            To:
<linuxppc-dev@ozlabs.org>
                      Sent by:                    cc:

                      linuxppc-dev-bounces        Subject:  =
copy_from_user(
) problem...help
                      @ozlabs.org


e insmod (you c
                      06/01/2005 10:00







Hi everybody,
I'm tryin to write some device drivers modules in order to manage some =
of
our devices of our ppc405EP based board.
I read the Allessandro Rubini book (Linux Kernel device drivers) in =
order
to help me.
Before going on difficult stuff, I'd like to make some basic training =
and
experiments.
What I want to do seems to be very easy (but...):
 - a user space programm has a global structure and contains an integer =
and
a char
 - the user space programm loads the module with a parameter: the =
structure
address
 - during the init_module(),I check that the address can be accessed in =
R/W
mode with the access_ok()
 - the module copies the user structure in its own context and prints =
the
values retreived

So, it's supposed to be a very easy operation, but something goes wrong.
Could someone give me a clue cause
I read it again and again and I don't get what's the matter. Here is the
code:

/************************************************************************=
******/


/*                           USER SPACE PROG
*/
/************************************************************************=
******/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

typedef struct une_structure
{
    int un_entier;
    char un_char;
}UNE_STRUCTURE;

UNE_STRUCTURE my_structure;

void main(void)
{
    char buff[100];

    /* Init of the structure */
    my_structure.un_entier =3D 5;
    my_structure.un_char =3D 'a';

    /* Build the shell command to load the module */
    sprintf(buff,"insmod -q ./un_module.o addr=3D%p",&my_structure);

    /* Print the shell command that loads the module */
    printf("\nCommmande : ");
    puts(buff);

    /* Load the module*/
    system(buff);

    sleep(2);

    /* Remove the module */
    system("rmmod un_module");
}


/************************************************************************=
/
/*                      KERNEL MODULE                                   =
*/
/************************************************************************=
/
[...]
typedef struct une_structure
{
    int un_entier;
    char un_char;
}UNE_STRUCTURE;

UNE_STRUCTURE *addr =3D 0x0;  /* default value */

MODULE_PARM(addr,"l");      /* get the address of the user space =
structure
                               given in argument at insmod()
*/


int init_module(void)
{
  int rc;
  UNE_STRUCTURE * my_structure;

  printk("Address of the user structure : %d\n",(int)addr);

  /* Alloc space for ou structure */
  my_structure =3D kmalloc(sizeof(UNE_STRUCTURE),GFP_DMA);
  if(my_structure=3D=3DNULL)
  {
    printk("Kernel memory allocation failed!\n");
    return -1;
  }
  else
    printk("Kernel memory allocation succeeded!\n");

  rc =3D access_ok(VERIFY_READ,(void *)addr,sizeof(UNE_STRUCTURE));
  if(rc !=3D 0)
  {
     rc =3D access_ok(VERIFY_WRITE,(void *)addr,sizeof(UNE_STRUCTURE));
     if(rc !=3D 0)
     {
          rc =3D copy_from_user(my_structure,(void
*)addr,sizeof(UNE_STRUCTURE));
          if(rc)
              printk("Error in copy_from_user, rc=3D%d\n",rc);
          else
          {
            printk("Values of the retreived user-space structure 's
fields:\n");
            printk("\t -> un_entier =3D %d \n",my_structure->un_entier);
            printk("\t -> un_unsigned_char =3D %c =
\n",my_structure->un_char);
          }

      }
      else
      {
          printk("Erreur in accessing addr in WRITE mode\n");
          return -1;
      }
    }
    else
    {
      printk("Erreur in accessing addr in READ mode\n");
      return -1;
    }
    return 0;
}

/************************************************************************=
***/


/*                         EXECUTION RESULTS
*/
/************************************************************************=
***/


root@10.16.9.232:/home/testDir# ./une_appli.exe

[USER-SPACE]Commmande : insmod -q ./un_module.o addr=3D0x10010a74
[KERN-SPACE]Address of the user structure : 268503668               // =
is
the same if converted in hexa
[KERN-SPACE]Kernel memory allocation succeeded!
[KERN-SPACE]Values of the retreived user-space structure 's fields:
               -> un_entier =3D -1857486844                           //
weird result and !=3D 5
               -> un_unsigned_char =3D .                              //
weird result and !=3D 'a'

[KERN-SPACE]Now releasing the module...


As you can see, I don't really retreived the user-space structure in the
kernel. Is it an address problem?
If I understood well, no ioremap is needded here cause the address given =
in
argument of insmod is from MMU.
So what's the problem ; I really think that I'm dealing with a wrong
address.

Please help a newbie that would like to understand... Tks for your =
precious
help.
Jeremie

_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev

^ permalink raw reply

* RE: Newbie question on Linux-PPC
From: Srivatsan CR @ 2005-06-02  7:41 UTC (permalink / raw)
  To: linuxppc-embedded

[-- Attachment #1: Type: text/plain, Size: 696 bytes --]

 
Hi all,
 
   Thanks everyone for the time. It's done and I have it working.
 
   I have another question regarding MAC address in Linux. I had ported
U-boot onto our customized board (MPC8280 based). It is working fine. I am
also able to boot a Linux Kernel. The Kernel version is Linux-2.4.20 . 
 
We set the MAC address for the board in U-boot as 00:FD:11:01:01:01. But
when the Linux Kernel boots it takes the MAC as 00:FD:81:01:01:01. 
 
I have confirmed that the U-boot passes the MAC address properly to the
Linux Kernel properly. Can anyone guide me to where to look out for the
issue stated above in the Linux code? 
 
Thanks everyone for the time. 
 
With Regards,
C.R.Srivatsan
 
 
 

[-- Attachment #2: Type: text/html, Size: 7455 bytes --]

^ permalink raw reply

* Re: [RFC] handle access to non-present IO ports on 8xx
From: Pantelis Antoniou @ 2005-06-02  7:04 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linux-ppc-embedded
In-Reply-To: <1117680392.31082.16.camel@gaston>

Benjamin Herrenschmidt wrote:
> On Wed, 2005-06-01 at 13:50 -0300, Marcelo Tosatti wrote:
> 
> Hrm... removing a PCMCIA card triggers mchecks ? that is bad... With
> "proper" PCMCIA controllers, those are swallowed properly when the card
> is removed. The eating of the machine check is a bit too hackish to my
> taste... Better is to "not do that" by making sure the legacy crap isn't
> trying  to tap unexisting ports, but then, if PCMCIA is also a
> problem...
> 

8xx is not proper in any way whatsoever :)

There's no way to fix this thing with simple software hacks.

For example take a PCMCIA driver that's minding it's own businees,
when someone yanks the card out.

cli()
...
inb(xxx)
...
<----- card is yanked here
...
inb(yyy)
...
<----- MCE here
sti()

> 
>>1) why does the current PowerMac version covers only inb() and not outb() ?  
>>I had to add outb() exception table entries for 8xx.
> 
> 
> Not sure, maybe historical loss ? :) You should CC paulus
> 
> 
>>2) Is the same wanted for other embedded PPC's? 
> 
> 
> It's up to you. It slows down those IOs, but on the other hand, inX/outX
> aren't supposed to be very common anymore, at least not with "fast"
> devices, and the IO itself is usually an order of magnitude slower than
> doing those syncs...
> 

Fast ISA I/O. :)

> 
>>3) How to make the misc.S exception entries and additional instructions 
>>selectable only on the platform who need it? #ifdef does not sound 
>>a good idea. 

I wouldn't mind...

>>
>>Nevermind the "#ifdef CONFIG_ALL_PPC" crap - that needs to be done
>>properly.
>>
>>

Regards

Pantelis

P.S. Good job marcello :)

^ permalink raw reply

* Re: Booting the linux-ppc64 kernel & flattened device tree v0.4
From: David Gibson @ 2005-06-02  7:09 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: linuxppc-dev list, u-boot-users, linuxppc64-dev,
	linuxppc-embedded
In-Reply-To: <1117614390.19020.24.camel@gaston>

On Wed, Jun 01, 2005 at 06:26:30PM +1000, Benjamin Herrenschmidt wrote:
> DO NOT REPLY TO ALL LISTS PLEASE ! (and CC me on replies).
> 
> Here's the fourth version of my document along with new kernel patches
> for the new improved flattened format, and the first release of the
> device-tree "compiler" tool. The patches will be posted as a reply to
> this email. The compiler, dtc, can be downloaded, the URL is in the
> document.

[snip]

> IV - "dtc", the device tree compiler
> ====================================

> 
> dtc source code can be found at
> <http://ozlabs.org/~dgibson/dtc/dtc.tar.gz>

I've just updated the dtc tarball with a new version.  Notable
changes:
	- Corrected comment parsing
	- Corrected handling of #address-cells, #size-cells properties
	- Input from device tree blobs should actually work now
	- Corrected autogeneration of "name" properties in blob/asm
	  output version < 0x10
	- Added a TODO list

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/people/dgibson

^ permalink raw reply

* Re: Tiny patch for arch/ppc/kernel/cputable.c to properly support the IBM PowerPC 750CXe rev 3.1
From: Benjamin Herrenschmidt @ 2005-06-02  5:41 UTC (permalink / raw)
  To: Nicolas DET; +Cc: linuxppc-dev
In-Reply-To: <20050602053107.111887000086@mwinf0701.wanadoo.fr>

On Thu, 2005-06-02 at 07:29 +0100, Nicolas DET wrote:
> Hello Benjamin,
> 
> On 01/06/2005, you wrote:
> > On Wed, 2005-06-01 at 19:14 +0100, Nicolas DET wrote:
> >> Hello,
> >> 
> >> You can find enclosed a small patch to properly support the 750 CXe rev
> >> 3.1. Indeed, the current kernel (2.6.11.11) only supports rev 2.1 and
> >> ignores 3.1
> >> 
> >> It's a tiny patch: it only add an entry in the table with the correct
> >> PVR and name. Others values has been copied from 750CXe rev 2.1.
> >> 
> >> I succesfully patched & compiled a vanila 2.6.11.11 from kernel.org.
> 
> > Is it needed ? I have it in my local tree and never actuall remembered
> > to actually send it :) In general, that kind of entries are really only
> > needed when there is a feature change...
> 
> .cpu_features is exactly the same compare to 745/755 (750CXe 3.1, PVR 0008
> 3311, was probed as 745/755). However, there is a small difference: It now
> calls __setup_cpu_750cx instead of __setup_cpu_750.
> This end up calling setup_750cx which looks like to disable NAP.

Ah, yes, for some PLL configurations... if the CXe is not affected by
this bug, it should probably avoid that "fixup" then...

> Well, I did not notice anything before and after the patch. It's more
> 'comsetic': cpuinfo shows the correct cpu name. :-)
> 
> Regards

^ permalink raw reply

* Re: Tiny patch for arch/ppc/kernel/cputable.c to properly support the IBM PowerPC 750CXe rev 3.1
From: Nicolas DET @ 2005-06-02  6:29 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, linuxppc-dev
In-Reply-To: <1117664786.19020.81.camel@gaston>

Hello Benjamin,

On 01/06/2005, you wrote:
> On Wed, 2005-06-01 at 19:14 +0100, Nicolas DET wrote:
>> Hello,
>> 
>> You can find enclosed a small patch to properly support the 750 CXe rev
>> 3.1. Indeed, the current kernel (2.6.11.11) only supports rev 2.1 and
>> ignores 3.1
>> 
>> It's a tiny patch: it only add an entry in the table with the correct
>> PVR and name. Others values has been copied from 750CXe rev 2.1.
>> 
>> I succesfully patched & compiled a vanila 2.6.11.11 from kernel.org.

> Is it needed ? I have it in my local tree and never actuall remembered
> to actually send it :) In general, that kind of entries are really only
> needed when there is a feature change...

.cpu_features is exactly the same compare to 745/755 (750CXe 3.1, PVR 0008
3311, was probed as 745/755). However, there is a small difference: It now
calls __setup_cpu_750cx instead of __setup_cpu_750.
This end up calling setup_750cx which looks like to disable NAP.

Well, I did not notice anything before and after the patch. It's more
'comsetic': cpuinfo shows the correct cpu name. :-)

Regards
-- 
Nicolas DET
MorphOS & Linux developer

^ permalink raw reply

* Re: [RFC] handle access to non-present IO ports on 8xx
From: Benjamin Herrenschmidt @ 2005-06-02  2:46 UTC (permalink / raw)
  To: Marcelo Tosatti; +Cc: linux-ppc-embedded
In-Reply-To: <20050601165054.GA2607@logos.cnet>

On Wed, 2005-06-01 at 13:50 -0300, Marcelo Tosatti wrote:

Hrm... removing a PCMCIA card triggers mchecks ? that is bad... With
"proper" PCMCIA controllers, those are swallowed properly when the card
is removed. The eating of the machine check is a bit too hackish to my
taste... Better is to "not do that" by making sure the legacy crap isn't
trying  to tap unexisting ports, but then, if PCMCIA is also a
problem...

> 1) why does the current PowerMac version covers only inb() and not outb() ?  
> I had to add outb() exception table entries for 8xx.

Not sure, maybe historical loss ? :) You should CC paulus

> 2) Is the same wanted for other embedded PPC's? 

It's up to you. It slows down those IOs, but on the other hand, inX/outX
aren't supposed to be very common anymore, at least not with "fast"
devices, and the IO itself is usually an order of magnitude slower than
doing those syncs...

> 3) How to make the misc.S exception entries and additional instructions 
> selectable only on the platform who need it? #ifdef does not sound 
> a good idea. 
> 
> Nevermind the "#ifdef CONFIG_ALL_PPC" crap - that needs to be done
> properly.
> 
> 
> Index: arch/ppc/kernel/misc.S
> ===================================================================
> RCS file: /mnt/test1/tslinux_mv21/linux-216/arch/ppc/kernel/misc.S,v
> retrieving revision 1.2
> diff -u -r1.2 misc.S
> --- arch/ppc/kernel/misc.S	22 Oct 2003 19:34:30 -0000	1.2
> +++ arch/ppc/kernel/misc.S	1 Jun 2005 17:59:30 -0000
> @@ -736,8 +736,23 @@
>  	subi	r4,r4,1
>  	blelr-
>  00:	lbz	r5,0(r3)
> -	eieio
> -	stbu	r5,1(r4)
> +01:	eieio
> +02:	stbu	r5,1(r4)
> +03:	twi 0, r5, 0
> +04:	isync
> +05:	nop

Hrm... the "twi/isync" stuff is not valid for a store. The reason for
doing twi here is to trigger a data dependency on the result of the load
(to make sure the load actually happens) and the isync to make sure that
twi has actually completed. For stores, you are stuffed... either your
HW don't do machine checks on stores, or you put a sync here and "hope"
you don't have write posting along the IO chain that would cause your
machine check to arrive too late...

Ben.

^ permalink raw reply

* Re: [PATCH][1/3] RapidIO support: core
From: Greg KH @ 2005-06-02  0:02 UTC (permalink / raw)
  To: Matt Porter; +Cc: akpm, torvalds, linux-kernel, linuxppc-embedded
In-Reply-To: <20050601110836.A16559@cox.net>

On Wed, Jun 01, 2005 at 11:08:36AM -0700, Matt Porter wrote:
> Patch is 108KB and can be found here:
> ftp://source.mvista.com/pub/rio/l26_rio_core.patch

register_driver() does not return the number of devices bound to the
driver.  So your comment in rio_register_driver() is incorrect.  Just
return count.

Hm, if the patch was inline it would be easier to comment on stuff like
this, I'll wait till then for the rest :)

thanks,

greg k-h

^ permalink raw reply

* Re: [PATCH][1/3] RapidIO support: core
From: Greg KH @ 2005-06-02  0:00 UTC (permalink / raw)
  To: Matt Porter; +Cc: akpm, torvalds, linux-kernel, linuxppc-embedded
In-Reply-To: <20050601110836.A16559@cox.net>

On Wed, Jun 01, 2005 at 11:08:36AM -0700, Matt Porter wrote:
> Adds a RapidIO subsystem to the kernel. RIO is a switched
> fabric interconnect used in higher-end embedded applications.
> The curious can look at the specs over at http://www.rapidio.org
> 
> The core code implements enumeration/discovery, management of
> devices/resources, and interfaces for RIO drivers.
> 
> There's a lot more to do to take advantages of all the hardware
> features. However, this should provide a good base for folks
> with RIO hardware to start contributing.
> 
> Signed-off-by: Matt Porter <mporter@kernel.crashing.org>
> 
> Patch is 108KB and can be found here:
> ftp://source.mvista.com/pub/rio/l26_rio_core.patch

Care to split it up into logical sections and post it?  It should be
small enough to do so that way.

thanks,

greg k-h

^ permalink raw reply

* Re: [PATCH][1/3] RapidIO support: core
From: Matt Porter @ 2005-06-01 22:58 UTC (permalink / raw)
  To: linux-kernel, linuxppc-embedded
In-Reply-To: <20050601110836.A16559@cox.net>

On Wed, Jun 01, 2005 at 11:08:36AM -0700, Matt Porter wrote:
> Adds a RapidIO subsystem to the kernel. RIO is a switched
> fabric interconnect used in higher-end embedded applications.
> The curious can look at the specs over at http://www.rapidio.org
> 
> The core code implements enumeration/discovery, management of
> devices/resources, and interfaces for RIO drivers.

I'm also hacking on a rioutils package (derived from pciutils)
that has a lsrio that works pretty much like the familiar
lspci tool.  The initial release can be grabbed from:
ftp://source.mvista.com/pub/rio/rioutils-0.10.tar.bz2

-Matt

^ permalink raw reply

* Re: RFC: PHY Abstraction Layer II
From: Andy Fleming @ 2005-06-01 22:42 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: Netdev, Embedded PPC Linux list
In-Reply-To: <429E2653.6010101@osdl.org>


On Jun 1, 2005, at 16:19, Stephen Hemminger wrote:

> Andy Fleming wrote:
>>
>> But not this one.  The phy_read and phy_write functions are  
>> reading  from and writing to a bus.  It is a reasonable  
>> implementation to have  the operation block in the bus driver, and  
>> be awoken when an  interrupt signals the operation is done.  All  
>> of the phydev spinlocks  have been arranged so as to prevent the  
>> lock being taken during  interrupt time.
>>
>> Unless I've misunderstood spinlocks (it wouldn't be the first  
>> time),  as long as the lock is never taken in interrupt time, it  
>> should be ok  to hold the lock, and wait for an interrupt before  
>> clearing the lock.
>>
>
>
> The problem is that sleeping is defined in the linux kernel as  
> meaning waiting on a mutual exclusion
> primitive (like semaphore) that puts the current thread to sleep.  
> It is not legal to sleep with a spinlock held.
> In the phy_read code you do:
>     spin_lock_bh(&bus->mdio_lock);
>    retval = bus->read(bus, phydev->addr, regnum);
>    spin_unlock_bh(&bus->mdio_lock);
>
> If the bus->read function were to do something like start a request  
> and wait on a semaphore, then
> you would be sleeping with a spin lock held.  So bus->read can not  
> sleep! (as sleep is defined in the
> linux kernel).

Hmm...  I understand this reasoning, but I still need a way for a bus  
read to wait for an interrupt before returning.  I suppose I can just  
have the code spin while it waits, but that seems wrong, somehow.   
I'm open to any suggestions.

^ permalink raw reply

* Re: RFC: PHY Abstraction Layer II
From: Andy Fleming @ 2005-06-01 22:36 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: Netdev, Embedded PPC Linux list
In-Reply-To: <20050601144123.2bc11c06@dxpl.pdx.osdl.net>


On Jun 1, 2005, at 16:41, Stephen Hemminger wrote:

> On Wed, 1 Jun 2005 15:45:26 -0500
> Andy Fleming <afleming@freescale.com> wrote:
>>
>>>     * get rid of bus read may sleep implication in comment.
>>>       since you are holding phy spin lock it better not!!
>>>
>>
>>
>
> On a different note, I am not sure that using sysfs/kobject bus object
> is the right thing for this object.  Isn't the phy instance really  
> just
> an kobject whose parent is the network device?  I can't see a 1 to N
> relationship between phy bus and phy objects existing.

Well, the MII Management bus is, in fact, a bus.  When a network  
driver wants to modify a PHY, it must access that bus.  Many ethernet  
controllers have a 1 to 1 relationship, since a typical NIC is a PCI  
card with 1 ethernet port (meaning one controller, and one PHY).   
However, many systems have multiple ethernet controllers attached to  
one bus, which configures multiple PHYs.  Currently, these systems  
have been relying on luck to prevent multiple accesses to the same bus.

This tends to work because all of the PHY support is contained within  
the ethernet driver, so it is easy for such drivers to ensure that  
only one PHY transaction is done at a time.  This system begins to  
fall apart, though, when the PHY drivers start operating more  
independently to react to changing PHY state.  It really begins to  
fall apart if you have multiple drivers trying to access a shared  
bus.  For instance, the 8560 ADS board has 2 gigabit ethernet ports  
controlled by the gianfar driver, and 2 10/100 ports in the CPM  
subsystem, controlled by the fcc_enet driver.

These two drivers each have an access point for the bus, which use  
different mechanisms (one is a bit bang interface, and one is  
register based).  Using the new abstraction, it is possible for the  
FCC driver to use the gianfar driver's bus, thus saving code, and  
reducing complexity.

>
> The main use I can see for being a driver object is to catch  
> suspend/resume,
> and wouldn't you want that to be tied to the network device.

It would be quite easy for the network driver to suspend or resume  
the PHY and bus objects under the new abstraction.  However, if eth0  
is suspended, should it suspend the whole bus, and all the PHYs on  
it?  By making the MII bus an independent entity, eth0 can be  
suspended, and it can choose to suspend its PHY, but eth1 can  
continue to access its PHY over the bus, since those aren't suspended.

^ permalink raw reply

* Re: Tiny patch for arch/ppc/kernel/cputable.c to properly support the IBM PowerPC 750CXe rev 3.1
From: Benjamin Herrenschmidt @ 2005-06-01 22:26 UTC (permalink / raw)
  To: Nicolas DET; +Cc: linuxppc-dev
In-Reply-To: <20050601171555.9E86B1C00209@mwinf0808.wanadoo.fr>

On Wed, 2005-06-01 at 19:14 +0100, Nicolas DET wrote:
> Hello,
> 
> You can find enclosed a small patch to properly support the 750 CXe rev
> 3.1. Indeed, the current kernel (2.6.11.11) only supports rev 2.1 and
> ignores 3.1
> 
> It's a tiny patch: it only add an entry in the table with the correct PVR
> and name. Others values has been copied from 750CXe rev 2.1.
> 
> I succesfully patched & compiled a vanila 2.6.11.11 from kernel.org.

Is it needed ? I have it in my local tree and never actuall remembered
to actually send it :) In general, that kind of entries are really only
needed when there is a feature change...

Ben.

^ permalink raw reply

* [RFC] handle access to non-present IO ports on 8xx
From: Marcelo Tosatti @ 2005-06-01 16:50 UTC (permalink / raw)
  To: linux-ppc-embedded, Pantelis Antoniou, Dan Malek

Hi,

Accessing non present "IO ports" on 8xx generates MCE's. The exception is easily
triggered during insertion/removal/suspension of PCMCIA cards. 

The following (against ancient v2.4) adds exception table entries for I/O
instructions on 8xx (copied from the original Paul's PowerMac code), and
changes MachineCheckException() slightly to cover 8xx specific's (on 8xx
the MCE can be generated while executing the IO access instruction itself,
which is not the case on PowerMac's, as the comment on traps.c details).

A few things I'm wondering:

1) why does the current PowerMac version covers only inb() and not outb() ?  
I had to add outb() exception table entries for 8xx.

2) Is the same wanted for other embedded PPC's? 

3) How to make the misc.S exception entries and additional instructions 
selectable only on the platform who need it? #ifdef does not sound 
a good idea. 

Nevermind the "#ifdef CONFIG_ALL_PPC" crap - that needs to be done
properly.


Index: arch/ppc/kernel/misc.S
===================================================================
RCS file: /mnt/test1/tslinux_mv21/linux-216/arch/ppc/kernel/misc.S,v
retrieving revision 1.2
diff -u -r1.2 misc.S
--- arch/ppc/kernel/misc.S	22 Oct 2003 19:34:30 -0000	1.2
+++ arch/ppc/kernel/misc.S	1 Jun 2005 17:59:30 -0000
@@ -736,8 +736,23 @@
 	subi	r4,r4,1
 	blelr-
 00:	lbz	r5,0(r3)
-	eieio
-	stbu	r5,1(r4)
+01:	eieio
+02:	stbu	r5,1(r4)
+03:	twi 0, r5, 0
+04:	isync
+05:	nop
+06:	.section .fixup,"ax"
+07:		b 9f
+	.text
+08:	.section __ex_table, "a"
+		.align 2
+		.long 00b, 07b
+		.long 01b, 07b
+		.long 02b, 07b
+		.long 03b, 07b
+		.long 04b, 07b
+		.long 05b, 07b
+	.text
 	bdnz	00b
 	blr
 
@@ -747,10 +762,27 @@
 	subi	r4,r4,1
 	blelr-
 00:	lbzu	r5,1(r4)
-	stb	r5,0(r3)
-	eieio
+01:	stb	r5,0(r3)
+02:	eieio
+03:	twi 0, r5, 0
+04:	isync
+05:	nop
+06:	.section .fixup,"ax"
+07:		b 9f
+	.text
+08:	.section __ex_table, "a"
+		.align 2
+		.long 00b, 07b
+		.long 01b, 07b
+		.long 02b, 07b
+		.long 03b, 07b
+		.long 04b, 07b
+		.long 05b, 07b
+	.text
+
 	bdnz	00b
-	blr	
+9:	blr	
+
 
 _GLOBAL(_insw)
 	cmpwi	0,r5,0
@@ -758,10 +790,25 @@
 	subi	r4,r4,2
 	blelr-
 00:	lhbrx	r5,0,r3
-	eieio
-	sthu	r5,2(r4)
+01:	eieio
+02:	sthu	r5,2(r4)
+03:	twi 0, r5, 0
+04:	isync
+05:	nop
+06:	.section .fixup,"ax"
+07:		b 9f
+	.text
+08:	.section __ex_table, "a"
+		.align 2
+		.long 00b, 07b
+		.long 01b, 07b
+		.long 02b, 07b
+		.long 03b, 07b
+		.long 04b, 07b
+		.long 05b, 07b
+	.text
 	bdnz	00b
-	blr
+9:	blr
 
 _GLOBAL(_outsw)
 	cmpwi	0,r5,0
@@ -769,10 +816,25 @@
 	subi	r4,r4,2
 	blelr-
 00:	lhzu	r5,2(r4)
-	eieio
-	sthbrx	r5,0,r3	
+01:	eieio
+02:	sthbrx	r5,0,r3	
+03:	twi 0, r5, 0
+04:	isync
+05:	nop
+06:	.section .fixup,"ax"
+07:		b 9f	
+	.text
+08:	.section __ex_table, "a"
+		.align 2
+		.long 00b, 07b
+		.long 01b, 07b
+		.long 02b, 07b
+		.long 03b, 07b
+		.long 04b, 07b
+		.long 05b, 07b
+	.text
 	bdnz	00b
-	blr	
+9:	blr	
 
 _GLOBAL(_insl)
 	cmpwi	0,r5,0
@@ -780,10 +842,25 @@
 	subi	r4,r4,4
 	blelr-
 00:	lwbrx	r5,0,r3
-	eieio
-	stwu	r5,4(r4)
+01:	eieio
+02:	stwu	r5,4(r4)
+03:	twi 0, r5, 0
+04:	isync
+05:	nop
+06:	.section .fixup,"ax"
+07:		b 9f
+	.text
+08:	.section __ex_table, "a"
+		.align 2
+		.long 00b, 07b
+		.long 01b, 07b
+		.long 02b, 07b
+		.long 03b, 07b
+		.long 04b, 07b
+		.long 05b, 07b
+	.text
 	bdnz	00b
-	blr
+9:	blr
 
 _GLOBAL(_outsl)
 	cmpwi	0,r5,0
@@ -791,10 +868,26 @@
 	subi	r4,r4,4
 	blelr-
 00:	lwzu	r5,4(r4)
-	stwbrx	r5,0,r3
-	eieio
+01:	stwbrx	r5,0,r3
+02:	eieio
+02:	stwu	r5,4(r4)
+03:	twi 0, r5, 0
+04:	isync
+05:	nop
+06:	.section .fixup,"ax"
+07:		b 9f
+	.text
+08:	.section __ex_table, "a"
+		.align 2
+		.long 00b, 07b
+		.long 01b, 07b
+		.long 02b, 07b
+		.long 03b, 07b
+		.long 04b, 07b
+		.long 05b, 07b
+	.text
 	bdnz	00b
-	blr	
+9:	blr	
 
 _GLOBAL(ide_insw)
 _GLOBAL(_insw_ns)
@@ -803,10 +896,25 @@
 	subi	r4,r4,2
 	blelr-
 00:	lhz	r5,0(r3)
-	eieio
-	sthu	r5,2(r4)
+01:	eieio
+02:	sthu	r5,2(r4)
+03:	twi 0, r5, 0
+04:	isync
+05:	nop
+06:	.section .fixup,"ax"
+07:		blr
+	.previous
+08:	.section __ex_table, "a"
+		.align 2
+		.long 00b, 07b
+		.long 01b, 07b
+		.long 02b, 07b
+		.long 03b, 07b
+		.long 04b, 07b
+		.long 05b, 07b
+	.previous
 	bdnz	00b
-	blr
+9:	blr
 
 _GLOBAL(ide_outsw)
 _GLOBAL(_outsw_ns)
@@ -815,10 +923,25 @@
 	subi	r4,r4,2
 	blelr-
 00:	lhzu	r5,2(r4)
-	sth	r5,0(r3)
-	eieio
+01:	sth	r5,0(r3)
+02:	eieio
+03:	twi 0, r5, 0
+04:	isync
+05:	nop
+06:	.section .fixup,"ax"
+07:		b 9f
+	.text
+08:	.section __ex_table, "a"
+		.align 2
+		.long 00b, 07b
+		.long 01b, 07b
+		.long 02b, 07b
+		.long 03b, 07b
+		.long 04b, 07b
+		.long 05b, 07b
+	.text
 	bdnz	00b
-	blr	
+9:	blr	
 
 _GLOBAL(_insl_ns)
 	cmpwi	0,r5,0
@@ -826,10 +949,10 @@
 	subi	r4,r4,4
 	blelr-
 00:	lwz	r5,0(r3)
-	eieio
-	stwu	r5,4(r4)
+01:	eieio
+02:	stwu	r5,4(r4)
 	bdnz	00b
-	blr
+9:	blr
 
 _GLOBAL(_outsl_ns)
 	cmpwi	0,r5,0
@@ -837,10 +960,10 @@
 	subi	r4,r4,4
 	blelr-
 00:	lwzu	r5,4(r4)
-	stw	r5,0(r3)
-	eieio
+01:	stw	r5,0(r3)
+02:	eieio
 	bdnz	00b
-	blr	
+9:	blr	
 
 /*
  * Extended precision shifts.
Index: arch/ppc/kernel/traps.c
===================================================================
RCS file: /mnt/test1/tslinux_mv21/linux-216/arch/ppc/kernel/traps.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 traps.c
--- arch/ppc/kernel/traps.c	19 Jun 2002 18:15:32 -0000	1.1.1.1
+++ arch/ppc/kernel/traps.c	1 Jun 2005 19:09:15 -0000
@@ -130,9 +130,7 @@
 void
 MachineCheckException(struct pt_regs *regs)
 {
-#ifdef CONFIG_ALL_PPC
 	unsigned long fixup;
-#endif /* CONFIG_ALL_PPC */
 	unsigned long msr = regs->msr;
 
 	if (user_mode(regs)) {
@@ -150,7 +148,7 @@
 		return;
 	}
 
-#ifdef CONFIG_ALL_PPC
+//#ifdef CONFIG_ALL_PPC
 	/*
 	 * I/O accesses can cause machine checks on powermacs.
 	 * Check if the NIP corresponds to the address of a sync
@@ -176,20 +174,25 @@
 			nip -= 2;
 		else if (*nip == 0x4c00012c)	/* isync */
 			--nip;
-		if (*nip == 0x7c0004ac || (*nip >> 26) == 3) {
+		/* eieio from I/O string functions */
+		else if ((*nip) == 0x7c0006ac || *(nip+1) == 0x7c0006ac)
+			nip += 2;
+
+		if (*nip == 0x7c0004ac || (*(nip+1) >> 26) == 3 ||
+				(*nip >> 26) == 3) {
 			/* sync or twi */
 			unsigned int rb;
 
 			--nip;
 			rb = (*nip >> 11) & 0x1f;
-			printk(KERN_DEBUG "%s bad port %lx at %p\n",
+			printk(KERN_ERR "%s bad port %lx at %p\n",
 			       (*nip & 0x100)? "OUT to": "IN from",
 			       regs->gpr[rb] - _IO_BASE, nip);
 			regs->nip = fixup;
 			return;
 		}
 	}
-#endif /* CONFIG_ALL_PPC */
+//#endif /* CONFIG_ALL_PPC */
 	printk("Machine check in kernel mode.\n");
 	printk("Caused by (from SRR1=%lx): ", msr);
 	switch (msr & 0x601F0000) {
Index: include/asm-ppc/io.h
===================================================================
RCS file: /mnt/test1/tslinux_mv21/linux-216/include/asm-ppc/io.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 io.h
--- include/asm-ppc/io.h	19 Jun 2002 18:16:26 -0000	1.1.1.1
+++ include/asm-ppc/io.h	30 May 2005 21:12:38 -0000
@@ -82,7 +82,7 @@
 #define insl(port, buf, nl)	_insl_ns((u32 *)((port)+_IO_BASE), (buf), (nl))
 #define outsl(port, buf, nl)	_outsl_ns((u32 *)((port)+_IO_BASE), (buf), (nl))
 
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_8xx
 /*
  * On powermacs, we will get a machine check exception if we
  * try to read data from a non-existent I/O port.  Because the
@@ -105,7 +105,7 @@
 {							\
 	unsigned int x;					\
 	__asm__ __volatile__(				\
-			op "	%0,0,%1\n"		\
+		"0:"	op "	%0,0,%1\n"		\
 		"1:	twi	0,%0,0\n"		\
 		"2:	isync\n"			\
 		"3:	nop\n"				\
@@ -116,6 +116,7 @@
 		".previous\n"				\
 		".section __ex_table,\"a\"\n"		\
 		"	.align	2\n"			\
+		"	.long   0b,5b\n"			\
 		"	.long	1b,5b\n"		\
 		"	.long	2b,5b\n"		\
 		"	.long	3b,5b\n"		\
@@ -129,12 +130,20 @@
 extern __inline__ void name(unsigned int val, unsigned int port) \
 {							\
 	__asm__ __volatile__(				\
-		op " %0,0,%1\n"				\
-		"1:	sync\n"				\
-		"2:\n"					\
+		"0:" op " %0,0,%1\n"			\
+		"1:  twi 0, %0, 0\n"			\
+		"2:   isync\n"				\
+		"3:   nop\n"				\
+		"4:\n"					\
+		".section .fixup,\"ax\"\n"		\
+		"5:	b	4b\n"			\
+		".previous\n"				\
 		".section __ex_table,\"a\"\n"		\
 		"	.align	2\n"			\
-		"	.long	1b,2b\n"		\
+		"	.long   0b,5b\n"		\
+		"	.long	1b,5b\n"		\
+		"	.long	2b,5b\n"		\
+		"	.long	3b,5b\n"		\
 		".previous"				\
 		: : "r" (val), "r" (port + _IO_BASE));	\
 }

^ permalink raw reply

* Re: Booting the linux-ppc64 kernel & flattened device tree v0.4
From: Benjamin Herrenschmidt @ 2005-06-01 21:58 UTC (permalink / raw)
  To: Jon Loeliger; +Cc: linuxppc-embedded@ozlabs.org
In-Reply-To: <1117655671.6517.99.camel@cashmere.sps.mot.com>

On Wed, 2005-06-01 at 14:54 -0500, Jon Loeliger wrote:
> On Wed, 2005-06-01 at 03:26, Benjamin Herrenschmidt wrote:
> > DO NOT REPLY TO ALL LISTS PLEASE ! (and CC me on replies).
> > 
> > Here's the fourth version of my document along with new kernel patches
> > for the new improved flattened format, and the first release of the
> > device-tree "compiler" tool. The patches will be posted as a reply to
> > this email. The compiler, dtc, can be downloaded, the URL is in the
> > document.
> > 
> > ---
> 
> > 
> > dtc source code can be found at <http://ozlabs.org/~dgibson/dtc/dtc.tar.gz>
> 
> Ben,
> 
> Here are diffs to:
> 
>     - Fix multi-line C-style comments.
> 
>     - Adjust the output of write_tree_source() such that it
>       separates properties and nodes a bit better.


Excellent, thanks. Please CC david next time.

Ben.

^ permalink raw reply

* Re: Booting the linux-ppc64 kernel & flattened device tree v0.4
From: Benjamin Herrenschmidt @ 2005-06-01 21:56 UTC (permalink / raw)
  To: Jon Loeliger; +Cc: linuxppc-embedded@ozlabs.org, David Gibson
In-Reply-To: <1117645131.6517.31.camel@cashmere.sps.mot.com>

On Wed, 2005-06-01 at 11:58 -0500, Jon Loeliger wrote:
> On Wed, 2005-06-01 at 03:26, Benjamin Herrenschmidt wrote:
> > Here's the fourth version of my document along with new kernel patches
> > for the new improved flattened format, and the first release of the
> > device-tree "compiler" tool. The patches will be posted as a reply to
> > this email. The compiler, dtc, can be downloaded, the URL is in the
> > document.
> 
> Ben,
> 
> Does it make sense to do this as well?

You mean include lsprop ? Well, I have another version of lsprop hacked
here that can generate a "source", but dtc can do it too now ... I think
we may just make dtc able to output in "lsprop" format too :) But I'll
talk to david (CC'd, he's the author of dtc).

Ben.

^ permalink raw reply

* [PATCH] [RFC] ppc32 (linux-2.6.11.4): remove the limitation of 2MB consistent DMA memory on ppc440
From: Shawn Jin @ 2005-06-01 21:55 UTC (permalink / raw)
  To: ppcembed, Ahamed K, Rafiq (HP)
In-Reply-To: <1B5A11557D6A86458B1AD15DBBDB6CE2066D8CF4@tayexc13.americas.cpqcorp.net>

[-- Attachment #1: Type: text/plain, Size: 905 bytes --]

Hi,

This patch removes the limitation of 2MB consistent DMA memory on
ppc440. Originally consistent_pte was allocated only one page no
matter what value of CONFIG_CONSISTENT_SIZE is set. By default
CONFIG_CONSISTENT_SIZE is 0x200000. This causes some troubles on high
performance I/O applications which may require more than 2MB
consistent DMA memory.

The modifications allocate multiple pages for consistent pte table
according to CONFIG_CONSISTENT_SIZE. For example if
CONFIG_CONSISTENT_SIZE is set to 4MB, 2 pages are allocated for
consistent pte table. Please note that CONFIG_CONSISTENT_SIZE cannot
be any value. You have to find a free continuous memory space on your
system memory mapping.

The patch was tested successfully on Ocotea board. But I'm not sure if
it works on other systems. Use it at your own risk. However feedback
is more than welcome. :)

Regards,
-Shawn.

[-- Attachment #2: dma-mapping.patch --]
[-- Type: application/octet-stream, Size: 4203 bytes --]

--- orig/linux-2.6.11.4/arch/ppc/kernel/dma-mapping.c	2005-03-15 16:08:58.000000000 -0800
+++ linux-2.6.11.4/arch/ppc/kernel/dma-mapping.c	2005-05-27 19:06:27.956937000 -0700
@@ -17,6 +17,11 @@
  * implementation. This is pulled straight from ARM and barely
  * modified. -Matt
  *
+ * Changed consistent_pte to consistent_ptes, in order to remove the 
+ * limitation of 2MB consistent DMA memory. Now the size is confined by
+ * CONFIG_CONSISTENT_SIZE. And there are multiple pages containing PTE.
+ * - Xiaogeng (Shawn) Jin (Agilent Technologies), 2005
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
@@ -66,11 +71,14 @@
 #define CONSISTENT_BASE	(CONFIG_CONSISTENT_START)
 #define CONSISTENT_END	(CONFIG_CONSISTENT_START + CONFIG_CONSISTENT_SIZE)
 #define CONSISTENT_OFFSET(x)	(((unsigned long)(x) - CONSISTENT_BASE) >> PAGE_SHIFT)
+#define	CONSISTENT_PTE_PAGENR	((CONFIG_CONSISTENT_SIZE >> PAGE_SHIFT) >> PTE_SHIFT)
+#define CONSISTENT_SIZE_PER_PTEPAGE	(1UL << (PAGE_SHIFT + PTE_SHIFT))
 
 /*
- * This is the page table (2MB) covering uncached, DMA consistent allocations
+ * This is page tables covering uncached, DMA consistent allocations,
+ * with the size of CONFIG_CONSISTENT_SIZE
  */
-static pte_t *consistent_pte;
+pte_t **consistent_ptes = NULL;
 static DEFINE_SPINLOCK(consistent_lock);
 
 /*
@@ -180,7 +188,7 @@
 	unsigned long order;
 	u64 mask = 0x00ffffff, limit; /* ISA default */
 
-	if (!consistent_pte) {
+	if (!consistent_ptes) {
 		printk(KERN_ERR "%s: not initialised\n", __func__);
 		dump_stack();
 		return NULL;
@@ -219,9 +227,14 @@
 	c = vm_region_alloc(&consistent_head, size,
 			    gfp & ~(__GFP_DMA | __GFP_HIGHMEM));
 	if (c) {
-		pte_t *pte = consistent_pte + CONSISTENT_OFFSET(c->vm_start);
+		pte_t *pte;
+		int offset = CONSISTENT_OFFSET(c->vm_start);
+		int idx = offset >> PTE_SHIFT;
 		struct page *end = page + (1 << order);
 
+		offset &= (1 << PTE_SHIFT) - 1;
+		pte = consistent_ptes[idx] + offset;
+
 		/*
 		 * Set the "dma handle"
 		 */
@@ -235,6 +248,11 @@
 			set_pte(pte, mk_pte(page, pgprot_noncached(PAGE_KERNEL)));
 			page++;
 			pte++;
+			offset++;
+			if (offset > ((1 << PTE_SHIFT) - 1)) {
+				pte = consistent_ptes[++idx];
+				offset = 0;
+			}
 		} while (size -= PAGE_SIZE);
 
 		/*
@@ -264,6 +282,7 @@
 	struct vm_region *c;
 	unsigned long flags;
 	pte_t *ptep;
+	int offset, idx;
 
 	size = PAGE_ALIGN(size);
 
@@ -280,12 +299,21 @@
 		size = c->vm_end - c->vm_start;
 	}
 
-	ptep = consistent_pte + CONSISTENT_OFFSET(c->vm_start);
+	offset = CONSISTENT_OFFSET(c->vm_start);
+	idx = offset >> PTE_SHIFT;
+	offset &= (1 << PTE_SHIFT) - 1;
+	ptep = consistent_ptes[idx] + offset;
+
 	do {
 		pte_t pte = ptep_get_and_clear(ptep);
 		unsigned long pfn;
 
 		ptep++;
+		offset++;
+		if (offset > ((1 << PTE_SHIFT) - 1)) {
+			ptep = consistent_ptes[++idx];
+			offset = 0;
+		}
 
 		if (!pte_none(pte) && pte_present(pte)) {
 			pfn = pte_pfn(pte);
@@ -328,13 +356,22 @@
 	pgd_t *pgd;
 	pmd_t *pmd;
 	pte_t *pte;
-	int ret = 0;
+	int ret = 0, i;
+	unsigned long address;
 
 	spin_lock(&init_mm.page_table_lock);
 
-	do {
-		pgd = pgd_offset(&init_mm, CONSISTENT_BASE);
-		pmd = pmd_alloc(&init_mm, pgd, CONSISTENT_BASE);
+	consistent_ptes = (pte_t **)kmalloc(sizeof(pte_t **) * 
+					CONSISTENT_PTE_PAGENR, GFP_KERNEL);
+	if (!consistent_ptes) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	
+	for (i = 0, address = CONSISTENT_BASE; i < CONSISTENT_PTE_PAGENR; i++) {
+		pgd = pgd_offset(&init_mm, address);
+		pmd = pmd_alloc(&init_mm, pgd, address);
 		if (!pmd) {
 			printk(KERN_ERR "%s: no pmd tables\n", __func__);
 			ret = -ENOMEM;
@@ -342,16 +379,19 @@
 		}
 		WARN_ON(!pmd_none(*pmd));
 
-		pte = pte_alloc_kernel(&init_mm, pmd, CONSISTENT_BASE);
+		pte = pte_alloc_kernel(&init_mm, pmd, address);
 		if (!pte) {
 			printk(KERN_ERR "%s: no pte tables\n", __func__);
 			ret = -ENOMEM;
 			break;
 		}
 
-		consistent_pte = pte;
-	} while (0);
+		consistent_ptes[i] = pte;
+
+		address += CONSISTENT_SIZE_PER_PTEPAGE;
+	}
 
+out:
 	spin_unlock(&init_mm.page_table_lock);
 
 	return ret;

^ permalink raw reply

* Re: RFC: PHY Abstraction Layer II
From: Stephen Hemminger @ 2005-06-01 21:41 UTC (permalink / raw)
  To: Andy Fleming; +Cc: Netdev, Embedded PPC Linux list
In-Reply-To: <92F1428A-0B26-428B-8C06-35C7E5B9EEE3@freescale.com>

On Wed, 1 Jun 2005 15:45:26 -0500
Andy Fleming <afleming@freescale.com> wrote:

> 
> On May 31, 2005, at 12:59, Stephen Hemminger wrote:
> 
> > Here are some patches:
> >     * allow phy's to be modules
> >     * use driver owner for ref count
> >     * make local functions static where ever possible
> 
> I agree with all these.
> 
> >     * get rid of bus read may sleep implication in comment.
> >       since you are holding phy spin lock it better not!!
> 

On a different note, I am not sure that using sysfs/kobject bus object
is the right thing for this object.  Isn't the phy instance really just
an kobject whose parent is the network device?  I can't see a 1 to N
relationship between phy bus and phy objects existing. 

The main use I can see for being a driver object is to catch suspend/resume,
and wouldn't you want that to be tied to the network device.

^ permalink raw reply

* Does linuxppc_2_4_devel still accept patch?
From: ming lei @ 2005-06-01 21:32 UTC (permalink / raw)
  To: linuxppc-embedded
In-Reply-To: <20050524133819.B23084@cox.net>

Hi,

I found there is a serious problem in head_440.S
regarding the handling of mmucr in DataTLBmiss and
InstructionTLBmiss exceptions in 2.4 linux ppc branch.
Where should I submit the changes?

Which branch right now is active for ppc44x
development? Have we moved to linux kernel 2.6
official development already?

Ming

__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 

^ permalink raw reply

* Re: RFC: PHY Abstraction Layer II
From: Stephen Hemminger @ 2005-06-01 21:19 UTC (permalink / raw)
  To: Andy Fleming; +Cc: Netdev, Embedded PPC Linux list
In-Reply-To: <92F1428A-0B26-428B-8C06-35C7E5B9EEE3@freescale.com>

Andy Fleming wrote:

>
> On May 31, 2005, at 12:59, Stephen Hemminger wrote:
>
>> Here are some patches:
>>     * allow phy's to be modules
>>     * use driver owner for ref count
>>     * make local functions static where ever possible
>
>
> I agree with all these.
>
>>     * get rid of bus read may sleep implication in comment.
>>       since you are holding phy spin lock it better not!!
>
>
> But not this one.  The phy_read and phy_write functions are reading  
> from and writing to a bus.  It is a reasonable implementation to have  
> the operation block in the bus driver, and be awoken when an  
> interrupt signals the operation is done.  All of the phydev spinlocks  
> have been arranged so as to prevent the lock being taken during  
> interrupt time.
>
> Unless I've misunderstood spinlocks (it wouldn't be the first time),  
> as long as the lock is never taken in interrupt time, it should be ok  
> to hold the lock, and wait for an interrupt before clearing the lock.


The problem is that sleeping is defined in the linux kernel as meaning 
waiting on a mutual exclusion
primitive (like semaphore) that puts the current thread to sleep. It is 
not legal to sleep with a spinlock held.
In the phy_read code you do:
   
   spin_lock_bh(&bus->mdio_lock);
    retval = bus->read(bus, phydev->addr, regnum);
    spin_unlock_bh(&bus->mdio_lock);

If the bus->read function were to do something like start a request and 
wait on a semaphore, then
you would be sleeping with a spin lock held.  So bus->read can not 
sleep! (as sleep is defined in the
linux kernel).

   

^ permalink raw reply

* Re: RFC: PHY Abstraction Layer II
From: Andy Fleming @ 2005-06-01 20:45 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: Netdev, Embedded PPC Linux list
In-Reply-To: <20050531105939.7486e071@dxpl.pdx.osdl.net>


On May 31, 2005, at 12:59, Stephen Hemminger wrote:

> Here are some patches:
>     * allow phy's to be modules
>     * use driver owner for ref count
>     * make local functions static where ever possible

I agree with all these.

>     * get rid of bus read may sleep implication in comment.
>       since you are holding phy spin lock it better not!!

But not this one.  The phy_read and phy_write functions are reading  
from and writing to a bus.  It is a reasonable implementation to have  
the operation block in the bus driver, and be awoken when an  
interrupt signals the operation is done.  All of the phydev spinlocks  
have been arranged so as to prevent the lock being taken during  
interrupt time.

Unless I've misunderstood spinlocks (it wouldn't be the first time),  
as long as the lock is never taken in interrupt time, it should be ok  
to hold the lock, and wait for an interrupt before clearing the lock.

Andy Fleming

^ permalink raw reply

* Re: Booting the linux-ppc64 kernel & flattened device tree v0.4
From: Jon Loeliger @ 2005-06-01 19:54 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-embedded@ozlabs.org
In-Reply-To: <1117614390.19020.24.camel@gaston>

On Wed, 2005-06-01 at 03:26, Benjamin Herrenschmidt wrote:
> DO NOT REPLY TO ALL LISTS PLEASE ! (and CC me on replies).
> 
> Here's the fourth version of my document along with new kernel patches
> for the new improved flattened format, and the first release of the
> device-tree "compiler" tool. The patches will be posted as a reply to
> this email. The compiler, dtc, can be downloaded, the URL is in the
> document.
> 
> ---

> 
> dtc source code can be found at <http://ozlabs.org/~dgibson/dtc/dtc.tar.gz>

Ben,

Here are diffs to:

    - Fix multi-line C-style comments.

    - Adjust the output of write_tree_source() such that it
      separates properties and nodes a bit better.

Thanks,
jdl


diff -u dtc.orig/dtc-lexer.l dtc/dtc-lexer.l
--- dtc.orig/dtc-lexer.l	2005-06-01 11:44:29.000002000 -0500
+++ dtc/dtc-lexer.l	2005-06-01 13:39:56.000001000 -0500
@@ -34,8 +34,6 @@
 
 #include "y.tab.h"
 
-#undef LEXDEBUG	1
-
 %}
 
 \"[^"]*\"	{
@@ -102,7 +100,7 @@
 
 <*>{WS}+	/* eat whitespace */
 
-<*>\/\*[^*]*(\*[^/][^*])*\*\/	/* eat comments */
+<*>\/\*([^*]|\**[^*/])*\*+\/	/* eat C comments */
 
 <*>\/\/.*\n	/* eat line comments */
 
diff -u dtc.orig/treesource.c dtc/treesource.c
--- dtc.orig/treesource.c	2005-06-01 11:44:29.000002000 -0500
+++ dtc/treesource.c	2005-06-01 13:58:33.000001000 -0500
@@ -131,10 +131,16 @@
 			break;
 		}
 	}
-	fprintf(f, "\n");
+	if (tree->children) {
+		fprintf(f, "\n");
+	}
 	for_each_child(tree, child) {
 		write_tree_source(f, child, level+1);
 	}
 	write_prefix(f, level);
 	fprintf(f, "};\n");
+
+	if (tree->next_sibling) {
+		fprintf(f, "\n");
+	}
 }

^ permalink raw reply

* Re: bd_t Cleaning: Board Changes
From: Kumar Gala @ 2005-06-01 18:52 UTC (permalink / raw)
  To: Mark A. Greer, Dan Malek, Matt Porter, Tom Rini; +Cc: linuxppc-embedded
In-Reply-To: <429DFA28.30509@mvista.com>

Well, as 85xx/83xx maintainer I'm ok with it.  We should probably need 
4xx (Matt) and 8xx/82xx (Dan/Tom) agreement.

- kumar

On Jun 1, 2005, at 1:10 PM, Mark A. Greer wrote:

> Jon Loeliger wrote:
>
>> <snip>
>>
>> Part Two of Four, the Board Changes.
>>
>> ppc/platforms/4xx/ash.h                 |   21 -
>> ppc/platforms/4xx/bubinga.c             |    4
>> ppc/platforms/4xx/bubinga.h             |   23 -
>> ppc/platforms/4xx/cpci405.h             |    2
>> ppc/platforms/4xx/ebony.c               |    9
>> ppc/platforms/4xx/ep405.c               |   12
>> ppc/platforms/4xx/ep405.h               |   13
>> ppc/platforms/4xx/luan.c                |    7
>> ppc/platforms/4xx/oak.c                 |   15
>> ppc/platforms/4xx/oak.h                 |   19 -
>> ppc/platforms/4xx/oak_setup.h           |    2
>> ppc/platforms/4xx/ocotea.c              |   13
>> ppc/platforms/4xx/redwood5.h            |   13
>> ppc/platforms/4xx/redwood6.c            |   27 -
>> ppc/platforms/4xx/redwood6.h            |   13
>> ppc/platforms/4xx/sycamore.h            |   22 -
>> ppc/platforms/4xx/walnut.h              |   22 -
>> ppc/platforms/4xx/xilinx_ml300.h        |   12
>> ppc/platforms/83xx/mpc834x_sys.c        |   49 +-
>> ppc/platforms/83xx/mpc834x_sys.h        |    1
>> ppc/platforms/85xx/mpc8540_ads.c        |   57 ++-
>> ppc/platforms/85xx/mpc8560_ads.c        |   21 -
>> ppc/platforms/85xx/mpc85xx_ads_common.c |   10
>> ppc/platforms/85xx/mpc85xx_ads_common.h |    1
>> ppc/platforms/85xx/mpc85xx_cds_common.c |   48 +-
>> ppc/platforms/85xx/mpc85xx_cds_common.h |    1
>> ppc/platforms/85xx/sbc8560.c            |   19 -
>> ppc/platforms/85xx/sbc85xx.c            |   14
>> ppc/platforms/85xx/sbc85xx.h            |    1
>> ppc/platforms/85xx/stx_gp3.c            |   34 -
>> ppc/platforms/85xx/stx_gp3.h            |    1
>> ppc/platforms/bseip.h                   |   13
>> ppc/platforms/ccm.h                     |    2
>> ppc/platforms/cpci690.h                 |   10
>> ppc/platforms/est8260.h                 |   18
>> ppc/platforms/fads.h                    |    2
>> ppc/platforms/hdpu.c                    |   13
>> ppc/platforms/hermes.h                  |    2
>> ppc/platforms/ip860.h                   |    2
>> ppc/platforms/ivms8.h                   |    2
>> ppc/platforms/katana.c                  |    6
>> ppc/platforms/lantec.h                  |    2
>> ppc/platforms/lite5200.c                |    9
>> ppc/platforms/lwmon.h                   |    2
>> ppc/platforms/mbx.h                     |   22 -
>> ppc/platforms/pcu_e.h                   |    2
>> ppc/platforms/pq2ads.c                  |    1
>> ppc/platforms/pq2ads.h                  |    2
>> ppc/platforms/radstone_ppc7d.c          |   32 -
>> ppc/platforms/radstone_ppc7d.h          |    2
>> ppc/platforms/rpx8260.h                 |   19 -
>> ppc/platforms/rpxclassic.h              |   13
>> ppc/platforms/rpxlite.h                 |   13
>> ppc/platforms/sandpoint.c               |   11
>> ppc/platforms/sandpoint.h               |    2
>> ppc/platforms/sbc82xx.c                 |    6
>> ppc/platforms/sbc82xx.h                 |    2
>> ppc/platforms/sbs8260.h                 |   18
>> ppc/platforms/spd8xx.h                  |    2
>> ppc/platforms/tqm8260.h                 |    2
>> ppc/platforms/tqm8260_setup.c           |    1
>> ppc/platforms/tqm8xx.h                  |    2
>>
>>
>>
> <snip>
>
> All,
>
> So is this patch going to go in?  I haven't seen anyone "push it up".
> The reason I'm asking is that I have a couple patches that I would like
> to push up but they will collide with this one so I need to know if it
> (or a variation thereof) is going to go in or not.
>
> Thanks,
>
> Mark
>
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded

^ permalink raw reply

* [PATCH][3/3] RapidIO support: net driver over messaging
From: Matt Porter @ 2005-06-01 18:25 UTC (permalink / raw)
  To: torvalds, akpm, jgarzik; +Cc: netdev, linux-kernel, linuxppc-embedded
In-Reply-To: <20050601111516.B16559@cox.net>

Adds an "Ethernet" driver which sends Ethernet packets over the
standard RapidIO messaging. This depends on the core RIO
patch for mailbox/doorbell access.

Signed-off-by: Matt Porter <mporter@kernel.crashing.org>

Index: drivers/net/Kconfig
===================================================================
--- f0bf7810dbe8c4073832d6c3785364084e9523a7/drivers/net/Kconfig  (mode:100644)
+++ 4ed27b6e30a69f314a2ca131e80ac45e2111f245/drivers/net/Kconfig  (mode:100644)
@@ -2185,6 +2185,20 @@
 	tristate "iSeries Virtual Ethernet driver support"
 	depends on NETDEVICES && PPC_ISERIES
 
+config RIONET
+	tristate "RapidIO Ethernet over messaging driver support"
+	depends on NETDEVICES && RAPIDIO
+
+config RIONET_TX_SIZE
+	int "Number of outbound queue entries"
+	depends on RIONET
+	default "128"
+
+config RIONET_RX_SIZE
+	int "Number of inbound queue entries"
+	depends on RIONET
+	default "128"
+
 config FDDI
 	bool "FDDI driver support"
 	depends on NETDEVICES && (PCI || EISA)
Index: drivers/net/Makefile
===================================================================
--- f0bf7810dbe8c4073832d6c3785364084e9523a7/drivers/net/Makefile  (mode:100644)
+++ 4ed27b6e30a69f314a2ca131e80ac45e2111f245/drivers/net/Makefile  (mode:100644)
@@ -58,6 +58,7 @@
 obj-$(CONFIG_VIA_RHINE) += via-rhine.o
 obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o
 obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
+obj-$(CONFIG_RIONET) += rionet.o
 
 #
 # end link order section
Index: drivers/net/rionet.c
===================================================================
--- /dev/null  (tree:f0bf7810dbe8c4073832d6c3785364084e9523a7)
+++ 4ed27b6e30a69f314a2ca131e80ac45e2111f245/drivers/net/rionet.c  (mode:100644)
@@ -0,0 +1,622 @@
+/*
+ * rionet - Ethernet driver over RapidIO messaging services
+ *
+ * Copyright 2005 MontaVista Software, Inc.
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * 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 <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/rio.h>
+#include <linux/rio_drv.h>
+#include <linux/rio_ids.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/crc32.h>
+#include <linux/ethtool.h>
+
+#define DRV_NAME        "rionet"
+#define DRV_VERSION     "0.1"
+#define DRV_AUTHOR      "Matt Porter <mporter@kernel.crashing.org>"
+#define DRV_DESC        "Ethernet over RapidIO"
+
+MODULE_AUTHOR(DRV_AUTHOR);
+MODULE_DESCRIPTION(DRV_DESC);
+MODULE_LICENSE("GPL");
+
+#define RIONET_DEFAULT_MSGLEVEL	0
+#define RIONET_DOORBELL_JOIN	0x1000
+#define RIONET_DOORBELL_LEAVE	0x1001
+
+#define RIONET_MAILBOX		0
+
+#define RIONET_TX_RING_SIZE	CONFIG_RIONET_TX_SIZE
+#define RIONET_RX_RING_SIZE	CONFIG_RIONET_RX_SIZE
+
+LIST_HEAD(rionet_peers);
+
+struct rionet_private {
+	struct rio_mport *mport;
+	struct sk_buff *rx_skb[RIONET_RX_RING_SIZE];
+	struct sk_buff *tx_skb[RIONET_TX_RING_SIZE];
+	struct net_device_stats stats;
+	int rx_slot;
+	int tx_slot;
+	int tx_cnt;
+	int ack_slot;
+	spinlock_t lock;
+	u32 msg_enable;
+};
+
+struct rionet_peer {
+	struct list_head node;
+	struct rio_dev *rdev;
+	struct resource *res;
+};
+
+static int rionet_check = 0;
+static int rionet_capable = 1;
+static struct net_device *sndev = NULL;
+
+/*
+ * This is a fast lookup table for for translating TX
+ * Ethernet packets into a destination RIO device. It
+ * could be made into a hash table to save memory depending
+ * on system trade-offs.
+ */
+static struct rio_dev *rionet_active[RIO_MAX_ROUTE_ENTRIES];
+
+#define is_rionet_capable(pef, src_ops, dst_ops)		\
+			((pef & RIO_PEF_INB_MBOX) &&		\
+			 (pef & RIO_PEF_INB_DOORBELL) &&	\
+			 (src_ops & RIO_SRC_OPS_DOORBELL) &&	\
+			 (dst_ops & RIO_DST_OPS_DOORBELL))
+#define dev_rionet_capable(dev) \
+	is_rionet_capable(dev->pef, dev->src_ops, dev->dst_ops)
+
+#define RIONET_MAC_MATCH(x)	(*(u32 *)x == 0x00010001)
+#define RIONET_GET_DESTID(x)	(*(u16 *)(x + 4))
+
+static struct net_device_stats *rionet_stats(struct net_device *ndev)
+{
+	struct rionet_private *rnet = ndev->priv;
+	return &rnet->stats;
+}
+
+static int rionet_rx_clean(struct net_device *ndev)
+{
+	int i;
+	int error = 0;
+	struct rionet_private *rnet = ndev->priv;
+	void *data;
+
+	i = rnet->rx_slot;
+
+	do {
+		if (!rnet->rx_skb[i]) {
+			rnet->stats.rx_dropped++;
+			continue;
+		}
+
+		if (!(data = rio_get_inb_message(rnet->mport, RIONET_MAILBOX)))
+			break;
+
+		rnet->rx_skb[i]->data = data;
+		skb_put(rnet->rx_skb[i], RIO_MAX_MSG_SIZE);
+		rnet->rx_skb[i]->dev = sndev;
+		rnet->rx_skb[i]->protocol =
+		    eth_type_trans(rnet->rx_skb[i], sndev);
+		error = netif_rx(rnet->rx_skb[i]);
+
+		if (error == NET_RX_DROP) {
+			rnet->stats.rx_dropped++;
+		} else if (error == NET_RX_BAD) {
+			if (netif_msg_rx_err(rnet))
+				printk(KERN_WARNING "%s: bad rx packet\n",
+				       DRV_NAME);
+			rnet->stats.rx_errors++;
+		} else {
+			rnet->stats.rx_packets++;
+			rnet->stats.rx_bytes += RIO_MAX_MSG_SIZE;
+		}
+
+	} while ((i = (i + 1) % RIONET_RX_RING_SIZE) != rnet->rx_slot);
+
+	return i;
+}
+
+static void rionet_rx_fill(struct net_device *ndev, int end)
+{
+	int i;
+	struct rionet_private *rnet = ndev->priv;
+
+	i = rnet->rx_slot;
+	do {
+		rnet->rx_skb[i] = dev_alloc_skb(RIO_MAX_MSG_SIZE);
+
+		if (!rnet->rx_skb[i])
+			break;
+
+		rio_add_inb_buffer(rnet->mport, RIONET_MAILBOX,
+				   rnet->rx_skb[i]->data);
+	} while ((i = (i + 1) % RIONET_RX_RING_SIZE) != end);
+
+	rnet->rx_slot = i;
+}
+
+static int rionet_queue_tx_msg(struct sk_buff *skb, struct net_device *ndev,
+			       struct rio_dev *rdev)
+{
+	struct rionet_private *rnet = ndev->priv;
+
+	rio_add_outb_message(rnet->mport, rdev, 0, skb->data, skb->len);
+	rnet->tx_skb[rnet->tx_slot] = skb;
+
+	rnet->stats.tx_packets++;
+	rnet->stats.tx_bytes += skb->len;
+
+	if (++rnet->tx_cnt == RIONET_TX_RING_SIZE)
+		netif_stop_queue(ndev);
+
+	if (++rnet->tx_slot == RIONET_TX_RING_SIZE)
+		rnet->tx_slot = 0;
+
+	if (netif_msg_tx_queued(rnet))
+		printk(KERN_INFO "%s: queued skb %8.8x len %8.8x\n", DRV_NAME,
+		       (u32) skb, skb->len);
+
+	return 0;
+}
+
+static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+	int i;
+	struct rionet_private *rnet = ndev->priv;
+	struct ethhdr *eth = (struct ethhdr *)skb->data;
+	u16 destid;
+
+	spin_lock_irq(&rnet->lock);
+
+	if ((rnet->tx_cnt + 1) > RIONET_TX_RING_SIZE) {
+		netif_stop_queue(ndev);
+		spin_unlock_irq(&rnet->lock);
+		return -EBUSY;
+	}
+
+	if (eth->h_dest[0] & 0x01) {
+		/*
+		 * XXX Need to delay queuing if ring max is reached,
+		 * flush additional packets in tx_event() before
+		 * awakening the queue. We can easily exceed ring
+		 * size with a large number of nodes or even a
+		 * small number where the ring is relatively full
+		 * on entrance to hard_start_xmit.
+		 */
+		for (i = 0; i < RIO_MAX_ROUTE_ENTRIES; i++)
+			if (rionet_active[i])
+				rionet_queue_tx_msg(skb, ndev,
+						    rionet_active[i]);
+	} else if (RIONET_MAC_MATCH(eth->h_dest)) {
+		destid = RIONET_GET_DESTID(eth->h_dest);
+		if (rionet_active[destid])
+			rionet_queue_tx_msg(skb, ndev, rionet_active[destid]);
+	}
+
+	spin_unlock_irq(&rnet->lock);
+
+	return 0;
+}
+
+static int rionet_set_mac_address(struct net_device *ndev, void *p)
+{
+	struct sockaddr *addr = p;
+
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EADDRNOTAVAIL;
+
+	memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len);
+
+	return 0;
+}
+
+static int rionet_change_mtu(struct net_device *ndev, int new_mtu)
+{
+	struct rionet_private *rnet = ndev->priv;
+
+	if (netif_msg_drv(rnet))
+		printk(KERN_WARNING
+		       "%s: rionet_change_mtu(): not implemented\n", DRV_NAME);
+
+	return 0;
+}
+
+static void rionet_set_multicast_list(struct net_device *ndev)
+{
+	struct rionet_private *rnet = ndev->priv;
+
+	if (netif_msg_drv(rnet))
+		printk(KERN_WARNING
+		       "%s: rionet_set_multicast_list(): not implemented\n",
+		       DRV_NAME);
+}
+
+static void rionet_dbell_event(struct rio_mport *mport, u16 sid, u16 tid,
+			       u16 info)
+{
+	struct net_device *ndev = sndev;
+	struct rionet_private *rnet = ndev->priv;
+	struct rionet_peer *peer;
+
+	if (netif_msg_intr(rnet))
+		printk(KERN_INFO "%s: doorbell sid %4.4x tid %4.4x info %4.4x",
+		       DRV_NAME, sid, tid, info);
+	if (info == RIONET_DOORBELL_JOIN) {
+		if (!rionet_active[sid]) {
+			list_for_each_entry(peer, &rionet_peers, node) {
+				if (peer->rdev->destid == sid)
+					rionet_active[sid] = peer->rdev;
+			}
+			rio_mport_send_doorbell(mport, sid,
+						RIONET_DOORBELL_JOIN);
+		}
+	} else if (info == RIONET_DOORBELL_LEAVE) {
+		rionet_active[sid] = NULL;
+	} else {
+		if (netif_msg_intr(rnet))
+			printk(KERN_WARNING "%s: unhandled doorbell\n",
+			       DRV_NAME);
+	}
+}
+
+static void rionet_inb_msg_event(struct rio_mport *mport, int mbox, int slot)
+{
+	int n;
+	struct net_device *ndev = sndev;
+	struct rionet_private *rnet = (struct rionet_private *)ndev->priv;
+
+	if (netif_msg_intr(rnet))
+		printk(KERN_INFO "%s: inbound message event, mbox %d slot %d\n",
+		       DRV_NAME, mbox, slot);
+
+	spin_lock(&rnet->lock);
+	if ((n = rionet_rx_clean(ndev)) != rnet->rx_slot)
+		rionet_rx_fill(ndev, n);
+	spin_unlock(&rnet->lock);
+}
+
+static void rionet_outb_msg_event(struct rio_mport *mport, int mbox, int slot)
+{
+	struct net_device *ndev = sndev;
+	struct rionet_private *rnet = ndev->priv;
+
+	spin_lock(&rnet->lock);
+
+	if (netif_msg_intr(rnet))
+		printk(KERN_INFO
+		       "%s: outbound message event, mbox %d slot %d\n",
+		       DRV_NAME, mbox, slot);
+
+	while (rnet->tx_cnt && (rnet->ack_slot != slot)) {
+		/* dma unmap single */
+		dev_kfree_skb_irq(rnet->tx_skb[rnet->ack_slot]);
+		rnet->tx_skb[rnet->ack_slot] = NULL;
+		if (++rnet->ack_slot == RIONET_TX_RING_SIZE)
+			rnet->ack_slot = 0;
+		rnet->tx_cnt--;
+	}
+
+	if (rnet->tx_cnt < RIONET_TX_RING_SIZE)
+		netif_wake_queue(ndev);
+
+	spin_unlock(&rnet->lock);
+}
+
+static int rionet_open(struct net_device *ndev)
+{
+	int i, rc = 0;
+	struct rionet_peer *peer, *tmp;
+	u32 pwdcsr;
+	struct rionet_private *rnet = ndev->priv;
+
+	if (netif_msg_ifup(rnet))
+		printk(KERN_INFO "%s: open\n", DRV_NAME);
+
+	if ((rc = rio_request_inb_dbell(rnet->mport,
+					RIONET_DOORBELL_JOIN,
+					RIONET_DOORBELL_LEAVE,
+					rionet_dbell_event)) < 0)
+		goto out;
+
+	if ((rc = rio_request_inb_mbox(rnet->mport,
+				       RIONET_MAILBOX,
+				       RIONET_RX_RING_SIZE,
+				       rionet_inb_msg_event)) < 0)
+		goto out;
+
+	if ((rc = rio_request_outb_mbox(rnet->mport,
+					RIONET_MAILBOX,
+					RIONET_TX_RING_SIZE,
+					rionet_outb_msg_event)) < 0)
+		goto out;
+
+	/* Initialize inbound message ring */
+	for (i = 0; i < RIONET_RX_RING_SIZE; i++)
+		rnet->rx_skb[i] = NULL;
+	rnet->rx_slot = 0;
+	rionet_rx_fill(ndev, 0);
+
+	rnet->tx_slot = 0;
+	rnet->tx_cnt = 0;
+	rnet->ack_slot = 0;
+
+	spin_lock_init(&rnet->lock);
+
+	rnet->msg_enable = RIONET_DEFAULT_MSGLEVEL;
+
+	netif_carrier_on(ndev);
+	netif_start_queue(ndev);
+
+	list_for_each_entry_safe(peer, tmp, &rionet_peers, node) {
+		if (!(peer->res = rio_request_outb_dbell(peer->rdev,
+							 RIONET_DOORBELL_JOIN,
+							 RIONET_DOORBELL_LEAVE)))
+		{
+			printk(KERN_ERR "%s: error requesting doorbells\n",
+			       DRV_NAME);
+			continue;
+		}
+
+		/*
+		 * If device has initialized inbound doorbells,
+		 * send a join message
+		 */
+		rio_read_config_32(peer->rdev, RIO_WRITE_PORT_CSR, &pwdcsr);
+		if (pwdcsr & RIO_DOORBELL_AVAIL)
+			rio_send_doorbell(peer->rdev, RIONET_DOORBELL_JOIN);
+	}
+
+      out:
+	return rc;
+}
+
+static int rionet_close(struct net_device *ndev)
+{
+	struct rionet_private *rnet = (struct rionet_private *)ndev->priv;
+	struct rionet_peer *peer, *tmp;
+	int i;
+
+	if (netif_msg_ifup(rnet))
+		printk(KERN_INFO "%s: close\n", DRV_NAME);
+
+	netif_stop_queue(ndev);
+	netif_carrier_off(ndev);
+
+	for (i = 0; i < RIONET_RX_RING_SIZE; i++)
+		if (rnet->rx_skb[i])
+			kfree_skb(rnet->rx_skb[i]);
+
+	list_for_each_entry_safe(peer, tmp, &rionet_peers, node) {
+		if (rionet_active[peer->rdev->destid]) {
+			rio_send_doorbell(peer->rdev, RIONET_DOORBELL_LEAVE);
+			rionet_active[peer->rdev->destid] = NULL;
+		}
+		rio_release_outb_dbell(peer->rdev, peer->res);
+	}
+
+	rio_release_inb_dbell(rnet->mport, RIONET_DOORBELL_JOIN,
+			      RIONET_DOORBELL_LEAVE);
+	rio_release_inb_mbox(rnet->mport, RIONET_MAILBOX);
+	rio_release_outb_mbox(rnet->mport, RIONET_MAILBOX);
+
+	return 0;
+}
+
+static void rionet_remove(struct rio_dev *rdev)
+{
+	struct net_device *ndev = NULL;
+	struct rionet_peer *peer, *tmp;
+
+	unregister_netdev(ndev);
+	kfree(ndev);
+
+	list_for_each_entry_safe(peer, tmp, &rionet_peers, node) {
+		list_del(&peer->node);
+		kfree(peer);
+	}
+}
+
+static int rionet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
+{
+	return -EOPNOTSUPP;
+}
+
+static void rionet_get_drvinfo(struct net_device *ndev,
+			       struct ethtool_drvinfo *info)
+{
+	struct rionet_private *rnet = ndev->priv;
+
+	strcpy(info->driver, DRV_NAME);
+	strcpy(info->version, DRV_VERSION);
+	strcpy(info->fw_version, "n/a");
+	sprintf(info->bus_info, "RIO master port %d", rnet->mport->id);
+}
+
+static u32 rionet_get_msglevel(struct net_device *ndev)
+{
+	struct rionet_private *rnet = ndev->priv;
+
+	return rnet->msg_enable;
+}
+
+static void rionet_set_msglevel(struct net_device *ndev, u32 value)
+{
+	struct rionet_private *rnet = ndev->priv;
+
+	rnet->msg_enable = value;
+}
+
+static u32 rionet_get_link(struct net_device *ndev)
+{
+	return netif_carrier_ok(ndev);
+}
+
+static struct ethtool_ops rionet_ethtool_ops = {
+	.get_drvinfo = rionet_get_drvinfo,
+	.get_msglevel = rionet_get_msglevel,
+	.set_msglevel = rionet_set_msglevel,
+	.get_link = rionet_get_link,
+};
+
+static int rionet_setup_netdev(struct rio_mport *mport)
+{
+	int rc = 0;
+	struct net_device *ndev = NULL;
+	struct rionet_private *rnet;
+	u16 device_id;
+
+	/* Allocate our net_device structure */
+	ndev = alloc_etherdev(sizeof(struct rionet_private));
+	if (ndev == NULL) {
+		printk(KERN_INFO "%s: could not allocate ethernet device.\n",
+		       DRV_NAME);
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	/*
+	 * XXX hack, store point a static at ndev so we can get it...
+	 * Perhaps need an array of these that the handler can
+	 * index via the mbox number.
+	 */
+	sndev = ndev;
+
+	/* Set up private area */
+	rnet = (struct rionet_private *)ndev->priv;
+	rnet->mport = mport;
+
+	/* Set the default MAC address */
+	device_id = rio_local_get_device_id(mport);
+	ndev->dev_addr[0] = 0x00;
+	ndev->dev_addr[1] = 0x01;
+	ndev->dev_addr[2] = 0x00;
+	ndev->dev_addr[3] = 0x01;
+	ndev->dev_addr[4] = device_id >> 8;
+	ndev->dev_addr[5] = device_id & 0xff;
+
+	/* Fill in the driver function table */
+	ndev->open = &rionet_open;
+	ndev->hard_start_xmit = &rionet_start_xmit;
+	ndev->stop = &rionet_close;
+	ndev->get_stats = &rionet_stats;
+	ndev->change_mtu = &rionet_change_mtu;
+	ndev->set_mac_address = &rionet_set_mac_address;
+	ndev->set_multicast_list = &rionet_set_multicast_list;
+	ndev->do_ioctl = &rionet_ioctl;
+	SET_ETHTOOL_OPS(ndev, &rionet_ethtool_ops);
+
+	ndev->mtu = RIO_MAX_MSG_SIZE - 14;
+
+	SET_MODULE_OWNER(ndev);
+
+	rc = register_netdev(ndev);
+	if (rc != 0)
+		goto out;
+
+	printk("%s: %s %s Version %s, MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
+	       ndev->name,
+	       DRV_NAME,
+	       DRV_DESC,
+	       DRV_VERSION,
+	       ndev->dev_addr[0], ndev->dev_addr[1], ndev->dev_addr[2],
+	       ndev->dev_addr[3], ndev->dev_addr[4], ndev->dev_addr[5]);
+
+      out:
+	return rc;
+}
+
+/*
+ * XXX Make multi-net safe
+ */
+static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id)
+{
+	int rc = -ENODEV;
+	u32 lpef, lsrc_ops, ldst_ops;
+	struct rionet_peer *peer;
+
+	/* If local device is not rionet capable, give up quickly */
+	if (!rionet_capable)
+		goto out;
+
+	/*
+	 * First time through, make sure local device is rionet
+	 * capable, setup netdev,  and set flags so this is skipped
+	 * on later probes
+	 */
+	if (!rionet_check) {
+		rio_local_read_config_32(rdev->net->hport, RIO_PEF_CAR, &lpef);
+		rio_local_read_config_32(rdev->net->hport, RIO_SRC_OPS_CAR,
+					 &lsrc_ops);
+		rio_local_read_config_32(rdev->net->hport, RIO_DST_OPS_CAR,
+					 &ldst_ops);
+		if (!is_rionet_capable(lpef, lsrc_ops, ldst_ops)) {
+			printk(KERN_ERR
+			       "%s: local device is not network capable\n",
+			       DRV_NAME);
+			rionet_check = 1;
+			rionet_capable = 0;
+			goto out;
+		}
+
+		rc = rionet_setup_netdev(rdev->net->hport);
+		rionet_check = 1;
+	}
+
+	/*
+	 * If the remote device has mailbox/doorbell capabilities,
+	 * add it to the peer list.
+	 */
+	if (dev_rionet_capable(rdev)) {
+		if (!(peer = kmalloc(sizeof(struct rionet_peer), GFP_KERNEL))) {
+			rc = -ENOMEM;
+			goto out;
+		}
+		peer->rdev = rdev;
+		list_add_tail(&peer->node, &rionet_peers);
+	}
+
+      out:
+	return rc;
+}
+
+static struct rio_device_id rionet_id_table[] = {
+	{RIO_DEVICE(RIO_ANY_ID, RIO_ANY_ID)}
+};
+
+static struct rio_driver rionet_driver = {
+	.name = "rionet",
+	.id_table = rionet_id_table,
+	.probe = rionet_probe,
+	.remove = rionet_remove,
+};
+
+static int __init rionet_init(void)
+{
+	return rio_register_driver(&rionet_driver);
+}
+
+static void __exit rionet_exit(void)
+{
+	rio_unregister_driver(&rionet_driver);
+}
+
+module_init(rionet_init);
+module_exit(rionet_exit);

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox