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