blob: 448d156c3d0804da56c2633113d3a7ef04b8e683 [file] [log] [blame]
Jitendra Kalsaria577ae392013-02-04 12:33:07 +00001/*
2 * QLogic qlcnic NIC Driver
3 * Copyright (c) 2009-2013 QLogic Corporation
4 *
5 * See LICENSE.qlcnic for copyright and licensing details.
6 */
7
Sony Chackoec079a02012-11-28 04:34:28 +00008#include <linux/slab.h>
Sony Chackoec079a02012-11-28 04:34:28 +00009#include <linux/interrupt.h>
10
11#include "qlcnic.h"
Sony Chacko319ecf12013-01-01 03:20:22 +000012#include "qlcnic_hw.h"
Sony Chackoec079a02012-11-28 04:34:28 +000013
14#include <linux/swab.h>
15#include <linux/dma-mapping.h>
16#include <net/ip.h>
17#include <linux/ipv6.h>
18#include <linux/inetdevice.h>
19#include <linux/sysfs.h>
20#include <linux/aer.h>
21#include <linux/log2.h>
22
Sony Chacko319ecf12013-01-01 03:20:22 +000023#define QLC_STATUS_UNSUPPORTED_CMD -2
24
Sony Chackoec079a02012-11-28 04:34:28 +000025int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable)
26{
27 return -EOPNOTSUPP;
28}
29
30int qlcnicvf_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate)
31{
32 return -EOPNOTSUPP;
33}
34
Sony Chackob66e29c2012-11-28 04:34:29 +000035static ssize_t qlcnic_store_bridged_mode(struct device *dev,
36 struct device_attribute *attr,
37 const char *buf, size_t len)
Sony Chackoec079a02012-11-28 04:34:28 +000038{
39 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
40 unsigned long new;
41 int ret = -EINVAL;
42
Sony Chacko79788452012-12-04 03:33:53 +000043 if (!(adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_BDG))
Sony Chackoec079a02012-11-28 04:34:28 +000044 goto err_out;
45
46 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
47 goto err_out;
48
Jingoo Han67d6bfa2013-05-31 21:21:35 +000049 if (kstrtoul(buf, 2, &new))
Sony Chackoec079a02012-11-28 04:34:28 +000050 goto err_out;
51
Sony Chacko319ecf12013-01-01 03:20:22 +000052 if (!qlcnic_config_bridged_mode(adapter, !!new))
Sony Chackoec079a02012-11-28 04:34:28 +000053 ret = len;
54
55err_out:
56 return ret;
57}
58
Sony Chackob66e29c2012-11-28 04:34:29 +000059static ssize_t qlcnic_show_bridged_mode(struct device *dev,
60 struct device_attribute *attr,
61 char *buf)
Sony Chackoec079a02012-11-28 04:34:28 +000062{
63 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
64 int bridged_mode = 0;
65
Sony Chacko79788452012-12-04 03:33:53 +000066 if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_BDG)
Sony Chackoec079a02012-11-28 04:34:28 +000067 bridged_mode = !!(adapter->flags & QLCNIC_BRIDGE_ENABLED);
68
69 return sprintf(buf, "%d\n", bridged_mode);
70}
71
Sony Chackob66e29c2012-11-28 04:34:29 +000072static ssize_t qlcnic_store_diag_mode(struct device *dev,
73 struct device_attribute *attr,
74 const char *buf, size_t len)
Sony Chackoec079a02012-11-28 04:34:28 +000075{
76 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
77 unsigned long new;
78
Jingoo Han67d6bfa2013-05-31 21:21:35 +000079 if (kstrtoul(buf, 2, &new))
Sony Chackoec079a02012-11-28 04:34:28 +000080 return -EINVAL;
81
82 if (!!new != !!(adapter->flags & QLCNIC_DIAG_ENABLED))
83 adapter->flags ^= QLCNIC_DIAG_ENABLED;
84
85 return len;
86}
87
Sony Chackob66e29c2012-11-28 04:34:29 +000088static ssize_t qlcnic_show_diag_mode(struct device *dev,
89 struct device_attribute *attr, char *buf)
Sony Chackoec079a02012-11-28 04:34:28 +000090{
91 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
Sony Chacko319ecf12013-01-01 03:20:22 +000092 return sprintf(buf, "%d\n", !!(adapter->flags & QLCNIC_DIAG_ENABLED));
Sony Chackoec079a02012-11-28 04:34:28 +000093}
94
Sony Chackob66e29c2012-11-28 04:34:29 +000095static int qlcnic_validate_beacon(struct qlcnic_adapter *adapter, u16 beacon,
96 u8 *state, u8 *rate)
Sony Chackoec079a02012-11-28 04:34:28 +000097{
98 *rate = LSB(beacon);
99 *state = MSB(beacon);
100
101 QLCDB(adapter, DRV, "rate %x state %x\n", *rate, *state);
102
103 if (!*state) {
104 *rate = __QLCNIC_MAX_LED_RATE;
105 return 0;
Sony Chackob66e29c2012-11-28 04:34:29 +0000106 } else if (*state > __QLCNIC_MAX_LED_STATE) {
Sony Chackoec079a02012-11-28 04:34:28 +0000107 return -EINVAL;
Sony Chackob66e29c2012-11-28 04:34:29 +0000108 }
Sony Chackoec079a02012-11-28 04:34:28 +0000109
110 if ((!*rate) || (*rate > __QLCNIC_MAX_LED_RATE))
111 return -EINVAL;
112
113 return 0;
114}
115
Himanshu Madhani487042a2013-05-23 21:04:33 +0000116static int qlcnic_83xx_store_beacon(struct qlcnic_adapter *adapter,
117 const char *buf, size_t len)
Sony Chackoec079a02012-11-28 04:34:28 +0000118{
Himanshu Madhani487042a2013-05-23 21:04:33 +0000119 struct qlcnic_hardware_context *ahw = adapter->ahw;
120 unsigned long h_beacon;
121 int err;
122
123 if (test_bit(__QLCNIC_RESETTING, &adapter->state))
124 return -EIO;
125
126 if (kstrtoul(buf, 2, &h_beacon))
127 return -EINVAL;
128
Himanshu Madhania0431582014-01-10 11:48:56 -0500129 qlcnic_get_beacon_state(adapter);
130
Himanshu Madhani487042a2013-05-23 21:04:33 +0000131 if (ahw->beacon_state == h_beacon)
132 return len;
133
134 rtnl_lock();
135 if (!ahw->beacon_state) {
136 if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state)) {
137 rtnl_unlock();
138 return -EBUSY;
139 }
140 }
141
142 if (h_beacon)
143 err = qlcnic_83xx_config_led(adapter, 1, h_beacon);
144 else
145 err = qlcnic_83xx_config_led(adapter, 0, !h_beacon);
146 if (!err)
147 ahw->beacon_state = h_beacon;
148
149 if (!ahw->beacon_state)
150 clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
151
152 rtnl_unlock();
153 return len;
154}
155
156static int qlcnic_82xx_store_beacon(struct qlcnic_adapter *adapter,
157 const char *buf, size_t len)
158{
Sony Chacko319ecf12013-01-01 03:20:22 +0000159 struct qlcnic_hardware_context *ahw = adapter->ahw;
Himanshu Madhani34e8c402013-11-04 13:31:31 -0500160 int err, drv_sds_rings = adapter->drv_sds_rings;
Sony Chackoec079a02012-11-28 04:34:28 +0000161 u16 beacon;
Himanshu Madhania0431582014-01-10 11:48:56 -0500162 u8 b_state, b_rate;
Sony Chacko319ecf12013-01-01 03:20:22 +0000163
Sony Chackoec079a02012-11-28 04:34:28 +0000164 if (len != sizeof(u16))
165 return QL_STATUS_INVALID_PARAM;
166
167 memcpy(&beacon, buf, sizeof(u16));
168 err = qlcnic_validate_beacon(adapter, beacon, &b_state, &b_rate);
169 if (err)
170 return err;
171
Himanshu Madhania0431582014-01-10 11:48:56 -0500172 qlcnic_get_beacon_state(adapter);
Himanshu Madhani487042a2013-05-23 21:04:33 +0000173
174 if (ahw->beacon_state == b_state)
Sony Chackoec079a02012-11-28 04:34:28 +0000175 return len;
176
177 rtnl_lock();
Himanshu Madhani487042a2013-05-23 21:04:33 +0000178 if (!ahw->beacon_state) {
Sony Chackoec079a02012-11-28 04:34:28 +0000179 if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state)) {
180 rtnl_unlock();
181 return -EBUSY;
182 }
Himanshu Madhani487042a2013-05-23 21:04:33 +0000183 }
Sony Chackoec079a02012-11-28 04:34:28 +0000184
185 if (test_bit(__QLCNIC_RESETTING, &adapter->state)) {
186 err = -EIO;
187 goto out;
188 }
189
190 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
191 err = qlcnic_diag_alloc_res(adapter->netdev, QLCNIC_LED_TEST);
192 if (err)
193 goto out;
194 set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state);
195 }
196
197 err = qlcnic_config_led(adapter, b_state, b_rate);
Himanshu Madhani361cd292013-04-16 18:11:10 +0000198 if (!err) {
Sony Chackoec079a02012-11-28 04:34:28 +0000199 err = len;
Sony Chacko319ecf12013-01-01 03:20:22 +0000200 ahw->beacon_state = b_state;
Himanshu Madhani361cd292013-04-16 18:11:10 +0000201 }
Sony Chackoec079a02012-11-28 04:34:28 +0000202
203 if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state))
Himanshu Madhani34e8c402013-11-04 13:31:31 -0500204 qlcnic_diag_free_res(adapter->netdev, drv_sds_rings);
Sony Chackoec079a02012-11-28 04:34:28 +0000205
Himanshu Madhani487042a2013-05-23 21:04:33 +0000206out:
207 if (!ahw->beacon_state)
Sony Chackoec079a02012-11-28 04:34:28 +0000208 clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
209 rtnl_unlock();
210
211 return err;
212}
213
Himanshu Madhani487042a2013-05-23 21:04:33 +0000214static ssize_t qlcnic_store_beacon(struct device *dev,
215 struct device_attribute *attr,
216 const char *buf, size_t len)
217{
218 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
219 int err = 0;
220
221 if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
222 dev_warn(dev,
223 "LED test not supported in non privileged mode\n");
224 return -EOPNOTSUPP;
225 }
226
227 if (qlcnic_82xx_check(adapter))
228 err = qlcnic_82xx_store_beacon(adapter, buf, len);
229 else if (qlcnic_83xx_check(adapter))
230 err = qlcnic_83xx_store_beacon(adapter, buf, len);
231 else
232 return -EIO;
233
234 return err;
235}
236
Sony Chackob66e29c2012-11-28 04:34:29 +0000237static ssize_t qlcnic_show_beacon(struct device *dev,
238 struct device_attribute *attr, char *buf)
Sony Chackoec079a02012-11-28 04:34:28 +0000239{
240 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
241
242 return sprintf(buf, "%d\n", adapter->ahw->beacon_state);
243}
244
Sony Chackob66e29c2012-11-28 04:34:29 +0000245static int qlcnic_sysfs_validate_crb(struct qlcnic_adapter *adapter,
246 loff_t offset, size_t size)
Sony Chackoec079a02012-11-28 04:34:28 +0000247{
248 size_t crb_size = 4;
249
250 if (!(adapter->flags & QLCNIC_DIAG_ENABLED))
251 return -EIO;
252
253 if (offset < QLCNIC_PCI_CRBSPACE) {
254 if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM,
Sony Chackob66e29c2012-11-28 04:34:29 +0000255 QLCNIC_PCI_CAMQM_END))
Sony Chackoec079a02012-11-28 04:34:28 +0000256 crb_size = 8;
257 else
258 return -EINVAL;
259 }
260
261 if ((size != crb_size) || (offset & (crb_size-1)))
262 return -EINVAL;
263
264 return 0;
265}
266
Sony Chackob66e29c2012-11-28 04:34:29 +0000267static ssize_t qlcnic_sysfs_read_crb(struct file *filp, struct kobject *kobj,
268 struct bin_attribute *attr, char *buf,
269 loff_t offset, size_t size)
Sony Chackoec079a02012-11-28 04:34:28 +0000270{
271 struct device *dev = container_of(kobj, struct device, kobj);
272 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
Sony Chackoec079a02012-11-28 04:34:28 +0000273 int ret;
274
275 ret = qlcnic_sysfs_validate_crb(adapter, offset, size);
276 if (ret != 0)
277 return ret;
Sony Chacko319ecf12013-01-01 03:20:22 +0000278 qlcnic_read_crb(adapter, buf, offset, size);
Sony Chackoec079a02012-11-28 04:34:28 +0000279
Sony Chackoec079a02012-11-28 04:34:28 +0000280 return size;
281}
282
Sony Chackob66e29c2012-11-28 04:34:29 +0000283static ssize_t qlcnic_sysfs_write_crb(struct file *filp, struct kobject *kobj,
284 struct bin_attribute *attr, char *buf,
285 loff_t offset, size_t size)
Sony Chackoec079a02012-11-28 04:34:28 +0000286{
287 struct device *dev = container_of(kobj, struct device, kobj);
288 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
Sony Chackoec079a02012-11-28 04:34:28 +0000289 int ret;
290
291 ret = qlcnic_sysfs_validate_crb(adapter, offset, size);
292 if (ret != 0)
293 return ret;
294
Sony Chacko319ecf12013-01-01 03:20:22 +0000295 qlcnic_write_crb(adapter, buf, offset, size);
Sony Chackoec079a02012-11-28 04:34:28 +0000296 return size;
297}
298
Sony Chackob66e29c2012-11-28 04:34:29 +0000299static int qlcnic_sysfs_validate_mem(struct qlcnic_adapter *adapter,
300 loff_t offset, size_t size)
Sony Chackoec079a02012-11-28 04:34:28 +0000301{
302 if (!(adapter->flags & QLCNIC_DIAG_ENABLED))
303 return -EIO;
304
305 if ((size != 8) || (offset & 0x7))
306 return -EIO;
307
308 return 0;
309}
310
Sony Chackob66e29c2012-11-28 04:34:29 +0000311static ssize_t qlcnic_sysfs_read_mem(struct file *filp, struct kobject *kobj,
312 struct bin_attribute *attr, char *buf,
313 loff_t offset, size_t size)
Sony Chackoec079a02012-11-28 04:34:28 +0000314{
315 struct device *dev = container_of(kobj, struct device, kobj);
316 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
317 u64 data;
318 int ret;
319
320 ret = qlcnic_sysfs_validate_mem(adapter, offset, size);
321 if (ret != 0)
322 return ret;
323
324 if (qlcnic_pci_mem_read_2M(adapter, offset, &data))
325 return -EIO;
326
327 memcpy(buf, &data, size);
328
329 return size;
330}
331
Sony Chackob66e29c2012-11-28 04:34:29 +0000332static ssize_t qlcnic_sysfs_write_mem(struct file *filp, struct kobject *kobj,
333 struct bin_attribute *attr, char *buf,
334 loff_t offset, size_t size)
Sony Chackoec079a02012-11-28 04:34:28 +0000335{
336 struct device *dev = container_of(kobj, struct device, kobj);
337 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
338 u64 data;
339 int ret;
340
341 ret = qlcnic_sysfs_validate_mem(adapter, offset, size);
342 if (ret != 0)
343 return ret;
344
345 memcpy(&data, buf, size);
346
347 if (qlcnic_pci_mem_write_2M(adapter, offset, data))
348 return -EIO;
349
350 return size;
351}
352
Jitendra Kalsaria2f514c52013-12-17 09:01:54 -0500353int qlcnic_is_valid_nic_func(struct qlcnic_adapter *adapter, u8 pci_func)
354{
Sony Chacko319ecf12013-01-01 03:20:22 +0000355 int i;
Jitendra Kalsaria2f514c52013-12-17 09:01:54 -0500356
Jitendra Kalsariad91abf92014-02-21 13:20:11 -0500357 for (i = 0; i < adapter->ahw->max_vnic_func; i++) {
Sony Chacko319ecf12013-01-01 03:20:22 +0000358 if (adapter->npars[i].pci_func == pci_func)
359 return i;
360 }
Jitendra Kalsariad91abf92014-02-21 13:20:11 -0500361 return -EINVAL;
Sony Chacko319ecf12013-01-01 03:20:22 +0000362}
363
Sony Chackob66e29c2012-11-28 04:34:29 +0000364static int validate_pm_config(struct qlcnic_adapter *adapter,
365 struct qlcnic_pm_func_cfg *pm_cfg, int count)
Sony Chackoec079a02012-11-28 04:34:28 +0000366{
Sony Chacko319ecf12013-01-01 03:20:22 +0000367 u8 src_pci_func, s_esw_id, d_esw_id;
368 u8 dest_pci_func;
369 int i, src_index, dest_index;
Sony Chackoec079a02012-11-28 04:34:28 +0000370
371 for (i = 0; i < count; i++) {
372 src_pci_func = pm_cfg[i].pci_func;
373 dest_pci_func = pm_cfg[i].dest_npar;
Sony Chacko319ecf12013-01-01 03:20:22 +0000374 src_index = qlcnic_is_valid_nic_func(adapter, src_pci_func);
Sony Chacko319ecf12013-01-01 03:20:22 +0000375 if (src_index < 0)
Sony Chackoec079a02012-11-28 04:34:28 +0000376 return QL_STATUS_INVALID_PARAM;
377
Sony Chacko319ecf12013-01-01 03:20:22 +0000378 dest_index = qlcnic_is_valid_nic_func(adapter, dest_pci_func);
379 if (dest_index < 0)
Sony Chackoec079a02012-11-28 04:34:28 +0000380 return QL_STATUS_INVALID_PARAM;
381
Sony Chacko319ecf12013-01-01 03:20:22 +0000382 s_esw_id = adapter->npars[src_index].phy_port;
383 d_esw_id = adapter->npars[dest_index].phy_port;
Sony Chackoec079a02012-11-28 04:34:28 +0000384
385 if (s_esw_id != d_esw_id)
386 return QL_STATUS_INVALID_PARAM;
Sony Chackoec079a02012-11-28 04:34:28 +0000387 }
Sony Chackoec079a02012-11-28 04:34:28 +0000388
Sony Chacko319ecf12013-01-01 03:20:22 +0000389 return 0;
Sony Chackoec079a02012-11-28 04:34:28 +0000390}
391
Sony Chackob66e29c2012-11-28 04:34:29 +0000392static ssize_t qlcnic_sysfs_write_pm_config(struct file *filp,
393 struct kobject *kobj,
394 struct bin_attribute *attr,
395 char *buf, loff_t offset,
396 size_t size)
Sony Chackoec079a02012-11-28 04:34:28 +0000397{
398 struct device *dev = container_of(kobj, struct device, kobj);
399 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
400 struct qlcnic_pm_func_cfg *pm_cfg;
401 u32 id, action, pci_func;
Sony Chacko319ecf12013-01-01 03:20:22 +0000402 int count, rem, i, ret, index;
Sony Chackoec079a02012-11-28 04:34:28 +0000403
404 count = size / sizeof(struct qlcnic_pm_func_cfg);
405 rem = size % sizeof(struct qlcnic_pm_func_cfg);
406 if (rem)
407 return QL_STATUS_INVALID_PARAM;
408
Sony Chackob66e29c2012-11-28 04:34:29 +0000409 pm_cfg = (struct qlcnic_pm_func_cfg *)buf;
Sony Chackoec079a02012-11-28 04:34:28 +0000410 ret = validate_pm_config(adapter, pm_cfg, count);
Sony Chacko319ecf12013-01-01 03:20:22 +0000411
Sony Chackoec079a02012-11-28 04:34:28 +0000412 if (ret)
413 return ret;
414 for (i = 0; i < count; i++) {
415 pci_func = pm_cfg[i].pci_func;
416 action = !!pm_cfg[i].action;
Sony Chacko319ecf12013-01-01 03:20:22 +0000417 index = qlcnic_is_valid_nic_func(adapter, pci_func);
418 if (index < 0)
419 return QL_STATUS_INVALID_PARAM;
420
421 id = adapter->npars[index].phy_port;
422 ret = qlcnic_config_port_mirroring(adapter, id,
423 action, pci_func);
Sony Chackoec079a02012-11-28 04:34:28 +0000424 if (ret)
425 return ret;
426 }
427
428 for (i = 0; i < count; i++) {
429 pci_func = pm_cfg[i].pci_func;
Sony Chacko319ecf12013-01-01 03:20:22 +0000430 index = qlcnic_is_valid_nic_func(adapter, pci_func);
Jitendra Kalsaria2f514c52013-12-17 09:01:54 -0500431 if (index < 0)
432 return QL_STATUS_INVALID_PARAM;
Sony Chacko319ecf12013-01-01 03:20:22 +0000433 id = adapter->npars[index].phy_port;
434 adapter->npars[index].enable_pm = !!pm_cfg[i].action;
435 adapter->npars[index].dest_npar = id;
Sony Chackoec079a02012-11-28 04:34:28 +0000436 }
Sony Chacko319ecf12013-01-01 03:20:22 +0000437
Sony Chackoec079a02012-11-28 04:34:28 +0000438 return size;
439}
440
Sony Chackob66e29c2012-11-28 04:34:29 +0000441static ssize_t qlcnic_sysfs_read_pm_config(struct file *filp,
442 struct kobject *kobj,
443 struct bin_attribute *attr,
444 char *buf, loff_t offset,
445 size_t size)
Sony Chackoec079a02012-11-28 04:34:28 +0000446{
447 struct device *dev = container_of(kobj, struct device, kobj);
448 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
Jitendra Kalsaria2f514c52013-12-17 09:01:54 -0500449 struct qlcnic_pm_func_cfg *pm_cfg;
Sony Chacko319ecf12013-01-01 03:20:22 +0000450 u8 pci_func;
Jitendra Kalsariad91abf92014-02-21 13:20:11 -0500451 u32 count;
452 int i;
Sony Chackoec079a02012-11-28 04:34:28 +0000453
Jitendra Kalsariad91abf92014-02-21 13:20:11 -0500454 memset(buf, 0, size);
Jitendra Kalsaria2f514c52013-12-17 09:01:54 -0500455 pm_cfg = (struct qlcnic_pm_func_cfg *)buf;
Jitendra Kalsariad91abf92014-02-21 13:20:11 -0500456 count = size / sizeof(struct qlcnic_pm_func_cfg);
457 for (i = 0; i < adapter->ahw->total_nic_func; i++) {
Sony Chacko319ecf12013-01-01 03:20:22 +0000458 pci_func = adapter->npars[i].pci_func;
Jitendra Kalsariad91abf92014-02-21 13:20:11 -0500459 if (pci_func >= count) {
460 dev_dbg(dev, "%s: Total nic functions[%d], App sent function count[%d]\n",
461 __func__, adapter->ahw->total_nic_func, count);
Sony Chacko35dafcb2013-08-30 13:51:23 -0400462 continue;
Jitendra Kalsariad91abf92014-02-21 13:20:11 -0500463 }
Sony Chacko35dafcb2013-08-30 13:51:23 -0400464 if (!adapter->npars[i].eswitch_status)
465 continue;
466
Sony Chacko319ecf12013-01-01 03:20:22 +0000467 pm_cfg[pci_func].action = adapter->npars[i].enable_pm;
468 pm_cfg[pci_func].dest_npar = 0;
469 pm_cfg[pci_func].pci_func = i;
Sony Chackoec079a02012-11-28 04:34:28 +0000470 }
Sony Chackoec079a02012-11-28 04:34:28 +0000471 return size;
472}
473
Sony Chackob66e29c2012-11-28 04:34:29 +0000474static int validate_esw_config(struct qlcnic_adapter *adapter,
475 struct qlcnic_esw_func_cfg *esw_cfg, int count)
Sony Chackoec079a02012-11-28 04:34:28 +0000476{
Jitendra Kalsaria2f514c52013-12-17 09:01:54 -0500477 struct qlcnic_hardware_context *ahw = adapter->ahw;
478 int i, ret;
Sony Chackoec079a02012-11-28 04:34:28 +0000479 u32 op_mode;
480 u8 pci_func;
Sony Chackoec079a02012-11-28 04:34:28 +0000481
Sony Chacko319ecf12013-01-01 03:20:22 +0000482 if (qlcnic_82xx_check(adapter))
Jitendra Kalsaria2f514c52013-12-17 09:01:54 -0500483 op_mode = readl(ahw->pci_base0 + QLCNIC_DRV_OP_MODE);
Sony Chacko319ecf12013-01-01 03:20:22 +0000484 else
Jitendra Kalsaria2f514c52013-12-17 09:01:54 -0500485 op_mode = QLCRDX(ahw, QLC_83XX_DRV_OP_MODE);
Sony Chackoec079a02012-11-28 04:34:28 +0000486
487 for (i = 0; i < count; i++) {
488 pci_func = esw_cfg[i].pci_func;
Jitendra Kalsariad91abf92014-02-21 13:20:11 -0500489 if (pci_func >= ahw->max_vnic_func)
Sony Chackoec079a02012-11-28 04:34:28 +0000490 return QL_STATUS_INVALID_PARAM;
491
Sony Chacko319ecf12013-01-01 03:20:22 +0000492 if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC)
493 if (qlcnic_is_valid_nic_func(adapter, pci_func) < 0)
Sony Chackoec079a02012-11-28 04:34:28 +0000494 return QL_STATUS_INVALID_PARAM;
495
496 switch (esw_cfg[i].op_mode) {
497 case QLCNIC_PORT_DEFAULTS:
Sony Chacko319ecf12013-01-01 03:20:22 +0000498 if (qlcnic_82xx_check(adapter)) {
499 ret = QLC_DEV_GET_DRV(op_mode, pci_func);
500 } else {
501 ret = QLC_83XX_GET_FUNC_PRIVILEGE(op_mode,
502 pci_func);
503 esw_cfg[i].offload_flags = 0;
504 }
505
506 if (ret != QLCNIC_NON_PRIV_FUNC) {
Sony Chackoec079a02012-11-28 04:34:28 +0000507 if (esw_cfg[i].mac_anti_spoof != 0)
508 return QL_STATUS_INVALID_PARAM;
509 if (esw_cfg[i].mac_override != 1)
510 return QL_STATUS_INVALID_PARAM;
511 if (esw_cfg[i].promisc_mode != 1)
512 return QL_STATUS_INVALID_PARAM;
513 }
514 break;
515 case QLCNIC_ADD_VLAN:
516 if (!IS_VALID_VLAN(esw_cfg[i].vlan_id))
517 return QL_STATUS_INVALID_PARAM;
518 if (!esw_cfg[i].op_type)
519 return QL_STATUS_INVALID_PARAM;
520 break;
521 case QLCNIC_DEL_VLAN:
522 if (!esw_cfg[i].op_type)
523 return QL_STATUS_INVALID_PARAM;
524 break;
525 default:
526 return QL_STATUS_INVALID_PARAM;
527 }
528 }
Sony Chacko319ecf12013-01-01 03:20:22 +0000529
Sony Chackoec079a02012-11-28 04:34:28 +0000530 return 0;
531}
532
Sony Chackob66e29c2012-11-28 04:34:29 +0000533static ssize_t qlcnic_sysfs_write_esw_config(struct file *file,
534 struct kobject *kobj,
535 struct bin_attribute *attr,
536 char *buf, loff_t offset,
537 size_t size)
Sony Chackoec079a02012-11-28 04:34:28 +0000538{
539 struct device *dev = container_of(kobj, struct device, kobj);
540 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
541 struct qlcnic_esw_func_cfg *esw_cfg;
542 struct qlcnic_npar_info *npar;
543 int count, rem, i, ret;
Sony Chacko319ecf12013-01-01 03:20:22 +0000544 int index;
545 u8 op_mode = 0, pci_func;
Sony Chackoec079a02012-11-28 04:34:28 +0000546
547 count = size / sizeof(struct qlcnic_esw_func_cfg);
548 rem = size % sizeof(struct qlcnic_esw_func_cfg);
549 if (rem)
550 return QL_STATUS_INVALID_PARAM;
551
Sony Chackob66e29c2012-11-28 04:34:29 +0000552 esw_cfg = (struct qlcnic_esw_func_cfg *)buf;
Sony Chackoec079a02012-11-28 04:34:28 +0000553 ret = validate_esw_config(adapter, esw_cfg, count);
554 if (ret)
555 return ret;
556
557 for (i = 0; i < count; i++) {
Sony Chacko319ecf12013-01-01 03:20:22 +0000558 if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC)
Sony Chackoec079a02012-11-28 04:34:28 +0000559 if (qlcnic_config_switch_port(adapter, &esw_cfg[i]))
560 return QL_STATUS_INVALID_PARAM;
561
562 if (adapter->ahw->pci_func != esw_cfg[i].pci_func)
563 continue;
564
565 op_mode = esw_cfg[i].op_mode;
566 qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i]);
567 esw_cfg[i].op_mode = op_mode;
568 esw_cfg[i].pci_func = adapter->ahw->pci_func;
569
570 switch (esw_cfg[i].op_mode) {
571 case QLCNIC_PORT_DEFAULTS:
572 qlcnic_set_eswitch_port_features(adapter, &esw_cfg[i]);
Shahed Shaikh147a9082013-05-21 09:27:01 +0000573 rtnl_lock();
574 qlcnic_set_netdev_features(adapter, &esw_cfg[i]);
575 rtnl_unlock();
Sony Chackoec079a02012-11-28 04:34:28 +0000576 break;
577 case QLCNIC_ADD_VLAN:
578 qlcnic_set_vlan_config(adapter, &esw_cfg[i]);
579 break;
580 case QLCNIC_DEL_VLAN:
581 esw_cfg[i].vlan_id = 0;
582 qlcnic_set_vlan_config(adapter, &esw_cfg[i]);
583 break;
584 }
585 }
586
Sony Chacko79788452012-12-04 03:33:53 +0000587 if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
Sony Chackoec079a02012-11-28 04:34:28 +0000588 goto out;
589
590 for (i = 0; i < count; i++) {
591 pci_func = esw_cfg[i].pci_func;
Sony Chacko319ecf12013-01-01 03:20:22 +0000592 index = qlcnic_is_valid_nic_func(adapter, pci_func);
Jitendra Kalsaria2f514c52013-12-17 09:01:54 -0500593 if (index < 0)
594 return QL_STATUS_INVALID_PARAM;
Sony Chacko319ecf12013-01-01 03:20:22 +0000595 npar = &adapter->npars[index];
Sony Chackoec079a02012-11-28 04:34:28 +0000596 switch (esw_cfg[i].op_mode) {
597 case QLCNIC_PORT_DEFAULTS:
598 npar->promisc_mode = esw_cfg[i].promisc_mode;
599 npar->mac_override = esw_cfg[i].mac_override;
600 npar->offload_flags = esw_cfg[i].offload_flags;
601 npar->mac_anti_spoof = esw_cfg[i].mac_anti_spoof;
602 npar->discard_tagged = esw_cfg[i].discard_tagged;
603 break;
604 case QLCNIC_ADD_VLAN:
605 npar->pvid = esw_cfg[i].vlan_id;
606 break;
607 case QLCNIC_DEL_VLAN:
608 npar->pvid = 0;
609 break;
610 }
611 }
612out:
613 return size;
614}
615
Sony Chackob66e29c2012-11-28 04:34:29 +0000616static ssize_t qlcnic_sysfs_read_esw_config(struct file *file,
617 struct kobject *kobj,
618 struct bin_attribute *attr,
619 char *buf, loff_t offset,
620 size_t size)
Sony Chackoec079a02012-11-28 04:34:28 +0000621{
622 struct device *dev = container_of(kobj, struct device, kobj);
623 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
Jitendra Kalsaria2f514c52013-12-17 09:01:54 -0500624 struct qlcnic_esw_func_cfg *esw_cfg;
Jitendra Kalsariad91abf92014-02-21 13:20:11 -0500625 u8 pci_func;
626 u32 count;
627 int i;
Sony Chackoec079a02012-11-28 04:34:28 +0000628
Jitendra Kalsariad91abf92014-02-21 13:20:11 -0500629 memset(buf, 0, size);
Jitendra Kalsaria2f514c52013-12-17 09:01:54 -0500630 esw_cfg = (struct qlcnic_esw_func_cfg *)buf;
Jitendra Kalsariad91abf92014-02-21 13:20:11 -0500631 count = size / sizeof(struct qlcnic_esw_func_cfg);
632 for (i = 0; i < adapter->ahw->total_nic_func; i++) {
Sony Chacko319ecf12013-01-01 03:20:22 +0000633 pci_func = adapter->npars[i].pci_func;
Jitendra Kalsariad91abf92014-02-21 13:20:11 -0500634 if (pci_func >= count) {
635 dev_dbg(dev, "%s: Total nic functions[%d], App sent function count[%d]\n",
636 __func__, adapter->ahw->total_nic_func, count);
Sony Chacko35dafcb2013-08-30 13:51:23 -0400637 continue;
Jitendra Kalsariad91abf92014-02-21 13:20:11 -0500638 }
Sony Chacko35dafcb2013-08-30 13:51:23 -0400639 if (!adapter->npars[i].eswitch_status)
640 continue;
641
Sony Chacko319ecf12013-01-01 03:20:22 +0000642 esw_cfg[pci_func].pci_func = pci_func;
643 if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg[pci_func]))
Sony Chackoec079a02012-11-28 04:34:28 +0000644 return QL_STATUS_INVALID_PARAM;
645 }
Sony Chackoec079a02012-11-28 04:34:28 +0000646 return size;
647}
648
Sony Chackob66e29c2012-11-28 04:34:29 +0000649static int validate_npar_config(struct qlcnic_adapter *adapter,
650 struct qlcnic_npar_func_cfg *np_cfg,
651 int count)
Sony Chackoec079a02012-11-28 04:34:28 +0000652{
653 u8 pci_func, i;
654
655 for (i = 0; i < count; i++) {
656 pci_func = np_cfg[i].pci_func;
Sony Chacko319ecf12013-01-01 03:20:22 +0000657 if (qlcnic_is_valid_nic_func(adapter, pci_func) < 0)
Sony Chackoec079a02012-11-28 04:34:28 +0000658 return QL_STATUS_INVALID_PARAM;
659
660 if (!IS_VALID_BW(np_cfg[i].min_bw) ||
661 !IS_VALID_BW(np_cfg[i].max_bw))
662 return QL_STATUS_INVALID_PARAM;
663 }
664 return 0;
665}
666
Sony Chackob66e29c2012-11-28 04:34:29 +0000667static ssize_t qlcnic_sysfs_write_npar_config(struct file *file,
668 struct kobject *kobj,
669 struct bin_attribute *attr,
670 char *buf, loff_t offset,
671 size_t size)
Sony Chackoec079a02012-11-28 04:34:28 +0000672{
673 struct device *dev = container_of(kobj, struct device, kobj);
674 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
675 struct qlcnic_info nic_info;
676 struct qlcnic_npar_func_cfg *np_cfg;
Sony Chacko319ecf12013-01-01 03:20:22 +0000677 int i, count, rem, ret, index;
Sony Chackoec079a02012-11-28 04:34:28 +0000678 u8 pci_func;
679
680 count = size / sizeof(struct qlcnic_npar_func_cfg);
681 rem = size % sizeof(struct qlcnic_npar_func_cfg);
682 if (rem)
683 return QL_STATUS_INVALID_PARAM;
684
Sony Chackob66e29c2012-11-28 04:34:29 +0000685 np_cfg = (struct qlcnic_npar_func_cfg *)buf;
Sony Chackoec079a02012-11-28 04:34:28 +0000686 ret = validate_npar_config(adapter, np_cfg, count);
687 if (ret)
688 return ret;
689
Sony Chacko319ecf12013-01-01 03:20:22 +0000690 for (i = 0; i < count; i++) {
Sony Chackoec079a02012-11-28 04:34:28 +0000691 pci_func = np_cfg[i].pci_func;
Sony Chacko319ecf12013-01-01 03:20:22 +0000692
693 memset(&nic_info, 0, sizeof(struct qlcnic_info));
Sony Chackoec079a02012-11-28 04:34:28 +0000694 ret = qlcnic_get_nic_info(adapter, &nic_info, pci_func);
695 if (ret)
696 return ret;
697 nic_info.pci_func = pci_func;
698 nic_info.min_tx_bw = np_cfg[i].min_bw;
699 nic_info.max_tx_bw = np_cfg[i].max_bw;
700 ret = qlcnic_set_nic_info(adapter, &nic_info);
701 if (ret)
702 return ret;
Sony Chacko319ecf12013-01-01 03:20:22 +0000703 index = qlcnic_is_valid_nic_func(adapter, pci_func);
Jitendra Kalsaria2f514c52013-12-17 09:01:54 -0500704 if (index < 0)
705 return QL_STATUS_INVALID_PARAM;
Sony Chacko319ecf12013-01-01 03:20:22 +0000706 adapter->npars[index].min_bw = nic_info.min_tx_bw;
707 adapter->npars[index].max_bw = nic_info.max_tx_bw;
Sony Chackoec079a02012-11-28 04:34:28 +0000708 }
709
710 return size;
Sony Chackoec079a02012-11-28 04:34:28 +0000711}
Sony Chackob66e29c2012-11-28 04:34:29 +0000712
713static ssize_t qlcnic_sysfs_read_npar_config(struct file *file,
714 struct kobject *kobj,
715 struct bin_attribute *attr,
716 char *buf, loff_t offset,
717 size_t size)
Sony Chackoec079a02012-11-28 04:34:28 +0000718{
719 struct device *dev = container_of(kobj, struct device, kobj);
720 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
Jitendra Kalsaria2f514c52013-12-17 09:01:54 -0500721 struct qlcnic_npar_func_cfg *np_cfg;
Sony Chackoec079a02012-11-28 04:34:28 +0000722 struct qlcnic_info nic_info;
Sony Chackoec079a02012-11-28 04:34:28 +0000723 int i, ret;
Jitendra Kalsariad91abf92014-02-21 13:20:11 -0500724 u32 count;
Sony Chackoec079a02012-11-28 04:34:28 +0000725
Sony Chacko319ecf12013-01-01 03:20:22 +0000726 memset(&nic_info, 0, sizeof(struct qlcnic_info));
Jitendra Kalsariad91abf92014-02-21 13:20:11 -0500727 memset(buf, 0, size);
Jitendra Kalsaria2f514c52013-12-17 09:01:54 -0500728 np_cfg = (struct qlcnic_npar_func_cfg *)buf;
Sony Chacko319ecf12013-01-01 03:20:22 +0000729
Jitendra Kalsariad91abf92014-02-21 13:20:11 -0500730 count = size / sizeof(struct qlcnic_npar_func_cfg);
731 for (i = 0; i < adapter->ahw->total_nic_func; i++) {
Sony Chacko319ecf12013-01-01 03:20:22 +0000732 if (qlcnic_is_valid_nic_func(adapter, i) < 0)
Sony Chackoec079a02012-11-28 04:34:28 +0000733 continue;
Jitendra Kalsariad91abf92014-02-21 13:20:11 -0500734 if (adapter->npars[i].pci_func >= count) {
735 dev_dbg(dev, "%s: Total nic functions[%d], App sent function count[%d]\n",
736 __func__, adapter->ahw->total_nic_func, count);
737 continue;
738 }
Sony Chackoec079a02012-11-28 04:34:28 +0000739 ret = qlcnic_get_nic_info(adapter, &nic_info, i);
740 if (ret)
741 return ret;
Sony Chacko35dafcb2013-08-30 13:51:23 -0400742 if (!adapter->npars[i].eswitch_status)
743 continue;
Sony Chackoec079a02012-11-28 04:34:28 +0000744 np_cfg[i].pci_func = i;
745 np_cfg[i].op_mode = (u8)nic_info.op_mode;
746 np_cfg[i].port_num = nic_info.phys_port;
747 np_cfg[i].fw_capab = nic_info.capabilities;
Sony Chackob66e29c2012-11-28 04:34:29 +0000748 np_cfg[i].min_bw = nic_info.min_tx_bw;
Sony Chackoec079a02012-11-28 04:34:28 +0000749 np_cfg[i].max_bw = nic_info.max_tx_bw;
750 np_cfg[i].max_tx_queues = nic_info.max_tx_ques;
751 np_cfg[i].max_rx_queues = nic_info.max_rx_ques;
752 }
Sony Chackoec079a02012-11-28 04:34:28 +0000753 return size;
754}
755
Sony Chackob66e29c2012-11-28 04:34:29 +0000756static ssize_t qlcnic_sysfs_get_port_stats(struct file *file,
757 struct kobject *kobj,
758 struct bin_attribute *attr,
759 char *buf, loff_t offset,
760 size_t size)
Sony Chackoec079a02012-11-28 04:34:28 +0000761{
762 struct device *dev = container_of(kobj, struct device, kobj);
763 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
764 struct qlcnic_esw_statistics port_stats;
765 int ret;
766
Sony Chacko319ecf12013-01-01 03:20:22 +0000767 if (qlcnic_83xx_check(adapter))
768 return QLC_STATUS_UNSUPPORTED_CMD;
769
Sony Chackoec079a02012-11-28 04:34:28 +0000770 if (size != sizeof(struct qlcnic_esw_statistics))
771 return QL_STATUS_INVALID_PARAM;
772
Jitendra Kalsariad91abf92014-02-21 13:20:11 -0500773 if (offset >= adapter->ahw->max_vnic_func)
Sony Chackoec079a02012-11-28 04:34:28 +0000774 return QL_STATUS_INVALID_PARAM;
775
776 memset(&port_stats, 0, size);
777 ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER,
Sony Chackob66e29c2012-11-28 04:34:29 +0000778 &port_stats.rx);
Sony Chackoec079a02012-11-28 04:34:28 +0000779 if (ret)
780 return ret;
781
782 ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER,
Sony Chackob66e29c2012-11-28 04:34:29 +0000783 &port_stats.tx);
Sony Chackoec079a02012-11-28 04:34:28 +0000784 if (ret)
785 return ret;
786
787 memcpy(buf, &port_stats, size);
788 return size;
789}
790
Sony Chackob66e29c2012-11-28 04:34:29 +0000791static ssize_t qlcnic_sysfs_get_esw_stats(struct file *file,
792 struct kobject *kobj,
793 struct bin_attribute *attr,
794 char *buf, loff_t offset,
795 size_t size)
Sony Chackoec079a02012-11-28 04:34:28 +0000796{
797 struct device *dev = container_of(kobj, struct device, kobj);
798 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
799 struct qlcnic_esw_statistics esw_stats;
800 int ret;
801
Sony Chacko319ecf12013-01-01 03:20:22 +0000802 if (qlcnic_83xx_check(adapter))
803 return QLC_STATUS_UNSUPPORTED_CMD;
804
Sony Chackoec079a02012-11-28 04:34:28 +0000805 if (size != sizeof(struct qlcnic_esw_statistics))
806 return QL_STATUS_INVALID_PARAM;
807
808 if (offset >= QLCNIC_NIU_MAX_XG_PORTS)
809 return QL_STATUS_INVALID_PARAM;
810
811 memset(&esw_stats, 0, size);
812 ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER,
Sony Chackob66e29c2012-11-28 04:34:29 +0000813 &esw_stats.rx);
Sony Chackoec079a02012-11-28 04:34:28 +0000814 if (ret)
815 return ret;
816
817 ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER,
Sony Chackob66e29c2012-11-28 04:34:29 +0000818 &esw_stats.tx);
Sony Chackoec079a02012-11-28 04:34:28 +0000819 if (ret)
820 return ret;
821
822 memcpy(buf, &esw_stats, size);
823 return size;
824}
825
Sony Chackob66e29c2012-11-28 04:34:29 +0000826static ssize_t qlcnic_sysfs_clear_esw_stats(struct file *file,
827 struct kobject *kobj,
828 struct bin_attribute *attr,
829 char *buf, loff_t offset,
830 size_t size)
Sony Chackoec079a02012-11-28 04:34:28 +0000831{
832 struct device *dev = container_of(kobj, struct device, kobj);
833 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
834 int ret;
835
Sony Chacko319ecf12013-01-01 03:20:22 +0000836 if (qlcnic_83xx_check(adapter))
837 return QLC_STATUS_UNSUPPORTED_CMD;
838
Sony Chackoec079a02012-11-28 04:34:28 +0000839 if (offset >= QLCNIC_NIU_MAX_XG_PORTS)
840 return QL_STATUS_INVALID_PARAM;
841
842 ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset,
Sony Chackob66e29c2012-11-28 04:34:29 +0000843 QLCNIC_QUERY_RX_COUNTER);
Sony Chackoec079a02012-11-28 04:34:28 +0000844 if (ret)
845 return ret;
846
847 ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset,
Sony Chackob66e29c2012-11-28 04:34:29 +0000848 QLCNIC_QUERY_TX_COUNTER);
Sony Chackoec079a02012-11-28 04:34:28 +0000849 if (ret)
850 return ret;
851
852 return size;
853}
854
Sony Chackob66e29c2012-11-28 04:34:29 +0000855static ssize_t qlcnic_sysfs_clear_port_stats(struct file *file,
856 struct kobject *kobj,
857 struct bin_attribute *attr,
858 char *buf, loff_t offset,
859 size_t size)
Sony Chackoec079a02012-11-28 04:34:28 +0000860{
Sony Chacko319ecf12013-01-01 03:20:22 +0000861
Sony Chackoec079a02012-11-28 04:34:28 +0000862 struct device *dev = container_of(kobj, struct device, kobj);
863 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
864 int ret;
865
Sony Chacko319ecf12013-01-01 03:20:22 +0000866 if (qlcnic_83xx_check(adapter))
867 return QLC_STATUS_UNSUPPORTED_CMD;
868
Jitendra Kalsariad91abf92014-02-21 13:20:11 -0500869 if (offset >= adapter->ahw->max_vnic_func)
Sony Chackoec079a02012-11-28 04:34:28 +0000870 return QL_STATUS_INVALID_PARAM;
871
872 ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset,
Sony Chackob66e29c2012-11-28 04:34:29 +0000873 QLCNIC_QUERY_RX_COUNTER);
Sony Chackoec079a02012-11-28 04:34:28 +0000874 if (ret)
875 return ret;
876
877 ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset,
Sony Chackob66e29c2012-11-28 04:34:29 +0000878 QLCNIC_QUERY_TX_COUNTER);
Sony Chackoec079a02012-11-28 04:34:28 +0000879 if (ret)
880 return ret;
881
882 return size;
883}
884
Sony Chackob66e29c2012-11-28 04:34:29 +0000885static ssize_t qlcnic_sysfs_read_pci_config(struct file *file,
886 struct kobject *kobj,
887 struct bin_attribute *attr,
888 char *buf, loff_t offset,
889 size_t size)
Sony Chackoec079a02012-11-28 04:34:28 +0000890{
891 struct device *dev = container_of(kobj, struct device, kobj);
892 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
Jitendra Kalsaria2f514c52013-12-17 09:01:54 -0500893 struct qlcnic_pci_func_cfg *pci_cfg;
Sony Chackoec079a02012-11-28 04:34:28 +0000894 struct qlcnic_pci_info *pci_info;
895 int i, ret;
Jitendra Kalsariad91abf92014-02-21 13:20:11 -0500896 u32 count;
Sony Chackoec079a02012-11-28 04:34:28 +0000897
Jitendra Kalsariad91abf92014-02-21 13:20:11 -0500898 pci_info = kcalloc(size, sizeof(*pci_info), GFP_KERNEL);
Sony Chackoec079a02012-11-28 04:34:28 +0000899 if (!pci_info)
900 return -ENOMEM;
901
902 ret = qlcnic_get_pci_info(adapter, pci_info);
903 if (ret) {
Joe Perchesf3c07732014-01-08 22:42:25 -0800904 kfree(pci_info);
Sony Chackoec079a02012-11-28 04:34:28 +0000905 return ret;
906 }
907
Joe Perchesf3c07732014-01-08 22:42:25 -0800908 pci_cfg = (struct qlcnic_pci_func_cfg *)buf;
Jitendra Kalsariad91abf92014-02-21 13:20:11 -0500909 count = size / sizeof(struct qlcnic_pci_func_cfg);
910 for (i = 0; i < count; i++) {
Sony Chackoec079a02012-11-28 04:34:28 +0000911 pci_cfg[i].pci_func = pci_info[i].id;
912 pci_cfg[i].func_type = pci_info[i].type;
Joe Perchesf3c07732014-01-08 22:42:25 -0800913 pci_cfg[i].func_state = 0;
Sony Chackoec079a02012-11-28 04:34:28 +0000914 pci_cfg[i].port_num = pci_info[i].default_port;
915 pci_cfg[i].min_bw = pci_info[i].tx_min_bw;
916 pci_cfg[i].max_bw = pci_info[i].tx_max_bw;
917 memcpy(&pci_cfg[i].def_mac_addr, &pci_info[i].mac, ETH_ALEN);
918 }
Sony Chacko319ecf12013-01-01 03:20:22 +0000919
Joe Perchesf3c07732014-01-08 22:42:25 -0800920 kfree(pci_info);
Sony Chackoec079a02012-11-28 04:34:28 +0000921 return size;
922}
923
Himanshu Madhania5200302013-03-12 09:02:16 +0000924static ssize_t qlcnic_83xx_sysfs_flash_read_handler(struct file *filp,
925 struct kobject *kobj,
926 struct bin_attribute *attr,
927 char *buf, loff_t offset,
928 size_t size)
929{
930 unsigned char *p_read_buf;
931 int ret, count;
932 struct device *dev = container_of(kobj, struct device, kobj);
933 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
934
935 if (!size)
936 return QL_STATUS_INVALID_PARAM;
937 if (!buf)
938 return QL_STATUS_INVALID_PARAM;
939
940 count = size / sizeof(u32);
941
942 if (size % sizeof(u32))
943 count++;
944
945 p_read_buf = kcalloc(size, sizeof(unsigned char), GFP_KERNEL);
946 if (!p_read_buf)
947 return -ENOMEM;
948 if (qlcnic_83xx_lock_flash(adapter) != 0) {
949 kfree(p_read_buf);
950 return -EIO;
951 }
952
953 ret = qlcnic_83xx_lockless_flash_read32(adapter, offset, p_read_buf,
954 count);
955
956 if (ret) {
957 qlcnic_83xx_unlock_flash(adapter);
958 kfree(p_read_buf);
959 return ret;
960 }
961
962 qlcnic_83xx_unlock_flash(adapter);
963 memcpy(buf, p_read_buf, size);
964 kfree(p_read_buf);
965
966 return size;
967}
968
969static int qlcnic_83xx_sysfs_flash_bulk_write(struct qlcnic_adapter *adapter,
970 char *buf, loff_t offset,
971 size_t size)
972{
973 int i, ret, count;
974 unsigned char *p_cache, *p_src;
975
976 p_cache = kcalloc(size, sizeof(unsigned char), GFP_KERNEL);
977 if (!p_cache)
978 return -ENOMEM;
979
980 memcpy(p_cache, buf, size);
981 p_src = p_cache;
982 count = size / sizeof(u32);
983
984 if (qlcnic_83xx_lock_flash(adapter) != 0) {
985 kfree(p_cache);
986 return -EIO;
987 }
988
989 if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) {
990 ret = qlcnic_83xx_enable_flash_write(adapter);
991 if (ret) {
992 kfree(p_cache);
993 qlcnic_83xx_unlock_flash(adapter);
994 return -EIO;
995 }
996 }
997
998 for (i = 0; i < count / QLC_83XX_FLASH_WRITE_MAX; i++) {
999 ret = qlcnic_83xx_flash_bulk_write(adapter, offset,
1000 (u32 *)p_src,
1001 QLC_83XX_FLASH_WRITE_MAX);
1002
1003 if (ret) {
1004 if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) {
1005 ret = qlcnic_83xx_disable_flash_write(adapter);
1006 if (ret) {
1007 kfree(p_cache);
1008 qlcnic_83xx_unlock_flash(adapter);
1009 return -EIO;
1010 }
1011 }
1012
1013 kfree(p_cache);
1014 qlcnic_83xx_unlock_flash(adapter);
1015 return -EIO;
1016 }
1017
1018 p_src = p_src + sizeof(u32)*QLC_83XX_FLASH_WRITE_MAX;
1019 offset = offset + sizeof(u32)*QLC_83XX_FLASH_WRITE_MAX;
1020 }
1021
1022 if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) {
1023 ret = qlcnic_83xx_disable_flash_write(adapter);
1024 if (ret) {
1025 kfree(p_cache);
1026 qlcnic_83xx_unlock_flash(adapter);
1027 return -EIO;
1028 }
1029 }
1030
1031 kfree(p_cache);
1032 qlcnic_83xx_unlock_flash(adapter);
1033
1034 return 0;
1035}
1036
1037static int qlcnic_83xx_sysfs_flash_write(struct qlcnic_adapter *adapter,
1038 char *buf, loff_t offset, size_t size)
1039{
1040 int i, ret, count;
1041 unsigned char *p_cache, *p_src;
1042
1043 p_cache = kcalloc(size, sizeof(unsigned char), GFP_KERNEL);
1044 if (!p_cache)
1045 return -ENOMEM;
1046
1047 memcpy(p_cache, buf, size);
1048 p_src = p_cache;
1049 count = size / sizeof(u32);
1050
1051 if (qlcnic_83xx_lock_flash(adapter) != 0) {
1052 kfree(p_cache);
1053 return -EIO;
1054 }
1055
1056 if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) {
1057 ret = qlcnic_83xx_enable_flash_write(adapter);
1058 if (ret) {
1059 kfree(p_cache);
1060 qlcnic_83xx_unlock_flash(adapter);
1061 return -EIO;
1062 }
1063 }
1064
1065 for (i = 0; i < count; i++) {
1066 ret = qlcnic_83xx_flash_write32(adapter, offset, (u32 *)p_src);
1067 if (ret) {
1068 if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) {
1069 ret = qlcnic_83xx_disable_flash_write(adapter);
1070 if (ret) {
1071 kfree(p_cache);
1072 qlcnic_83xx_unlock_flash(adapter);
1073 return -EIO;
1074 }
1075 }
1076 kfree(p_cache);
1077 qlcnic_83xx_unlock_flash(adapter);
1078 return -EIO;
1079 }
1080
1081 p_src = p_src + sizeof(u32);
1082 offset = offset + sizeof(u32);
1083 }
1084
1085 if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) {
1086 ret = qlcnic_83xx_disable_flash_write(adapter);
1087 if (ret) {
1088 kfree(p_cache);
1089 qlcnic_83xx_unlock_flash(adapter);
1090 return -EIO;
1091 }
1092 }
1093
1094 kfree(p_cache);
1095 qlcnic_83xx_unlock_flash(adapter);
1096
1097 return 0;
1098}
1099
1100static ssize_t qlcnic_83xx_sysfs_flash_write_handler(struct file *filp,
1101 struct kobject *kobj,
1102 struct bin_attribute *attr,
1103 char *buf, loff_t offset,
1104 size_t size)
1105{
1106 int ret;
1107 static int flash_mode;
1108 unsigned long data;
1109 struct device *dev = container_of(kobj, struct device, kobj);
1110 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
1111
1112 if (!buf)
1113 return QL_STATUS_INVALID_PARAM;
1114
1115 ret = kstrtoul(buf, 16, &data);
1116
1117 switch (data) {
1118 case QLC_83XX_FLASH_SECTOR_ERASE_CMD:
1119 flash_mode = QLC_83XX_ERASE_MODE;
1120 ret = qlcnic_83xx_erase_flash_sector(adapter, offset);
1121 if (ret) {
1122 dev_err(&adapter->pdev->dev,
1123 "%s failed at %d\n", __func__, __LINE__);
1124 return -EIO;
1125 }
1126 break;
1127
1128 case QLC_83XX_FLASH_BULK_WRITE_CMD:
1129 flash_mode = QLC_83XX_BULK_WRITE_MODE;
1130 break;
1131
1132 case QLC_83XX_FLASH_WRITE_CMD:
1133 flash_mode = QLC_83XX_WRITE_MODE;
1134 break;
1135 default:
1136 if (flash_mode == QLC_83XX_BULK_WRITE_MODE) {
1137 ret = qlcnic_83xx_sysfs_flash_bulk_write(adapter, buf,
1138 offset, size);
1139 if (ret) {
1140 dev_err(&adapter->pdev->dev,
1141 "%s failed at %d\n",
1142 __func__, __LINE__);
1143 return -EIO;
1144 }
1145 }
1146
1147 if (flash_mode == QLC_83XX_WRITE_MODE) {
1148 ret = qlcnic_83xx_sysfs_flash_write(adapter, buf,
1149 offset, size);
1150 if (ret) {
1151 dev_err(&adapter->pdev->dev,
1152 "%s failed at %d\n", __func__,
1153 __LINE__);
1154 return -EIO;
1155 }
1156 }
1157 }
1158
1159 return size;
1160}
1161
Sony Chackoec079a02012-11-28 04:34:28 +00001162static struct device_attribute dev_attr_bridged_mode = {
1163 .attr = {.name = "bridged_mode", .mode = (S_IRUGO | S_IWUSR)},
1164 .show = qlcnic_show_bridged_mode,
1165 .store = qlcnic_store_bridged_mode,
1166};
1167
1168static struct device_attribute dev_attr_diag_mode = {
1169 .attr = {.name = "diag_mode", .mode = (S_IRUGO | S_IWUSR)},
1170 .show = qlcnic_show_diag_mode,
1171 .store = qlcnic_store_diag_mode,
1172};
1173
1174static struct device_attribute dev_attr_beacon = {
1175 .attr = {.name = "beacon", .mode = (S_IRUGO | S_IWUSR)},
1176 .show = qlcnic_show_beacon,
1177 .store = qlcnic_store_beacon,
1178};
1179
1180static struct bin_attribute bin_attr_crb = {
1181 .attr = {.name = "crb", .mode = (S_IRUGO | S_IWUSR)},
1182 .size = 0,
1183 .read = qlcnic_sysfs_read_crb,
1184 .write = qlcnic_sysfs_write_crb,
1185};
1186
1187static struct bin_attribute bin_attr_mem = {
1188 .attr = {.name = "mem", .mode = (S_IRUGO | S_IWUSR)},
1189 .size = 0,
1190 .read = qlcnic_sysfs_read_mem,
1191 .write = qlcnic_sysfs_write_mem,
1192};
1193
1194static struct bin_attribute bin_attr_npar_config = {
1195 .attr = {.name = "npar_config", .mode = (S_IRUGO | S_IWUSR)},
1196 .size = 0,
1197 .read = qlcnic_sysfs_read_npar_config,
1198 .write = qlcnic_sysfs_write_npar_config,
1199};
1200
1201static struct bin_attribute bin_attr_pci_config = {
1202 .attr = {.name = "pci_config", .mode = (S_IRUGO | S_IWUSR)},
1203 .size = 0,
1204 .read = qlcnic_sysfs_read_pci_config,
1205 .write = NULL,
1206};
1207
1208static struct bin_attribute bin_attr_port_stats = {
1209 .attr = {.name = "port_stats", .mode = (S_IRUGO | S_IWUSR)},
1210 .size = 0,
1211 .read = qlcnic_sysfs_get_port_stats,
1212 .write = qlcnic_sysfs_clear_port_stats,
1213};
1214
1215static struct bin_attribute bin_attr_esw_stats = {
1216 .attr = {.name = "esw_stats", .mode = (S_IRUGO | S_IWUSR)},
1217 .size = 0,
1218 .read = qlcnic_sysfs_get_esw_stats,
1219 .write = qlcnic_sysfs_clear_esw_stats,
1220};
1221
1222static struct bin_attribute bin_attr_esw_config = {
1223 .attr = {.name = "esw_config", .mode = (S_IRUGO | S_IWUSR)},
1224 .size = 0,
1225 .read = qlcnic_sysfs_read_esw_config,
1226 .write = qlcnic_sysfs_write_esw_config,
1227};
1228
1229static struct bin_attribute bin_attr_pm_config = {
1230 .attr = {.name = "pm_config", .mode = (S_IRUGO | S_IWUSR)},
1231 .size = 0,
1232 .read = qlcnic_sysfs_read_pm_config,
1233 .write = qlcnic_sysfs_write_pm_config,
1234};
1235
Himanshu Madhania5200302013-03-12 09:02:16 +00001236static struct bin_attribute bin_attr_flash = {
1237 .attr = {.name = "flash", .mode = (S_IRUGO | S_IWUSR)},
1238 .size = 0,
1239 .read = qlcnic_83xx_sysfs_flash_read_handler,
1240 .write = qlcnic_83xx_sysfs_flash_write_handler,
1241};
1242
Sony Chackoec079a02012-11-28 04:34:28 +00001243void qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter)
1244{
1245 struct device *dev = &adapter->pdev->dev;
1246
Sony Chacko79788452012-12-04 03:33:53 +00001247 if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_BDG)
Sony Chackoec079a02012-11-28 04:34:28 +00001248 if (device_create_file(dev, &dev_attr_bridged_mode))
1249 dev_warn(dev,
Sony Chackob66e29c2012-11-28 04:34:29 +00001250 "failed to create bridged_mode sysfs entry\n");
Sony Chackoec079a02012-11-28 04:34:28 +00001251}
1252
1253void qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter)
1254{
1255 struct device *dev = &adapter->pdev->dev;
1256
Sony Chacko79788452012-12-04 03:33:53 +00001257 if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_BDG)
Sony Chackoec079a02012-11-28 04:34:28 +00001258 device_remove_file(dev, &dev_attr_bridged_mode);
1259}
1260
stephen hemminger21041402014-01-16 10:31:27 -08001261static void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter)
Sony Chackoec079a02012-11-28 04:34:28 +00001262{
1263 struct device *dev = &adapter->pdev->dev;
Sony Chackoec079a02012-11-28 04:34:28 +00001264
1265 if (device_create_bin_file(dev, &bin_attr_port_stats))
1266 dev_info(dev, "failed to create port stats sysfs entry");
1267
Sony Chacko79788452012-12-04 03:33:53 +00001268 if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC)
Sony Chackoec079a02012-11-28 04:34:28 +00001269 return;
1270 if (device_create_file(dev, &dev_attr_diag_mode))
1271 dev_info(dev, "failed to create diag_mode sysfs entry\n");
1272 if (device_create_bin_file(dev, &bin_attr_crb))
1273 dev_info(dev, "failed to create crb sysfs entry\n");
1274 if (device_create_bin_file(dev, &bin_attr_mem))
1275 dev_info(dev, "failed to create mem sysfs entry\n");
1276
Sucheta Chakraborty78ea2d92013-11-04 13:31:29 -05001277 if (test_bit(__QLCNIC_MAINTENANCE_MODE, &adapter->state))
Sucheta Chakraborty66451612013-09-27 02:12:36 -04001278 return;
1279
Sony Chackoec079a02012-11-28 04:34:28 +00001280 if (device_create_bin_file(dev, &bin_attr_pci_config))
1281 dev_info(dev, "failed to create pci config sysfs entry");
Sucheta Chakraborty66451612013-09-27 02:12:36 -04001282
Sony Chackoec079a02012-11-28 04:34:28 +00001283 if (device_create_file(dev, &dev_attr_beacon))
1284 dev_info(dev, "failed to create beacon sysfs entry");
1285
1286 if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
1287 return;
1288 if (device_create_bin_file(dev, &bin_attr_esw_config))
1289 dev_info(dev, "failed to create esw config sysfs entry");
Sony Chacko79788452012-12-04 03:33:53 +00001290 if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
Sony Chackoec079a02012-11-28 04:34:28 +00001291 return;
1292 if (device_create_bin_file(dev, &bin_attr_npar_config))
1293 dev_info(dev, "failed to create npar config sysfs entry");
1294 if (device_create_bin_file(dev, &bin_attr_pm_config))
1295 dev_info(dev, "failed to create pm config sysfs entry");
1296 if (device_create_bin_file(dev, &bin_attr_esw_stats))
1297 dev_info(dev, "failed to create eswitch stats sysfs entry");
1298}
1299
stephen hemminger21041402014-01-16 10:31:27 -08001300static void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter)
Sony Chackoec079a02012-11-28 04:34:28 +00001301{
1302 struct device *dev = &adapter->pdev->dev;
Sony Chackoec079a02012-11-28 04:34:28 +00001303
1304 device_remove_bin_file(dev, &bin_attr_port_stats);
1305
Sony Chacko79788452012-12-04 03:33:53 +00001306 if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC)
Sony Chackoec079a02012-11-28 04:34:28 +00001307 return;
1308 device_remove_file(dev, &dev_attr_diag_mode);
1309 device_remove_bin_file(dev, &bin_attr_crb);
1310 device_remove_bin_file(dev, &bin_attr_mem);
Sucheta Chakraborty66451612013-09-27 02:12:36 -04001311
Sucheta Chakraborty78ea2d92013-11-04 13:31:29 -05001312 if (test_bit(__QLCNIC_MAINTENANCE_MODE, &adapter->state))
Sucheta Chakraborty66451612013-09-27 02:12:36 -04001313 return;
1314
Sony Chackoec079a02012-11-28 04:34:28 +00001315 device_remove_bin_file(dev, &bin_attr_pci_config);
1316 device_remove_file(dev, &dev_attr_beacon);
1317 if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
1318 return;
1319 device_remove_bin_file(dev, &bin_attr_esw_config);
Sony Chacko79788452012-12-04 03:33:53 +00001320 if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
Sony Chackoec079a02012-11-28 04:34:28 +00001321 return;
1322 device_remove_bin_file(dev, &bin_attr_npar_config);
1323 device_remove_bin_file(dev, &bin_attr_pm_config);
1324 device_remove_bin_file(dev, &bin_attr_esw_stats);
1325}
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001326
1327void qlcnic_82xx_add_sysfs(struct qlcnic_adapter *adapter)
1328{
1329 qlcnic_create_diag_entries(adapter);
1330}
1331
1332void qlcnic_82xx_remove_sysfs(struct qlcnic_adapter *adapter)
1333{
1334 qlcnic_remove_diag_entries(adapter);
1335}
Sony Chacko319ecf12013-01-01 03:20:22 +00001336
1337void qlcnic_83xx_add_sysfs(struct qlcnic_adapter *adapter)
1338{
Himanshu Madhania5200302013-03-12 09:02:16 +00001339 struct device *dev = &adapter->pdev->dev;
1340
Sony Chacko319ecf12013-01-01 03:20:22 +00001341 qlcnic_create_diag_entries(adapter);
Himanshu Madhania5200302013-03-12 09:02:16 +00001342
1343 if (sysfs_create_bin_file(&dev->kobj, &bin_attr_flash))
1344 dev_info(dev, "failed to create flash sysfs entry\n");
Sony Chacko319ecf12013-01-01 03:20:22 +00001345}
1346
1347void qlcnic_83xx_remove_sysfs(struct qlcnic_adapter *adapter)
1348{
Himanshu Madhania5200302013-03-12 09:02:16 +00001349 struct device *dev = &adapter->pdev->dev;
1350
Sony Chacko319ecf12013-01-01 03:20:22 +00001351 qlcnic_remove_diag_entries(adapter);
Himanshu Madhania5200302013-03-12 09:02:16 +00001352 sysfs_remove_bin_file(&dev->kobj, &bin_attr_flash);
Sony Chacko319ecf12013-01-01 03:20:22 +00001353}