aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorSony Chacko <sony.chacko@qlogic.com>2012-11-27 23:34:28 -0500
committerDavid S. Miller <davem@davemloft.net>2012-11-28 11:07:43 -0500
commitec079a07db570ec6ba333525cc43805163bcb043 (patch)
tree4b850bb2791521ef7b1ef66e84755f8c79f8857c /drivers/net
parentd17dd0d9dfb235952c62703ffd34c5bf05257e4d (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/Makefile3
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic.h11
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c960
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c951
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 @@
5obj-$(CONFIG_QLCNIC) := qlcnic.o 5obj-$(CONFIG_QLCNIC) := qlcnic.o
6 6
7qlcnic-y := qlcnic_hw.o qlcnic_main.o qlcnic_init.o \ 7qlcnic-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 *);
1566void qlcnic_free_tx_rings(struct qlcnic_adapter *); 1566void qlcnic_free_tx_rings(struct qlcnic_adapter *);
1567int qlcnic_alloc_tx_rings(struct qlcnic_adapter *, struct net_device *); 1567int qlcnic_alloc_tx_rings(struct qlcnic_adapter *, struct net_device *);
1568 1568
1569void qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter);
1570void qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter);
1571void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter);
1572void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter);
1573int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *, u32);
1574int qlcnicvf_config_led(struct qlcnic_adapter *, u32, u32);
1575void qlcnic_set_vlan_config(struct qlcnic_adapter *,
1576 struct qlcnic_esw_func_cfg *);
1577void 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);
70static void qlcnic_poll_controller(struct net_device *netdev); 70static void qlcnic_poll_controller(struct net_device *netdev);
71#endif 71#endif
72 72
73static void qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter);
74static void qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter);
75static void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter);
76static void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter);
77
78static void qlcnic_idc_debug_info(struct qlcnic_adapter *adapter, u8 encoding); 73static void qlcnic_idc_debug_info(struct qlcnic_adapter *adapter, u8 encoding);
79static void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8); 74static void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8);
80static int qlcnic_can_start_firmware(struct qlcnic_adapter *adapter); 75static int qlcnic_can_start_firmware(struct qlcnic_adapter *adapter);
@@ -90,8 +85,6 @@ static int qlcnic_start_firmware(struct qlcnic_adapter *);
90 85
91static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter); 86static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter);
92static void qlcnic_dev_set_npar_ready(struct qlcnic_adapter *); 87static void qlcnic_dev_set_npar_ready(struct qlcnic_adapter *);
93static int qlcnicvf_config_led(struct qlcnic_adapter *, u32, u32);
94static int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *, u32);
95static int qlcnicvf_start_firmware(struct qlcnic_adapter *); 88static int qlcnicvf_start_firmware(struct qlcnic_adapter *);
96static void qlcnic_set_netdev_features(struct qlcnic_adapter *, 89static 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
632static void 625void qlcnic_set_vlan_config(struct qlcnic_adapter *adapter,
633qlcnic_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
665static void 657void qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter,
666qlcnic_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
684static int 675static int qlcnic_set_eswitch_port_config(struct qlcnic_adapter *adapter)
685qlcnic_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
2743static int
2744qlcnicvf_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable)
2745{
2746 return -EOPNOTSUPP;
2747}
2748
2749static int
2750qlcnicvf_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate)
2751{
2752 return -EOPNOTSUPP;
2753}
2754
2755static ssize_t
2756qlcnic_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
2775err_out:
2776 return ret;
2777}
2778
2779static ssize_t
2780qlcnic_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
2792static 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
2798static ssize_t
2799qlcnic_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
2814static ssize_t
2815qlcnic_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
2824static 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
2830int qlcnic_validate_max_rss(struct net_device *netdev, u8 max_hw, u8 val) 2733int 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
2880static int
2881qlcnic_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
2901static ssize_t
2902qlcnic_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
2966static ssize_t
2967qlcnic_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
2975static 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
2981static int
2982qlcnic_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
3004static ssize_t
3005qlcnic_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
3029static ssize_t
3030qlcnic_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
3054static int
3055qlcnic_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
3067static ssize_t
3068qlcnic_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
3089static ssize_t
3090qlcnic_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
3111static 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
3118static 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
3125static int
3126validate_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
3158static ssize_t
3159qlcnic_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
3197static ssize_t
3198qlcnic_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
3221static int
3222validate_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
3269static ssize_t
3270qlcnic_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 }
3339out:
3340 return size;
3341}
3342
3343static ssize_t
3344qlcnic_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
3367static int
3368validate_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
3388static ssize_t
3389qlcnic_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}
3427static ssize_t
3428qlcnic_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
3460static ssize_t
3461qlcnic_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
3490static ssize_t
3491qlcnic_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
3520static ssize_t
3521qlcnic_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
3544static ssize_t
3545qlcnic_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
3569static ssize_t
3570qlcnic_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}
3604static 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
3611static 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
3618static 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
3625static 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
3632static 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
3639static 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
3646static void
3647qlcnic_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
3657static void
3658qlcnic_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
3666static void
3667qlcnic_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
3706static void
3707qlcnic_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
18int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable)
19{
20 return -EOPNOTSUPP;
21}
22
23int qlcnicvf_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate)
24{
25 return -EOPNOTSUPP;
26}
27
28static ssize_t
29qlcnic_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
48err_out:
49 return ret;
50}
51
52static ssize_t
53qlcnic_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
65static ssize_t
66qlcnic_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
81static ssize_t
82qlcnic_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
91static int
92qlcnic_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
112static ssize_t
113qlcnic_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
177static ssize_t
178qlcnic_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
186static int
187qlcnic_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
209static ssize_t
210qlcnic_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
234static ssize_t
235qlcnic_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
259static int
260qlcnic_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
272static ssize_t
273qlcnic_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
294static ssize_t
295qlcnic_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
316static int
317validate_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
349static ssize_t
350qlcnic_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
388static ssize_t
389qlcnic_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
412static int
413validate_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
460static ssize_t
461qlcnic_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 }
530out:
531 return size;
532}
533
534static ssize_t
535qlcnic_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
558static int
559validate_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
579static ssize_t
580qlcnic_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}
618static ssize_t
619qlcnic_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
651static ssize_t
652qlcnic_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
681static ssize_t
682qlcnic_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
711static ssize_t
712qlcnic_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
735static ssize_t
736qlcnic_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
760static ssize_t
761qlcnic_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
796static 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
802static 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
808static 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
814static 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
821static 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
828static 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
835static 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
842static 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
849static 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
856static 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
863static 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
870void 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
880void 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
888void 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
927void 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}