{
struct fec_enet_private *fep = netdev_priv(dev);
struct bufdesc *bdp;
+ void *bufaddr;
unsigned short status;
unsigned long flags;
if (!fep->link) {
/* Link is down or autonegotiation is in progress. */
- return 1;
+ return NETDEV_TX_BUSY;
}
spin_lock_irqsave(&fep->hw_lock, flags);
*/
printk("%s: tx queue full!.\n", dev->name);
spin_unlock_irqrestore(&fep->hw_lock, flags);
- return 1;
+ return NETDEV_TX_BUSY;
}
/* Clear all of the status flags */
status &= ~BD_ENET_TX_STATS;
/* Set buffer length and buffer pointer */
- bdp->cbd_bufaddr = __pa(skb->data);
+ bufaddr = skb->data;
bdp->cbd_datlen = skb->len;
/*
* 4-byte boundaries. Use bounce buffers to copy data
* and get it aligned. Ugh.
*/
- if (bdp->cbd_bufaddr & FEC_ALIGNMENT) {
+ if (((unsigned long) bufaddr) & FEC_ALIGNMENT) {
unsigned int index;
index = bdp - fep->tx_bd_base;
memcpy(fep->tx_bounce[index], (void *)skb->data, skb->len);
- bdp->cbd_bufaddr = __pa(fep->tx_bounce[index]);
+ bufaddr = fep->tx_bounce[index];
}
/* Save skb pointer */
/* Push the data cache so the CPM does not get stale memory
* data.
*/
- bdp->cbd_bufaddr = dma_map_single(&dev->dev, skb->data,
+ bdp->cbd_bufaddr = dma_map_single(&dev->dev, bufaddr,
FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE);
/* Send it on its way. Tell FEC it's ready, interrupt when done,
spin_unlock_irqrestore(&fep->hw_lock, flags);
- return 0;
+ return NETDEV_TX_OK;
}
static void
struct sk_buff *skb;
fep = netdev_priv(dev);
- spin_lock_irq(&fep->hw_lock);
+ spin_lock(&fep->hw_lock);
bdp = fep->dirty_tx;
while (((status = bdp->cbd_sc) & BD_ENET_TX_READY) == 0) {
}
}
fep->dirty_tx = bdp;
- spin_unlock_irq(&fep->hw_lock);
+ spin_unlock(&fep->hw_lock);
}
flush_cache_all();
#endif
- spin_lock_irq(&fep->hw_lock);
+ spin_lock(&fep->hw_lock);
/* First, grab all of the stats for the incoming packet.
* These get messed up if we get called due to a busy condition.
}
fep->cur_rx = bdp;
- spin_unlock_irq(&fep->hw_lock);
+ spin_unlock(&fep->hw_lock);
}
/* called from interrupt context */
mii_list_t *mip;
fep = netdev_priv(dev);
- spin_lock_irq(&fep->mii_lock);
+ spin_lock(&fep->mii_lock);
if ((mip = mii_head) == NULL) {
printk("MII and no head!\n");
writel(mip->mii_regval, fep->hwp + FEC_MII_DATA);
unlock:
- spin_unlock_irq(&fep->mii_lock);
+ spin_unlock(&fep->mii_lock);
}
static int
-mii_queue(struct net_device *dev, int regval, void (*func)(uint, struct net_device *))
+mii_queue_unlocked(struct net_device *dev, int regval,
+ void (*func)(uint, struct net_device *))
{
struct fec_enet_private *fep;
- unsigned long flags;
mii_list_t *mip;
int retval;
/* Add PHY address to register command */
fep = netdev_priv(dev);
- spin_lock_irqsave(&fep->mii_lock, flags);
regval |= fep->phy_addr << 23;
retval = 0;
retval = 1;
}
+ return retval;
+}
+
+static int
+mii_queue(struct net_device *dev, int regval,
+ void (*func)(uint, struct net_device *))
+{
+ struct fec_enet_private *fep;
+ unsigned long flags;
+ int retval;
+ fep = netdev_priv(dev);
+ spin_lock_irqsave(&fep->mii_lock, flags);
+ retval = mii_queue_unlocked(dev, regval, func);
spin_unlock_irqrestore(&fep->mii_lock, flags);
return retval;
}
},
};
+static phy_info_t phy_info_lan8700 = {
+ 0x0007C0C,
+ "LAN8700",
+ (const phy_cmd_t []) { /* config */
+ { mk_mii_read(MII_REG_CR), mii_parse_cr },
+ { mk_mii_read(MII_REG_ANAR), mii_parse_anar },
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* startup */
+ { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
+ { mk_mii_read(MII_REG_SR), mii_parse_sr },
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* act_int */
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* shutdown */
+ { mk_mii_end, }
+ },
+};
/* ------------------------------------------------------------------------- */
static phy_info_t const * const phy_info[] = {
&phy_info_am79c874,
&phy_info_ks8721bl,
&phy_info_dp83848,
+ &phy_info_lan8700,
NULL
};
printk("FEC: Could not allocate fec(MII) IRQ(66)!\n");
}
-static void __inline__ fec_disable_phy_intr(void)
-{
- volatile unsigned long *icrp;
- icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1);
- *icrp = 0x08000000;
-}
-
-static void __inline__ fec_phy_ack_intr(void)
+static void __inline__ fec_disable_phy_intr(struct net_device *dev)
{
- volatile unsigned long *icrp;
- /* Acknowledge the interrupt */
- icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1);
- *icrp = 0x0d000000;
+ free_irq(66, dev);
}
#endif
/* Got first part of ID, now get remainder */
fep->phy_id = phytype << 16;
- mii_queue(dev, mk_mii_read(MII_REG_PHYIR2),
+ mii_queue_unlocked(dev, mk_mii_read(MII_REG_PHYIR2),
mii_discover_phy3);
} else {
fep->phy_addr++;
- mii_queue(dev, mk_mii_read(MII_REG_PHYIR1),
+ mii_queue_unlocked(dev, mk_mii_read(MII_REG_PHYIR1),
mii_discover_phy);
}
} else {
writel(0, fep->hwp + FEC_MII_SPEED);
fep->phy_speed = 0;
#ifdef HAVE_mii_link_interrupt
- fec_disable_phy_intr();
+ fec_disable_phy_intr(dev);
#endif
}
}
struct net_device *dev = dev_id;
struct fec_enet_private *fep = netdev_priv(dev);
- fec_phy_ack_intr();
-
mii_do_cmd(dev, fep->phy->ack_int);
mii_do_cmd(dev, phy_cmd_relink); /* restart and display status */
dmi = dev->mc_list;
- for (j = 0; j < dev->mc_count; j++, dmi = dmi->next) {
+ for (j = 0; j < netdev_mc_count(dev); j++, dmi = dmi->next) {
/* Only support group multicast for now */
if (!(dmi->dmi_addr[0] & 1))
continue;
.ndo_stop = fec_enet_close,
.ndo_start_xmit = fec_enet_start_xmit,
.ndo_set_multicast_list = set_multicast_list,
+ .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_tx_timeout = fec_timeout,
.ndo_set_mac_address = fec_set_mac_address,
*
* index is only used in legacy code
*/
-int __init fec_enet_init(struct net_device *dev, int index)
+static int fec_enet_init(struct net_device *dev, int index)
{
struct fec_enet_private *fep = netdev_priv(dev);
struct bufdesc *cbd_base;
+ struct bufdesc *bdp;
int i;
/* Allocate memory for buffer descriptors. */
/* Set MII speed to 2.5 MHz */
fep->phy_speed = ((((clk_get_rate(fep->clk) / 2 + 4999999)
/ 2500000) / 2) & 0x3F) << 1;
+
+ /* Initialize the receive buffer descriptors. */
+ bdp = fep->rx_bd_base;
+ for (i = 0; i < RX_RING_SIZE; i++) {
+
+ /* Initialize the BD for every fragment in the page. */
+ bdp->cbd_sc = 0;
+ bdp++;
+ }
+
+ /* Set the last buffer to wrap */
+ bdp--;
+ bdp->cbd_sc |= BD_SC_WRAP;
+
+ /* ...and the same for transmit */
+ bdp = fep->tx_bd_base;
+ for (i = 0; i < TX_RING_SIZE; i++) {
+
+ /* Initialize the BD for every fragment in the page. */
+ bdp->cbd_sc = 0;
+ bdp->cbd_bufaddr = 0;
+ bdp++;
+ }
+
+ /* Set the last buffer to wrap */
+ bdp--;
+ bdp->cbd_sc |= BD_SC_WRAP;
+
fec_restart(dev, 0);
/* Queue up command to detect the PHY and initialize the
fec_restart(struct net_device *dev, int duplex)
{
struct fec_enet_private *fep = netdev_priv(dev);
- struct bufdesc *bdp;
int i;
/* Whack a reset. We should wait for this. */
}
}
- /* Initialize the receive buffer descriptors. */
- bdp = fep->rx_bd_base;
- for (i = 0; i < RX_RING_SIZE; i++) {
-
- /* Initialize the BD for every fragment in the page. */
- bdp->cbd_sc = BD_ENET_RX_EMPTY;
- bdp++;
- }
-
- /* Set the last buffer to wrap */
- bdp--;
- bdp->cbd_sc |= BD_SC_WRAP;
-
- /* ...and the same for transmit */
- bdp = fep->tx_bd_base;
- for (i = 0; i < TX_RING_SIZE; i++) {
-
- /* Initialize the BD for every fragment in the page. */
- bdp->cbd_sc = 0;
- bdp->cbd_bufaddr = 0;
- bdp++;
- }
-
- /* Set the last buffer to wrap */
- bdp--;
- bdp->cbd_sc |= BD_SC_WRAP;
-
/* Enable MII mode */
if (duplex) {
/* MII enable / FD enable */