1*1d6cff4fSYuval Mintz /* QLogic qed NIC Driver 2*1d6cff4fSYuval Mintz * Copyright (c) 2015 QLogic Corporation 3*1d6cff4fSYuval Mintz * 4*1d6cff4fSYuval Mintz * This software is available under the terms of the GNU General Public License 5*1d6cff4fSYuval Mintz * (GPL) Version 2, available from the file COPYING in the main directory of 6*1d6cff4fSYuval Mintz * this source tree. 7*1d6cff4fSYuval Mintz */ 8*1d6cff4fSYuval Mintz 9*1d6cff4fSYuval Mintz #include <linux/types.h> 10*1d6cff4fSYuval Mintz #include <linux/dma-mapping.h> 11*1d6cff4fSYuval Mintz #include <linux/kernel.h> 12*1d6cff4fSYuval Mintz #include <linux/list.h> 13*1d6cff4fSYuval Mintz #include <linux/pci.h> 14*1d6cff4fSYuval Mintz #include <linux/slab.h> 15*1d6cff4fSYuval Mintz #include <linux/string.h> 16*1d6cff4fSYuval Mintz #include "qed.h" 17*1d6cff4fSYuval Mintz #include "qed_iscsi.h" 18*1d6cff4fSYuval Mintz #include "qed_ll2.h" 19*1d6cff4fSYuval Mintz #include "qed_ooo.h" 20*1d6cff4fSYuval Mintz 21*1d6cff4fSYuval Mintz static struct qed_ooo_archipelago 22*1d6cff4fSYuval Mintz *qed_ooo_seek_archipelago(struct qed_hwfn *p_hwfn, 23*1d6cff4fSYuval Mintz struct qed_ooo_info 24*1d6cff4fSYuval Mintz *p_ooo_info, 25*1d6cff4fSYuval Mintz u32 cid) 26*1d6cff4fSYuval Mintz { 27*1d6cff4fSYuval Mintz struct qed_ooo_archipelago *p_archipelago = NULL; 28*1d6cff4fSYuval Mintz 29*1d6cff4fSYuval Mintz list_for_each_entry(p_archipelago, 30*1d6cff4fSYuval Mintz &p_ooo_info->archipelagos_list, list_entry) { 31*1d6cff4fSYuval Mintz if (p_archipelago->cid == cid) 32*1d6cff4fSYuval Mintz return p_archipelago; 33*1d6cff4fSYuval Mintz } 34*1d6cff4fSYuval Mintz 35*1d6cff4fSYuval Mintz return NULL; 36*1d6cff4fSYuval Mintz } 37*1d6cff4fSYuval Mintz 38*1d6cff4fSYuval Mintz static struct qed_ooo_isle *qed_ooo_seek_isle(struct qed_hwfn *p_hwfn, 39*1d6cff4fSYuval Mintz struct qed_ooo_info *p_ooo_info, 40*1d6cff4fSYuval Mintz u32 cid, u8 isle) 41*1d6cff4fSYuval Mintz { 42*1d6cff4fSYuval Mintz struct qed_ooo_archipelago *p_archipelago = NULL; 43*1d6cff4fSYuval Mintz struct qed_ooo_isle *p_isle = NULL; 44*1d6cff4fSYuval Mintz u8 the_num_of_isle = 1; 45*1d6cff4fSYuval Mintz 46*1d6cff4fSYuval Mintz p_archipelago = qed_ooo_seek_archipelago(p_hwfn, p_ooo_info, cid); 47*1d6cff4fSYuval Mintz if (!p_archipelago) { 48*1d6cff4fSYuval Mintz DP_NOTICE(p_hwfn, 49*1d6cff4fSYuval Mintz "Connection %d is not found in OOO list\n", cid); 50*1d6cff4fSYuval Mintz return NULL; 51*1d6cff4fSYuval Mintz } 52*1d6cff4fSYuval Mintz 53*1d6cff4fSYuval Mintz list_for_each_entry(p_isle, &p_archipelago->isles_list, list_entry) { 54*1d6cff4fSYuval Mintz if (the_num_of_isle == isle) 55*1d6cff4fSYuval Mintz return p_isle; 56*1d6cff4fSYuval Mintz the_num_of_isle++; 57*1d6cff4fSYuval Mintz } 58*1d6cff4fSYuval Mintz 59*1d6cff4fSYuval Mintz return NULL; 60*1d6cff4fSYuval Mintz } 61*1d6cff4fSYuval Mintz 62*1d6cff4fSYuval Mintz void qed_ooo_save_history_entry(struct qed_hwfn *p_hwfn, 63*1d6cff4fSYuval Mintz struct qed_ooo_info *p_ooo_info, 64*1d6cff4fSYuval Mintz struct ooo_opaque *p_cqe) 65*1d6cff4fSYuval Mintz { 66*1d6cff4fSYuval Mintz struct qed_ooo_history *p_history = &p_ooo_info->ooo_history; 67*1d6cff4fSYuval Mintz 68*1d6cff4fSYuval Mintz if (p_history->head_idx == p_history->num_of_cqes) 69*1d6cff4fSYuval Mintz p_history->head_idx = 0; 70*1d6cff4fSYuval Mintz p_history->p_cqes[p_history->head_idx] = *p_cqe; 71*1d6cff4fSYuval Mintz p_history->head_idx++; 72*1d6cff4fSYuval Mintz } 73*1d6cff4fSYuval Mintz 74*1d6cff4fSYuval Mintz struct qed_ooo_info *qed_ooo_alloc(struct qed_hwfn *p_hwfn) 75*1d6cff4fSYuval Mintz { 76*1d6cff4fSYuval Mintz struct qed_ooo_info *p_ooo_info; 77*1d6cff4fSYuval Mintz u16 max_num_archipelagos = 0; 78*1d6cff4fSYuval Mintz u16 max_num_isles = 0; 79*1d6cff4fSYuval Mintz u32 i; 80*1d6cff4fSYuval Mintz 81*1d6cff4fSYuval Mintz if (p_hwfn->hw_info.personality != QED_PCI_ISCSI) { 82*1d6cff4fSYuval Mintz DP_NOTICE(p_hwfn, 83*1d6cff4fSYuval Mintz "Failed to allocate qed_ooo_info: unknown personality\n"); 84*1d6cff4fSYuval Mintz return NULL; 85*1d6cff4fSYuval Mintz } 86*1d6cff4fSYuval Mintz 87*1d6cff4fSYuval Mintz max_num_archipelagos = p_hwfn->pf_params.iscsi_pf_params.num_cons; 88*1d6cff4fSYuval Mintz max_num_isles = QED_MAX_NUM_ISLES + max_num_archipelagos; 89*1d6cff4fSYuval Mintz 90*1d6cff4fSYuval Mintz if (!max_num_archipelagos) { 91*1d6cff4fSYuval Mintz DP_NOTICE(p_hwfn, 92*1d6cff4fSYuval Mintz "Failed to allocate qed_ooo_info: unknown amount of connections\n"); 93*1d6cff4fSYuval Mintz return NULL; 94*1d6cff4fSYuval Mintz } 95*1d6cff4fSYuval Mintz 96*1d6cff4fSYuval Mintz p_ooo_info = kzalloc(sizeof(*p_ooo_info), GFP_KERNEL); 97*1d6cff4fSYuval Mintz if (!p_ooo_info) 98*1d6cff4fSYuval Mintz return NULL; 99*1d6cff4fSYuval Mintz 100*1d6cff4fSYuval Mintz INIT_LIST_HEAD(&p_ooo_info->free_buffers_list); 101*1d6cff4fSYuval Mintz INIT_LIST_HEAD(&p_ooo_info->ready_buffers_list); 102*1d6cff4fSYuval Mintz INIT_LIST_HEAD(&p_ooo_info->free_isles_list); 103*1d6cff4fSYuval Mintz INIT_LIST_HEAD(&p_ooo_info->free_archipelagos_list); 104*1d6cff4fSYuval Mintz INIT_LIST_HEAD(&p_ooo_info->archipelagos_list); 105*1d6cff4fSYuval Mintz 106*1d6cff4fSYuval Mintz p_ooo_info->p_isles_mem = kcalloc(max_num_isles, 107*1d6cff4fSYuval Mintz sizeof(struct qed_ooo_isle), 108*1d6cff4fSYuval Mintz GFP_KERNEL); 109*1d6cff4fSYuval Mintz if (!p_ooo_info->p_isles_mem) 110*1d6cff4fSYuval Mintz goto no_isles_mem; 111*1d6cff4fSYuval Mintz 112*1d6cff4fSYuval Mintz for (i = 0; i < max_num_isles; i++) { 113*1d6cff4fSYuval Mintz INIT_LIST_HEAD(&p_ooo_info->p_isles_mem[i].buffers_list); 114*1d6cff4fSYuval Mintz list_add_tail(&p_ooo_info->p_isles_mem[i].list_entry, 115*1d6cff4fSYuval Mintz &p_ooo_info->free_isles_list); 116*1d6cff4fSYuval Mintz } 117*1d6cff4fSYuval Mintz 118*1d6cff4fSYuval Mintz p_ooo_info->p_archipelagos_mem = 119*1d6cff4fSYuval Mintz kcalloc(max_num_archipelagos, 120*1d6cff4fSYuval Mintz sizeof(struct qed_ooo_archipelago), 121*1d6cff4fSYuval Mintz GFP_KERNEL); 122*1d6cff4fSYuval Mintz if (!p_ooo_info->p_archipelagos_mem) 123*1d6cff4fSYuval Mintz goto no_archipelagos_mem; 124*1d6cff4fSYuval Mintz 125*1d6cff4fSYuval Mintz for (i = 0; i < max_num_archipelagos; i++) { 126*1d6cff4fSYuval Mintz INIT_LIST_HEAD(&p_ooo_info->p_archipelagos_mem[i].isles_list); 127*1d6cff4fSYuval Mintz list_add_tail(&p_ooo_info->p_archipelagos_mem[i].list_entry, 128*1d6cff4fSYuval Mintz &p_ooo_info->free_archipelagos_list); 129*1d6cff4fSYuval Mintz } 130*1d6cff4fSYuval Mintz 131*1d6cff4fSYuval Mintz p_ooo_info->ooo_history.p_cqes = 132*1d6cff4fSYuval Mintz kcalloc(QED_MAX_NUM_OOO_HISTORY_ENTRIES, 133*1d6cff4fSYuval Mintz sizeof(struct ooo_opaque), 134*1d6cff4fSYuval Mintz GFP_KERNEL); 135*1d6cff4fSYuval Mintz if (!p_ooo_info->ooo_history.p_cqes) 136*1d6cff4fSYuval Mintz goto no_history_mem; 137*1d6cff4fSYuval Mintz 138*1d6cff4fSYuval Mintz return p_ooo_info; 139*1d6cff4fSYuval Mintz 140*1d6cff4fSYuval Mintz no_history_mem: 141*1d6cff4fSYuval Mintz kfree(p_ooo_info->p_archipelagos_mem); 142*1d6cff4fSYuval Mintz no_archipelagos_mem: 143*1d6cff4fSYuval Mintz kfree(p_ooo_info->p_isles_mem); 144*1d6cff4fSYuval Mintz no_isles_mem: 145*1d6cff4fSYuval Mintz kfree(p_ooo_info); 146*1d6cff4fSYuval Mintz return NULL; 147*1d6cff4fSYuval Mintz } 148*1d6cff4fSYuval Mintz 149*1d6cff4fSYuval Mintz void qed_ooo_release_connection_isles(struct qed_hwfn *p_hwfn, 150*1d6cff4fSYuval Mintz struct qed_ooo_info *p_ooo_info, u32 cid) 151*1d6cff4fSYuval Mintz { 152*1d6cff4fSYuval Mintz struct qed_ooo_archipelago *p_archipelago; 153*1d6cff4fSYuval Mintz struct qed_ooo_buffer *p_buffer; 154*1d6cff4fSYuval Mintz struct qed_ooo_isle *p_isle; 155*1d6cff4fSYuval Mintz bool b_found = false; 156*1d6cff4fSYuval Mintz 157*1d6cff4fSYuval Mintz if (list_empty(&p_ooo_info->archipelagos_list)) 158*1d6cff4fSYuval Mintz return; 159*1d6cff4fSYuval Mintz 160*1d6cff4fSYuval Mintz list_for_each_entry(p_archipelago, 161*1d6cff4fSYuval Mintz &p_ooo_info->archipelagos_list, list_entry) { 162*1d6cff4fSYuval Mintz if (p_archipelago->cid == cid) { 163*1d6cff4fSYuval Mintz list_del(&p_archipelago->list_entry); 164*1d6cff4fSYuval Mintz b_found = true; 165*1d6cff4fSYuval Mintz break; 166*1d6cff4fSYuval Mintz } 167*1d6cff4fSYuval Mintz } 168*1d6cff4fSYuval Mintz 169*1d6cff4fSYuval Mintz if (!b_found) 170*1d6cff4fSYuval Mintz return; 171*1d6cff4fSYuval Mintz 172*1d6cff4fSYuval Mintz while (!list_empty(&p_archipelago->isles_list)) { 173*1d6cff4fSYuval Mintz p_isle = list_first_entry(&p_archipelago->isles_list, 174*1d6cff4fSYuval Mintz struct qed_ooo_isle, list_entry); 175*1d6cff4fSYuval Mintz 176*1d6cff4fSYuval Mintz list_del(&p_isle->list_entry); 177*1d6cff4fSYuval Mintz 178*1d6cff4fSYuval Mintz while (!list_empty(&p_isle->buffers_list)) { 179*1d6cff4fSYuval Mintz p_buffer = list_first_entry(&p_isle->buffers_list, 180*1d6cff4fSYuval Mintz struct qed_ooo_buffer, 181*1d6cff4fSYuval Mintz list_entry); 182*1d6cff4fSYuval Mintz 183*1d6cff4fSYuval Mintz if (!p_buffer) 184*1d6cff4fSYuval Mintz break; 185*1d6cff4fSYuval Mintz 186*1d6cff4fSYuval Mintz list_del(&p_buffer->list_entry); 187*1d6cff4fSYuval Mintz list_add_tail(&p_buffer->list_entry, 188*1d6cff4fSYuval Mintz &p_ooo_info->free_buffers_list); 189*1d6cff4fSYuval Mintz } 190*1d6cff4fSYuval Mintz list_add_tail(&p_isle->list_entry, 191*1d6cff4fSYuval Mintz &p_ooo_info->free_isles_list); 192*1d6cff4fSYuval Mintz } 193*1d6cff4fSYuval Mintz 194*1d6cff4fSYuval Mintz list_add_tail(&p_archipelago->list_entry, 195*1d6cff4fSYuval Mintz &p_ooo_info->free_archipelagos_list); 196*1d6cff4fSYuval Mintz } 197*1d6cff4fSYuval Mintz 198*1d6cff4fSYuval Mintz void qed_ooo_release_all_isles(struct qed_hwfn *p_hwfn, 199*1d6cff4fSYuval Mintz struct qed_ooo_info *p_ooo_info) 200*1d6cff4fSYuval Mintz { 201*1d6cff4fSYuval Mintz struct qed_ooo_archipelago *p_arch; 202*1d6cff4fSYuval Mintz struct qed_ooo_buffer *p_buffer; 203*1d6cff4fSYuval Mintz struct qed_ooo_isle *p_isle; 204*1d6cff4fSYuval Mintz 205*1d6cff4fSYuval Mintz while (!list_empty(&p_ooo_info->archipelagos_list)) { 206*1d6cff4fSYuval Mintz p_arch = list_first_entry(&p_ooo_info->archipelagos_list, 207*1d6cff4fSYuval Mintz struct qed_ooo_archipelago, 208*1d6cff4fSYuval Mintz list_entry); 209*1d6cff4fSYuval Mintz 210*1d6cff4fSYuval Mintz list_del(&p_arch->list_entry); 211*1d6cff4fSYuval Mintz 212*1d6cff4fSYuval Mintz while (!list_empty(&p_arch->isles_list)) { 213*1d6cff4fSYuval Mintz p_isle = list_first_entry(&p_arch->isles_list, 214*1d6cff4fSYuval Mintz struct qed_ooo_isle, 215*1d6cff4fSYuval Mintz list_entry); 216*1d6cff4fSYuval Mintz 217*1d6cff4fSYuval Mintz list_del(&p_isle->list_entry); 218*1d6cff4fSYuval Mintz 219*1d6cff4fSYuval Mintz while (!list_empty(&p_isle->buffers_list)) { 220*1d6cff4fSYuval Mintz p_buffer = 221*1d6cff4fSYuval Mintz list_first_entry(&p_isle->buffers_list, 222*1d6cff4fSYuval Mintz struct qed_ooo_buffer, 223*1d6cff4fSYuval Mintz list_entry); 224*1d6cff4fSYuval Mintz 225*1d6cff4fSYuval Mintz if (!p_buffer) 226*1d6cff4fSYuval Mintz break; 227*1d6cff4fSYuval Mintz 228*1d6cff4fSYuval Mintz list_del(&p_buffer->list_entry); 229*1d6cff4fSYuval Mintz list_add_tail(&p_buffer->list_entry, 230*1d6cff4fSYuval Mintz &p_ooo_info->free_buffers_list); 231*1d6cff4fSYuval Mintz } 232*1d6cff4fSYuval Mintz list_add_tail(&p_isle->list_entry, 233*1d6cff4fSYuval Mintz &p_ooo_info->free_isles_list); 234*1d6cff4fSYuval Mintz } 235*1d6cff4fSYuval Mintz list_add_tail(&p_arch->list_entry, 236*1d6cff4fSYuval Mintz &p_ooo_info->free_archipelagos_list); 237*1d6cff4fSYuval Mintz } 238*1d6cff4fSYuval Mintz if (!list_empty(&p_ooo_info->ready_buffers_list)) 239*1d6cff4fSYuval Mintz list_splice_tail_init(&p_ooo_info->ready_buffers_list, 240*1d6cff4fSYuval Mintz &p_ooo_info->free_buffers_list); 241*1d6cff4fSYuval Mintz } 242*1d6cff4fSYuval Mintz 243*1d6cff4fSYuval Mintz void qed_ooo_setup(struct qed_hwfn *p_hwfn, struct qed_ooo_info *p_ooo_info) 244*1d6cff4fSYuval Mintz { 245*1d6cff4fSYuval Mintz qed_ooo_release_all_isles(p_hwfn, p_ooo_info); 246*1d6cff4fSYuval Mintz memset(p_ooo_info->ooo_history.p_cqes, 0, 247*1d6cff4fSYuval Mintz p_ooo_info->ooo_history.num_of_cqes * 248*1d6cff4fSYuval Mintz sizeof(struct ooo_opaque)); 249*1d6cff4fSYuval Mintz p_ooo_info->ooo_history.head_idx = 0; 250*1d6cff4fSYuval Mintz } 251*1d6cff4fSYuval Mintz 252*1d6cff4fSYuval Mintz void qed_ooo_free(struct qed_hwfn *p_hwfn, struct qed_ooo_info *p_ooo_info) 253*1d6cff4fSYuval Mintz { 254*1d6cff4fSYuval Mintz struct qed_ooo_buffer *p_buffer; 255*1d6cff4fSYuval Mintz 256*1d6cff4fSYuval Mintz qed_ooo_release_all_isles(p_hwfn, p_ooo_info); 257*1d6cff4fSYuval Mintz while (!list_empty(&p_ooo_info->free_buffers_list)) { 258*1d6cff4fSYuval Mintz p_buffer = list_first_entry(&p_ooo_info->free_buffers_list, 259*1d6cff4fSYuval Mintz struct qed_ooo_buffer, list_entry); 260*1d6cff4fSYuval Mintz 261*1d6cff4fSYuval Mintz if (!p_buffer) 262*1d6cff4fSYuval Mintz break; 263*1d6cff4fSYuval Mintz 264*1d6cff4fSYuval Mintz list_del(&p_buffer->list_entry); 265*1d6cff4fSYuval Mintz dma_free_coherent(&p_hwfn->cdev->pdev->dev, 266*1d6cff4fSYuval Mintz p_buffer->rx_buffer_size, 267*1d6cff4fSYuval Mintz p_buffer->rx_buffer_virt_addr, 268*1d6cff4fSYuval Mintz p_buffer->rx_buffer_phys_addr); 269*1d6cff4fSYuval Mintz kfree(p_buffer); 270*1d6cff4fSYuval Mintz } 271*1d6cff4fSYuval Mintz 272*1d6cff4fSYuval Mintz kfree(p_ooo_info->p_isles_mem); 273*1d6cff4fSYuval Mintz kfree(p_ooo_info->p_archipelagos_mem); 274*1d6cff4fSYuval Mintz kfree(p_ooo_info->ooo_history.p_cqes); 275*1d6cff4fSYuval Mintz kfree(p_ooo_info); 276*1d6cff4fSYuval Mintz } 277*1d6cff4fSYuval Mintz 278*1d6cff4fSYuval Mintz void qed_ooo_put_free_buffer(struct qed_hwfn *p_hwfn, 279*1d6cff4fSYuval Mintz struct qed_ooo_info *p_ooo_info, 280*1d6cff4fSYuval Mintz struct qed_ooo_buffer *p_buffer) 281*1d6cff4fSYuval Mintz { 282*1d6cff4fSYuval Mintz list_add_tail(&p_buffer->list_entry, &p_ooo_info->free_buffers_list); 283*1d6cff4fSYuval Mintz } 284*1d6cff4fSYuval Mintz 285*1d6cff4fSYuval Mintz struct qed_ooo_buffer *qed_ooo_get_free_buffer(struct qed_hwfn *p_hwfn, 286*1d6cff4fSYuval Mintz struct qed_ooo_info *p_ooo_info) 287*1d6cff4fSYuval Mintz { 288*1d6cff4fSYuval Mintz struct qed_ooo_buffer *p_buffer = NULL; 289*1d6cff4fSYuval Mintz 290*1d6cff4fSYuval Mintz if (!list_empty(&p_ooo_info->free_buffers_list)) { 291*1d6cff4fSYuval Mintz p_buffer = list_first_entry(&p_ooo_info->free_buffers_list, 292*1d6cff4fSYuval Mintz struct qed_ooo_buffer, list_entry); 293*1d6cff4fSYuval Mintz 294*1d6cff4fSYuval Mintz list_del(&p_buffer->list_entry); 295*1d6cff4fSYuval Mintz } 296*1d6cff4fSYuval Mintz 297*1d6cff4fSYuval Mintz return p_buffer; 298*1d6cff4fSYuval Mintz } 299*1d6cff4fSYuval Mintz 300*1d6cff4fSYuval Mintz void qed_ooo_put_ready_buffer(struct qed_hwfn *p_hwfn, 301*1d6cff4fSYuval Mintz struct qed_ooo_info *p_ooo_info, 302*1d6cff4fSYuval Mintz struct qed_ooo_buffer *p_buffer, u8 on_tail) 303*1d6cff4fSYuval Mintz { 304*1d6cff4fSYuval Mintz if (on_tail) 305*1d6cff4fSYuval Mintz list_add_tail(&p_buffer->list_entry, 306*1d6cff4fSYuval Mintz &p_ooo_info->ready_buffers_list); 307*1d6cff4fSYuval Mintz else 308*1d6cff4fSYuval Mintz list_add(&p_buffer->list_entry, 309*1d6cff4fSYuval Mintz &p_ooo_info->ready_buffers_list); 310*1d6cff4fSYuval Mintz } 311*1d6cff4fSYuval Mintz 312*1d6cff4fSYuval Mintz struct qed_ooo_buffer *qed_ooo_get_ready_buffer(struct qed_hwfn *p_hwfn, 313*1d6cff4fSYuval Mintz struct qed_ooo_info *p_ooo_info) 314*1d6cff4fSYuval Mintz { 315*1d6cff4fSYuval Mintz struct qed_ooo_buffer *p_buffer = NULL; 316*1d6cff4fSYuval Mintz 317*1d6cff4fSYuval Mintz if (!list_empty(&p_ooo_info->ready_buffers_list)) { 318*1d6cff4fSYuval Mintz p_buffer = list_first_entry(&p_ooo_info->ready_buffers_list, 319*1d6cff4fSYuval Mintz struct qed_ooo_buffer, list_entry); 320*1d6cff4fSYuval Mintz 321*1d6cff4fSYuval Mintz list_del(&p_buffer->list_entry); 322*1d6cff4fSYuval Mintz } 323*1d6cff4fSYuval Mintz 324*1d6cff4fSYuval Mintz return p_buffer; 325*1d6cff4fSYuval Mintz } 326*1d6cff4fSYuval Mintz 327*1d6cff4fSYuval Mintz void qed_ooo_delete_isles(struct qed_hwfn *p_hwfn, 328*1d6cff4fSYuval Mintz struct qed_ooo_info *p_ooo_info, 329*1d6cff4fSYuval Mintz u32 cid, u8 drop_isle, u8 drop_size) 330*1d6cff4fSYuval Mintz { 331*1d6cff4fSYuval Mintz struct qed_ooo_archipelago *p_archipelago = NULL; 332*1d6cff4fSYuval Mintz struct qed_ooo_isle *p_isle = NULL; 333*1d6cff4fSYuval Mintz u8 isle_idx; 334*1d6cff4fSYuval Mintz 335*1d6cff4fSYuval Mintz p_archipelago = qed_ooo_seek_archipelago(p_hwfn, p_ooo_info, cid); 336*1d6cff4fSYuval Mintz for (isle_idx = 0; isle_idx < drop_size; isle_idx++) { 337*1d6cff4fSYuval Mintz p_isle = qed_ooo_seek_isle(p_hwfn, p_ooo_info, cid, drop_isle); 338*1d6cff4fSYuval Mintz if (!p_isle) { 339*1d6cff4fSYuval Mintz DP_NOTICE(p_hwfn, 340*1d6cff4fSYuval Mintz "Isle %d is not found(cid %d)\n", 341*1d6cff4fSYuval Mintz drop_isle, cid); 342*1d6cff4fSYuval Mintz return; 343*1d6cff4fSYuval Mintz } 344*1d6cff4fSYuval Mintz if (list_empty(&p_isle->buffers_list)) 345*1d6cff4fSYuval Mintz DP_NOTICE(p_hwfn, 346*1d6cff4fSYuval Mintz "Isle %d is empty(cid %d)\n", drop_isle, cid); 347*1d6cff4fSYuval Mintz else 348*1d6cff4fSYuval Mintz list_splice_tail_init(&p_isle->buffers_list, 349*1d6cff4fSYuval Mintz &p_ooo_info->free_buffers_list); 350*1d6cff4fSYuval Mintz 351*1d6cff4fSYuval Mintz list_del(&p_isle->list_entry); 352*1d6cff4fSYuval Mintz p_ooo_info->cur_isles_number--; 353*1d6cff4fSYuval Mintz list_add(&p_isle->list_entry, &p_ooo_info->free_isles_list); 354*1d6cff4fSYuval Mintz } 355*1d6cff4fSYuval Mintz 356*1d6cff4fSYuval Mintz if (list_empty(&p_archipelago->isles_list)) { 357*1d6cff4fSYuval Mintz list_del(&p_archipelago->list_entry); 358*1d6cff4fSYuval Mintz list_add(&p_archipelago->list_entry, 359*1d6cff4fSYuval Mintz &p_ooo_info->free_archipelagos_list); 360*1d6cff4fSYuval Mintz } 361*1d6cff4fSYuval Mintz } 362*1d6cff4fSYuval Mintz 363*1d6cff4fSYuval Mintz void qed_ooo_add_new_isle(struct qed_hwfn *p_hwfn, 364*1d6cff4fSYuval Mintz struct qed_ooo_info *p_ooo_info, 365*1d6cff4fSYuval Mintz u32 cid, u8 ooo_isle, 366*1d6cff4fSYuval Mintz struct qed_ooo_buffer *p_buffer) 367*1d6cff4fSYuval Mintz { 368*1d6cff4fSYuval Mintz struct qed_ooo_archipelago *p_archipelago = NULL; 369*1d6cff4fSYuval Mintz struct qed_ooo_isle *p_prev_isle = NULL; 370*1d6cff4fSYuval Mintz struct qed_ooo_isle *p_isle = NULL; 371*1d6cff4fSYuval Mintz 372*1d6cff4fSYuval Mintz if (ooo_isle > 1) { 373*1d6cff4fSYuval Mintz p_prev_isle = qed_ooo_seek_isle(p_hwfn, 374*1d6cff4fSYuval Mintz p_ooo_info, cid, ooo_isle - 1); 375*1d6cff4fSYuval Mintz if (!p_prev_isle) { 376*1d6cff4fSYuval Mintz DP_NOTICE(p_hwfn, 377*1d6cff4fSYuval Mintz "Isle %d is not found(cid %d)\n", 378*1d6cff4fSYuval Mintz ooo_isle - 1, cid); 379*1d6cff4fSYuval Mintz return; 380*1d6cff4fSYuval Mintz } 381*1d6cff4fSYuval Mintz } 382*1d6cff4fSYuval Mintz p_archipelago = qed_ooo_seek_archipelago(p_hwfn, p_ooo_info, cid); 383*1d6cff4fSYuval Mintz if (!p_archipelago && (ooo_isle != 1)) { 384*1d6cff4fSYuval Mintz DP_NOTICE(p_hwfn, 385*1d6cff4fSYuval Mintz "Connection %d is not found in OOO list\n", cid); 386*1d6cff4fSYuval Mintz return; 387*1d6cff4fSYuval Mintz } 388*1d6cff4fSYuval Mintz 389*1d6cff4fSYuval Mintz if (!list_empty(&p_ooo_info->free_isles_list)) { 390*1d6cff4fSYuval Mintz p_isle = list_first_entry(&p_ooo_info->free_isles_list, 391*1d6cff4fSYuval Mintz struct qed_ooo_isle, list_entry); 392*1d6cff4fSYuval Mintz 393*1d6cff4fSYuval Mintz list_del(&p_isle->list_entry); 394*1d6cff4fSYuval Mintz if (!list_empty(&p_isle->buffers_list)) { 395*1d6cff4fSYuval Mintz DP_NOTICE(p_hwfn, "Free isle is not empty\n"); 396*1d6cff4fSYuval Mintz INIT_LIST_HEAD(&p_isle->buffers_list); 397*1d6cff4fSYuval Mintz } 398*1d6cff4fSYuval Mintz } else { 399*1d6cff4fSYuval Mintz DP_NOTICE(p_hwfn, "No more free isles\n"); 400*1d6cff4fSYuval Mintz return; 401*1d6cff4fSYuval Mintz } 402*1d6cff4fSYuval Mintz 403*1d6cff4fSYuval Mintz if (!p_archipelago && 404*1d6cff4fSYuval Mintz !list_empty(&p_ooo_info->free_archipelagos_list)) { 405*1d6cff4fSYuval Mintz p_archipelago = 406*1d6cff4fSYuval Mintz list_first_entry(&p_ooo_info->free_archipelagos_list, 407*1d6cff4fSYuval Mintz struct qed_ooo_archipelago, list_entry); 408*1d6cff4fSYuval Mintz 409*1d6cff4fSYuval Mintz list_del(&p_archipelago->list_entry); 410*1d6cff4fSYuval Mintz if (!list_empty(&p_archipelago->isles_list)) { 411*1d6cff4fSYuval Mintz DP_NOTICE(p_hwfn, 412*1d6cff4fSYuval Mintz "Free OOO connection is not empty\n"); 413*1d6cff4fSYuval Mintz INIT_LIST_HEAD(&p_archipelago->isles_list); 414*1d6cff4fSYuval Mintz } 415*1d6cff4fSYuval Mintz p_archipelago->cid = cid; 416*1d6cff4fSYuval Mintz list_add(&p_archipelago->list_entry, 417*1d6cff4fSYuval Mintz &p_ooo_info->archipelagos_list); 418*1d6cff4fSYuval Mintz } else if (!p_archipelago) { 419*1d6cff4fSYuval Mintz DP_NOTICE(p_hwfn, "No more free OOO connections\n"); 420*1d6cff4fSYuval Mintz list_add(&p_isle->list_entry, 421*1d6cff4fSYuval Mintz &p_ooo_info->free_isles_list); 422*1d6cff4fSYuval Mintz list_add(&p_buffer->list_entry, 423*1d6cff4fSYuval Mintz &p_ooo_info->free_buffers_list); 424*1d6cff4fSYuval Mintz return; 425*1d6cff4fSYuval Mintz } 426*1d6cff4fSYuval Mintz 427*1d6cff4fSYuval Mintz list_add(&p_buffer->list_entry, &p_isle->buffers_list); 428*1d6cff4fSYuval Mintz p_ooo_info->cur_isles_number++; 429*1d6cff4fSYuval Mintz p_ooo_info->gen_isles_number++; 430*1d6cff4fSYuval Mintz 431*1d6cff4fSYuval Mintz if (p_ooo_info->cur_isles_number > p_ooo_info->max_isles_number) 432*1d6cff4fSYuval Mintz p_ooo_info->max_isles_number = p_ooo_info->cur_isles_number; 433*1d6cff4fSYuval Mintz 434*1d6cff4fSYuval Mintz if (!p_prev_isle) 435*1d6cff4fSYuval Mintz list_add(&p_isle->list_entry, &p_archipelago->isles_list); 436*1d6cff4fSYuval Mintz else 437*1d6cff4fSYuval Mintz list_add(&p_isle->list_entry, &p_prev_isle->list_entry); 438*1d6cff4fSYuval Mintz } 439*1d6cff4fSYuval Mintz 440*1d6cff4fSYuval Mintz void qed_ooo_add_new_buffer(struct qed_hwfn *p_hwfn, 441*1d6cff4fSYuval Mintz struct qed_ooo_info *p_ooo_info, 442*1d6cff4fSYuval Mintz u32 cid, 443*1d6cff4fSYuval Mintz u8 ooo_isle, 444*1d6cff4fSYuval Mintz struct qed_ooo_buffer *p_buffer, u8 buffer_side) 445*1d6cff4fSYuval Mintz { 446*1d6cff4fSYuval Mintz struct qed_ooo_isle *p_isle = NULL; 447*1d6cff4fSYuval Mintz 448*1d6cff4fSYuval Mintz p_isle = qed_ooo_seek_isle(p_hwfn, p_ooo_info, cid, ooo_isle); 449*1d6cff4fSYuval Mintz if (!p_isle) { 450*1d6cff4fSYuval Mintz DP_NOTICE(p_hwfn, 451*1d6cff4fSYuval Mintz "Isle %d is not found(cid %d)\n", ooo_isle, cid); 452*1d6cff4fSYuval Mintz return; 453*1d6cff4fSYuval Mintz } 454*1d6cff4fSYuval Mintz 455*1d6cff4fSYuval Mintz if (buffer_side == QED_OOO_LEFT_BUF) 456*1d6cff4fSYuval Mintz list_add(&p_buffer->list_entry, &p_isle->buffers_list); 457*1d6cff4fSYuval Mintz else 458*1d6cff4fSYuval Mintz list_add_tail(&p_buffer->list_entry, &p_isle->buffers_list); 459*1d6cff4fSYuval Mintz } 460*1d6cff4fSYuval Mintz 461*1d6cff4fSYuval Mintz void qed_ooo_join_isles(struct qed_hwfn *p_hwfn, 462*1d6cff4fSYuval Mintz struct qed_ooo_info *p_ooo_info, u32 cid, u8 left_isle) 463*1d6cff4fSYuval Mintz { 464*1d6cff4fSYuval Mintz struct qed_ooo_archipelago *p_archipelago = NULL; 465*1d6cff4fSYuval Mintz struct qed_ooo_isle *p_right_isle = NULL; 466*1d6cff4fSYuval Mintz struct qed_ooo_isle *p_left_isle = NULL; 467*1d6cff4fSYuval Mintz 468*1d6cff4fSYuval Mintz p_right_isle = qed_ooo_seek_isle(p_hwfn, p_ooo_info, cid, 469*1d6cff4fSYuval Mintz left_isle + 1); 470*1d6cff4fSYuval Mintz if (!p_right_isle) { 471*1d6cff4fSYuval Mintz DP_NOTICE(p_hwfn, 472*1d6cff4fSYuval Mintz "Right isle %d is not found(cid %d)\n", 473*1d6cff4fSYuval Mintz left_isle + 1, cid); 474*1d6cff4fSYuval Mintz return; 475*1d6cff4fSYuval Mintz } 476*1d6cff4fSYuval Mintz 477*1d6cff4fSYuval Mintz p_archipelago = qed_ooo_seek_archipelago(p_hwfn, p_ooo_info, cid); 478*1d6cff4fSYuval Mintz list_del(&p_right_isle->list_entry); 479*1d6cff4fSYuval Mintz p_ooo_info->cur_isles_number--; 480*1d6cff4fSYuval Mintz if (left_isle) { 481*1d6cff4fSYuval Mintz p_left_isle = qed_ooo_seek_isle(p_hwfn, p_ooo_info, cid, 482*1d6cff4fSYuval Mintz left_isle); 483*1d6cff4fSYuval Mintz if (!p_left_isle) { 484*1d6cff4fSYuval Mintz DP_NOTICE(p_hwfn, 485*1d6cff4fSYuval Mintz "Left isle %d is not found(cid %d)\n", 486*1d6cff4fSYuval Mintz left_isle, cid); 487*1d6cff4fSYuval Mintz return; 488*1d6cff4fSYuval Mintz } 489*1d6cff4fSYuval Mintz list_splice_tail_init(&p_right_isle->buffers_list, 490*1d6cff4fSYuval Mintz &p_left_isle->buffers_list); 491*1d6cff4fSYuval Mintz } else { 492*1d6cff4fSYuval Mintz list_splice_tail_init(&p_right_isle->buffers_list, 493*1d6cff4fSYuval Mintz &p_ooo_info->ready_buffers_list); 494*1d6cff4fSYuval Mintz if (list_empty(&p_archipelago->isles_list)) { 495*1d6cff4fSYuval Mintz list_del(&p_archipelago->list_entry); 496*1d6cff4fSYuval Mintz list_add(&p_archipelago->list_entry, 497*1d6cff4fSYuval Mintz &p_ooo_info->free_archipelagos_list); 498*1d6cff4fSYuval Mintz } 499*1d6cff4fSYuval Mintz } 500*1d6cff4fSYuval Mintz list_add_tail(&p_right_isle->list_entry, &p_ooo_info->free_isles_list); 501*1d6cff4fSYuval Mintz } 502