diff options
| -rw-r--r-- | drivers/net/stmmac/common.h | 4 | ||||
| -rw-r--r-- | drivers/net/stmmac/dwmac1000.h | 2 | ||||
| -rw-r--r-- | drivers/net/stmmac/dwmac1000_core.c | 13 | ||||
| -rw-r--r-- | drivers/net/stmmac/dwmac100_core.c | 6 | ||||
| -rw-r--r-- | drivers/net/stmmac/stmmac.h | 4 | ||||
| -rw-r--r-- | drivers/net/stmmac/stmmac_ethtool.c | 2 | ||||
| -rw-r--r-- | drivers/net/stmmac/stmmac_main.c | 66 | ||||
| -rw-r--r-- | include/linux/stmmac.h | 2 |
8 files changed, 60 insertions, 39 deletions
diff --git a/drivers/net/stmmac/common.h b/drivers/net/stmmac/common.h index e8cbcb5c206e..673ef86a063f 100644 --- a/drivers/net/stmmac/common.h +++ b/drivers/net/stmmac/common.h | |||
| @@ -102,8 +102,6 @@ struct stmmac_extra_stats { | |||
| 102 | 102 | ||
| 103 | #define SF_DMA_MODE 1 /* DMA STORE-AND-FORWARD Operation Mode */ | 103 | #define SF_DMA_MODE 1 /* DMA STORE-AND-FORWARD Operation Mode */ |
| 104 | 104 | ||
| 105 | #define HW_CSUM 1 | ||
| 106 | #define NO_HW_CSUM 0 | ||
| 107 | enum rx_frame_status { /* IPC status */ | 105 | enum rx_frame_status { /* IPC status */ |
| 108 | good_frame = 0, | 106 | good_frame = 0, |
| 109 | discard_frame = 1, | 107 | discard_frame = 1, |
| @@ -205,6 +203,8 @@ struct stmmac_dma_ops { | |||
| 205 | struct stmmac_ops { | 203 | struct stmmac_ops { |
| 206 | /* MAC core initialization */ | 204 | /* MAC core initialization */ |
| 207 | void (*core_init) (void __iomem *ioaddr) ____cacheline_aligned; | 205 | void (*core_init) (void __iomem *ioaddr) ____cacheline_aligned; |
| 206 | /* Support checksum offload engine */ | ||
| 207 | int (*rx_coe) (void __iomem *ioaddr); | ||
| 208 | /* Dump MAC registers */ | 208 | /* Dump MAC registers */ |
| 209 | void (*dump_regs) (void __iomem *ioaddr); | 209 | void (*dump_regs) (void __iomem *ioaddr); |
| 210 | /* Handle extra events on specific interrupts hw dependent */ | 210 | /* Handle extra events on specific interrupts hw dependent */ |
diff --git a/drivers/net/stmmac/dwmac1000.h b/drivers/net/stmmac/dwmac1000.h index 8b20b19971cb..81ee4fd04386 100644 --- a/drivers/net/stmmac/dwmac1000.h +++ b/drivers/net/stmmac/dwmac1000.h | |||
| @@ -99,7 +99,7 @@ enum inter_frame_gap { | |||
| 99 | #define GMAC_CONTROL_RE 0x00000004 /* Receiver Enable */ | 99 | #define GMAC_CONTROL_RE 0x00000004 /* Receiver Enable */ |
| 100 | 100 | ||
| 101 | #define GMAC_CORE_INIT (GMAC_CONTROL_JD | GMAC_CONTROL_PS | GMAC_CONTROL_ACS | \ | 101 | #define GMAC_CORE_INIT (GMAC_CONTROL_JD | GMAC_CONTROL_PS | GMAC_CONTROL_ACS | \ |
| 102 | GMAC_CONTROL_IPC | GMAC_CONTROL_JE | GMAC_CONTROL_BE) | 102 | GMAC_CONTROL_JE | GMAC_CONTROL_BE) |
| 103 | 103 | ||
| 104 | /* GMAC Frame Filter defines */ | 104 | /* GMAC Frame Filter defines */ |
| 105 | #define GMAC_FRAME_FILTER_PR 0x00000001 /* Promiscuous Mode */ | 105 | #define GMAC_FRAME_FILTER_PR 0x00000001 /* Promiscuous Mode */ |
diff --git a/drivers/net/stmmac/dwmac1000_core.c b/drivers/net/stmmac/dwmac1000_core.c index f1f426146f40..c18c85993179 100644 --- a/drivers/net/stmmac/dwmac1000_core.c +++ b/drivers/net/stmmac/dwmac1000_core.c | |||
| @@ -50,6 +50,18 @@ static void dwmac1000_core_init(void __iomem *ioaddr) | |||
| 50 | #endif | 50 | #endif |
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | static int dwmac1000_rx_coe_supported(void __iomem *ioaddr) | ||
| 54 | { | ||
| 55 | u32 value = readl(ioaddr + GMAC_CONTROL); | ||
| 56 | |||
| 57 | value |= GMAC_CONTROL_IPC; | ||
| 58 | writel(value, ioaddr + GMAC_CONTROL); | ||
| 59 | |||
| 60 | value = readl(ioaddr + GMAC_CONTROL); | ||
| 61 | |||
| 62 | return !!(value & GMAC_CONTROL_IPC); | ||
| 63 | } | ||
| 64 | |||
| 53 | static void dwmac1000_dump_regs(void __iomem *ioaddr) | 65 | static void dwmac1000_dump_regs(void __iomem *ioaddr) |
| 54 | { | 66 | { |
| 55 | int i; | 67 | int i; |
| @@ -202,6 +214,7 @@ static void dwmac1000_irq_status(void __iomem *ioaddr) | |||
| 202 | 214 | ||
| 203 | struct stmmac_ops dwmac1000_ops = { | 215 | struct stmmac_ops dwmac1000_ops = { |
| 204 | .core_init = dwmac1000_core_init, | 216 | .core_init = dwmac1000_core_init, |
| 217 | .rx_coe = dwmac1000_rx_coe_supported, | ||
| 205 | .dump_regs = dwmac1000_dump_regs, | 218 | .dump_regs = dwmac1000_dump_regs, |
| 206 | .host_irq_status = dwmac1000_irq_status, | 219 | .host_irq_status = dwmac1000_irq_status, |
| 207 | .set_filter = dwmac1000_set_filter, | 220 | .set_filter = dwmac1000_set_filter, |
diff --git a/drivers/net/stmmac/dwmac100_core.c b/drivers/net/stmmac/dwmac100_core.c index db06c04ce480..58a914b27003 100644 --- a/drivers/net/stmmac/dwmac100_core.c +++ b/drivers/net/stmmac/dwmac100_core.c | |||
| @@ -42,6 +42,11 @@ static void dwmac100_core_init(void __iomem *ioaddr) | |||
| 42 | #endif | 42 | #endif |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | static int dwmac100_rx_coe_supported(void __iomem *ioaddr) | ||
| 46 | { | ||
| 47 | return 0; | ||
| 48 | } | ||
| 49 | |||
| 45 | static void dwmac100_dump_mac_regs(void __iomem *ioaddr) | 50 | static void dwmac100_dump_mac_regs(void __iomem *ioaddr) |
| 46 | { | 51 | { |
| 47 | pr_info("\t----------------------------------------------\n" | 52 | pr_info("\t----------------------------------------------\n" |
| @@ -165,6 +170,7 @@ static void dwmac100_pmt(void __iomem *ioaddr, unsigned long mode) | |||
| 165 | 170 | ||
| 166 | struct stmmac_ops dwmac100_ops = { | 171 | struct stmmac_ops dwmac100_ops = { |
| 167 | .core_init = dwmac100_core_init, | 172 | .core_init = dwmac100_core_init, |
| 173 | .rx_coe = dwmac100_rx_coe_supported, | ||
| 168 | .dump_regs = dwmac100_dump_mac_regs, | 174 | .dump_regs = dwmac100_dump_mac_regs, |
| 169 | .host_irq_status = dwmac100_irq_status, | 175 | .host_irq_status = dwmac100_irq_status, |
| 170 | .set_filter = dwmac100_set_filter, | 176 | .set_filter = dwmac100_set_filter, |
diff --git a/drivers/net/stmmac/stmmac.h b/drivers/net/stmmac/stmmac.h index 12d1cb00c0d7..92154ff7d702 100644 --- a/drivers/net/stmmac/stmmac.h +++ b/drivers/net/stmmac/stmmac.h | |||
| @@ -51,7 +51,6 @@ struct stmmac_priv { | |||
| 51 | int is_gmac; | 51 | int is_gmac; |
| 52 | dma_addr_t dma_rx_phy; | 52 | dma_addr_t dma_rx_phy; |
| 53 | unsigned int dma_rx_size; | 53 | unsigned int dma_rx_size; |
| 54 | int rx_csum; | ||
| 55 | unsigned int dma_buf_sz; | 54 | unsigned int dma_buf_sz; |
| 56 | struct device *device; | 55 | struct device *device; |
| 57 | struct mac_device_info *hw; | 56 | struct mac_device_info *hw; |
| @@ -92,6 +91,9 @@ struct stmmac_priv { | |||
| 92 | struct vlan_group *vlgrp; | 91 | struct vlan_group *vlgrp; |
| 93 | #endif | 92 | #endif |
| 94 | int enh_desc; | 93 | int enh_desc; |
| 94 | int rx_coe; | ||
| 95 | int bugged_jumbo; | ||
| 96 | int no_csum_insertion; | ||
| 95 | }; | 97 | }; |
| 96 | 98 | ||
| 97 | #ifdef CONFIG_STM_DRIVERS | 99 | #ifdef CONFIG_STM_DRIVERS |
diff --git a/drivers/net/stmmac/stmmac_ethtool.c b/drivers/net/stmmac/stmmac_ethtool.c index 63b68e61afce..b32c16ae55c6 100644 --- a/drivers/net/stmmac/stmmac_ethtool.c +++ b/drivers/net/stmmac/stmmac_ethtool.c | |||
| @@ -209,7 +209,7 @@ u32 stmmac_ethtool_get_rx_csum(struct net_device *dev) | |||
| 209 | { | 209 | { |
| 210 | struct stmmac_priv *priv = netdev_priv(dev); | 210 | struct stmmac_priv *priv = netdev_priv(dev); |
| 211 | 211 | ||
| 212 | return priv->rx_csum; | 212 | return priv->rx_coe; |
| 213 | } | 213 | } |
| 214 | 214 | ||
| 215 | static void | 215 | static void |
diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c index a169b1441d50..a908f7201aae 100644 --- a/drivers/net/stmmac/stmmac_main.c +++ b/drivers/net/stmmac/stmmac_main.c | |||
| @@ -134,13 +134,6 @@ static int buf_sz = DMA_BUFFER_SIZE; | |||
| 134 | module_param(buf_sz, int, S_IRUGO | S_IWUSR); | 134 | module_param(buf_sz, int, S_IRUGO | S_IWUSR); |
| 135 | MODULE_PARM_DESC(buf_sz, "DMA buffer size"); | 135 | MODULE_PARM_DESC(buf_sz, "DMA buffer size"); |
| 136 | 136 | ||
| 137 | /* In case of Giga ETH, we can enable/disable the COE for the | ||
| 138 | * transmit HW checksum computation. | ||
| 139 | * Note that, if tx csum is off in HW, SG will be still supported. */ | ||
| 140 | static int tx_coe = HW_CSUM; | ||
| 141 | module_param(tx_coe, int, S_IRUGO | S_IWUSR); | ||
| 142 | MODULE_PARM_DESC(tx_coe, "GMAC COE type 2 [on/off]"); | ||
| 143 | |||
| 144 | static const u32 default_msg_level = (NETIF_MSG_DRV | NETIF_MSG_PROBE | | 137 | static const u32 default_msg_level = (NETIF_MSG_DRV | NETIF_MSG_PROBE | |
| 145 | NETIF_MSG_LINK | NETIF_MSG_IFUP | | 138 | NETIF_MSG_LINK | NETIF_MSG_IFUP | |
| 146 | NETIF_MSG_IFDOWN | NETIF_MSG_TIMER); | 139 | NETIF_MSG_IFDOWN | NETIF_MSG_TIMER); |
| @@ -569,29 +562,22 @@ static void free_dma_desc_resources(struct stmmac_priv *priv) | |||
| 569 | * stmmac_dma_operation_mode - HW DMA operation mode | 562 | * stmmac_dma_operation_mode - HW DMA operation mode |
| 570 | * @priv : pointer to the private device structure. | 563 | * @priv : pointer to the private device structure. |
| 571 | * Description: it sets the DMA operation mode: tx/rx DMA thresholds | 564 | * Description: it sets the DMA operation mode: tx/rx DMA thresholds |
| 572 | * or Store-And-Forward capability. It also verifies the COE for the | 565 | * or Store-And-Forward capability. |
| 573 | * transmission in case of Giga ETH. | ||
| 574 | */ | 566 | */ |
| 575 | static void stmmac_dma_operation_mode(struct stmmac_priv *priv) | 567 | static void stmmac_dma_operation_mode(struct stmmac_priv *priv) |
| 576 | { | 568 | { |
| 577 | if (!priv->is_gmac) { | 569 | if (likely((priv->tx_coe) && (!priv->no_csum_insertion))) { |
| 578 | /* MAC 10/100 */ | 570 | /* In case of GMAC, SF mode has to be enabled |
| 579 | priv->hw->dma->dma_mode(priv->ioaddr, tc, 0); | 571 | * to perform the TX COE. This depends on: |
| 580 | priv->tx_coe = NO_HW_CSUM; | 572 | * 1) TX COE if actually supported |
| 581 | } else { | 573 | * 2) There is no bugged Jumbo frame support |
| 582 | if ((priv->dev->mtu <= ETH_DATA_LEN) && (tx_coe)) { | 574 | * that needs to not insert csum in the TDES. |
| 583 | priv->hw->dma->dma_mode(priv->ioaddr, | 575 | */ |
| 584 | SF_DMA_MODE, SF_DMA_MODE); | 576 | priv->hw->dma->dma_mode(priv->ioaddr, |
| 585 | tc = SF_DMA_MODE; | 577 | SF_DMA_MODE, SF_DMA_MODE); |
| 586 | priv->tx_coe = HW_CSUM; | 578 | tc = SF_DMA_MODE; |
| 587 | } else { | 579 | } else |
| 588 | /* Checksum computation is performed in software. */ | 580 | priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE); |
| 589 | priv->hw->dma->dma_mode(priv->ioaddr, tc, | ||
| 590 | SF_DMA_MODE); | ||
| 591 | priv->tx_coe = NO_HW_CSUM; | ||
| 592 | } | ||
| 593 | } | ||
| 594 | tx_coe = priv->tx_coe; | ||
| 595 | } | 581 | } |
| 596 | 582 | ||
| 597 | /** | 583 | /** |
| @@ -858,6 +844,12 @@ static int stmmac_open(struct net_device *dev) | |||
| 858 | /* Initialize the MAC Core */ | 844 | /* Initialize the MAC Core */ |
| 859 | priv->hw->mac->core_init(priv->ioaddr); | 845 | priv->hw->mac->core_init(priv->ioaddr); |
| 860 | 846 | ||
| 847 | priv->rx_coe = priv->hw->mac->rx_coe(priv->ioaddr); | ||
| 848 | if (priv->rx_coe) | ||
| 849 | pr_info("stmmac: Rx Checksum Offload Engine supported\n"); | ||
| 850 | if (priv->tx_coe) | ||
| 851 | pr_info("\tTX Checksum insertion supported\n"); | ||
| 852 | |||
| 861 | priv->shutdown = 0; | 853 | priv->shutdown = 0; |
| 862 | 854 | ||
| 863 | /* Initialise the MMC (if present) to disable all interrupts. */ | 855 | /* Initialise the MMC (if present) to disable all interrupts. */ |
| @@ -1066,7 +1058,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 1066 | return stmmac_sw_tso(priv, skb); | 1058 | return stmmac_sw_tso(priv, skb); |
| 1067 | 1059 | ||
| 1068 | if (likely((skb->ip_summed == CHECKSUM_PARTIAL))) { | 1060 | if (likely((skb->ip_summed == CHECKSUM_PARTIAL))) { |
| 1069 | if (likely(priv->tx_coe == NO_HW_CSUM)) | 1061 | if (unlikely((!priv->tx_coe) || (priv->no_csum_insertion))) |
| 1070 | skb_checksum_help(skb); | 1062 | skb_checksum_help(skb); |
| 1071 | else | 1063 | else |
| 1072 | csum_insertion = 1; | 1064 | csum_insertion = 1; |
| @@ -1390,6 +1382,15 @@ static int stmmac_change_mtu(struct net_device *dev, int new_mtu) | |||
| 1390 | return -EINVAL; | 1382 | return -EINVAL; |
| 1391 | } | 1383 | } |
| 1392 | 1384 | ||
| 1385 | /* Some GMAC devices have a bugged Jumbo frame support that | ||
| 1386 | * needs to have the Tx COE disabled for oversized frames | ||
| 1387 | * (due to limited buffer sizes). In this case we disable | ||
| 1388 | * the TX csum insertionin the TDES and not use SF. */ | ||
| 1389 | if ((priv->bugged_jumbo) && (priv->dev->mtu > ETH_DATA_LEN)) | ||
| 1390 | priv->no_csum_insertion = 1; | ||
| 1391 | else | ||
| 1392 | priv->no_csum_insertion = 0; | ||
| 1393 | |||
| 1393 | dev->mtu = new_mtu; | 1394 | dev->mtu = new_mtu; |
| 1394 | 1395 | ||
| 1395 | return 0; | 1396 | return 0; |
| @@ -1510,9 +1511,6 @@ static int stmmac_probe(struct net_device *dev) | |||
| 1510 | #endif | 1511 | #endif |
| 1511 | priv->msg_enable = netif_msg_init(debug, default_msg_level); | 1512 | priv->msg_enable = netif_msg_init(debug, default_msg_level); |
| 1512 | 1513 | ||
| 1513 | if (priv->is_gmac) | ||
| 1514 | priv->rx_csum = 1; | ||
| 1515 | |||
| 1516 | if (flow_ctrl) | 1514 | if (flow_ctrl) |
| 1517 | priv->flow_ctrl = FLOW_AUTO; /* RX/TX pause on */ | 1515 | priv->flow_ctrl = FLOW_AUTO; /* RX/TX pause on */ |
| 1518 | 1516 | ||
| @@ -1662,7 +1660,7 @@ static int stmmac_dvr_probe(struct platform_device *pdev) | |||
| 1662 | ret = -ENODEV; | 1660 | ret = -ENODEV; |
| 1663 | goto out; | 1661 | goto out; |
| 1664 | } | 1662 | } |
| 1665 | pr_info("done!\n"); | 1663 | pr_info("\tdone!\n"); |
| 1666 | 1664 | ||
| 1667 | if (!request_mem_region(res->start, resource_size(res), | 1665 | if (!request_mem_region(res->start, resource_size(res), |
| 1668 | pdev->name)) { | 1666 | pdev->name)) { |
| @@ -1705,6 +1703,8 @@ static int stmmac_dvr_probe(struct platform_device *pdev) | |||
| 1705 | priv->bus_id = plat_dat->bus_id; | 1703 | priv->bus_id = plat_dat->bus_id; |
| 1706 | priv->pbl = plat_dat->pbl; /* TLI */ | 1704 | priv->pbl = plat_dat->pbl; /* TLI */ |
| 1707 | priv->mii_clk_csr = plat_dat->clk_csr; | 1705 | priv->mii_clk_csr = plat_dat->clk_csr; |
| 1706 | priv->tx_coe = plat_dat->tx_coe; | ||
| 1707 | priv->bugged_jumbo = plat_dat->bugged_jumbo; | ||
| 1708 | priv->is_gmac = plat_dat->has_gmac; /* GMAC is on board */ | 1708 | priv->is_gmac = plat_dat->has_gmac; /* GMAC is on board */ |
| 1709 | priv->enh_desc = plat_dat->enh_desc; | 1709 | priv->enh_desc = plat_dat->enh_desc; |
| 1710 | priv->ioaddr = addr; | 1710 | priv->ioaddr = addr; |
| @@ -1966,8 +1966,6 @@ static int __init stmmac_cmdline_opt(char *str) | |||
| 1966 | strict_strtoul(opt + 7, 0, (unsigned long *)&buf_sz); | 1966 | strict_strtoul(opt + 7, 0, (unsigned long *)&buf_sz); |
| 1967 | else if (!strncmp(opt, "tc:", 3)) | 1967 | else if (!strncmp(opt, "tc:", 3)) |
| 1968 | strict_strtoul(opt + 3, 0, (unsigned long *)&tc); | 1968 | strict_strtoul(opt + 3, 0, (unsigned long *)&tc); |
| 1969 | else if (!strncmp(opt, "tx_coe:", 7)) | ||
| 1970 | strict_strtoul(opt + 7, 0, (unsigned long *)&tx_coe); | ||
| 1971 | else if (!strncmp(opt, "watchdog:", 9)) | 1969 | else if (!strncmp(opt, "watchdog:", 9)) |
| 1972 | strict_strtoul(opt + 9, 0, (unsigned long *)&watchdog); | 1970 | strict_strtoul(opt + 9, 0, (unsigned long *)&watchdog); |
| 1973 | else if (!strncmp(opt, "flow_ctrl:", 10)) | 1971 | else if (!strncmp(opt, "flow_ctrl:", 10)) |
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h index c87c88ccffc0..1d8baf719211 100644 --- a/include/linux/stmmac.h +++ b/include/linux/stmmac.h | |||
| @@ -35,6 +35,8 @@ struct plat_stmmacenet_data { | |||
| 35 | int clk_csr; | 35 | int clk_csr; |
| 36 | int has_gmac; | 36 | int has_gmac; |
| 37 | int enh_desc; | 37 | int enh_desc; |
| 38 | int tx_coe; | ||
| 39 | int bugged_jumbo; | ||
| 38 | void (*fix_mac_speed)(void *priv, unsigned int speed); | 40 | void (*fix_mac_speed)(void *priv, unsigned int speed); |
| 39 | void (*bus_setup)(void __iomem *ioaddr); | 41 | void (*bus_setup)(void __iomem *ioaddr); |
| 40 | #ifdef CONFIG_STM_DRIVERS | 42 | #ifdef CONFIG_STM_DRIVERS |
