aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYevgeny Petrilin <yevgenyp@mellanox.co.il>2009-03-18 22:45:11 -0400
committerRoland Dreier <rolandd@cisco.com>2009-03-18 22:45:11 -0400
commit27bf91d6a0d5a9c7224e8687754249bba67dd4cf (patch)
tree55c253fa4438ea29d73f072a88dff5fb74e2ca4e
parent793730bfb6711d6d14629e63845c25a3c14d205e (diff)
mlx4_core: Add link type autosensing
When a port's link is down (except to driver restart) and the port is configured for auto sensing, we try to sense port link type (Ethernet or InfiniBand) in order to determine how to initialize the port. If the port type needs to be changed, all mlx4 for the device interfaces are unregistered and then registered again with the new port types. Sensing is done with intervals of 3 seconds. Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il> Signed-off-by: Roland Dreier <rolandd@cisco.com>
-rw-r--r--drivers/net/mlx4/Makefile2
-rw-r--r--drivers/net/mlx4/catas.c16
-rw-r--r--drivers/net/mlx4/eq.c16
-rw-r--r--drivers/net/mlx4/main.c104
-rw-r--r--drivers/net/mlx4/mlx4.h27
-rw-r--r--drivers/net/mlx4/sense.c156
-rw-r--r--include/linux/mlx4/cmd.h1
-rw-r--r--include/linux/mlx4/device.h6
8 files changed, 277 insertions, 51 deletions
diff --git a/drivers/net/mlx4/Makefile b/drivers/net/mlx4/Makefile
index a7a97bf998f8..21040a0d81fe 100644
--- a/drivers/net/mlx4/Makefile
+++ b/drivers/net/mlx4/Makefile
@@ -1,7 +1,7 @@
1obj-$(CONFIG_MLX4_CORE) += mlx4_core.o 1obj-$(CONFIG_MLX4_CORE) += mlx4_core.o
2 2
3mlx4_core-y := alloc.o catas.o cmd.o cq.o eq.o fw.o icm.o intf.o main.o mcg.o \ 3mlx4_core-y := alloc.o catas.o cmd.o cq.o eq.o fw.o icm.o intf.o main.o mcg.o \
4 mr.o pd.o port.o profile.o qp.o reset.o srq.o 4 mr.o pd.o port.o profile.o qp.o reset.o sense.o srq.o
5 5
6obj-$(CONFIG_MLX4_EN) += mlx4_en.o 6obj-$(CONFIG_MLX4_EN) += mlx4_en.o
7 7
diff --git a/drivers/net/mlx4/catas.c b/drivers/net/mlx4/catas.c
index f094ee00c416..aa9674b7f19c 100644
--- a/drivers/net/mlx4/catas.c
+++ b/drivers/net/mlx4/catas.c
@@ -42,7 +42,6 @@ enum {
42static DEFINE_SPINLOCK(catas_lock); 42static DEFINE_SPINLOCK(catas_lock);
43 43
44static LIST_HEAD(catas_list); 44static LIST_HEAD(catas_list);
45static struct workqueue_struct *catas_wq;
46static struct work_struct catas_work; 45static struct work_struct catas_work;
47 46
48static int internal_err_reset = 1; 47static int internal_err_reset = 1;
@@ -77,7 +76,7 @@ static void poll_catas(unsigned long dev_ptr)
77 list_add(&priv->catas_err.list, &catas_list); 76 list_add(&priv->catas_err.list, &catas_list);
78 spin_unlock(&catas_lock); 77 spin_unlock(&catas_lock);
79 78
80 queue_work(catas_wq, &catas_work); 79 queue_work(mlx4_wq, &catas_work);
81 } 80 }
82 } else 81 } else
83 mod_timer(&priv->catas_err.timer, 82 mod_timer(&priv->catas_err.timer,
@@ -146,18 +145,7 @@ void mlx4_stop_catas_poll(struct mlx4_dev *dev)
146 spin_unlock_irq(&catas_lock); 145 spin_unlock_irq(&catas_lock);
147} 146}
148 147
149int __init mlx4_catas_init(void) 148void __init mlx4_catas_init(void)
150{ 149{
151 INIT_WORK(&catas_work, catas_reset); 150 INIT_WORK(&catas_work, catas_reset);
152
153 catas_wq = create_singlethread_workqueue("mlx4_err");
154 if (!catas_wq)
155 return -ENOMEM;
156
157 return 0;
158}
159
160void mlx4_catas_cleanup(void)
161{
162 destroy_workqueue(catas_wq);
163} 151}
diff --git a/drivers/net/mlx4/eq.c b/drivers/net/mlx4/eq.c
index 2c19bff7cbab..8830dcb92ec8 100644
--- a/drivers/net/mlx4/eq.c
+++ b/drivers/net/mlx4/eq.c
@@ -163,6 +163,7 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
163 int cqn; 163 int cqn;
164 int eqes_found = 0; 164 int eqes_found = 0;
165 int set_ci = 0; 165 int set_ci = 0;
166 int port;
166 167
167 while ((eqe = next_eqe_sw(eq))) { 168 while ((eqe = next_eqe_sw(eq))) {
168 /* 169 /*
@@ -203,11 +204,16 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
203 break; 204 break;
204 205
205 case MLX4_EVENT_TYPE_PORT_CHANGE: 206 case MLX4_EVENT_TYPE_PORT_CHANGE:
206 mlx4_dispatch_event(dev, 207 port = be32_to_cpu(eqe->event.port_change.port) >> 28;
207 eqe->subtype == MLX4_PORT_CHANGE_SUBTYPE_ACTIVE ? 208 if (eqe->subtype == MLX4_PORT_CHANGE_SUBTYPE_DOWN) {
208 MLX4_DEV_EVENT_PORT_UP : 209 mlx4_dispatch_event(dev, MLX4_DEV_EVENT_PORT_DOWN,
209 MLX4_DEV_EVENT_PORT_DOWN, 210 port);
210 be32_to_cpu(eqe->event.port_change.port) >> 28); 211 mlx4_priv(dev)->sense.do_sense_port[port] = 1;
212 } else {
213 mlx4_dispatch_event(dev, MLX4_DEV_EVENT_PORT_UP,
214 port);
215 mlx4_priv(dev)->sense.do_sense_port[port] = 0;
216 }
211 break; 217 break;
212 218
213 case MLX4_EVENT_TYPE_CQ_ERROR: 219 case MLX4_EVENT_TYPE_CQ_ERROR:
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index 8480f0346844..a66f5b2fd288 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -51,6 +51,8 @@ MODULE_DESCRIPTION("Mellanox ConnectX HCA low-level driver");
51MODULE_LICENSE("Dual BSD/GPL"); 51MODULE_LICENSE("Dual BSD/GPL");
52MODULE_VERSION(DRV_VERSION); 52MODULE_VERSION(DRV_VERSION);
53 53
54struct workqueue_struct *mlx4_wq;
55
54#ifdef CONFIG_MLX4_DEBUG 56#ifdef CONFIG_MLX4_DEBUG
55 57
56int mlx4_debug_level = 0; 58int mlx4_debug_level = 0;
@@ -98,24 +100,23 @@ module_param_named(use_prio, use_prio, bool, 0444);
98MODULE_PARM_DESC(use_prio, "Enable steering by VLAN priority on ETH ports " 100MODULE_PARM_DESC(use_prio, "Enable steering by VLAN priority on ETH ports "
99 "(0/1, default 0)"); 101 "(0/1, default 0)");
100 102
101static int mlx4_check_port_params(struct mlx4_dev *dev, 103int mlx4_check_port_params(struct mlx4_dev *dev,
102 enum mlx4_port_type *port_type) 104 enum mlx4_port_type *port_type)
103{ 105{
104 int i; 106 int i;
105 107
106 for (i = 0; i < dev->caps.num_ports - 1; i++) { 108 for (i = 0; i < dev->caps.num_ports - 1; i++) {
107 if (port_type[i] != port_type[i+1] && 109 if (port_type[i] != port_type[i + 1]) {
108 !(dev->caps.flags & MLX4_DEV_CAP_FLAG_DPDP)) { 110 if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_DPDP)) {
109 mlx4_err(dev, "Only same port types supported " 111 mlx4_err(dev, "Only same port types supported "
110 "on this HCA, aborting.\n"); 112 "on this HCA, aborting.\n");
111 return -EINVAL; 113 return -EINVAL;
114 }
115 if (port_type[i] == MLX4_PORT_TYPE_ETH &&
116 port_type[i + 1] == MLX4_PORT_TYPE_IB)
117 return -EINVAL;
112 } 118 }
113 } 119 }
114 if ((port_type[0] == MLX4_PORT_TYPE_ETH) &&
115 (port_type[1] == MLX4_PORT_TYPE_IB)) {
116 mlx4_err(dev, "eth-ib configuration is not supported.\n");
117 return -EINVAL;
118 }
119 120
120 for (i = 0; i < dev->caps.num_ports; i++) { 121 for (i = 0; i < dev->caps.num_ports; i++) {
121 if (!(port_type[i] & dev->caps.supported_type[i+1])) { 122 if (!(port_type[i] & dev->caps.supported_type[i+1])) {
@@ -225,6 +226,9 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
225 dev->caps.port_type[i] = MLX4_PORT_TYPE_IB; 226 dev->caps.port_type[i] = MLX4_PORT_TYPE_IB;
226 else 227 else
227 dev->caps.port_type[i] = MLX4_PORT_TYPE_ETH; 228 dev->caps.port_type[i] = MLX4_PORT_TYPE_ETH;
229 dev->caps.possible_type[i] = dev->caps.port_type[i];
230 mlx4_priv(dev)->sense.sense_allowed[i] =
231 dev->caps.supported_type[i] == MLX4_PORT_TYPE_AUTO;
228 232
229 if (dev->caps.log_num_macs > dev_cap->log_max_macs[i]) { 233 if (dev->caps.log_num_macs > dev_cap->log_max_macs[i]) {
230 dev->caps.log_num_macs = dev_cap->log_max_macs[i]; 234 dev->caps.log_num_macs = dev_cap->log_max_macs[i];
@@ -263,14 +267,16 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
263 * Change the port configuration of the device. 267 * Change the port configuration of the device.
264 * Every user of this function must hold the port mutex. 268 * Every user of this function must hold the port mutex.
265 */ 269 */
266static int mlx4_change_port_types(struct mlx4_dev *dev, 270int mlx4_change_port_types(struct mlx4_dev *dev,
267 enum mlx4_port_type *port_types) 271 enum mlx4_port_type *port_types)
268{ 272{
269 int err = 0; 273 int err = 0;
270 int change = 0; 274 int change = 0;
271 int port; 275 int port;
272 276
273 for (port = 0; port < dev->caps.num_ports; port++) { 277 for (port = 0; port < dev->caps.num_ports; port++) {
278 /* Change the port type only if the new type is different
279 * from the current, and not set to Auto */
274 if (port_types[port] != dev->caps.port_type[port + 1]) { 280 if (port_types[port] != dev->caps.port_type[port + 1]) {
275 change = 1; 281 change = 1;