diff options
Diffstat (limited to 'drivers/net/ucc_geth.c')
-rw-r--r-- | drivers/net/ucc_geth.c | 408 |
1 files changed, 72 insertions, 336 deletions
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index c87747bb24c5..7d5a1303e30d 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c | |||
@@ -188,17 +188,6 @@ static void mem_disp(u8 *addr, int size) | |||
188 | } | 188 | } |
189 | #endif /* DEBUG */ | 189 | #endif /* DEBUG */ |
190 | 190 | ||
191 | #ifdef CONFIG_UGETH_FILTERING | ||
192 | static void enqueue(struct list_head *node, struct list_head *lh) | ||
193 | { | ||
194 | unsigned long flags; | ||
195 | |||
196 | spin_lock_irqsave(&ugeth_lock, flags); | ||
197 | list_add_tail(node, lh); | ||
198 | spin_unlock_irqrestore(&ugeth_lock, flags); | ||
199 | } | ||
200 | #endif /* CONFIG_UGETH_FILTERING */ | ||
201 | |||
202 | static struct list_head *dequeue(struct list_head *lh) | 191 | static struct list_head *dequeue(struct list_head *lh) |
203 | { | 192 | { |
204 | unsigned long flags; | 193 | unsigned long flags; |
@@ -391,23 +380,6 @@ static int dump_init_enet_entries(struct ucc_geth_private *ugeth, | |||
391 | } | 380 | } |
392 | #endif | 381 | #endif |
393 | 382 | ||
394 | #ifdef CONFIG_UGETH_FILTERING | ||
395 | static struct enet_addr_container *get_enet_addr_container(void) | ||
396 | { | ||
397 | struct enet_addr_container *enet_addr_cont; | ||
398 | |||
399 | /* allocate memory */ | ||
400 | enet_addr_cont = kmalloc(sizeof(struct enet_addr_container), GFP_KERNEL); | ||
401 | if (!enet_addr_cont) { | ||
402 | ugeth_err("%s: No memory for enet_addr_container object.", | ||
403 | __func__); | ||
404 | return NULL; | ||
405 | } | ||
406 | |||
407 | return enet_addr_cont; | ||
408 | } | ||
409 | #endif /* CONFIG_UGETH_FILTERING */ | ||
410 | |||
411 | static void put_enet_addr_container(struct enet_addr_container *enet_addr_cont) | 383 | static void put_enet_addr_container(struct enet_addr_container *enet_addr_cont) |
412 | { | 384 | { |
413 | kfree(enet_addr_cont); | 385 | kfree(enet_addr_cont); |
@@ -420,28 +392,6 @@ static void set_mac_addr(__be16 __iomem *reg, u8 *mac) | |||
420 | out_be16(®[2], ((u16)mac[1] << 8) | mac[0]); | 392 | out_be16(®[2], ((u16)mac[1] << 8) | mac[0]); |
421 | } | 393 | } |
422 | 394 | ||
423 | #ifdef CONFIG_UGETH_FILTERING | ||
424 | static int hw_add_addr_in_paddr(struct ucc_geth_private *ugeth, | ||
425 | u8 *p_enet_addr, u8 paddr_num) | ||
426 | { | ||
427 | struct ucc_geth_82xx_address_filtering_pram *p_82xx_addr_filt; | ||
428 | |||
429 | if (!(paddr_num < NUM_OF_PADDRS)) { | ||
430 | ugeth_warn("%s: Illegal paddr_num.", __func__); | ||
431 | return -EINVAL; | ||
432 | } | ||
433 | |||
434 | p_82xx_addr_filt = | ||
435 | (struct ucc_geth_82xx_address_filtering_pram *) ugeth->p_rx_glbl_pram-> | ||
436 | addressfiltering; | ||
437 | |||
438 | /* Ethernet frames are defined in Little Endian mode, */ | ||
439 | /* therefore to insert the address we reverse the bytes. */ | ||
440 | set_mac_addr(&p_82xx_addr_filt->paddr[paddr_num].h, p_enet_addr); | ||
441 | return 0; | ||
442 | } | ||
443 | #endif /* CONFIG_UGETH_FILTERING */ | ||
444 | |||
445 | static int hw_clear_addr_in_paddr(struct ucc_geth_private *ugeth, u8 paddr_num) | 395 | static int hw_clear_addr_in_paddr(struct ucc_geth_private *ugeth, u8 paddr_num) |
446 | { | 396 | { |
447 | struct ucc_geth_82xx_address_filtering_pram __iomem *p_82xx_addr_filt; | 397 | struct ucc_geth_82xx_address_filtering_pram __iomem *p_82xx_addr_filt; |
@@ -1615,8 +1565,8 @@ static int init_phy(struct net_device *dev) | |||
1615 | priv->oldspeed = 0; | 1565 | priv->oldspeed = 0; |
1616 | priv->oldduplex = -1; | 1566 | priv->oldduplex = -1; |
1617 | 1567 | ||
1618 | snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, priv->ug_info->mdio_bus, | 1568 | snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, priv->ug_info->mdio_bus, |
1619 | priv->ug_info->phy_address); | 1569 | priv->ug_info->phy_address); |
1620 | 1570 | ||
1621 | phydev = phy_connect(dev, phy_id, &adjust_link, 0, priv->phy_interface); | 1571 | phydev = phy_connect(dev, phy_id, &adjust_link, 0, priv->phy_interface); |
1622 | 1572 | ||
@@ -1647,6 +1597,7 @@ static int ugeth_graceful_stop_tx(struct ucc_geth_private *ugeth) | |||
1647 | struct ucc_fast_private *uccf; | 1597 | struct ucc_fast_private *uccf; |
1648 | u32 cecr_subblock; | 1598 | u32 cecr_subblock; |
1649 | u32 temp; | 1599 | u32 temp; |
1600 | int i = 10; | ||
1650 | 1601 | ||
1651 | uccf = ugeth->uccf; | 1602 | uccf = ugeth->uccf; |
1652 | 1603 | ||
@@ -1664,8 +1615,9 @@ static int ugeth_graceful_stop_tx(struct ucc_geth_private *ugeth) | |||
1664 | 1615 | ||
1665 | /* Wait for command to complete */ | 1616 | /* Wait for command to complete */ |
1666 | do { | 1617 | do { |
1618 | msleep(10); | ||
1667 | temp = in_be32(uccf->p_ucce); | 1619 | temp = in_be32(uccf->p_ucce); |
1668 | } while (!(temp & UCCE_GRA)); | 1620 | } while (!(temp & UCCE_GRA) && --i); |
1669 | 1621 | ||
1670 | uccf->stopped_tx = 1; | 1622 | uccf->stopped_tx = 1; |
1671 | 1623 | ||
@@ -1677,6 +1629,7 @@ static int ugeth_graceful_stop_rx(struct ucc_geth_private * ugeth) | |||
1677 | struct ucc_fast_private *uccf; | 1629 | struct ucc_fast_private *uccf; |
1678 | u32 cecr_subblock; | 1630 | u32 cecr_subblock; |
1679 | u8 temp; | 1631 | u8 temp; |
1632 | int i = 10; | ||
1680 | 1633 | ||
1681 | uccf = ugeth->uccf; | 1634 | uccf = ugeth->uccf; |
1682 | 1635 | ||
@@ -1694,9 +1647,9 @@ static int ugeth_graceful_stop_rx(struct ucc_geth_private * ugeth) | |||
1694 | ucc_num); | 1647 | ucc_num); |
1695 | qe_issue_cmd(QE_GRACEFUL_STOP_RX, cecr_subblock, | 1648 | qe_issue_cmd(QE_GRACEFUL_STOP_RX, cecr_subblock, |
1696 | QE_CR_PROTOCOL_ETHERNET, 0); | 1649 | QE_CR_PROTOCOL_ETHERNET, 0); |
1697 | 1650 | msleep(10); | |
1698 | temp = in_8(&ugeth->p_rx_glbl_pram->rxgstpack); | 1651 | temp = in_8(&ugeth->p_rx_glbl_pram->rxgstpack); |
1699 | } while (!(temp & GRACEFUL_STOP_ACKNOWLEDGE_RX)); | 1652 | } while (!(temp & GRACEFUL_STOP_ACKNOWLEDGE_RX) && --i); |
1700 | 1653 | ||
1701 | uccf->stopped_rx = 1; | 1654 | uccf->stopped_rx = 1; |
1702 | 1655 | ||
@@ -1799,196 +1752,6 @@ static void ugeth_dump_regs(struct ucc_geth_private *ugeth) | |||
1799 | #endif | 1752 | #endif |
1800 | } | 1753 | } |
1801 | 1754 | ||
1802 | #ifdef CONFIG_UGETH_FILTERING | ||
1803 | static int ugeth_ext_filtering_serialize_tad(struct ucc_geth_tad_params * | ||
1804 | p_UccGethTadParams, | ||
1805 | struct qe_fltr_tad *qe_fltr_tad) | ||
1806 | { | ||
1807 | u16 temp; | ||
1808 | |||
1809 | /* Zero serialized TAD */ | ||
1810 | memset(qe_fltr_tad, 0, QE_FLTR_TAD_SIZE); | ||
1811 | |||
1812 | qe_fltr_tad->serialized[0] |= UCC_GETH_TAD_V; /* Must have this */ | ||
1813 | if (p_UccGethTadParams->rx_non_dynamic_extended_features_mode || | ||
1814 | (p_UccGethTadParams->vtag_op != UCC_GETH_VLAN_OPERATION_TAGGED_NOP) | ||
1815 | || (p_UccGethTadParams->vnontag_op != | ||
1816 | UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP) | ||
1817 | ) | ||
1818 | qe_fltr_tad->serialized[0] |= UCC_GETH_TAD_EF; | ||
1819 | if (p_UccGethTadParams->reject_frame) | ||
1820 | qe_fltr_tad->serialized[0] |= UCC_GETH_TAD_REJ; | ||
1821 | temp = | ||
1822 | (u16) (((u16) p_UccGethTadParams-> | ||
1823 | vtag_op) << UCC_GETH_TAD_VTAG_OP_SHIFT); | ||
1824 | qe_fltr_tad->serialized[0] |= (u8) (temp >> 8); /* upper bits */ | ||
1825 | |||
1826 | qe_fltr_tad->serialized[1] |= (u8) (temp & 0x00ff); /* lower bits */ | ||
1827 | if (p_UccGethTadParams->vnontag_op == | ||
1828 | UCC_GETH_VLAN_OPERATION_NON_TAGGED_Q_TAG_INSERT) | ||
1829 | qe_fltr_tad->serialized[1] |= UCC_GETH_TAD_V_NON_VTAG_OP; | ||
1830 | qe_fltr_tad->serialized[1] |= | ||
1831 | p_UccGethTadParams->rqos << UCC_GETH_TAD_RQOS_SHIFT; | ||
1832 | |||
1833 | qe_fltr_tad->serialized[2] |= | ||
1834 | p_UccGethTadParams->vpri << UCC_GETH_TAD_V_PRIORITY_SHIFT; | ||
1835 | /* upper bits */ | ||
1836 | qe_fltr_tad->serialized[2] |= (u8) (p_UccGethTadParams->vid >> 8); | ||
1837 | /* lower bits */ | ||
1838 | qe_fltr_tad->serialized[3] |= (u8) (p_UccGethTadParams->vid & 0x00ff); | ||
1839 | |||
1840 | return 0; | ||
1841 | } | ||
1842 | |||
1843 | static struct enet_addr_container_t | ||
1844 | *ugeth_82xx_filtering_get_match_addr_in_hash(struct ucc_geth_private *ugeth, | ||
1845 | struct enet_addr *p_enet_addr) | ||
1846 | { | ||
1847 | struct enet_addr_container *enet_addr_cont; | ||
1848 | struct list_head *p_lh; | ||
1849 | u16 i, num; | ||
1850 | int32_t j; | ||
1851 | u8 *p_counter; | ||
1852 | |||
1853 | if ((*p_enet_addr)[0] & ENET_GROUP_ADDR) { | ||
1854 | p_lh = &ugeth->group_hash_q; | ||
1855 | p_counter = &(ugeth->numGroupAddrInHash); | ||
1856 | } else { | ||
1857 | p_lh = &ugeth->ind_hash_q; | ||
1858 | p_counter = &(ugeth->numIndAddrInHash); | ||
1859 | } | ||
1860 | |||
1861 | if (!p_lh) | ||
1862 | return NULL; | ||
1863 | |||
1864 | num = *p_counter; | ||
1865 | |||
1866 | for (i = 0; i < num; i++) { | ||
1867 | enet_addr_cont = | ||
1868 | (struct enet_addr_container *) | ||
1869 | ENET_ADDR_CONT_ENTRY(dequeue(p_lh)); | ||
1870 | for (j = ENET_NUM_OCTETS_PER_ADDRESS - 1; j >= 0; j--) { | ||
1871 | if ((*p_enet_addr)[j] != (enet_addr_cont->address)[j]) | ||
1872 | break; | ||
1873 | if (j == 0) | ||
1874 | return enet_addr_cont; /* Found */ | ||
1875 | } | ||
1876 | enqueue(p_lh, &enet_addr_cont->node); /* Put it back */ | ||
1877 | } | ||
1878 | return NULL; | ||
1879 | } | ||
1880 | |||
1881 | static int ugeth_82xx_filtering_add_addr_in_hash(struct ucc_geth_private *ugeth, | ||
1882 | struct enet_addr *p_enet_addr) | ||
1883 | { | ||
1884 | enum ucc_geth_enet_address_recognition_location location; | ||
1885 | struct enet_addr_container *enet_addr_cont; | ||
1886 | struct list_head *p_lh; | ||
1887 | u8 i; | ||
1888 | u32 limit; | ||
1889 | u8 *p_counter; | ||
1890 | |||
1891 | if ((*p_enet_addr)[0] & ENET_GROUP_ADDR) { | ||
1892 | p_lh = &ugeth->group_hash_q; | ||
1893 | limit = ugeth->ug_info->maxGroupAddrInHash; | ||
1894 | location = | ||
1895 | UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_GROUP_HASH; | ||
1896 | p_counter = &(ugeth->numGroupAddrInHash); | ||
1897 | } else { | ||
1898 | p_lh = &ugeth->ind_hash_q; | ||
1899 | limit = ugeth->ug_info->maxIndAddrInHash; | ||
1900 | location = | ||
1901 | UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_INDIVIDUAL_HASH; | ||
1902 | p_counter = &(ugeth->numIndAddrInHash); | ||
1903 | } | ||
1904 | |||
1905 | if ((enet_addr_cont = | ||
1906 | ugeth_82xx_filtering_get_match_addr_in_hash(ugeth, p_enet_addr))) { | ||
1907 | list_add(p_lh, &enet_addr_cont->node); /* Put it back */ | ||
1908 | return 0; | ||
1909 | } | ||
1910 | if ((!p_lh) || (!(*p_counter < limit))) | ||
1911 | return -EBUSY; | ||
1912 | if (!(enet_addr_cont = get_enet_addr_container())) | ||
1913 | return -ENOMEM; | ||
1914 | for (i = 0; i < ENET_NUM_OCTETS_PER_ADDRESS; i++) | ||
1915 | (enet_addr_cont->address)[i] = (*p_enet_addr)[i]; | ||
1916 | enet_addr_cont->location = location; | ||
1917 | enqueue(p_lh, &enet_addr_cont->node); /* Put it back */ | ||
1918 | ++(*p_counter); | ||
1919 | |||
1920 | hw_add_addr_in_hash(ugeth, enet_addr_cont->address); | ||
1921 | return 0; | ||
1922 | } | ||
1923 | |||
1924 | static int ugeth_82xx_filtering_clear_addr_in_hash(struct ucc_geth_private *ugeth, | ||
1925 | struct enet_addr *p_enet_addr) | ||
1926 | { | ||
1927 | struct ucc_geth_82xx_address_filtering_pram *p_82xx_addr_filt; | ||
1928 | struct enet_addr_container *enet_addr_cont; | ||
1929 | struct ucc_fast_private *uccf; | ||
1930 | enum comm_dir comm_dir; | ||
1931 | u16 i, num; | ||
1932 | struct list_head *p_lh; | ||
1933 | u32 *addr_h, *addr_l; | ||
1934 | u8 *p_counter; | ||
1935 | |||
1936 | uccf = ugeth->uccf; | ||
1937 | |||
1938 | p_82xx_addr_filt = | ||
1939 | (struct ucc_geth_82xx_address_filtering_pram *) ugeth->p_rx_glbl_pram-> | ||
1940 | addressfiltering; | ||
1941 | |||
1942 | if (! | ||
1943 | (enet_addr_cont = | ||
1944 | ugeth_82xx_filtering_get_match_addr_in_hash(ugeth, p_enet_addr))) | ||
1945 | return -ENOENT; | ||
1946 | |||
1947 | /* It's been found and removed from the CQ. */ | ||
1948 | /* Now destroy its container */ | ||
1949 | put_enet_addr_container(enet_addr_cont); | ||
1950 | |||
1951 | if ((*p_enet_addr)[0] & ENET_GROUP_ADDR) { | ||
1952 | addr_h = &(p_82xx_addr_filt->gaddr_h); | ||
1953 | addr_l = &(p_82xx_addr_filt->gaddr_l); | ||
1954 | p_lh = &ugeth->group_hash_q; | ||
1955 | p_counter = &(ugeth->numGroupAddrInHash); | ||
1956 | } else { | ||
1957 | addr_h = &(p_82xx_addr_filt->iaddr_h); | ||
1958 | addr_l = &(p_82xx_addr_filt->iaddr_l); | ||
1959 | p_lh = &ugeth->ind_hash_q; | ||
1960 | p_counter = &(ugeth->numIndAddrInHash); | ||
1961 | } | ||
1962 | |||
1963 | comm_dir = 0; | ||
1964 | if (uccf->enabled_tx) | ||
1965 | comm_dir |= COMM_DIR_TX; | ||
1966 | if (uccf->enabled_rx) | ||
1967 | comm_dir |= COMM_DIR_RX; | ||
1968 | if (comm_dir) | ||
1969 | ugeth_disable(ugeth, comm_dir); | ||
1970 | |||
1971 | /* Clear the hash table. */ | ||
1972 | out_be32(addr_h, 0x00000000); | ||
1973 | out_be32(addr_l, 0x00000000); | ||
1974 | |||
1975 | /* Add all remaining CQ elements back into hash */ | ||
1976 | num = --(*p_counter); | ||
1977 | for (i = 0; i < num; i++) { | ||
1978 | enet_addr_cont = | ||
1979 | (struct enet_addr_container *) | ||
1980 | ENET_ADDR_CONT_ENTRY(dequeue(p_lh)); | ||
1981 | hw_add_addr_in_hash(ugeth, enet_addr_cont->address); | ||
1982 | enqueue(p_lh, &enet_addr_cont->node); /* Put it back */ | ||
1983 | } | ||
1984 | |||
1985 | if (comm_dir) | ||
1986 | ugeth_enable(ugeth, comm_dir); | ||
1987 | |||
1988 | return 0; | ||
1989 | } | ||
1990 | #endif /* CONFIG_UGETH_FILTERING */ | ||
1991 | |||
1992 | static int ugeth_82xx_filtering_clear_all_addr_in_hash(struct ucc_geth_private * | 1755 | static int ugeth_82xx_filtering_clear_all_addr_in_hash(struct ucc_geth_private * |
1993 | ugeth, | 1756 | ugeth, |
1994 | enum enet_addr_type | 1757 | enum enet_addr_type |
@@ -2051,28 +1814,6 @@ static int ugeth_82xx_filtering_clear_all_addr_in_hash(struct ucc_geth_private * | |||
2051 | return 0; | 1814 | return 0; |
2052 | } | 1815 | } |
2053 | 1816 | ||
2054 | #ifdef CONFIG_UGETH_FILTERING | ||
2055 | static int ugeth_82xx_filtering_add_addr_in_paddr(struct ucc_geth_private *ugeth, | ||
2056 | struct enet_addr *p_enet_addr, | ||
2057 | u8 paddr_num) | ||
2058 | { | ||
2059 | int i; | ||
2060 | |||
2061 | if ((*p_enet_addr)[0] & ENET_GROUP_ADDR) | ||
2062 | ugeth_warn | ||
2063 | ("%s: multicast address added to paddr will have no " | ||
2064 | "effect - is this what you wanted?", | ||
2065 | __func__); | ||
2066 | |||
2067 | ugeth->indAddrRegUsed[paddr_num] = 1; /* mark this paddr as used */ | ||
2068 | /* store address in our database */ | ||
2069 | for (i = 0; i < ENET_NUM_OCTETS_PER_ADDRESS; i++) | ||
2070 | ugeth->paddr[paddr_num][i] = (*p_enet_addr)[i]; | ||
2071 | /* put in hardware */ | ||
2072 | return hw_add_addr_in_paddr(ugeth, p_enet_addr, paddr_num); | ||
2073 | } | ||
2074 | #endif /* CONFIG_UGETH_FILTERING */ | ||
2075 | |||
2076 | static int ugeth_82xx_filtering_clear_addr_in_paddr(struct ucc_geth_private *ugeth, | 1817 | static int ugeth_82xx_filtering_clear_addr_in_paddr(struct ucc_geth_private *ugeth, |
2077 | u8 paddr_num) | 1818 | u8 paddr_num) |
2078 | { | 1819 | { |
@@ -2215,7 +1956,10 @@ static void ucc_geth_memclean(struct ucc_geth_private *ugeth) | |||
2215 | while (!list_empty(&ugeth->ind_hash_q)) | 1956 | while (!list_empty(&ugeth->ind_hash_q)) |
2216 | put_enet_addr_container(ENET_ADDR_CONT_ENTRY | 1957 | put_enet_addr_container(ENET_ADDR_CONT_ENTRY |
2217 | (dequeue(&ugeth->ind_hash_q))); | 1958 | (dequeue(&ugeth->ind_hash_q))); |
2218 | 1959 | if (ugeth->ug_regs) { | |
1960 | iounmap(ugeth->ug_regs); | ||
1961 | ugeth->ug_regs = NULL; | ||
1962 | } | ||
2219 | } | 1963 | } |
2220 | 1964 | ||
2221 | static void ucc_geth_set_multi(struct net_device *dev) | 1965 | static void ucc_geth_set_multi(struct net_device *dev) |
@@ -2297,8 +2041,6 @@ static void ucc_geth_stop(struct ucc_geth_private *ugeth) | |||
2297 | tempval &= ~(MACCFG1_ENABLE_RX | MACCFG1_ENABLE_TX); | 2041 | tempval &= ~(MACCFG1_ENABLE_RX | MACCFG1_ENABLE_TX); |
2298 | out_be32(&ug_regs->maccfg1, tempval); | 2042 | out_be32(&ug_regs->maccfg1, tempval); |
2299 | 2043 | ||
2300 | free_irq(ugeth->ug_info->uf_info.irq, ugeth->dev); | ||
2301 | |||
2302 | ucc_geth_memclean(ugeth); | 2044 | ucc_geth_memclean(ugeth); |
2303 | } | 2045 | } |
2304 | 2046 | ||
@@ -2419,11 +2161,15 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth) | |||
2419 | if (ucc_fast_init(uf_info, &ugeth->uccf)) { | 2161 | if (ucc_fast_init(uf_info, &ugeth->uccf)) { |
2420 | if (netif_msg_probe(ugeth)) | 2162 | if (netif_msg_probe(ugeth)) |
2421 | ugeth_err("%s: Failed to init uccf.", __func__); | 2163 | ugeth_err("%s: Failed to init uccf.", __func__); |
2422 | ucc_geth_memclean(ugeth); | ||
2423 | return -ENOMEM; | 2164 | return -ENOMEM; |
2424 | } | 2165 | } |
2425 | 2166 | ||
2426 | ugeth->ug_regs = (struct ucc_geth __iomem *) ioremap(uf_info->regs, sizeof(struct ucc_geth)); | 2167 | ugeth->ug_regs = ioremap(uf_info->regs, sizeof(*ugeth->ug_regs)); |
2168 | if (!ugeth->ug_regs) { | ||
2169 | if (netif_msg_probe(ugeth)) | ||
2170 | ugeth_err("%s: Failed to ioremap regs.", __func__); | ||
2171 | return -ENOMEM; | ||
2172 | } | ||
2427 | 2173 | ||
2428 | return 0; | 2174 | return 0; |
2429 | } | 2175 | } |
@@ -2475,7 +2221,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) | |||
2475 | if (netif_msg_ifup(ugeth)) | 2221 | if (netif_msg_ifup(ugeth)) |
2476 | ugeth_err("%s: Bad number of Rx threads value.", | 2222 | ugeth_err("%s: Bad number of Rx threads value.", |
2477 | __func__); | 2223 | __func__); |
2478 | ucc_geth_memclean(ugeth); | ||
2479 | return -EINVAL; | 2224 | return -EINVAL; |
2480 | break; | 2225 | break; |
2481 | } | 2226 | } |
@@ -2500,7 +2245,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) | |||
2500 | if (netif_msg_ifup(ugeth)) | 2245 | if (netif_msg_ifup(ugeth)) |
2501 | ugeth_err("%s: Bad number of Tx threads value.", | 2246 | ugeth_err("%s: Bad number of Tx threads value.", |
2502 | __func__); | 2247 | __func__); |
2503 | ucc_geth_memclean(ugeth); | ||
2504 | return -EINVAL; | 2248 | return -EINVAL; |
2505 | break; | 2249 | break; |
2506 | } | 2250 | } |
@@ -2554,7 +2298,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) | |||
2554 | if (netif_msg_ifup(ugeth)) | 2298 | if (netif_msg_ifup(ugeth)) |
2555 | ugeth_err("%s: IPGIFG initialization parameter too large.", | 2299 | ugeth_err("%s: IPGIFG initialization parameter too large.", |
2556 | __func__); | 2300 | __func__); |
2557 | ucc_geth_memclean(ugeth); | ||
2558 | return ret_val; | 2301 | return ret_val; |
2559 | } | 2302 | } |
2560 | 2303 | ||
@@ -2572,7 +2315,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) | |||
2572 | if (netif_msg_ifup(ugeth)) | 2315 | if (netif_msg_ifup(ugeth)) |
2573 | ugeth_err("%s: Half Duplex initialization parameter too large.", | 2316 | ugeth_err("%s: Half Duplex initialization parameter too large.", |
2574 | __func__); | 2317 | __func__); |
2575 | ucc_geth_memclean(ugeth); | ||
2576 | return ret_val; | 2318 | return ret_val; |
2577 | } | 2319 | } |
2578 | 2320 | ||
@@ -2627,7 +2369,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) | |||
2627 | ugeth_err | 2369 | ugeth_err |
2628 | ("%s: Can not allocate memory for Tx bd rings.", | 2370 | ("%s: Can not allocate memory for Tx bd rings.", |
2629 | __func__); | 2371 | __func__); |
2630 | ucc_geth_memclean(ugeth); | ||
2631 | return -ENOMEM; | 2372 | return -ENOMEM; |
2632 | } | 2373 | } |
2633 | /* Zero unused end of bd ring, according to spec */ | 2374 | /* Zero unused end of bd ring, according to spec */ |
@@ -2663,7 +2404,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) | |||
2663 | ugeth_err | 2404 | ugeth_err |
2664 | ("%s: Can not allocate memory for Rx bd rings.", | 2405 | ("%s: Can not allocate memory for Rx bd rings.", |
2665 | __func__); | 2406 | __func__); |
2666 | ucc_geth_memclean(ugeth); | ||
2667 | return -ENOMEM; | 2407 | return -ENOMEM; |
2668 | } | 2408 | } |
2669 | } | 2409 | } |
@@ -2679,7 +2419,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) | |||
2679 | if (netif_msg_ifup(ugeth)) | 2419 | if (netif_msg_ifup(ugeth)) |
2680 | ugeth_err("%s: Could not allocate tx_skbuff", | 2420 | ugeth_err("%s: Could not allocate tx_skbuff", |
2681 | __func__); | 2421 | __func__); |
2682 | ucc_geth_memclean(ugeth); | ||
2683 | return -ENOMEM; | 2422 | return -ENOMEM; |
2684 | } | 2423 | } |
2685 | 2424 | ||
@@ -2711,7 +2450,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) | |||
2711 | if (netif_msg_ifup(ugeth)) | 2450 | if (netif_msg_ifup(ugeth)) |
2712 | ugeth_err("%s: Could not allocate rx_skbuff", | 2451 | ugeth_err("%s: Could not allocate rx_skbuff", |
2713 | __func__); | 2452 | __func__); |
2714 | ucc_geth_memclean(ugeth); | ||
2715 | return -ENOMEM; | 2453 | return -ENOMEM; |
2716 | } | 2454 | } |
2717 | 2455 | ||
@@ -2745,7 +2483,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) | |||
2745 | ugeth_err | 2483 | ugeth_err |
2746 | ("%s: Can not allocate DPRAM memory for p_tx_glbl_pram.", | 2484 | ("%s: Can not allocate DPRAM memory for p_tx_glbl_pram.", |
2747 | __func__); | 2485 | __func__); |
2748 | ucc_geth_memclean(ugeth); | ||
2749 | return -ENOMEM; | 2486 | return -ENOMEM; |
2750 | } | 2487 | } |
2751 | ugeth->p_tx_glbl_pram = | 2488 | ugeth->p_tx_glbl_pram = |
@@ -2768,7 +2505,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) | |||
2768 | ugeth_err | 2505 | ugeth_err |
2769 | ("%s: Can not allocate DPRAM memory for p_thread_data_tx.", | 2506 | ("%s: Can not allocate DPRAM memory for p_thread_data_tx.", |
2770 | __func__); | 2507 | __func__); |
2771 | ucc_geth_memclean(ugeth); | ||
2772 | return -ENOMEM; | 2508 | return -ENOMEM; |
2773 | } | 2509 | } |
2774 | 2510 | ||
@@ -2798,7 +2534,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) | |||
2798 | ugeth_err | 2534 | ugeth_err |
2799 | ("%s: Can not allocate DPRAM memory for p_send_q_mem_reg.", | 2535 | ("%s: Can not allocate DPRAM memory for p_send_q_mem_reg.", |
2800 | __func__); | 2536 | __func__); |
2801 | ucc_geth_memclean(ugeth); | ||
2802 | return -ENOMEM; | 2537 | return -ENOMEM; |
2803 | } | 2538 | } |
2804 | 2539 | ||
@@ -2842,7 +2577,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) | |||
2842 | ugeth_err | 2577 | ugeth_err |
2843 | ("%s: Can not allocate DPRAM memory for p_scheduler.", | 2578 | ("%s: Can not allocate DPRAM memory for p_scheduler.", |
2844 | __func__); | 2579 | __func__); |
2845 | ucc_geth_memclean(ugeth); | ||
2846 | return -ENOMEM; | 2580 | return -ENOMEM; |
2847 | } | 2581 | } |
2848 | 2582 | ||
@@ -2893,7 +2627,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) | |||
2893 | ("%s: Can not allocate DPRAM memory for" | 2627 | ("%s: Can not allocate DPRAM memory for" |
2894 | " p_tx_fw_statistics_pram.", | 2628 | " p_tx_fw_statistics_pram.", |
2895 | __func__); | 2629 | __func__); |
2896 | ucc_geth_memclean(ugeth); | ||
2897 | return -ENOMEM; | 2630 | return -ENOMEM; |
2898 | } | 2631 | } |
2899 | ugeth->p_tx_fw_statistics_pram = | 2632 | ugeth->p_tx_fw_statistics_pram = |
@@ -2933,7 +2666,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) | |||
2933 | ugeth_err | 2666 | ugeth_err |
2934 | ("%s: Can not allocate DPRAM memory for p_rx_glbl_pram.", | 2667 | ("%s: Can not allocate DPRAM memory for p_rx_glbl_pram.", |
2935 | __func__); | 2668 | __func__); |
2936 | ucc_geth_memclean(ugeth); | ||
2937 | return -ENOMEM; | 2669 | return -ENOMEM; |
2938 | } | 2670 | } |
2939 | ugeth->p_rx_glbl_pram = | 2671 | ugeth->p_rx_glbl_pram = |
@@ -2955,7 +2687,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) | |||
2955 | ugeth_err | 2687 | ugeth_err |
2956 | ("%s: Can not allocate DPRAM memory for p_thread_data_rx.", | 2688 | ("%s: Can not allocate DPRAM memory for p_thread_data_rx.", |
2957 | __func__); | 2689 | __func__); |
2958 | ucc_geth_memclean(ugeth); | ||
2959 | return -ENOMEM; | 2690 | return -ENOMEM; |
2960 | } | 2691 | } |
2961 | 2692 | ||
@@ -2979,7 +2710,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) | |||
2979 | ugeth_err | 2710 | ugeth_err |
2980 | ("%s: Can not allocate DPRAM memory for" | 2711 | ("%s: Can not allocate DPRAM memory for" |
2981 | " p_rx_fw_statistics_pram.", __func__); | 2712 | " p_rx_fw_statistics_pram.", __func__); |
2982 | ucc_geth_memclean(ugeth); | ||
2983 | return -ENOMEM; | 2713 | return -ENOMEM; |
2984 | } | 2714 | } |
2985 | ugeth->p_rx_fw_statistics_pram = | 2715 | ugeth->p_rx_fw_statistics_pram = |
@@ -3002,7 +2732,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) | |||
3002 | ugeth_err | 2732 | ugeth_err |
3003 | ("%s: Can not allocate DPRAM memory for" | 2733 | ("%s: Can not allocate DPRAM memory for" |
3004 | " p_rx_irq_coalescing_tbl.", __func__); | 2734 | " p_rx_irq_coalescing_tbl.", __func__); |
3005 | ucc_geth_memclean(ugeth); | ||
3006 | return -ENOMEM; | 2735 | return -ENOMEM; |
3007 | } | 2736 | } |
3008 | 2737 | ||
@@ -3071,7 +2800,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) | |||
3071 | ugeth_err | 2800 | ugeth_err |
3072 | ("%s: Can not allocate DPRAM memory for p_rx_bd_qs_tbl.", | 2801 | ("%s: Can not allocate DPRAM memory for p_rx_bd_qs_tbl.", |
3073 | __func__); | 2802 | __func__); |
3074 | ucc_geth_memclean(ugeth); | ||
3075 | return -ENOMEM; | 2803 | return -ENOMEM; |
3076 | } | 2804 | } |
3077 | 2805 | ||
@@ -3148,7 +2876,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) | |||
3148 | if (netif_msg_ifup(ugeth)) | 2876 | if (netif_msg_ifup(ugeth)) |
3149 | ugeth_err("%s: Null Extended Filtering Chain Pointer.", | 2877 | ugeth_err("%s: Null Extended Filtering Chain Pointer.", |
3150 | __func__); | 2878 | __func__); |
3151 | ucc_geth_memclean(ugeth); | ||
3152 | return -EINVAL; | 2879 | return -EINVAL; |
3153 | } | 2880 | } |
3154 | 2881 | ||
@@ -3162,7 +2889,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) | |||
3162 | ugeth_err | 2889 | ugeth_err |
3163 | ("%s: Can not allocate DPRAM memory for" | 2890 | ("%s: Can not allocate DPRAM memory for" |
3164 | " p_exf_glbl_param.", __func__); | 2891 | " p_exf_glbl_param.", __func__); |
3165 | ucc_geth_memclean(ugeth); | ||
3166 | return -ENOMEM; | 2892 | return -ENOMEM; |
3167 | } | 2893 | } |
3168 | 2894 | ||
@@ -3210,7 +2936,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) | |||
3210 | ugeth_err | 2936 | ugeth_err |
3211 | ("%s: Can not allocate memory for" | 2937 | ("%s: Can not allocate memory for" |
3212 | " p_UccInitEnetParamShadows.", __func__); | 2938 | " p_UccInitEnetParamShadows.", __func__); |
3213 | ucc_geth_memclean(ugeth); | ||
3214 | return -ENOMEM; | 2939 | return -ENOMEM; |
3215 | } | 2940 | } |
3216 | /* Zero out *p_init_enet_param_shadow */ | 2941 | /* Zero out *p_init_enet_param_shadow */ |
@@ -3245,7 +2970,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) | |||
3245 | if (netif_msg_ifup(ugeth)) | 2970 | if (netif_msg_ifup(ugeth)) |
3246 | ugeth_err("%s: Invalid largest External Lookup Key Size.", | 2971 | ugeth_err("%s: Invalid largest External Lookup Key Size.", |
3247 | __func__); | 2972 | __func__); |
3248 | ucc_geth_memclean(ugeth); | ||
3249 | return -EINVAL; | 2973 | return -EINVAL; |
3250 | } | 2974 | } |
3251 | ugeth->p_init_enet_param_shadow->largestexternallookupkeysize = | 2975 | ugeth->p_init_enet_param_shadow->largestexternallookupkeysize = |
@@ -3272,7 +2996,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) | |||
3272 | if (netif_msg_ifup(ugeth)) | 2996 | if (netif_msg_ifup(ugeth)) |
3273 | ugeth_err("%s: Can not fill p_init_enet_param_shadow.", | 2997 | ugeth_err("%s: Can not fill p_init_enet_param_shadow.", |
3274 | __func__); | 2998 | __func__); |
3275 | ucc_geth_memclean(ugeth); | ||
3276 | return ret_val; | 2999 | return ret_val; |
3277 | } | 3000 | } |
3278 | 3001 | ||
@@ -3288,7 +3011,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) | |||
3288 | if (netif_msg_ifup(ugeth)) | 3011 | if (netif_msg_ifup(ugeth)) |
3289 | ugeth_err("%s: Can not fill p_init_enet_param_shadow.", | 3012 | ugeth_err("%s: Can not fill p_init_enet_param_shadow.", |
3290 | __func__); | 3013 | __func__); |
3291 | ucc_geth_memclean(ugeth); | ||
3292 | return ret_val; | 3014 | return ret_val; |
3293 | } | 3015 | } |
3294 | 3016 | ||
@@ -3298,7 +3020,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) | |||
3298 | if (netif_msg_ifup(ugeth)) | 3020 | if (netif_msg_ifup(ugeth)) |
3299 | ugeth_err("%s: Can not fill Rx bds with buffers.", | 3021 | ugeth_err("%s: Can not fill Rx bds with buffers.", |
3300 | __func__); | 3022 | __func__); |
3301 | ucc_geth_memclean(ugeth); | ||
3302 | return ret_val; | 3023 | return ret_val; |
3303 | } | 3024 | } |
3304 | } | 3025 | } |
@@ -3310,7 +3031,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) | |||
3310 | ugeth_err | 3031 | ugeth_err |
3311 | ("%s: Can not allocate DPRAM memory for p_init_enet_pram.", | 3032 | ("%s: Can not allocate DPRAM memory for p_init_enet_pram.", |
3312 | __func__); | 3033 | __func__); |
3313 | ucc_geth_memclean(ugeth); | ||
3314 | return -ENOMEM; | 3034 | return -ENOMEM; |
3315 | } | 3035 | } |
3316 | p_init_enet_pram = | 3036 | p_init_enet_pram = |
@@ -3352,28 +3072,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) | |||
3352 | return 0; | 3072 | return 0; |
3353 | } | 3073 | } |
3354 | 3074 | ||
3355 | /* ucc_geth_timeout gets called when a packet has not been | ||
3356 | * transmitted after a set amount of time. | ||
3357 | * For now, assume that clearing out all the structures, and | ||
3358 | * starting over will fix the problem. */ | ||
3359 | static void ucc_geth_timeout(struct net_device *dev) | ||
3360 | { | ||
3361 | struct ucc_geth_private *ugeth = netdev_priv(dev); | ||
3362 | |||
3363 | ugeth_vdbg("%s: IN", __func__); | ||
3364 | |||
3365 | dev->stats.tx_errors++; | ||
3366 | |||
3367 | ugeth_dump_regs(ugeth); | ||
3368 | |||
3369 | if (dev->flags & IFF_UP) { | ||
3370 | ucc_geth_stop(ugeth); | ||
3371 | ucc_geth_startup(ugeth); | ||
3372 | } | ||
3373 | |||
3374 | netif_tx_schedule_all(dev); | ||
3375 | } | ||
3376 | |||
3377 | /* This is called by the kernel when a frame is ready for transmission. */ | 3075 | /* This is called by the kernel when a frame is ready for transmission. */ |
3378 | /* It is pointed to by the dev->hard_start_xmit function pointer */ | 3076 | /* It is pointed to by the dev->hard_start_xmit function pointer */ |
3379 | static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev) | 3077 | static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev) |
@@ -3502,8 +3200,6 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit | |||
3502 | netif_receive_skb(skb); | 3200 | netif_receive_skb(skb); |
3503 | } | 3201 | } |
3504 | 3202 | ||
3505 | ugeth->dev->last_rx = jiffies; | ||
3506 | |||
3507 | skb = get_new_skb(ugeth, bd); | 3203 | skb = get_new_skb(ugeth, bd); |
3508 | if (!skb) { | 3204 | if (!skb) { |
3509 | if (netif_msg_rx_err(ugeth)) | 3205 | if (netif_msg_rx_err(ugeth)) |
@@ -3592,7 +3288,7 @@ static int ucc_geth_poll(struct napi_struct *napi, int budget) | |||
3592 | struct ucc_fast_private *uccf; | 3288 | struct ucc_fast_private *uccf; |
3593 | u32 uccm; | 3289 | u32 uccm; |
3594 | 3290 | ||
3595 | netif_rx_complete(dev, napi); | 3291 | netif_rx_complete(napi); |
3596 | uccf = ugeth->uccf; | 3292 | uccf = ugeth->uccf; |
3597 | uccm = in_be32(uccf->p_uccm); | 3293 | uccm = in_be32(uccf->p_uccm); |
3598 | uccm |= UCCE_RX_EVENTS; | 3294 | uccm |= UCCE_RX_EVENTS; |
@@ -3626,10 +3322,10 @@ static irqreturn_t ucc_geth_irq_handler(int irq, void *info) | |||
3626 | 3322 | ||
3627 | /* check for receive events that require processing */ | 3323 | /* check for receive events that require processing */ |
3628 | if (ucce & UCCE_RX_EVENTS) { | 3324 | if (ucce & UCCE_RX_EVENTS) { |
3629 | if (netif_rx_schedule_prep(dev, &ugeth->napi)) { | 3325 | if (netif_rx_schedule_prep(&ugeth->napi)) { |
3630 | uccm &= ~UCCE_RX_EVENTS; | 3326 | uccm &= ~UCCE_RX_EVENTS; |
3631 | out_be32(uccf->p_uccm, uccm); | 3327 | out_be32(uccf->p_uccm, uccm); |
3632 | __netif_rx_schedule(dev, &ugeth->napi); | 3328 | __netif_rx_schedule(&ugeth->napi); |
3633 | } | 3329 | } |
3634 | } | 3330 | } |
3635 | 3331 | ||
@@ -3697,7 +3393,7 @@ static int ucc_geth_open(struct net_device *dev) | |||
3697 | if (err) { | 3393 | if (err) { |
3698 | if (netif_msg_ifup(ugeth)) | 3394 | if (netif_msg_ifup(ugeth)) |
3699 | ugeth_err("%s: Cannot configure internal struct, aborting.", dev->name); | 3395 | ugeth_err("%s: Cannot configure internal struct, aborting.", dev->name); |
3700 | return err; | 3396 | goto out_err_stop; |
3701 | } | 3397 | } |
3702 | 3398 | ||
3703 | napi_enable(&ugeth->napi); | 3399 | napi_enable(&ugeth->napi); |
@@ -3738,22 +3434,19 @@ static int ucc_geth_open(struct net_device *dev) | |||
3738 | 3434 | ||
3739 | phy_start(ugeth->phydev); | 3435 | phy_start(ugeth->phydev); |
3740 | 3436 | ||
3741 | err = | 3437 | err = ugeth_enable(ugeth, COMM_DIR_RX_AND_TX); |
3742 | request_irq(ugeth->ug_info->uf_info.irq, ucc_geth_irq_handler, 0, | ||
3743 | "UCC Geth", dev); | ||
3744 | if (err) { | 3438 | if (err) { |
3745 | if (netif_msg_ifup(ugeth)) | 3439 | if (netif_msg_ifup(ugeth)) |
3746 | ugeth_err("%s: Cannot get IRQ for net device, aborting.", | 3440 | ugeth_err("%s: Cannot enable net device, aborting.", dev->name); |
3747 | dev->name); | ||
3748 | ucc_geth_stop(ugeth); | ||
3749 | goto out_err; | 3441 | goto out_err; |
3750 | } | 3442 | } |
3751 | 3443 | ||
3752 | err = ugeth_enable(ugeth, COMM_DIR_RX_AND_TX); | 3444 | err = request_irq(ugeth->ug_info->uf_info.irq, ucc_geth_irq_handler, |
3445 | 0, "UCC Geth", dev); | ||
3753 | if (err) { | 3446 | if (err) { |
3754 | if (netif_msg_ifup(ugeth)) | 3447 | if (netif_msg_ifup(ugeth)) |
3755 | ugeth_err("%s: Cannot enable net device, aborting.", dev->name); | 3448 | ugeth_err("%s: Cannot get IRQ for net device, aborting.", |
3756 | ucc_geth_stop(ugeth); | 3449 | dev->name); |
3757 | goto out_err; | 3450 | goto out_err; |
3758 | } | 3451 | } |
3759 | 3452 | ||
@@ -3763,7 +3456,8 @@ static int ucc_geth_open(struct net_device *dev) | |||
3763 | 3456 | ||
3764 | out_err: | 3457 | out_err: |
3765 | napi_disable(&ugeth->napi); | 3458 | napi_disable(&ugeth->napi); |
3766 | 3459 | out_err_stop: | |
3460 | ucc_geth_stop(ugeth); | ||
3767 | return err; | 3461 | return err; |
3768 | } | 3462 | } |
3769 | 3463 | ||
@@ -3778,6 +3472,8 @@ static int ucc_geth_close(struct net_device *dev) | |||
3778 | 3472 | ||
3779 | ucc_geth_stop(ugeth); | 3473 | ucc_geth_stop(ugeth); |
3780 | 3474 | ||
3475 | free_irq(ugeth->ug_info->uf_info.irq, ugeth->dev); | ||
3476 | |||
3781 | phy_disconnect(ugeth->phydev); | 3477 | phy_disconnect(ugeth->phydev); |
3782 | ugeth->phydev = NULL; | 3478 | ugeth->phydev = NULL; |
3783 | 3479 | ||
@@ -3786,6 +3482,45 @@ static int ucc_geth_close(struct net_device *dev) | |||
3786 | return 0; | 3482 | return 0; |
3787 | } | 3483 | } |
3788 | 3484 | ||
3485 | /* Reopen device. This will reset the MAC and PHY. */ | ||
3486 | static void ucc_geth_timeout_work(struct work_struct *work) | ||
3487 | { | ||
3488 | struct ucc_geth_private *ugeth; | ||
3489 | struct net_device *dev; | ||
3490 | |||
3491 | ugeth = container_of(work, struct ucc_geth_private, timeout_work); | ||
3492 | dev = ugeth->dev; | ||
3493 | |||
3494 | ugeth_vdbg("%s: IN", __func__); | ||
3495 | |||
3496 | dev->stats.tx_errors++; | ||
3497 | |||
3498 | ugeth_dump_regs(ugeth); | ||
3499 | |||
3500 | if (dev->flags & IFF_UP) { | ||
3501 | /* | ||
3502 | * Must reset MAC *and* PHY. This is done by reopening | ||
3503 | * the device. | ||
3504 | */ | ||
3505 | ucc_geth_close(dev); | ||
3506 | ucc_geth_open(dev); | ||
3507 | } | ||
3508 | |||
3509 | netif_tx_schedule_all(dev); | ||
3510 | } | ||
3511 | |||
3512 | /* | ||
3513 | * ucc_geth_timeout gets called when a packet has not been | ||
3514 | * transmitted after a set amount of time. | ||
3515 | */ | ||
3516 | static void ucc_geth_timeout(struct net_device *dev) | ||
3517 | { | ||
3518 | struct ucc_geth_private *ugeth = netdev_priv(dev); | ||
3519 | |||
3520 | netif_carrier_off(dev); | ||
3521 | schedule_work(&ugeth->timeout_work); | ||
3522 | } | ||
3523 | |||
3789 | static phy_interface_t to_phy_interface(const char *phy_connection_type) | 3524 | static phy_interface_t to_phy_interface(const char *phy_connection_type) |
3790 | { | 3525 | { |
3791 | if (strcasecmp(phy_connection_type, "mii") == 0) | 3526 | if (strcasecmp(phy_connection_type, "mii") == 0) |
@@ -4026,6 +3761,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma | |||
4026 | dev->hard_start_xmit = ucc_geth_start_xmit; | 3761 | dev->hard_start_xmit = ucc_geth_start_xmit; |
4027 | dev->tx_timeout = ucc_geth_timeout; | 3762 | dev->tx_timeout = ucc_geth_timeout; |
4028 | dev->watchdog_timeo = TX_TIMEOUT; | 3763 | dev->watchdog_timeo = TX_TIMEOUT; |
3764 | INIT_WORK(&ugeth->timeout_work, ucc_geth_timeout_work); | ||
4029 | netif_napi_add(dev, &ugeth->napi, ucc_geth_poll, UCC_GETH_DEV_WEIGHT); | 3765 | netif_napi_add(dev, &ugeth->napi, ucc_geth_poll, UCC_GETH_DEV_WEIGHT); |
4030 | #ifdef CONFIG_NET_POLL_CONTROLLER | 3766 | #ifdef CONFIG_NET_POLL_CONTROLLER |
4031 | dev->poll_controller = ucc_netpoll; | 3767 | dev->poll_controller = ucc_netpoll; |