diff options
author | Sony Chacko <sony.chacko@qlogic.com> | 2012-11-27 23:34:28 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-11-28 11:07:43 -0500 |
commit | ec079a07db570ec6ba333525cc43805163bcb043 (patch) | |
tree | 4b850bb2791521ef7b1ef66e84755f8c79f8857c /drivers/net | |
parent | d17dd0d9dfb235952c62703ffd34c5bf05257e4d (diff) |
qlcnic: create file qlcnic_sysfs.c for sysfs routines
Physical refactoring of 82xx adapter sysfs routines.
Move sysfs routines to new file qlcnic_sysfs.c
Existing sysfs routines has coding style issues, this code is
moved to the new file without fixing the style issues.
There is a seperate patch to fix the style issues in qlcnic_sysfs.c
Signed-off-by: Sony Chacko <sony.chacko@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/Makefile | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 11 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 960 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c | 951 |
4 files changed, 969 insertions, 956 deletions
diff --git a/drivers/net/ethernet/qlogic/qlcnic/Makefile b/drivers/net/ethernet/qlogic/qlcnic/Makefile index a26ee171fd7..34db05366c1 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/Makefile +++ b/drivers/net/ethernet/qlogic/qlcnic/Makefile | |||
@@ -5,4 +5,5 @@ | |||
5 | obj-$(CONFIG_QLCNIC) := qlcnic.o | 5 | obj-$(CONFIG_QLCNIC) := qlcnic.o |
6 | 6 | ||
7 | qlcnic-y := qlcnic_hw.o qlcnic_main.o qlcnic_init.o \ | 7 | qlcnic-y := qlcnic_hw.o qlcnic_main.o qlcnic_init.o \ |
8 | qlcnic_ethtool.o qlcnic_ctx.o qlcnic_io.o | 8 | qlcnic_ethtool.o qlcnic_ctx.o qlcnic_io.o \ |
9 | qlcnic_sysfs.o | ||
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index db4508fa5c9..618e5ec5506 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | |||
@@ -1566,6 +1566,17 @@ void qlcnic_free_sds_rings(struct qlcnic_recv_context *); | |||
1566 | void qlcnic_free_tx_rings(struct qlcnic_adapter *); | 1566 | void qlcnic_free_tx_rings(struct qlcnic_adapter *); |
1567 | int qlcnic_alloc_tx_rings(struct qlcnic_adapter *, struct net_device *); | 1567 | int qlcnic_alloc_tx_rings(struct qlcnic_adapter *, struct net_device *); |
1568 | 1568 | ||
1569 | void qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter); | ||
1570 | void qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter); | ||
1571 | void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter); | ||
1572 | void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter); | ||
1573 | int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *, u32); | ||
1574 | int qlcnicvf_config_led(struct qlcnic_adapter *, u32, u32); | ||
1575 | void qlcnic_set_vlan_config(struct qlcnic_adapter *, | ||
1576 | struct qlcnic_esw_func_cfg *); | ||
1577 | void qlcnic_set_eswitch_port_features(struct qlcnic_adapter *, | ||
1578 | struct qlcnic_esw_func_cfg *); | ||
1579 | |||
1569 | /* | 1580 | /* |
1570 | * QLOGIC Board information | 1581 | * QLOGIC Board information |
1571 | */ | 1582 | */ |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 1d334e99169..1eef0bf36aa 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | |||
@@ -70,11 +70,6 @@ static void qlcnic_cancel_fw_work(struct qlcnic_adapter *adapter); | |||
70 | static void qlcnic_poll_controller(struct net_device *netdev); | 70 | static void qlcnic_poll_controller(struct net_device *netdev); |
71 | #endif | 71 | #endif |
72 | 72 | ||
73 | static void qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter); | ||
74 | static void qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter); | ||
75 | static void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter); | ||
76 | static void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter); | ||
77 | |||
78 | static void qlcnic_idc_debug_info(struct qlcnic_adapter *adapter, u8 encoding); | 73 | static void qlcnic_idc_debug_info(struct qlcnic_adapter *adapter, u8 encoding); |
79 | static void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8); | 74 | static void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8); |
80 | static int qlcnic_can_start_firmware(struct qlcnic_adapter *adapter); | 75 | static int qlcnic_can_start_firmware(struct qlcnic_adapter *adapter); |
@@ -90,8 +85,6 @@ static int qlcnic_start_firmware(struct qlcnic_adapter *); | |||
90 | 85 | ||
91 | static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter); | 86 | static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter); |
92 | static void qlcnic_dev_set_npar_ready(struct qlcnic_adapter *); | 87 | static void qlcnic_dev_set_npar_ready(struct qlcnic_adapter *); |
93 | static int qlcnicvf_config_led(struct qlcnic_adapter *, u32, u32); | ||
94 | static int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *, u32); | ||
95 | static int qlcnicvf_start_firmware(struct qlcnic_adapter *); | 88 | static int qlcnicvf_start_firmware(struct qlcnic_adapter *); |
96 | static void qlcnic_set_netdev_features(struct qlcnic_adapter *, | 89 | static void qlcnic_set_netdev_features(struct qlcnic_adapter *, |
97 | struct qlcnic_esw_func_cfg *); | 90 | struct qlcnic_esw_func_cfg *); |
@@ -629,9 +622,8 @@ qlcnic_initialize_nic(struct qlcnic_adapter *adapter) | |||
629 | return err; | 622 | return err; |
630 | } | 623 | } |
631 | 624 | ||
632 | static void | 625 | void qlcnic_set_vlan_config(struct qlcnic_adapter *adapter, |
633 | qlcnic_set_vlan_config(struct qlcnic_adapter *adapter, | 626 | struct qlcnic_esw_func_cfg *esw_cfg) |
634 | struct qlcnic_esw_func_cfg *esw_cfg) | ||
635 | { | 627 | { |
636 | if (esw_cfg->discard_tagged) | 628 | if (esw_cfg->discard_tagged) |
637 | adapter->flags &= ~QLCNIC_TAGGING_ENABLED; | 629 | adapter->flags &= ~QLCNIC_TAGGING_ENABLED; |
@@ -662,9 +654,8 @@ qlcnic_vlan_rx_del(struct net_device *netdev, u16 vid) | |||
662 | return 0; | 654 | return 0; |
663 | } | 655 | } |
664 | 656 | ||
665 | static void | 657 | void qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter, |
666 | qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter, | 658 | struct qlcnic_esw_func_cfg *esw_cfg) |
667 | struct qlcnic_esw_func_cfg *esw_cfg) | ||
668 | { | 659 | { |
669 | adapter->flags &= ~(QLCNIC_MACSPOOF | QLCNIC_MAC_OVERRIDE_DISABLED | | 660 | adapter->flags &= ~(QLCNIC_MACSPOOF | QLCNIC_MAC_OVERRIDE_DISABLED | |
670 | QLCNIC_PROMISC_DISABLED); | 661 | QLCNIC_PROMISC_DISABLED); |
@@ -681,8 +672,7 @@ qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter, | |||
681 | qlcnic_set_netdev_features(adapter, esw_cfg); | 672 | qlcnic_set_netdev_features(adapter, esw_cfg); |
682 | } | 673 | } |
683 | 674 | ||
684 | static int | 675 | static int qlcnic_set_eswitch_port_config(struct qlcnic_adapter *adapter) |
685 | qlcnic_set_eswitch_port_config(struct qlcnic_adapter *adapter) | ||
686 | { | 676 | { |
687 | struct qlcnic_esw_func_cfg esw_cfg; | 677 | struct qlcnic_esw_func_cfg esw_cfg; |
688 | 678 | ||
@@ -2740,93 +2730,6 @@ qlcnicvf_start_firmware(struct qlcnic_adapter *adapter) | |||
2740 | return err; | 2730 | return err; |
2741 | } | 2731 | } |
2742 | 2732 | ||
2743 | static int | ||
2744 | qlcnicvf_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable) | ||
2745 | { | ||
2746 | return -EOPNOTSUPP; | ||
2747 | } | ||
2748 | |||
2749 | static int | ||
2750 | qlcnicvf_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate) | ||
2751 | { | ||
2752 | return -EOPNOTSUPP; | ||
2753 | } | ||
2754 | |||
2755 | static ssize_t | ||
2756 | qlcnic_store_bridged_mode(struct device *dev, | ||
2757 | struct device_attribute *attr, const char *buf, size_t len) | ||
2758 | { | ||
2759 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
2760 | unsigned long new; | ||
2761 | int ret = -EINVAL; | ||
2762 | |||
2763 | if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG)) | ||
2764 | goto err_out; | ||
2765 | |||
2766 | if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) | ||
2767 | goto err_out; | ||
2768 | |||
2769 | if (strict_strtoul(buf, 2, &new)) | ||
2770 | goto err_out; | ||
2771 | |||
2772 | if (!adapter->nic_ops->config_bridged_mode(adapter, !!new)) | ||
2773 | ret = len; | ||
2774 | |||
2775 | err_out: | ||
2776 | return ret; | ||
2777 | } | ||
2778 | |||
2779 | static ssize_t | ||
2780 | qlcnic_show_bridged_mode(struct device *dev, | ||
2781 | struct device_attribute *attr, char *buf) | ||
2782 | { | ||
2783 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
2784 | int bridged_mode = 0; | ||
2785 | |||
2786 | if (adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG) | ||
2787 | bridged_mode = !!(adapter->flags & QLCNIC_BRIDGE_ENABLED); | ||
2788 | |||
2789 | return sprintf(buf, "%d\n", bridged_mode); | ||
2790 | } | ||
2791 | |||
2792 | static struct device_attribute dev_attr_bridged_mode = { | ||
2793 | .attr = {.name = "bridged_mode", .mode = (S_IRUGO | S_IWUSR)}, | ||
2794 | .show = qlcnic_show_bridged_mode, | ||
2795 | .store = qlcnic_store_bridged_mode, | ||
2796 | }; | ||
2797 | |||
2798 | static ssize_t | ||
2799 | qlcnic_store_diag_mode(struct device *dev, | ||
2800 | struct device_attribute *attr, const char *buf, size_t len) | ||
2801 | { | ||
2802 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
2803 | unsigned long new; | ||
2804 | |||
2805 | if (strict_strtoul(buf, 2, &new)) | ||
2806 | return -EINVAL; | ||
2807 | |||
2808 | if (!!new != !!(adapter->flags & QLCNIC_DIAG_ENABLED)) | ||
2809 | adapter->flags ^= QLCNIC_DIAG_ENABLED; | ||
2810 | |||
2811 | return len; | ||
2812 | } | ||
2813 | |||
2814 | static ssize_t | ||
2815 | qlcnic_show_diag_mode(struct device *dev, | ||
2816 | struct device_attribute *attr, char *buf) | ||
2817 | { | ||
2818 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
2819 | |||
2820 | return sprintf(buf, "%d\n", | ||
2821 | !!(adapter->flags & QLCNIC_DIAG_ENABLED)); | ||
2822 | } | ||
2823 | |||
2824 | static struct device_attribute dev_attr_diag_mode = { | ||
2825 | .attr = {.name = "diag_mode", .mode = (S_IRUGO | S_IWUSR)}, | ||
2826 | .show = qlcnic_show_diag_mode, | ||
2827 | .store = qlcnic_store_diag_mode, | ||
2828 | }; | ||
2829 | |||
2830 | int qlcnic_validate_max_rss(struct net_device *netdev, u8 max_hw, u8 val) | 2733 | int qlcnic_validate_max_rss(struct net_device *netdev, u8 max_hw, u8 val) |
2831 | { | 2734 | { |
2832 | if (!use_msi_x && !use_msi) { | 2735 | if (!use_msi_x && !use_msi) { |
@@ -2877,859 +2780,6 @@ int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data) | |||
2877 | return err; | 2780 | return err; |
2878 | } | 2781 | } |
2879 | 2782 | ||
2880 | static int | ||
2881 | qlcnic_validate_beacon(struct qlcnic_adapter *adapter, u16 beacon, u8 *state, | ||
2882 | u8 *rate) | ||
2883 | { | ||
2884 | *rate = LSB(beacon); | ||
2885 | *state = MSB(beacon); | ||
2886 | |||
2887 | QLCDB(adapter, DRV, "rate %x state %x\n", *rate, *state); | ||
2888 | |||
2889 | if (!*state) { | ||
2890 | *rate = __QLCNIC_MAX_LED_RATE; | ||
2891 | return 0; | ||
2892 | } else if (*state > __QLCNIC_MAX_LED_STATE) | ||
2893 | return -EINVAL; | ||
2894 | |||
2895 | if ((!*rate) || (*rate > __QLCNIC_MAX_LED_RATE)) | ||
2896 | return -EINVAL; | ||
2897 | |||
2898 | return 0; | ||
2899 | } | ||
2900 | |||
2901 | static ssize_t | ||
2902 | qlcnic_store_beacon(struct device *dev, | ||
2903 | struct device_attribute *attr, const char *buf, size_t len) | ||
2904 | { | ||
2905 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
2906 | int max_sds_rings = adapter->max_sds_rings; | ||
2907 | u16 beacon; | ||
2908 | u8 b_state, b_rate; | ||
2909 | int err; | ||
2910 | |||
2911 | if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) { | ||
2912 | dev_warn(dev, "LED test not supported for non " | ||
2913 | "privilege function\n"); | ||
2914 | return -EOPNOTSUPP; | ||
2915 | } | ||
2916 | |||
2917 | if (len != sizeof(u16)) | ||
2918 | return QL_STATUS_INVALID_PARAM; | ||
2919 | |||
2920 | memcpy(&beacon, buf, sizeof(u16)); | ||
2921 | err = qlcnic_validate_beacon(adapter, beacon, &b_state, &b_rate); | ||
2922 | if (err) | ||
2923 | return err; | ||
2924 | |||
2925 | if (adapter->ahw->beacon_state == b_state) | ||
2926 | return len; | ||
2927 | |||
2928 | rtnl_lock(); | ||
2929 | |||
2930 | if (!adapter->ahw->beacon_state) | ||
2931 | if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state)) { | ||
2932 | rtnl_unlock(); | ||
2933 | return -EBUSY; | ||
2934 | } | ||
2935 | |||
2936 | if (test_bit(__QLCNIC_RESETTING, &adapter->state)) { | ||
2937 | err = -EIO; | ||
2938 | goto out; | ||
2939 | } | ||
2940 | |||
2941 | if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) { | ||
2942 | err = qlcnic_diag_alloc_res(adapter->netdev, QLCNIC_LED_TEST); | ||
2943 | if (err) | ||
2944 | goto out; | ||
2945 | set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state); | ||
2946 | } | ||
2947 | |||
2948 | err = qlcnic_config_led(adapter, b_state, b_rate); | ||
2949 | |||
2950 | if (!err) { | ||
2951 | err = len; | ||
2952 | adapter->ahw->beacon_state = b_state; | ||
2953 | } | ||
2954 | |||
2955 | if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state)) | ||
2956 | qlcnic_diag_free_res(adapter->netdev, max_sds_rings); | ||
2957 | |||
2958 | out: | ||
2959 | if (!adapter->ahw->beacon_state) | ||
2960 | clear_bit(__QLCNIC_LED_ENABLE, &adapter->state); | ||
2961 | rtnl_unlock(); | ||
2962 | |||
2963 | return err; | ||
2964 | } | ||
2965 | |||
2966 | static ssize_t | ||
2967 | qlcnic_show_beacon(struct device *dev, | ||
2968 | struct device_attribute *attr, char *buf) | ||
2969 | { | ||
2970 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
2971 | |||
2972 | return sprintf(buf, "%d\n", adapter->ahw->beacon_state); | ||
2973 | } | ||
2974 | |||
2975 | static struct device_attribute dev_attr_beacon = { | ||
2976 | .attr = {.name = "beacon", .mode = (S_IRUGO | S_IWUSR)}, | ||
2977 | .show = qlcnic_show_beacon, | ||
2978 | .store = qlcnic_store_beacon, | ||
2979 | }; | ||
2980 | |||
2981 | static int | ||
2982 | qlcnic_sysfs_validate_crb(struct qlcnic_adapter *adapter, | ||
2983 | loff_t offset, size_t size) | ||
2984 | { | ||
2985 | size_t crb_size = 4; | ||
2986 | |||
2987 | if (!(adapter->flags & QLCNIC_DIAG_ENABLED)) | ||
2988 | return -EIO; | ||
2989 | |||
2990 | if (offset < QLCNIC_PCI_CRBSPACE) { | ||
2991 | if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, | ||
2992 | QLCNIC_PCI_CAMQM_END)) | ||
2993 | crb_size = 8; | ||
2994 | else | ||
2995 | return -EINVAL; | ||
2996 | } | ||
2997 | |||
2998 | if ((size != crb_size) || (offset & (crb_size-1))) | ||
2999 | return -EINVAL; | ||
3000 | |||
3001 | return 0; | ||
3002 | } | ||
3003 | |||
3004 | static ssize_t | ||
3005 | qlcnic_sysfs_read_crb(struct file *filp, struct kobject *kobj, | ||
3006 | struct bin_attribute *attr, | ||
3007 | char *buf, loff_t offset, size_t size) | ||
3008 | { | ||
3009 | struct device *dev = container_of(kobj, struct device, kobj); | ||
3010 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
3011 | u32 data; | ||
3012 | u64 qmdata; | ||
3013 | int ret; | ||
3014 | |||
3015 | ret = qlcnic_sysfs_validate_crb(adapter, offset, size); | ||
3016 | if (ret != 0) | ||
3017 | return ret; | ||
3018 | |||
3019 | if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) { | ||
3020 | qlcnic_pci_camqm_read_2M(adapter, offset, &qmdata); | ||
3021 | memcpy(buf, &qmdata, size); | ||
3022 | } else { | ||
3023 | data = QLCRD32(adapter, offset); | ||
3024 | memcpy(buf, &data, size); | ||
3025 | } | ||
3026 | return size; | ||
3027 | } | ||
3028 | |||
3029 | static ssize_t | ||
3030 | qlcnic_sysfs_write_crb(struct file *filp, struct kobject *kobj, | ||
3031 | struct bin_attribute *attr, | ||
3032 | char *buf, loff_t offset, size_t size) | ||
3033 | { | ||
3034 | struct device *dev = container_of(kobj, struct device, kobj); | ||
3035 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
3036 | u32 data; | ||
3037 | u64 qmdata; | ||
3038 | int ret; | ||
3039 | |||
3040 | ret = qlcnic_sysfs_validate_crb(adapter, offset, size); | ||
3041 | if (ret != 0) | ||
3042 | return ret; | ||
3043 | |||
3044 | if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) { | ||
3045 | memcpy(&qmdata, buf, size); | ||
3046 | qlcnic_pci_camqm_write_2M(adapter, offset, qmdata); | ||
3047 | } else { | ||
3048 | memcpy(&data, buf, size); | ||
3049 | QLCWR32(adapter, offset, data); | ||
3050 | } | ||
3051 | return size; | ||
3052 | } | ||
3053 | |||
3054 | static int | ||
3055 | qlcnic_sysfs_validate_mem(struct qlcnic_adapter *adapter, | ||
3056 | loff_t offset, size_t size) | ||
3057 | { | ||
3058 | if (!(adapter->flags & QLCNIC_DIAG_ENABLED)) | ||
3059 | return -EIO; | ||
3060 | |||
3061 | if ((size != 8) || (offset & 0x7)) | ||
3062 | return -EIO; | ||
3063 | |||
3064 | return 0; | ||
3065 | } | ||
3066 | |||
3067 | static ssize_t | ||
3068 | qlcnic_sysfs_read_mem(struct file *filp, struct kobject *kobj, | ||
3069 | struct bin_attribute *attr, | ||
3070 | char *buf, loff_t offset, size_t size) | ||
3071 | { | ||
3072 | struct device *dev = container_of(kobj, struct device, kobj); | ||
3073 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
3074 | u64 data; | ||
3075 | int ret; | ||
3076 | |||
3077 | ret = qlcnic_sysfs_validate_mem(adapter, offset, size); | ||
3078 | if (ret != 0) | ||
3079 | return ret; | ||
3080 | |||
3081 | if (qlcnic_pci_mem_read_2M(adapter, offset, &data)) | ||
3082 | return -EIO; | ||
3083 | |||
3084 | memcpy(buf, &data, size); | ||
3085 | |||
3086 | return size; | ||
3087 | } | ||
3088 | |||
3089 | static ssize_t | ||
3090 | qlcnic_sysfs_write_mem(struct file *filp, struct kobject *kobj, | ||
3091 | struct bin_attribute *attr, | ||
3092 | char *buf, loff_t offset, size_t size) | ||
3093 | { | ||
3094 | struct device *dev = container_of(kobj, struct device, kobj); | ||
3095 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
3096 | u64 data; | ||
3097 | int ret; | ||
3098 | |||
3099 | ret = qlcnic_sysfs_validate_mem(adapter, offset, size); | ||
3100 | if (ret != 0) | ||
3101 | return ret; | ||
3102 | |||
3103 | memcpy(&data, buf, size); | ||
3104 | |||
3105 | if (qlcnic_pci_mem_write_2M(adapter, offset, data)) | ||
3106 | return -EIO; | ||
3107 | |||
3108 | return size; | ||
3109 | } | ||
3110 | |||
3111 | static struct bin_attribute bin_attr_crb = { | ||
3112 | .attr = {.name = "crb", .mode = (S_IRUGO | S_IWUSR)}, | ||
3113 | .size = 0, | ||
3114 | .read = qlcnic_sysfs_read_crb, | ||
3115 | .write = qlcnic_sysfs_write_crb, | ||
3116 | }; | ||
3117 | |||
3118 | static struct bin_attribute bin_attr_mem = { | ||
3119 | .attr = {.name = "mem", .mode = (S_IRUGO | S_IWUSR)}, | ||
3120 | .size = 0, | ||
3121 | .read = qlcnic_sysfs_read_mem, | ||
3122 | .write = qlcnic_sysfs_write_mem, | ||
3123 | }; | ||
3124 | |||
3125 | static int | ||
3126 | validate_pm_config(struct qlcnic_adapter *adapter, | ||
3127 | struct qlcnic_pm_func_cfg *pm_cfg, int count) | ||
3128 | { | ||
3129 | |||
3130 | u8 src_pci_func, s_esw_id, d_esw_id; | ||
3131 | u8 dest_pci_func; | ||
3132 | int i; | ||
3133 | |||
3134 | for (i = 0; i < count; i++) { | ||
3135 | src_pci_func = pm_cfg[i].pci_func; | ||
3136 | dest_pci_func = pm_cfg[i].dest_npar; | ||
3137 | if (src_pci_func >= QLCNIC_MAX_PCI_FUNC | ||
3138 | || dest_pci_func >= QLCNIC_MAX_PCI_FUNC) | ||
3139 | return QL_STATUS_INVALID_PARAM; | ||
3140 | |||
3141 | if (adapter->npars[src_pci_func].type != QLCNIC_TYPE_NIC) | ||
3142 | return QL_STATUS_INVALID_PARAM; | ||
3143 | |||
3144 | if (adapter->npars[dest_pci_func].type != QLCNIC_TYPE_NIC) | ||
3145 | return QL_STATUS_INVALID_PARAM; | ||
3146 | |||
3147 | s_esw_id = adapter->npars[src_pci_func].phy_port; | ||
3148 | d_esw_id = adapter->npars[dest_pci_func].phy_port; | ||
3149 | |||
3150 | if (s_esw_id != d_esw_id) | ||
3151 | return QL_STATUS_INVALID_PARAM; | ||
3152 | |||
3153 | } | ||
3154 | return 0; | ||
3155 | |||
3156 | } | ||
3157 | |||
3158 | static ssize_t | ||
3159 | qlcnic_sysfs_write_pm_config(struct file *filp, struct kobject *kobj, | ||
3160 | struct bin_attribute *attr, char *buf, loff_t offset, size_t size) | ||
3161 | { | ||
3162 | struct device *dev = container_of(kobj, struct device, kobj); | ||
3163 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
3164 | struct qlcnic_pm_func_cfg *pm_cfg; | ||
3165 | u32 id, action, pci_func; | ||
3166 | int count, rem, i, ret; | ||
3167 | |||
3168 | count = size / sizeof(struct qlcnic_pm_func_cfg); | ||
3169 | rem = size % sizeof(struct qlcnic_pm_func_cfg); | ||
3170 | if (rem) | ||
3171 | return QL_STATUS_INVALID_PARAM; | ||
3172 | |||
3173 | pm_cfg = (struct qlcnic_pm_func_cfg *) buf; | ||
3174 | |||
3175 | ret = validate_pm_config(adapter, pm_cfg, count); | ||
3176 | if (ret) | ||
3177 | return ret; | ||
3178 | for (i = 0; i < count; i++) { | ||
3179 | pci_func = pm_cfg[i].pci_func; | ||
3180 | action = !!pm_cfg[i].action; | ||
3181 | id = adapter->npars[pci_func].phy_port; | ||
3182 | ret = qlcnic_config_port_mirroring(adapter, id, | ||
3183 | action, pci_func); | ||
3184 | if (ret) | ||
3185 | return ret; | ||
3186 | } | ||
3187 | |||
3188 | for (i = 0; i < count; i++) { | ||
3189 | pci_func = pm_cfg[i].pci_func; | ||
3190 | id = adapter->npars[pci_func].phy_port; | ||
3191 | adapter->npars[pci_func].enable_pm = !!pm_cfg[i].action; | ||
3192 | adapter->npars[pci_func].dest_npar = id; | ||
3193 | } | ||
3194 | return size; | ||
3195 | } | ||
3196 | |||
3197 | static ssize_t | ||
3198 | qlcnic_sysfs_read_pm_config(struct file *filp, struct kobject *kobj, | ||
3199 | struct bin_attribute *attr, char *buf, loff_t offset, size_t size) | ||
3200 | { | ||
3201 | struct device *dev = container_of(kobj, struct device, kobj); | ||
3202 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
3203 | struct qlcnic_pm_func_cfg pm_cfg[QLCNIC_MAX_PCI_FUNC]; | ||
3204 | int i; | ||
3205 | |||
3206 | if (size != sizeof(pm_cfg)) | ||
3207 | return QL_STATUS_INVALID_PARAM; | ||
3208 | |||
3209 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { | ||
3210 | if (adapter->npars[i].type != QLCNIC_TYPE_NIC) | ||
3211 | continue; | ||
3212 | pm_cfg[i].action = adapter->npars[i].enable_pm; | ||
3213 | pm_cfg[i].dest_npar = 0; | ||
3214 | pm_cfg[i].pci_func = i; | ||
3215 | } | ||
3216 | memcpy(buf, &pm_cfg, size); | ||
3217 | |||
3218 | return size; | ||
3219 | } | ||
3220 | |||
3221 | static int | ||
3222 | validate_esw_config(struct qlcnic_adapter *adapter, | ||
3223 | struct qlcnic_esw_func_cfg *esw_cfg, int count) | ||
3224 | { | ||
3225 | u32 op_mode; | ||
3226 | u8 pci_func; | ||
3227 | int i; | ||
3228 | |||
3229 | op_mode = readl(adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE); | ||
3230 | |||
3231 | for (i = 0; i < count; i++) { | ||
3232 | pci_func = esw_cfg[i].pci_func; | ||
3233 | if (pci_func >= QLCNIC_MAX_PCI_FUNC) | ||
3234 | return QL_STATUS_INVALID_PARAM; | ||
3235 | |||
3236 | if (adapter->op_mode == QLCNIC_MGMT_FUNC) | ||
3237 | if (adapter->npars[pci_func].type != QLCNIC_TYPE_NIC) | ||
3238 | return QL_STATUS_INVALID_PARAM; | ||
3239 | |||
3240 | switch (esw_cfg[i].op_mode) { | ||
3241 | case QLCNIC_PORT_DEFAULTS: | ||
3242 | if (QLC_DEV_GET_DRV(op_mode, pci_func) != | ||
3243 | QLCNIC_NON_PRIV_FUNC) { | ||
3244 | if (esw_cfg[i].mac_anti_spoof != 0) | ||
3245 | return QL_STATUS_INVALID_PARAM; | ||
3246 | if (esw_cfg[i].mac_override != 1) | ||
3247 | return QL_STATUS_INVALID_PARAM; | ||
3248 | if (esw_cfg[i].promisc_mode != 1) | ||
3249 | return QL_STATUS_INVALID_PARAM; | ||
3250 | } | ||
3251 | break; | ||
3252 | case QLCNIC_ADD_VLAN: | ||
3253 | if (!IS_VALID_VLAN(esw_cfg[i].vlan_id)) | ||
3254 | return QL_STATUS_INVALID_PARAM; | ||
3255 | if (!esw_cfg[i].op_type) | ||
3256 | return QL_STATUS_INVALID_PARAM; | ||
3257 | break; | ||
3258 | case QLCNIC_DEL_VLAN: | ||
3259 | if (!esw_cfg[i].op_type) | ||
3260 | return QL_STATUS_INVALID_PARAM; | ||
3261 | break; | ||
3262 | default: | ||
3263 | return QL_STATUS_INVALID_PARAM; | ||
3264 | } | ||
3265 | } | ||
3266 | return 0; | ||
3267 | } | ||
3268 | |||
3269 | static ssize_t | ||
3270 | qlcnic_sysfs_write_esw_config(struct file *file, struct kobject *kobj, | ||
3271 | struct bin_attribute *attr, char *buf, loff_t offset, size_t size) | ||
3272 | { | ||
3273 | struct device *dev = container_of(kobj, struct device, kobj); | ||
3274 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
3275 | struct qlcnic_esw_func_cfg *esw_cfg; | ||
3276 | struct qlcnic_npar_info *npar; | ||
3277 | int count, rem, i, ret; | ||
3278 | u8 pci_func, op_mode = 0; | ||
3279 | |||
3280 | count = size / sizeof(struct qlcnic_esw_func_cfg); | ||
3281 | rem = size % sizeof(struct qlcnic_esw_func_cfg); | ||
3282 | if (rem) | ||
3283 | return QL_STATUS_INVALID_PARAM; | ||
3284 | |||
3285 | esw_cfg = (struct qlcnic_esw_func_cfg *) buf; | ||
3286 | ret = validate_esw_config(adapter, esw_cfg, count); | ||
3287 | if (ret) | ||
3288 | return ret; | ||
3289 | |||
3290 | for (i = 0; i < count; i++) { | ||
3291 | if (adapter->op_mode == QLCNIC_MGMT_FUNC) | ||
3292 | if (qlcnic_config_switch_port(adapter, &esw_cfg[i])) | ||
3293 | return QL_STATUS_INVALID_PARAM; | ||
3294 | |||
3295 | if (adapter->ahw->pci_func != esw_cfg[i].pci_func) | ||
3296 | continue; | ||
3297 | |||
3298 | op_mode = esw_cfg[i].op_mode; | ||
3299 | qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i]); | ||
3300 | esw_cfg[i].op_mode = op_mode; | ||
3301 | esw_cfg[i].pci_func = adapter->ahw->pci_func; | ||
3302 | |||
3303 | switch (esw_cfg[i].op_mode) { | ||
3304 | case QLCNIC_PORT_DEFAULTS: | ||
3305 | qlcnic_set_eswitch_port_features(adapter, &esw_cfg[i]); | ||
3306 | break; | ||
3307 | case QLCNIC_ADD_VLAN: | ||
3308 | qlcnic_set_vlan_config(adapter, &esw_cfg[i]); | ||
3309 | break; | ||
3310 | case QLCNIC_DEL_VLAN: | ||
3311 | esw_cfg[i].vlan_id = 0; | ||
3312 | qlcnic_set_vlan_config(adapter, &esw_cfg[i]); | ||
3313 | break; | ||
3314 | } | ||
3315 | } | ||
3316 | |||
3317 | if (adapter->op_mode != QLCNIC_MGMT_FUNC) | ||
3318 | goto out; | ||
3319 | |||
3320 | for (i = 0; i < count; i++) { | ||
3321 | pci_func = esw_cfg[i].pci_func; | ||
3322 | npar = &adapter->npars[pci_func]; | ||
3323 | switch (esw_cfg[i].op_mode) { | ||
3324 | case QLCNIC_PORT_DEFAULTS: | ||
3325 | npar->promisc_mode = esw_cfg[i].promisc_mode; | ||
3326 | npar->mac_override = esw_cfg[i].mac_override; | ||
3327 | npar->offload_flags = esw_cfg[i].offload_flags; | ||
3328 | npar->mac_anti_spoof = esw_cfg[i].mac_anti_spoof; | ||
3329 | npar->discard_tagged = esw_cfg[i].discard_tagged; | ||
3330 | break; | ||
3331 | case QLCNIC_ADD_VLAN: | ||
3332 | npar->pvid = esw_cfg[i].vlan_id; | ||
3333 | break; | ||
3334 | case QLCNIC_DEL_VLAN: | ||
3335 | npar->pvid = 0; | ||
3336 | break; | ||
3337 | } | ||
3338 | } | ||
3339 | out: | ||
3340 | return size; | ||
3341 | } | ||
3342 | |||
3343 | static ssize_t | ||
3344 | qlcnic_sysfs_read_esw_config(struct file *file, struct kobject *kobj, | ||
3345 | struct bin_attribute *attr, char *buf, loff_t offset, size_t size) | ||
3346 | { | ||
3347 | struct device *dev = container_of(kobj, struct device, kobj); | ||
3348 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
3349 | struct qlcnic_esw_func_cfg esw_cfg[QLCNIC_MAX_PCI_FUNC]; | ||
3350 | u8 i; | ||
3351 | |||
3352 | if (size != sizeof(esw_cfg)) | ||
3353 | return QL_STATUS_INVALID_PARAM; | ||
3354 | |||
3355 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { | ||
3356 | if (adapter->npars[i].type != QLCNIC_TYPE_NIC) | ||
3357 | continue; | ||
3358 | esw_cfg[i].pci_func = i; | ||
3359 | if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i])) | ||
3360 | return QL_STATUS_INVALID_PARAM; | ||
3361 | } | ||
3362 | memcpy(buf, &esw_cfg, size); | ||
3363 | |||
3364 | return size; | ||
3365 | } | ||
3366 | |||
3367 | static int | ||
3368 | validate_npar_config(struct qlcnic_adapter *adapter, | ||
3369 | struct qlcnic_npar_func_cfg *np_cfg, int count) | ||
3370 | { | ||
3371 | u8 pci_func, i; | ||
3372 | |||
3373 | for (i = 0; i < count; i++) { | ||
3374 | pci_func = np_cfg[i].pci_func; | ||
3375 | if (pci_func >= QLCNIC_MAX_PCI_FUNC) | ||
3376 | return QL_STATUS_INVALID_PARAM; | ||
3377 | |||
3378 | if (adapter->npars[pci_func].type != QLCNIC_TYPE_NIC) | ||
3379 | return QL_STATUS_INVALID_PARAM; | ||
3380 | |||
3381 | if (!IS_VALID_BW(np_cfg[i].min_bw) || | ||
3382 | !IS_VALID_BW(np_cfg[i].max_bw)) | ||
3383 | return QL_STATUS_INVALID_PARAM; | ||
3384 | } | ||
3385 | return 0; | ||
3386 | } | ||
3387 | |||
3388 | static ssize_t | ||
3389 | qlcnic_sysfs_write_npar_config(struct file *file, struct kobject *kobj, | ||
3390 | struct bin_attribute *attr, char *buf, loff_t offset, size_t size) | ||
3391 | { | ||
3392 | struct device *dev = container_of(kobj, struct device, kobj); | ||
3393 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
3394 | struct qlcnic_info nic_info; | ||
3395 | struct qlcnic_npar_func_cfg *np_cfg; | ||
3396 | int i, count, rem, ret; | ||
3397 | u8 pci_func; | ||
3398 | |||
3399 | count = size / sizeof(struct qlcnic_npar_func_cfg); | ||
3400 | rem = size % sizeof(struct qlcnic_npar_func_cfg); | ||
3401 | if (rem) | ||
3402 | return QL_STATUS_INVALID_PARAM; | ||
3403 | |||
3404 | np_cfg = (struct qlcnic_npar_func_cfg *) buf; | ||
3405 | ret = validate_npar_config(adapter, np_cfg, count); | ||
3406 | if (ret) | ||
3407 | return ret; | ||
3408 | |||
3409 | for (i = 0; i < count ; i++) { | ||
3410 | pci_func = np_cfg[i].pci_func; | ||
3411 | ret = qlcnic_get_nic_info(adapter, &nic_info, pci_func); | ||
3412 | if (ret) | ||
3413 | return ret; | ||
3414 | nic_info.pci_func = pci_func; | ||
3415 | nic_info.min_tx_bw = np_cfg[i].min_bw; | ||
3416 | nic_info.max_tx_bw = np_cfg[i].max_bw; | ||
3417 | ret = qlcnic_set_nic_info(adapter, &nic_info); | ||
3418 | if (ret) | ||
3419 | return ret; | ||
3420 | adapter->npars[i].min_bw = nic_info.min_tx_bw; | ||
3421 | adapter->npars[i].max_bw = nic_info.max_tx_bw; | ||
3422 | } | ||
3423 | |||
3424 | return size; | ||
3425 | |||
3426 | } | ||
3427 | static ssize_t | ||
3428 | qlcnic_sysfs_read_npar_config(struct file *file, struct kobject *kobj, | ||
3429 | struct bin_attribute *attr, char *buf, loff_t offset, size_t size) | ||
3430 | { | ||
3431 | struct device *dev = container_of(kobj, struct device, kobj); | ||
3432 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
3433 | struct qlcnic_info nic_info; | ||
3434 | struct qlcnic_npar_func_cfg np_cfg[QLCNIC_MAX_PCI_FUNC]; | ||
3435 | int i, ret; | ||
3436 | |||
3437 | if (size != sizeof(np_cfg)) | ||
3438 | return QL_STATUS_INVALID_PARAM; | ||
3439 | |||
3440 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC ; i++) { | ||
3441 | if (adapter->npars[i].type != QLCNIC_TYPE_NIC) | ||
3442 | continue; | ||
3443 | ret = qlcnic_get_nic_info(adapter, &nic_info, i); | ||
3444 | if (ret) | ||
3445 | return ret; | ||
3446 | |||
3447 | np_cfg[i].pci_func = i; | ||
3448 | np_cfg[i].op_mode = (u8)nic_info.op_mode; | ||
3449 | np_cfg[i].port_num = nic_info.phys_port; | ||
3450 | np_cfg[i].fw_capab = nic_info.capabilities; | ||
3451 | np_cfg[i].min_bw = nic_info.min_tx_bw ; | ||
3452 | np_cfg[i].max_bw = nic_info.max_tx_bw; | ||
3453 | np_cfg[i].max_tx_queues = nic_info.max_tx_ques; | ||
3454 | np_cfg[i].max_rx_queues = nic_info.max_rx_ques; | ||
3455 | } | ||
3456 | memcpy(buf, &np_cfg, size); | ||
3457 | return size; | ||
3458 | } | ||
3459 | |||
3460 | static ssize_t | ||
3461 | qlcnic_sysfs_get_port_stats(struct file *file, struct kobject *kobj, | ||
3462 | struct bin_attribute *attr, char *buf, loff_t offset, size_t size) | ||
3463 | { | ||
3464 | struct device *dev = container_of(kobj, struct device, kobj); | ||
3465 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
3466 | struct qlcnic_esw_statistics port_stats; | ||
3467 | int ret; | ||
3468 | |||
3469 | if (size != sizeof(struct qlcnic_esw_statistics)) | ||
3470 | return QL_STATUS_INVALID_PARAM; | ||
3471 | |||
3472 | if (offset >= QLCNIC_MAX_PCI_FUNC) | ||
3473 | return QL_STATUS_INVALID_PARAM; | ||
3474 | |||
3475 | memset(&port_stats, 0, size); | ||
3476 | ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER, | ||
3477 | &port_stats.rx); | ||
3478 | if (ret) | ||
3479 | return ret; | ||
3480 | |||
3481 | ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER, | ||
3482 | &port_stats.tx); | ||
3483 | if (ret) | ||
3484 | return ret; | ||
3485 | |||
3486 | memcpy(buf, &port_stats, size); | ||
3487 | return size; | ||
3488 | } | ||
3489 | |||
3490 | static ssize_t | ||
3491 | qlcnic_sysfs_get_esw_stats(struct file *file, struct kobject *kobj, | ||
3492 | struct bin_attribute *attr, char *buf, loff_t offset, size_t size) | ||
3493 | { | ||
3494 | struct device *dev = container_of(kobj, struct device, kobj); | ||
3495 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
3496 | struct qlcnic_esw_statistics esw_stats; | ||
3497 | int ret; | ||
3498 | |||
3499 | if (size != sizeof(struct qlcnic_esw_statistics)) | ||
3500 | return QL_STATUS_INVALID_PARAM; | ||
3501 | |||
3502 | if (offset >= QLCNIC_NIU_MAX_XG_PORTS) | ||
3503 | return QL_STATUS_INVALID_PARAM; | ||
3504 | |||
3505 | memset(&esw_stats, 0, size); | ||
3506 | ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER, | ||
3507 | &esw_stats.rx); | ||
3508 | if (ret) | ||
3509 | return ret; | ||
3510 | |||
3511 | ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER, | ||
3512 | &esw_stats.tx); | ||
3513 | if (ret) | ||
3514 | return ret; | ||
3515 | |||
3516 | memcpy(buf, &esw_stats, size); | ||
3517 | return size; | ||
3518 | } | ||
3519 | |||
3520 | static ssize_t | ||
3521 | qlcnic_sysfs_clear_esw_stats(struct file *file, struct kobject *kobj, | ||
3522 | struct bin_attribute *attr, char *buf, loff_t offset, size_t size) | ||
3523 | { | ||
3524 | struct device *dev = container_of(kobj, struct device, kobj); | ||
3525 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
3526 | int ret; | ||
3527 | |||
3528 | if (offset >= QLCNIC_NIU_MAX_XG_PORTS) | ||
3529 | return QL_STATUS_INVALID_PARAM; | ||
3530 | |||
3531 | ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset, | ||
3532 | QLCNIC_QUERY_RX_COUNTER); | ||
3533 | if (ret) | ||
3534 | return ret; | ||
3535 | |||
3536 | ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset, | ||
3537 | QLCNIC_QUERY_TX_COUNTER); | ||
3538 | if (ret) | ||
3539 | return ret; | ||
3540 | |||
3541 | return size; | ||
3542 | } | ||
3543 | |||
3544 | static ssize_t | ||
3545 | qlcnic_sysfs_clear_port_stats(struct file *file, struct kobject *kobj, | ||
3546 | struct bin_attribute *attr, char *buf, loff_t offset, size_t size) | ||
3547 | { | ||
3548 | |||
3549 | struct device *dev = container_of(kobj, struct device, kobj); | ||
3550 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
3551 | int ret; | ||
3552 | |||
3553 | if (offset >= QLCNIC_MAX_PCI_FUNC) | ||
3554 | return QL_STATUS_INVALID_PARAM; | ||
3555 | |||
3556 | ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset, | ||
3557 | QLCNIC_QUERY_RX_COUNTER); | ||
3558 | if (ret) | ||
3559 | return ret; | ||
3560 | |||
3561 | ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset, | ||
3562 | QLCNIC_QUERY_TX_COUNTER); | ||
3563 | if (ret) | ||
3564 | return ret; | ||
3565 | |||
3566 | return size; | ||
3567 | } | ||
3568 | |||
3569 | static ssize_t | ||
3570 | qlcnic_sysfs_read_pci_config(struct file *file, struct kobject *kobj, | ||
3571 | struct bin_attribute *attr, char *buf, loff_t offset, size_t size) | ||
3572 | { | ||
3573 | struct device *dev = container_of(kobj, struct device, kobj); | ||
3574 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
3575 | struct qlcnic_pci_func_cfg pci_cfg[QLCNIC_MAX_PCI_FUNC]; | ||
3576 | struct qlcnic_pci_info *pci_info; | ||
3577 | int i, ret; | ||
3578 | |||
3579 | if (size != sizeof(pci_cfg)) | ||
3580 | return QL_STATUS_INVALID_PARAM; | ||
3581 | |||
3582 | pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL); | ||
3583 | if (!pci_info) | ||
3584 | return -ENOMEM; | ||
3585 | |||
3586 | ret = qlcnic_get_pci_info(adapter, pci_info); | ||
3587 | if (ret) { | ||
3588 | kfree(pci_info); | ||
3589 | return ret; | ||
3590 | } | ||
3591 | |||
3592 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC ; i++) { | ||
3593 | pci_cfg[i].pci_func = pci_info[i].id; | ||
3594 | pci_cfg[i].func_type = pci_info[i].type; | ||
3595 | pci_cfg[i].port_num = pci_info[i].default_port; | ||
3596 | pci_cfg[i].min_bw = pci_info[i].tx_min_bw; | ||
3597 | pci_cfg[i].max_bw = pci_info[i].tx_max_bw; | ||
3598 | memcpy(&pci_cfg[i].def_mac_addr, &pci_info[i].mac, ETH_ALEN); | ||
3599 | } | ||
3600 | memcpy(buf, &pci_cfg, size); | ||
3601 | kfree(pci_info); | ||
3602 | return size; | ||
3603 | } | ||
3604 | static struct bin_attribute bin_attr_npar_config = { | ||
3605 | .attr = {.name = "npar_config", .mode = (S_IRUGO | S_IWUSR)}, | ||
3606 | .size = 0, | ||
3607 | .read = qlcnic_sysfs_read_npar_config, | ||
3608 | .write = qlcnic_sysfs_write_npar_config, | ||
3609 | }; | ||
3610 | |||
3611 | static struct bin_attribute bin_attr_pci_config = { | ||
3612 | .attr = {.name = "pci_config", .mode = (S_IRUGO | S_IWUSR)}, | ||
3613 | .size = 0, | ||
3614 | .read = qlcnic_sysfs_read_pci_config, | ||
3615 | .write = NULL, | ||
3616 | }; | ||
3617 | |||
3618 | static struct bin_attribute bin_attr_port_stats = { | ||
3619 | .attr = {.name = "port_stats", .mode = (S_IRUGO | S_IWUSR)}, | ||
3620 | .size = 0, | ||
3621 | .read = qlcnic_sysfs_get_port_stats, | ||
3622 | .write = qlcnic_sysfs_clear_port_stats, | ||
3623 | }; | ||
3624 | |||
3625 | static struct bin_attribute bin_attr_esw_stats = { | ||
3626 | .attr = {.name = "esw_stats", .mode = (S_IRUGO | S_IWUSR)}, | ||
3627 | .size = 0, | ||
3628 | .read = qlcnic_sysfs_get_esw_stats, | ||
3629 | .write = qlcnic_sysfs_clear_esw_stats, | ||
3630 | }; | ||
3631 | |||
3632 | static struct bin_attribute bin_attr_esw_config = { | ||
3633 | .attr = {.name = "esw_config", .mode = (S_IRUGO | S_IWUSR)}, | ||
3634 | .size = 0, | ||
3635 | .read = qlcnic_sysfs_read_esw_config, | ||
3636 | .write = qlcnic_sysfs_write_esw_config, | ||
3637 | }; | ||
3638 | |||
3639 | static struct bin_attribute bin_attr_pm_config = { | ||
3640 | .attr = {.name = "pm_config", .mode = (S_IRUGO | S_IWUSR)}, | ||
3641 | .size = 0, | ||
3642 | .read = qlcnic_sysfs_read_pm_config, | ||
3643 | .write = qlcnic_sysfs_write_pm_config, | ||
3644 | }; | ||
3645 | |||
3646 | static void | ||
3647 | qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter) | ||
3648 | { | ||
3649 | struct device *dev = &adapter->pdev->dev; | ||
3650 | |||
3651 | if (adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG) | ||
3652 | if (device_create_file(dev, &dev_attr_bridged_mode)) | ||
3653 | dev_warn(dev, | ||
3654 | "failed to create bridged_mode sysfs entry\n"); | ||
3655 | } | ||
3656 | |||
3657 | static void | ||
3658 | qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter) | ||
3659 | { | ||
3660 | struct device *dev = &adapter->pdev->dev; | ||
3661 | |||
3662 | if (adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG) | ||
3663 | device_remove_file(dev, &dev_attr_bridged_mode); | ||
3664 | } | ||
3665 | |||
3666 | static void | ||
3667 | qlcnic_create_diag_entries(struct qlcnic_adapter *adapter) | ||
3668 | { | ||
3669 | struct device *dev = &adapter->pdev->dev; | ||
3670 | u32 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); | ||
3671 | |||
3672 | if (device_create_bin_file(dev, &bin_attr_port_stats)) | ||
3673 | dev_info(dev, "failed to create port stats sysfs entry"); | ||
3674 | |||
3675 | if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) | ||
3676 | return; | ||
3677 | if (device_create_file(dev, &dev_attr_diag_mode)) | ||
3678 | dev_info(dev, "failed to create diag_mode sysfs entry\n"); | ||
3679 | if (device_create_bin_file(dev, &bin_attr_crb)) | ||
3680 | dev_info(dev, "failed to create crb sysfs entry\n"); | ||
3681 | if (device_create_bin_file(dev, &bin_attr_mem)) | ||
3682 | dev_info(dev, "failed to create mem sysfs entry\n"); | ||
3683 | |||
3684 | if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD)) | ||
3685 | return; | ||
3686 | |||
3687 | if (device_create_bin_file(dev, &bin_attr_pci_config)) | ||
3688 | dev_info(dev, "failed to create pci config sysfs entry"); | ||
3689 | if (device_create_file(dev, &dev_attr_beacon)) | ||
3690 | dev_info(dev, "failed to create beacon sysfs entry"); | ||
3691 | |||
3692 | if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) | ||
3693 | return; | ||
3694 | if (device_create_bin_file(dev, &bin_attr_esw_config)) | ||
3695 | dev_info(dev, "failed to create esw config sysfs entry"); | ||
3696 | if (adapter->op_mode != QLCNIC_MGMT_FUNC) | ||
3697 | return; | ||
3698 | if (device_create_bin_file(dev, &bin_attr_npar_config)) | ||
3699 | dev_info(dev, "failed to create npar config sysfs entry"); | ||
3700 | if (device_create_bin_file(dev, &bin_attr_pm_config)) | ||
3701 | dev_info(dev, "failed to create pm config sysfs entry"); | ||
3702 | if (device_create_bin_file(dev, &bin_attr_esw_stats)) | ||
3703 | dev_info(dev, "failed to create eswitch stats sysfs entry"); | ||
3704 | } | ||
3705 | |||
3706 | static void | ||
3707 | qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter) | ||
3708 | { | ||
3709 | struct device *dev = &adapter->pdev->dev; | ||
3710 | u32 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); | ||
3711 | |||
3712 | device_remove_bin_file(dev, &bin_attr_port_stats); | ||
3713 | |||
3714 | if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) | ||
3715 | return; | ||
3716 | device_remove_file(dev, &dev_attr_diag_mode); | ||
3717 | device_remove_bin_file(dev, &bin_attr_crb); | ||
3718 | device_remove_bin_file(dev, &bin_attr_mem); | ||
3719 | if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD)) | ||
3720 | return; | ||
3721 | device_remove_bin_file(dev, &bin_attr_pci_config); | ||
3722 | device_remove_file(dev, &dev_attr_beacon); | ||
3723 | if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) | ||
3724 | return; | ||
3725 | device_remove_bin_file(dev, &bin_attr_esw_config); | ||
3726 | if (adapter->op_mode != QLCNIC_MGMT_FUNC) | ||
3727 | return; | ||
3728 | device_remove_bin_file(dev, &bin_attr_npar_config); | ||
3729 | device_remove_bin_file(dev, &bin_attr_pm_config); | ||
3730 | device_remove_bin_file(dev, &bin_attr_esw_stats); | ||
3731 | } | ||
3732 | |||
3733 | #ifdef CONFIG_INET | 2783 | #ifdef CONFIG_INET |
3734 | 2784 | ||
3735 | #define is_qlcnic_netdev(dev) (dev->netdev_ops == &qlcnic_netdev_ops) | 2785 | #define is_qlcnic_netdev(dev) (dev->netdev_ops == &qlcnic_netdev_ops) |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c new file mode 100644 index 00000000000..e2bad8b6020 --- /dev/null +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c | |||
@@ -0,0 +1,951 @@ | |||
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 | |||
16 | #include <linux/sysfs.h> | ||
17 | |||
18 | int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable) | ||
19 | { | ||
20 | return -EOPNOTSUPP; | ||
21 | } | ||
22 | |||
23 | int qlcnicvf_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate) | ||
24 | { | ||
25 | return -EOPNOTSUPP; | ||
26 | } | ||
27 | |||
28 | static ssize_t | ||
29 | qlcnic_store_bridged_mode(struct device *dev, | ||
30 | struct device_attribute *attr, const char *buf, size_t len) | ||
31 | { | ||
32 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
33 | unsigned long new; | ||
34 | int ret = -EINVAL; | ||
35 | |||
36 | if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG)) | ||
37 | goto err_out; | ||
38 | |||
39 | if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) | ||
40 | goto err_out; | ||
41 | |||
42 | if (strict_strtoul(buf, 2, &new)) | ||
43 | goto err_out; | ||
44 | |||
45 | if (!adapter->nic_ops->config_bridged_mode(adapter, !!new)) | ||
46 | ret = len; | ||
47 | |||
48 | err_out: | ||
49 | return ret; | ||
50 | } | ||
51 | |||
52 | static ssize_t | ||
53 | qlcnic_show_bridged_mode(struct device *dev, | ||
54 | struct device_attribute *attr, char *buf) | ||
55 | { | ||
56 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
57 | int bridged_mode = 0; | ||
58 | |||
59 | if (adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG) | ||
60 | bridged_mode = !!(adapter->flags & QLCNIC_BRIDGE_ENABLED); | ||
61 | |||
62 | return sprintf(buf, "%d\n", bridged_mode); | ||
63 | } | ||
64 | |||
65 | static ssize_t | ||
66 | qlcnic_store_diag_mode(struct device *dev, | ||
67 | struct device_attribute *attr, const char *buf, size_t len) | ||
68 | { | ||
69 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
70 | unsigned long new; | ||
71 | |||
72 | if (strict_strtoul(buf, 2, &new)) | ||
73 | return -EINVAL; | ||
74 | |||
75 | if (!!new != !!(adapter->flags & QLCNIC_DIAG_ENABLED)) | ||
76 | adapter->flags ^= QLCNIC_DIAG_ENABLED; | ||
77 | |||
78 | return len; | ||
79 | } | ||
80 | |||
81 | static ssize_t | ||
82 | qlcnic_show_diag_mode(struct device *dev, | ||
83 | struct device_attribute *attr, char *buf) | ||
84 | { | ||
85 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
86 | |||
87 | return sprintf(buf, "%d\n", | ||
88 | !!(adapter->flags & QLCNIC_DIAG_ENABLED)); | ||
89 | } | ||
90 | |||
91 | static int | ||
92 | qlcnic_validate_beacon(struct qlcnic_adapter *adapter, u16 beacon, u8 *state, | ||
93 | u8 *rate) | ||
94 | { | ||
95 | *rate = LSB(beacon); | ||
96 | *state = MSB(beacon); | ||
97 | |||
98 | QLCDB(adapter, DRV, "rate %x state %x\n", *rate, *state); | ||
99 | |||
100 | if (!*state) { | ||
101 | *rate = __QLCNIC_MAX_LED_RATE; | ||
102 | return 0; | ||
103 | } else if (*state > __QLCNIC_MAX_LED_STATE) | ||
104 | return -EINVAL; | ||
105 | |||
106 | if ((!*rate) || (*rate > __QLCNIC_MAX_LED_RATE)) | ||
107 | return -EINVAL; | ||
108 | |||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | static ssize_t | ||
113 | qlcnic_store_beacon(struct device *dev, | ||
114 | struct device_attribute *attr, const char *buf, size_t len) | ||
115 | { | ||
116 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
117 | int max_sds_rings = adapter->max_sds_rings; | ||
118 | u16 beacon; | ||
119 | u8 b_state, b_rate; | ||
120 | int err; | ||
121 | |||
122 | if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) { | ||
123 | dev_warn(dev, "LED test not supported for non " | ||
124 | "privilege function\n"); | ||
125 | return -EOPNOTSUPP; | ||
126 | } | ||
127 | |||
128 | if (len != sizeof(u16)) | ||
129 | return QL_STATUS_INVALID_PARAM; | ||
130 | |||
131 | memcpy(&beacon, buf, sizeof(u16)); | ||
132 | err = qlcnic_validate_beacon(adapter, beacon, &b_state, &b_rate); | ||
133 | if (err) | ||
134 | return err; | ||
135 | |||
136 | if (adapter->ahw->beacon_state == b_state) | ||
137 | return len; | ||
138 | |||
139 | rtnl_lock(); | ||
140 | |||
141 | if (!adapter->ahw->beacon_state) | ||
142 | if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state)) { | ||
143 | rtnl_unlock(); | ||
144 | return -EBUSY; | ||
145 | } | ||
146 | |||
147 | if (test_bit(__QLCNIC_RESETTING, &adapter->state)) { | ||
148 | err = -EIO; | ||
149 | goto out; | ||
150 | } | ||
151 | |||
152 | if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) { | ||
153 | err = qlcnic_diag_alloc_res(adapter->netdev, QLCNIC_LED_TEST); | ||
154 | if (err) | ||
155 | goto out; | ||
156 | set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state); | ||
157 | } | ||
158 | |||
159 | err = qlcnic_config_led(adapter, b_state, b_rate); | ||
160 | |||
161 | if (!err) { | ||
162 | err = len; | ||
163 | adapter->ahw->beacon_state = b_state; | ||
164 | } | ||
165 | |||
166 | if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state)) | ||
167 | qlcnic_diag_free_res(adapter->netdev, max_sds_rings); | ||
168 | |||
169 | out: | ||
170 | if (!adapter->ahw->beacon_state) | ||
171 | clear_bit(__QLCNIC_LED_ENABLE, &adapter->state); | ||
172 | rtnl_unlock(); | ||
173 | |||
174 | return err; | ||
175 | } | ||
176 | |||
177 | static ssize_t | ||
178 | qlcnic_show_beacon(struct device *dev, | ||
179 | struct device_attribute *attr, char *buf) | ||
180 | { | ||
181 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
182 | |||
183 | return sprintf(buf, "%d\n", adapter->ahw->beacon_state); | ||
184 | } | ||
185 | |||
186 | static int | ||
187 | qlcnic_sysfs_validate_crb(struct qlcnic_adapter *adapter, | ||
188 | loff_t offset, size_t size) | ||
189 | { | ||
190 | size_t crb_size = 4; | ||
191 | |||
192 | if (!(adapter->flags & QLCNIC_DIAG_ENABLED)) | ||
193 | return -EIO; | ||
194 | |||
195 | if (offset < QLCNIC_PCI_CRBSPACE) { | ||
196 | if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, | ||
197 | QLCNIC_PCI_CAMQM_END)) | ||
198 | crb_size = 8; | ||
199 | else | ||
200 | return -EINVAL; | ||
201 | } | ||
202 | |||
203 | if ((size != crb_size) || (offset & (crb_size-1))) | ||
204 | return -EINVAL; | ||
205 | |||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | static ssize_t | ||
210 | qlcnic_sysfs_read_crb(struct file *filp, struct kobject *kobj, | ||
211 | struct bin_attribute *attr, | ||
212 | char *buf, loff_t offset, size_t size) | ||
213 | { | ||
214 | struct device *dev = container_of(kobj, struct device, kobj); | ||
215 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
216 | u32 data; | ||
217 | u64 qmdata; | ||
218 | int ret; | ||
219 | |||
220 | ret = qlcnic_sysfs_validate_crb(adapter, offset, size); | ||
221 | if (ret != 0) | ||
222 | return ret; | ||
223 | |||
224 | if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) { | ||
225 | qlcnic_pci_camqm_read_2M(adapter, offset, &qmdata); | ||
226 | memcpy(buf, &qmdata, size); | ||
227 | } else { | ||
228 | data = QLCRD32(adapter, offset); | ||
229 | memcpy(buf, &data, size); | ||
230 | } | ||
231 | return size; | ||
232 | } | ||
233 | |||
234 | static ssize_t | ||
235 | qlcnic_sysfs_write_crb(struct file *filp, struct kobject *kobj, | ||
236 | struct bin_attribute *attr, | ||
237 | char *buf, loff_t offset, size_t size) | ||
238 | { | ||
239 | struct device *dev = container_of(kobj, struct device, kobj); | ||
240 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
241 | u32 data; | ||
242 | u64 qmdata; | ||
243 | int ret; | ||
244 | |||
245 | ret = qlcnic_sysfs_validate_crb(adapter, offset, size); | ||
246 | if (ret != 0) | ||
247 | return ret; | ||
248 | |||
249 | if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) { | ||
250 | memcpy(&qmdata, buf, size); | ||
251 | qlcnic_pci_camqm_write_2M(adapter, offset, qmdata); | ||
252 | } else { | ||
253 | memcpy(&data, buf, size); | ||
254 | QLCWR32(adapter, offset, data); | ||
255 | } | ||
256 | return size; | ||
257 | } | ||
258 | |||
259 | static int | ||
260 | qlcnic_sysfs_validate_mem(struct qlcnic_adapter *adapter, | ||
261 | loff_t offset, size_t size) | ||
262 | { | ||
263 | if (!(adapter->flags & QLCNIC_DIAG_ENABLED)) | ||
264 | return -EIO; | ||
265 | |||
266 | if ((size != 8) || (offset & 0x7)) | ||
267 | return -EIO; | ||
268 | |||
269 | return 0; | ||
270 | } | ||
271 | |||
272 | static ssize_t | ||
273 | qlcnic_sysfs_read_mem(struct file *filp, struct kobject *kobj, | ||
274 | struct bin_attribute *attr, | ||
275 | char *buf, loff_t offset, size_t size) | ||
276 | { | ||
277 | struct device *dev = container_of(kobj, struct device, kobj); | ||
278 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
279 | u64 data; | ||
280 | int ret; | ||
281 | |||
282 | ret = qlcnic_sysfs_validate_mem(adapter, offset, size); | ||
283 | if (ret != 0) | ||
284 | return ret; | ||
285 | |||
286 | if (qlcnic_pci_mem_read_2M(adapter, offset, &data)) | ||
287 | return -EIO; | ||
288 | |||
289 | memcpy(buf, &data, size); | ||
290 | |||
291 | return size; | ||
292 | } | ||
293 | |||
294 | static ssize_t | ||
295 | qlcnic_sysfs_write_mem(struct file *filp, struct kobject *kobj, | ||
296 | struct bin_attribute *attr, | ||
297 | char *buf, loff_t offset, size_t size) | ||
298 | { | ||
299 | struct device *dev = container_of(kobj, struct device, kobj); | ||
300 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
301 | u64 data; | ||
302 | int ret; | ||
303 | |||
304 | ret = qlcnic_sysfs_validate_mem(adapter, offset, size); | ||
305 | if (ret != 0) | ||
306 | return ret; | ||
307 | |||
308 | memcpy(&data, buf, size); | ||
309 | |||
310 | if (qlcnic_pci_mem_write_2M(adapter, offset, data)) | ||
311 | return -EIO; | ||
312 | |||
313 | return size; | ||
314 | } | ||
315 | |||
316 | static int | ||
317 | validate_pm_config(struct qlcnic_adapter *adapter, | ||
318 | struct qlcnic_pm_func_cfg *pm_cfg, int count) | ||
319 | { | ||
320 | |||
321 | u8 src_pci_func, s_esw_id, d_esw_id; | ||
322 | u8 dest_pci_func; | ||
323 | int i; | ||
324 | |||
325 | for (i = 0; i < count; i++) { | ||
326 | src_pci_func = pm_cfg[i].pci_func; | ||
327 | dest_pci_func = pm_cfg[i].dest_npar; | ||
328 | if (src_pci_func >= QLCNIC_MAX_PCI_FUNC | ||
329 | || dest_pci_func >= QLCNIC_MAX_PCI_FUNC) | ||
330 | return QL_STATUS_INVALID_PARAM; | ||
331 | |||
332 | if (adapter->npars[src_pci_func].type != QLCNIC_TYPE_NIC) | ||
333 | return QL_STATUS_INVALID_PARAM; | ||
334 | |||
335 | if (adapter->npars[dest_pci_func].type != QLCNIC_TYPE_NIC) | ||
336 | return QL_STATUS_INVALID_PARAM; | ||
337 | |||
338 | s_esw_id = adapter->npars[src_pci_func].phy_port; | ||
339 | d_esw_id = adapter->npars[dest_pci_func].phy_port; | ||
340 | |||
341 | if (s_esw_id != d_esw_id) | ||
342 | return QL_STATUS_INVALID_PARAM; | ||
343 | |||
344 | } | ||
345 | return 0; | ||
346 | |||
347 | } | ||
348 | |||
349 | static ssize_t | ||
350 | qlcnic_sysfs_write_pm_config(struct file *filp, struct kobject *kobj, | ||
351 | struct bin_attribute *attr, char *buf, loff_t offset, size_t size) | ||
352 | { | ||
353 | struct device *dev = container_of(kobj, struct device, kobj); | ||
354 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
355 | struct qlcnic_pm_func_cfg *pm_cfg; | ||
356 | u32 id, action, pci_func; | ||
357 | int count, rem, i, ret; | ||
358 | |||
359 | count = size / sizeof(struct qlcnic_pm_func_cfg); | ||
360 | rem = size % sizeof(struct qlcnic_pm_func_cfg); | ||
361 | if (rem) | ||
362 | return QL_STATUS_INVALID_PARAM; | ||
363 | |||
364 | pm_cfg = (struct qlcnic_pm_func_cfg *) buf; | ||
365 | |||
366 | ret = validate_pm_config(adapter, pm_cfg, count); | ||
367 | if (ret) | ||
368 | return ret; | ||
369 | for (i = 0; i < count; i++) { | ||
370 | pci_func = pm_cfg[i].pci_func; | ||
371 | action = !!pm_cfg[i].action; | ||
372 | id = adapter->npars[pci_func].phy_port; | ||
373 | ret = qlcnic_config_port_mirroring(adapter, id, | ||
374 | action, pci_func); | ||
375 | if (ret) | ||
376 | return ret; | ||
377 | } | ||
378 | |||
379 | for (i = 0; i < count; i++) { | ||
380 | pci_func = pm_cfg[i].pci_func; | ||
381 | id = adapter->npars[pci_func].phy_port; | ||
382 | adapter->npars[pci_func].enable_pm = !!pm_cfg[i].action; | ||
383 | adapter->npars[pci_func].dest_npar = id; | ||
384 | } | ||
385 | return size; | ||
386 | } | ||
387 | |||
388 | static ssize_t | ||
389 | qlcnic_sysfs_read_pm_config(struct file *filp, struct kobject *kobj, | ||
390 | struct bin_attribute *attr, char *buf, loff_t offset, size_t size) | ||
391 | { | ||
392 | struct device *dev = container_of(kobj, struct device, kobj); | ||
393 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
394 | struct qlcnic_pm_func_cfg pm_cfg[QLCNIC_MAX_PCI_FUNC]; | ||
395 | int i; | ||
396 | |||
397 | if (size != sizeof(pm_cfg)) | ||
398 | return QL_STATUS_INVALID_PARAM; | ||
399 | |||
400 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { | ||
401 | if (adapter->npars[i].type != QLCNIC_TYPE_NIC) | ||
402 | continue; | ||
403 | pm_cfg[i].action = adapter->npars[i].enable_pm; | ||
404 | pm_cfg[i].dest_npar = 0; | ||
405 | pm_cfg[i].pci_func = i; | ||
406 | } | ||
407 | memcpy(buf, &pm_cfg, size); | ||
408 | |||
409 | return size; | ||
410 | } | ||
411 | |||
412 | static int | ||
413 | validate_esw_config(struct qlcnic_adapter *adapter, | ||
414 | struct qlcnic_esw_func_cfg *esw_cfg, int count) | ||
415 | { | ||
416 | u32 op_mode; | ||
417 | u8 pci_func; | ||
418 | int i; | ||
419 | |||
420 | op_mode = readl(adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE); | ||
421 | |||
422 | for (i = 0; i < count; i++) { | ||
423 | pci_func = esw_cfg[i].pci_func; | ||
424 | if (pci_func >= QLCNIC_MAX_PCI_FUNC) | ||
425 | return QL_STATUS_INVALID_PARAM; | ||
426 | |||
427 | if (adapter->op_mode == QLCNIC_MGMT_FUNC) | ||
428 | if (adapter->npars[pci_func].type != QLCNIC_TYPE_NIC) | ||
429 | return QL_STATUS_INVALID_PARAM; | ||
430 | |||
431 | switch (esw_cfg[i].op_mode) { | ||
432 | case QLCNIC_PORT_DEFAULTS: | ||
433 | if (QLC_DEV_GET_DRV(op_mode, pci_func) != | ||
434 | QLCNIC_NON_PRIV_FUNC) { | ||
435 | if (esw_cfg[i].mac_anti_spoof != 0) | ||
436 | return QL_STATUS_INVALID_PARAM; | ||
437 | if (esw_cfg[i].mac_override != 1) | ||
438 | return QL_STATUS_INVALID_PARAM; | ||
439 | if (esw_cfg[i].promisc_mode != 1) | ||
440 | return QL_STATUS_INVALID_PARAM; | ||
441 | } | ||
442 | break; | ||
443 | case QLCNIC_ADD_VLAN: | ||
444 | if (!IS_VALID_VLAN(esw_cfg[i].vlan_id)) | ||
445 | return QL_STATUS_INVALID_PARAM; | ||
446 | if (!esw_cfg[i].op_type) | ||
447 | return QL_STATUS_INVALID_PARAM; | ||
448 | break; | ||
449 | case QLCNIC_DEL_VLAN: | ||
450 | if (!esw_cfg[i].op_type) | ||
451 | return QL_STATUS_INVALID_PARAM; | ||
452 | break; | ||
453 | default: | ||
454 | return QL_STATUS_INVALID_PARAM; | ||
455 | } | ||
456 | } | ||
457 | return 0; | ||
458 | } | ||
459 | |||
460 | static ssize_t | ||
461 | qlcnic_sysfs_write_esw_config(struct file *file, struct kobject *kobj, | ||
462 | struct bin_attribute *attr, char *buf, loff_t offset, size_t size) | ||
463 | { | ||
464 | struct device *dev = container_of(kobj, struct device, kobj); | ||
465 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
466 | struct qlcnic_esw_func_cfg *esw_cfg; | ||
467 | struct qlcnic_npar_info *npar; | ||
468 | int count, rem, i, ret; | ||
469 | u8 pci_func, op_mode = 0; | ||
470 | |||
471 | count = size / sizeof(struct qlcnic_esw_func_cfg); | ||
472 | rem = size % sizeof(struct qlcnic_esw_func_cfg); | ||
473 | if (rem) | ||
474 | return QL_STATUS_INVALID_PARAM; | ||
475 | |||
476 | esw_cfg = (struct qlcnic_esw_func_cfg *) buf; | ||
477 | ret = validate_esw_config(adapter, esw_cfg, count); | ||
478 | if (ret) | ||
479 | return ret; | ||
480 | |||
481 | for (i = 0; i < count; i++) { | ||
482 | if (adapter->op_mode == QLCNIC_MGMT_FUNC) | ||
483 | if (qlcnic_config_switch_port(adapter, &esw_cfg[i])) | ||
484 | return QL_STATUS_INVALID_PARAM; | ||
485 | |||
486 | if (adapter->ahw->pci_func != esw_cfg[i].pci_func) | ||
487 | continue; | ||
488 | |||
489 | op_mode = esw_cfg[i].op_mode; | ||
490 | qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i]); | ||
491 | esw_cfg[i].op_mode = op_mode; | ||
492 | esw_cfg[i].pci_func = adapter->ahw->pci_func; | ||
493 | |||
494 | switch (esw_cfg[i].op_mode) { | ||
495 | case QLCNIC_PORT_DEFAULTS: | ||
496 | qlcnic_set_eswitch_port_features(adapter, &esw_cfg[i]); | ||
497 | break; | ||
498 | case QLCNIC_ADD_VLAN: | ||
499 | qlcnic_set_vlan_config(adapter, &esw_cfg[i]); | ||
500 | break; | ||
501 | case QLCNIC_DEL_VLAN: | ||
502 | esw_cfg[i].vlan_id = 0; | ||
503 | qlcnic_set_vlan_config(adapter, &esw_cfg[i]); | ||
504 | break; | ||
505 | } | ||
506 | } | ||
507 | |||
508 | if (adapter->op_mode != QLCNIC_MGMT_FUNC) | ||
509 | goto out; | ||
510 | |||
511 | for (i = 0; i < count; i++) { | ||
512 | pci_func = esw_cfg[i].pci_func; | ||
513 | npar = &adapter->npars[pci_func]; | ||
514 | switch (esw_cfg[i].op_mode) { | ||
515 | case QLCNIC_PORT_DEFAULTS: | ||
516 | npar->promisc_mode = esw_cfg[i].promisc_mode; | ||
517 | npar->mac_override = esw_cfg[i].mac_override; | ||
518 | npar->offload_flags = esw_cfg[i].offload_flags; | ||
519 | npar->mac_anti_spoof = esw_cfg[i].mac_anti_spoof; | ||
520 | npar->discard_tagged = esw_cfg[i].discard_tagged; | ||
521 | break; | ||
522 | case QLCNIC_ADD_VLAN: | ||
523 | npar->pvid = esw_cfg[i].vlan_id; | ||
524 | break; | ||
525 | case QLCNIC_DEL_VLAN: | ||
526 | npar->pvid = 0; | ||
527 | break; | ||
528 | } | ||
529 | } | ||
530 | out: | ||
531 | return size; | ||
532 | } | ||
533 | |||
534 | static ssize_t | ||
535 | qlcnic_sysfs_read_esw_config(struct file *file, struct kobject *kobj, | ||
536 | struct bin_attribute *attr, char *buf, loff_t offset, size_t size) | ||
537 | { | ||
538 | struct device *dev = container_of(kobj, struct device, kobj); | ||
539 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
540 | struct qlcnic_esw_func_cfg esw_cfg[QLCNIC_MAX_PCI_FUNC]; | ||
541 | u8 i; | ||
542 | |||
543 | if (size != sizeof(esw_cfg)) | ||
544 | return QL_STATUS_INVALID_PARAM; | ||
545 | |||
546 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { | ||
547 | if (adapter->npars[i].type != QLCNIC_TYPE_NIC) | ||
548 | continue; | ||
549 | esw_cfg[i].pci_func = i; | ||
550 | if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i])) | ||
551 | return QL_STATUS_INVALID_PARAM; | ||
552 | } | ||
553 | memcpy(buf, &esw_cfg, size); | ||
554 | |||
555 | return size; | ||
556 | } | ||
557 | |||
558 | static int | ||
559 | validate_npar_config(struct qlcnic_adapter *adapter, | ||
560 | struct qlcnic_npar_func_cfg *np_cfg, int count) | ||
561 | { | ||
562 | u8 pci_func, i; | ||
563 | |||
564 | for (i = 0; i < count; i++) { | ||
565 | pci_func = np_cfg[i].pci_func; | ||
566 | if (pci_func >= QLCNIC_MAX_PCI_FUNC) | ||
567 | return QL_STATUS_INVALID_PARAM; | ||
568 | |||
569 | if (adapter->npars[pci_func].type != QLCNIC_TYPE_NIC) | ||
570 | return QL_STATUS_INVALID_PARAM; | ||
571 | |||
572 | if (!IS_VALID_BW(np_cfg[i].min_bw) || | ||
573 | !IS_VALID_BW(np_cfg[i].max_bw)) | ||
574 | return QL_STATUS_INVALID_PARAM; | ||
575 | } | ||
576 | return 0; | ||
577 | } | ||
578 | |||
579 | static ssize_t | ||
580 | qlcnic_sysfs_write_npar_config(struct file *file, struct kobject *kobj, | ||
581 | struct bin_attribute *attr, char *buf, loff_t offset, size_t size) | ||
582 | { | ||
583 | struct device *dev = container_of(kobj, struct device, kobj); | ||
584 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
585 | struct qlcnic_info nic_info; | ||
586 | struct qlcnic_npar_func_cfg *np_cfg; | ||
587 | int i, count, rem, ret; | ||
588 | u8 pci_func; | ||
589 | |||
590 | count = size / sizeof(struct qlcnic_npar_func_cfg); | ||
591 | rem = size % sizeof(struct qlcnic_npar_func_cfg); | ||
592 | if (rem) | ||
593 | return QL_STATUS_INVALID_PARAM; | ||
594 | |||
595 | np_cfg = (struct qlcnic_npar_func_cfg *) buf; | ||
596 | ret = validate_npar_config(adapter, np_cfg, count); | ||
597 | if (ret) | ||
598 | return ret; | ||
599 | |||
600 | for (i = 0; i < count ; i++) { | ||
601 | pci_func = np_cfg[i].pci_func; | ||
602 | ret = qlcnic_get_nic_info(adapter, &nic_info, pci_func); | ||
603 | if (ret) | ||
604 | return ret; | ||
605 | nic_info.pci_func = pci_func; | ||
606 | nic_info.min_tx_bw = np_cfg[i].min_bw; | ||
607 | nic_info.max_tx_bw = np_cfg[i].max_bw; | ||
608 | ret = qlcnic_set_nic_info(adapter, &nic_info); | ||
609 | if (ret) | ||
610 | return ret; | ||
611 | adapter->npars[i].min_bw = nic_info.min_tx_bw; | ||
612 | adapter->npars[i].max_bw = nic_info.max_tx_bw; | ||
613 | } | ||
614 | |||
615 | return size; | ||
616 | |||
617 | } | ||
618 | static ssize_t | ||
619 | qlcnic_sysfs_read_npar_config(struct file *file, struct kobject *kobj, | ||
620 | struct bin_attribute *attr, char *buf, loff_t offset, size_t size) | ||
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 | |||
631 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC ; i++) { | ||
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; | ||
642 | np_cfg[i].min_bw = nic_info.min_tx_bw ; | ||
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 | |||
651 | static ssize_t | ||
652 | qlcnic_sysfs_get_port_stats(struct file *file, struct kobject *kobj, | ||
653 | struct bin_attribute *attr, char *buf, loff_t offset, size_t size) | ||
654 | { | ||
655 | struct device *dev = container_of(kobj, struct device, kobj); | ||
656 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
657 | struct qlcnic_esw_statistics port_stats; | ||
658 | int ret; | ||
659 | |||
660 | if (size != sizeof(struct qlcnic_esw_statistics)) | ||
661 | return QL_STATUS_INVALID_PARAM; | ||
662 | |||
663 | if (offset >= QLCNIC_MAX_PCI_FUNC) | ||
664 | return QL_STATUS_INVALID_PARAM; | ||
665 | |||
666 | memset(&port_stats, 0, size); | ||
667 | ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER, | ||
668 | &port_stats.rx); | ||
669 | if (ret) | ||
670 | return ret; | ||
671 | |||
672 | ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER, | ||
673 | &port_stats.tx); | ||
674 | if (ret) | ||
675 | return ret; | ||
676 | |||
677 | memcpy(buf, &port_stats, size); | ||
678 | return size; | ||
679 | } | ||
680 | |||
681 | static ssize_t | ||
682 | qlcnic_sysfs_get_esw_stats(struct file *file, struct kobject *kobj, | ||
683 | struct bin_attribute *attr, char *buf, loff_t offset, size_t size) | ||
684 | { | ||
685 | struct device *dev = container_of(kobj, struct device, kobj); | ||
686 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
687 | struct qlcnic_esw_statistics esw_stats; | ||
688 | int ret; | ||
689 | |||
690 | if (size != sizeof(struct qlcnic_esw_statistics)) | ||
691 | return QL_STATUS_INVALID_PARAM; | ||
692 | |||
693 | if (offset >= QLCNIC_NIU_MAX_XG_PORTS) | ||
694 | return QL_STATUS_INVALID_PARAM; | ||
695 | |||
696 | memset(&esw_stats, 0, size); | ||
697 | ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER, | ||
698 | &esw_stats.rx); | ||
699 | if (ret) | ||
700 | return ret; | ||
701 | |||
702 | ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER, | ||
703 | &esw_stats.tx); | ||
704 | if (ret) | ||
705 | return ret; | ||
706 | |||
707 | memcpy(buf, &esw_stats, size); | ||
708 | return size; | ||
709 | } | ||
710 | |||
711 | static ssize_t | ||
712 | qlcnic_sysfs_clear_esw_stats(struct file *file, struct kobject *kobj, | ||
713 | struct bin_attribute *attr, char *buf, loff_t offset, size_t size) | ||
714 | { | ||
715 | struct device *dev = container_of(kobj, struct device, kobj); | ||
716 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
717 | int ret; | ||
718 | |||
719 | if (offset >= QLCNIC_NIU_MAX_XG_PORTS) | ||
720 | return QL_STATUS_INVALID_PARAM; | ||
721 | |||
722 | ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset, | ||
723 | QLCNIC_QUERY_RX_COUNTER); | ||
724 | if (ret) | ||
725 | return ret; | ||
726 | |||
727 | ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset, | ||
728 | QLCNIC_QUERY_TX_COUNTER); | ||
729 | if (ret) | ||
730 | return ret; | ||
731 | |||
732 | return size; | ||
733 | } | ||
734 | |||
735 | static ssize_t | ||
736 | qlcnic_sysfs_clear_port_stats(struct file *file, struct kobject *kobj, | ||
737 | struct bin_attribute *attr, char *buf, loff_t offset, size_t size) | ||
738 | { | ||
739 | |||
740 | struct device *dev = container_of(kobj, struct device, kobj); | ||
741 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
742 | int ret; | ||
743 | |||
744 | if (offset >= QLCNIC_MAX_PCI_FUNC) | ||
745 | return QL_STATUS_INVALID_PARAM; | ||
746 | |||
747 | ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset, | ||
748 | QLCNIC_QUERY_RX_COUNTER); | ||
749 | if (ret) | ||
750 | return ret; | ||
751 | |||
752 | ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset, | ||
753 | QLCNIC_QUERY_TX_COUNTER); | ||
754 | if (ret) | ||
755 | return ret; | ||
756 | |||
757 | return size; | ||
758 | } | ||
759 | |||
760 | static ssize_t | ||
761 | qlcnic_sysfs_read_pci_config(struct file *file, struct kobject *kobj, | ||
762 | struct bin_attribute *attr, char *buf, loff_t offset, size_t size) | ||
763 | { | ||
764 | struct device *dev = container_of(kobj, struct device, kobj); | ||
765 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
766 | struct qlcnic_pci_func_cfg pci_cfg[QLCNIC_MAX_PCI_FUNC]; | ||
767 | struct qlcnic_pci_info *pci_info; | ||
768 | int i, ret; | ||
769 | |||
770 | if (size != sizeof(pci_cfg)) | ||
771 | return QL_STATUS_INVALID_PARAM; | ||
772 | |||
773 | pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL); | ||
774 | if (!pci_info) | ||
775 | return -ENOMEM; | ||
776 | |||
777 | ret = qlcnic_get_pci_info(adapter, pci_info); | ||
778 | if (ret) { | ||
779 | kfree(pci_info); | ||
780 | return ret; | ||
781 | } | ||
782 | |||
783 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC ; i++) { | ||
784 | pci_cfg[i].pci_func = pci_info[i].id; | ||
785 | pci_cfg[i].func_type = pci_info[i].type; | ||
786 | pci_cfg[i].port_num = pci_info[i].default_port; | ||
787 | pci_cfg[i].min_bw = pci_info[i].tx_min_bw; | ||
788 | pci_cfg[i].max_bw = pci_info[i].tx_max_bw; | ||
789 | memcpy(&pci_cfg[i].def_mac_addr, &pci_info[i].mac, ETH_ALEN); | ||
790 | } | ||
791 | memcpy(buf, &pci_cfg, size); | ||
792 | kfree(pci_info); | ||
793 | return size; | ||
794 | } | ||
795 | |||
796 | static struct device_attribute dev_attr_bridged_mode = { | ||
797 | .attr = {.name = "bridged_mode", .mode = (S_IRUGO | S_IWUSR)}, | ||
798 | .show = qlcnic_show_bridged_mode, | ||
799 | .store = qlcnic_store_bridged_mode, | ||
800 | }; | ||
801 | |||
802 | static struct device_attribute dev_attr_diag_mode = { | ||
803 | .attr = {.name = "diag_mode", .mode = (S_IRUGO | S_IWUSR)}, | ||
804 | .show = qlcnic_show_diag_mode, | ||
805 | .store = qlcnic_store_diag_mode, | ||
806 | }; | ||
807 | |||
808 | static struct device_attribute dev_attr_beacon = { | ||
809 | .attr = {.name = "beacon", .mode = (S_IRUGO | S_IWUSR)}, | ||
810 | .show = qlcnic_show_beacon, | ||
811 | .store = qlcnic_store_beacon, | ||
812 | }; | ||
813 | |||
814 | static struct bin_attribute bin_attr_crb = { | ||
815 | .attr = {.name = "crb", .mode = (S_IRUGO | S_IWUSR)}, | ||
816 | .size = 0, | ||
817 | .read = qlcnic_sysfs_read_crb, | ||
818 | .write = qlcnic_sysfs_write_crb, | ||
819 | }; | ||
820 | |||
821 | static struct bin_attribute bin_attr_mem = { | ||
822 | .attr = {.name = "mem", .mode = (S_IRUGO | S_IWUSR)}, | ||
823 | .size = 0, | ||
824 | .read = qlcnic_sysfs_read_mem, | ||
825 | .write = qlcnic_sysfs_write_mem, | ||
826 | }; | ||
827 | |||
828 | static struct bin_attribute bin_attr_npar_config = { | ||
829 | .attr = {.name = "npar_config", .mode = (S_IRUGO | S_IWUSR)}, | ||
830 | .size = 0, | ||
831 | .read = qlcnic_sysfs_read_npar_config, | ||
832 | .write = qlcnic_sysfs_write_npar_config, | ||
833 | }; | ||
834 | |||
835 | static struct bin_attribute bin_attr_pci_config = { | ||
836 | .attr = {.name = "pci_config", .mode = (S_IRUGO | S_IWUSR)}, | ||
837 | .size = 0, | ||
838 | .read = qlcnic_sysfs_read_pci_config, | ||
839 | .write = NULL, | ||
840 | }; | ||
841 | |||
842 | static struct bin_attribute bin_attr_port_stats = { | ||
843 | .attr = {.name = "port_stats", .mode = (S_IRUGO | S_IWUSR)}, | ||
844 | .size = 0, | ||
845 | .read = qlcnic_sysfs_get_port_stats, | ||
846 | .write = qlcnic_sysfs_clear_port_stats, | ||
847 | }; | ||
848 | |||
849 | static struct bin_attribute bin_attr_esw_stats = { | ||
850 | .attr = {.name = "esw_stats", .mode = (S_IRUGO | S_IWUSR)}, | ||
851 | .size = 0, | ||
852 | .read = qlcnic_sysfs_get_esw_stats, | ||
853 | .write = qlcnic_sysfs_clear_esw_stats, | ||
854 | }; | ||
855 | |||
856 | static struct bin_attribute bin_attr_esw_config = { | ||
857 | .attr = {.name = "esw_config", .mode = (S_IRUGO | S_IWUSR)}, | ||
858 | .size = 0, | ||
859 | .read = qlcnic_sysfs_read_esw_config, | ||
860 | .write = qlcnic_sysfs_write_esw_config, | ||
861 | }; | ||
862 | |||
863 | static struct bin_attribute bin_attr_pm_config = { | ||
864 | .attr = {.name = "pm_config", .mode = (S_IRUGO | S_IWUSR)}, | ||
865 | .size = 0, | ||
866 | .read = qlcnic_sysfs_read_pm_config, | ||
867 | .write = qlcnic_sysfs_write_pm_config, | ||
868 | }; | ||
869 | |||
870 | void qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter) | ||
871 | { | ||
872 | struct device *dev = &adapter->pdev->dev; | ||
873 | |||
874 | if (adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG) | ||
875 | if (device_create_file(dev, &dev_attr_bridged_mode)) | ||
876 | dev_warn(dev, | ||
877 | "failed to create bridged_mode sysfs entry\n"); | ||
878 | } | ||
879 | |||
880 | void qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter) | ||
881 | { | ||
882 | struct device *dev = &adapter->pdev->dev; | ||
883 | |||
884 | if (adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG) | ||
885 | device_remove_file(dev, &dev_attr_bridged_mode); | ||
886 | } | ||
887 | |||
888 | void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter) | ||
889 | { | ||
890 | struct device *dev = &adapter->pdev->dev; | ||
891 | u32 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); | ||
892 | |||
893 | if (device_create_bin_file(dev, &bin_attr_port_stats)) | ||
894 | dev_info(dev, "failed to create port stats sysfs entry"); | ||
895 | |||
896 | if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) | ||
897 | return; | ||
898 | if (device_create_file(dev, &dev_attr_diag_mode)) | ||
899 | dev_info(dev, "failed to create diag_mode sysfs entry\n"); | ||
900 | if (device_create_bin_file(dev, &bin_attr_crb)) | ||
901 | dev_info(dev, "failed to create crb sysfs entry\n"); | ||
902 | if (device_create_bin_file(dev, &bin_attr_mem)) | ||
903 | dev_info(dev, "failed to create mem sysfs entry\n"); | ||
904 | |||
905 | if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD)) | ||
906 | return; | ||
907 | |||
908 | if (device_create_bin_file(dev, &bin_attr_pci_config)) | ||
909 | dev_info(dev, "failed to create pci config sysfs entry"); | ||
910 | if (device_create_file(dev, &dev_attr_beacon)) | ||
911 | dev_info(dev, "failed to create beacon sysfs entry"); | ||
912 | |||
913 | if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) | ||
914 | return; | ||
915 | if (device_create_bin_file(dev, &bin_attr_esw_config)) | ||
916 | dev_info(dev, "failed to create esw config sysfs entry"); | ||
917 | if (adapter->op_mode != QLCNIC_MGMT_FUNC) | ||
918 | return; | ||
919 | if (device_create_bin_file(dev, &bin_attr_npar_config)) | ||
920 | dev_info(dev, "failed to create npar config sysfs entry"); | ||
921 | if (device_create_bin_file(dev, &bin_attr_pm_config)) | ||
922 | dev_info(dev, "failed to create pm config sysfs entry"); | ||
923 | if (device_create_bin_file(dev, &bin_attr_esw_stats)) | ||
924 | dev_info(dev, "failed to create eswitch stats sysfs entry"); | ||
925 | } | ||
926 | |||
927 | void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter) | ||
928 | { | ||
929 | struct device *dev = &adapter->pdev->dev; | ||
930 | u32 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); | ||
931 | |||
932 | device_remove_bin_file(dev, &bin_attr_port_stats); | ||
933 | |||
934 | if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) | ||
935 | return; | ||
936 | device_remove_file(dev, &dev_attr_diag_mode); | ||
937 | device_remove_bin_file(dev, &bin_attr_crb); | ||
938 | device_remove_bin_file(dev, &bin_attr_mem); | ||
939 | if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD)) | ||
940 | return; | ||
941 | device_remove_bin_file(dev, &bin_attr_pci_config); | ||
942 | device_remove_file(dev, &dev_attr_beacon); | ||
943 | if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) | ||
944 | return; | ||
945 | device_remove_bin_file(dev, &bin_attr_esw_config); | ||
946 | if (adapter->op_mode != QLCNIC_MGMT_FUNC) | ||
947 | return; | ||
948 | device_remove_bin_file(dev, &bin_attr_npar_config); | ||
949 | device_remove_bin_file(dev, &bin_attr_pm_config); | ||
950 | device_remove_bin_file(dev, &bin_attr_esw_stats); | ||
951 | } | ||