diff options
author | Rajesh Borundia <rajesh.borundia@qlogic.com> | 2010-08-19 01:08:26 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-08-19 19:52:39 -0400 |
commit | 0325d69b2a1feb72f11413dbfcc1705ccfc203c1 (patch) | |
tree | 55b3d39f86ac2db38bae43209d0ce6111b3abd39 | |
parent | 4e8acb011f0e9e86e29b53ff051e699ba0c5726d (diff) |
qlcnic: configure offload setting on eswitch
Device is not capable of enabling/disabling offload setting per
port in case of Nic Partition.So offload settings needs to be
enabled/disabled per eswitch and it will affect all the function
on that eswitch.
Signed-off-by: Rajesh Borundia <rajesh.borundia@qlogic.com>
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/qlcnic/qlcnic_ethtool.c | 18 | ||||
-rw-r--r-- | drivers/net/qlcnic/qlcnic_main.c | 121 |
2 files changed, 133 insertions, 6 deletions
diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c index e38fc3d96d43..2805f88aaf7c 100644 --- a/drivers/net/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/qlcnic/qlcnic_ethtool.c | |||
@@ -804,6 +804,20 @@ qlcnic_get_ethtool_stats(struct net_device *dev, | |||
804 | } | 804 | } |
805 | } | 805 | } |
806 | 806 | ||
807 | static int qlcnic_set_tx_csum(struct net_device *dev, u32 data) | ||
808 | { | ||
809 | struct qlcnic_adapter *adapter = netdev_priv(dev); | ||
810 | |||
811 | if ((adapter->flags & QLCNIC_ESWITCH_ENABLED)) | ||
812 | return -EOPNOTSUPP; | ||
813 | if (data) | ||
814 | dev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); | ||
815 | else | ||
816 | dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); | ||
817 | |||
818 | return 0; | ||
819 | |||
820 | } | ||
807 | static u32 qlcnic_get_tx_csum(struct net_device *dev) | 821 | static u32 qlcnic_get_tx_csum(struct net_device *dev) |
808 | { | 822 | { |
809 | return dev->features & NETIF_F_IP_CSUM; | 823 | return dev->features & NETIF_F_IP_CSUM; |
@@ -819,6 +833,8 @@ static int qlcnic_set_rx_csum(struct net_device *dev, u32 data) | |||
819 | { | 833 | { |
820 | struct qlcnic_adapter *adapter = netdev_priv(dev); | 834 | struct qlcnic_adapter *adapter = netdev_priv(dev); |
821 | 835 | ||
836 | if ((adapter->flags & QLCNIC_ESWITCH_ENABLED)) | ||
837 | return -EOPNOTSUPP; | ||
822 | if (!!data) { | 838 | if (!!data) { |
823 | adapter->rx_csum = !!data; | 839 | adapter->rx_csum = !!data; |
824 | return 0; | 840 | return 0; |
@@ -1070,7 +1086,7 @@ const struct ethtool_ops qlcnic_ethtool_ops = { | |||
1070 | .get_pauseparam = qlcnic_get_pauseparam, | 1086 | .get_pauseparam = qlcnic_get_pauseparam, |
1071 | .set_pauseparam = qlcnic_set_pauseparam, | 1087 | .set_pauseparam = qlcnic_set_pauseparam, |
1072 | .get_tx_csum = qlcnic_get_tx_csum, | 1088 | .get_tx_csum = qlcnic_get_tx_csum, |
1073 | .set_tx_csum = ethtool_op_set_tx_csum, | 1089 | .set_tx_csum = qlcnic_set_tx_csum, |
1074 | .set_sg = ethtool_op_set_sg, | 1090 | .set_sg = ethtool_op_set_sg, |
1075 | .get_tso = qlcnic_get_tso, | 1091 | .get_tso = qlcnic_get_tso, |
1076 | .set_tso = qlcnic_set_tso, | 1092 | .set_tso = qlcnic_set_tso, |
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index 7bb32859b928..aa1f6b3c3b80 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c | |||
@@ -110,6 +110,8 @@ static void qlcnic_dev_set_npar_ready(struct qlcnic_adapter *); | |||
110 | static int qlcnicvf_config_led(struct qlcnic_adapter *, u32, u32); | 110 | static int qlcnicvf_config_led(struct qlcnic_adapter *, u32, u32); |
111 | static int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *, u32); | 111 | static int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *, u32); |
112 | static int qlcnicvf_start_firmware(struct qlcnic_adapter *); | 112 | static int qlcnicvf_start_firmware(struct qlcnic_adapter *); |
113 | static void qlcnic_set_netdev_features(struct qlcnic_adapter *, | ||
114 | struct qlcnic_esw_func_cfg *); | ||
113 | /* PCI Device ID Table */ | 115 | /* PCI Device ID Table */ |
114 | #define ENTRY(device) \ | 116 | #define ENTRY(device) \ |
115 | {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, (device)), \ | 117 | {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, (device)), \ |
@@ -756,6 +758,98 @@ qlcnic_check_options(struct qlcnic_adapter *adapter) | |||
756 | adapter->max_rds_rings = MAX_RDS_RINGS; | 758 | adapter->max_rds_rings = MAX_RDS_RINGS; |
757 | } | 759 | } |
758 | 760 | ||
761 | static void | ||
762 | qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter, | ||
763 | struct qlcnic_esw_func_cfg *esw_cfg) | ||
764 | { | ||
765 | qlcnic_set_netdev_features(adapter, esw_cfg); | ||
766 | } | ||
767 | |||
768 | static int | ||
769 | qlcnic_set_eswitch_port_config(struct qlcnic_adapter *adapter) | ||
770 | { | ||
771 | struct qlcnic_esw_func_cfg esw_cfg; | ||
772 | |||
773 | if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) | ||
774 | return 0; | ||
775 | |||
776 | esw_cfg.pci_func = adapter->ahw.pci_func; | ||
777 | if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg)) | ||
778 | return -EIO; | ||
779 | qlcnic_set_eswitch_port_features(adapter, &esw_cfg); | ||
780 | |||
781 | return 0; | ||
782 | } | ||
783 | |||
784 | static void | ||
785 | qlcnic_set_netdev_features(struct qlcnic_adapter *adapter, | ||
786 | struct qlcnic_esw_func_cfg *esw_cfg) | ||
787 | { | ||
788 | struct net_device *netdev = adapter->netdev; | ||
789 | unsigned long features, vlan_features; | ||
790 | |||
791 | features = (NETIF_F_SG | NETIF_F_IP_CSUM | | ||
792 | NETIF_F_IPV6_CSUM | NETIF_F_GRO); | ||
793 | vlan_features = (NETIF_F_SG | NETIF_F_IP_CSUM | | ||
794 | NETIF_F_IPV6_CSUM); | ||
795 | |||
796 | if (adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO) { | ||
797 | features |= (NETIF_F_TSO | NETIF_F_TSO6); | ||
798 | vlan_features |= (NETIF_F_TSO | NETIF_F_TSO6); | ||
799 | } | ||
800 | if (adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO) | ||
801 | features |= NETIF_F_LRO; | ||
802 | |||
803 | if (esw_cfg->offload_flags & BIT_0) { | ||
804 | netdev->features |= features; | ||
805 | adapter->rx_csum = 1; | ||
806 | if (!(esw_cfg->offload_flags & BIT_1)) | ||
807 | netdev->features &= ~NETIF_F_TSO; | ||
808 | if (!(esw_cfg->offload_flags & BIT_2)) | ||
809 | netdev->features &= ~NETIF_F_TSO6; | ||
810 | } else { | ||
811 | netdev->features &= ~features; | ||
812 | adapter->rx_csum = 0; | ||
813 | } | ||
814 | |||
815 | netdev->vlan_features = (features & vlan_features); | ||
816 | } | ||
817 | |||
818 | static int | ||
819 | qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter) | ||
820 | { | ||
821 | struct qlcnic_esw_func_cfg esw_cfg; | ||
822 | struct qlcnic_npar_info *npar; | ||
823 | u8 i; | ||
824 | |||
825 | if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) || | ||
826 | adapter->need_fw_reset || | ||
827 | adapter->op_mode != QLCNIC_MGMT_FUNC) | ||
828 | return 0; | ||
829 | |||
830 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { | ||
831 | if (adapter->npars[i].type != QLCNIC_TYPE_NIC) | ||
832 | continue; | ||
833 | memset(&esw_cfg, 0, sizeof(struct qlcnic_esw_func_cfg)); | ||
834 | esw_cfg.pci_func = i; | ||
835 | esw_cfg.offload_flags = BIT_0; | ||
836 | esw_cfg.mac_learning = BIT_0; | ||
837 | if (adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO) | ||
838 | esw_cfg.offload_flags |= (BIT_1 | BIT_2); | ||
839 | if (qlcnic_config_switch_port(adapter, &esw_cfg)) | ||
840 | return -EIO; | ||
841 | npar = &adapter->npars[i]; | ||
842 | npar->pvid = esw_cfg.vlan_id; | ||
843 | npar->mac_learning = esw_cfg.offload_flags; | ||
844 | npar->mac_anti_spoof = esw_cfg.mac_anti_spoof; | ||
845 | npar->discard_tagged = esw_cfg.discard_tagged; | ||
846 | npar->promisc_mode = esw_cfg.promisc_mode; | ||
847 | npar->offload_flags = esw_cfg.offload_flags; | ||
848 | } | ||
849 | |||
850 | return 0; | ||
851 | } | ||
852 | |||
759 | static int | 853 | static int |
760 | qlcnic_reset_eswitch_config(struct qlcnic_adapter *adapter, | 854 | qlcnic_reset_eswitch_config(struct qlcnic_adapter *adapter, |
761 | struct qlcnic_npar_info *npar, int pci_func) | 855 | struct qlcnic_npar_info *npar, int pci_func) |
@@ -879,6 +973,8 @@ wait_init: | |||
879 | 973 | ||
880 | QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_READY); | 974 | QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_READY); |
881 | qlcnic_idc_debug_info(adapter, 1); | 975 | qlcnic_idc_debug_info(adapter, 1); |
976 | if (qlcnic_set_default_offload_settings(adapter)) | ||
977 | goto err_out; | ||
882 | if (qlcnic_reset_npar_config(adapter)) | 978 | if (qlcnic_reset_npar_config(adapter)) |
883 | goto err_out; | 979 | goto err_out; |
884 | qlcnic_dev_set_npar_ready(adapter); | 980 | qlcnic_dev_set_npar_ready(adapter); |
@@ -974,6 +1070,8 @@ __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev) | |||
974 | 1070 | ||
975 | if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) | 1071 | if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) |
976 | return 0; | 1072 | return 0; |
1073 | if (qlcnic_set_eswitch_port_config(adapter)) | ||
1074 | return -EIO; | ||
977 | 1075 | ||
978 | if (qlcnic_fw_create_ctx(adapter)) | 1076 | if (qlcnic_fw_create_ctx(adapter)) |
979 | return -EIO; | 1077 | return -EIO; |
@@ -1291,7 +1389,6 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, | |||
1291 | 1389 | ||
1292 | if (adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO) | 1390 | if (adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO) |
1293 | netdev->features |= NETIF_F_LRO; | 1391 | netdev->features |= NETIF_F_LRO; |
1294 | |||
1295 | netdev->irq = adapter->msix_entries[0].vector; | 1392 | netdev->irq = adapter->msix_entries[0].vector; |
1296 | 1393 | ||
1297 | if (qlcnic_read_mac_addr(adapter)) | 1394 | if (qlcnic_read_mac_addr(adapter)) |
@@ -3216,7 +3313,7 @@ qlcnic_sysfs_write_esw_config(struct file *file, struct kobject *kobj, | |||
3216 | struct qlcnic_esw_func_cfg *esw_cfg; | 3313 | struct qlcnic_esw_func_cfg *esw_cfg; |
3217 | struct qlcnic_npar_info *npar; | 3314 | struct qlcnic_npar_info *npar; |
3218 | int count, rem, i, ret; | 3315 | int count, rem, i, ret; |
3219 | u8 pci_func; | 3316 | u8 pci_func, op_mode = 0; |
3220 | 3317 | ||
3221 | count = size / sizeof(struct qlcnic_esw_func_cfg); | 3318 | count = size / sizeof(struct qlcnic_esw_func_cfg); |
3222 | rem = size % sizeof(struct qlcnic_esw_func_cfg); | 3319 | rem = size % sizeof(struct qlcnic_esw_func_cfg); |
@@ -3229,10 +3326,24 @@ qlcnic_sysfs_write_esw_config(struct file *file, struct kobject *kobj, | |||
3229 | return ret; | 3326 | return ret; |
3230 | 3327 | ||
3231 | for (i = 0; i < count; i++) { | 3328 | for (i = 0; i < count; i++) { |
3232 | if (qlcnic_config_switch_port(adapter, &esw_cfg[i])) | 3329 | if (adapter->op_mode == QLCNIC_MGMT_FUNC) |
3233 | return QL_STATUS_INVALID_PARAM; | 3330 | if (qlcnic_config_switch_port(adapter, &esw_cfg[i])) |
3331 | return QL_STATUS_INVALID_PARAM; | ||
3332 | if (adapter->ahw.pci_func == esw_cfg[i].pci_func) | ||
3333 | op_mode = esw_cfg[i].op_mode; | ||
3334 | qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i]); | ||
3335 | esw_cfg[i].op_mode = op_mode; | ||
3336 | esw_cfg[i].pci_func = adapter->ahw.pci_func; | ||
3337 | switch (esw_cfg[i].op_mode) { | ||
3338 | case QLCNIC_PORT_DEFAULTS: | ||
3339 | qlcnic_set_eswitch_port_features(adapter, | ||
3340 | &esw_cfg[i]); | ||
3341 | break; | ||
3342 | } | ||
3234 | } | 3343 | } |
3235 | 3344 | ||
3345 | if (adapter->op_mode != QLCNIC_MGMT_FUNC) | ||
3346 | goto out; | ||
3236 | for (i = 0; i < count; i++) { | 3347 | for (i = 0; i < count; i++) { |
3237 | pci_func = esw_cfg[i].pci_func; | 3348 | pci_func = esw_cfg[i].pci_func; |
3238 | npar = &adapter->npars[pci_func]; | 3349 | npar = &adapter->npars[pci_func]; |
@@ -3252,7 +3363,7 @@ qlcnic_sysfs_write_esw_config(struct file *file, struct kobject *kobj, | |||
3252 | break; | 3363 | break; |
3253 | } | 3364 | } |
3254 | } | 3365 | } |
3255 | 3366 | out: | |
3256 | return size; | 3367 | return size; |
3257 | } | 3368 | } |
3258 | 3369 | ||