bnx2x: Add VF device ids and enable feature
[linux-2.6-block.git] / drivers / net / ethernet / qlogic / qlcnic / qlcnic_sysfs.c
CommitLineData
ec079a07
SC
1#include <linux/slab.h>
2#include <linux/vmalloc.h>
3#include <linux/interrupt.h>
4
5#include "qlcnic.h"
6
7#include <linux/swab.h>
8#include <linux/dma-mapping.h>
9#include <net/ip.h>
10#include <linux/ipv6.h>
11#include <linux/inetdevice.h>
12#include <linux/sysfs.h>
13#include <linux/aer.h>
14#include <linux/log2.h>
15
ec079a07
SC
16int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable)
17{
18 return -EOPNOTSUPP;
19}
20
21int qlcnicvf_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate)
22{
23 return -EOPNOTSUPP;
24}
25
b66e29c9
SC
26static ssize_t qlcnic_store_bridged_mode(struct device *dev,
27 struct device_attribute *attr,
28 const char *buf, size_t len)
ec079a07
SC
29{
30 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
31 unsigned long new;
32 int ret = -EINVAL;
33
79788450 34 if (!(adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_BDG))
ec079a07
SC
35 goto err_out;
36
37 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
38 goto err_out;
39
40 if (strict_strtoul(buf, 2, &new))
41 goto err_out;
42
43 if (!adapter->nic_ops->config_bridged_mode(adapter, !!new))
44 ret = len;
45
46err_out:
47 return ret;
48}
49
b66e29c9
SC
50static ssize_t qlcnic_show_bridged_mode(struct device *dev,
51 struct device_attribute *attr,
52 char *buf)
ec079a07
SC
53{
54 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
55 int bridged_mode = 0;
56
79788450 57 if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_BDG)
ec079a07
SC
58 bridged_mode = !!(adapter->flags & QLCNIC_BRIDGE_ENABLED);
59
60 return sprintf(buf, "%d\n", bridged_mode);
61}
62
b66e29c9
SC
63static ssize_t qlcnic_store_diag_mode(struct device *dev,
64 struct device_attribute *attr,
65 const char *buf, size_t len)
ec079a07
SC
66{
67 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
68 unsigned long new;
69
70 if (strict_strtoul(buf, 2, &new))
71 return -EINVAL;
72
73 if (!!new != !!(adapter->flags & QLCNIC_DIAG_ENABLED))
74 adapter->flags ^= QLCNIC_DIAG_ENABLED;
75
76 return len;
77}
78
b66e29c9
SC
79static ssize_t qlcnic_show_diag_mode(struct device *dev,
80 struct device_attribute *attr, char *buf)
ec079a07
SC
81{
82 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
83
84 return sprintf(buf, "%d\n",
b66e29c9 85 !!(adapter->flags & QLCNIC_DIAG_ENABLED));
ec079a07
SC
86}
87
b66e29c9
SC
88static int qlcnic_validate_beacon(struct qlcnic_adapter *adapter, u16 beacon,
89 u8 *state, u8 *rate)
ec079a07
SC
90{
91 *rate = LSB(beacon);
92 *state = MSB(beacon);
93
94 QLCDB(adapter, DRV, "rate %x state %x\n", *rate, *state);
95
96 if (!*state) {
97 *rate = __QLCNIC_MAX_LED_RATE;
98 return 0;
b66e29c9 99 } else if (*state > __QLCNIC_MAX_LED_STATE) {
ec079a07 100 return -EINVAL;
b66e29c9 101 }
ec079a07
SC
102
103 if ((!*rate) || (*rate > __QLCNIC_MAX_LED_RATE))
104 return -EINVAL;
105
106 return 0;
107}
108
b66e29c9
SC
109static ssize_t qlcnic_store_beacon(struct device *dev,
110 struct device_attribute *attr,
111 const char *buf, size_t len)
ec079a07
SC
112{
113 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
114 int max_sds_rings = adapter->max_sds_rings;
115 u16 beacon;
116 u8 b_state, b_rate;
117 int err;
118
79788450 119 if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
b66e29c9
SC
120 dev_warn(dev,
121 "LED test not supported in non privileged mode\n");
ec079a07
SC
122 return -EOPNOTSUPP;
123 }
124
125 if (len != sizeof(u16))
126 return QL_STATUS_INVALID_PARAM;
127
128 memcpy(&beacon, buf, sizeof(u16));
129 err = qlcnic_validate_beacon(adapter, beacon, &b_state, &b_rate);
130 if (err)
131 return err;
132
133 if (adapter->ahw->beacon_state == b_state)
134 return len;
135
136 rtnl_lock();
137
138 if (!adapter->ahw->beacon_state)
139 if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state)) {
140 rtnl_unlock();
141 return -EBUSY;
142 }
143
144 if (test_bit(__QLCNIC_RESETTING, &adapter->state)) {
145 err = -EIO;
146 goto out;
147 }
148
149 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
150 err = qlcnic_diag_alloc_res(adapter->netdev, QLCNIC_LED_TEST);
151 if (err)
152 goto out;
153 set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state);
154 }
155
156 err = qlcnic_config_led(adapter, b_state, b_rate);
157
158 if (!err) {
159 err = len;
160 adapter->ahw->beacon_state = b_state;
161 }
162
163 if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state))
164 qlcnic_diag_free_res(adapter->netdev, max_sds_rings);
165
166 out:
167 if (!adapter->ahw->beacon_state)
168 clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
169 rtnl_unlock();
170
171 return err;
172}
173
b66e29c9
SC
174static ssize_t qlcnic_show_beacon(struct device *dev,
175 struct device_attribute *attr, char *buf)
ec079a07
SC
176{
177 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
178
179 return sprintf(buf, "%d\n", adapter->ahw->beacon_state);
180}
181
b66e29c9
SC
182static int qlcnic_sysfs_validate_crb(struct qlcnic_adapter *adapter,
183 loff_t offset, size_t size)
ec079a07
SC
184{
185 size_t crb_size = 4;
186
187 if (!(adapter->flags & QLCNIC_DIAG_ENABLED))
188 return -EIO;
189
190 if (offset < QLCNIC_PCI_CRBSPACE) {
191 if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM,
b66e29c9 192 QLCNIC_PCI_CAMQM_END))
ec079a07
SC
193 crb_size = 8;
194 else
195 return -EINVAL;
196 }
197
198 if ((size != crb_size) || (offset & (crb_size-1)))
199 return -EINVAL;
200
201 return 0;
202}
203
b66e29c9
SC
204static ssize_t qlcnic_sysfs_read_crb(struct file *filp, struct kobject *kobj,
205 struct bin_attribute *attr, char *buf,
206 loff_t offset, size_t size)
ec079a07
SC
207{
208 struct device *dev = container_of(kobj, struct device, kobj);
209 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
210 u32 data;
211 u64 qmdata;
212 int ret;
213
214 ret = qlcnic_sysfs_validate_crb(adapter, offset, size);
215 if (ret != 0)
216 return ret;
217
218 if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) {
219 qlcnic_pci_camqm_read_2M(adapter, offset, &qmdata);
220 memcpy(buf, &qmdata, size);
221 } else {
222 data = QLCRD32(adapter, offset);
223 memcpy(buf, &data, size);
224 }
225 return size;
226}
227
b66e29c9
SC
228static ssize_t qlcnic_sysfs_write_crb(struct file *filp, struct kobject *kobj,
229 struct bin_attribute *attr, char *buf,
230 loff_t offset, size_t size)
ec079a07
SC
231{
232 struct device *dev = container_of(kobj, struct device, kobj);
233 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
234 u32 data;
235 u64 qmdata;
236 int ret;
237
238 ret = qlcnic_sysfs_validate_crb(adapter, offset, size);
239 if (ret != 0)
240 return ret;
241
242 if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) {
243 memcpy(&qmdata, buf, size);
244 qlcnic_pci_camqm_write_2M(adapter, offset, qmdata);
245 } else {
246 memcpy(&data, buf, size);
247 QLCWR32(adapter, offset, data);
248 }
249 return size;
250}
251
b66e29c9
SC
252static int qlcnic_sysfs_validate_mem(struct qlcnic_adapter *adapter,
253 loff_t offset, size_t size)
ec079a07
SC
254{
255 if (!(adapter->flags & QLCNIC_DIAG_ENABLED))
256 return -EIO;
257
258 if ((size != 8) || (offset & 0x7))
259 return -EIO;
260
261 return 0;
262}
263
b66e29c9
SC
264static ssize_t qlcnic_sysfs_read_mem(struct file *filp, struct kobject *kobj,
265 struct bin_attribute *attr, char *buf,
266 loff_t offset, size_t size)
ec079a07
SC
267{
268 struct device *dev = container_of(kobj, struct device, kobj);
269 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
270 u64 data;
271 int ret;
272
273 ret = qlcnic_sysfs_validate_mem(adapter, offset, size);
274 if (ret != 0)
275 return ret;
276
277 if (qlcnic_pci_mem_read_2M(adapter, offset, &data))
278 return -EIO;
279
280 memcpy(buf, &data, size);
281
282 return size;
283}
284
b66e29c9
SC
285static ssize_t qlcnic_sysfs_write_mem(struct file *filp, struct kobject *kobj,
286 struct bin_attribute *attr, char *buf,
287 loff_t offset, size_t size)
ec079a07
SC
288{
289 struct device *dev = container_of(kobj, struct device, kobj);
290 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
291 u64 data;
292 int ret;
293
294 ret = qlcnic_sysfs_validate_mem(adapter, offset, size);
295 if (ret != 0)
296 return ret;
297
298 memcpy(&data, buf, size);
299
300 if (qlcnic_pci_mem_write_2M(adapter, offset, data))
301 return -EIO;
302
303 return size;
304}
305
b66e29c9
SC
306static int validate_pm_config(struct qlcnic_adapter *adapter,
307 struct qlcnic_pm_func_cfg *pm_cfg, int count)
ec079a07 308{
b66e29c9 309 u8 src_pci_func, s_esw_id, d_esw_id, dest_pci_func;
ec079a07
SC
310 int i;
311
312 for (i = 0; i < count; i++) {
313 src_pci_func = pm_cfg[i].pci_func;
314 dest_pci_func = pm_cfg[i].dest_npar;
b66e29c9
SC
315 if (src_pci_func >= QLCNIC_MAX_PCI_FUNC ||
316 dest_pci_func >= QLCNIC_MAX_PCI_FUNC)
ec079a07
SC
317 return QL_STATUS_INVALID_PARAM;
318
319 if (adapter->npars[src_pci_func].type != QLCNIC_TYPE_NIC)
320 return QL_STATUS_INVALID_PARAM;
321
322 if (adapter->npars[dest_pci_func].type != QLCNIC_TYPE_NIC)
323 return QL_STATUS_INVALID_PARAM;
324
325 s_esw_id = adapter->npars[src_pci_func].phy_port;
326 d_esw_id = adapter->npars[dest_pci_func].phy_port;
327
328 if (s_esw_id != d_esw_id)
329 return QL_STATUS_INVALID_PARAM;
ec079a07
SC
330 }
331 return 0;
332
333}
334
b66e29c9
SC
335static ssize_t qlcnic_sysfs_write_pm_config(struct file *filp,
336 struct kobject *kobj,
337 struct bin_attribute *attr,
338 char *buf, loff_t offset,
339 size_t size)
ec079a07
SC
340{
341 struct device *dev = container_of(kobj, struct device, kobj);
342 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
343 struct qlcnic_pm_func_cfg *pm_cfg;
344 u32 id, action, pci_func;
345 int count, rem, i, ret;
346
347 count = size / sizeof(struct qlcnic_pm_func_cfg);
348 rem = size % sizeof(struct qlcnic_pm_func_cfg);
349 if (rem)
350 return QL_STATUS_INVALID_PARAM;
351
b66e29c9 352 pm_cfg = (struct qlcnic_pm_func_cfg *)buf;
ec079a07
SC
353
354 ret = validate_pm_config(adapter, pm_cfg, count);
355 if (ret)
356 return ret;
357 for (i = 0; i < count; i++) {
358 pci_func = pm_cfg[i].pci_func;
359 action = !!pm_cfg[i].action;
360 id = adapter->npars[pci_func].phy_port;
b66e29c9
SC
361 ret = qlcnic_config_port_mirroring(adapter, id, action,
362 pci_func);
ec079a07
SC
363 if (ret)
364 return ret;
365 }
366
367 for (i = 0; i < count; i++) {
368 pci_func = pm_cfg[i].pci_func;
369 id = adapter->npars[pci_func].phy_port;
370 adapter->npars[pci_func].enable_pm = !!pm_cfg[i].action;
371 adapter->npars[pci_func].dest_npar = id;
372 }
373 return size;
374}
375
b66e29c9
SC
376static ssize_t qlcnic_sysfs_read_pm_config(struct file *filp,
377 struct kobject *kobj,
378 struct bin_attribute *attr,
379 char *buf, loff_t offset,
380 size_t size)
ec079a07
SC
381{
382 struct device *dev = container_of(kobj, struct device, kobj);
383 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
384 struct qlcnic_pm_func_cfg pm_cfg[QLCNIC_MAX_PCI_FUNC];
385 int i;
386
387 if (size != sizeof(pm_cfg))
388 return QL_STATUS_INVALID_PARAM;
389
390 for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
391 if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
392 continue;
393 pm_cfg[i].action = adapter->npars[i].enable_pm;
394 pm_cfg[i].dest_npar = 0;
395 pm_cfg[i].pci_func = i;
396 }
397 memcpy(buf, &pm_cfg, size);
398
399 return size;
400}
401
b66e29c9
SC
402static int validate_esw_config(struct qlcnic_adapter *adapter,
403 struct qlcnic_esw_func_cfg *esw_cfg, int count)
ec079a07
SC
404{
405 u32 op_mode;
406 u8 pci_func;
407 int i;
408
409 op_mode = readl(adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE);
410
411 for (i = 0; i < count; i++) {
412 pci_func = esw_cfg[i].pci_func;
413 if (pci_func >= QLCNIC_MAX_PCI_FUNC)
414 return QL_STATUS_INVALID_PARAM;
415
79788450 416 if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC) {
ec079a07
SC
417 if (adapter->npars[pci_func].type != QLCNIC_TYPE_NIC)
418 return QL_STATUS_INVALID_PARAM;
b66e29c9 419 }
ec079a07
SC
420
421 switch (esw_cfg[i].op_mode) {
422 case QLCNIC_PORT_DEFAULTS:
423 if (QLC_DEV_GET_DRV(op_mode, pci_func) !=
b66e29c9 424 QLCNIC_NON_PRIV_FUNC) {
ec079a07
SC
425 if (esw_cfg[i].mac_anti_spoof != 0)
426 return QL_STATUS_INVALID_PARAM;
427 if (esw_cfg[i].mac_override != 1)
428 return QL_STATUS_INVALID_PARAM;
429 if (esw_cfg[i].promisc_mode != 1)
430 return QL_STATUS_INVALID_PARAM;
431 }
432 break;
433 case QLCNIC_ADD_VLAN:
434 if (!IS_VALID_VLAN(esw_cfg[i].vlan_id))
435 return QL_STATUS_INVALID_PARAM;
436 if (!esw_cfg[i].op_type)
437 return QL_STATUS_INVALID_PARAM;
438 break;
439 case QLCNIC_DEL_VLAN:
440 if (!esw_cfg[i].op_type)
441 return QL_STATUS_INVALID_PARAM;
442 break;
443 default:
444 return QL_STATUS_INVALID_PARAM;
445 }
446 }
447 return 0;
448}
449
b66e29c9
SC
450static ssize_t qlcnic_sysfs_write_esw_config(struct file *file,
451 struct kobject *kobj,
452 struct bin_attribute *attr,
453 char *buf, loff_t offset,
454 size_t size)
ec079a07
SC
455{
456 struct device *dev = container_of(kobj, struct device, kobj);
457 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
458 struct qlcnic_esw_func_cfg *esw_cfg;
459 struct qlcnic_npar_info *npar;
460 int count, rem, i, ret;
461 u8 pci_func, op_mode = 0;
462
463 count = size / sizeof(struct qlcnic_esw_func_cfg);
464 rem = size % sizeof(struct qlcnic_esw_func_cfg);
465 if (rem)
466 return QL_STATUS_INVALID_PARAM;
467
b66e29c9 468 esw_cfg = (struct qlcnic_esw_func_cfg *)buf;
ec079a07
SC
469 ret = validate_esw_config(adapter, esw_cfg, count);
470 if (ret)
471 return ret;
472
473 for (i = 0; i < count; i++) {
79788450 474 if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC) {
ec079a07
SC
475 if (qlcnic_config_switch_port(adapter, &esw_cfg[i]))
476 return QL_STATUS_INVALID_PARAM;
b66e29c9 477 }
ec079a07
SC
478
479 if (adapter->ahw->pci_func != esw_cfg[i].pci_func)
480 continue;
481
482 op_mode = esw_cfg[i].op_mode;
483 qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i]);
484 esw_cfg[i].op_mode = op_mode;
485 esw_cfg[i].pci_func = adapter->ahw->pci_func;
486
487 switch (esw_cfg[i].op_mode) {
488 case QLCNIC_PORT_DEFAULTS:
489 qlcnic_set_eswitch_port_features(adapter, &esw_cfg[i]);
490 break;
491 case QLCNIC_ADD_VLAN:
492 qlcnic_set_vlan_config(adapter, &esw_cfg[i]);
493 break;
494 case QLCNIC_DEL_VLAN:
495 esw_cfg[i].vlan_id = 0;
496 qlcnic_set_vlan_config(adapter, &esw_cfg[i]);
497 break;
498 }
499 }
500
79788450 501 if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
ec079a07
SC
502 goto out;
503
504 for (i = 0; i < count; i++) {
505 pci_func = esw_cfg[i].pci_func;
506 npar = &adapter->npars[pci_func];
507 switch (esw_cfg[i].op_mode) {
508 case QLCNIC_PORT_DEFAULTS:
509 npar->promisc_mode = esw_cfg[i].promisc_mode;
510 npar->mac_override = esw_cfg[i].mac_override;
511 npar->offload_flags = esw_cfg[i].offload_flags;
512 npar->mac_anti_spoof = esw_cfg[i].mac_anti_spoof;
513 npar->discard_tagged = esw_cfg[i].discard_tagged;
514 break;
515 case QLCNIC_ADD_VLAN:
516 npar->pvid = esw_cfg[i].vlan_id;
517 break;
518 case QLCNIC_DEL_VLAN:
519 npar->pvid = 0;
520 break;
521 }
522 }
523out:
524 return size;
525}
526
b66e29c9
SC
527static ssize_t qlcnic_sysfs_read_esw_config(struct file *file,
528 struct kobject *kobj,
529 struct bin_attribute *attr,
530 char *buf, loff_t offset,
531 size_t size)
ec079a07
SC
532{
533 struct device *dev = container_of(kobj, struct device, kobj);
534 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
535 struct qlcnic_esw_func_cfg esw_cfg[QLCNIC_MAX_PCI_FUNC];
536 u8 i;
537
538 if (size != sizeof(esw_cfg))
539 return QL_STATUS_INVALID_PARAM;
540
541 for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
542 if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
543 continue;
544 esw_cfg[i].pci_func = i;
545 if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i]))
546 return QL_STATUS_INVALID_PARAM;
547 }
548 memcpy(buf, &esw_cfg, size);
549
550 return size;
551}
552
b66e29c9
SC
553static int validate_npar_config(struct qlcnic_adapter *adapter,
554 struct qlcnic_npar_func_cfg *np_cfg,
555 int count)
ec079a07
SC
556{
557 u8 pci_func, i;
558
559 for (i = 0; i < count; i++) {
560 pci_func = np_cfg[i].pci_func;
561 if (pci_func >= QLCNIC_MAX_PCI_FUNC)
562 return QL_STATUS_INVALID_PARAM;
563
564 if (adapter->npars[pci_func].type != QLCNIC_TYPE_NIC)
565 return QL_STATUS_INVALID_PARAM;
566
567 if (!IS_VALID_BW(np_cfg[i].min_bw) ||
568 !IS_VALID_BW(np_cfg[i].max_bw))
569 return QL_STATUS_INVALID_PARAM;
570 }
571 return 0;
572}
573
b66e29c9
SC
574static ssize_t qlcnic_sysfs_write_npar_config(struct file *file,
575 struct kobject *kobj,
576 struct bin_attribute *attr,
577 char *buf, loff_t offset,
578 size_t size)
ec079a07
SC
579{
580 struct device *dev = container_of(kobj, struct device, kobj);
581 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
582 struct qlcnic_info nic_info;
583 struct qlcnic_npar_func_cfg *np_cfg;
584 int i, count, rem, ret;
585 u8 pci_func;
586
587 count = size / sizeof(struct qlcnic_npar_func_cfg);
588 rem = size % sizeof(struct qlcnic_npar_func_cfg);
589 if (rem)
590 return QL_STATUS_INVALID_PARAM;
591
b66e29c9 592 np_cfg = (struct qlcnic_npar_func_cfg *)buf;
ec079a07
SC
593 ret = validate_npar_config(adapter, np_cfg, count);
594 if (ret)
595 return ret;
596
597 for (i = 0; i < count ; i++) {
598 pci_func = np_cfg[i].pci_func;
599 ret = qlcnic_get_nic_info(adapter, &nic_info, pci_func);
600 if (ret)
601 return ret;
602 nic_info.pci_func = pci_func;
603 nic_info.min_tx_bw = np_cfg[i].min_bw;
604 nic_info.max_tx_bw = np_cfg[i].max_bw;
605 ret = qlcnic_set_nic_info(adapter, &nic_info);
606 if (ret)
607 return ret;
608 adapter->npars[i].min_bw = nic_info.min_tx_bw;
609 adapter->npars[i].max_bw = nic_info.max_tx_bw;
610 }
611
612 return size;
613
614}
b66e29c9
SC
615
616static ssize_t qlcnic_sysfs_read_npar_config(struct file *file,
617 struct kobject *kobj,
618 struct bin_attribute *attr,
619 char *buf, loff_t offset,
620 size_t size)
ec079a07
SC
621{
622 struct device *dev = container_of(kobj, struct device, kobj);
623 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
624 struct qlcnic_info nic_info;
625 struct qlcnic_npar_func_cfg np_cfg[QLCNIC_MAX_PCI_FUNC];
626 int i, ret;
627
628 if (size != sizeof(np_cfg))
629 return QL_STATUS_INVALID_PARAM;
630
b66e29c9 631 for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
ec079a07
SC
632 if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
633 continue;
634 ret = qlcnic_get_nic_info(adapter, &nic_info, i);
635 if (ret)
636 return ret;
637
638 np_cfg[i].pci_func = i;
639 np_cfg[i].op_mode = (u8)nic_info.op_mode;
640 np_cfg[i].port_num = nic_info.phys_port;
641 np_cfg[i].fw_capab = nic_info.capabilities;
b66e29c9 642 np_cfg[i].min_bw = nic_info.min_tx_bw;
ec079a07
SC
643 np_cfg[i].max_bw = nic_info.max_tx_bw;
644 np_cfg[i].max_tx_queues = nic_info.max_tx_ques;
645 np_cfg[i].max_rx_queues = nic_info.max_rx_ques;
646 }
647 memcpy(buf, &np_cfg, size);
648 return size;
649}
650
b66e29c9
SC
651static ssize_t qlcnic_sysfs_get_port_stats(struct file *file,
652 struct kobject *kobj,
653 struct bin_attribute *attr,
654 char *buf, loff_t offset,
655 size_t size)
ec079a07
SC
656{
657 struct device *dev = container_of(kobj, struct device, kobj);
658 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
659 struct qlcnic_esw_statistics port_stats;
660 int ret;
661
662 if (size != sizeof(struct qlcnic_esw_statistics))
663 return QL_STATUS_INVALID_PARAM;
664
665 if (offset >= QLCNIC_MAX_PCI_FUNC)
666 return QL_STATUS_INVALID_PARAM;
667
668 memset(&port_stats, 0, size);
669 ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER,
b66e29c9 670 &port_stats.rx);
ec079a07
SC
671 if (ret)
672 return ret;
673
674 ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER,
b66e29c9 675 &port_stats.tx);
ec079a07
SC
676 if (ret)
677 return ret;
678
679 memcpy(buf, &port_stats, size);
680 return size;
681}
682
b66e29c9
SC
683static ssize_t qlcnic_sysfs_get_esw_stats(struct file *file,
684 struct kobject *kobj,
685 struct bin_attribute *attr,
686 char *buf, loff_t offset,
687 size_t size)
ec079a07
SC
688{
689 struct device *dev = container_of(kobj, struct device, kobj);
690 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
691 struct qlcnic_esw_statistics esw_stats;
692 int ret;
693
694 if (size != sizeof(struct qlcnic_esw_statistics))
695 return QL_STATUS_INVALID_PARAM;
696
697 if (offset >= QLCNIC_NIU_MAX_XG_PORTS)
698 return QL_STATUS_INVALID_PARAM;
699
700 memset(&esw_stats, 0, size);
701 ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER,
b66e29c9 702 &esw_stats.rx);
ec079a07
SC
703 if (ret)
704 return ret;
705
706 ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER,
b66e29c9 707 &esw_stats.tx);
ec079a07
SC
708 if (ret)
709 return ret;
710
711 memcpy(buf, &esw_stats, size);
712 return size;
713}
714
b66e29c9
SC
715static ssize_t qlcnic_sysfs_clear_esw_stats(struct file *file,
716 struct kobject *kobj,
717 struct bin_attribute *attr,
718 char *buf, loff_t offset,
719 size_t size)
ec079a07
SC
720{
721 struct device *dev = container_of(kobj, struct device, kobj);
722 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
723 int ret;
724
725 if (offset >= QLCNIC_NIU_MAX_XG_PORTS)
726 return QL_STATUS_INVALID_PARAM;
727
728 ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset,
b66e29c9 729 QLCNIC_QUERY_RX_COUNTER);
ec079a07
SC
730 if (ret)
731 return ret;
732
733 ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset,
b66e29c9 734 QLCNIC_QUERY_TX_COUNTER);
ec079a07
SC
735 if (ret)
736 return ret;
737
738 return size;
739}
740
b66e29c9
SC
741static ssize_t qlcnic_sysfs_clear_port_stats(struct file *file,
742 struct kobject *kobj,
743 struct bin_attribute *attr,
744 char *buf, loff_t offset,
745 size_t size)
ec079a07 746{
ec079a07
SC
747 struct device *dev = container_of(kobj, struct device, kobj);
748 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
749 int ret;
750
751 if (offset >= QLCNIC_MAX_PCI_FUNC)
752 return QL_STATUS_INVALID_PARAM;
753
754 ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset,
b66e29c9 755 QLCNIC_QUERY_RX_COUNTER);
ec079a07
SC
756 if (ret)
757 return ret;
758
759 ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset,
b66e29c9 760 QLCNIC_QUERY_TX_COUNTER);
ec079a07
SC
761 if (ret)
762 return ret;
763
764 return size;
765}
766
b66e29c9
SC
767static ssize_t qlcnic_sysfs_read_pci_config(struct file *file,
768 struct kobject *kobj,
769 struct bin_attribute *attr,
770 char *buf, loff_t offset,
771 size_t size)
ec079a07
SC
772{
773 struct device *dev = container_of(kobj, struct device, kobj);
774 struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
775 struct qlcnic_pci_func_cfg pci_cfg[QLCNIC_MAX_PCI_FUNC];
776 struct qlcnic_pci_info *pci_info;
777 int i, ret;
778
779 if (size != sizeof(pci_cfg))
780 return QL_STATUS_INVALID_PARAM;
781
782 pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL);
783 if (!pci_info)
784 return -ENOMEM;
785
786 ret = qlcnic_get_pci_info(adapter, pci_info);
787 if (ret) {
788 kfree(pci_info);
789 return ret;
790 }
791
792 for (i = 0; i < QLCNIC_MAX_PCI_FUNC ; i++) {
793 pci_cfg[i].pci_func = pci_info[i].id;
794 pci_cfg[i].func_type = pci_info[i].type;
795 pci_cfg[i].port_num = pci_info[i].default_port;
796 pci_cfg[i].min_bw = pci_info[i].tx_min_bw;
797 pci_cfg[i].max_bw = pci_info[i].tx_max_bw;
798 memcpy(&pci_cfg[i].def_mac_addr, &pci_info[i].mac, ETH_ALEN);
799 }
800 memcpy(buf, &pci_cfg, size);
801 kfree(pci_info);
802 return size;
803}
804
805static struct device_attribute dev_attr_bridged_mode = {
806 .attr = {.name = "bridged_mode", .mode = (S_IRUGO | S_IWUSR)},
807 .show = qlcnic_show_bridged_mode,
808 .store = qlcnic_store_bridged_mode,
809};
810
811static struct device_attribute dev_attr_diag_mode = {
812 .attr = {.name = "diag_mode", .mode = (S_IRUGO | S_IWUSR)},
813 .show = qlcnic_show_diag_mode,
814 .store = qlcnic_store_diag_mode,
815};
816
817static struct device_attribute dev_attr_beacon = {
818 .attr = {.name = "beacon", .mode = (S_IRUGO | S_IWUSR)},
819 .show = qlcnic_show_beacon,
820 .store = qlcnic_store_beacon,
821};
822
823static struct bin_attribute bin_attr_crb = {
824 .attr = {.name = "crb", .mode = (S_IRUGO | S_IWUSR)},
825 .size = 0,
826 .read = qlcnic_sysfs_read_crb,
827 .write = qlcnic_sysfs_write_crb,
828};
829
830static struct bin_attribute bin_attr_mem = {
831 .attr = {.name = "mem", .mode = (S_IRUGO | S_IWUSR)},
832 .size = 0,
833 .read = qlcnic_sysfs_read_mem,
834 .write = qlcnic_sysfs_write_mem,
835};
836
837static struct bin_attribute bin_attr_npar_config = {
838 .attr = {.name = "npar_config", .mode = (S_IRUGO | S_IWUSR)},
839 .size = 0,
840 .read = qlcnic_sysfs_read_npar_config,
841 .write = qlcnic_sysfs_write_npar_config,
842};
843
844static struct bin_attribute bin_attr_pci_config = {
845 .attr = {.name = "pci_config", .mode = (S_IRUGO | S_IWUSR)},
846 .size = 0,
847 .read = qlcnic_sysfs_read_pci_config,
848 .write = NULL,
849};
850
851static struct bin_attribute bin_attr_port_stats = {
852 .attr = {.name = "port_stats", .mode = (S_IRUGO | S_IWUSR)},
853 .size = 0,
854 .read = qlcnic_sysfs_get_port_stats,
855 .write = qlcnic_sysfs_clear_port_stats,
856};
857
858static struct bin_attribute bin_attr_esw_stats = {
859 .attr = {.name = "esw_stats", .mode = (S_IRUGO | S_IWUSR)},
860 .size = 0,
861 .read = qlcnic_sysfs_get_esw_stats,
862 .write = qlcnic_sysfs_clear_esw_stats,
863};
864
865static struct bin_attribute bin_attr_esw_config = {
866 .attr = {.name = "esw_config", .mode = (S_IRUGO | S_IWUSR)},
867 .size = 0,
868 .read = qlcnic_sysfs_read_esw_config,
869 .write = qlcnic_sysfs_write_esw_config,
870};
871
872static struct bin_attribute bin_attr_pm_config = {
873 .attr = {.name = "pm_config", .mode = (S_IRUGO | S_IWUSR)},
874 .size = 0,
875 .read = qlcnic_sysfs_read_pm_config,
876 .write = qlcnic_sysfs_write_pm_config,
877};
878
879void qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter)
880{
881 struct device *dev = &adapter->pdev->dev;
882
79788450 883 if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_BDG)
ec079a07
SC
884 if (device_create_file(dev, &dev_attr_bridged_mode))
885 dev_warn(dev,
b66e29c9 886 "failed to create bridged_mode sysfs entry\n");
ec079a07
SC
887}
888
889void qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter)
890{
891 struct device *dev = &adapter->pdev->dev;
892
79788450 893 if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_BDG)
ec079a07
SC
894 device_remove_file(dev, &dev_attr_bridged_mode);
895}
896
897void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter)
898{
899 struct device *dev = &adapter->pdev->dev;
900 u32 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
901
902 if (device_create_bin_file(dev, &bin_attr_port_stats))
903 dev_info(dev, "failed to create port stats sysfs entry");
904
79788450 905 if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC)
ec079a07
SC
906 return;
907 if (device_create_file(dev, &dev_attr_diag_mode))
908 dev_info(dev, "failed to create diag_mode sysfs entry\n");
909 if (device_create_bin_file(dev, &bin_attr_crb))
910 dev_info(dev, "failed to create crb sysfs entry\n");
911 if (device_create_bin_file(dev, &bin_attr_mem))
912 dev_info(dev, "failed to create mem sysfs entry\n");
913
914 if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD))
915 return;
916
917 if (device_create_bin_file(dev, &bin_attr_pci_config))
918 dev_info(dev, "failed to create pci config sysfs entry");
919 if (device_create_file(dev, &dev_attr_beacon))
920 dev_info(dev, "failed to create beacon sysfs entry");
921
922 if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
923 return;
924 if (device_create_bin_file(dev, &bin_attr_esw_config))
925 dev_info(dev, "failed to create esw config sysfs entry");
79788450 926 if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
ec079a07
SC
927 return;
928 if (device_create_bin_file(dev, &bin_attr_npar_config))
929 dev_info(dev, "failed to create npar config sysfs entry");
930 if (device_create_bin_file(dev, &bin_attr_pm_config))
931 dev_info(dev, "failed to create pm config sysfs entry");
932 if (device_create_bin_file(dev, &bin_attr_esw_stats))
933 dev_info(dev, "failed to create eswitch stats sysfs entry");
934}
935
936void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter)
937{
938 struct device *dev = &adapter->pdev->dev;
939 u32 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
940
941 device_remove_bin_file(dev, &bin_attr_port_stats);
942
79788450 943 if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC)
ec079a07
SC
944 return;
945 device_remove_file(dev, &dev_attr_diag_mode);
946 device_remove_bin_file(dev, &bin_attr_crb);
947 device_remove_bin_file(dev, &bin_attr_mem);
948 if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD))
949 return;
950 device_remove_bin_file(dev, &bin_attr_pci_config);
951 device_remove_file(dev, &dev_attr_beacon);
952 if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
953 return;
954 device_remove_bin_file(dev, &bin_attr_esw_config);
79788450 955 if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
ec079a07
SC
956 return;
957 device_remove_bin_file(dev, &bin_attr_npar_config);
958 device_remove_bin_file(dev, &bin_attr_pm_config);
959 device_remove_bin_file(dev, &bin_attr_esw_stats);
960}