drivers/net: ks8851_mll ethernet network driver -resubmit

Summary of Changes:

	-Fix to receive multicast packets by setting the corresponding hardware
	 bit during initialization.
	-Fix to re-enable the interface [by interface up command(ifup)] while the
	 interface is down.
	-Fix to be able to down the interface by passing the last parameter
	 correctly to request_irq().
	-Remove to read 4 extra bytes from the receiving queue after reading a
	 packet, even though it does not cause a predictable issue now.
	-Remove occurrences of transmission done interrupt in order to tx
	 throughput enhancement.
	-Enable IP checksum for packet receiving by setting the corresponding
	 hardware bit during initialization.
	-Relocate ks_enable_int()/ks_disable_int() in order not to declare those
	 functions at the beginning of the file.
	-Rename ks_enable()/_disable() to ks_enable_qmu()/ks_disable_qmu() in
	 order to give more meaningful names and relocate them not declaire
	 those functions at the beginning of the file.

Signed-off-by: David J. Choi <david.choi@micrel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David J. Choi 2009-11-19 15:34:30 +00:00 committed by David S. Miller
parent 0ebe74e7ba
commit 4a91ca4e18

View file

@ -568,6 +568,16 @@ static inline void ks_outblk(struct ks_net *ks, u16 *wptr, u32 len)
iowrite16(*wptr++, ks->hw_addr); iowrite16(*wptr++, ks->hw_addr);
} }
static void ks_disable_int(struct ks_net *ks)
{
ks_wrreg16(ks, KS_IER, 0x0000);
} /* ks_disable_int */
static void ks_enable_int(struct ks_net *ks)
{
ks_wrreg16(ks, KS_IER, ks->rc_ier);
} /* ks_enable_int */
/** /**
* ks_tx_fifo_space - return the available hardware buffer size. * ks_tx_fifo_space - return the available hardware buffer size.
* @ks: The chip information * @ks: The chip information
@ -681,6 +691,47 @@ static void ks_soft_reset(struct ks_net *ks, unsigned op)
} }
void ks_enable_qmu(struct ks_net *ks)
{
u16 w;
w = ks_rdreg16(ks, KS_TXCR);
/* Enables QMU Transmit (TXCR). */
ks_wrreg16(ks, KS_TXCR, w | TXCR_TXE);
/*
* RX Frame Count Threshold Enable and Auto-Dequeue RXQ Frame
* Enable
*/
w = ks_rdreg16(ks, KS_RXQCR);
ks_wrreg16(ks, KS_RXQCR, w | RXQCR_RXFCTE);
/* Enables QMU Receive (RXCR1). */
w = ks_rdreg16(ks, KS_RXCR1);
ks_wrreg16(ks, KS_RXCR1, w | RXCR1_RXE);
ks->enabled = true;
} /* ks_enable_qmu */
static void ks_disable_qmu(struct ks_net *ks)
{
u16 w;
w = ks_rdreg16(ks, KS_TXCR);
/* Disables QMU Transmit (TXCR). */
w &= ~TXCR_TXE;
ks_wrreg16(ks, KS_TXCR, w);
/* Disables QMU Receive (RXCR1). */
w = ks_rdreg16(ks, KS_RXCR1);
w &= ~RXCR1_RXE ;
ks_wrreg16(ks, KS_RXCR1, w);
ks->enabled = false;
} /* ks_disable_qmu */
/** /**
* ks_read_qmu - read 1 pkt data from the QMU. * ks_read_qmu - read 1 pkt data from the QMU.
* @ks: The chip information * @ks: The chip information
@ -752,7 +803,7 @@ static void ks_rcv(struct ks_net *ks, struct net_device *netdev)
(frame_hdr->len < RX_BUF_SIZE) && frame_hdr->len)) { (frame_hdr->len < RX_BUF_SIZE) && frame_hdr->len)) {
skb_reserve(skb, 2); skb_reserve(skb, 2);
/* read data block including CRC 4 bytes */ /* read data block including CRC 4 bytes */
ks_read_qmu(ks, (u16 *)skb->data, frame_hdr->len + 4); ks_read_qmu(ks, (u16 *)skb->data, frame_hdr->len);
skb_put(skb, frame_hdr->len); skb_put(skb, frame_hdr->len);
skb->dev = netdev; skb->dev = netdev;
skb->protocol = eth_type_trans(skb, netdev); skb->protocol = eth_type_trans(skb, netdev);
@ -861,7 +912,7 @@ static int ks_net_open(struct net_device *netdev)
ks_dbg(ks, "%s - entry\n", __func__); ks_dbg(ks, "%s - entry\n", __func__);
/* reset the HW */ /* reset the HW */
err = request_irq(ks->irq, ks_irq, KS_INT_FLAGS, DRV_NAME, ks); err = request_irq(ks->irq, ks_irq, KS_INT_FLAGS, DRV_NAME, netdev);
if (err) { if (err) {
printk(KERN_ERR "Failed to request IRQ: %d: %d\n", printk(KERN_ERR "Failed to request IRQ: %d: %d\n",
@ -869,6 +920,15 @@ static int ks_net_open(struct net_device *netdev)
return err; return err;
} }
/* wake up powermode to normal mode */
ks_set_powermode(ks, PMECR_PM_NORMAL);
mdelay(1); /* wait for normal mode to take effect */
ks_wrreg16(ks, KS_ISR, 0xffff);
ks_enable_int(ks);
ks_enable_qmu(ks);
netif_start_queue(ks->netdev);
if (netif_msg_ifup(ks)) if (netif_msg_ifup(ks))
ks_dbg(ks, "network device %s up\n", netdev->name); ks_dbg(ks, "network device %s up\n", netdev->name);
@ -892,19 +952,14 @@ static int ks_net_stop(struct net_device *netdev)
netif_stop_queue(netdev); netif_stop_queue(netdev);
kfree(ks->frame_head_info);
mutex_lock(&ks->lock); mutex_lock(&ks->lock);
/* turn off the IRQs and ack any outstanding */ /* turn off the IRQs and ack any outstanding */
ks_wrreg16(ks, KS_IER, 0x0000); ks_wrreg16(ks, KS_IER, 0x0000);
ks_wrreg16(ks, KS_ISR, 0xffff); ks_wrreg16(ks, KS_ISR, 0xffff);
/* shutdown RX process */ /* shutdown RX/TX QMU */
ks_wrreg16(ks, KS_RXCR1, 0x0000); ks_disable_qmu(ks);
/* shutdown TX process */
ks_wrreg16(ks, KS_TXCR, 0x0000);
/* set powermode to soft power down to save power */ /* set powermode to soft power down to save power */
ks_set_powermode(ks, PMECR_PM_SOFTDOWN); ks_set_powermode(ks, PMECR_PM_SOFTDOWN);
@ -929,17 +984,8 @@ static int ks_net_stop(struct net_device *netdev)
*/ */
static void ks_write_qmu(struct ks_net *ks, u8 *pdata, u16 len) static void ks_write_qmu(struct ks_net *ks, u8 *pdata, u16 len)
{ {
unsigned fid = ks->fid;
fid = ks->fid;
ks->fid = (ks->fid + 1) & TXFR_TXFID_MASK;
/* reduce the tx interrupt occurrances. */
if (!fid)
fid |= TXFR_TXIC; /* irq on completion */
/* start header at txb[0] to align txw entries */ /* start header at txb[0] to align txw entries */
ks->txh.txw[0] = cpu_to_le16(fid); ks->txh.txw[0] = 0;
ks->txh.txw[1] = cpu_to_le16(len); ks->txh.txw[1] = cpu_to_le16(len);
/* 1. set sudo-DMA mode */ /* 1. set sudo-DMA mode */
@ -957,16 +1003,6 @@ static void ks_write_qmu(struct ks_net *ks, u8 *pdata, u16 len)
; ;
} }
static void ks_disable_int(struct ks_net *ks)
{
ks_wrreg16(ks, KS_IER, 0x0000);
} /* ks_disable_int */
static void ks_enable_int(struct ks_net *ks)
{
ks_wrreg16(ks, KS_IER, ks->rc_ier);
} /* ks_enable_int */
/** /**
* ks_start_xmit - transmit packet * ks_start_xmit - transmit packet
* @skb : The buffer to transmit * @skb : The buffer to transmit
@ -1410,25 +1446,6 @@ static int ks_read_selftest(struct ks_net *ks)
return ret; return ret;
} }
static void ks_disable(struct ks_net *ks)
{
u16 w;
w = ks_rdreg16(ks, KS_TXCR);
/* Disables QMU Transmit (TXCR). */
w &= ~TXCR_TXE;
ks_wrreg16(ks, KS_TXCR, w);
/* Disables QMU Receive (RXCR1). */
w = ks_rdreg16(ks, KS_RXCR1);
w &= ~RXCR1_RXE ;
ks_wrreg16(ks, KS_RXCR1, w);
ks->enabled = false;
} /* ks_disable */
static void ks_setup(struct ks_net *ks) static void ks_setup(struct ks_net *ks)
{ {
u16 w; u16 w;
@ -1463,7 +1480,7 @@ static void ks_setup(struct ks_net *ks)
w = TXCR_TXFCE | TXCR_TXPE | TXCR_TXCRC | TXCR_TCGIP; w = TXCR_TXFCE | TXCR_TXPE | TXCR_TXCRC | TXCR_TCGIP;
ks_wrreg16(ks, KS_TXCR, w); ks_wrreg16(ks, KS_TXCR, w);
w = RXCR1_RXFCE | RXCR1_RXBE | RXCR1_RXUE; w = RXCR1_RXFCE | RXCR1_RXBE | RXCR1_RXUE | RXCR1_RXME | RXCR1_RXIPFCC;
if (ks->promiscuous) /* bPromiscuous */ if (ks->promiscuous) /* bPromiscuous */
w |= (RXCR1_RXAE | RXCR1_RXINVF); w |= (RXCR1_RXAE | RXCR1_RXINVF);
@ -1486,28 +1503,6 @@ static void ks_setup_int(struct ks_net *ks)
ks->rc_ier = (IRQ_LCI | IRQ_TXI | IRQ_RXI); ks->rc_ier = (IRQ_LCI | IRQ_TXI | IRQ_RXI);
} /* ks_setup_int */ } /* ks_setup_int */
void ks_enable(struct ks_net *ks)
{
u16 w;
w = ks_rdreg16(ks, KS_TXCR);
/* Enables QMU Transmit (TXCR). */
ks_wrreg16(ks, KS_TXCR, w | TXCR_TXE);
/*
* RX Frame Count Threshold Enable and Auto-Dequeue RXQ Frame
* Enable
*/
w = ks_rdreg16(ks, KS_RXQCR);
ks_wrreg16(ks, KS_RXQCR, w | RXQCR_RXFCTE);
/* Enables QMU Receive (RXCR1). */
w = ks_rdreg16(ks, KS_RXCR1);
ks_wrreg16(ks, KS_RXCR1, w | RXCR1_RXE);
ks->enabled = true;
} /* ks_enable */
static int ks_hw_init(struct ks_net *ks) static int ks_hw_init(struct ks_net *ks)
{ {
#define MHEADER_SIZE (sizeof(struct type_frame_head) * MAX_RECV_FRAMES) #define MHEADER_SIZE (sizeof(struct type_frame_head) * MAX_RECV_FRAMES)
@ -1612,11 +1607,9 @@ static int __devinit ks8851_probe(struct platform_device *pdev)
ks_soft_reset(ks, GRR_GSR); ks_soft_reset(ks, GRR_GSR);
ks_hw_init(ks); ks_hw_init(ks);
ks_disable(ks); ks_disable_qmu(ks);
ks_setup(ks); ks_setup(ks);
ks_setup_int(ks); ks_setup_int(ks);
ks_enable_int(ks);
ks_enable(ks);
memcpy(netdev->dev_addr, ks->mac_addr, 6); memcpy(netdev->dev_addr, ks->mac_addr, 6);
data = ks_rdreg16(ks, KS_OBCR); data = ks_rdreg16(ks, KS_OBCR);
@ -1658,6 +1651,7 @@ static int __devexit ks8851_remove(struct platform_device *pdev)
struct ks_net *ks = netdev_priv(netdev); struct ks_net *ks = netdev_priv(netdev);
struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
kfree(ks->frame_head_info);
unregister_netdev(netdev); unregister_netdev(netdev);
iounmap(ks->hw_addr); iounmap(ks->hw_addr);
free_netdev(netdev); free_netdev(netdev);