[PATCH] net: netcp: fix unused interface rx buffer size configuration
Prior to this patch, rx buffer size for each rx queue of an interface is configurable through dts bindings. But for an interface, the first rx queue's rx buffer size is always the usual MTU size (plus usual overhead) and page size for the remaining rx queues (if they are enabled by specifying a non-zero rx queue depth dts binding of the corresponding interface). This patch removes the rx buffer size configuration capability. Signed-off-by: WingMan Kwok w-kw...@ti.com --- drivers/net/ethernet/ti/netcp.h |1 - drivers/net/ethernet/ti/netcp_core.c | 35 +- 2 files changed, 13 insertions(+), 23 deletions(-) diff --git a/drivers/net/ethernet/ti/netcp.h b/drivers/net/ethernet/ti/netcp.h index a8a7306..bb1bb72 100644 --- a/drivers/net/ethernet/ti/netcp.h +++ b/drivers/net/ethernet/ti/netcp.h @@ -85,7 +85,6 @@ struct netcp_intf { struct list_headrxhook_list_head; unsigned intrx_queue_id; void*rx_fdq[KNAV_DMA_FDQ_PER_CHAN]; - u32 rx_buffer_sizes[KNAV_DMA_FDQ_PER_CHAN]; struct napi_struct rx_napi; struct napi_struct tx_napi; diff --git a/drivers/net/ethernet/ti/netcp_core.c b/drivers/net/ethernet/ti/netcp_core.c index 9749dfd..4755838 100644 --- a/drivers/net/ethernet/ti/netcp_core.c +++ b/drivers/net/ethernet/ti/netcp_core.c @@ -34,6 +34,7 @@ #define NETCP_SOP_OFFSET (NET_IP_ALIGN + NET_SKB_PAD) #define NETCP_NAPI_WEIGHT 64 #define NETCP_TX_TIMEOUT (5 * HZ) +#define NETCP_PACKET_SIZE (ETH_FRAME_LEN + ETH_FCS_LEN) #define NETCP_MIN_PACKET_SIZE ETH_ZLEN #define NETCP_MAX_MCAST_ADDR 16 @@ -804,30 +805,28 @@ static void netcp_allocate_rx_buf(struct netcp_intf *netcp, int fdq) if (likely(fdq == 0)) { unsigned int primary_buf_len; /* Allocate a primary receive queue entry */ - buf_len = netcp-rx_buffer_sizes[0] + NETCP_SOP_OFFSET; + buf_len = NETCP_PACKET_SIZE + NETCP_SOP_OFFSET; primary_buf_len = SKB_DATA_ALIGN(buf_len) + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); - if (primary_buf_len = PAGE_SIZE) { - bufptr = netdev_alloc_frag(primary_buf_len); - pad[1] = primary_buf_len; - } else { - bufptr = kmalloc(primary_buf_len, GFP_ATOMIC | -GFP_DMA32 | __GFP_COLD); - pad[1] = 0; - } + bufptr = netdev_alloc_frag(primary_buf_len); + pad[1] = primary_buf_len; if (unlikely(!bufptr)) { - dev_warn_ratelimited(netcp-ndev_dev, Primary RX buffer alloc failed\n); + dev_warn_ratelimited(netcp-ndev_dev, +Primary RX buffer alloc failed\n); goto fail; } dma = dma_map_single(netcp-dev, bufptr, buf_len, DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(netcp-dev, dma))) + goto fail; + pad[0] = (u32)bufptr; } else { /* Allocate a secondary receive queue entry */ - page = alloc_page(GFP_ATOMIC | GFP_DMA32 | __GFP_COLD); + page = alloc_page(GFP_ATOMIC | GFP_DMA | __GFP_COLD); if (unlikely(!page)) { dev_warn_ratelimited(netcp-ndev_dev, Secondary page alloc failed\n); goto fail; @@ -1010,7 +1009,7 @@ netcp_tx_map_skb(struct sk_buff *skb, struct netcp_intf *netcp) /* Map the linear buffer */ dma_addr = dma_map_single(dev, skb-data, pkt_len, DMA_TO_DEVICE); - if (unlikely(!dma_addr)) { + if (unlikely(dma_mapping_error(dev, dma_addr))) { dev_err(netcp-ndev_dev, Failed to map skb buffer\n); return NULL; } @@ -1546,8 +1545,8 @@ static int netcp_setup_navigator_resources(struct net_device *ndev) knav_queue_disable_notify(netcp-rx_queue); /* open Rx FDQs */ - for (i = 0; i KNAV_DMA_FDQ_PER_CHAN -netcp-rx_queue_depths[i] netcp-rx_buffer_sizes[i]; ++i) { + for (i = 0; i KNAV_DMA_FDQ_PER_CHAN netcp-rx_queue_depths[i]; +++i) { snprintf(name, sizeof(name), rx-fdq-%s-%d, ndev-name, i); netcp-rx_fdq[i] = knav_queue_open(name, KNAV_QUEUE_GP, 0); if (IS_ERR_OR_NULL(netcp-rx_fdq[i])) { @@ -1941,14 +1940,6 @@ static int netcp_create_interface(struct netcp_device *netcp_device, netcp-rx_queue_depths[0] = 128; } - ret = of_property_read_u32_array(node_interface, rx-buffer-size, -netcp-rx_buffer_sizes
[PATCH 2/2] net: netcp: Allocate RX packet buffers using __GFP_DMA
The Keystone II DMA hardware can only access addresses in the lower 2 GiB of SDRAM. This patch makes sure the RX buffers are allocated using the __GFP_DMA flag so they meet this requirement. Signed-off-by: WingMan Kwok w-kw...@ti.com Signed-off-by: Reece R. Pollack x0183...@ti.com --- drivers/net/ethernet/ti/netcp_core.c | 11 +++ 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/ti/netcp_core.c b/drivers/net/ethernet/ti/netcp_core.c index 2d07701..39c68df 100644 --- a/drivers/net/ethernet/ti/netcp_core.c +++ b/drivers/net/ethernet/ti/netcp_core.c @@ -820,11 +820,13 @@ static void netcp_allocate_rx_buf(struct netcp_intf *netcp, int fdq) SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); if (primary_buf_len = PAGE_SIZE) { - bufptr = netdev_alloc_frag(primary_buf_len); + bufptr = __netdev_alloc_frag(primary_buf_len, +GFP_ATOMIC | __GFP_COLD | +__GFP_DMA); pad[1] = primary_buf_len; } else { bufptr = kmalloc(primary_buf_len, GFP_ATOMIC | -GFP_DMA32 | __GFP_COLD); +__GFP_COLD | __GFP_DMA); pad[1] = 0; } @@ -838,9 +840,10 @@ static void netcp_allocate_rx_buf(struct netcp_intf *netcp, int fdq) } else { /* Allocate a secondary receive queue entry */ - page = alloc_page(GFP_ATOMIC | GFP_DMA32 | __GFP_COLD); + page = alloc_page(GFP_ATOMIC | __GFP_COLD | __GFP_DMA); if (unlikely(!page)) { - dev_warn_ratelimited(netcp-ndev_dev, Secondary page alloc failed\n); + dev_warn_ratelimited(netcp-ndev_dev, +Secondary page alloc failed\n); goto fail; } buf_len = PAGE_SIZE; -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/2] net: Export __netdev_alloc_frag() to allow gfp_mask flags
This patch makes the function __netdev_alloc_frag() non-static and exports it so that drivers that need to specify additional flags, such as __GFP_DMA, can use it. The currently exported function, netdev_alloc_frag() doesn't allow passing in gfp_mask flags. Signed-off-by: WingMan Kwok w-kw...@ti.com Signed-off-by: Reece R. Pollack x0183...@ti.com --- include/linux/skbuff.h |1 + net/core/skbuff.c |3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index d6cdd6e..596deb3 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -2139,6 +2139,7 @@ static inline void __skb_queue_purge(struct sk_buff_head *list) kfree_skb(skb); } +void *__netdev_alloc_frag(unsigned int fragsz, gfp_t gfp_mask); void *netdev_alloc_frag(unsigned int fragsz); struct sk_buff *__netdev_alloc_skb(struct net_device *dev, unsigned int length, diff --git a/net/core/skbuff.c b/net/core/skbuff.c index b6a19ca..6f3451f 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -350,7 +350,7 @@ EXPORT_SYMBOL(build_skb); static DEFINE_PER_CPU(struct page_frag_cache, netdev_alloc_cache); static DEFINE_PER_CPU(struct page_frag_cache, napi_alloc_cache); -static void *__netdev_alloc_frag(unsigned int fragsz, gfp_t gfp_mask) +void *__netdev_alloc_frag(unsigned int fragsz, gfp_t gfp_mask) { struct page_frag_cache *nc; unsigned long flags; @@ -362,6 +362,7 @@ static void *__netdev_alloc_frag(unsigned int fragsz, gfp_t gfp_mask) local_irq_restore(flags); return data; } +EXPORT_SYMBOL(__netdev_alloc_frag); /** * netdev_alloc_frag - allocate a page fragment -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[net-next PATCH] net: netcp: Fixes efuse mac addr swap on k2e and k2l
On some of the K2E and K2L platforms, the two DWORDs in efuse occupied by the pre-programmed mac address for slave port 1 are swapped. To workaround this issue, this patch adds a new define NETCP_EFUSE_ADDR_SWAP (2) which signifies the occurrence of such swapping so that the driver can take proper action. The flag can be enabled in the corresponding netcp interface dts binding as efuse-mac = 2 under the corresponding netcp interface node. Signed-off-by: WingMan Kwok w-kw...@ti.com --- .../devicetree/bindings/net/keystone-netcp.txt |6 +- drivers/net/ethernet/ti/netcp_core.c | 15 +-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/net/keystone-netcp.txt b/Documentation/devicetree/bindings/net/keystone-netcp.txt index d0e6fa3..b30ab6b 100644 --- a/Documentation/devicetree/bindings/net/keystone-netcp.txt +++ b/Documentation/devicetree/bindings/net/keystone-netcp.txt @@ -130,7 +130,11 @@ Required properties: Optional properties: - efuse-mac: If this is 1, then the MAC address for the interface is - obtained from the device efuse mac address register + obtained from the device efuse mac address register. + If this is 2, the two DWORDs occupied by the MAC address + are swapped. The netcp driver will swap the two DWORDs + back to the proper order when this property is set to 2 + when it obtains the mac address from efuse. - local-mac-address: the driver is designed to use the of_get_mac_address api only if efuse-mac is 0. When efuse-mac is 0, the MAC address is obtained from local-mac-address. If this diff --git a/drivers/net/ethernet/ti/netcp_core.c b/drivers/net/ethernet/ti/netcp_core.c index 3ca87f2..6f2e151 100644 --- a/drivers/net/ethernet/ti/netcp_core.c +++ b/drivers/net/ethernet/ti/netcp_core.c @@ -51,6 +51,8 @@ NETIF_MSG_PKTDATA | NETIF_MSG_TX_QUEUED | \ NETIF_MSG_RX_STATUS) +#define NETCP_EFUSE_ADDR_SWAP 2 + #define knav_queue_get_id(q) knav_queue_device_control(q, \ KNAV_QUEUE_GET_ID, (unsigned long)NULL) @@ -172,13 +174,22 @@ static void set_words(u32 *words, int num_words, u32 *desc) } /* Read the e-fuse value as 32 bit values to be endian independent */ -static int emac_arch_get_mac_addr(char *x, void __iomem *efuse_mac) +static int emac_arch_get_mac_addr(char *x, void __iomem *efuse_mac, u32 swap) { unsigned int addr0, addr1; addr1 = readl(efuse_mac + 4); addr0 = readl(efuse_mac); + switch (swap) { + case NETCP_EFUSE_ADDR_SWAP: + addr0 = addr1; + addr1 = readl(efuse_mac); + break; + default: + break; + } + x[0] = (addr1 0xff00) 8; x[1] = addr1 0x00ff; x[2] = (addr0 0xff00) 24; @@ -1902,7 +1913,7 @@ static int netcp_create_interface(struct netcp_device *netcp_device, goto quit; } - emac_arch_get_mac_addr(efuse_mac_addr, efuse); + emac_arch_get_mac_addr(efuse_mac_addr, efuse, efuse_mac); if (is_valid_ether_addr(efuse_mac_addr)) ether_addr_copy(ndev-dev_addr, efuse_mac_addr); else -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] net: netcp: Fixes SGMII reset on network interface shutdown
This patch asserts SGMII RTRESET, i.e. resetting the SGMII Tx/Rx logic, during network interface shutdown to avoid having the hardware wedge when shutting down with high incoming traffic rates. This is cleared (brought out of RTRESET) when the interface is brought back up. Signed-off-by: WingMan Kwok w-kw...@ti.com --- This patch depends on the patch set Subject: [net-next PATCH v1 0/6] net: netcp: Bug fixes of CPSW statistics collection submitted earlier. drivers/net/ethernet/ti/netcp.h |1 + drivers/net/ethernet/ti/netcp_ethss.c | 18 ++ drivers/net/ethernet/ti/netcp_sgmii.c | 30 -- 3 files changed, 47 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/ti/netcp.h b/drivers/net/ethernet/ti/netcp.h index bbacf5c..a8a7306 100644 --- a/drivers/net/ethernet/ti/netcp.h +++ b/drivers/net/ethernet/ti/netcp.h @@ -223,6 +223,7 @@ void *netcp_device_find_module(struct netcp_device *netcp_device, /* SGMII functions */ int netcp_sgmii_reset(void __iomem *sgmii_ofs, int port); +bool netcp_sgmii_rtreset(void __iomem *sgmii_ofs, int port, bool set); int netcp_sgmii_get_port_link(void __iomem *sgmii_ofs, int port); int netcp_sgmii_config(void __iomem *sgmii_ofs, int port, u32 interface); diff --git a/drivers/net/ethernet/ti/netcp_ethss.c b/drivers/net/ethernet/ti/netcp_ethss.c index 7782120..571cf7a 100644 --- a/drivers/net/ethernet/ti/netcp_ethss.c +++ b/drivers/net/ethernet/ti/netcp_ethss.c @@ -2101,11 +2101,28 @@ static void gbe_port_config(struct gbe_priv *gbe_dev, struct gbe_slave *slave, writel(slave-mac_control, GBE_REG_ADDR(slave, emac_regs, mac_control)); } +static void gbe_sgmii_rtreset(struct gbe_priv *priv, + struct gbe_slave *slave, bool set) +{ + void __iomem *sgmii_port_regs; + + if (SLAVE_LINK_IS_XGMII(slave)) + return; + + if ((priv-ss_version == GBE_SS_VERSION_14) (slave-slave_num = 2)) + sgmii_port_regs = priv-sgmii_port34_regs; + else + sgmii_port_regs = priv-sgmii_port_regs; + + netcp_sgmii_rtreset(sgmii_port_regs, slave-slave_num, set); +} + static void gbe_slave_stop(struct gbe_intf *intf) { struct gbe_priv *gbe_dev = intf-gbe_dev; struct gbe_slave *slave = intf-slave; + gbe_sgmii_rtreset(gbe_dev, slave, true); gbe_port_reset(slave); /* Disable forwarding */ cpsw_ale_control_set(gbe_dev-ale, slave-port_num, @@ -2147,6 +2164,7 @@ static int gbe_slave_open(struct gbe_intf *gbe_intf) gbe_sgmii_config(priv, slave); gbe_port_reset(slave); + gbe_sgmii_rtreset(priv, slave, false); gbe_port_config(priv, slave, priv-rx_packet_max); gbe_set_slave_mac(slave, gbe_intf); /* enable forwarding */ diff --git a/drivers/net/ethernet/ti/netcp_sgmii.c b/drivers/net/ethernet/ti/netcp_sgmii.c index dbeb142..5d8419f 100644 --- a/drivers/net/ethernet/ti/netcp_sgmii.c +++ b/drivers/net/ethernet/ti/netcp_sgmii.c @@ -18,6 +18,9 @@ #include netcp.h +#define SGMII_SRESET_RESET BIT(0) +#define SGMII_SRESET_RTRESET BIT(1) + #define SGMII_REG_STATUS_LOCK BIT(4) #defineSGMII_REG_STATUS_LINK BIT(0) #define SGMII_REG_STATUS_AUTONEG BIT(2) @@ -51,12 +54,35 @@ static void sgmii_write_reg_bit(void __iomem *base, int reg, u32 val) int netcp_sgmii_reset(void __iomem *sgmii_ofs, int port) { /* Soft reset */ - sgmii_write_reg_bit(sgmii_ofs, SGMII_SRESET_REG(port), 0x1); - while (sgmii_read_reg(sgmii_ofs, SGMII_SRESET_REG(port)) != 0x0) + sgmii_write_reg_bit(sgmii_ofs, SGMII_SRESET_REG(port), + SGMII_SRESET_RESET); + + while ((sgmii_read_reg(sgmii_ofs, SGMII_SRESET_REG(port)) + SGMII_SRESET_RESET) != 0x0) ; + return 0; } +/* port is 0 based */ +bool netcp_sgmii_rtreset(void __iomem *sgmii_ofs, int port, bool set) +{ + u32 reg; + bool oldval; + + /* Initiate a soft reset */ + reg = sgmii_read_reg(sgmii_ofs, SGMII_SRESET_REG(port)); + oldval = (reg SGMII_SRESET_RTRESET) != 0x0; + if (set) + reg |= SGMII_SRESET_RTRESET; + else + reg = ~SGMII_SRESET_RTRESET; + sgmii_write_reg(sgmii_ofs, SGMII_SRESET_REG(port), reg); + wmb(); + + return oldval; +} + int netcp_sgmii_get_port_link(void __iomem *sgmii_ofs, int port) { u32 status = 0, link = 0; -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[net-next PATCH v0 0/6] net: netcp: Bug fixes of CPSW statistics collection
This patch set contains bug fixes and enhencements of hw ethernet statistics processing on TI's Keystone2 CPSW ethernet switches. WingMan Kwok (6): net: netcp: Fixes the use of spin_lock_bh in timer function net: netcp: Fixes hw statistics module base setting error net: netcp: Fixes error in oversized memory allocation for statistics storage net: netcp: Consolidates statistics collection code net: netcp: Fixes to CPSW statistics collection net: netcp: Adds missing statistics for K2L and K2E drivers/net/ethernet/ti/netcp_ethss.c | 399 ++--- 1 file changed, 324 insertions(+), 75 deletions(-) -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[net-next PATCH v0 5/6] net: netcp: Fixes to CPSW statistics collection
In certain applications it's beneficial to allow the CPSW h/w stats counters to continue to increment even while the kernel polls them. This patch implements this behavior for both 1G and 10G ethernet subsystem modules. Signed-off-by: WingMan Kwok w-kw...@ti.com --- drivers/net/ethernet/ti/netcp_ethss.c | 86 - 1 file changed, 75 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/ti/netcp_ethss.c b/drivers/net/ethernet/ti/netcp_ethss.c index aadca02..e2ef7ba 100644 --- a/drivers/net/ethernet/ti/netcp_ethss.c +++ b/drivers/net/ethernet/ti/netcp_ethss.c @@ -646,6 +646,7 @@ struct gbe_priv { boolenable_ale; u8 max_num_slaves; u8 max_num_ports; /* max_num_slaves + 1 */ + u8 num_stats_mods; struct netcp_tx_pipetx_pipe; int host_port; @@ -675,6 +676,7 @@ struct gbe_priv { struct net_device *dummy_ndev; u64 *hw_stats; + u32 *hw_stats_prev; const struct netcp_ethtool_stat *et_stats; int num_et_stats; /* Lock for updating the hwstats */ @@ -1554,25 +1556,37 @@ static int keystone_get_sset_count(struct net_device *ndev, int stringset) } } +static void gbe_reset_mod_stats(struct gbe_priv *gbe_dev, int stats_mod) +{ + void __iomem *base = gbe_dev-hw_stats_regs[stats_mod]; + u32 __iomem *p_stats_entry; + int i; + + for (i = 0; i gbe_dev-num_et_stats; i++) { + if (gbe_dev-et_stats[i].type == stats_mod) { + p_stats_entry = base + gbe_dev-et_stats[i].offset; + gbe_dev-hw_stats[i] = 0; + gbe_dev-hw_stats_prev[i] = readl(p_stats_entry); + } + } +} + static inline void gbe_update_hw_stats_entry(struct gbe_priv *gbe_dev, int et_stats_entry) { void __iomem *base = NULL; - u32 __iomem *p; - u32 tmp = 0; + u32 __iomem *p_stats_entry; + u32 curr, delta; /* The hw_stats_regs pointers are already * properly set to point to the right base: */ base = gbe_dev-hw_stats_regs[gbe_dev-et_stats[et_stats_entry].type]; - p = base + gbe_dev-et_stats[et_stats_entry].offset; - tmp = readl(p); - gbe_dev-hw_stats[et_stats_entry] += tmp; - - /* write-to-decrement: -* new register value = old register value - write value -*/ - writel(tmp, p); + p_stats_entry = base + gbe_dev-et_stats[et_stats_entry].offset; + curr = readl(p_stats_entry); + delta = curr - gbe_dev-hw_stats_prev[et_stats_entry]; + gbe_dev-hw_stats_prev[et_stats_entry] = curr; + gbe_dev-hw_stats[et_stats_entry] += delta; } static void gbe_update_stats(struct gbe_priv *gbe_dev, uint64_t *data) @@ -1611,6 +1625,12 @@ static inline void gbe_stats_mod_visible_ver14(struct gbe_priv *gbe_dev, writel(val, GBE_REG_ADDR(gbe_dev, switch_regs, stat_port_en)); } +static void gbe_reset_mod_stats_ver14(struct gbe_priv *gbe_dev, int stats_mod) +{ + gbe_stats_mod_visible_ver14(gbe_dev, stats_mod); + gbe_reset_mod_stats(gbe_dev, stats_mod); +} + static void gbe_update_stats_ver14(struct gbe_priv *gbe_dev, uint64_t *data) { u32 half_num_et_stats = (gbe_dev-num_et_stats / 2); @@ -2564,6 +2584,7 @@ static int set_xgbe_ethss10_priv(struct gbe_priv *gbe_dev, } gbe_dev-xgbe_serdes_regs = regs; + gbe_dev-num_stats_mods = gbe_dev-max_num_ports; gbe_dev-et_stats = xgbe10_et_stats; gbe_dev-num_et_stats = ARRAY_SIZE(xgbe10_et_stats); @@ -2575,6 +2596,16 @@ static int set_xgbe_ethss10_priv(struct gbe_priv *gbe_dev, return -ENOMEM; } + gbe_dev-hw_stats_prev = + devm_kzalloc(gbe_dev-dev, +gbe_dev-num_et_stats * sizeof(u32), +GFP_KERNEL); + if (!gbe_dev-hw_stats_prev) { + dev_err(gbe_dev-dev, + hw_stats_prev memory allocation failed\n); + return -ENOMEM; + } + gbe_dev-ss_version = XGBE_SS_VERSION_10; gbe_dev-sgmii_port_regs = gbe_dev-ss_regs + XGBE10_SGMII_MODULE_OFFSET; @@ -2672,6 +2703,7 @@ static int set_gbe_ethss14_priv(struct gbe_priv *gbe_dev, } gbe_dev-switch_regs = regs; + gbe_dev-num_stats_mods = gbe_dev-max_num_slaves; gbe_dev-et_stats = gbe13_et_stats; gbe_dev-num_et_stats = ARRAY_SIZE(gbe13_et_stats); @@ -2683,6 +2715,16 @@ static int set_gbe_ethss14_priv(struct gbe_priv *gbe_dev, return -ENOMEM; } + gbe_dev
[net-next PATCH v0 4/6] net: netcp: Consolidates statistics collection code
Different Keystone2 platforms have different number and layouts of hw statistics modules. This patch consolidates the statistics processing of different Keystone2 platforms for easy maintenance. Signed-off-by: WingMan Kwok w-kw...@ti.com --- drivers/net/ethernet/ti/netcp_ethss.c | 99 ++--- 1 file changed, 54 insertions(+), 45 deletions(-) diff --git a/drivers/net/ethernet/ti/netcp_ethss.c b/drivers/net/ethernet/ti/netcp_ethss.c index a1f16e1..aadca02 100644 --- a/drivers/net/ethernet/ti/netcp_ethss.c +++ b/drivers/net/ethernet/ti/netcp_ethss.c @@ -1554,70 +1554,79 @@ static int keystone_get_sset_count(struct net_device *ndev, int stringset) } } -static void gbe_update_stats(struct gbe_priv *gbe_dev, uint64_t *data) +static inline void gbe_update_hw_stats_entry(struct gbe_priv *gbe_dev, +int et_stats_entry) { void __iomem *base = NULL; u32 __iomem *p; u32 tmp = 0; + + /* The hw_stats_regs pointers are already +* properly set to point to the right base: +*/ + base = gbe_dev-hw_stats_regs[gbe_dev-et_stats[et_stats_entry].type]; + p = base + gbe_dev-et_stats[et_stats_entry].offset; + tmp = readl(p); + gbe_dev-hw_stats[et_stats_entry] += tmp; + + /* write-to-decrement: +* new register value = old register value - write value +*/ + writel(tmp, p); +} + +static void gbe_update_stats(struct gbe_priv *gbe_dev, uint64_t *data) +{ int i; for (i = 0; i gbe_dev-num_et_stats; i++) { - base = gbe_dev-hw_stats_regs[gbe_dev-et_stats[i].type]; - p = base + gbe_dev-et_stats[i].offset; - tmp = readl(p); - gbe_dev-hw_stats[i] = gbe_dev-hw_stats[i] + tmp; + gbe_update_hw_stats_entry(gbe_dev, i); + if (data) data[i] = gbe_dev-hw_stats[i]; - /* write-to-decrement: -* new register value = old register value - write value -*/ - writel(tmp, p); } } -static void gbe_update_stats_ver14(struct gbe_priv *gbe_dev, uint64_t *data) +static inline void gbe_stats_mod_visible_ver14(struct gbe_priv *gbe_dev, + int stats_mod) { - void __iomem *gbe_statsa = gbe_dev-hw_stats_regs[0]; - void __iomem *gbe_statsb = gbe_dev-hw_stats_regs[1]; - u64 *hw_stats = gbe_dev-hw_stats[0]; - void __iomem *base = NULL; - u32 __iomem *p; - u32 tmp = 0, val, pair_size = (gbe_dev-num_et_stats / 2); - int i, j, pair; + u32 val; - for (pair = 0; pair 2; pair++) { - val = readl(GBE_REG_ADDR(gbe_dev, switch_regs, stat_port_en)); + val = readl(GBE_REG_ADDR(gbe_dev, switch_regs, stat_port_en)); - if (pair == 0) - val = ~GBE_STATS_CD_SEL; - else - val |= GBE_STATS_CD_SEL; + switch (stats_mod) { + case GBE_STATSA_MODULE: + case GBE_STATSB_MODULE: + val = ~GBE_STATS_CD_SEL; + break; + case GBE_STATSC_MODULE: + case GBE_STATSD_MODULE: + val |= GBE_STATS_CD_SEL; + break; + default: + return; + } + + /* make the stat module visible */ + writel(val, GBE_REG_ADDR(gbe_dev, switch_regs, stat_port_en)); +} - /* make the stat modules visible */ - writel(val, GBE_REG_ADDR(gbe_dev, switch_regs, stat_port_en)); +static void gbe_update_stats_ver14(struct gbe_priv *gbe_dev, uint64_t *data) +{ + u32 half_num_et_stats = (gbe_dev-num_et_stats / 2); + int et_entry, j, pair; - for (i = 0; i pair_size; i++) { - j = pair * pair_size + i; - switch (gbe_dev-et_stats[j].type) { - case GBE_STATSA_MODULE: - case GBE_STATSC_MODULE: - base = gbe_statsa; - break; - case GBE_STATSB_MODULE: - case GBE_STATSD_MODULE: - base = gbe_statsb; - break; - } + for (pair = 0; pair 2; pair++) { + gbe_stats_mod_visible_ver14(gbe_dev, (pair ? + GBE_STATSC_MODULE : + GBE_STATSA_MODULE)); + + for (j = 0; j half_num_et_stats; j++) { + et_entry = pair * half_num_et_stats + j; + gbe_update_hw_stats_entry(gbe_dev, et_entry); - p = base + gbe_dev-et_stats[j].offset; - tmp = readl(p); - hw_stats[j] += tmp; if (data
[net-next PATCH v0 3/6] net: netcp: Fixes error in oversized memory allocation for statistics storage
The CPSW driver keeps internally some, but not all, of the statistics available in the hw statistics modules. Furthermore, some of the locations in the hw statistics modules are reserved and contain no useful information. Prior to this patch, the driver allocates memory of the size of the the whole hw statistics modules, instead of the size of statistics-entries-interested-in (i.e. et_stats), for internal storage. This patch fixes that. Signed-off-by: WingMan Kwok w-kw...@ti.com --- drivers/net/ethernet/ti/netcp_ethss.c | 42 - 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/drivers/net/ethernet/ti/netcp_ethss.c b/drivers/net/ethernet/ti/netcp_ethss.c index b954856..a1f16e1 100644 --- a/drivers/net/ethernet/ti/netcp_ethss.c +++ b/drivers/net/ethernet/ti/netcp_ethss.c @@ -2555,10 +2555,12 @@ static int set_xgbe_ethss10_priv(struct gbe_priv *gbe_dev, } gbe_dev-xgbe_serdes_regs = regs; + gbe_dev-et_stats = xgbe10_et_stats; + gbe_dev-num_et_stats = ARRAY_SIZE(xgbe10_et_stats); + gbe_dev-hw_stats = devm_kzalloc(gbe_dev-dev, - XGBE10_NUM_STAT_ENTRIES * - (gbe_dev-max_num_ports) * sizeof(u64), - GFP_KERNEL); +gbe_dev-num_et_stats * sizeof(u64), +GFP_KERNEL); if (!gbe_dev-hw_stats) { dev_err(gbe_dev-dev, hw_stats memory allocation failed\n); return -ENOMEM; @@ -2577,8 +2579,6 @@ static int set_xgbe_ethss10_priv(struct gbe_priv *gbe_dev, gbe_dev-ale_ports = gbe_dev-max_num_ports; gbe_dev-host_port = XGBE10_HOST_PORT_NUM; gbe_dev-ale_entries = XGBE10_NUM_ALE_ENTRIES; - gbe_dev-et_stats = xgbe10_et_stats; - gbe_dev-num_et_stats = ARRAY_SIZE(xgbe10_et_stats); gbe_dev-stats_en_mask = (1 (gbe_dev-max_num_ports)) - 1; /* Subsystem registers */ @@ -2663,10 +2663,12 @@ static int set_gbe_ethss14_priv(struct gbe_priv *gbe_dev, } gbe_dev-switch_regs = regs; + gbe_dev-et_stats = gbe13_et_stats; + gbe_dev-num_et_stats = ARRAY_SIZE(gbe13_et_stats); + gbe_dev-hw_stats = devm_kzalloc(gbe_dev-dev, - GBE13_NUM_HW_STAT_ENTRIES * - gbe_dev-max_num_slaves * sizeof(u64), - GFP_KERNEL); +gbe_dev-num_et_stats * sizeof(u64), +GFP_KERNEL); if (!gbe_dev-hw_stats) { dev_err(gbe_dev-dev, hw_stats memory allocation failed\n); return -ENOMEM; @@ -2689,8 +2691,6 @@ static int set_gbe_ethss14_priv(struct gbe_priv *gbe_dev, gbe_dev-ale_ports = gbe_dev-max_num_ports; gbe_dev-host_port = GBE13_HOST_PORT_NUM; gbe_dev-ale_entries = GBE13_NUM_ALE_ENTRIES; - gbe_dev-et_stats = gbe13_et_stats; - gbe_dev-num_et_stats = ARRAY_SIZE(gbe13_et_stats); gbe_dev-stats_en_mask = GBE13_REG_VAL_STAT_ENABLE_ALL; /* Subsystem registers */ @@ -2717,10 +2717,18 @@ static int set_gbenu_ethss_priv(struct gbe_priv *gbe_dev, void __iomem *regs; int i, ret; + gbe_dev-et_stats = gbenu_et_stats; + + if (IS_SS_ID_NU(gbe_dev)) + gbe_dev-num_et_stats = GBENU_ET_STATS_HOST_SIZE + + (gbe_dev-max_num_slaves * GBENU_ET_STATS_PORT_SIZE); + else + gbe_dev-num_et_stats = GBENU_ET_STATS_HOST_SIZE + + GBENU_ET_STATS_PORT_SIZE; + gbe_dev-hw_stats = devm_kzalloc(gbe_dev-dev, - GBENU_NUM_HW_STAT_ENTRIES * - (gbe_dev-max_num_ports) * sizeof(u64), - GFP_KERNEL); +gbe_dev-num_et_stats * sizeof(u64), +GFP_KERNEL); if (!gbe_dev-hw_stats) { dev_err(gbe_dev-dev, hw_stats memory allocation failed\n); return -ENOMEM; @@ -2753,16 +2761,8 @@ static int set_gbenu_ethss_priv(struct gbe_priv *gbe_dev, gbe_dev-ale_ports = gbe_dev-max_num_ports; gbe_dev-host_port = GBENU_HOST_PORT_NUM; gbe_dev-ale_entries = GBE13_NUM_ALE_ENTRIES; - gbe_dev-et_stats = gbenu_et_stats; gbe_dev-stats_en_mask = (1 (gbe_dev-max_num_ports)) - 1; - if (IS_SS_ID_NU(gbe_dev)) - gbe_dev-num_et_stats = GBENU_ET_STATS_HOST_SIZE + - (gbe_dev-max_num_slaves * GBENU_ET_STATS_PORT_SIZE); - else - gbe_dev-num_et_stats = GBENU_ET_STATS_HOST_SIZE + - GBENU_ET_STATS_PORT_SIZE; - /* Subsystem registers */ GBENU_SET_REG_OFS(gbe_dev, ss_regs, id_ver); -- 1.7.9.5
[net-next PATCH v0 6/6] net: netcp: Adds missing statistics for K2L and K2E
This patch adds the missing statistics for the host and slave ports of the CPSW on K2L and K2E platforms. Signed-off-by: WingMan Kwok w-kw...@ti.com --- drivers/net/ethernet/ti/netcp_ethss.c | 177 - 1 file changed, 174 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/ti/netcp_ethss.c b/drivers/net/ethernet/ti/netcp_ethss.c index e2ef7ba..7782120 100644 --- a/drivers/net/ethernet/ti/netcp_ethss.c +++ b/drivers/net/ethernet/ti/netcp_ethss.c @@ -876,7 +876,7 @@ static const struct netcp_ethtool_stat gbe13_et_stats[] = { }; /* This is the size of entries in GBENU_STATS_HOST */ -#define GBENU_ET_STATS_HOST_SIZE 33 +#define GBENU_ET_STATS_HOST_SIZE 52 #define GBENU_STATS_HOST(field)\ { \ @@ -885,8 +885,8 @@ static const struct netcp_ethtool_stat gbe13_et_stats[] = { offsetof(struct gbenu_hw_stats, field) \ } -/* This is the size of entries in GBENU_STATS_HOST */ -#define GBENU_ET_STATS_PORT_SIZE 46 +/* This is the size of entries in GBENU_STATS_PORT */ +#define GBENU_ET_STATS_PORT_SIZE 65 #define GBENU_STATS_P1(field) \ { \ @@ -978,7 +978,26 @@ static const struct netcp_ethtool_stat gbenu_et_stats[] = { GBENU_STATS_HOST(ale_unknown_mcast_bytes), GBENU_STATS_HOST(ale_unknown_bcast), GBENU_STATS_HOST(ale_unknown_bcast_bytes), + GBENU_STATS_HOST(ale_pol_match), + GBENU_STATS_HOST(ale_pol_match_red), + GBENU_STATS_HOST(ale_pol_match_yellow), GBENU_STATS_HOST(tx_mem_protect_err), + GBENU_STATS_HOST(tx_pri0_drop), + GBENU_STATS_HOST(tx_pri1_drop), + GBENU_STATS_HOST(tx_pri2_drop), + GBENU_STATS_HOST(tx_pri3_drop), + GBENU_STATS_HOST(tx_pri4_drop), + GBENU_STATS_HOST(tx_pri5_drop), + GBENU_STATS_HOST(tx_pri6_drop), + GBENU_STATS_HOST(tx_pri7_drop), + GBENU_STATS_HOST(tx_pri0_drop_bcnt), + GBENU_STATS_HOST(tx_pri1_drop_bcnt), + GBENU_STATS_HOST(tx_pri2_drop_bcnt), + GBENU_STATS_HOST(tx_pri3_drop_bcnt), + GBENU_STATS_HOST(tx_pri4_drop_bcnt), + GBENU_STATS_HOST(tx_pri5_drop_bcnt), + GBENU_STATS_HOST(tx_pri6_drop_bcnt), + GBENU_STATS_HOST(tx_pri7_drop_bcnt), /* GBENU Module 1 */ GBENU_STATS_P1(rx_good_frames), GBENU_STATS_P1(rx_broadcast_frames), @@ -1025,7 +1044,26 @@ static const struct netcp_ethtool_stat gbenu_et_stats[] = { GBENU_STATS_P1(ale_unknown_mcast_bytes), GBENU_STATS_P1(ale_unknown_bcast), GBENU_STATS_P1(ale_unknown_bcast_bytes), + GBENU_STATS_P1(ale_pol_match), + GBENU_STATS_P1(ale_pol_match_red), + GBENU_STATS_P1(ale_pol_match_yellow), GBENU_STATS_P1(tx_mem_protect_err), + GBENU_STATS_P1(tx_pri0_drop), + GBENU_STATS_P1(tx_pri1_drop), + GBENU_STATS_P1(tx_pri2_drop), + GBENU_STATS_P1(tx_pri3_drop), + GBENU_STATS_P1(tx_pri4_drop), + GBENU_STATS_P1(tx_pri5_drop), + GBENU_STATS_P1(tx_pri6_drop), + GBENU_STATS_P1(tx_pri7_drop), + GBENU_STATS_P1(tx_pri0_drop_bcnt), + GBENU_STATS_P1(tx_pri1_drop_bcnt), + GBENU_STATS_P1(tx_pri2_drop_bcnt), + GBENU_STATS_P1(tx_pri3_drop_bcnt), + GBENU_STATS_P1(tx_pri4_drop_bcnt), + GBENU_STATS_P1(tx_pri5_drop_bcnt), + GBENU_STATS_P1(tx_pri6_drop_bcnt), + GBENU_STATS_P1(tx_pri7_drop_bcnt), /* GBENU Module 2 */ GBENU_STATS_P2(rx_good_frames), GBENU_STATS_P2(rx_broadcast_frames), @@ -1072,7 +1110,26 @@ static const struct netcp_ethtool_stat gbenu_et_stats[] = { GBENU_STATS_P2(ale_unknown_mcast_bytes), GBENU_STATS_P2(ale_unknown_bcast), GBENU_STATS_P2(ale_unknown_bcast_bytes), + GBENU_STATS_P2(ale_pol_match), + GBENU_STATS_P2(ale_pol_match_red), + GBENU_STATS_P2(ale_pol_match_yellow), GBENU_STATS_P2(tx_mem_protect_err), + GBENU_STATS_P2(tx_pri0_drop), + GBENU_STATS_P2(tx_pri1_drop), + GBENU_STATS_P2(tx_pri2_drop), + GBENU_STATS_P2(tx_pri3_drop), + GBENU_STATS_P2(tx_pri4_drop), + GBENU_STATS_P2(tx_pri5_drop), + GBENU_STATS_P2(tx_pri6_drop), + GBENU_STATS_P2(tx_pri7_drop), + GBENU_STATS_P2(tx_pri0_drop_bcnt), + GBENU_STATS_P2(tx_pri1_drop_bcnt), + GBENU_STATS_P2(tx_pri2_drop_bcnt), + GBENU_STATS_P2(tx_pri3_drop_bcnt), + GBENU_STATS_P2(tx_pri4_drop_bcnt), + GBENU_STATS_P2(tx_pri5_drop_bcnt), + GBENU_STATS_P2(tx_pri6_drop_bcnt), + GBENU_STATS_P2(tx_pri7_drop_bcnt), /* GBENU Module 3 */ GBENU_STATS_P3(rx_good_frames), GBENU_STATS_P3(rx_broadcast_frames), @@ -1119,7 +1176,26 @@ static const struct netcp_ethtool_stat gbenu_et_stats[] = { GBENU_STATS_P3(ale_unknown_mcast_bytes
[net-next PATCH v0 1/6] net: netcp: Fixes the use of spin_lock_bh in timer function
This patch fixes a bug in which the timer routine synchronized against the ethtool-triggered statistics updates with spin_lock_bh(). A timer function is itself a bottom-half, so this should be spin_lock(). Signed-off-by: WingMan Kwok w-kw...@ti.com --- drivers/net/ethernet/ti/netcp_ethss.c |5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/ti/netcp_ethss.c b/drivers/net/ethernet/ti/netcp_ethss.c index 9b7e0a3..cabf977 100644 --- a/drivers/net/ethernet/ti/netcp_ethss.c +++ b/drivers/net/ethernet/ti/netcp_ethss.c @@ -2189,14 +2189,15 @@ static void netcp_ethss_timer(unsigned long arg) netcp_ethss_update_link_state(gbe_dev, slave, NULL); } - spin_lock_bh(gbe_dev-hw_stats_lock); + /* A timer runs as a BH, no need to block them */ + spin_lock(gbe_dev-hw_stats_lock); if (gbe_dev-ss_version == GBE_SS_VERSION_14) gbe_update_stats_ver14(gbe_dev, NULL); else gbe_update_stats(gbe_dev, NULL); - spin_unlock_bh(gbe_dev-hw_stats_lock); + spin_unlock(gbe_dev-hw_stats_lock); gbe_dev-timer.expires = jiffies + GBE_TIMER_INTERVAL; add_timer(gbe_dev-timer); -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[net-next PATCH v0 2/6] net: netcp: Fixes hw statistics module base setting error
This patch fixes error in the setting of the hw statistics module base for K2HK platform. In K2HK although there are 4 hw statistics modules, but only 2 are visible at a time. Thus when setting up the pointers to the base of the corresponding hw statistics modules, modules 0 and 2 should point to one base, while modules 1 and 3 should point to the other. Signed-off-by: WingMan Kwok w-kw...@ti.com --- drivers/net/ethernet/ti/netcp_ethss.c |6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/ti/netcp_ethss.c b/drivers/net/ethernet/ti/netcp_ethss.c index cabf977..b954856 100644 --- a/drivers/net/ethernet/ti/netcp_ethss.c +++ b/drivers/net/ethernet/ti/netcp_ethss.c @@ -2675,10 +2675,14 @@ static int set_gbe_ethss14_priv(struct gbe_priv *gbe_dev, gbe_dev-sgmii_port_regs = gbe_dev-ss_regs + GBE13_SGMII_MODULE_OFFSET; gbe_dev-host_port_regs = gbe_dev-switch_regs + GBE13_HOST_PORT_OFFSET; + /* K2HK has only 2 hw stats modules visible at a time, so +* module 0 2 points to one base and +* module 1 3 points to the other base +*/ for (i = 0; i gbe_dev-max_num_slaves; i++) { gbe_dev-hw_stats_regs[i] = gbe_dev-switch_regs + GBE13_HW_STATS_OFFSET + - (GBE_HW_STATS_REG_MAP_SZ * i); + (GBE_HW_STATS_REG_MAP_SZ * (i 0x1)); } gbe_dev-ale_reg = gbe_dev-switch_regs + GBE13_ALE_OFFSET; -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[net-next PATCH v1 5/6] net: netcp: Fixes to CPSW statistics collection
In certain applications it's beneficial to allow the CPSW h/w stats counters to continue to increment even while the kernel polls them. This patch implements this behavior for both 1G and 10G ethernet subsystem modules. Signed-off-by: WingMan Kwok w-kw...@ti.com --- drivers/net/ethernet/ti/netcp_ethss.c | 86 - 1 file changed, 75 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/ti/netcp_ethss.c b/drivers/net/ethernet/ti/netcp_ethss.c index b06f210..aa33066 100644 --- a/drivers/net/ethernet/ti/netcp_ethss.c +++ b/drivers/net/ethernet/ti/netcp_ethss.c @@ -642,6 +642,7 @@ struct gbe_priv { boolenable_ale; u8 max_num_slaves; u8 max_num_ports; /* max_num_slaves + 1 */ + u8 num_stats_mods; struct netcp_tx_pipetx_pipe; int host_port; @@ -671,6 +672,7 @@ struct gbe_priv { struct net_device *dummy_ndev; u64 *hw_stats; + u32 *hw_stats_prev; const struct netcp_ethtool_stat *et_stats; int num_et_stats; /* Lock for updating the hwstats */ @@ -1550,25 +1552,37 @@ static int keystone_get_sset_count(struct net_device *ndev, int stringset) } } +static void gbe_reset_mod_stats(struct gbe_priv *gbe_dev, int stats_mod) +{ + void __iomem *base = gbe_dev-hw_stats_regs[stats_mod]; + u32 __iomem *p_stats_entry; + int i; + + for (i = 0; i gbe_dev-num_et_stats; i++) { + if (gbe_dev-et_stats[i].type == stats_mod) { + p_stats_entry = base + gbe_dev-et_stats[i].offset; + gbe_dev-hw_stats[i] = 0; + gbe_dev-hw_stats_prev[i] = readl(p_stats_entry); + } + } +} + static inline void gbe_update_hw_stats_entry(struct gbe_priv *gbe_dev, int et_stats_entry) { void __iomem *base = NULL; - u32 __iomem *p; - u32 tmp = 0; + u32 __iomem *p_stats_entry; + u32 curr, delta; /* The hw_stats_regs pointers are already * properly set to point to the right base: */ base = gbe_dev-hw_stats_regs[gbe_dev-et_stats[et_stats_entry].type]; - p = base + gbe_dev-et_stats[et_stats_entry].offset; - tmp = readl(p); - gbe_dev-hw_stats[et_stats_entry] += tmp; - - /* write-to-decrement: -* new register value = old register value - write value -*/ - writel(tmp, p); + p_stats_entry = base + gbe_dev-et_stats[et_stats_entry].offset; + curr = readl(p_stats_entry); + delta = curr - gbe_dev-hw_stats_prev[et_stats_entry]; + gbe_dev-hw_stats_prev[et_stats_entry] = curr; + gbe_dev-hw_stats[et_stats_entry] += delta; } static void gbe_update_stats(struct gbe_priv *gbe_dev, uint64_t *data) @@ -1607,6 +1621,12 @@ static inline void gbe_stats_mod_visible_ver14(struct gbe_priv *gbe_dev, writel(val, GBE_REG_ADDR(gbe_dev, switch_regs, stat_port_en)); } +static void gbe_reset_mod_stats_ver14(struct gbe_priv *gbe_dev, int stats_mod) +{ + gbe_stats_mod_visible_ver14(gbe_dev, stats_mod); + gbe_reset_mod_stats(gbe_dev, stats_mod); +} + static void gbe_update_stats_ver14(struct gbe_priv *gbe_dev, uint64_t *data) { u32 half_num_et_stats = (gbe_dev-num_et_stats / 2); @@ -2560,6 +2580,7 @@ static int set_xgbe_ethss10_priv(struct gbe_priv *gbe_dev, } gbe_dev-xgbe_serdes_regs = regs; + gbe_dev-num_stats_mods = gbe_dev-max_num_ports; gbe_dev-et_stats = xgbe10_et_stats; gbe_dev-num_et_stats = ARRAY_SIZE(xgbe10_et_stats); @@ -2571,6 +2592,16 @@ static int set_xgbe_ethss10_priv(struct gbe_priv *gbe_dev, return -ENOMEM; } + gbe_dev-hw_stats_prev = + devm_kzalloc(gbe_dev-dev, +gbe_dev-num_et_stats * sizeof(u32), +GFP_KERNEL); + if (!gbe_dev-hw_stats_prev) { + dev_err(gbe_dev-dev, + hw_stats_prev memory allocation failed\n); + return -ENOMEM; + } + gbe_dev-ss_version = XGBE_SS_VERSION_10; gbe_dev-sgmii_port_regs = gbe_dev-ss_regs + XGBE10_SGMII_MODULE_OFFSET; @@ -2668,6 +2699,7 @@ static int set_gbe_ethss14_priv(struct gbe_priv *gbe_dev, } gbe_dev-switch_regs = regs; + gbe_dev-num_stats_mods = gbe_dev-max_num_slaves; gbe_dev-et_stats = gbe13_et_stats; gbe_dev-num_et_stats = ARRAY_SIZE(gbe13_et_stats); @@ -2679,6 +2711,16 @@ static int set_gbe_ethss14_priv(struct gbe_priv *gbe_dev, return -ENOMEM; } + gbe_dev
[net-next PATCH v1 4/6] net: netcp: Consolidates statistics collection code
Different Keystone2 platforms have different number and layouts of hw statistics modules. This patch consolidates the statistics processing of different Keystone2 platforms for easy maintenance. Signed-off-by: WingMan Kwok w-kw...@ti.com --- drivers/net/ethernet/ti/netcp_ethss.c | 99 ++--- 1 file changed, 54 insertions(+), 45 deletions(-) diff --git a/drivers/net/ethernet/ti/netcp_ethss.c b/drivers/net/ethernet/ti/netcp_ethss.c index 3976516..b06f210 100644 --- a/drivers/net/ethernet/ti/netcp_ethss.c +++ b/drivers/net/ethernet/ti/netcp_ethss.c @@ -1550,70 +1550,79 @@ static int keystone_get_sset_count(struct net_device *ndev, int stringset) } } -static void gbe_update_stats(struct gbe_priv *gbe_dev, uint64_t *data) +static inline void gbe_update_hw_stats_entry(struct gbe_priv *gbe_dev, +int et_stats_entry) { void __iomem *base = NULL; u32 __iomem *p; u32 tmp = 0; + + /* The hw_stats_regs pointers are already +* properly set to point to the right base: +*/ + base = gbe_dev-hw_stats_regs[gbe_dev-et_stats[et_stats_entry].type]; + p = base + gbe_dev-et_stats[et_stats_entry].offset; + tmp = readl(p); + gbe_dev-hw_stats[et_stats_entry] += tmp; + + /* write-to-decrement: +* new register value = old register value - write value +*/ + writel(tmp, p); +} + +static void gbe_update_stats(struct gbe_priv *gbe_dev, uint64_t *data) +{ int i; for (i = 0; i gbe_dev-num_et_stats; i++) { - base = gbe_dev-hw_stats_regs[gbe_dev-et_stats[i].type]; - p = base + gbe_dev-et_stats[i].offset; - tmp = readl(p); - gbe_dev-hw_stats[i] = gbe_dev-hw_stats[i] + tmp; + gbe_update_hw_stats_entry(gbe_dev, i); + if (data) data[i] = gbe_dev-hw_stats[i]; - /* write-to-decrement: -* new register value = old register value - write value -*/ - writel(tmp, p); } } -static void gbe_update_stats_ver14(struct gbe_priv *gbe_dev, uint64_t *data) +static inline void gbe_stats_mod_visible_ver14(struct gbe_priv *gbe_dev, + int stats_mod) { - void __iomem *gbe_statsa = gbe_dev-hw_stats_regs[0]; - void __iomem *gbe_statsb = gbe_dev-hw_stats_regs[1]; - u64 *hw_stats = gbe_dev-hw_stats[0]; - void __iomem *base = NULL; - u32 __iomem *p; - u32 tmp = 0, val, pair_size = (gbe_dev-num_et_stats / 2); - int i, j, pair; + u32 val; - for (pair = 0; pair 2; pair++) { - val = readl(GBE_REG_ADDR(gbe_dev, switch_regs, stat_port_en)); + val = readl(GBE_REG_ADDR(gbe_dev, switch_regs, stat_port_en)); - if (pair == 0) - val = ~GBE_STATS_CD_SEL; - else - val |= GBE_STATS_CD_SEL; + switch (stats_mod) { + case GBE_STATSA_MODULE: + case GBE_STATSB_MODULE: + val = ~GBE_STATS_CD_SEL; + break; + case GBE_STATSC_MODULE: + case GBE_STATSD_MODULE: + val |= GBE_STATS_CD_SEL; + break; + default: + return; + } + + /* make the stat module visible */ + writel(val, GBE_REG_ADDR(gbe_dev, switch_regs, stat_port_en)); +} - /* make the stat modules visible */ - writel(val, GBE_REG_ADDR(gbe_dev, switch_regs, stat_port_en)); +static void gbe_update_stats_ver14(struct gbe_priv *gbe_dev, uint64_t *data) +{ + u32 half_num_et_stats = (gbe_dev-num_et_stats / 2); + int et_entry, j, pair; - for (i = 0; i pair_size; i++) { - j = pair * pair_size + i; - switch (gbe_dev-et_stats[j].type) { - case GBE_STATSA_MODULE: - case GBE_STATSC_MODULE: - base = gbe_statsa; - break; - case GBE_STATSB_MODULE: - case GBE_STATSD_MODULE: - base = gbe_statsb; - break; - } + for (pair = 0; pair 2; pair++) { + gbe_stats_mod_visible_ver14(gbe_dev, (pair ? + GBE_STATSC_MODULE : + GBE_STATSA_MODULE)); + + for (j = 0; j half_num_et_stats; j++) { + et_entry = pair * half_num_et_stats + j; + gbe_update_hw_stats_entry(gbe_dev, et_entry); - p = base + gbe_dev-et_stats[j].offset; - tmp = readl(p); - hw_stats[j] += tmp; if (data
[net-next PATCH v1 3/6] net: netcp: Fixes error in oversized memory allocation for statistics storage
The CPSW driver keeps internally some, but not all, of the statistics available in the hw statistics modules. Furthermore, some of the locations in the hw statistics modules are reserved and contain no useful information. Prior to this patch, the driver allocates memory of the size of the the whole hw statistics modules, instead of the size of statistics-entries-interested-in (i.e. et_stats), for internal storage. This patch fixes that. Signed-off-by: WingMan Kwok w-kw...@ti.com --- drivers/net/ethernet/ti/netcp_ethss.c | 46 +++-- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/drivers/net/ethernet/ti/netcp_ethss.c b/drivers/net/ethernet/ti/netcp_ethss.c index b954856..3976516 100644 --- a/drivers/net/ethernet/ti/netcp_ethss.c +++ b/drivers/net/ethernet/ti/netcp_ethss.c @@ -295,8 +295,6 @@ struct xgbe_hw_stats { u32 rx_dma_overruns; }; -#define XGBE10_NUM_STAT_ENTRIES (sizeof(struct xgbe_hw_stats)/sizeof(u32)) - struct gbenu_ss_regs { u32 id_ver; u32 synce_count;/* NU */ @@ -480,7 +478,6 @@ struct gbenu_hw_stats { u32 tx_pri7_drop_bcnt; }; -#define GBENU_NUM_HW_STAT_ENTRIES (sizeof(struct gbenu_hw_stats) / sizeof(u32)) #define GBENU_HW_STATS_REG_MAP_SZ 0x200 struct gbe_ss_regs { @@ -615,7 +612,6 @@ struct gbe_hw_stats { u32 rx_dma_overruns; }; -#define GBE13_NUM_HW_STAT_ENTRIES (sizeof(struct gbe_hw_stats)/sizeof(u32)) #define GBE_MAX_HW_STAT_MODS 9 #define GBE_HW_STATS_REG_MAP_SZ0x100 @@ -2555,10 +2551,12 @@ static int set_xgbe_ethss10_priv(struct gbe_priv *gbe_dev, } gbe_dev-xgbe_serdes_regs = regs; + gbe_dev-et_stats = xgbe10_et_stats; + gbe_dev-num_et_stats = ARRAY_SIZE(xgbe10_et_stats); + gbe_dev-hw_stats = devm_kzalloc(gbe_dev-dev, - XGBE10_NUM_STAT_ENTRIES * - (gbe_dev-max_num_ports) * sizeof(u64), - GFP_KERNEL); +gbe_dev-num_et_stats * sizeof(u64), +GFP_KERNEL); if (!gbe_dev-hw_stats) { dev_err(gbe_dev-dev, hw_stats memory allocation failed\n); return -ENOMEM; @@ -2577,8 +2575,6 @@ static int set_xgbe_ethss10_priv(struct gbe_priv *gbe_dev, gbe_dev-ale_ports = gbe_dev-max_num_ports; gbe_dev-host_port = XGBE10_HOST_PORT_NUM; gbe_dev-ale_entries = XGBE10_NUM_ALE_ENTRIES; - gbe_dev-et_stats = xgbe10_et_stats; - gbe_dev-num_et_stats = ARRAY_SIZE(xgbe10_et_stats); gbe_dev-stats_en_mask = (1 (gbe_dev-max_num_ports)) - 1; /* Subsystem registers */ @@ -2663,10 +2659,12 @@ static int set_gbe_ethss14_priv(struct gbe_priv *gbe_dev, } gbe_dev-switch_regs = regs; + gbe_dev-et_stats = gbe13_et_stats; + gbe_dev-num_et_stats = ARRAY_SIZE(gbe13_et_stats); + gbe_dev-hw_stats = devm_kzalloc(gbe_dev-dev, - GBE13_NUM_HW_STAT_ENTRIES * - gbe_dev-max_num_slaves * sizeof(u64), - GFP_KERNEL); +gbe_dev-num_et_stats * sizeof(u64), +GFP_KERNEL); if (!gbe_dev-hw_stats) { dev_err(gbe_dev-dev, hw_stats memory allocation failed\n); return -ENOMEM; @@ -2689,8 +2687,6 @@ static int set_gbe_ethss14_priv(struct gbe_priv *gbe_dev, gbe_dev-ale_ports = gbe_dev-max_num_ports; gbe_dev-host_port = GBE13_HOST_PORT_NUM; gbe_dev-ale_entries = GBE13_NUM_ALE_ENTRIES; - gbe_dev-et_stats = gbe13_et_stats; - gbe_dev-num_et_stats = ARRAY_SIZE(gbe13_et_stats); gbe_dev-stats_en_mask = GBE13_REG_VAL_STAT_ENABLE_ALL; /* Subsystem registers */ @@ -2717,10 +2713,18 @@ static int set_gbenu_ethss_priv(struct gbe_priv *gbe_dev, void __iomem *regs; int i, ret; + gbe_dev-et_stats = gbenu_et_stats; + + if (IS_SS_ID_NU(gbe_dev)) + gbe_dev-num_et_stats = GBENU_ET_STATS_HOST_SIZE + + (gbe_dev-max_num_slaves * GBENU_ET_STATS_PORT_SIZE); + else + gbe_dev-num_et_stats = GBENU_ET_STATS_HOST_SIZE + + GBENU_ET_STATS_PORT_SIZE; + gbe_dev-hw_stats = devm_kzalloc(gbe_dev-dev, - GBENU_NUM_HW_STAT_ENTRIES * - (gbe_dev-max_num_ports) * sizeof(u64), - GFP_KERNEL); +gbe_dev-num_et_stats * sizeof(u64), +GFP_KERNEL); if (!gbe_dev-hw_stats) { dev_err(gbe_dev-dev, hw_stats memory allocation failed\n); return -ENOMEM
[net-next PATCH v1 1/6] net: netcp: Fixes the use of spin_lock_bh in timer function
This patch fixes a bug in which the timer routine synchronized against the ethtool-triggered statistics updates with spin_lock_bh(). A timer function is itself a bottom-half, so this should be spin_lock(). Signed-off-by: WingMan Kwok w-kw...@ti.com --- drivers/net/ethernet/ti/netcp_ethss.c |5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/ti/netcp_ethss.c b/drivers/net/ethernet/ti/netcp_ethss.c index 9b7e0a3..cabf977 100644 --- a/drivers/net/ethernet/ti/netcp_ethss.c +++ b/drivers/net/ethernet/ti/netcp_ethss.c @@ -2189,14 +2189,15 @@ static void netcp_ethss_timer(unsigned long arg) netcp_ethss_update_link_state(gbe_dev, slave, NULL); } - spin_lock_bh(gbe_dev-hw_stats_lock); + /* A timer runs as a BH, no need to block them */ + spin_lock(gbe_dev-hw_stats_lock); if (gbe_dev-ss_version == GBE_SS_VERSION_14) gbe_update_stats_ver14(gbe_dev, NULL); else gbe_update_stats(gbe_dev, NULL); - spin_unlock_bh(gbe_dev-hw_stats_lock); + spin_unlock(gbe_dev-hw_stats_lock); gbe_dev-timer.expires = jiffies + GBE_TIMER_INTERVAL; add_timer(gbe_dev-timer); -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[net-next PATCH v1 2/6] net: netcp: Fixes hw statistics module base setting error
This patch fixes error in the setting of the hw statistics module base for K2HK platform. In K2HK although there are 4 hw statistics modules, but only 2 are visible at a time. Thus when setting up the pointers to the base of the corresponding hw statistics modules, modules 0 and 2 should point to one base, while modules 1 and 3 should point to the other. Signed-off-by: WingMan Kwok w-kw...@ti.com --- drivers/net/ethernet/ti/netcp_ethss.c |6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/ti/netcp_ethss.c b/drivers/net/ethernet/ti/netcp_ethss.c index cabf977..b954856 100644 --- a/drivers/net/ethernet/ti/netcp_ethss.c +++ b/drivers/net/ethernet/ti/netcp_ethss.c @@ -2675,10 +2675,14 @@ static int set_gbe_ethss14_priv(struct gbe_priv *gbe_dev, gbe_dev-sgmii_port_regs = gbe_dev-ss_regs + GBE13_SGMII_MODULE_OFFSET; gbe_dev-host_port_regs = gbe_dev-switch_regs + GBE13_HOST_PORT_OFFSET; + /* K2HK has only 2 hw stats modules visible at a time, so +* module 0 2 points to one base and +* module 1 3 points to the other base +*/ for (i = 0; i gbe_dev-max_num_slaves; i++) { gbe_dev-hw_stats_regs[i] = gbe_dev-switch_regs + GBE13_HW_STATS_OFFSET + - (GBE_HW_STATS_REG_MAP_SZ * i); + (GBE_HW_STATS_REG_MAP_SZ * (i 0x1)); } gbe_dev-ale_reg = gbe_dev-switch_regs + GBE13_ALE_OFFSET; -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[net-next PATCH v1 6/6] net: netcp: Adds missing statistics for K2L and K2E
This patch adds the missing statistics for the host and slave ports of the CPSW on K2L and K2E platforms. Signed-off-by: WingMan Kwok w-kw...@ti.com --- drivers/net/ethernet/ti/netcp_ethss.c | 177 - 1 file changed, 174 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/ti/netcp_ethss.c b/drivers/net/ethernet/ti/netcp_ethss.c index aa33066..01a955c 100644 --- a/drivers/net/ethernet/ti/netcp_ethss.c +++ b/drivers/net/ethernet/ti/netcp_ethss.c @@ -872,7 +872,7 @@ static const struct netcp_ethtool_stat gbe13_et_stats[] = { }; /* This is the size of entries in GBENU_STATS_HOST */ -#define GBENU_ET_STATS_HOST_SIZE 33 +#define GBENU_ET_STATS_HOST_SIZE 52 #define GBENU_STATS_HOST(field)\ { \ @@ -881,8 +881,8 @@ static const struct netcp_ethtool_stat gbe13_et_stats[] = { offsetof(struct gbenu_hw_stats, field) \ } -/* This is the size of entries in GBENU_STATS_HOST */ -#define GBENU_ET_STATS_PORT_SIZE 46 +/* This is the size of entries in GBENU_STATS_PORT */ +#define GBENU_ET_STATS_PORT_SIZE 65 #define GBENU_STATS_P1(field) \ { \ @@ -974,7 +974,26 @@ static const struct netcp_ethtool_stat gbenu_et_stats[] = { GBENU_STATS_HOST(ale_unknown_mcast_bytes), GBENU_STATS_HOST(ale_unknown_bcast), GBENU_STATS_HOST(ale_unknown_bcast_bytes), + GBENU_STATS_HOST(ale_pol_match), + GBENU_STATS_HOST(ale_pol_match_red), + GBENU_STATS_HOST(ale_pol_match_yellow), GBENU_STATS_HOST(tx_mem_protect_err), + GBENU_STATS_HOST(tx_pri0_drop), + GBENU_STATS_HOST(tx_pri1_drop), + GBENU_STATS_HOST(tx_pri2_drop), + GBENU_STATS_HOST(tx_pri3_drop), + GBENU_STATS_HOST(tx_pri4_drop), + GBENU_STATS_HOST(tx_pri5_drop), + GBENU_STATS_HOST(tx_pri6_drop), + GBENU_STATS_HOST(tx_pri7_drop), + GBENU_STATS_HOST(tx_pri0_drop_bcnt), + GBENU_STATS_HOST(tx_pri1_drop_bcnt), + GBENU_STATS_HOST(tx_pri2_drop_bcnt), + GBENU_STATS_HOST(tx_pri3_drop_bcnt), + GBENU_STATS_HOST(tx_pri4_drop_bcnt), + GBENU_STATS_HOST(tx_pri5_drop_bcnt), + GBENU_STATS_HOST(tx_pri6_drop_bcnt), + GBENU_STATS_HOST(tx_pri7_drop_bcnt), /* GBENU Module 1 */ GBENU_STATS_P1(rx_good_frames), GBENU_STATS_P1(rx_broadcast_frames), @@ -1021,7 +1040,26 @@ static const struct netcp_ethtool_stat gbenu_et_stats[] = { GBENU_STATS_P1(ale_unknown_mcast_bytes), GBENU_STATS_P1(ale_unknown_bcast), GBENU_STATS_P1(ale_unknown_bcast_bytes), + GBENU_STATS_P1(ale_pol_match), + GBENU_STATS_P1(ale_pol_match_red), + GBENU_STATS_P1(ale_pol_match_yellow), GBENU_STATS_P1(tx_mem_protect_err), + GBENU_STATS_P1(tx_pri0_drop), + GBENU_STATS_P1(tx_pri1_drop), + GBENU_STATS_P1(tx_pri2_drop), + GBENU_STATS_P1(tx_pri3_drop), + GBENU_STATS_P1(tx_pri4_drop), + GBENU_STATS_P1(tx_pri5_drop), + GBENU_STATS_P1(tx_pri6_drop), + GBENU_STATS_P1(tx_pri7_drop), + GBENU_STATS_P1(tx_pri0_drop_bcnt), + GBENU_STATS_P1(tx_pri1_drop_bcnt), + GBENU_STATS_P1(tx_pri2_drop_bcnt), + GBENU_STATS_P1(tx_pri3_drop_bcnt), + GBENU_STATS_P1(tx_pri4_drop_bcnt), + GBENU_STATS_P1(tx_pri5_drop_bcnt), + GBENU_STATS_P1(tx_pri6_drop_bcnt), + GBENU_STATS_P1(tx_pri7_drop_bcnt), /* GBENU Module 2 */ GBENU_STATS_P2(rx_good_frames), GBENU_STATS_P2(rx_broadcast_frames), @@ -1068,7 +1106,26 @@ static const struct netcp_ethtool_stat gbenu_et_stats[] = { GBENU_STATS_P2(ale_unknown_mcast_bytes), GBENU_STATS_P2(ale_unknown_bcast), GBENU_STATS_P2(ale_unknown_bcast_bytes), + GBENU_STATS_P2(ale_pol_match), + GBENU_STATS_P2(ale_pol_match_red), + GBENU_STATS_P2(ale_pol_match_yellow), GBENU_STATS_P2(tx_mem_protect_err), + GBENU_STATS_P2(tx_pri0_drop), + GBENU_STATS_P2(tx_pri1_drop), + GBENU_STATS_P2(tx_pri2_drop), + GBENU_STATS_P2(tx_pri3_drop), + GBENU_STATS_P2(tx_pri4_drop), + GBENU_STATS_P2(tx_pri5_drop), + GBENU_STATS_P2(tx_pri6_drop), + GBENU_STATS_P2(tx_pri7_drop), + GBENU_STATS_P2(tx_pri0_drop_bcnt), + GBENU_STATS_P2(tx_pri1_drop_bcnt), + GBENU_STATS_P2(tx_pri2_drop_bcnt), + GBENU_STATS_P2(tx_pri3_drop_bcnt), + GBENU_STATS_P2(tx_pri4_drop_bcnt), + GBENU_STATS_P2(tx_pri5_drop_bcnt), + GBENU_STATS_P2(tx_pri6_drop_bcnt), + GBENU_STATS_P2(tx_pri7_drop_bcnt), /* GBENU Module 3 */ GBENU_STATS_P3(rx_good_frames), GBENU_STATS_P3(rx_broadcast_frames), @@ -1115,7 +1172,26 @@ static const struct netcp_ethtool_stat gbenu_et_stats[] = { GBENU_STATS_P3(ale_unknown_mcast_bytes
[net-next PATCH v1 0/6] net: netcp: Bug fixes of CPSW statistics collection
This patch set contains bug fixes and enhencements of hw ethernet statistics processing on TI's Keystone2 CPSW ethernet switches. v1: Removes unused defines in PATCH 3/6 based on reviewer's comment WingMan Kwok (6): net: netcp: Fixes the use of spin_lock_bh in timer function net: netcp: Fixes hw statistics module base setting error net: netcp: Fixes error in oversized memory allocation for statistics storage net: netcp: Consolidates statistics collection code net: netcp: Fixes to CPSW statistics collection net: netcp: Adds missing statistics for K2L and K2E drivers/net/ethernet/ti/netcp_ethss.c | 403 ++--- 1 file changed, 324 insertions(+), 79 deletions(-) -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html