162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2021 Broadcom. All Rights Reserved. The term 462306a36Sopenharmony_ci * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci/* 862306a36Sopenharmony_ci * LIBEFC LOCKING 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * The critical sections protected by the efc's spinlock are quite broad and 1162306a36Sopenharmony_ci * may be improved upon in the future. The libefc code and its locking doesn't 1262306a36Sopenharmony_ci * influence the I/O path, so excessive locking doesn't impact I/O performance. 1362306a36Sopenharmony_ci * 1462306a36Sopenharmony_ci * The strategy is to lock whenever processing a request from user driver. This 1562306a36Sopenharmony_ci * means that the entry points into the libefc library are protected by efc 1662306a36Sopenharmony_ci * lock. So all the state machine transitions are protected. 1762306a36Sopenharmony_ci */ 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#include <linux/module.h> 2062306a36Sopenharmony_ci#include <linux/kernel.h> 2162306a36Sopenharmony_ci#include "efc.h" 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ciint efcport_init(struct efc *efc) 2462306a36Sopenharmony_ci{ 2562306a36Sopenharmony_ci u32 rc = 0; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci spin_lock_init(&efc->lock); 2862306a36Sopenharmony_ci INIT_LIST_HEAD(&efc->vport_list); 2962306a36Sopenharmony_ci efc->hold_frames = false; 3062306a36Sopenharmony_ci spin_lock_init(&efc->pend_frames_lock); 3162306a36Sopenharmony_ci INIT_LIST_HEAD(&efc->pend_frames); 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci /* Create Node pool */ 3462306a36Sopenharmony_ci efc->node_pool = mempool_create_kmalloc_pool(EFC_MAX_REMOTE_NODES, 3562306a36Sopenharmony_ci sizeof(struct efc_node)); 3662306a36Sopenharmony_ci if (!efc->node_pool) { 3762306a36Sopenharmony_ci efc_log_err(efc, "Can't allocate node pool\n"); 3862306a36Sopenharmony_ci return -ENOMEM; 3962306a36Sopenharmony_ci } 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci efc->node_dma_pool = dma_pool_create("node_dma_pool", &efc->pci->dev, 4262306a36Sopenharmony_ci NODE_SPARAMS_SIZE, 0, 0); 4362306a36Sopenharmony_ci if (!efc->node_dma_pool) { 4462306a36Sopenharmony_ci efc_log_err(efc, "Can't allocate node dma pool\n"); 4562306a36Sopenharmony_ci mempool_destroy(efc->node_pool); 4662306a36Sopenharmony_ci return -ENOMEM; 4762306a36Sopenharmony_ci } 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci efc->els_io_pool = mempool_create_kmalloc_pool(EFC_ELS_IO_POOL_SZ, 5062306a36Sopenharmony_ci sizeof(struct efc_els_io_req)); 5162306a36Sopenharmony_ci if (!efc->els_io_pool) { 5262306a36Sopenharmony_ci efc_log_err(efc, "Can't allocate els io pool\n"); 5362306a36Sopenharmony_ci return -ENOMEM; 5462306a36Sopenharmony_ci } 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci return rc; 5762306a36Sopenharmony_ci} 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_cistatic void 6062306a36Sopenharmony_ciefc_purge_pending(struct efc *efc) 6162306a36Sopenharmony_ci{ 6262306a36Sopenharmony_ci struct efc_hw_sequence *frame, *next; 6362306a36Sopenharmony_ci unsigned long flags = 0; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci spin_lock_irqsave(&efc->pend_frames_lock, flags); 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci list_for_each_entry_safe(frame, next, &efc->pend_frames, list_entry) { 6862306a36Sopenharmony_ci list_del(&frame->list_entry); 6962306a36Sopenharmony_ci efc->tt.hw_seq_free(efc, frame); 7062306a36Sopenharmony_ci } 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci spin_unlock_irqrestore(&efc->pend_frames_lock, flags); 7362306a36Sopenharmony_ci} 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_civoid efcport_destroy(struct efc *efc) 7662306a36Sopenharmony_ci{ 7762306a36Sopenharmony_ci efc_purge_pending(efc); 7862306a36Sopenharmony_ci mempool_destroy(efc->els_io_pool); 7962306a36Sopenharmony_ci mempool_destroy(efc->node_pool); 8062306a36Sopenharmony_ci dma_pool_destroy(efc->node_dma_pool); 8162306a36Sopenharmony_ci} 82