patch-2.4.22 linux-2.4.22/arch/ppc/8xx_io/fec.c
Next file: linux-2.4.22/arch/ppc/8xx_io/uart.c
Previous file: linux-2.4.22/arch/ppc/8xx_io/enet.c
Back to the patch index
Back to the overall index
- Lines: 319
- Date:
2003-08-25 04:44:40.000000000 -0700
- Orig file:
linux-2.4.21/arch/ppc/8xx_io/fec.c
- Orig date:
2003-06-13 07:51:31.000000000 -0700
diff -urN linux-2.4.21/arch/ppc/8xx_io/fec.c linux-2.4.22/arch/ppc/8xx_io/fec.c
@@ -163,7 +163,7 @@
cbd_t *dirty_tx; /* The ring entries to be free()ed. */
scc_t *sccp;
struct net_device_stats stats;
- uint tx_full;
+ uint tx_free;
spinlock_t lock;
#ifdef CONFIG_USE_MDIO
@@ -229,6 +229,7 @@
mii_list_t *mii_free;
mii_list_t *mii_head;
mii_list_t *mii_tail;
+int mii_stopped;
typedef struct mdio_read_data {
u16 regval;
@@ -295,18 +296,13 @@
fep = dev->priv;
fecp = (volatile fec_t*)dev->base_addr;
- if (!fep->link) {
- /* Link is down or autonegotiation is in progress. */
- return 1;
- }
-
/* Fill in a Tx ring entry */
bdp = fep->cur_tx;
#ifndef final_version
- if (bdp->cbd_sc & BD_ENET_TX_READY) {
+ if (!fep->tx_free || (bdp->cbd_sc & BD_ENET_TX_READY)) {
/* Ooops. All transmit buffers are full. Bail out.
- * This should not happen, since dev->tbusy should be set.
+ * This should not happen, since the tx queue should be stopped.
*/
printk("%s: tx queue full!.\n", dev->name);
return 1;
@@ -357,10 +353,8 @@
bdp++;
}
- if (bdp->cbd_sc & BD_ENET_TX_READY) {
+ if (!--fep->tx_free)
netif_stop_queue(dev);
- fep->tx_full = 1;
- }
fep->cur_tx = (cbd_t *)bdp;
@@ -381,8 +375,8 @@
int i;
cbd_t *bdp;
- printk("Ring data dump: cur_tx %lx%s, dirty_tx %lx cur_rx: %lx\n",
- (unsigned long)fep->cur_tx, fep->tx_full ? " (full)" : "",
+ printk("Ring data dump: cur_tx %lx, tx_free %d, dirty_tx %lx, cur_rx %lx\n",
+ (unsigned long)fep->cur_tx, fep->tx_free,
(unsigned long)fep->dirty_tx,
(unsigned long)fep->cur_rx);
@@ -409,7 +403,7 @@
}
}
#endif
- if (!fep->tx_full)
+ if (fep->tx_free)
netif_wake_queue(dev);
}
@@ -469,7 +463,7 @@
bdp = fep->dirty_tx;
while ((bdp->cbd_sc&BD_ENET_TX_READY) == 0) {
- if (bdp == fep->cur_tx && fep->tx_full == 0) break;
+ if (fep->tx_free == TX_RING_SIZE) break;
skb = fep->tx_skbuff[fep->skb_dirty];
/* Check for errors. */
@@ -519,8 +513,7 @@
/* Since we have freed up a buffer, the ring is no longer
* full.
*/
- if (fep->tx_full) {
- fep->tx_full = 0;
+ if (!fep->tx_free++) {
if (netif_queue_stopped(dev))
netif_wake_queue(dev);
}
@@ -668,6 +661,12 @@
ep = &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec);
mii_reg = ep->fec_mii_data;
+ /* Ignore this answer if the request queue has been stopped.
+ * The request will be re-issued when the queue is restarted.
+ */
+ if (mii_stopped)
+ return;
+
if ((mip = mii_head) == NULL) {
printk("MII and no head!\n");
return;
@@ -714,7 +713,8 @@
mii_tail = mip;
} else {
mii_head = mii_tail = mip;
- (&(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec))->fec_mii_data = regval;
+ if (!mii_stopped)
+ (&(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec))->fec_mii_data = regval;
}
} else {
retval = 1;
@@ -725,6 +725,30 @@
return(retval);
}
+/* Functions to stop/start the transmission of requests through the MDIO.
+ * They are intended to be used before and after a FEC reset.
+ */
+static void stop_mii_queue(struct net_device *dev)
+{
+ unsigned long flags;
+ save_flags(flags);
+ cli();
+ mii_stopped = 1;
+ restore_flags(flags);
+}
+
+static void start_mii_queue(struct net_device *dev)
+{
+ unsigned long flags;
+ volatile fec_t *ep = &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec);
+ save_flags(flags);
+ cli();
+ mii_stopped = 0;
+ if(mii_head)
+ ep->fec_mii_data = mii_head->mii_regval;
+ restore_flags(flags);
+}
+
static void mii_do_cmd(struct net_device *dev, const phy_cmd_t *c)
{
int k;
@@ -995,7 +1019,7 @@
{ mk_mii_end, }
},
(const phy_cmd_t []) { /* startup - enable interrupts */
- { mk_mii_write(MII_QS6612_IMR, 0x003a), NULL },
+ { mk_mii_write(MII_QS6612_IMR, 0x0050), NULL },
{ mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
{ mk_mii_end, }
},
@@ -1060,7 +1084,7 @@
0x020005c1,
"DP83843BVJE",
- (const phy_cmd_t []) { /* config */
+ (const phy_cmd_t []) { /* config */
{ mk_mii_write(MII_REG_ANAR, 0x01E1), NULL }, /* Auto-Negociation Register Control set to */
/* auto-negociate 10/100MBps, Half/Full duplex */
{ mk_mii_read(MII_REG_CR), mii_parse_cr },
@@ -1132,7 +1156,7 @@
0x020005c2,
"DP83846A",
- (const phy_cmd_t []) { /* config */
+ (const phy_cmd_t []) { /* config */
{ mk_mii_write(MII_REG_ANAR, 0x01E1), NULL }, /* Auto-Negociation Register Control set to */
/* auto-negociate 10/100MBps, Half/Full duplex */
{ mk_mii_read(MII_REG_CR), mii_parse_cr },
@@ -1367,31 +1391,20 @@
#ifdef CONFIG_USE_MDIO
struct net_device *dev = dev_id;
struct fec_enet_private *fep = dev->priv;
- volatile immap_t *immap = (immap_t *)IMAP_ADDR;
- volatile fec_t *fecp = &(immap->im_cpm.cp_fec);
- unsigned int ecntrl = fecp->fec_ecntrl;
-
- /* We need the FEC enabled to access the MII
- */
- if ((ecntrl & FEC_ECNTRL_ETHER_EN) == 0) {
- fecp->fec_ecntrl |= FEC_ECNTRL_ETHER_EN;
- }
-#endif /* CONFIG_USE_MDIO */
-
-#if 0
- disable_irq(fep->mii_irq); /* disable now, enable later */
-#endif
-
-#ifdef CONFIG_USE_MDIO
- mii_do_cmd(dev, fep->phy->ack_int);
- mii_do_cmd(dev, phy_cmd_relink); /* restart and display status */
-
- if ((ecntrl & FEC_ECNTRL_ETHER_EN) == 0) {
- fecp->fec_ecntrl = ecntrl; /* restore old settings */
+ /*
+ * Acknowledge the interrupt if possible. If we have not
+ * found the PHY yet we can't process or acknowledge the
+ * interrupt now. Instead we ignore this interrupt for now,
+ * which we can do since it is edge triggered. It will be
+ * acknowledged later by fec_enet_open().
+ */
+ if (fep->phy) {
+ mii_do_cmd(dev, fep->phy->ack_int);
+ mii_do_cmd(dev, phy_cmd_relink); /* restart and display status */
}
#else
-printk("%s[%d] %s: unexpected Link interrupt\n", __FILE__,__LINE__,__FUNCTION__);
+ printk ("FEC: unexpected Link interrupt\n");
#endif /* CONFIG_USE_MDIO */
}
@@ -1422,7 +1435,7 @@
{
/* Initializing timers
*/
- init_timer( &fep->phy_timer_list );
+ init_timer( &fep->phy_timer_list );
/* Starting timer for periodic link status check
* After 100 milli-seconds, mdio_timer_callback function is called.
@@ -1492,7 +1505,7 @@
{
fep->phy_timer_list.expires = jiffies + (1 * HZ); /* Sleep for 1 sec. */
}
- add_timer( &fep->phy_timer_list );
+ add_timer( &fep->phy_timer_list );
}
#endif /* CONFIG_FEC_DP83846A */
@@ -1540,7 +1553,7 @@
else
{
switch(cmd)
- {
+ {
case SIOCETHTOOL:
return netdev_ethtool_ioctl(dev, (void*)rq->ifr_data);
break;
@@ -1571,7 +1584,7 @@
default:
retval = -EOPNOTSUPP;
break;
- }
+ }
}
return retval;
}
@@ -1652,7 +1665,7 @@
dmi = dev->mc_list;
- for (i=0; i<dev->mc_count; i++) {
+ for (i=0; i<dev->mc_count; i++, dmi = dmi->next) {
/* Only support group multicast for now.
*/
@@ -1927,6 +1940,11 @@
fep = dev->priv;
+#ifdef CONFIG_USE_MDIO
+ /* Stop the MDIO communication prior to reset. */
+ stop_mii_queue(dev);
+#endif
+
/* Whack a reset. We should wait for this.
*/
fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET;
@@ -1960,6 +1978,7 @@
fecp->fec_x_des_start = __pa((uint)(fep->tx_bd_base));
fep->dirty_tx = fep->cur_tx = fep->tx_bd_base;
+ fep->tx_free = TX_RING_SIZE;
fep->cur_rx = fep->rx_bd_base;
/* Reset SKB transmit buffers.
@@ -2043,12 +2062,10 @@
fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN;
fecp->fec_r_des_active = 0x01000000;
- /* The tx ring is no longer full. */
- if(fep->tx_full)
- {
- fep->tx_full = 0;
- netif_wake_queue(dev);
- }
+#ifdef CONFIG_USE_MDIO
+ /* Re-start any pending MDIO communication. */
+ start_mii_queue(dev);
+#endif
}
static void
@@ -2080,22 +2097,7 @@
printk ("FEC timeout on graceful transmit stop\n");
}
- /* Clear outstanding MII command interrupts.
- */
- fecp->fec_ievent = FEC_ENET_MII;
-
- /* Enable MII command finished interrupt
- */
- fecp->fec_ivec = (FEC_INTERRUPT/2) << 29;
+ /* Disable FEC. Let only MII interrupts. */
fecp->fec_imask = FEC_ENET_MII;
-
-#ifdef CONFIG_USE_MDIO
- /* Set MII speed.
- */
- fecp->fec_mii_speed = fep->phy_speed;
-#endif /* CONFIG_USE_MDIO */
-
- /* Disable FEC
- */
fecp->fec_ecntrl &= ~(FEC_ECNTRL_ETHER_EN);
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)