[PATCH 1/2] PAL: Support of the fixed PHY

Vitaly Bordug vbordug at ru.mvista.com
Fri May 5 10:51:34 EST 2006


On Thu, 4 May 2006 19:21:12 -0500
Andy Fleming <afleming at freescale.com> wrote:

> What happened to this patch?  It doesn't seem to have been applied to  
> any trees.  Well, I'm gonna give it a little review now, since I have  
> some time.
> 
Under final review/updates, gonna to push uptodated shortly...
> On Apr 3, 2006, at 10:26, Vitaly Bordug wrote:
> 
> >
> > This makes it possible for HW PHY-less boards to utilize PAL goodies.
> > Generic routines to connect to fixed PHY are provided, as well as  
> > ability
> > to specify software callback that fills up link, speed, etc.  
> > information
> > into PHY descriptor (the latter feature not tested so far).
> >
> > Signed-off-by: Vitaly Bordug <vbordug at ru.mvista.com>
> > ---
> 
> [snip]
> 
> > +/ 
> > *--------------------------------------------------------------------- 
> > --------
> > + *  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.
> > + * number is used to create multiple fixed PHYs, so that several  
> > devices can
> > + * utilize them simultaneously.
> > +  
> > *--------------------------------------------------------------------- 
> > --------*/
> > +static int fixed_mdio_register_device(int number, int speed, int  
> > duplex)
> > +{
> > +	struct mii_bus *new_bus;
> > +	struct fixed_info *fixed;
> > +	struct phy_device *phydev;
> > +	int err = 0;
> > +
> > +	struct device* dev = kzalloc(sizeof(struct device), GFP_KERNEL);
> > +
> > +	if (NULL == dev)
> > +		return -EINVAL;
> > +
> > +	new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
> > +	
> > +	if (NULL == new_bus)
> > +		return -ENOMEM;
> 
> You don't free dev, here
> 
> > +	
> > +	fixed = kzalloc(sizeof(struct fixed_info), GFP_KERNEL);
> > +	
> > +	if (NULL == fixed) {
> > +		kfree(new_bus);
> > +		return -ENOMEM;
> > +	}
> 
> And dev
> 
> 
> > +	
> > +	fixed->regs = kzalloc(MII_REGS_NUM*sizeof(int), GFP_KERNEL);
> 
> You don't check for failure for regs's allocation.
> 
As to upper notes, OK.

> [snip]
> 
> > +	/* create phy_device and register it on the mdio bus */
> > +	phydev = phy_device_create(new_bus, 0, 0);
> > +
> > +	/*
> > +	 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 bus_register_fail;
> > +	}
> 
> You're going to need to change this, because phydev isn't guaranteed  
> to be NULL in the event of a failure to allocate.  it will be ERR_PTR 
> (-ENOMEM).  I know you changed this in phy_device_create(), but I  
> have more on that later.  You should do:
> 
> if (IS_ERR(phydev)) {
> 	err = PTR_ERR(-ENOMEM);
> 	goto bus_register_fail;
> }
> 

Assuming IS_ERR will shoot on NULL too, the code is not quite right(see below) :)
But I agree this check is odd - will fix.


> [snip]
> 
> > +
> > +	return 0;
> > +
> > +bus_register_fail:
> > +	kfree(new_bus);
> 
> You need to free regs and dev, too
> 
> 
ok
> 
> > diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
> > index 459443b..c87f89e 100644
> > --- a/drivers/net/phy/mdio_bus.c
> > +++ b/drivers/net/phy/mdio_bus.c
> > @@ -66,7 +66,7 @@ int mdiobus_register(struct mii_bus *bus
> >  		phydev = get_phy_device(bus, i);
> >
> >  		if (IS_ERR(phydev))
> > -			return PTR_ERR(phydev);
> > +			continue;
> 
> 
> No.  Why'd you change that?  Now mdiobus_register doesn't return an  
> error if memory runs out.  Here's how the system works:   
> get_phy_device() can return one of three things:
> 
> 1) A pointer to a newly allocated phy_device
> 2) a NULL pointer, indicating that there is no PHY at that address  
> (indicated by the bus returning all Fs)
> 3) an error (due to bus read failure, or to memory allocation  
> failure, as indicated by PTR_ERR(phydev)
> 
> This change has several issues:
> 1) due to the change below, IS_ERR(phydev) is never true
> 2) If you continue, mdiobus_register() will not inform its caller  
> that it failed.
> 

I am not really stick to this change, but it simply does not work otherwise. 
I want the whole bus to be scanned, and the code scans until first fail, and returns error when there's no phy. Hereby, having phy's on 0 and 3 I end up with only 0 registered on bus. So maybe check for NULL and continue, check for err and return... Will inquire and fix - no big deal.

> > diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/ 
> > phy_device.c
> > index 7da0e3d..0dffecf 100644
> > --- a/drivers/net/phy/phy_device.c
> > +++ b/drivers/net/phy/phy_device.c
> > @@ -46,6 +46,35 @@ static struct phy_driver genphy_driver;
> >  extern int mdio_bus_init(void);
> >  extern void mdio_bus_exit(void);
> >
> > +struct phy_device* phy_device_create(struct mii_bus *bus, int  
> > addr, int phy_id)
> > +{
> > +	struct phy_device *dev;
> > +	/* We allocate the device, and initialize the
> > +	 * default values */
> > +	dev = kcalloc(1, sizeof(*dev), GFP_KERNEL);
> > +
> > +	if (NULL == dev)
> > +		return NULL;
> 
> Here's the other change which breaks get_phy_device().  Now it  
> doesn't return an error when it fails to allocate memory, it returns  
> NULL.  Which mdiobus_register doesn't interpret as an error (because  
> it isn't.  Not every PHY address has a device on it).
> 

OK, this part definitely needs a bit attention and a rework. So, phy_device_create should return PTR_ERR if it fail to allocate memory, and we need to keep get_phy_device() return as it was, right?

> > +
> > +	dev->speed = 0;
> > +	dev->duplex = -1;
> > +	dev->pause = dev->asym_pause = 0;
> > +	dev->link = 1;
> > +
> > +	dev->autoneg = AUTONEG_ENABLE;
> > +
> > +	dev->addr = addr;
> > +	dev->phy_id = phy_id;
> > +	dev->bus = bus;
> > +
> > +	dev->state = PHY_DOWN;
> > +
> > +	spin_lock_init(&dev->lock);
> > +
> > +	return dev;
> > +}
> > +EXPORT_SYMBOL(phy_device_create);
> 
> Also, as a side note, I'm not completely convinced you need to go  
> through this degree of effort to circumvent the PHY Layer's normal  
> operation.  I think it should be possible to make it simpler.  With  
> the right implementation, it should even be possible to do really  
> "clever" things, like allow users to change the PHY settings with  
> ethtool.  However, this code exists and works (I'm assuming), and  
> that's good enough for now.  I'll be glad to have this capability  
> next time someone asks me to boot linux on a simulator.
> 

I made it as it is not that complex as it seemed at the first sight,
and may be a proving ground to some incoming PAL feature. Also, if there is fixed PHY, 
it often does not mean it is really "fixed" - it may be just far too weird to suite into any known form,
but still able to control the link etc. 

So, the main aim is to do: if PAL doesn't know PHY, use fixed phy. If you do not want it fixed and wanna to control the link - ok, just implement the link update callback, pass it to emulated PHY, and here we go...


-- 
Sincerely, 
Vitaly



More information about the Linuxppc-embedded mailing list