18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) 2014-2015 Hisilicon Limited. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h> 78c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 88c2ecf20Sopenharmony_ci#include <linux/of.h> 98c2ecf20Sopenharmony_ci#include <linux/skbuff.h> 108c2ecf20Sopenharmony_ci#include <linux/slab.h> 118c2ecf20Sopenharmony_ci#include "hnae.h" 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#define cls_to_ae_dev(dev) container_of(dev, struct hnae_ae_dev, cls_dev) 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_cistatic struct class *hnae_class; 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_cistatic void 188c2ecf20Sopenharmony_cihnae_list_add(spinlock_t *lock, struct list_head *node, struct list_head *head) 198c2ecf20Sopenharmony_ci{ 208c2ecf20Sopenharmony_ci unsigned long flags; 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci spin_lock_irqsave(lock, flags); 238c2ecf20Sopenharmony_ci list_add_tail_rcu(node, head); 248c2ecf20Sopenharmony_ci spin_unlock_irqrestore(lock, flags); 258c2ecf20Sopenharmony_ci} 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_cistatic void hnae_list_del(spinlock_t *lock, struct list_head *node) 288c2ecf20Sopenharmony_ci{ 298c2ecf20Sopenharmony_ci unsigned long flags; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci spin_lock_irqsave(lock, flags); 328c2ecf20Sopenharmony_ci list_del_rcu(node); 338c2ecf20Sopenharmony_ci spin_unlock_irqrestore(lock, flags); 348c2ecf20Sopenharmony_ci} 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cistatic int hnae_alloc_buffer(struct hnae_ring *ring, struct hnae_desc_cb *cb) 378c2ecf20Sopenharmony_ci{ 388c2ecf20Sopenharmony_ci unsigned int order = hnae_page_order(ring); 398c2ecf20Sopenharmony_ci struct page *p = dev_alloc_pages(order); 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci if (!p) 428c2ecf20Sopenharmony_ci return -ENOMEM; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci cb->priv = p; 458c2ecf20Sopenharmony_ci cb->page_offset = 0; 468c2ecf20Sopenharmony_ci cb->reuse_flag = 0; 478c2ecf20Sopenharmony_ci cb->buf = page_address(p); 488c2ecf20Sopenharmony_ci cb->length = hnae_page_size(ring); 498c2ecf20Sopenharmony_ci cb->type = DESC_TYPE_PAGE; 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci return 0; 528c2ecf20Sopenharmony_ci} 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_cistatic void hnae_free_buffer(struct hnae_ring *ring, struct hnae_desc_cb *cb) 558c2ecf20Sopenharmony_ci{ 568c2ecf20Sopenharmony_ci if (unlikely(!cb->priv)) 578c2ecf20Sopenharmony_ci return; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci if (cb->type == DESC_TYPE_SKB) 608c2ecf20Sopenharmony_ci dev_kfree_skb_any((struct sk_buff *)cb->priv); 618c2ecf20Sopenharmony_ci else if (unlikely(is_rx_ring(ring))) 628c2ecf20Sopenharmony_ci put_page((struct page *)cb->priv); 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci cb->priv = NULL; 658c2ecf20Sopenharmony_ci} 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_cistatic int hnae_map_buffer(struct hnae_ring *ring, struct hnae_desc_cb *cb) 688c2ecf20Sopenharmony_ci{ 698c2ecf20Sopenharmony_ci cb->dma = dma_map_page(ring_to_dev(ring), cb->priv, 0, 708c2ecf20Sopenharmony_ci cb->length, ring_to_dma_dir(ring)); 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci if (dma_mapping_error(ring_to_dev(ring), cb->dma)) 738c2ecf20Sopenharmony_ci return -EIO; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci return 0; 768c2ecf20Sopenharmony_ci} 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_cistatic void hnae_unmap_buffer(struct hnae_ring *ring, struct hnae_desc_cb *cb) 798c2ecf20Sopenharmony_ci{ 808c2ecf20Sopenharmony_ci if (cb->type == DESC_TYPE_SKB) 818c2ecf20Sopenharmony_ci dma_unmap_single(ring_to_dev(ring), cb->dma, cb->length, 828c2ecf20Sopenharmony_ci ring_to_dma_dir(ring)); 838c2ecf20Sopenharmony_ci else if (cb->length) 848c2ecf20Sopenharmony_ci dma_unmap_page(ring_to_dev(ring), cb->dma, cb->length, 858c2ecf20Sopenharmony_ci ring_to_dma_dir(ring)); 868c2ecf20Sopenharmony_ci} 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_cistatic struct hnae_buf_ops hnae_bops = { 898c2ecf20Sopenharmony_ci .alloc_buffer = hnae_alloc_buffer, 908c2ecf20Sopenharmony_ci .free_buffer = hnae_free_buffer, 918c2ecf20Sopenharmony_ci .map_buffer = hnae_map_buffer, 928c2ecf20Sopenharmony_ci .unmap_buffer = hnae_unmap_buffer, 938c2ecf20Sopenharmony_ci}; 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_cistatic int __ae_match(struct device *dev, const void *data) 968c2ecf20Sopenharmony_ci{ 978c2ecf20Sopenharmony_ci struct hnae_ae_dev *hdev = cls_to_ae_dev(dev); 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci if (dev_of_node(hdev->dev)) 1008c2ecf20Sopenharmony_ci return (data == &hdev->dev->of_node->fwnode); 1018c2ecf20Sopenharmony_ci else if (is_acpi_node(hdev->dev->fwnode)) 1028c2ecf20Sopenharmony_ci return (data == hdev->dev->fwnode); 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci dev_err(dev, "__ae_match cannot read cfg data from OF or acpi\n"); 1058c2ecf20Sopenharmony_ci return 0; 1068c2ecf20Sopenharmony_ci} 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_cistatic struct hnae_ae_dev *find_ae(const struct fwnode_handle *fwnode) 1098c2ecf20Sopenharmony_ci{ 1108c2ecf20Sopenharmony_ci struct device *dev; 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci WARN_ON(!fwnode); 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci dev = class_find_device(hnae_class, NULL, fwnode, __ae_match); 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci return dev ? cls_to_ae_dev(dev) : NULL; 1178c2ecf20Sopenharmony_ci} 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_cistatic void hnae_free_buffers(struct hnae_ring *ring) 1208c2ecf20Sopenharmony_ci{ 1218c2ecf20Sopenharmony_ci int i; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci for (i = 0; i < ring->desc_num; i++) 1248c2ecf20Sopenharmony_ci hnae_free_buffer_detach(ring, i); 1258c2ecf20Sopenharmony_ci} 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci/* Allocate memory for raw pkg, and map with dma */ 1288c2ecf20Sopenharmony_cistatic int hnae_alloc_buffers(struct hnae_ring *ring) 1298c2ecf20Sopenharmony_ci{ 1308c2ecf20Sopenharmony_ci int i, j, ret; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci for (i = 0; i < ring->desc_num; i++) { 1338c2ecf20Sopenharmony_ci ret = hnae_alloc_buffer_attach(ring, i); 1348c2ecf20Sopenharmony_ci if (ret) 1358c2ecf20Sopenharmony_ci goto out_buffer_fail; 1368c2ecf20Sopenharmony_ci } 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci return 0; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ciout_buffer_fail: 1418c2ecf20Sopenharmony_ci for (j = i - 1; j >= 0; j--) 1428c2ecf20Sopenharmony_ci hnae_free_buffer_detach(ring, j); 1438c2ecf20Sopenharmony_ci return ret; 1448c2ecf20Sopenharmony_ci} 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci/* free desc along with its attached buffer */ 1478c2ecf20Sopenharmony_cistatic void hnae_free_desc(struct hnae_ring *ring) 1488c2ecf20Sopenharmony_ci{ 1498c2ecf20Sopenharmony_ci dma_unmap_single(ring_to_dev(ring), ring->desc_dma_addr, 1508c2ecf20Sopenharmony_ci ring->desc_num * sizeof(ring->desc[0]), 1518c2ecf20Sopenharmony_ci ring_to_dma_dir(ring)); 1528c2ecf20Sopenharmony_ci ring->desc_dma_addr = 0; 1538c2ecf20Sopenharmony_ci kfree(ring->desc); 1548c2ecf20Sopenharmony_ci ring->desc = NULL; 1558c2ecf20Sopenharmony_ci} 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci/* alloc desc, without buffer attached */ 1588c2ecf20Sopenharmony_cistatic int hnae_alloc_desc(struct hnae_ring *ring) 1598c2ecf20Sopenharmony_ci{ 1608c2ecf20Sopenharmony_ci int size = ring->desc_num * sizeof(ring->desc[0]); 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci ring->desc = kzalloc(size, GFP_KERNEL); 1638c2ecf20Sopenharmony_ci if (!ring->desc) 1648c2ecf20Sopenharmony_ci return -ENOMEM; 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci ring->desc_dma_addr = dma_map_single(ring_to_dev(ring), 1678c2ecf20Sopenharmony_ci ring->desc, size, ring_to_dma_dir(ring)); 1688c2ecf20Sopenharmony_ci if (dma_mapping_error(ring_to_dev(ring), ring->desc_dma_addr)) { 1698c2ecf20Sopenharmony_ci ring->desc_dma_addr = 0; 1708c2ecf20Sopenharmony_ci kfree(ring->desc); 1718c2ecf20Sopenharmony_ci ring->desc = NULL; 1728c2ecf20Sopenharmony_ci return -ENOMEM; 1738c2ecf20Sopenharmony_ci } 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci return 0; 1768c2ecf20Sopenharmony_ci} 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci/* fini ring, also free the buffer for the ring */ 1798c2ecf20Sopenharmony_cistatic void hnae_fini_ring(struct hnae_ring *ring) 1808c2ecf20Sopenharmony_ci{ 1818c2ecf20Sopenharmony_ci if (is_rx_ring(ring)) 1828c2ecf20Sopenharmony_ci hnae_free_buffers(ring); 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci hnae_free_desc(ring); 1858c2ecf20Sopenharmony_ci kfree(ring->desc_cb); 1868c2ecf20Sopenharmony_ci ring->desc_cb = NULL; 1878c2ecf20Sopenharmony_ci ring->next_to_clean = 0; 1888c2ecf20Sopenharmony_ci ring->next_to_use = 0; 1898c2ecf20Sopenharmony_ci} 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci/* init ring, and with buffer for rx ring */ 1928c2ecf20Sopenharmony_cistatic int 1938c2ecf20Sopenharmony_cihnae_init_ring(struct hnae_queue *q, struct hnae_ring *ring, int flags) 1948c2ecf20Sopenharmony_ci{ 1958c2ecf20Sopenharmony_ci int ret; 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci if (ring->desc_num <= 0 || ring->buf_size <= 0) 1988c2ecf20Sopenharmony_ci return -EINVAL; 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci ring->q = q; 2018c2ecf20Sopenharmony_ci ring->flags = flags; 2028c2ecf20Sopenharmony_ci ring->coal_param = q->handle->coal_param; 2038c2ecf20Sopenharmony_ci assert(!ring->desc && !ring->desc_cb && !ring->desc_dma_addr); 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci /* not matter for tx or rx ring, the ntc and ntc start from 0 */ 2068c2ecf20Sopenharmony_ci assert(ring->next_to_use == 0); 2078c2ecf20Sopenharmony_ci assert(ring->next_to_clean == 0); 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci ring->desc_cb = kcalloc(ring->desc_num, sizeof(ring->desc_cb[0]), 2108c2ecf20Sopenharmony_ci GFP_KERNEL); 2118c2ecf20Sopenharmony_ci if (!ring->desc_cb) { 2128c2ecf20Sopenharmony_ci ret = -ENOMEM; 2138c2ecf20Sopenharmony_ci goto out; 2148c2ecf20Sopenharmony_ci } 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci ret = hnae_alloc_desc(ring); 2178c2ecf20Sopenharmony_ci if (ret) 2188c2ecf20Sopenharmony_ci goto out_with_desc_cb; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci if (is_rx_ring(ring)) { 2218c2ecf20Sopenharmony_ci ret = hnae_alloc_buffers(ring); 2228c2ecf20Sopenharmony_ci if (ret) 2238c2ecf20Sopenharmony_ci goto out_with_desc; 2248c2ecf20Sopenharmony_ci } 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci return 0; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ciout_with_desc: 2298c2ecf20Sopenharmony_ci hnae_free_desc(ring); 2308c2ecf20Sopenharmony_ciout_with_desc_cb: 2318c2ecf20Sopenharmony_ci kfree(ring->desc_cb); 2328c2ecf20Sopenharmony_ci ring->desc_cb = NULL; 2338c2ecf20Sopenharmony_ciout: 2348c2ecf20Sopenharmony_ci return ret; 2358c2ecf20Sopenharmony_ci} 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_cistatic int hnae_init_queue(struct hnae_handle *h, struct hnae_queue *q, 2388c2ecf20Sopenharmony_ci struct hnae_ae_dev *dev) 2398c2ecf20Sopenharmony_ci{ 2408c2ecf20Sopenharmony_ci int ret; 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci q->dev = dev; 2438c2ecf20Sopenharmony_ci q->handle = h; 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci ret = hnae_init_ring(q, &q->tx_ring, q->tx_ring.flags | RINGF_DIR); 2468c2ecf20Sopenharmony_ci if (ret) 2478c2ecf20Sopenharmony_ci goto out; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci ret = hnae_init_ring(q, &q->rx_ring, q->rx_ring.flags & ~RINGF_DIR); 2508c2ecf20Sopenharmony_ci if (ret) 2518c2ecf20Sopenharmony_ci goto out_with_tx_ring; 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci if (dev->ops->init_queue) 2548c2ecf20Sopenharmony_ci dev->ops->init_queue(q); 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci return 0; 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ciout_with_tx_ring: 2598c2ecf20Sopenharmony_ci hnae_fini_ring(&q->tx_ring); 2608c2ecf20Sopenharmony_ciout: 2618c2ecf20Sopenharmony_ci return ret; 2628c2ecf20Sopenharmony_ci} 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_cistatic void hnae_fini_queue(struct hnae_queue *q) 2658c2ecf20Sopenharmony_ci{ 2668c2ecf20Sopenharmony_ci if (q->dev->ops->fini_queue) 2678c2ecf20Sopenharmony_ci q->dev->ops->fini_queue(q); 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci hnae_fini_ring(&q->tx_ring); 2708c2ecf20Sopenharmony_ci hnae_fini_ring(&q->rx_ring); 2718c2ecf20Sopenharmony_ci} 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci/* 2748c2ecf20Sopenharmony_ci * ae_chain - define ae chain head 2758c2ecf20Sopenharmony_ci */ 2768c2ecf20Sopenharmony_cistatic RAW_NOTIFIER_HEAD(ae_chain); 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ciint hnae_register_notifier(struct notifier_block *nb) 2798c2ecf20Sopenharmony_ci{ 2808c2ecf20Sopenharmony_ci return raw_notifier_chain_register(&ae_chain, nb); 2818c2ecf20Sopenharmony_ci} 2828c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hnae_register_notifier); 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_civoid hnae_unregister_notifier(struct notifier_block *nb) 2858c2ecf20Sopenharmony_ci{ 2868c2ecf20Sopenharmony_ci if (raw_notifier_chain_unregister(&ae_chain, nb)) 2878c2ecf20Sopenharmony_ci dev_err(NULL, "notifier chain unregister fail\n"); 2888c2ecf20Sopenharmony_ci} 2898c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hnae_unregister_notifier); 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ciint hnae_reinit_handle(struct hnae_handle *handle) 2928c2ecf20Sopenharmony_ci{ 2938c2ecf20Sopenharmony_ci int i, j; 2948c2ecf20Sopenharmony_ci int ret; 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci for (i = 0; i < handle->q_num; i++) /* free ring*/ 2978c2ecf20Sopenharmony_ci hnae_fini_queue(handle->qs[i]); 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci if (handle->dev->ops->reset) 3008c2ecf20Sopenharmony_ci handle->dev->ops->reset(handle); 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci for (i = 0; i < handle->q_num; i++) {/* reinit ring*/ 3038c2ecf20Sopenharmony_ci ret = hnae_init_queue(handle, handle->qs[i], handle->dev); 3048c2ecf20Sopenharmony_ci if (ret) 3058c2ecf20Sopenharmony_ci goto out_when_init_queue; 3068c2ecf20Sopenharmony_ci } 3078c2ecf20Sopenharmony_ci return 0; 3088c2ecf20Sopenharmony_ciout_when_init_queue: 3098c2ecf20Sopenharmony_ci for (j = i - 1; j >= 0; j--) 3108c2ecf20Sopenharmony_ci hnae_fini_queue(handle->qs[j]); 3118c2ecf20Sopenharmony_ci return ret; 3128c2ecf20Sopenharmony_ci} 3138c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hnae_reinit_handle); 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci/* hnae_get_handle - get a handle from the AE 3168c2ecf20Sopenharmony_ci * @owner_dev: the dev use this handle 3178c2ecf20Sopenharmony_ci * @ae_id: the id of the ae to be used 3188c2ecf20Sopenharmony_ci * @ae_opts: the options set for the handle 3198c2ecf20Sopenharmony_ci * @bops: the callbacks for buffer management 3208c2ecf20Sopenharmony_ci * 3218c2ecf20Sopenharmony_ci * return handle ptr or ERR_PTR 3228c2ecf20Sopenharmony_ci */ 3238c2ecf20Sopenharmony_cistruct hnae_handle *hnae_get_handle(struct device *owner_dev, 3248c2ecf20Sopenharmony_ci const struct fwnode_handle *fwnode, 3258c2ecf20Sopenharmony_ci u32 port_id, 3268c2ecf20Sopenharmony_ci struct hnae_buf_ops *bops) 3278c2ecf20Sopenharmony_ci{ 3288c2ecf20Sopenharmony_ci struct hnae_ae_dev *dev; 3298c2ecf20Sopenharmony_ci struct hnae_handle *handle; 3308c2ecf20Sopenharmony_ci int i, j; 3318c2ecf20Sopenharmony_ci int ret; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci dev = find_ae(fwnode); 3348c2ecf20Sopenharmony_ci if (!dev) 3358c2ecf20Sopenharmony_ci return ERR_PTR(-ENODEV); 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci handle = dev->ops->get_handle(dev, port_id); 3388c2ecf20Sopenharmony_ci if (IS_ERR(handle)) { 3398c2ecf20Sopenharmony_ci put_device(&dev->cls_dev); 3408c2ecf20Sopenharmony_ci return handle; 3418c2ecf20Sopenharmony_ci } 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci handle->dev = dev; 3448c2ecf20Sopenharmony_ci handle->owner_dev = owner_dev; 3458c2ecf20Sopenharmony_ci handle->bops = bops ? bops : &hnae_bops; 3468c2ecf20Sopenharmony_ci handle->eport_id = port_id; 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci for (i = 0; i < handle->q_num; i++) { 3498c2ecf20Sopenharmony_ci ret = hnae_init_queue(handle, handle->qs[i], dev); 3508c2ecf20Sopenharmony_ci if (ret) 3518c2ecf20Sopenharmony_ci goto out_when_init_queue; 3528c2ecf20Sopenharmony_ci } 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci __module_get(dev->owner); 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci hnae_list_add(&dev->lock, &handle->node, &dev->handle_list); 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci return handle; 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ciout_when_init_queue: 3618c2ecf20Sopenharmony_ci for (j = i - 1; j >= 0; j--) 3628c2ecf20Sopenharmony_ci hnae_fini_queue(handle->qs[j]); 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci put_device(&dev->cls_dev); 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 3678c2ecf20Sopenharmony_ci} 3688c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hnae_get_handle); 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_civoid hnae_put_handle(struct hnae_handle *h) 3718c2ecf20Sopenharmony_ci{ 3728c2ecf20Sopenharmony_ci struct hnae_ae_dev *dev = h->dev; 3738c2ecf20Sopenharmony_ci int i; 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ci for (i = 0; i < h->q_num; i++) 3768c2ecf20Sopenharmony_ci hnae_fini_queue(h->qs[i]); 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci if (h->dev->ops->reset) 3798c2ecf20Sopenharmony_ci h->dev->ops->reset(h); 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci hnae_list_del(&dev->lock, &h->node); 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci if (dev->ops->put_handle) 3848c2ecf20Sopenharmony_ci dev->ops->put_handle(h); 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci module_put(dev->owner); 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci put_device(&dev->cls_dev); 3898c2ecf20Sopenharmony_ci} 3908c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hnae_put_handle); 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_cistatic void hnae_release(struct device *dev) 3938c2ecf20Sopenharmony_ci{ 3948c2ecf20Sopenharmony_ci} 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci/** 3978c2ecf20Sopenharmony_ci * hnae_ae_register - register a AE engine to hnae framework 3988c2ecf20Sopenharmony_ci * @hdev: the hnae ae engine device 3998c2ecf20Sopenharmony_ci * @owner: the module who provides this dev 4008c2ecf20Sopenharmony_ci * NOTE: the duplicated name will not be checked 4018c2ecf20Sopenharmony_ci */ 4028c2ecf20Sopenharmony_ciint hnae_ae_register(struct hnae_ae_dev *hdev, struct module *owner) 4038c2ecf20Sopenharmony_ci{ 4048c2ecf20Sopenharmony_ci static atomic_t id = ATOMIC_INIT(-1); 4058c2ecf20Sopenharmony_ci int ret; 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci if (!hdev->dev) 4088c2ecf20Sopenharmony_ci return -ENODEV; 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci if (!hdev->ops || !hdev->ops->get_handle || 4118c2ecf20Sopenharmony_ci !hdev->ops->toggle_ring_irq || 4128c2ecf20Sopenharmony_ci !hdev->ops->get_status || !hdev->ops->adjust_link) 4138c2ecf20Sopenharmony_ci return -EINVAL; 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci hdev->owner = owner; 4168c2ecf20Sopenharmony_ci hdev->id = (int)atomic_inc_return(&id); 4178c2ecf20Sopenharmony_ci hdev->cls_dev.parent = hdev->dev; 4188c2ecf20Sopenharmony_ci hdev->cls_dev.class = hnae_class; 4198c2ecf20Sopenharmony_ci hdev->cls_dev.release = hnae_release; 4208c2ecf20Sopenharmony_ci (void)dev_set_name(&hdev->cls_dev, "hnae%d", hdev->id); 4218c2ecf20Sopenharmony_ci ret = device_register(&hdev->cls_dev); 4228c2ecf20Sopenharmony_ci if (ret) { 4238c2ecf20Sopenharmony_ci put_device(&hdev->cls_dev); 4248c2ecf20Sopenharmony_ci return ret; 4258c2ecf20Sopenharmony_ci } 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci __module_get(THIS_MODULE); 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&hdev->handle_list); 4308c2ecf20Sopenharmony_ci spin_lock_init(&hdev->lock); 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci ret = raw_notifier_call_chain(&ae_chain, HNAE_AE_REGISTER, NULL); 4338c2ecf20Sopenharmony_ci if (ret) 4348c2ecf20Sopenharmony_ci dev_dbg(hdev->dev, 4358c2ecf20Sopenharmony_ci "has not notifier for AE: %s\n", hdev->name); 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci return 0; 4388c2ecf20Sopenharmony_ci} 4398c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hnae_ae_register); 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ci/** 4428c2ecf20Sopenharmony_ci * hnae_ae_unregister - unregisters a HNAE AE engine 4438c2ecf20Sopenharmony_ci * @hdev: the device to unregister 4448c2ecf20Sopenharmony_ci */ 4458c2ecf20Sopenharmony_civoid hnae_ae_unregister(struct hnae_ae_dev *hdev) 4468c2ecf20Sopenharmony_ci{ 4478c2ecf20Sopenharmony_ci device_unregister(&hdev->cls_dev); 4488c2ecf20Sopenharmony_ci module_put(THIS_MODULE); 4498c2ecf20Sopenharmony_ci} 4508c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hnae_ae_unregister); 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_cistatic int __init hnae_init(void) 4538c2ecf20Sopenharmony_ci{ 4548c2ecf20Sopenharmony_ci hnae_class = class_create(THIS_MODULE, "hnae"); 4558c2ecf20Sopenharmony_ci return PTR_ERR_OR_ZERO(hnae_class); 4568c2ecf20Sopenharmony_ci} 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_cistatic void __exit hnae_exit(void) 4598c2ecf20Sopenharmony_ci{ 4608c2ecf20Sopenharmony_ci class_destroy(hnae_class); 4618c2ecf20Sopenharmony_ci} 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_cisubsys_initcall(hnae_init); 4648c2ecf20Sopenharmony_cimodule_exit(hnae_exit); 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ciMODULE_AUTHOR("Hisilicon, Inc."); 4678c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 4688c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Hisilicon Network Acceleration Engine Framework"); 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci/* vi: set tw=78 noet: */ 471