diff options
author | Francois Romieu <romieu@fr.zoreil.com> | 2008-07-31 16:51:18 -0400 |
---|---|---|
committer | Francois Romieu <romieu@fr.zoreil.com> | 2008-07-31 17:08:06 -0400 |
commit | 3c4dc7115dfdb9e0450b7a3b0649948f5356d4af (patch) | |
tree | 48367c3315162265f225e87d6480e3bfeee4c84f /drivers/net/via-velocity.c | |
parent | 0fe9f15ee8bd652242a778ddfd30aa6d97a98e23 (diff) |
via-velocity: velocity_init_{rd/tx}_ring use kcalloc(..., GFP_KERNEL).
Allocate and free everyting outside of the locked section.
Spotted-by: Arjan van de Ven <arjan@linux.intel.com>
Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
Fixed-by: Seguier Regis <rseguier@e-teleport.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Diffstat (limited to 'drivers/net/via-velocity.c')
-rw-r--r-- | drivers/net/via-velocity.c | 132 |
1 files changed, 86 insertions, 46 deletions
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index ad3c6733bde7..007c12970065 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c | |||
@@ -662,6 +662,10 @@ static void velocity_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid | |||
662 | spin_unlock_irq(&vptr->lock); | 662 | spin_unlock_irq(&vptr->lock); |
663 | } | 663 | } |
664 | 664 | ||
665 | static void velocity_init_rx_ring_indexes(struct velocity_info *vptr) | ||
666 | { | ||
667 | vptr->rx.dirty = vptr->rx.filled = vptr->rx.curr = 0; | ||
668 | } | ||
665 | 669 | ||
666 | /** | 670 | /** |
667 | * velocity_rx_reset - handle a receive reset | 671 | * velocity_rx_reset - handle a receive reset |
@@ -677,7 +681,7 @@ static void velocity_rx_reset(struct velocity_info *vptr) | |||
677 | struct mac_regs __iomem * regs = vptr->mac_regs; | 681 | struct mac_regs __iomem * regs = vptr->mac_regs; |
678 | int i; | 682 | int i; |
679 | 683 | ||
680 | vptr->rx.dirty = vptr->rx.filled = vptr->rx.curr = 0; | 684 | velocity_init_rx_ring_indexes(vptr); |
681 | 685 | ||
682 | /* | 686 | /* |
683 | * Init state, all RD entries belong to the NIC | 687 | * Init state, all RD entries belong to the NIC |
@@ -1093,14 +1097,14 @@ static int __devinit velocity_get_pci_info(struct velocity_info *vptr, struct pc | |||
1093 | } | 1097 | } |
1094 | 1098 | ||
1095 | /** | 1099 | /** |
1096 | * velocity_init_rings - set up DMA rings | 1100 | * velocity_init_dma_rings - set up DMA rings |
1097 | * @vptr: Velocity to set up | 1101 | * @vptr: Velocity to set up |
1098 | * | 1102 | * |
1099 | * Allocate PCI mapped DMA rings for the receive and transmit layer | 1103 | * Allocate PCI mapped DMA rings for the receive and transmit layer |
1100 | * to use. | 1104 | * to use. |
1101 | */ | 1105 | */ |
1102 | 1106 | ||
1103 | static int velocity_init_rings(struct velocity_info *vptr) | 1107 | static int velocity_init_dma_rings(struct velocity_info *vptr) |
1104 | { | 1108 | { |
1105 | struct velocity_opt *opt = &vptr->options; | 1109 | struct velocity_opt *opt = &vptr->options; |
1106 | const unsigned int rx_ring_size = opt->numrx * sizeof(struct rx_desc); | 1110 | const unsigned int rx_ring_size = opt->numrx * sizeof(struct rx_desc); |
@@ -1141,13 +1145,13 @@ static int velocity_init_rings(struct velocity_info *vptr) | |||
1141 | } | 1145 | } |
1142 | 1146 | ||
1143 | /** | 1147 | /** |
1144 | * velocity_free_rings - free PCI ring pointers | 1148 | * velocity_free_dma_rings - free PCI ring pointers |
1145 | * @vptr: Velocity to free from | 1149 | * @vptr: Velocity to free from |
1146 | * | 1150 | * |
1147 | * Clean up the PCI ring buffers allocated to this velocity. | 1151 | * Clean up the PCI ring buffers allocated to this velocity. |
1148 | */ | 1152 | */ |
1149 | 1153 | ||
1150 | static void velocity_free_rings(struct velocity_info *vptr) | 1154 | static void velocity_free_dma_rings(struct velocity_info *vptr) |
1151 | { | 1155 | { |
1152 | const int size = vptr->options.numrx * sizeof(struct rx_desc) + | 1156 | const int size = vptr->options.numrx * sizeof(struct rx_desc) + |
1153 | vptr->options.numtx * sizeof(struct tx_desc) * vptr->tx.numq; | 1157 | vptr->options.numtx * sizeof(struct tx_desc) * vptr->tx.numq; |
@@ -1229,7 +1233,7 @@ static int velocity_init_rd_ring(struct velocity_info *vptr) | |||
1229 | if (!vptr->rx.info) | 1233 | if (!vptr->rx.info) |
1230 | goto out; | 1234 | goto out; |
1231 | 1235 | ||
1232 | vptr->rx.filled = vptr->rx.dirty = vptr->rx.curr = 0; | 1236 | velocity_init_rx_ring_indexes(vptr); |
1233 | 1237 | ||
1234 | if (velocity_rx_refill(vptr) != vptr->options.numrx) { | 1238 | if (velocity_rx_refill(vptr) != vptr->options.numrx) { |
1235 | VELOCITY_PRT(MSG_LEVEL_ERR, KERN_ERR | 1239 | VELOCITY_PRT(MSG_LEVEL_ERR, KERN_ERR |
@@ -1847,6 +1851,40 @@ static void velocity_free_tx_buf(struct velocity_info *vptr, struct velocity_td_ | |||
1847 | tdinfo->skb = NULL; | 1851 | tdinfo->skb = NULL; |
1848 | } | 1852 | } |
1849 | 1853 | ||
1854 | static int velocity_init_rings(struct velocity_info *vptr, int mtu) | ||
1855 | { | ||
1856 | int ret; | ||
1857 | |||
1858 | velocity_set_rxbufsize(vptr, mtu); | ||
1859 | |||
1860 | ret = velocity_init_dma_rings(vptr); | ||
1861 | if (ret < 0) | ||
1862 | goto out; | ||
1863 | |||
1864 | ret = velocity_init_rd_ring(vptr); | ||
1865 | if (ret < 0) | ||
1866 | goto err_free_dma_rings_0; | ||
1867 | |||
1868 | ret = velocity_init_td_ring(vptr); | ||
1869 | if (ret < 0) | ||
1870 | goto err_free_rd_ring_1; | ||
1871 | out: | ||
1872 | return ret; | ||
1873 | |||
1874 | err_free_rd_ring_1: | ||
1875 | velocity_free_rd_ring(vptr); | ||
1876 | err_free_dma_rings_0: | ||
1877 | velocity_free_dma_rings(vptr); | ||
1878 | goto out; | ||
1879 | } | ||
1880 | |||
1881 | static void velocity_free_rings(struct velocity_info *vptr) | ||
1882 | { | ||
1883 | velocity_free_td_ring(vptr); | ||
1884 | velocity_free_rd_ring(vptr); | ||
1885 | velocity_free_dma_rings(vptr); | ||
1886 | } | ||
1887 | |||
1850 | /** | 1888 | /** |
1851 | * velocity_open - interface activation callback | 1889 | * velocity_open - interface activation callback |
1852 | * @dev: network layer device to open | 1890 | * @dev: network layer device to open |
@@ -1863,20 +1901,10 @@ static int velocity_open(struct net_device *dev) | |||
1863 | struct velocity_info *vptr = netdev_priv(dev); | 1901 | struct velocity_info *vptr = netdev_priv(dev); |
1864 | int ret; | 1902 | int ret; |
1865 | 1903 | ||
1866 | velocity_set_rxbufsize(vptr, dev->mtu); | 1904 | ret = velocity_init_rings(vptr, dev->mtu); |
1867 | |||
1868 | ret = velocity_init_rings(vptr); | ||
1869 | if (ret < 0) | 1905 | if (ret < 0) |
1870 | goto out; | 1906 | goto out; |
1871 | 1907 | ||
1872 | ret = velocity_init_rd_ring(vptr); | ||
1873 | if (ret < 0) | ||
1874 | goto err_free_desc_rings; | ||
1875 | |||
1876 | ret = velocity_init_td_ring(vptr); | ||
1877 | if (ret < 0) | ||
1878 | goto err_free_rd_ring; | ||
1879 | |||
1880 | /* Ensure chip is running */ | 1908 | /* Ensure chip is running */ |
1881 | pci_set_power_state(vptr->pdev, PCI_D0); | 1909 | pci_set_power_state(vptr->pdev, PCI_D0); |
1882 | 1910 | ||
@@ -1889,7 +1917,8 @@ static int velocity_open(struct net_device *dev) | |||
1889 | if (ret < 0) { | 1917 | if (ret < 0) { |
1890 | /* Power down the chip */ | 1918 | /* Power down the chip */ |
1891 | pci_set_power_state(vptr->pdev, PCI_D3hot); | 1919 | pci_set_power_state(vptr->pdev, PCI_D3hot); |
1892 | goto err_free_td_ring; | 1920 | velocity_free_rings(vptr); |
1921 | goto out; | ||
1893 | } | 1922 | } |
1894 | 1923 | ||
1895 | mac_enable_int(vptr->mac_regs); | 1924 | mac_enable_int(vptr->mac_regs); |
@@ -1897,14 +1926,6 @@ static int velocity_open(struct net_device *dev) | |||
1897 | vptr->flags |= VELOCITY_FLAGS_OPENED; | 1926 | vptr->flags |= VELOCITY_FLAGS_OPENED; |
1898 | out: | 1927 | out: |
1899 | return ret; | 1928 | return ret; |
1900 | |||
1901 | err_free_td_ring: | ||
1902 | velocity_free_td_ring(vptr); | ||
1903 | err_free_rd_ring: | ||
1904 | velocity_free_rd_ring(vptr); | ||
1905 | err_free_desc_rings: | ||
1906 | velocity_free_rings(vptr); | ||
1907 | goto out; | ||
1908 | } | 1929 | } |
1909 | 1930 | ||
1910 | /** | 1931 | /** |
@@ -1920,50 +1941,72 @@ err_free_desc_rings: | |||
1920 | static int velocity_change_mtu(struct net_device *dev, int new_mtu) | 1941 | static int velocity_change_mtu(struct net_device *dev, int new_mtu) |
1921 | { | 1942 | { |
1922 | struct velocity_info *vptr = netdev_priv(dev); | 1943 | struct velocity_info *vptr = netdev_priv(dev); |
1923 | unsigned long flags; | ||
1924 | int oldmtu = dev->mtu; | ||
1925 | int ret = 0; | 1944 | int ret = 0; |
1926 | 1945 | ||
1927 | if ((new_mtu < VELOCITY_MIN_MTU) || new_mtu > (VELOCITY_MAX_MTU)) { | 1946 | if ((new_mtu < VELOCITY_MIN_MTU) || new_mtu > (VELOCITY_MAX_MTU)) { |
1928 | VELOCITY_PRT(MSG_LEVEL_ERR, KERN_NOTICE "%s: Invalid MTU.\n", | 1947 | VELOCITY_PRT(MSG_LEVEL_ERR, KERN_NOTICE "%s: Invalid MTU.\n", |
1929 | vptr->dev->name); | 1948 | vptr->dev->name); |
1930 | return -EINVAL; | 1949 | ret = -EINVAL; |
1950 | goto out_0; | ||
1931 | } | 1951 | } |
1932 | 1952 | ||
1933 | if (!netif_running(dev)) { | 1953 | if (!netif_running(dev)) { |
1934 | dev->mtu = new_mtu; | 1954 | dev->mtu = new_mtu; |
1935 | return 0; | 1955 | goto out_0; |
1936 | } | 1956 | } |
1937 | 1957 | ||
1938 | if (new_mtu != oldmtu) { | 1958 | if (dev->mtu != new_mtu) { |
1959 | struct velocity_info *tmp_vptr; | ||
1960 | unsigned long flags; | ||
1961 | struct rx_info rx; | ||
1962 | struct tx_info tx; | ||
1963 | |||
1964 | tmp_vptr = kzalloc(sizeof(*tmp_vptr), GFP_KERNEL); | ||
1965 | if (!tmp_vptr) { | ||
1966 | ret = -ENOMEM; | ||
1967 | goto out_0; | ||
1968 | } | ||
1969 | |||
1970 | tmp_vptr->dev = dev; | ||
1971 | tmp_vptr->pdev = vptr->pdev; | ||
1972 | tmp_vptr->options = vptr->options; | ||
1973 | tmp_vptr->tx.numq = vptr->tx.numq; | ||
1974 | |||
1975 | ret = velocity_init_rings(tmp_vptr, new_mtu); | ||
1976 | if (ret < 0) | ||
1977 | goto out_free_tmp_vptr_1; | ||
1978 | |||
1939 | spin_lock_irqsave(&vptr->lock, flags); | 1979 | spin_lock_irqsave(&vptr->lock, flags); |
1940 | 1980 | ||
1941 | netif_stop_queue(dev); | 1981 | netif_stop_queue(dev); |
1942 | velocity_shutdown(vptr); | 1982 | velocity_shutdown(vptr); |
1943 | 1983 | ||
1944 | velocity_free_td_ring(vptr); | 1984 | rx = vptr->rx; |
1945 | velocity_free_rd_ring(vptr); | 1985 | tx = vptr->tx; |
1946 | 1986 | ||
1947 | dev->mtu = new_mtu; | 1987 | vptr->rx = tmp_vptr->rx; |
1988 | vptr->tx = tmp_vptr->tx; | ||
1948 | 1989 | ||
1949 | velocity_set_rxbufsize(vptr, new_mtu); | 1990 | tmp_vptr->rx = rx; |
1991 | tmp_vptr->tx = tx; | ||
1950 | 1992 | ||
1951 | ret = velocity_init_rd_ring(vptr); | 1993 | dev->mtu = new_mtu; |
1952 | if (ret < 0) | ||
1953 | goto out_unlock; | ||
1954 | 1994 | ||
1955 | ret = velocity_init_td_ring(vptr); | 1995 | velocity_give_many_rx_descs(vptr); |
1956 | if (ret < 0) | ||
1957 | goto out_unlock; | ||
1958 | 1996 | ||
1959 | velocity_init_registers(vptr, VELOCITY_INIT_COLD); | 1997 | velocity_init_registers(vptr, VELOCITY_INIT_COLD); |
1960 | 1998 | ||
1961 | mac_enable_int(vptr->mac_regs); | 1999 | mac_enable_int(vptr->mac_regs); |
1962 | netif_start_queue(dev); | 2000 | netif_start_queue(dev); |
1963 | out_unlock: | 2001 | |
1964 | spin_unlock_irqrestore(&vptr->lock, flags); | 2002 | spin_unlock_irqrestore(&vptr->lock, flags); |
1965 | } | ||
1966 | 2003 | ||
2004 | velocity_free_rings(tmp_vptr); | ||
2005 | |||
2006 | out_free_tmp_vptr_1: | ||
2007 | kfree(tmp_vptr); | ||
2008 | } | ||
2009 | out_0: | ||
1967 | return ret; | 2010 | return ret; |
1968 | } | 2011 | } |
1969 | 2012 | ||
@@ -2009,9 +2052,6 @@ static int velocity_close(struct net_device *dev) | |||
2009 | /* Power down the chip */ | 2052 | /* Power down the chip */ |
2010 | pci_set_power_state(vptr->pdev, PCI_D3hot); | 2053 | pci_set_power_state(vptr->pdev, PCI_D3hot); |
2011 | 2054 | ||
2012 | /* Free the resources */ | ||
2013 | velocity_free_td_ring(vptr); | ||
2014 | velocity_free_rd_ring(vptr); | ||
2015 | velocity_free_rings(vptr); | 2055 | velocity_free_rings(vptr); |
2016 | 2056 | ||
2017 | vptr->flags &= (~VELOCITY_FLAGS_OPENED); | 2057 | vptr->flags &= (~VELOCITY_FLAGS_OPENED); |