blob: deecc44b36177aff72f65f1a258d5b7391827a6e [file] [log] [blame]
Parav Pandit045508a2012-03-26 14:27:13 +00001/*
2 * Copyright (C) 2005 - 2011 Emulex
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
26static struct ocrdma_driver *ocrdma_drv;
27static LIST_HEAD(be_adapter_list);
28static DEFINE_MUTEX(be_adapter_list_lock);
29
30static 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;
50 if (adapter->sli_family == SKYHAWK_SLI_FAMILY)
51 dev_info.db = adapter->db;
52 else
53 dev_info.db = adapter->roce_db.base;
54 dev_info.unmapped_db = adapter->roce_db.io_addr;
55 dev_info.db_page_size = adapter->roce_db.size;
56 dev_info.db_total_size = adapter->roce_db.total_size;
57 dev_info.netdev = adapter->netdev;
58 memcpy(dev_info.mac_addr, adapter->netdev->dev_addr, ETH_ALEN);
59 dev_info.dev_family = adapter->sli_family;
60 if (msix_enabled(adapter)) {
61 /* provide all the vectors, so that EQ creation response
62 * can decide which one to use.
63 */
64 num_vec = adapter->num_msix_vec + adapter->num_msix_roce_vec;
65 dev_info.intr_mode = BE_INTERRUPT_MODE_MSIX;
66 dev_info.msix.num_vectors = min(num_vec, MAX_ROCE_MSIX_VECTORS);
67 /* provide start index of the vector,
68 * so in case of linear usage,
69 * it can use the base as starting point.
70 */
71 dev_info.msix.start_vector = adapter->num_evt_qs;
72 for (i = 0; i < dev_info.msix.num_vectors; i++) {
73 dev_info.msix.vector_list[i] =
74 adapter->msix_entries[i].vector;
75 }
76 } else {
77 dev_info.msix.num_vectors = 0;
78 dev_info.intr_mode = BE_INTERRUPT_MODE_INTX;
79 }
80 adapter->ocrdma_dev = ocrdma_drv->add(&dev_info);
81}
82
83void be_roce_dev_add(struct be_adapter *adapter)
84{
85 if (be_roce_supported(adapter)) {
86 INIT_LIST_HEAD(&adapter->entry);
87 mutex_lock(&be_adapter_list_lock);
88 list_add_tail(&adapter->entry, &be_adapter_list);
89
90 /* invoke add() routine of roce driver only if
91 * valid driver registered with add method and add() is not yet
92 * invoked on a given adapter.
93 */
94 _be_roce_dev_add(adapter);
95 mutex_unlock(&be_adapter_list_lock);
96 }
97}
98
99void _be_roce_dev_remove(struct be_adapter *adapter)
100{
101 if (ocrdma_drv && ocrdma_drv->remove && adapter->ocrdma_dev)
102 ocrdma_drv->remove(adapter->ocrdma_dev);
103 adapter->ocrdma_dev = NULL;
104}
105
106void be_roce_dev_remove(struct be_adapter *adapter)
107{
108 if (be_roce_supported(adapter)) {
109 mutex_lock(&be_adapter_list_lock);
110 _be_roce_dev_remove(adapter);
111 list_del(&adapter->entry);
112 mutex_unlock(&be_adapter_list_lock);
113 }
114}
115
116void _be_roce_dev_open(struct be_adapter *adapter)
117{
118 if (ocrdma_drv && adapter->ocrdma_dev &&
119 ocrdma_drv->state_change_handler)
120 ocrdma_drv->state_change_handler(adapter->ocrdma_dev, 0);
121}
122
123void be_roce_dev_open(struct be_adapter *adapter)
124{
125 if (be_roce_supported(adapter)) {
126 mutex_lock(&be_adapter_list_lock);
127 _be_roce_dev_open(adapter);
128 mutex_unlock(&be_adapter_list_lock);
129 }
130}
131
132void _be_roce_dev_close(struct be_adapter *adapter)
133{
134 if (ocrdma_drv && adapter->ocrdma_dev &&
135 ocrdma_drv->state_change_handler)
136 ocrdma_drv->state_change_handler(adapter->ocrdma_dev, 1);
137}
138
139void be_roce_dev_close(struct be_adapter *adapter)
140{
141 if (be_roce_supported(adapter)) {
142 mutex_lock(&be_adapter_list_lock);
143 _be_roce_dev_close(adapter);
144 mutex_unlock(&be_adapter_list_lock);
145 }
146}
147
148int be_roce_register_driver(struct ocrdma_driver *drv)
149{
150 struct be_adapter *dev;
151
152 mutex_lock(&be_adapter_list_lock);
153 if (ocrdma_drv) {
154 mutex_unlock(&be_adapter_list_lock);
155 return -EINVAL;
156 }
157 ocrdma_drv = drv;
158 list_for_each_entry(dev, &be_adapter_list, entry) {
159 struct net_device *netdev;
160 _be_roce_dev_add(dev);
161 netdev = dev->netdev;
162 if (netif_running(netdev) && netif_oper_up(netdev))
163 _be_roce_dev_open(dev);
164 }
165 mutex_unlock(&be_adapter_list_lock);
166 return 0;
167}
168EXPORT_SYMBOL(be_roce_register_driver);
169
170void be_roce_unregister_driver(struct ocrdma_driver *drv)
171{
172 struct be_adapter *dev;
173
174 mutex_lock(&be_adapter_list_lock);
175 list_for_each_entry(dev, &be_adapter_list, entry) {
176 if (dev->ocrdma_dev)
177 _be_roce_dev_remove(dev);
178 }
179 ocrdma_drv = NULL;
180 mutex_unlock(&be_adapter_list_lock);
181}
182EXPORT_SYMBOL(be_roce_unregister_driver);