1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2005 - 2016 Broadcom 4 * All rights reserved. 5 * 6 * Contact Information: 7 * linux-drivers@emulex.com 8 * 9 * Emulex 10 * 3333 Susan Street 11 * Costa Mesa, CA 92626 12 */ 13 14 #include <linux/mutex.h> 15 #include <linux/list.h> 16 #include <linux/netdevice.h> 17 #include <linux/module.h> 18 19 #include "be.h" 20 #include "be_cmds.h" 21 22 static struct ocrdma_driver *ocrdma_drv; 23 static LIST_HEAD(be_adapter_list); 24 static DEFINE_MUTEX(be_adapter_list_lock); 25 26 static void _be_roce_dev_add(struct be_adapter *adapter) 27 { 28 struct be_dev_info dev_info; 29 int i, num_vec; 30 struct pci_dev *pdev = adapter->pdev; 31 32 if (!ocrdma_drv) 33 return; 34 35 if (ocrdma_drv->be_abi_version != BE_ROCE_ABI_VERSION) { 36 dev_warn(&pdev->dev, "Cannot initialize RoCE due to ocrdma ABI mismatch\n"); 37 return; 38 } 39 40 if (pdev->device == OC_DEVICE_ID5) { 41 /* only msix is supported on these devices */ 42 if (!msix_enabled(adapter)) 43 return; 44 /* DPP region address and length */ 45 dev_info.dpp_unmapped_addr = pci_resource_start(pdev, 2); 46 dev_info.dpp_unmapped_len = pci_resource_len(pdev, 2); 47 } else { 48 dev_info.dpp_unmapped_addr = 0; 49 dev_info.dpp_unmapped_len = 0; 50 } 51 dev_info.pdev = adapter->pdev; 52 dev_info.db = adapter->db; 53 dev_info.unmapped_db = adapter->roce_db.io_addr; 54 dev_info.db_page_size = adapter->roce_db.size; 55 dev_info.db_total_size = adapter->roce_db.total_size; 56 dev_info.netdev = adapter->netdev; 57 memcpy(dev_info.mac_addr, adapter->netdev->dev_addr, ETH_ALEN); 58 dev_info.dev_family = adapter->sli_family; 59 if (msix_enabled(adapter)) { 60 /* provide all the vectors, so that EQ creation response 61 * can decide which one to use. 62 */ 63 num_vec = adapter->num_msix_vec + adapter->num_msix_roce_vec; 64 dev_info.intr_mode = BE_INTERRUPT_MODE_MSIX; 65 dev_info.msix.num_vectors = min(num_vec, MAX_MSIX_VECTORS); 66 /* provide start index of the vector, 67 * so in case of linear usage, 68 * it can use the base as starting point. 69 */ 70 dev_info.msix.start_vector = adapter->num_evt_qs; 71 for (i = 0; i < dev_info.msix.num_vectors; i++) { 72 dev_info.msix.vector_list[i] = 73 adapter->msix_entries[i].vector; 74 } 75 } else { 76 dev_info.msix.num_vectors = 0; 77 dev_info.intr_mode = BE_INTERRUPT_MODE_INTX; 78 } 79 adapter->ocrdma_dev = ocrdma_drv->add(&dev_info); 80 } 81 82 void be_roce_dev_add(struct be_adapter *adapter) 83 { 84 if (be_roce_supported(adapter)) { 85 INIT_LIST_HEAD(&adapter->entry); 86 mutex_lock(&be_adapter_list_lock); 87 list_add_tail(&adapter->entry, &be_adapter_list); 88 89 /* invoke add() routine of roce driver only if 90 * valid driver registered with add method and add() is not yet 91 * invoked on a given adapter. 92 */ 93 _be_roce_dev_add(adapter); 94 mutex_unlock(&be_adapter_list_lock); 95 } 96 } 97 98 static void _be_roce_dev_remove(struct be_adapter *adapter) 99 { 100 if (ocrdma_drv && ocrdma_drv->remove && adapter->ocrdma_dev) 101 ocrdma_drv->remove(adapter->ocrdma_dev); 102 adapter->ocrdma_dev = NULL; 103 } 104 105 void be_roce_dev_remove(struct be_adapter *adapter) 106 { 107 if (be_roce_supported(adapter)) { 108 mutex_lock(&be_adapter_list_lock); 109 _be_roce_dev_remove(adapter); 110 list_del(&adapter->entry); 111 mutex_unlock(&be_adapter_list_lock); 112 } 113 } 114 115 void be_roce_dev_shutdown(struct be_adapter *adapter) 116 { 117 if (be_roce_supported(adapter)) { 118 mutex_lock(&be_adapter_list_lock); 119 if (ocrdma_drv && adapter->ocrdma_dev && 120 ocrdma_drv->state_change_handler) 121 ocrdma_drv->state_change_handler(adapter->ocrdma_dev, 122 BE_DEV_SHUTDOWN); 123 mutex_unlock(&be_adapter_list_lock); 124 } 125 } 126 127 int be_roce_register_driver(struct ocrdma_driver *drv) 128 { 129 struct be_adapter *dev; 130 131 mutex_lock(&be_adapter_list_lock); 132 if (ocrdma_drv) { 133 mutex_unlock(&be_adapter_list_lock); 134 return -EINVAL; 135 } 136 ocrdma_drv = drv; 137 list_for_each_entry(dev, &be_adapter_list, entry) { 138 _be_roce_dev_add(dev); 139 } 140 mutex_unlock(&be_adapter_list_lock); 141 return 0; 142 } 143 EXPORT_SYMBOL(be_roce_register_driver); 144 145 void be_roce_unregister_driver(struct ocrdma_driver *drv) 146 { 147 struct be_adapter *dev; 148 149 mutex_lock(&be_adapter_list_lock); 150 list_for_each_entry(dev, &be_adapter_list, entry) { 151 if (dev->ocrdma_dev) 152 _be_roce_dev_remove(dev); 153 } 154 ocrdma_drv = NULL; 155 mutex_unlock(&be_adapter_list_lock); 156 } 157 EXPORT_SYMBOL(be_roce_unregister_driver); 158