Commit | Line | Data |
---|---|---|
045508a8 | 1 | /* |
c7bb15a6 | 2 | * Copyright (C) 2005 - 2013 Emulex |
045508a8 PP |
3 | * All rights reserved. |
4 | * | |
5 | * This program is free software; you can redistribute it and/or | |
6 | * modify it under the terms of the GNU General Public License version 2 | |
7 | * as published by the Free Software Foundation. The full GNU General | |
8 | * Public License is included in this distribution in the file called COPYING. | |
9 | * | |
10 | * Contact Information: | |
11 | * linux-drivers@emulex.com | |
12 | * | |
13 | * Emulex | |
14 | * 3333 Susan Street | |
15 | * Costa Mesa, CA 92626 | |
16 | */ | |
17 | ||
18 | #include <linux/mutex.h> | |
19 | #include <linux/list.h> | |
20 | #include <linux/netdevice.h> | |
21 | #include <linux/module.h> | |
22 | ||
23 | #include "be.h" | |
24 | #include "be_cmds.h" | |
25 | ||
26 | static struct ocrdma_driver *ocrdma_drv; | |
27 | static LIST_HEAD(be_adapter_list); | |
28 | static DEFINE_MUTEX(be_adapter_list_lock); | |
29 | ||
30 | static void _be_roce_dev_add(struct be_adapter *adapter) | |
31 | { | |
32 | struct be_dev_info dev_info; | |
33 | int i, num_vec; | |
34 | struct pci_dev *pdev = adapter->pdev; | |
35 | ||
36 | if (!ocrdma_drv) | |
37 | return; | |
38 | if (pdev->device == OC_DEVICE_ID5) { | |
39 | /* only msix is supported on these devices */ | |
40 | if (!msix_enabled(adapter)) | |
41 | return; | |
42 | /* DPP region address and length */ | |
43 | dev_info.dpp_unmapped_addr = pci_resource_start(pdev, 2); | |
44 | dev_info.dpp_unmapped_len = pci_resource_len(pdev, 2); | |
45 | } else { | |
46 | dev_info.dpp_unmapped_addr = 0; | |
47 | dev_info.dpp_unmapped_len = 0; | |
48 | } | |
49 | dev_info.pdev = adapter->pdev; | |
dbf0f2a7 | 50 | dev_info.db = adapter->db; |
045508a8 PP |
51 | dev_info.unmapped_db = adapter->roce_db.io_addr; |
52 | dev_info.db_page_size = adapter->roce_db.size; | |
53 | dev_info.db_total_size = adapter->roce_db.total_size; | |
54 | dev_info.netdev = adapter->netdev; | |
55 | memcpy(dev_info.mac_addr, adapter->netdev->dev_addr, ETH_ALEN); | |
56 | dev_info.dev_family = adapter->sli_family; | |
57 | if (msix_enabled(adapter)) { | |
58 | /* provide all the vectors, so that EQ creation response | |
59 | * can decide which one to use. | |
60 | */ | |
61 | num_vec = adapter->num_msix_vec + adapter->num_msix_roce_vec; | |
62 | dev_info.intr_mode = BE_INTERRUPT_MODE_MSIX; | |
63 | dev_info.msix.num_vectors = min(num_vec, MAX_ROCE_MSIX_VECTORS); | |
64 | /* provide start index of the vector, | |
65 | * so in case of linear usage, | |
66 | * it can use the base as starting point. | |
67 | */ | |
68 | dev_info.msix.start_vector = adapter->num_evt_qs; | |
69 | for (i = 0; i < dev_info.msix.num_vectors; i++) { | |
70 | dev_info.msix.vector_list[i] = | |
71 | adapter->msix_entries[i].vector; | |
72 | } | |
73 | } else { | |
74 | dev_info.msix.num_vectors = 0; | |
75 | dev_info.intr_mode = BE_INTERRUPT_MODE_INTX; | |
76 | } | |
77 | adapter->ocrdma_dev = ocrdma_drv->add(&dev_info); | |
78 | } | |
79 | ||
80 | void be_roce_dev_add(struct be_adapter *adapter) | |
81 | { | |
82 | if (be_roce_supported(adapter)) { | |
83 | INIT_LIST_HEAD(&adapter->entry); | |
84 | mutex_lock(&be_adapter_list_lock); | |
85 | list_add_tail(&adapter->entry, &be_adapter_list); | |
86 | ||
87 | /* invoke add() routine of roce driver only if | |
88 | * valid driver registered with add method and add() is not yet | |
89 | * invoked on a given adapter. | |
90 | */ | |
91 | _be_roce_dev_add(adapter); | |
92 | mutex_unlock(&be_adapter_list_lock); | |
93 | } | |
94 | } | |
95 | ||
96 | void _be_roce_dev_remove(struct be_adapter *adapter) | |
97 | { | |
98 | if (ocrdma_drv && ocrdma_drv->remove && adapter->ocrdma_dev) | |
99 | ocrdma_drv->remove(adapter->ocrdma_dev); | |
100 | adapter->ocrdma_dev = NULL; | |
101 | } | |
102 | ||
103 | void be_roce_dev_remove(struct be_adapter *adapter) | |
104 | { | |
105 | if (be_roce_supported(adapter)) { | |
106 | mutex_lock(&be_adapter_list_lock); | |
107 | _be_roce_dev_remove(adapter); | |
108 | list_del(&adapter->entry); | |
109 | mutex_unlock(&be_adapter_list_lock); | |
110 | } | |
111 | } | |
112 | ||
113 | void _be_roce_dev_open(struct be_adapter *adapter) | |
114 | { | |
115 | if (ocrdma_drv && adapter->ocrdma_dev && | |
116 | ocrdma_drv->state_change_handler) | |
117 | ocrdma_drv->state_change_handler(adapter->ocrdma_dev, 0); | |
118 | } | |
119 | ||
120 | void be_roce_dev_open(struct be_adapter *adapter) | |
121 | { | |
122 | if (be_roce_supported(adapter)) { | |
123 | mutex_lock(&be_adapter_list_lock); | |
124 | _be_roce_dev_open(adapter); | |
125 | mutex_unlock(&be_adapter_list_lock); | |
126 | } | |
127 | } | |
128 | ||
129 | void _be_roce_dev_close(struct be_adapter *adapter) | |
130 | { | |
131 | if (ocrdma_drv && adapter->ocrdma_dev && | |
132 | ocrdma_drv->state_change_handler) | |
133 | ocrdma_drv->state_change_handler(adapter->ocrdma_dev, 1); | |
134 | } | |
135 | ||
136 | void be_roce_dev_close(struct be_adapter *adapter) | |
137 | { | |
138 | if (be_roce_supported(adapter)) { | |
139 | mutex_lock(&be_adapter_list_lock); | |
140 | _be_roce_dev_close(adapter); | |
141 | mutex_unlock(&be_adapter_list_lock); | |
142 | } | |
143 | } | |
144 | ||
145 | int be_roce_register_driver(struct ocrdma_driver *drv) | |
146 | { | |
147 | struct be_adapter *dev; | |
148 | ||
149 | mutex_lock(&be_adapter_list_lock); | |
150 | if (ocrdma_drv) { | |
151 | mutex_unlock(&be_adapter_list_lock); | |
152 | return -EINVAL; | |
153 | } | |
154 | ocrdma_drv = drv; | |
155 | list_for_each_entry(dev, &be_adapter_list, entry) { | |
156 | struct net_device *netdev; | |
157 | _be_roce_dev_add(dev); | |
158 | netdev = dev->netdev; | |
159 | if (netif_running(netdev) && netif_oper_up(netdev)) | |
160 | _be_roce_dev_open(dev); | |
161 | } | |
162 | mutex_unlock(&be_adapter_list_lock); | |
163 | return 0; | |
164 | } | |
165 | EXPORT_SYMBOL(be_roce_register_driver); | |
166 | ||
167 | void be_roce_unregister_driver(struct ocrdma_driver *drv) | |
168 | { | |
169 | struct be_adapter *dev; | |
170 | ||
171 | mutex_lock(&be_adapter_list_lock); | |
172 | list_for_each_entry(dev, &be_adapter_list, entry) { | |
173 | if (dev->ocrdma_dev) | |
174 | _be_roce_dev_remove(dev); | |
175 | } | |
176 | ocrdma_drv = NULL; | |
177 | mutex_unlock(&be_adapter_list_lock); | |
178 | } | |
179 | EXPORT_SYMBOL(be_roce_unregister_driver); |