Thread (19 messages) 19 messages, 5 authors, 2006-08-04

Re: SMSC LAN911x and LAN921x vendor driver

From: <hidden>
Date: 2006-07-31 20:20:52

Possibly related (same subject, not in this thread)

Hi Francois,

Thanks for your feedback, I have a few questions.
quoted
+            return serviced;
+}
+
+/* Autodetects and initialises external phy for SMSC9115 and SMSC9117 
flavors.
quoted
+ * If something goes wrong, returns -ENODEV to revert back to 
internal phy. */
quoted
+static int smsc911x_phy_initialise_external(struct smsc911x_data 
*pdata)
quoted
+{
+            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
quoted
+                             * its address. Assuming tx and rx are 
stopped because
quoted
+                             * smsc911x_phy_initialise is called 
before
quoted
+                             * smsc911x_rx_initialise and 
tx_initialise.
quoted
+                             */
+
+                            /* 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?

quoted
+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 
quoted
+             * (revA or revB), where MAC_CR, HASHH and HASHL should 
not
quoted
+             * be modified during Rx - newer devices immediately 
update the
quoted
+             * 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
quoted
+             * block until the end of this frame.  (this may take a 
long time at
quoted
+             * 10Mbps) */
+            timeout = 2000;
+            while ((timeout--)
+                   && (!(smsc911x_reg_read(pdata, INT_STS) & 
INT_STS_RXSTOP_INT_))) {
quoted
+                            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: steve.glendinning@smsc.com
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help