Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4a91ca4e authored by David J. Choi's avatar David J. Choi Committed by David S. Miller
Browse files

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: default avatarDavid J. Choi <david.choi@micrel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 0ebe74e7
Loading
Loading
Loading
Loading
+68 −74
Original line number Original line Diff line number Diff line
@@ -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);