Hi Francois,

Thanks for your feedback, I have a few questions.

> > +            return serviced;
> > +}
> > +
> > +/* Autodetects and initialises external phy for SMSC9115 and SMSC9117 
flavors.
> > + * If something goes wrong, returns -ENODEV to revert back to 
internal phy. */
> > +static int smsc911x_phy_initialise_external(struct smsc911x_data 
*pdata)
> > +{
> > +            unsigned int address;
> > +            unsigned int hwcfg;
> > +            unsigned int phyid1;
> > +            unsigned int phyid2;
> > +
> > +            hwcfg = smsc911x_reg_read(pdata, HW_CFG);
> > +
> > +            /* External phy is requested, supported, and detected */
> > +            if (hwcfg & HW_CFG_EXT_PHY_DET_) {
> > +
> > +                            /* Attempt to switch to external phy for 
auto-detecting
> > +                             * its address. Assuming tx and rx are 
stopped because
> > +                             * smsc911x_phy_initialise is called 
before
> > +                             * smsc911x_rx_initialise and 
tx_initialise.
> > +                             */
> > +
> > +                            /* Disable phy clocks to the MAC */
> > +                            hwcfg &= (~HW_CFG_PHY_CLK_SEL_);
> > +                            hwcfg |= HW_CFG_PHY_CLK_SEL_CLK_DIS_;
> > +                            smsc911x_reg_write(hwcfg, pdata, HW_CFG);
> > +                            udelay(10);             /* Enough time 
for clocks to stop */
> 
> I assume that writes are never posted, right ?
> 

I don't understand the question, what do you mean?


> > +static void smsc911x_rx_multicast_update(struct smsc911x_data *pdata)
> > +{
> > +            unsigned long flags;
> > +            unsigned int timeout;
> > +            unsigned int mac_cr;
> > +
> > +            /* This function is only called for older LAN911x devices 

> > +             * (revA or revB), where MAC_CR, HASHH and HASHL should 
not
> > +             * be modified during Rx - newer devices immediately 
update the
> > +             * registers */
> > +
> > +            local_irq_save(flags);
> > +
> > +            /* Stop Rx */
> > +            mac_cr = smsc911x_mac_read(pdata, MAC_CR);
> > +            mac_cr &= ~(MAC_CR_RXEN_);
> > +            smsc911x_mac_write(pdata, MAC_CR, mac_cr);
> > +
> > +            /* Poll until Rx has stopped.  If a frame is being 
recieved, this will
> > +             * block until the end of this frame.  (this may take a 
long time at
> > +             * 10Mbps) */
> > +            timeout = 2000;
> > +            while ((timeout--)
> > +                   && (!(smsc911x_reg_read(pdata, INT_STS) & 
INT_STS_RXSTOP_INT_))) {
> > +                            udelay(1);
> 
> 
> In a completely ideal world the driver would probably race outside of an
> irq disabled section until it grabs the napi poll handler, thus 
preserving
> the nice low latency property of the kernel.
> 
> Nevermind :o}

Agreed, I would like to find a nicer way to do this.  It's a nasty 
workaround to a nasty hardware issue :o}

There are two problems.  First, on older hardware revisions the multicast 
hash filters (as well as the promisc flag) cannot be modified while rx is 
active (bad things might happen).  There is an interrupt which can be used 
to indicate RX has stopped, but on early hardware this is not 100% 
reliable.

The current solution is the simplest option, and works.  A better way 
could be to use the RX_STOP interrupt, but also schedule a task to run 
later "just in case"?

Best Regards,
--
Steve Glendinning
SMSC GmbH
m: +44 777 933 9124
e: [EMAIL PROTECTED]

-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to