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:
parent
0ebe74e7ba
commit
4a91ca4e18
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue