16991abcbSKaike Wan // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) 26991abcbSKaike Wan /* 36991abcbSKaike Wan * Copyright(c) 2020 Intel Corporation. 46991abcbSKaike Wan * 56991abcbSKaike Wan */ 66991abcbSKaike Wan 76991abcbSKaike Wan #include "netdev.h" 86991abcbSKaike Wan #include "ipoib.h" 96991abcbSKaike Wan 106991abcbSKaike Wan #define HFI1_IPOIB_SKB_PAD ((NET_SKB_PAD) + (NET_IP_ALIGN)) 116991abcbSKaike Wan 126991abcbSKaike Wan static void copy_ipoib_buf(struct sk_buff *skb, void *data, int size) 136991abcbSKaike Wan { 146991abcbSKaike Wan skb_checksum_none_assert(skb); 156991abcbSKaike Wan skb->protocol = *((__be16 *)data); 166991abcbSKaike Wan 17*cbdae01dSShang XiaoJing skb_put_data(skb, data, size); 186991abcbSKaike Wan skb->mac_header = HFI1_IPOIB_PSEUDO_LEN; 196991abcbSKaike Wan skb_pull(skb, HFI1_IPOIB_ENCAP_LEN); 206991abcbSKaike Wan } 216991abcbSKaike Wan 226991abcbSKaike Wan static struct sk_buff *prepare_frag_skb(struct napi_struct *napi, int size) 236991abcbSKaike Wan { 246991abcbSKaike Wan struct sk_buff *skb; 256991abcbSKaike Wan int skb_size = SKB_DATA_ALIGN(size + HFI1_IPOIB_SKB_PAD); 266991abcbSKaike Wan void *frag; 276991abcbSKaike Wan 286991abcbSKaike Wan skb_size += SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); 296991abcbSKaike Wan skb_size = SKB_DATA_ALIGN(skb_size); 306991abcbSKaike Wan frag = napi_alloc_frag(skb_size); 316991abcbSKaike Wan 326991abcbSKaike Wan if (unlikely(!frag)) 336991abcbSKaike Wan return napi_alloc_skb(napi, size); 346991abcbSKaike Wan 356991abcbSKaike Wan skb = build_skb(frag, skb_size); 366991abcbSKaike Wan 376991abcbSKaike Wan if (unlikely(!skb)) { 386991abcbSKaike Wan skb_free_frag(frag); 396991abcbSKaike Wan return NULL; 406991abcbSKaike Wan } 416991abcbSKaike Wan 426991abcbSKaike Wan skb_reserve(skb, HFI1_IPOIB_SKB_PAD); 436991abcbSKaike Wan return skb; 446991abcbSKaike Wan } 456991abcbSKaike Wan 466991abcbSKaike Wan struct sk_buff *hfi1_ipoib_prepare_skb(struct hfi1_netdev_rxq *rxq, 476991abcbSKaike Wan int size, void *data) 486991abcbSKaike Wan { 496991abcbSKaike Wan struct napi_struct *napi = &rxq->napi; 506991abcbSKaike Wan int skb_size = size + HFI1_IPOIB_ENCAP_LEN; 516991abcbSKaike Wan struct sk_buff *skb; 526991abcbSKaike Wan 536991abcbSKaike Wan /* 546991abcbSKaike Wan * For smaller(4k + skb overhead) allocations we will go using 556991abcbSKaike Wan * napi cache. Otherwise we will try to use napi frag cache. 566991abcbSKaike Wan */ 576991abcbSKaike Wan if (size <= SKB_WITH_OVERHEAD(PAGE_SIZE)) 586991abcbSKaike Wan skb = napi_alloc_skb(napi, skb_size); 596991abcbSKaike Wan else 606991abcbSKaike Wan skb = prepare_frag_skb(napi, skb_size); 616991abcbSKaike Wan 626991abcbSKaike Wan if (unlikely(!skb)) 636991abcbSKaike Wan return NULL; 646991abcbSKaike Wan 656991abcbSKaike Wan copy_ipoib_buf(skb, data, size); 666991abcbSKaike Wan 676991abcbSKaike Wan return skb; 686991abcbSKaike Wan } 69370caa5bSGrzegorz Andrejczuk 70370caa5bSGrzegorz Andrejczuk int hfi1_ipoib_rxq_init(struct net_device *netdev) 71370caa5bSGrzegorz Andrejczuk { 72370caa5bSGrzegorz Andrejczuk struct hfi1_ipoib_dev_priv *ipoib_priv = hfi1_ipoib_priv(netdev); 73370caa5bSGrzegorz Andrejczuk struct hfi1_devdata *dd = ipoib_priv->dd; 744730f4a6SGrzegorz Andrejczuk int ret; 75370caa5bSGrzegorz Andrejczuk 764730f4a6SGrzegorz Andrejczuk ret = hfi1_netdev_rx_init(dd); 774730f4a6SGrzegorz Andrejczuk if (ret) 784730f4a6SGrzegorz Andrejczuk return ret; 794730f4a6SGrzegorz Andrejczuk 804730f4a6SGrzegorz Andrejczuk hfi1_init_aip_rsm(dd); 814730f4a6SGrzegorz Andrejczuk 824730f4a6SGrzegorz Andrejczuk return ret; 83370caa5bSGrzegorz Andrejczuk } 84370caa5bSGrzegorz Andrejczuk 85370caa5bSGrzegorz Andrejczuk void hfi1_ipoib_rxq_deinit(struct net_device *netdev) 86370caa5bSGrzegorz Andrejczuk { 87370caa5bSGrzegorz Andrejczuk struct hfi1_ipoib_dev_priv *ipoib_priv = hfi1_ipoib_priv(netdev); 88370caa5bSGrzegorz Andrejczuk struct hfi1_devdata *dd = ipoib_priv->dd; 89370caa5bSGrzegorz Andrejczuk 904730f4a6SGrzegorz Andrejczuk hfi1_deinit_aip_rsm(dd); 91370caa5bSGrzegorz Andrejczuk hfi1_netdev_rx_destroy(dd); 92370caa5bSGrzegorz Andrejczuk } 93