diff options
author | Atsushi Nemoto <anemo@mba.ocn.ne.jp> | 2009-08-06 00:41:46 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-08-06 16:14:22 -0400 |
commit | db30f5ef6e4471fd55671382b8870fdd61e35814 (patch) | |
tree | 62307b1346a56025edc1fe17482e92adc6bd7d27 /drivers | |
parent | 297713decac17527d3583fcd4d18564568cac759 (diff) |
tc35815: Improve BLEx / FDAEx handling
Clear Int_BLEx / Int_FDAEx after (not before) processing Rx interrupt.
This will reduce number of unnecessary interrupts.
Also print rx error messages only if netif_msg_rx_err() enabled.
Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/tc35815.c | 60 |
1 files changed, 26 insertions, 34 deletions
diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c index a7581632f811..62965d6665d2 100644 --- a/drivers/net/tc35815.c +++ b/drivers/net/tc35815.c | |||
@@ -1541,8 +1541,6 @@ static int tc35815_do_interrupt(struct net_device *dev, u32 status) | |||
1541 | #endif | 1541 | #endif |
1542 | { | 1542 | { |
1543 | struct tc35815_local *lp = netdev_priv(dev); | 1543 | struct tc35815_local *lp = netdev_priv(dev); |
1544 | struct tc35815_regs __iomem *tr = | ||
1545 | (struct tc35815_regs __iomem *)dev->base_addr; | ||
1546 | int ret = -1; | 1544 | int ret = -1; |
1547 | 1545 | ||
1548 | /* Fatal errors... */ | 1546 | /* Fatal errors... */ |
@@ -1552,27 +1550,26 @@ static int tc35815_do_interrupt(struct net_device *dev, u32 status) | |||
1552 | } | 1550 | } |
1553 | /* recoverable errors */ | 1551 | /* recoverable errors */ |
1554 | if (status & Int_IntFDAEx) { | 1552 | if (status & Int_IntFDAEx) { |
1555 | /* disable FDAEx int. (until we make rooms...) */ | 1553 | if (netif_msg_rx_err(lp)) |
1556 | tc_writel(tc_readl(&tr->Int_En) & ~Int_FDAExEn, &tr->Int_En); | 1554 | dev_warn(&dev->dev, |
1557 | printk(KERN_WARNING | 1555 | "Free Descriptor Area Exhausted (%#x).\n", |
1558 | "%s: Free Descriptor Area Exhausted (%#x).\n", | 1556 | status); |
1559 | dev->name, status); | ||
1560 | dev->stats.rx_dropped++; | 1557 | dev->stats.rx_dropped++; |
1561 | ret = 0; | 1558 | ret = 0; |
1562 | } | 1559 | } |
1563 | if (status & Int_IntBLEx) { | 1560 | if (status & Int_IntBLEx) { |
1564 | /* disable BLEx int. (until we make rooms...) */ | 1561 | if (netif_msg_rx_err(lp)) |
1565 | tc_writel(tc_readl(&tr->Int_En) & ~Int_BLExEn, &tr->Int_En); | 1562 | dev_warn(&dev->dev, |
1566 | printk(KERN_WARNING | 1563 | "Buffer List Exhausted (%#x).\n", |
1567 | "%s: Buffer List Exhausted (%#x).\n", | 1564 | status); |
1568 | dev->name, status); | ||
1569 | dev->stats.rx_dropped++; | 1565 | dev->stats.rx_dropped++; |
1570 | ret = 0; | 1566 | ret = 0; |
1571 | } | 1567 | } |
1572 | if (status & Int_IntExBD) { | 1568 | if (status & Int_IntExBD) { |
1573 | printk(KERN_WARNING | 1569 | if (netif_msg_rx_err(lp)) |
1574 | "%s: Excessive Buffer Descriptiors (%#x).\n", | 1570 | dev_warn(&dev->dev, |
1575 | dev->name, status); | 1571 | "Excessive Buffer Descriptiors (%#x).\n", |
1572 | status); | ||
1576 | dev->stats.rx_length_errors++; | 1573 | dev->stats.rx_length_errors++; |
1577 | ret = 0; | 1574 | ret = 0; |
1578 | } | 1575 | } |
@@ -1631,8 +1628,12 @@ static irqreturn_t tc35815_interrupt(int irq, void *dev_id) | |||
1631 | 1628 | ||
1632 | spin_lock(&lp->lock); | 1629 | spin_lock(&lp->lock); |
1633 | status = tc_readl(&tr->Int_Src); | 1630 | status = tc_readl(&tr->Int_Src); |
1634 | tc_writel(status, &tr->Int_Src); /* write to clear */ | 1631 | /* BLEx, FDAEx will be cleared later */ |
1632 | tc_writel(status & ~(Int_BLEx | Int_FDAEx), | ||
1633 | &tr->Int_Src); /* write to clear */ | ||
1635 | handled = tc35815_do_interrupt(dev, status); | 1634 | handled = tc35815_do_interrupt(dev, status); |
1635 | if (status & (Int_BLEx | Int_FDAEx)) | ||
1636 | tc_writel(status & (Int_BLEx | Int_FDAEx), &tr->Int_Src); | ||
1636 | (void)tc_readl(&tr->Int_Src); /* flush */ | 1637 | (void)tc_readl(&tr->Int_Src); /* flush */ |
1637 | spin_unlock(&lp->lock); | 1638 | spin_unlock(&lp->lock); |
1638 | return IRQ_RETVAL(handled >= 0); | 1639 | return IRQ_RETVAL(handled >= 0); |
@@ -1660,8 +1661,6 @@ tc35815_rx(struct net_device *dev) | |||
1660 | struct tc35815_local *lp = netdev_priv(dev); | 1661 | struct tc35815_local *lp = netdev_priv(dev); |
1661 | unsigned int fdctl; | 1662 | unsigned int fdctl; |
1662 | int i; | 1663 | int i; |
1663 | int buf_free_count = 0; | ||
1664 | int fd_free_count = 0; | ||
1665 | #ifdef TC35815_NAPI | 1664 | #ifdef TC35815_NAPI |
1666 | int received = 0; | 1665 | int received = 0; |
1667 | #endif | 1666 | #endif |
@@ -1770,8 +1769,9 @@ tc35815_rx(struct net_device *dev) | |||
1770 | dev->stats.rx_bytes += pkt_len; | 1769 | dev->stats.rx_bytes += pkt_len; |
1771 | } else { | 1770 | } else { |
1772 | dev->stats.rx_errors++; | 1771 | dev->stats.rx_errors++; |
1773 | printk(KERN_DEBUG "%s: Rx error (status %x)\n", | 1772 | if (netif_msg_rx_err(lp)) |
1774 | dev->name, status & Rx_Stat_Mask); | 1773 | dev_info(&dev->dev, "Rx error (status %x)\n", |
1774 | status & Rx_Stat_Mask); | ||
1775 | /* WORKAROUND: LongErr and CRCErr means Overflow. */ | 1775 | /* WORKAROUND: LongErr and CRCErr means Overflow. */ |
1776 | if ((status & Rx_LongErr) && (status & Rx_CRCErr)) { | 1776 | if ((status & Rx_LongErr) && (status & Rx_CRCErr)) { |
1777 | status &= ~(Rx_LongErr|Rx_CRCErr); | 1777 | status &= ~(Rx_LongErr|Rx_CRCErr); |
@@ -1849,7 +1849,6 @@ tc35815_rx(struct net_device *dev) | |||
1849 | #else | 1849 | #else |
1850 | lp->fbl_count++; | 1850 | lp->fbl_count++; |
1851 | #endif | 1851 | #endif |
1852 | buf_free_count++; | ||
1853 | } | 1852 | } |
1854 | } | 1853 | } |
1855 | 1854 | ||
@@ -1871,7 +1870,6 @@ tc35815_rx(struct net_device *dev) | |||
1871 | #endif | 1870 | #endif |
1872 | lp->rfd_cur->fd.FDCtl = cpu_to_le32(FD_CownsFD); | 1871 | lp->rfd_cur->fd.FDCtl = cpu_to_le32(FD_CownsFD); |
1873 | lp->rfd_cur++; | 1872 | lp->rfd_cur++; |
1874 | fd_free_count++; | ||
1875 | } | 1873 | } |
1876 | if (lp->rfd_cur > lp->rfd_limit) | 1874 | if (lp->rfd_cur > lp->rfd_limit) |
1877 | lp->rfd_cur = lp->rfd_base; | 1875 | lp->rfd_cur = lp->rfd_base; |
@@ -1882,17 +1880,6 @@ tc35815_rx(struct net_device *dev) | |||
1882 | #endif | 1880 | #endif |
1883 | } | 1881 | } |
1884 | 1882 | ||
1885 | /* re-enable BL/FDA Exhaust interrupts. */ | ||
1886 | if (fd_free_count) { | ||
1887 | struct tc35815_regs __iomem *tr = | ||
1888 | (struct tc35815_regs __iomem *)dev->base_addr; | ||
1889 | u32 en, en_old = tc_readl(&tr->Int_En); | ||
1890 | en = en_old | Int_FDAExEn; | ||
1891 | if (buf_free_count) | ||
1892 | en |= Int_BLExEn; | ||
1893 | if (en != en_old) | ||
1894 | tc_writel(en, &tr->Int_En); | ||
1895 | } | ||
1896 | #ifdef TC35815_NAPI | 1883 | #ifdef TC35815_NAPI |
1897 | return received; | 1884 | return received; |
1898 | #endif | 1885 | #endif |
@@ -1911,9 +1898,14 @@ static int tc35815_poll(struct napi_struct *napi, int budget) | |||
1911 | spin_lock(&lp->lock); | 1898 | spin_lock(&lp->lock); |
1912 | status = tc_readl(&tr->Int_Src); | 1899 | status = tc_readl(&tr->Int_Src); |
1913 | do { | 1900 | do { |
1914 | tc_writel(status, &tr->Int_Src); /* write to clear */ | 1901 | /* BLEx, FDAEx will be cleared later */ |
1902 | tc_writel(status & ~(Int_BLEx | Int_FDAEx), | ||
1903 | &tr->Int_Src); /* write to clear */ | ||
1915 | 1904 | ||
1916 | handled = tc35815_do_interrupt(dev, status, budget - received); | 1905 | handled = tc35815_do_interrupt(dev, status, budget - received); |
1906 | if (status & (Int_BLEx | Int_FDAEx)) | ||
1907 | tc_writel(status & (Int_BLEx | Int_FDAEx), | ||
1908 | &tr->Int_Src); | ||
1917 | if (handled >= 0) { | 1909 | if (handled >= 0) { |
1918 | received += handled; | 1910 | received += handled; |
1919 | if (received >= budget) | 1911 | if (received >= budget) |