* [PATCH v2 1/4] net: emac: implement 802.1Q VLAN TX tagging support @ 2018-10-22 11:04 Christian Lamparter 2018-10-22 11:04 ` [PATCH v2 2/4] net: emac: implement TCP segmentation offload (TSO) Christian Lamparter 0 siblings, 1 reply; 5+ messages in thread From: Christian Lamparter @ 2018-10-22 11:04 UTC (permalink / raw) To: netdev; +Cc: David S . Miller, Florian Fainelli As per' APM82181 Embedded Processor User Manual 26.1 EMAC Features: VLAN: - Support for VLAN tag ID in compliance with IEEE 802.3ac. - VLAN tag insertion or replacement for transmit packets This patch completes the missing code for the VLAN tx tagging support, as the the EMAC_MR1_VLE was already enabled. Signed-off-by: Christian Lamparter <chunkeey@gmail.com> --- drivers/net/ethernet/ibm/emac/core.c | 32 ++++++++++++++++++++++++---- drivers/net/ethernet/ibm/emac/core.h | 6 +++++- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c index 760b2ad8e295..be560f9031f4 100644 --- a/drivers/net/ethernet/ibm/emac/core.c +++ b/drivers/net/ethernet/ibm/emac/core.c @@ -37,6 +37,7 @@ #include <linux/ethtool.h> #include <linux/mii.h> #include <linux/bitops.h> +#include <linux/if_vlan.h> #include <linux/workqueue.h> #include <linux/of.h> #include <linux/of_address.h> @@ -674,7 +675,7 @@ static int emac_configure(struct emac_instance *dev) ndev->dev_addr[5]); /* VLAN Tag Protocol ID */ - out_be32(&p->vtpid, 0x8100); + out_be32(&p->vtpid, ETH_P_8021Q); /* Receive mode register */ r = emac_iff2rmr(ndev); @@ -1435,6 +1436,22 @@ static inline netdev_tx_t emac_xmit_finish(struct emac_instance *dev, int len) return NETDEV_TX_OK; } +static inline u16 emac_tx_vlan(struct emac_instance *dev, struct sk_buff *skb) +{ + /* Handle VLAN TPID and TCI insert if this is a VLAN skb */ + if (emac_has_feature(dev, EMAC_FTR_HAS_VLAN_CTAG_TX) && + skb_vlan_tag_present(skb)) { + struct emac_regs __iomem *p = dev->emacp; + + /* update the VLAN TCI */ + out_be32(&p->vtci, (u32)skb_vlan_tag_get(skb)); + + /* Insert VLAN tag */ + return EMAC_TX_CTRL_IVT; + } + return 0; +} + /* Tx lock BH */ static netdev_tx_t emac_start_xmit(struct sk_buff *skb, struct net_device *ndev) { @@ -1443,7 +1460,7 @@ static netdev_tx_t emac_start_xmit(struct sk_buff *skb, struct net_device *ndev) int slot; u16 ctrl = EMAC_TX_CTRL_GFCS | EMAC_TX_CTRL_GP | MAL_TX_CTRL_READY | - MAL_TX_CTRL_LAST | emac_tx_csum(dev, skb); + MAL_TX_CTRL_LAST | emac_tx_csum(dev, skb) | emac_tx_vlan(dev, skb); slot = dev->tx_slot++; if (dev->tx_slot == NUM_TX_BUFF) { @@ -1518,7 +1535,7 @@ emac_start_xmit_sg(struct sk_buff *skb, struct net_device *ndev) goto stop_queue; ctrl = EMAC_TX_CTRL_GFCS | EMAC_TX_CTRL_GP | MAL_TX_CTRL_READY | - emac_tx_csum(dev, skb); + emac_tx_csum(dev, skb) | emac_tx_vlan(dev, skb); slot = dev->tx_slot; /* skb data */ @@ -2891,7 +2908,8 @@ static int emac_init_config(struct emac_instance *dev) if (of_device_is_compatible(np, "ibm,emac-apm821xx")) { dev->features |= (EMAC_APM821XX_REQ_JUMBO_FRAME_SIZE | EMAC_FTR_APM821XX_NO_HALF_DUPLEX | - EMAC_FTR_460EX_PHY_CLK_FIX); + EMAC_FTR_460EX_PHY_CLK_FIX | + EMAC_FTR_HAS_VLAN_CTAG_TX); } } else if (of_device_is_compatible(np, "ibm,emac4")) { dev->features |= EMAC_FTR_EMAC4; @@ -3148,6 +3166,12 @@ static int emac_probe(struct platform_device *ofdev) if (dev->tah_dev) { ndev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG; + + if (emac_has_feature(dev, EMAC_FTR_HAS_VLAN_CTAG_TX)) { + ndev->vlan_features |= ndev->hw_features; + ndev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX; + } + ndev->features |= ndev->hw_features | NETIF_F_RXCSUM; } ndev->watchdog_timeo = 5 * HZ; diff --git a/drivers/net/ethernet/ibm/emac/core.h b/drivers/net/ethernet/ibm/emac/core.h index 84caa4a3fc52..8d84d439168c 100644 --- a/drivers/net/ethernet/ibm/emac/core.h +++ b/drivers/net/ethernet/ibm/emac/core.h @@ -334,6 +334,8 @@ struct emac_instance { * APM821xx does not support Half Duplex mode */ #define EMAC_FTR_APM821XX_NO_HALF_DUPLEX 0x00001000 +/* EMAC can insert 802.1Q tag */ +#define EMAC_FTR_HAS_VLAN_CTAG_TX 0x00002000 /* Right now, we don't quite handle the always/possible masks on the * most optimal way as we don't have a way to say something like @@ -363,7 +365,9 @@ enum { EMAC_FTR_460EX_PHY_CLK_FIX | EMAC_FTR_440EP_PHY_CLK_FIX | EMAC_APM821XX_REQ_JUMBO_FRAME_SIZE | - EMAC_FTR_APM821XX_NO_HALF_DUPLEX, + EMAC_FTR_APM821XX_NO_HALF_DUPLEX | + EMAC_FTR_HAS_VLAN_CTAG_TX | + 0, }; static inline int emac_has_feature(struct emac_instance *dev, -- 2.19.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v2 2/4] net: emac: implement TCP segmentation offload (TSO) 2018-10-22 11:04 [PATCH v2 1/4] net: emac: implement 802.1Q VLAN TX tagging support Christian Lamparter @ 2018-10-22 11:04 ` Christian Lamparter 2018-10-22 11:04 ` [PATCH v2 3/4] net: emac: remove IBM_EMAC_RX_SKB_HEADROOM Christian Lamparter 2018-10-23 2:55 ` [PATCH v2 2/4] net: emac: implement TCP segmentation offload (TSO) David Miller 0 siblings, 2 replies; 5+ messages in thread From: Christian Lamparter @ 2018-10-22 11:04 UTC (permalink / raw) To: netdev; +Cc: David S . Miller, Florian Fainelli This patch enables TSO(v4) hw feature for emac driver. As atleast the APM82181's TCP/IP acceleration hardware controller (TAH) provides TCP segmentation support in the transmit path. Signed-off-by: Christian Lamparter <chunkeey@gmail.com> --- drivers/net/ethernet/ibm/emac/core.c | 113 ++++++++++++++++++++++++++- drivers/net/ethernet/ibm/emac/core.h | 7 ++ drivers/net/ethernet/ibm/emac/emac.h | 7 ++ drivers/net/ethernet/ibm/emac/tah.c | 22 +++++- drivers/net/ethernet/ibm/emac/tah.h | 2 + 5 files changed, 148 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c index be560f9031f4..b5c4b7d3057d 100644 --- a/drivers/net/ethernet/ibm/emac/core.c +++ b/drivers/net/ethernet/ibm/emac/core.c @@ -38,6 +38,9 @@ #include <linux/mii.h> #include <linux/bitops.h> #include <linux/if_vlan.h> +#include <linux/ip.h> +#include <linux/ipv6.h> +#include <linux/tcp.h> #include <linux/workqueue.h> #include <linux/of.h> #include <linux/of_address.h> @@ -1118,6 +1121,32 @@ static int emac_resize_rx_ring(struct emac_instance *dev, int new_mtu) return ret; } +/* Restriction applied for the segmentation size + * to use HW segmentation offload feature. the size + * of the segment must not be less than 168 bytes for + * DIX formatted segments, or 176 bytes for + * IEEE formatted segments. However based on actual + * tests any MTU less than 416 causes excessive retries + * due to TX FIFO underruns. + */ +const u32 tah_ss[TAH_NO_SSR] = { 1500, 1344, 1152, 960, 768, 416 }; + +/* look-up matching segment size for the given mtu */ +static void emac_find_tso_ss_for_mtu(struct emac_instance *dev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(tah_ss); i++) { + if (tah_ss[i] <= dev->ndev->mtu) + break; + } + /* if no matching segment size is found, set the tso_ss_mtu_start + * variable anyway. This will cause the emac_tx_tso to skip straight + * to the software fallback. + */ + dev->tso_ss_mtu_start = i; +} + /* Process ctx, rtnl_lock semaphore */ static int emac_change_mtu(struct net_device *ndev, int new_mtu) { @@ -1134,6 +1163,7 @@ static int emac_change_mtu(struct net_device *ndev, int new_mtu) if (!ret) { ndev->mtu = new_mtu; + emac_find_tso_ss_for_mtu(dev); dev->rx_skb_size = emac_rx_skb_size(new_mtu); dev->rx_sync_size = emac_rx_sync_size(new_mtu); } @@ -1410,6 +1440,33 @@ static inline u16 emac_tx_csum(struct emac_instance *dev, return 0; } +static int emac_tx_tso(struct emac_instance *dev, struct sk_buff *skb, + u16 *ctrl) +{ + if (emac_has_feature(dev, EMAC_FTR_TAH_HAS_TSO) && skb_is_gso(skb) && + !!(skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))) { + u32 seg_size = 0, i; + + /* Get the MTU */ + seg_size = skb_shinfo(skb)->gso_size + tcp_hdrlen(skb) + + skb_network_header_len(skb); + + for (i = dev->tso_ss_mtu_start; i < ARRAY_SIZE(tah_ss); i++) { + if (tah_ss[i] > seg_size) + continue; + + *ctrl |= EMAC_TX_CTRL_TAH_SSR(i); + return 0; + } + + /* none found fall back to software */ + return -EINVAL; + } + + *ctrl |= emac_tx_csum(dev, skb); + return 0; +} + static inline netdev_tx_t emac_xmit_finish(struct emac_instance *dev, int len) { struct emac_regs __iomem *p = dev->emacp; @@ -1452,8 +1509,49 @@ static inline u16 emac_tx_vlan(struct emac_instance *dev, struct sk_buff *skb) return 0; } +static netdev_tx_t +emac_start_xmit_sg(struct sk_buff *skb, struct net_device *ndev); + +static netdev_tx_t +emac_sw_tso(struct sk_buff *skb, struct net_device *ndev) +{ + struct emac_instance *dev = netdev_priv(ndev); + struct sk_buff *segs, *curr; + unsigned int i, frag_slots; + + /* make sure to not overflow the tx ring */ + frag_slots = dev->tx_cnt; + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i]; + + frag_slots += mal_tx_chunks(skb_frag_size(frag)); + + if (frag_slots >= NUM_TX_BUFF) + return NETDEV_TX_BUSY; + }; + + segs = skb_gso_segment(skb, ndev->features & + ~(NETIF_F_TSO | NETIF_F_TSO6)); + if (IS_ERR_OR_NULL(segs)) { + ++dev->estats.tx_dropped; + dev_kfree_skb_any(skb); + } else { + while (segs) { + curr = segs; + segs = curr->next; + curr->next = NULL; + + emac_start_xmit_sg(curr, ndev); + } + dev_consume_skb_any(skb); + } + + return NETDEV_TX_OK; +} + /* Tx lock BH */ -static netdev_tx_t emac_start_xmit(struct sk_buff *skb, struct net_device *ndev) +static netdev_tx_t +emac_start_xmit(struct sk_buff *skb, struct net_device *ndev) { struct emac_instance *dev = netdev_priv(ndev); unsigned int len = skb->len; @@ -1535,7 +1633,10 @@ emac_start_xmit_sg(struct sk_buff *skb, struct net_device *ndev) goto stop_queue; ctrl = EMAC_TX_CTRL_GFCS | EMAC_TX_CTRL_GP | MAL_TX_CTRL_READY | - emac_tx_csum(dev, skb) | emac_tx_vlan(dev, skb); + emac_tx_vlan(dev, skb); + if (emac_tx_tso(dev, skb, &ctrl)) + return emac_sw_tso(skb, ndev); + slot = dev->tx_slot; /* skb data */ @@ -2946,6 +3047,9 @@ static int emac_init_config(struct emac_instance *dev) if (dev->tah_ph != 0) { #ifdef CONFIG_IBM_EMAC_TAH dev->features |= EMAC_FTR_HAS_TAH; + + if (of_device_is_compatible(np, "ibm,emac-apm821xx")) + dev->features |= EMAC_FTR_TAH_HAS_TSO; #else printk(KERN_ERR "%pOF: TAH support not enabled !\n", np); return -ENXIO; @@ -3113,6 +3217,8 @@ static int emac_probe(struct platform_device *ofdev) } dev->rx_skb_size = emac_rx_skb_size(ndev->mtu); dev->rx_sync_size = emac_rx_sync_size(ndev->mtu); + ndev->gso_max_segs = NUM_TX_BUFF / 2; + emac_find_tso_ss_for_mtu(dev); /* Get pointers to BD rings */ dev->tx_desc = @@ -3167,6 +3273,9 @@ static int emac_probe(struct platform_device *ofdev) if (dev->tah_dev) { ndev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG; + if (emac_has_feature(dev, EMAC_FTR_TAH_HAS_TSO)) + ndev->hw_features |= NETIF_F_TSO; + if (emac_has_feature(dev, EMAC_FTR_HAS_VLAN_CTAG_TX)) { ndev->vlan_features |= ndev->hw_features; ndev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX; diff --git a/drivers/net/ethernet/ibm/emac/core.h b/drivers/net/ethernet/ibm/emac/core.h index 8d84d439168c..0bcfe952a3cf 100644 --- a/drivers/net/ethernet/ibm/emac/core.h +++ b/drivers/net/ethernet/ibm/emac/core.h @@ -245,6 +245,9 @@ struct emac_instance { u32 xaht_slots_shift; u32 xaht_width_shift; + /* TAH TSO start index */ + int tso_ss_mtu_start; + /* Descriptor management */ struct mal_descriptor *tx_desc; @@ -336,6 +339,8 @@ struct emac_instance { #define EMAC_FTR_APM821XX_NO_HALF_DUPLEX 0x00001000 /* EMAC can insert 802.1Q tag */ #define EMAC_FTR_HAS_VLAN_CTAG_TX 0x00002000 +/* TAH can do TCP segmentation offload */ +#define EMAC_FTR_TAH_HAS_TSO 0x00004000 /* Right now, we don't quite handle the always/possible masks on the * most optimal way as we don't have a way to say something like @@ -352,6 +357,8 @@ enum { #endif #ifdef CONFIG_IBM_EMAC_TAH EMAC_FTR_HAS_TAH | + EMAC_FTR_TAH_HAS_TSO | + #endif #ifdef CONFIG_IBM_EMAC_ZMII EMAC_FTR_HAS_ZMII | diff --git a/drivers/net/ethernet/ibm/emac/emac.h b/drivers/net/ethernet/ibm/emac/emac.h index e2f80cca9bed..833967aceb2f 100644 --- a/drivers/net/ethernet/ibm/emac/emac.h +++ b/drivers/net/ethernet/ibm/emac/emac.h @@ -266,6 +266,13 @@ struct emac_regs { #define EMAC_TX_CTRL_IVT 0x0020 #define EMAC_TX_CTRL_RVT 0x0010 #define EMAC_TX_CTRL_TAH_CSUM 0x000e +#define EMAC_TX_CTRL_TAH_SSR(idx) (((idx) + 1) << 1) +#define EMAC_TX_CTRL_TAH_SSR5 0x000c +#define EMAC_TX_CTRL_TAH_SSR4 0x000a +#define EMAC_TX_CTRL_TAH_SSR3 0x0008 +#define EMAC_TX_CTRL_TAH_SSR2 0x0006 +#define EMAC_TX_CTRL_TAH_SSR1 0x0004 +#define EMAC_TX_CTRL_TAH_SSR0 0x0002 /* EMAC specific TX descriptor status fields (read access) */ #define EMAC_TX_ST_BFCS 0x0200 diff --git a/drivers/net/ethernet/ibm/emac/tah.c b/drivers/net/ethernet/ibm/emac/tah.c index 9912456dca48..619c08ee22f7 100644 --- a/drivers/net/ethernet/ibm/emac/tah.c +++ b/drivers/net/ethernet/ibm/emac/tah.c @@ -45,6 +45,24 @@ void tah_detach(struct platform_device *ofdev, int channel) mutex_unlock(&dev->lock); } +static void tah_set_ssr(struct platform_device *ofdev) +{ + struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); + struct tah_regs __iomem *p = dev->base; + int i; + + mutex_lock(&dev->lock); + + for (i = 0; i < ARRAY_SIZE(tah_ss); i++) { + /* Segment size can be up to 16K, but needs + * to be a multiple of 2 bytes + */ + out_be32(&p->ssr0 + i, (tah_ss[i] & 0x3ffc) << 16); + } + + mutex_unlock(&dev->lock); +} + void tah_reset(struct platform_device *ofdev) { struct tah_instance *dev = platform_get_drvdata(ofdev); @@ -64,6 +82,8 @@ void tah_reset(struct platform_device *ofdev) out_be32(&p->mr, TAH_MR_CVR | TAH_MR_ST_768 | TAH_MR_TFS_10KB | TAH_MR_DTFP | TAH_MR_DIG); + + tah_set_ssr(ofdev); } int tah_get_regs_len(struct platform_device *ofdev) @@ -118,7 +138,7 @@ static int tah_probe(struct platform_device *ofdev) platform_set_drvdata(ofdev, dev); - /* Initialize TAH and enable IPv4 checksum verification, no TSO yet */ + /* Initialize TAH and enable IPv4 checksum verification */ tah_reset(ofdev); printk(KERN_INFO "TAH %pOF initialized\n", ofdev->dev.of_node); diff --git a/drivers/net/ethernet/ibm/emac/tah.h b/drivers/net/ethernet/ibm/emac/tah.h index 4d5f336f07b3..2cb0629f30e2 100644 --- a/drivers/net/ethernet/ibm/emac/tah.h +++ b/drivers/net/ethernet/ibm/emac/tah.h @@ -36,6 +36,8 @@ struct tah_regs { u32 tsr; }; +#define TAH_NO_SSR 6 +extern const u32 tah_ss[TAH_NO_SSR]; /* TAH device */ struct tah_instance { -- 2.19.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v2 3/4] net: emac: remove IBM_EMAC_RX_SKB_HEADROOM 2018-10-22 11:04 ` [PATCH v2 2/4] net: emac: implement TCP segmentation offload (TSO) Christian Lamparter @ 2018-10-22 11:04 ` Christian Lamparter 2018-10-22 11:04 ` [PATCH v2 4/4] net: emac: add deprecation notice to emac custom phy users Christian Lamparter 2018-10-23 2:55 ` [PATCH v2 2/4] net: emac: implement TCP segmentation offload (TSO) David Miller 1 sibling, 1 reply; 5+ messages in thread From: Christian Lamparter @ 2018-10-22 11:04 UTC (permalink / raw) To: netdev; +Cc: David S . Miller, Florian Fainelli The EMAC driver had a custom IBM_EMAC_RX_SKB_HEADROOM Kconfig option that reserved additional skb headroom for RX. This patch removes the option and migrates the code to use napi_alloc_skb() and netdev_alloc_skb_ip_align() in its place. Signed-off-by: Christian Lamparter <chunkeey@gmail.com> --- drivers/net/ethernet/ibm/emac/Kconfig | 12 ------ drivers/net/ethernet/ibm/emac/core.c | 57 +++++++++++++++++++-------- drivers/net/ethernet/ibm/emac/core.h | 10 ++--- 3 files changed, 43 insertions(+), 36 deletions(-) diff --git a/drivers/net/ethernet/ibm/emac/Kconfig b/drivers/net/ethernet/ibm/emac/Kconfig index 90d49191beb3..eacf7e141fdc 100644 --- a/drivers/net/ethernet/ibm/emac/Kconfig +++ b/drivers/net/ethernet/ibm/emac/Kconfig @@ -28,18 +28,6 @@ config IBM_EMAC_RX_COPY_THRESHOLD depends on IBM_EMAC default "256" -config IBM_EMAC_RX_SKB_HEADROOM - int "Additional RX skb headroom (bytes)" - depends on IBM_EMAC - default "0" - help - Additional receive skb headroom. Note, that driver - will always reserve at least 2 bytes to make IP header - aligned, so usually there is no need to add any additional - headroom. - - If unsure, set to 0. - config IBM_EMAC_DEBUG bool "Debugging" depends on IBM_EMAC diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c index b5c4b7d3057d..388443e08674 100644 --- a/drivers/net/ethernet/ibm/emac/core.c +++ b/drivers/net/ethernet/ibm/emac/core.c @@ -1075,7 +1075,9 @@ static int emac_resize_rx_ring(struct emac_instance *dev, int new_mtu) /* Second pass, allocate new skbs */ for (i = 0; i < NUM_RX_BUFF; ++i) { - struct sk_buff *skb = alloc_skb(rx_skb_size, GFP_ATOMIC); + struct sk_buff *skb; + + skb = netdev_alloc_skb_ip_align(dev->ndev, rx_skb_size); if (!skb) { ret = -ENOMEM; goto oom; @@ -1084,7 +1086,6 @@ static int emac_resize_rx_ring(struct emac_instance *dev, int new_mtu) BUG_ON(!dev->rx_skb[i]); dev_kfree_skb(dev->rx_skb[i]); - skb_reserve(skb, EMAC_RX_SKB_HEADROOM + 2); dev->rx_desc[i].data_ptr = dma_map_single(&dev->ofdev->dev, skb->data - 2, rx_sync_size, DMA_FROM_DEVICE) + 2; @@ -1205,20 +1206,18 @@ static void emac_clean_rx_ring(struct emac_instance *dev) } } -static inline int emac_alloc_rx_skb(struct emac_instance *dev, int slot, - gfp_t flags) +static inline int +__emac_prepare_rx_skb(struct sk_buff *skb, struct emac_instance *dev, int slot) { - struct sk_buff *skb = alloc_skb(dev->rx_skb_size, flags); if (unlikely(!skb)) return -ENOMEM; dev->rx_skb[slot] = skb; dev->rx_desc[slot].data_len = 0; - skb_reserve(skb, EMAC_RX_SKB_HEADROOM + 2); dev->rx_desc[slot].data_ptr = - dma_map_single(&dev->ofdev->dev, skb->data - 2, dev->rx_sync_size, - DMA_FROM_DEVICE) + 2; + dma_map_single(&dev->ofdev->dev, skb->data - NET_IP_ALIGN, + dev->rx_sync_size, DMA_FROM_DEVICE) + NET_IP_ALIGN; wmb(); dev->rx_desc[slot].ctrl = MAL_RX_CTRL_EMPTY | (slot == (NUM_RX_BUFF - 1) ? MAL_RX_CTRL_WRAP : 0); @@ -1226,6 +1225,27 @@ static inline int emac_alloc_rx_skb(struct emac_instance *dev, int slot, return 0; } +static inline int +emac_alloc_rx_skb(struct emac_instance *dev, int slot) +{ + struct sk_buff *skb; + + skb = __netdev_alloc_skb_ip_align(dev->ndev, dev->rx_skb_size, + GFP_KERNEL); + + return __emac_prepare_rx_skb(skb, dev, slot); +} + +static inline int +emac_alloc_rx_skb_napi(struct emac_instance *dev, int slot) +{ + struct sk_buff *skb; + + skb = napi_alloc_skb(&dev->mal->napi, dev->rx_skb_size); + + return __emac_prepare_rx_skb(skb, dev, slot); +} + static void emac_print_link_status(struct emac_instance *dev) { if (netif_carrier_ok(dev->ndev)) @@ -1256,7 +1276,7 @@ static int emac_open(struct net_device *ndev) /* Allocate RX ring */ for (i = 0; i < NUM_RX_BUFF; ++i) - if (emac_alloc_rx_skb(dev, i, GFP_KERNEL)) { + if (emac_alloc_rx_skb(dev, i)) { printk(KERN_ERR "%s: failed to allocate RX ring\n", ndev->name); goto oom; @@ -1778,8 +1798,9 @@ static inline void emac_recycle_rx_skb(struct emac_instance *dev, int slot, DBG2(dev, "recycle %d %d" NL, slot, len); if (len) - dma_map_single(&dev->ofdev->dev, skb->data - 2, - EMAC_DMA_ALIGN(len + 2), DMA_FROM_DEVICE); + dma_map_single(&dev->ofdev->dev, skb->data - NET_IP_ALIGN, + SKB_DATA_ALIGN(len + NET_IP_ALIGN), + DMA_FROM_DEVICE); dev->rx_desc[slot].data_len = 0; wmb(); @@ -1887,16 +1908,18 @@ static int emac_poll_rx(void *param, int budget) } if (len && len < EMAC_RX_COPY_THRESH) { - struct sk_buff *copy_skb = - alloc_skb(len + EMAC_RX_SKB_HEADROOM + 2, GFP_ATOMIC); + struct sk_buff *copy_skb; + + copy_skb = napi_alloc_skb(&dev->mal->napi, len); if (unlikely(!copy_skb)) goto oom; - skb_reserve(copy_skb, EMAC_RX_SKB_HEADROOM + 2); - memcpy(copy_skb->data - 2, skb->data - 2, len + 2); + memcpy(copy_skb->data - NET_IP_ALIGN, + skb->data - NET_IP_ALIGN, + len + NET_IP_ALIGN); emac_recycle_rx_skb(dev, slot, len); skb = copy_skb; - } else if (unlikely(emac_alloc_rx_skb(dev, slot, GFP_ATOMIC))) + } else if (unlikely(emac_alloc_rx_skb_napi(dev, slot))) goto oom; skb_put(skb, len); @@ -1917,7 +1940,7 @@ static int emac_poll_rx(void *param, int budget) sg: if (ctrl & MAL_RX_CTRL_FIRST) { BUG_ON(dev->rx_sg_skb); - if (unlikely(emac_alloc_rx_skb(dev, slot, GFP_ATOMIC))) { + if (unlikely(emac_alloc_rx_skb_napi(dev, slot))) { DBG(dev, "rx OOM %d" NL, slot); ++dev->estats.rx_dropped_oom; emac_recycle_rx_skb(dev, slot, 0); diff --git a/drivers/net/ethernet/ibm/emac/core.h b/drivers/net/ethernet/ibm/emac/core.h index 0bcfe952a3cf..0faeb7c7e958 100644 --- a/drivers/net/ethernet/ibm/emac/core.h +++ b/drivers/net/ethernet/ibm/emac/core.h @@ -68,22 +68,18 @@ static inline int emac_rx_size(int mtu) return mal_rx_size(ETH_DATA_LEN + EMAC_MTU_OVERHEAD); } -#define EMAC_DMA_ALIGN(x) ALIGN((x), dma_get_cache_alignment()) - -#define EMAC_RX_SKB_HEADROOM \ - EMAC_DMA_ALIGN(CONFIG_IBM_EMAC_RX_SKB_HEADROOM) - /* Size of RX skb for the given MTU */ static inline int emac_rx_skb_size(int mtu) { int size = max(mtu + EMAC_MTU_OVERHEAD, emac_rx_size(mtu)); - return EMAC_DMA_ALIGN(size + 2) + EMAC_RX_SKB_HEADROOM; + + return SKB_DATA_ALIGN(size + NET_SKB_PAD + NET_IP_ALIGN); } /* RX DMA sync size */ static inline int emac_rx_sync_size(int mtu) { - return EMAC_DMA_ALIGN(emac_rx_size(mtu) + 2); + return SKB_DATA_ALIGN(emac_rx_size(mtu) + NET_IP_ALIGN); } /* Driver statistcs is split into two parts to make it more cache friendly: -- 2.19.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v2 4/4] net: emac: add deprecation notice to emac custom phy users 2018-10-22 11:04 ` [PATCH v2 3/4] net: emac: remove IBM_EMAC_RX_SKB_HEADROOM Christian Lamparter @ 2018-10-22 11:04 ` Christian Lamparter 0 siblings, 0 replies; 5+ messages in thread From: Christian Lamparter @ 2018-10-22 11:04 UTC (permalink / raw) To: netdev; +Cc: Christian Lamparter, David S . Miller, Florian Fainelli From: Christian Lamparter <chunkeey@googlemail.com> This patch starts the deprecation process of emac's small library of supported phys by adding a message to inform all remaining users to start looking into converting their platform's device-tree to PHYLIB. EMAC's phy.c support is limited to mostly single ethernet transceivers: CIS8201, BCM5248, ET1011C, Marvell 88E1111 and 88E1112, AR8035. And Linux has dedicated PHYLIB drivers for all but the BCM5248 which can be supported by the generic phy driver. Signed-off-by: Christian Lamparter <chunkeey@googlemail.com> --- drivers/net/ethernet/ibm/emac/phy.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/ethernet/ibm/emac/phy.c b/drivers/net/ethernet/ibm/emac/phy.c index aa070c063e48..143b4c688ee9 100644 --- a/drivers/net/ethernet/ibm/emac/phy.c +++ b/drivers/net/ethernet/ibm/emac/phy.c @@ -496,6 +496,7 @@ static struct mii_phy_def ar8035_phy_def = { }; static struct mii_phy_def *mii_phy_table[] = { + /* DEPRECATED: Do not add any new PHY drivers to this list. */ &et1011c_phy_def, &cis8201_phy_def, &bcm5248_phy_def, @@ -512,6 +513,9 @@ int emac_mii_phy_probe(struct mii_phy *phy, int address) int i; u32 id; + pr_info("EMAC's custom phy code has been deprecated.\n" + "Please convert your EMAC device to PHYLIB.\n"); + phy->autoneg = AUTONEG_DISABLE; phy->advertising = 0; phy->address = address; -- 2.19.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v2 2/4] net: emac: implement TCP segmentation offload (TSO) 2018-10-22 11:04 ` [PATCH v2 2/4] net: emac: implement TCP segmentation offload (TSO) Christian Lamparter 2018-10-22 11:04 ` [PATCH v2 3/4] net: emac: remove IBM_EMAC_RX_SKB_HEADROOM Christian Lamparter @ 2018-10-23 2:55 ` David Miller 1 sibling, 0 replies; 5+ messages in thread From: David Miller @ 2018-10-23 2:55 UTC (permalink / raw) To: chunkeey; +Cc: netdev, f.fainelli From: Christian Lamparter <chunkeey@gmail.com> Date: Mon, 22 Oct 2018 13:04:12 +0200 > @@ -1452,8 +1509,49 @@ static inline u16 emac_tx_vlan(struct emac_instance *dev, struct sk_buff *skb) > return 0; > } > > +static netdev_tx_t > +emac_start_xmit_sg(struct sk_buff *skb, struct net_device *ndev); > + > +static netdev_tx_t > +emac_sw_tso(struct sk_buff *skb, struct net_device *ndev) > +{ > + struct emac_instance *dev = netdev_priv(ndev); > + struct sk_buff *segs, *curr; > + unsigned int i, frag_slots; > + > + /* make sure to not overflow the tx ring */ > + frag_slots = dev->tx_cnt; > + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { > + struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i]; > + > + frag_slots += mal_tx_chunks(skb_frag_size(frag)); > + > + if (frag_slots >= NUM_TX_BUFF) > + return NETDEV_TX_BUSY; > + }; > + > + segs = skb_gso_segment(skb, ndev->features & > + ~(NETIF_F_TSO | NETIF_F_TSO6)); This NETDEV_TX_BUSY isn't going to work. Your TX queue is awake. So there won't be any guaranteed event to "wake up" the queue and try sending this SKB again. Please take a look at how the tg3.c driver handles this situation. You have to first stop the queue, do you overflow test, and then you can return NETDEV_TX_BUSY if necessary. ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2018-10-23 11:17 UTC | newest] Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2018-10-22 11:04 [PATCH v2 1/4] net: emac: implement 802.1Q VLAN TX tagging support Christian Lamparter 2018-10-22 11:04 ` [PATCH v2 2/4] net: emac: implement TCP segmentation offload (TSO) Christian Lamparter 2018-10-22 11:04 ` [PATCH v2 3/4] net: emac: remove IBM_EMAC_RX_SKB_HEADROOM Christian Lamparter 2018-10-22 11:04 ` [PATCH v2 4/4] net: emac: add deprecation notice to emac custom phy users Christian Lamparter 2018-10-23 2:55 ` [PATCH v2 2/4] net: emac: implement TCP segmentation offload (TSO) David Miller
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.