18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) 28c2ecf20Sopenharmony_ci/* QLogic qed NIC Driver 38c2ecf20Sopenharmony_ci * Copyright (c) 2015-2017 QLogic Corporation 48c2ecf20Sopenharmony_ci * Copyright (c) 2019-2020 Marvell International Ltd. 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <linux/types.h> 88c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h> 98c2ecf20Sopenharmony_ci#include <linux/kernel.h> 108c2ecf20Sopenharmony_ci#include <linux/list.h> 118c2ecf20Sopenharmony_ci#include <linux/pci.h> 128c2ecf20Sopenharmony_ci#include <linux/slab.h> 138c2ecf20Sopenharmony_ci#include <linux/string.h> 148c2ecf20Sopenharmony_ci#include "qed.h" 158c2ecf20Sopenharmony_ci#include "qed_iscsi.h" 168c2ecf20Sopenharmony_ci#include "qed_ll2.h" 178c2ecf20Sopenharmony_ci#include "qed_ooo.h" 188c2ecf20Sopenharmony_ci#include "qed_cxt.h" 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_cistatic struct qed_ooo_archipelago 218c2ecf20Sopenharmony_ci*qed_ooo_seek_archipelago(struct qed_hwfn *p_hwfn, 228c2ecf20Sopenharmony_ci struct qed_ooo_info 238c2ecf20Sopenharmony_ci *p_ooo_info, 248c2ecf20Sopenharmony_ci u32 cid) 258c2ecf20Sopenharmony_ci{ 268c2ecf20Sopenharmony_ci u32 idx = (cid & 0xffff) - p_ooo_info->cid_base; 278c2ecf20Sopenharmony_ci struct qed_ooo_archipelago *p_archipelago; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci if (idx >= p_ooo_info->max_num_archipelagos) 308c2ecf20Sopenharmony_ci return NULL; 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci p_archipelago = &p_ooo_info->p_archipelagos_mem[idx]; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci if (list_empty(&p_archipelago->isles_list)) 358c2ecf20Sopenharmony_ci return NULL; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci return p_archipelago; 388c2ecf20Sopenharmony_ci} 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_cistatic struct qed_ooo_isle *qed_ooo_seek_isle(struct qed_hwfn *p_hwfn, 418c2ecf20Sopenharmony_ci struct qed_ooo_info *p_ooo_info, 428c2ecf20Sopenharmony_ci u32 cid, u8 isle) 438c2ecf20Sopenharmony_ci{ 448c2ecf20Sopenharmony_ci struct qed_ooo_archipelago *p_archipelago = NULL; 458c2ecf20Sopenharmony_ci struct qed_ooo_isle *p_isle = NULL; 468c2ecf20Sopenharmony_ci u8 the_num_of_isle = 1; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci p_archipelago = qed_ooo_seek_archipelago(p_hwfn, p_ooo_info, cid); 498c2ecf20Sopenharmony_ci if (!p_archipelago) { 508c2ecf20Sopenharmony_ci DP_NOTICE(p_hwfn, 518c2ecf20Sopenharmony_ci "Connection %d is not found in OOO list\n", cid); 528c2ecf20Sopenharmony_ci return NULL; 538c2ecf20Sopenharmony_ci } 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci list_for_each_entry(p_isle, &p_archipelago->isles_list, list_entry) { 568c2ecf20Sopenharmony_ci if (the_num_of_isle == isle) 578c2ecf20Sopenharmony_ci return p_isle; 588c2ecf20Sopenharmony_ci the_num_of_isle++; 598c2ecf20Sopenharmony_ci } 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci return NULL; 628c2ecf20Sopenharmony_ci} 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_civoid qed_ooo_save_history_entry(struct qed_hwfn *p_hwfn, 658c2ecf20Sopenharmony_ci struct qed_ooo_info *p_ooo_info, 668c2ecf20Sopenharmony_ci struct ooo_opaque *p_cqe) 678c2ecf20Sopenharmony_ci{ 688c2ecf20Sopenharmony_ci struct qed_ooo_history *p_history = &p_ooo_info->ooo_history; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci if (p_history->head_idx == p_history->num_of_cqes) 718c2ecf20Sopenharmony_ci p_history->head_idx = 0; 728c2ecf20Sopenharmony_ci p_history->p_cqes[p_history->head_idx] = *p_cqe; 738c2ecf20Sopenharmony_ci p_history->head_idx++; 748c2ecf20Sopenharmony_ci} 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ciint qed_ooo_alloc(struct qed_hwfn *p_hwfn) 778c2ecf20Sopenharmony_ci{ 788c2ecf20Sopenharmony_ci u16 max_num_archipelagos = 0, cid_base; 798c2ecf20Sopenharmony_ci struct qed_ooo_info *p_ooo_info; 808c2ecf20Sopenharmony_ci enum protocol_type proto; 818c2ecf20Sopenharmony_ci u16 max_num_isles = 0; 828c2ecf20Sopenharmony_ci u32 i; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci switch (p_hwfn->hw_info.personality) { 858c2ecf20Sopenharmony_ci case QED_PCI_ISCSI: 868c2ecf20Sopenharmony_ci proto = PROTOCOLID_ISCSI; 878c2ecf20Sopenharmony_ci break; 888c2ecf20Sopenharmony_ci case QED_PCI_ETH_RDMA: 898c2ecf20Sopenharmony_ci case QED_PCI_ETH_IWARP: 908c2ecf20Sopenharmony_ci proto = PROTOCOLID_IWARP; 918c2ecf20Sopenharmony_ci break; 928c2ecf20Sopenharmony_ci default: 938c2ecf20Sopenharmony_ci DP_NOTICE(p_hwfn, 948c2ecf20Sopenharmony_ci "Failed to allocate qed_ooo_info: unknown personality\n"); 958c2ecf20Sopenharmony_ci return -EINVAL; 968c2ecf20Sopenharmony_ci } 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci max_num_archipelagos = (u16)qed_cxt_get_proto_cid_count(p_hwfn, proto, 998c2ecf20Sopenharmony_ci NULL); 1008c2ecf20Sopenharmony_ci max_num_isles = QED_MAX_NUM_ISLES + max_num_archipelagos; 1018c2ecf20Sopenharmony_ci cid_base = (u16)qed_cxt_get_proto_cid_start(p_hwfn, proto); 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci if (!max_num_archipelagos) { 1048c2ecf20Sopenharmony_ci DP_NOTICE(p_hwfn, 1058c2ecf20Sopenharmony_ci "Failed to allocate qed_ooo_info: unknown amount of connections\n"); 1068c2ecf20Sopenharmony_ci return -EINVAL; 1078c2ecf20Sopenharmony_ci } 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci p_ooo_info = kzalloc(sizeof(*p_ooo_info), GFP_KERNEL); 1108c2ecf20Sopenharmony_ci if (!p_ooo_info) 1118c2ecf20Sopenharmony_ci return -ENOMEM; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci p_ooo_info->cid_base = cid_base; 1148c2ecf20Sopenharmony_ci p_ooo_info->max_num_archipelagos = max_num_archipelagos; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&p_ooo_info->free_buffers_list); 1178c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&p_ooo_info->ready_buffers_list); 1188c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&p_ooo_info->free_isles_list); 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci p_ooo_info->p_isles_mem = kcalloc(max_num_isles, 1218c2ecf20Sopenharmony_ci sizeof(struct qed_ooo_isle), 1228c2ecf20Sopenharmony_ci GFP_KERNEL); 1238c2ecf20Sopenharmony_ci if (!p_ooo_info->p_isles_mem) 1248c2ecf20Sopenharmony_ci goto no_isles_mem; 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci for (i = 0; i < max_num_isles; i++) { 1278c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&p_ooo_info->p_isles_mem[i].buffers_list); 1288c2ecf20Sopenharmony_ci list_add_tail(&p_ooo_info->p_isles_mem[i].list_entry, 1298c2ecf20Sopenharmony_ci &p_ooo_info->free_isles_list); 1308c2ecf20Sopenharmony_ci } 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci p_ooo_info->p_archipelagos_mem = 1338c2ecf20Sopenharmony_ci kcalloc(max_num_archipelagos, 1348c2ecf20Sopenharmony_ci sizeof(struct qed_ooo_archipelago), 1358c2ecf20Sopenharmony_ci GFP_KERNEL); 1368c2ecf20Sopenharmony_ci if (!p_ooo_info->p_archipelagos_mem) 1378c2ecf20Sopenharmony_ci goto no_archipelagos_mem; 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci for (i = 0; i < max_num_archipelagos; i++) 1408c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&p_ooo_info->p_archipelagos_mem[i].isles_list); 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci p_ooo_info->ooo_history.p_cqes = 1438c2ecf20Sopenharmony_ci kcalloc(QED_MAX_NUM_OOO_HISTORY_ENTRIES, 1448c2ecf20Sopenharmony_ci sizeof(struct ooo_opaque), 1458c2ecf20Sopenharmony_ci GFP_KERNEL); 1468c2ecf20Sopenharmony_ci if (!p_ooo_info->ooo_history.p_cqes) 1478c2ecf20Sopenharmony_ci goto no_history_mem; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci p_ooo_info->ooo_history.num_of_cqes = QED_MAX_NUM_OOO_HISTORY_ENTRIES; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci p_hwfn->p_ooo_info = p_ooo_info; 1528c2ecf20Sopenharmony_ci return 0; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_cino_history_mem: 1558c2ecf20Sopenharmony_ci kfree(p_ooo_info->p_archipelagos_mem); 1568c2ecf20Sopenharmony_cino_archipelagos_mem: 1578c2ecf20Sopenharmony_ci kfree(p_ooo_info->p_isles_mem); 1588c2ecf20Sopenharmony_cino_isles_mem: 1598c2ecf20Sopenharmony_ci kfree(p_ooo_info); 1608c2ecf20Sopenharmony_ci return -ENOMEM; 1618c2ecf20Sopenharmony_ci} 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_civoid qed_ooo_release_connection_isles(struct qed_hwfn *p_hwfn, 1648c2ecf20Sopenharmony_ci struct qed_ooo_info *p_ooo_info, u32 cid) 1658c2ecf20Sopenharmony_ci{ 1668c2ecf20Sopenharmony_ci struct qed_ooo_archipelago *p_archipelago; 1678c2ecf20Sopenharmony_ci struct qed_ooo_buffer *p_buffer; 1688c2ecf20Sopenharmony_ci struct qed_ooo_isle *p_isle; 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci p_archipelago = qed_ooo_seek_archipelago(p_hwfn, p_ooo_info, cid); 1718c2ecf20Sopenharmony_ci if (!p_archipelago) 1728c2ecf20Sopenharmony_ci return; 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci while (!list_empty(&p_archipelago->isles_list)) { 1758c2ecf20Sopenharmony_ci p_isle = list_first_entry(&p_archipelago->isles_list, 1768c2ecf20Sopenharmony_ci struct qed_ooo_isle, list_entry); 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci list_del(&p_isle->list_entry); 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci while (!list_empty(&p_isle->buffers_list)) { 1818c2ecf20Sopenharmony_ci p_buffer = list_first_entry(&p_isle->buffers_list, 1828c2ecf20Sopenharmony_ci struct qed_ooo_buffer, 1838c2ecf20Sopenharmony_ci list_entry); 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci if (!p_buffer) 1868c2ecf20Sopenharmony_ci break; 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci list_move_tail(&p_buffer->list_entry, 1898c2ecf20Sopenharmony_ci &p_ooo_info->free_buffers_list); 1908c2ecf20Sopenharmony_ci } 1918c2ecf20Sopenharmony_ci list_add_tail(&p_isle->list_entry, 1928c2ecf20Sopenharmony_ci &p_ooo_info->free_isles_list); 1938c2ecf20Sopenharmony_ci } 1948c2ecf20Sopenharmony_ci} 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_civoid qed_ooo_release_all_isles(struct qed_hwfn *p_hwfn, 1978c2ecf20Sopenharmony_ci struct qed_ooo_info *p_ooo_info) 1988c2ecf20Sopenharmony_ci{ 1998c2ecf20Sopenharmony_ci struct qed_ooo_archipelago *p_archipelago; 2008c2ecf20Sopenharmony_ci struct qed_ooo_buffer *p_buffer; 2018c2ecf20Sopenharmony_ci struct qed_ooo_isle *p_isle; 2028c2ecf20Sopenharmony_ci u32 i; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci for (i = 0; i < p_ooo_info->max_num_archipelagos; i++) { 2058c2ecf20Sopenharmony_ci p_archipelago = &(p_ooo_info->p_archipelagos_mem[i]); 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci while (!list_empty(&p_archipelago->isles_list)) { 2088c2ecf20Sopenharmony_ci p_isle = list_first_entry(&p_archipelago->isles_list, 2098c2ecf20Sopenharmony_ci struct qed_ooo_isle, 2108c2ecf20Sopenharmony_ci list_entry); 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci list_del(&p_isle->list_entry); 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci while (!list_empty(&p_isle->buffers_list)) { 2158c2ecf20Sopenharmony_ci p_buffer = 2168c2ecf20Sopenharmony_ci list_first_entry(&p_isle->buffers_list, 2178c2ecf20Sopenharmony_ci struct qed_ooo_buffer, 2188c2ecf20Sopenharmony_ci list_entry); 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci if (!p_buffer) 2218c2ecf20Sopenharmony_ci break; 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci list_move_tail(&p_buffer->list_entry, 2248c2ecf20Sopenharmony_ci &p_ooo_info->free_buffers_list); 2258c2ecf20Sopenharmony_ci } 2268c2ecf20Sopenharmony_ci list_add_tail(&p_isle->list_entry, 2278c2ecf20Sopenharmony_ci &p_ooo_info->free_isles_list); 2288c2ecf20Sopenharmony_ci } 2298c2ecf20Sopenharmony_ci } 2308c2ecf20Sopenharmony_ci if (!list_empty(&p_ooo_info->ready_buffers_list)) 2318c2ecf20Sopenharmony_ci list_splice_tail_init(&p_ooo_info->ready_buffers_list, 2328c2ecf20Sopenharmony_ci &p_ooo_info->free_buffers_list); 2338c2ecf20Sopenharmony_ci} 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_civoid qed_ooo_setup(struct qed_hwfn *p_hwfn) 2368c2ecf20Sopenharmony_ci{ 2378c2ecf20Sopenharmony_ci qed_ooo_release_all_isles(p_hwfn, p_hwfn->p_ooo_info); 2388c2ecf20Sopenharmony_ci memset(p_hwfn->p_ooo_info->ooo_history.p_cqes, 0, 2398c2ecf20Sopenharmony_ci p_hwfn->p_ooo_info->ooo_history.num_of_cqes * 2408c2ecf20Sopenharmony_ci sizeof(struct ooo_opaque)); 2418c2ecf20Sopenharmony_ci p_hwfn->p_ooo_info->ooo_history.head_idx = 0; 2428c2ecf20Sopenharmony_ci} 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_civoid qed_ooo_free(struct qed_hwfn *p_hwfn) 2458c2ecf20Sopenharmony_ci{ 2468c2ecf20Sopenharmony_ci struct qed_ooo_info *p_ooo_info = p_hwfn->p_ooo_info; 2478c2ecf20Sopenharmony_ci struct qed_ooo_buffer *p_buffer; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci if (!p_ooo_info) 2508c2ecf20Sopenharmony_ci return; 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci qed_ooo_release_all_isles(p_hwfn, p_ooo_info); 2538c2ecf20Sopenharmony_ci while (!list_empty(&p_ooo_info->free_buffers_list)) { 2548c2ecf20Sopenharmony_ci p_buffer = list_first_entry(&p_ooo_info->free_buffers_list, 2558c2ecf20Sopenharmony_ci struct qed_ooo_buffer, list_entry); 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci if (!p_buffer) 2588c2ecf20Sopenharmony_ci break; 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci list_del(&p_buffer->list_entry); 2618c2ecf20Sopenharmony_ci dma_free_coherent(&p_hwfn->cdev->pdev->dev, 2628c2ecf20Sopenharmony_ci p_buffer->rx_buffer_size, 2638c2ecf20Sopenharmony_ci p_buffer->rx_buffer_virt_addr, 2648c2ecf20Sopenharmony_ci p_buffer->rx_buffer_phys_addr); 2658c2ecf20Sopenharmony_ci kfree(p_buffer); 2668c2ecf20Sopenharmony_ci } 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci kfree(p_ooo_info->p_isles_mem); 2698c2ecf20Sopenharmony_ci kfree(p_ooo_info->p_archipelagos_mem); 2708c2ecf20Sopenharmony_ci kfree(p_ooo_info->ooo_history.p_cqes); 2718c2ecf20Sopenharmony_ci kfree(p_ooo_info); 2728c2ecf20Sopenharmony_ci p_hwfn->p_ooo_info = NULL; 2738c2ecf20Sopenharmony_ci} 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_civoid qed_ooo_put_free_buffer(struct qed_hwfn *p_hwfn, 2768c2ecf20Sopenharmony_ci struct qed_ooo_info *p_ooo_info, 2778c2ecf20Sopenharmony_ci struct qed_ooo_buffer *p_buffer) 2788c2ecf20Sopenharmony_ci{ 2798c2ecf20Sopenharmony_ci list_add_tail(&p_buffer->list_entry, &p_ooo_info->free_buffers_list); 2808c2ecf20Sopenharmony_ci} 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_cistruct qed_ooo_buffer *qed_ooo_get_free_buffer(struct qed_hwfn *p_hwfn, 2838c2ecf20Sopenharmony_ci struct qed_ooo_info *p_ooo_info) 2848c2ecf20Sopenharmony_ci{ 2858c2ecf20Sopenharmony_ci struct qed_ooo_buffer *p_buffer = NULL; 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci if (!list_empty(&p_ooo_info->free_buffers_list)) { 2888c2ecf20Sopenharmony_ci p_buffer = list_first_entry(&p_ooo_info->free_buffers_list, 2898c2ecf20Sopenharmony_ci struct qed_ooo_buffer, list_entry); 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci list_del(&p_buffer->list_entry); 2928c2ecf20Sopenharmony_ci } 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci return p_buffer; 2958c2ecf20Sopenharmony_ci} 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_civoid qed_ooo_put_ready_buffer(struct qed_hwfn *p_hwfn, 2988c2ecf20Sopenharmony_ci struct qed_ooo_info *p_ooo_info, 2998c2ecf20Sopenharmony_ci struct qed_ooo_buffer *p_buffer, u8 on_tail) 3008c2ecf20Sopenharmony_ci{ 3018c2ecf20Sopenharmony_ci if (on_tail) 3028c2ecf20Sopenharmony_ci list_add_tail(&p_buffer->list_entry, 3038c2ecf20Sopenharmony_ci &p_ooo_info->ready_buffers_list); 3048c2ecf20Sopenharmony_ci else 3058c2ecf20Sopenharmony_ci list_add(&p_buffer->list_entry, 3068c2ecf20Sopenharmony_ci &p_ooo_info->ready_buffers_list); 3078c2ecf20Sopenharmony_ci} 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_cistruct qed_ooo_buffer *qed_ooo_get_ready_buffer(struct qed_hwfn *p_hwfn, 3108c2ecf20Sopenharmony_ci struct qed_ooo_info *p_ooo_info) 3118c2ecf20Sopenharmony_ci{ 3128c2ecf20Sopenharmony_ci struct qed_ooo_buffer *p_buffer = NULL; 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci if (!list_empty(&p_ooo_info->ready_buffers_list)) { 3158c2ecf20Sopenharmony_ci p_buffer = list_first_entry(&p_ooo_info->ready_buffers_list, 3168c2ecf20Sopenharmony_ci struct qed_ooo_buffer, list_entry); 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci list_del(&p_buffer->list_entry); 3198c2ecf20Sopenharmony_ci } 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci return p_buffer; 3228c2ecf20Sopenharmony_ci} 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_civoid qed_ooo_delete_isles(struct qed_hwfn *p_hwfn, 3258c2ecf20Sopenharmony_ci struct qed_ooo_info *p_ooo_info, 3268c2ecf20Sopenharmony_ci u32 cid, u8 drop_isle, u8 drop_size) 3278c2ecf20Sopenharmony_ci{ 3288c2ecf20Sopenharmony_ci struct qed_ooo_isle *p_isle = NULL; 3298c2ecf20Sopenharmony_ci u8 isle_idx; 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci for (isle_idx = 0; isle_idx < drop_size; isle_idx++) { 3328c2ecf20Sopenharmony_ci p_isle = qed_ooo_seek_isle(p_hwfn, p_ooo_info, cid, drop_isle); 3338c2ecf20Sopenharmony_ci if (!p_isle) { 3348c2ecf20Sopenharmony_ci DP_NOTICE(p_hwfn, 3358c2ecf20Sopenharmony_ci "Isle %d is not found(cid %d)\n", 3368c2ecf20Sopenharmony_ci drop_isle, cid); 3378c2ecf20Sopenharmony_ci return; 3388c2ecf20Sopenharmony_ci } 3398c2ecf20Sopenharmony_ci if (list_empty(&p_isle->buffers_list)) 3408c2ecf20Sopenharmony_ci DP_NOTICE(p_hwfn, 3418c2ecf20Sopenharmony_ci "Isle %d is empty(cid %d)\n", drop_isle, cid); 3428c2ecf20Sopenharmony_ci else 3438c2ecf20Sopenharmony_ci list_splice_tail_init(&p_isle->buffers_list, 3448c2ecf20Sopenharmony_ci &p_ooo_info->free_buffers_list); 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci list_del(&p_isle->list_entry); 3478c2ecf20Sopenharmony_ci p_ooo_info->cur_isles_number--; 3488c2ecf20Sopenharmony_ci list_add(&p_isle->list_entry, &p_ooo_info->free_isles_list); 3498c2ecf20Sopenharmony_ci } 3508c2ecf20Sopenharmony_ci} 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_civoid qed_ooo_add_new_isle(struct qed_hwfn *p_hwfn, 3538c2ecf20Sopenharmony_ci struct qed_ooo_info *p_ooo_info, 3548c2ecf20Sopenharmony_ci u32 cid, u8 ooo_isle, 3558c2ecf20Sopenharmony_ci struct qed_ooo_buffer *p_buffer) 3568c2ecf20Sopenharmony_ci{ 3578c2ecf20Sopenharmony_ci struct qed_ooo_archipelago *p_archipelago = NULL; 3588c2ecf20Sopenharmony_ci struct qed_ooo_isle *p_prev_isle = NULL; 3598c2ecf20Sopenharmony_ci struct qed_ooo_isle *p_isle = NULL; 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci if (ooo_isle > 1) { 3628c2ecf20Sopenharmony_ci p_prev_isle = qed_ooo_seek_isle(p_hwfn, 3638c2ecf20Sopenharmony_ci p_ooo_info, cid, ooo_isle - 1); 3648c2ecf20Sopenharmony_ci if (!p_prev_isle) { 3658c2ecf20Sopenharmony_ci DP_NOTICE(p_hwfn, 3668c2ecf20Sopenharmony_ci "Isle %d is not found(cid %d)\n", 3678c2ecf20Sopenharmony_ci ooo_isle - 1, cid); 3688c2ecf20Sopenharmony_ci return; 3698c2ecf20Sopenharmony_ci } 3708c2ecf20Sopenharmony_ci } 3718c2ecf20Sopenharmony_ci p_archipelago = qed_ooo_seek_archipelago(p_hwfn, p_ooo_info, cid); 3728c2ecf20Sopenharmony_ci if (!p_archipelago && (ooo_isle != 1)) { 3738c2ecf20Sopenharmony_ci DP_NOTICE(p_hwfn, 3748c2ecf20Sopenharmony_ci "Connection %d is not found in OOO list\n", cid); 3758c2ecf20Sopenharmony_ci return; 3768c2ecf20Sopenharmony_ci } 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci if (!list_empty(&p_ooo_info->free_isles_list)) { 3798c2ecf20Sopenharmony_ci p_isle = list_first_entry(&p_ooo_info->free_isles_list, 3808c2ecf20Sopenharmony_ci struct qed_ooo_isle, list_entry); 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci list_del(&p_isle->list_entry); 3838c2ecf20Sopenharmony_ci if (!list_empty(&p_isle->buffers_list)) { 3848c2ecf20Sopenharmony_ci DP_NOTICE(p_hwfn, "Free isle is not empty\n"); 3858c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&p_isle->buffers_list); 3868c2ecf20Sopenharmony_ci } 3878c2ecf20Sopenharmony_ci } else { 3888c2ecf20Sopenharmony_ci DP_NOTICE(p_hwfn, "No more free isles\n"); 3898c2ecf20Sopenharmony_ci return; 3908c2ecf20Sopenharmony_ci } 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci if (!p_archipelago) { 3938c2ecf20Sopenharmony_ci u32 idx = (cid & 0xffff) - p_ooo_info->cid_base; 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci p_archipelago = &p_ooo_info->p_archipelagos_mem[idx]; 3968c2ecf20Sopenharmony_ci } 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci list_add(&p_buffer->list_entry, &p_isle->buffers_list); 3998c2ecf20Sopenharmony_ci p_ooo_info->cur_isles_number++; 4008c2ecf20Sopenharmony_ci p_ooo_info->gen_isles_number++; 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci if (p_ooo_info->cur_isles_number > p_ooo_info->max_isles_number) 4038c2ecf20Sopenharmony_ci p_ooo_info->max_isles_number = p_ooo_info->cur_isles_number; 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci if (!p_prev_isle) 4068c2ecf20Sopenharmony_ci list_add(&p_isle->list_entry, &p_archipelago->isles_list); 4078c2ecf20Sopenharmony_ci else 4088c2ecf20Sopenharmony_ci list_add(&p_isle->list_entry, &p_prev_isle->list_entry); 4098c2ecf20Sopenharmony_ci} 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_civoid qed_ooo_add_new_buffer(struct qed_hwfn *p_hwfn, 4128c2ecf20Sopenharmony_ci struct qed_ooo_info *p_ooo_info, 4138c2ecf20Sopenharmony_ci u32 cid, 4148c2ecf20Sopenharmony_ci u8 ooo_isle, 4158c2ecf20Sopenharmony_ci struct qed_ooo_buffer *p_buffer, u8 buffer_side) 4168c2ecf20Sopenharmony_ci{ 4178c2ecf20Sopenharmony_ci struct qed_ooo_isle *p_isle = NULL; 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci p_isle = qed_ooo_seek_isle(p_hwfn, p_ooo_info, cid, ooo_isle); 4208c2ecf20Sopenharmony_ci if (!p_isle) { 4218c2ecf20Sopenharmony_ci DP_NOTICE(p_hwfn, 4228c2ecf20Sopenharmony_ci "Isle %d is not found(cid %d)\n", ooo_isle, cid); 4238c2ecf20Sopenharmony_ci return; 4248c2ecf20Sopenharmony_ci } 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci if (buffer_side == QED_OOO_LEFT_BUF) 4278c2ecf20Sopenharmony_ci list_add(&p_buffer->list_entry, &p_isle->buffers_list); 4288c2ecf20Sopenharmony_ci else 4298c2ecf20Sopenharmony_ci list_add_tail(&p_buffer->list_entry, &p_isle->buffers_list); 4308c2ecf20Sopenharmony_ci} 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_civoid qed_ooo_join_isles(struct qed_hwfn *p_hwfn, 4338c2ecf20Sopenharmony_ci struct qed_ooo_info *p_ooo_info, u32 cid, u8 left_isle) 4348c2ecf20Sopenharmony_ci{ 4358c2ecf20Sopenharmony_ci struct qed_ooo_isle *p_right_isle = NULL; 4368c2ecf20Sopenharmony_ci struct qed_ooo_isle *p_left_isle = NULL; 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci p_right_isle = qed_ooo_seek_isle(p_hwfn, p_ooo_info, cid, 4398c2ecf20Sopenharmony_ci left_isle + 1); 4408c2ecf20Sopenharmony_ci if (!p_right_isle) { 4418c2ecf20Sopenharmony_ci DP_NOTICE(p_hwfn, 4428c2ecf20Sopenharmony_ci "Right isle %d is not found(cid %d)\n", 4438c2ecf20Sopenharmony_ci left_isle + 1, cid); 4448c2ecf20Sopenharmony_ci return; 4458c2ecf20Sopenharmony_ci } 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ci list_del(&p_right_isle->list_entry); 4488c2ecf20Sopenharmony_ci p_ooo_info->cur_isles_number--; 4498c2ecf20Sopenharmony_ci if (left_isle) { 4508c2ecf20Sopenharmony_ci p_left_isle = qed_ooo_seek_isle(p_hwfn, p_ooo_info, cid, 4518c2ecf20Sopenharmony_ci left_isle); 4528c2ecf20Sopenharmony_ci if (!p_left_isle) { 4538c2ecf20Sopenharmony_ci DP_NOTICE(p_hwfn, 4548c2ecf20Sopenharmony_ci "Left isle %d is not found(cid %d)\n", 4558c2ecf20Sopenharmony_ci left_isle, cid); 4568c2ecf20Sopenharmony_ci return; 4578c2ecf20Sopenharmony_ci } 4588c2ecf20Sopenharmony_ci list_splice_tail_init(&p_right_isle->buffers_list, 4598c2ecf20Sopenharmony_ci &p_left_isle->buffers_list); 4608c2ecf20Sopenharmony_ci } else { 4618c2ecf20Sopenharmony_ci list_splice_tail_init(&p_right_isle->buffers_list, 4628c2ecf20Sopenharmony_ci &p_ooo_info->ready_buffers_list); 4638c2ecf20Sopenharmony_ci } 4648c2ecf20Sopenharmony_ci list_add_tail(&p_right_isle->list_entry, &p_ooo_info->free_isles_list); 4658c2ecf20Sopenharmony_ci} 466