18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright(c) 2020 Intel Corporation. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include "netdev.h" 88c2ecf20Sopenharmony_ci#include "ipoib.h" 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#define HFI1_IPOIB_SKB_PAD ((NET_SKB_PAD) + (NET_IP_ALIGN)) 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_cistatic void copy_ipoib_buf(struct sk_buff *skb, void *data, int size) 138c2ecf20Sopenharmony_ci{ 148c2ecf20Sopenharmony_ci void *dst_data; 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci skb_checksum_none_assert(skb); 178c2ecf20Sopenharmony_ci skb->protocol = *((__be16 *)data); 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci dst_data = skb_put(skb, size); 208c2ecf20Sopenharmony_ci memcpy(dst_data, data, size); 218c2ecf20Sopenharmony_ci skb->mac_header = HFI1_IPOIB_PSEUDO_LEN; 228c2ecf20Sopenharmony_ci skb_pull(skb, HFI1_IPOIB_ENCAP_LEN); 238c2ecf20Sopenharmony_ci} 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_cistatic struct sk_buff *prepare_frag_skb(struct napi_struct *napi, int size) 268c2ecf20Sopenharmony_ci{ 278c2ecf20Sopenharmony_ci struct sk_buff *skb; 288c2ecf20Sopenharmony_ci int skb_size = SKB_DATA_ALIGN(size + HFI1_IPOIB_SKB_PAD); 298c2ecf20Sopenharmony_ci void *frag; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci skb_size += SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); 328c2ecf20Sopenharmony_ci skb_size = SKB_DATA_ALIGN(skb_size); 338c2ecf20Sopenharmony_ci frag = napi_alloc_frag(skb_size); 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci if (unlikely(!frag)) 368c2ecf20Sopenharmony_ci return napi_alloc_skb(napi, size); 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci skb = build_skb(frag, skb_size); 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci if (unlikely(!skb)) { 418c2ecf20Sopenharmony_ci skb_free_frag(frag); 428c2ecf20Sopenharmony_ci return NULL; 438c2ecf20Sopenharmony_ci } 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci skb_reserve(skb, HFI1_IPOIB_SKB_PAD); 468c2ecf20Sopenharmony_ci return skb; 478c2ecf20Sopenharmony_ci} 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_cistruct sk_buff *hfi1_ipoib_prepare_skb(struct hfi1_netdev_rxq *rxq, 508c2ecf20Sopenharmony_ci int size, void *data) 518c2ecf20Sopenharmony_ci{ 528c2ecf20Sopenharmony_ci struct napi_struct *napi = &rxq->napi; 538c2ecf20Sopenharmony_ci int skb_size = size + HFI1_IPOIB_ENCAP_LEN; 548c2ecf20Sopenharmony_ci struct sk_buff *skb; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci /* 578c2ecf20Sopenharmony_ci * For smaller(4k + skb overhead) allocations we will go using 588c2ecf20Sopenharmony_ci * napi cache. Otherwise we will try to use napi frag cache. 598c2ecf20Sopenharmony_ci */ 608c2ecf20Sopenharmony_ci if (size <= SKB_WITH_OVERHEAD(PAGE_SIZE)) 618c2ecf20Sopenharmony_ci skb = napi_alloc_skb(napi, skb_size); 628c2ecf20Sopenharmony_ci else 638c2ecf20Sopenharmony_ci skb = prepare_frag_skb(napi, skb_size); 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci if (unlikely(!skb)) 668c2ecf20Sopenharmony_ci return NULL; 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci copy_ipoib_buf(skb, data, size); 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci return skb; 718c2ecf20Sopenharmony_ci} 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ciint hfi1_ipoib_rxq_init(struct net_device *netdev) 748c2ecf20Sopenharmony_ci{ 758c2ecf20Sopenharmony_ci struct hfi1_ipoib_dev_priv *ipoib_priv = hfi1_ipoib_priv(netdev); 768c2ecf20Sopenharmony_ci struct hfi1_devdata *dd = ipoib_priv->dd; 778c2ecf20Sopenharmony_ci int ret; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci ret = hfi1_netdev_rx_init(dd); 808c2ecf20Sopenharmony_ci if (ret) 818c2ecf20Sopenharmony_ci return ret; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci hfi1_init_aip_rsm(dd); 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci return ret; 868c2ecf20Sopenharmony_ci} 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_civoid hfi1_ipoib_rxq_deinit(struct net_device *netdev) 898c2ecf20Sopenharmony_ci{ 908c2ecf20Sopenharmony_ci struct hfi1_ipoib_dev_priv *ipoib_priv = hfi1_ipoib_priv(netdev); 918c2ecf20Sopenharmony_ci struct hfi1_devdata *dd = ipoib_priv->dd; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci hfi1_deinit_aip_rsm(dd); 948c2ecf20Sopenharmony_ci hfi1_netdev_rx_destroy(dd); 958c2ecf20Sopenharmony_ci} 96