diff options
Diffstat (limited to 'drivers/net/enic')
-rw-r--r-- | drivers/net/enic/Makefile | 2 | ||||
-rw-r--r-- | drivers/net/enic/cq_enet_desc.h | 12 | ||||
-rw-r--r-- | drivers/net/enic/enic.h | 12 | ||||
-rw-r--r-- | drivers/net/enic/enic_main.c | 341 | ||||
-rw-r--r-- | drivers/net/enic/enic_res.c | 5 | ||||
-rw-r--r-- | drivers/net/enic/enic_res.h | 1 | ||||
-rw-r--r-- | drivers/net/enic/vnic_dev.c | 110 | ||||
-rw-r--r-- | drivers/net/enic/vnic_dev.h | 10 | ||||
-rw-r--r-- | drivers/net/enic/vnic_rq.c | 4 | ||||
-rw-r--r-- | drivers/net/enic/vnic_vic.c | 73 | ||||
-rw-r--r-- | drivers/net/enic/vnic_vic.h | 59 | ||||
-rw-r--r-- | drivers/net/enic/vnic_wq.c | 4 |
12 files changed, 583 insertions, 50 deletions
diff --git a/drivers/net/enic/Makefile b/drivers/net/enic/Makefile index 391c3bce5b79..e7b6c31880ba 100644 --- a/drivers/net/enic/Makefile +++ b/drivers/net/enic/Makefile | |||
@@ -1,5 +1,5 @@ | |||
1 | obj-$(CONFIG_ENIC) := enic.o | 1 | obj-$(CONFIG_ENIC) := enic.o |
2 | 2 | ||
3 | enic-y := enic_main.o vnic_cq.o vnic_intr.o vnic_wq.o \ | 3 | enic-y := enic_main.o vnic_cq.o vnic_intr.o vnic_wq.o \ |
4 | enic_res.o vnic_dev.o vnic_rq.o | 4 | enic_res.o vnic_dev.o vnic_rq.o vnic_vic.o |
5 | 5 | ||
diff --git a/drivers/net/enic/cq_enet_desc.h b/drivers/net/enic/cq_enet_desc.h index 03dce9ed612c..337d1943af46 100644 --- a/drivers/net/enic/cq_enet_desc.h +++ b/drivers/net/enic/cq_enet_desc.h | |||
@@ -101,14 +101,18 @@ static inline void cq_enet_rq_desc_dec(struct cq_enet_rq_desc *desc, | |||
101 | u8 *tcp_udp_csum_ok, u8 *udp, u8 *tcp, u8 *ipv4_csum_ok, | 101 | u8 *tcp_udp_csum_ok, u8 *udp, u8 *tcp, u8 *ipv4_csum_ok, |
102 | u8 *ipv6, u8 *ipv4, u8 *ipv4_fragment, u8 *fcs_ok) | 102 | u8 *ipv6, u8 *ipv4, u8 *ipv4_fragment, u8 *fcs_ok) |
103 | { | 103 | { |
104 | u16 completed_index_flags = le16_to_cpu(desc->completed_index_flags); | 104 | u16 completed_index_flags; |
105 | u16 q_number_rss_type_flags = | 105 | u16 q_number_rss_type_flags; |
106 | le16_to_cpu(desc->q_number_rss_type_flags); | 106 | u16 bytes_written_flags; |
107 | u16 bytes_written_flags = le16_to_cpu(desc->bytes_written_flags); | ||
108 | 107 | ||
109 | cq_desc_dec((struct cq_desc *)desc, type, | 108 | cq_desc_dec((struct cq_desc *)desc, type, |
110 | color, q_number, completed_index); | 109 | color, q_number, completed_index); |
111 | 110 | ||
111 | completed_index_flags = le16_to_cpu(desc->completed_index_flags); | ||
112 | q_number_rss_type_flags = | ||
113 | le16_to_cpu(desc->q_number_rss_type_flags); | ||
114 | bytes_written_flags = le16_to_cpu(desc->bytes_written_flags); | ||
115 | |||
112 | *ingress_port = (completed_index_flags & | 116 | *ingress_port = (completed_index_flags & |
113 | CQ_ENET_RQ_DESC_FLAGS_INGRESS_PORT) ? 1 : 0; | 117 | CQ_ENET_RQ_DESC_FLAGS_INGRESS_PORT) ? 1 : 0; |
114 | *fcoe = (completed_index_flags & CQ_ENET_RQ_DESC_FLAGS_FCOE) ? | 118 | *fcoe = (completed_index_flags & CQ_ENET_RQ_DESC_FLAGS_FCOE) ? |
diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h index ee01f5a6d0d4..85f2a2e7030a 100644 --- a/drivers/net/enic/enic.h +++ b/drivers/net/enic/enic.h | |||
@@ -33,8 +33,8 @@ | |||
33 | #include "vnic_rss.h" | 33 | #include "vnic_rss.h" |
34 | 34 | ||
35 | #define DRV_NAME "enic" | 35 | #define DRV_NAME "enic" |
36 | #define DRV_DESCRIPTION "Cisco 10G Ethernet Driver" | 36 | #define DRV_DESCRIPTION "Cisco VIC Ethernet NIC Driver" |
37 | #define DRV_VERSION "1.1.0.241a" | 37 | #define DRV_VERSION "1.3.1.1-pp" |
38 | #define DRV_COPYRIGHT "Copyright 2008-2009 Cisco Systems, Inc" | 38 | #define DRV_COPYRIGHT "Copyright 2008-2009 Cisco Systems, Inc" |
39 | #define PFX DRV_NAME ": " | 39 | #define PFX DRV_NAME ": " |
40 | 40 | ||
@@ -74,6 +74,13 @@ struct enic_msix_entry { | |||
74 | void *devid; | 74 | void *devid; |
75 | }; | 75 | }; |
76 | 76 | ||
77 | struct enic_port_profile { | ||
78 | u8 request; | ||
79 | char name[PORT_PROFILE_MAX]; | ||
80 | u8 instance_uuid[PORT_UUID_MAX]; | ||
81 | u8 host_uuid[PORT_UUID_MAX]; | ||
82 | }; | ||
83 | |||
77 | /* Per-instance private data structure */ | 84 | /* Per-instance private data structure */ |
78 | struct enic { | 85 | struct enic { |
79 | struct net_device *netdev; | 86 | struct net_device *netdev; |
@@ -95,6 +102,7 @@ struct enic { | |||
95 | u32 port_mtu; | 102 | u32 port_mtu; |
96 | u32 rx_coalesce_usecs; | 103 | u32 rx_coalesce_usecs; |
97 | u32 tx_coalesce_usecs; | 104 | u32 tx_coalesce_usecs; |
105 | struct enic_port_profile pp; | ||
98 | 106 | ||
99 | /* work queue cache line section */ | 107 | /* work queue cache line section */ |
100 | ____cacheline_aligned struct vnic_wq wq[ENIC_WQ_MAX]; | 108 | ____cacheline_aligned struct vnic_wq wq[ENIC_WQ_MAX]; |
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index cf098bb636b8..e125113759a5 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/etherdevice.h> | 29 | #include <linux/etherdevice.h> |
30 | #include <linux/if_ether.h> | 30 | #include <linux/if_ether.h> |
31 | #include <linux/if_vlan.h> | 31 | #include <linux/if_vlan.h> |
32 | #include <linux/if_link.h> | ||
32 | #include <linux/ethtool.h> | 33 | #include <linux/ethtool.h> |
33 | #include <linux/in.h> | 34 | #include <linux/in.h> |
34 | #include <linux/ip.h> | 35 | #include <linux/ip.h> |
@@ -40,6 +41,7 @@ | |||
40 | #include "vnic_dev.h" | 41 | #include "vnic_dev.h" |
41 | #include "vnic_intr.h" | 42 | #include "vnic_intr.h" |
42 | #include "vnic_stats.h" | 43 | #include "vnic_stats.h" |
44 | #include "vnic_vic.h" | ||
43 | #include "enic_res.h" | 45 | #include "enic_res.h" |
44 | #include "enic.h" | 46 | #include "enic.h" |
45 | 47 | ||
@@ -49,10 +51,12 @@ | |||
49 | #define ENIC_DESC_MAX_SPLITS (MAX_TSO / WQ_ENET_MAX_DESC_LEN + 1) | 51 | #define ENIC_DESC_MAX_SPLITS (MAX_TSO / WQ_ENET_MAX_DESC_LEN + 1) |
50 | 52 | ||
51 | #define PCI_DEVICE_ID_CISCO_VIC_ENET 0x0043 /* ethernet vnic */ | 53 | #define PCI_DEVICE_ID_CISCO_VIC_ENET 0x0043 /* ethernet vnic */ |
54 | #define PCI_DEVICE_ID_CISCO_VIC_ENET_DYN 0x0044 /* enet dynamic vnic */ | ||
52 | 55 | ||
53 | /* Supported devices */ | 56 | /* Supported devices */ |
54 | static DEFINE_PCI_DEVICE_TABLE(enic_id_table) = { | 57 | static DEFINE_PCI_DEVICE_TABLE(enic_id_table) = { |
55 | { PCI_VDEVICE(CISCO, PCI_DEVICE_ID_CISCO_VIC_ENET) }, | 58 | { PCI_VDEVICE(CISCO, PCI_DEVICE_ID_CISCO_VIC_ENET) }, |
59 | { PCI_VDEVICE(CISCO, PCI_DEVICE_ID_CISCO_VIC_ENET_DYN) }, | ||
56 | { 0, } /* end of table */ | 60 | { 0, } /* end of table */ |
57 | }; | 61 | }; |
58 | 62 | ||
@@ -113,6 +117,11 @@ static const struct enic_stat enic_rx_stats[] = { | |||
113 | static const unsigned int enic_n_tx_stats = ARRAY_SIZE(enic_tx_stats); | 117 | static const unsigned int enic_n_tx_stats = ARRAY_SIZE(enic_tx_stats); |
114 | static const unsigned int enic_n_rx_stats = ARRAY_SIZE(enic_rx_stats); | 118 | static const unsigned int enic_n_rx_stats = ARRAY_SIZE(enic_rx_stats); |
115 | 119 | ||
120 | static int enic_is_dynamic(struct enic *enic) | ||
121 | { | ||
122 | return enic->pdev->device == PCI_DEVICE_ID_CISCO_VIC_ENET_DYN; | ||
123 | } | ||
124 | |||
116 | static int enic_get_settings(struct net_device *netdev, | 125 | static int enic_get_settings(struct net_device *netdev, |
117 | struct ethtool_cmd *ecmd) | 126 | struct ethtool_cmd *ecmd) |
118 | { | 127 | { |
@@ -810,26 +819,90 @@ static void enic_reset_mcaddrs(struct enic *enic) | |||
810 | 819 | ||
811 | static int enic_set_mac_addr(struct net_device *netdev, char *addr) | 820 | static int enic_set_mac_addr(struct net_device *netdev, char *addr) |
812 | { | 821 | { |
813 | if (!is_valid_ether_addr(addr)) | 822 | struct enic *enic = netdev_priv(netdev); |
814 | return -EADDRNOTAVAIL; | 823 | |
824 | if (enic_is_dynamic(enic)) { | ||
825 | if (!is_valid_ether_addr(addr) && !is_zero_ether_addr(addr)) | ||
826 | return -EADDRNOTAVAIL; | ||
827 | } else { | ||
828 | if (!is_valid_ether_addr(addr)) | ||
829 | return -EADDRNOTAVAIL; | ||
830 | } | ||
815 | 831 | ||
816 | memcpy(netdev->dev_addr, addr, netdev->addr_len); | 832 | memcpy(netdev->dev_addr, addr, netdev->addr_len); |
817 | 833 | ||
818 | return 0; | 834 | return 0; |
819 | } | 835 | } |
820 | 836 | ||
837 | static int enic_dev_add_station_addr(struct enic *enic) | ||
838 | { | ||
839 | int err = 0; | ||
840 | |||
841 | if (is_valid_ether_addr(enic->netdev->dev_addr)) { | ||
842 | spin_lock(&enic->devcmd_lock); | ||
843 | err = vnic_dev_add_addr(enic->vdev, enic->netdev->dev_addr); | ||
844 | spin_unlock(&enic->devcmd_lock); | ||
845 | } | ||
846 | |||
847 | return err; | ||
848 | } | ||
849 | |||
850 | static int enic_dev_del_station_addr(struct enic *enic) | ||
851 | { | ||
852 | int err = 0; | ||
853 | |||
854 | if (is_valid_ether_addr(enic->netdev->dev_addr)) { | ||
855 | spin_lock(&enic->devcmd_lock); | ||
856 | err = vnic_dev_del_addr(enic->vdev, enic->netdev->dev_addr); | ||
857 | spin_unlock(&enic->devcmd_lock); | ||
858 | } | ||
859 | |||
860 | return err; | ||
861 | } | ||
862 | |||
863 | static int enic_set_mac_address_dynamic(struct net_device *netdev, void *p) | ||
864 | { | ||
865 | struct enic *enic = netdev_priv(netdev); | ||
866 | struct sockaddr *saddr = p; | ||
867 | char *addr = saddr->sa_data; | ||
868 | int err; | ||
869 | |||
870 | if (netif_running(enic->netdev)) { | ||
871 | err = enic_dev_del_station_addr(enic); | ||
872 | if (err) | ||
873 | return err; | ||
874 | } | ||
875 | |||
876 | err = enic_set_mac_addr(netdev, addr); | ||
877 | if (err) | ||
878 | return err; | ||
879 | |||
880 | if (netif_running(enic->netdev)) { | ||
881 | err = enic_dev_add_station_addr(enic); | ||
882 | if (err) | ||
883 | return err; | ||
884 | } | ||
885 | |||
886 | return err; | ||
887 | } | ||
888 | |||
889 | static int enic_set_mac_address(struct net_device *netdev, void *p) | ||
890 | { | ||
891 | return -EOPNOTSUPP; | ||
892 | } | ||
893 | |||
821 | /* netif_tx_lock held, BHs disabled */ | 894 | /* netif_tx_lock held, BHs disabled */ |
822 | static void enic_set_multicast_list(struct net_device *netdev) | 895 | static void enic_set_multicast_list(struct net_device *netdev) |
823 | { | 896 | { |
824 | struct enic *enic = netdev_priv(netdev); | 897 | struct enic *enic = netdev_priv(netdev); |
825 | struct dev_mc_list *list; | 898 | struct netdev_hw_addr *ha; |
826 | int directed = 1; | 899 | int directed = 1; |
827 | int multicast = (netdev->flags & IFF_MULTICAST) ? 1 : 0; | 900 | int multicast = (netdev->flags & IFF_MULTICAST) ? 1 : 0; |
828 | int broadcast = (netdev->flags & IFF_BROADCAST) ? 1 : 0; | 901 | int broadcast = (netdev->flags & IFF_BROADCAST) ? 1 : 0; |
829 | int promisc = (netdev->flags & IFF_PROMISC) ? 1 : 0; | 902 | int promisc = (netdev->flags & IFF_PROMISC) ? 1 : 0; |
830 | unsigned int mc_count = netdev_mc_count(netdev); | 903 | unsigned int mc_count = netdev_mc_count(netdev); |
831 | int allmulti = (netdev->flags & IFF_ALLMULTI) || | 904 | int allmulti = (netdev->flags & IFF_ALLMULTI) || |
832 | mc_count > ENIC_MULTICAST_PERFECT_FILTERS; | 905 | mc_count > ENIC_MULTICAST_PERFECT_FILTERS; |
833 | unsigned int flags = netdev->flags | (allmulti ? IFF_ALLMULTI : 0); | 906 | unsigned int flags = netdev->flags | (allmulti ? IFF_ALLMULTI : 0); |
834 | u8 mc_addr[ENIC_MULTICAST_PERFECT_FILTERS][ETH_ALEN]; | 907 | u8 mc_addr[ENIC_MULTICAST_PERFECT_FILTERS][ETH_ALEN]; |
835 | unsigned int i, j; | 908 | unsigned int i, j; |
@@ -852,10 +925,10 @@ static void enic_set_multicast_list(struct net_device *netdev) | |||
852 | */ | 925 | */ |
853 | 926 | ||
854 | i = 0; | 927 | i = 0; |
855 | netdev_for_each_mc_addr(list, netdev) { | 928 | netdev_for_each_mc_addr(ha, netdev) { |
856 | if (i == mc_count) | 929 | if (i == mc_count) |
857 | break; | 930 | break; |
858 | memcpy(mc_addr[i++], list->dmi_addr, ETH_ALEN); | 931 | memcpy(mc_addr[i++], ha->addr, ETH_ALEN); |
859 | } | 932 | } |
860 | 933 | ||
861 | for (i = 0; i < enic->mc_count; i++) { | 934 | for (i = 0; i < enic->mc_count; i++) { |
@@ -922,6 +995,213 @@ static void enic_tx_timeout(struct net_device *netdev) | |||
922 | schedule_work(&enic->reset); | 995 | schedule_work(&enic->reset); |
923 | } | 996 | } |
924 | 997 | ||
998 | static int enic_vnic_dev_deinit(struct enic *enic) | ||
999 | { | ||
1000 | int err; | ||
1001 | |||
1002 | spin_lock(&enic->devcmd_lock); | ||
1003 | err = vnic_dev_deinit(enic->vdev); | ||
1004 | spin_unlock(&enic->devcmd_lock); | ||
1005 | |||
1006 | return err; | ||
1007 | } | ||
1008 | |||
1009 | static int enic_dev_init_prov(struct enic *enic, struct vic_provinfo *vp) | ||
1010 | { | ||
1011 | int err; | ||
1012 | |||
1013 | spin_lock(&enic->devcmd_lock); | ||
1014 | err = vnic_dev_init_prov(enic->vdev, | ||
1015 | (u8 *)vp, vic_provinfo_size(vp)); | ||
1016 | spin_unlock(&enic->devcmd_lock); | ||
1017 | |||
1018 | return err; | ||
1019 | } | ||
1020 | |||
1021 | static int enic_dev_init_done(struct enic *enic, int *done, int *error) | ||
1022 | { | ||
1023 | int err; | ||
1024 | |||
1025 | spin_lock(&enic->devcmd_lock); | ||
1026 | err = vnic_dev_init_done(enic->vdev, done, error); | ||
1027 | spin_unlock(&enic->devcmd_lock); | ||
1028 | |||
1029 | return err; | ||
1030 | } | ||
1031 | |||
1032 | static int enic_set_port_profile(struct enic *enic, u8 request, u8 *mac, | ||
1033 | char *name, u8 *instance_uuid, u8 *host_uuid) | ||
1034 | { | ||
1035 | struct vic_provinfo *vp; | ||
1036 | u8 oui[3] = VIC_PROVINFO_CISCO_OUI; | ||
1037 | unsigned short *uuid; | ||
1038 | char uuid_str[38]; | ||
1039 | static char *uuid_fmt = "%04X%04X-%04X-%04X-%04X-%04X%04X%04X"; | ||
1040 | int err; | ||
1041 | |||
1042 | if (!name) | ||
1043 | return -EINVAL; | ||
1044 | |||
1045 | if (!is_valid_ether_addr(mac)) | ||
1046 | return -EADDRNOTAVAIL; | ||
1047 | |||
1048 | vp = vic_provinfo_alloc(GFP_KERNEL, oui, VIC_PROVINFO_LINUX_TYPE); | ||
1049 | if (!vp) | ||
1050 | return -ENOMEM; | ||
1051 | |||
1052 | vic_provinfo_add_tlv(vp, | ||
1053 | VIC_LINUX_PROV_TLV_PORT_PROFILE_NAME_STR, | ||
1054 | strlen(name) + 1, name); | ||
1055 | |||
1056 | vic_provinfo_add_tlv(vp, | ||
1057 | VIC_LINUX_PROV_TLV_CLIENT_MAC_ADDR, | ||
1058 | ETH_ALEN, mac); | ||
1059 | |||
1060 | if (instance_uuid) { | ||
1061 | uuid = (unsigned short *)instance_uuid; | ||
1062 | sprintf(uuid_str, uuid_fmt, | ||
1063 | uuid[0], uuid[1], uuid[2], uuid[3], | ||
1064 | uuid[4], uuid[5], uuid[6], uuid[7]); | ||
1065 | vic_provinfo_add_tlv(vp, | ||
1066 | VIC_LINUX_PROV_TLV_CLIENT_UUID_STR, | ||
1067 | sizeof(uuid_str), uuid_str); | ||
1068 | } | ||
1069 | |||
1070 | if (host_uuid) { | ||
1071 | uuid = (unsigned short *)host_uuid; | ||
1072 | sprintf(uuid_str, uuid_fmt, | ||
1073 | uuid[0], uuid[1], uuid[2], uuid[3], | ||
1074 | uuid[4], uuid[5], uuid[6], uuid[7]); | ||
1075 | vic_provinfo_add_tlv(vp, | ||
1076 | VIC_LINUX_PROV_TLV_HOST_UUID_STR, | ||
1077 | sizeof(uuid_str), uuid_str); | ||
1078 | } | ||
1079 | |||
1080 | err = enic_vnic_dev_deinit(enic); | ||
1081 | if (err) | ||
1082 | goto err_out; | ||
1083 | |||
1084 | memset(&enic->pp, 0, sizeof(enic->pp)); | ||
1085 | |||
1086 | err = enic_dev_init_prov(enic, vp); | ||
1087 | if (err) | ||
1088 | goto err_out; | ||
1089 | |||
1090 | enic->pp.request = request; | ||
1091 | memcpy(enic->pp.name, name, PORT_PROFILE_MAX); | ||
1092 | if (instance_uuid) | ||
1093 | memcpy(enic->pp.instance_uuid, | ||
1094 | instance_uuid, PORT_UUID_MAX); | ||
1095 | if (host_uuid) | ||
1096 | memcpy(enic->pp.host_uuid, | ||
1097 | host_uuid, PORT_UUID_MAX); | ||
1098 | |||
1099 | err_out: | ||
1100 | vic_provinfo_free(vp); | ||
1101 | |||
1102 | return err; | ||
1103 | } | ||
1104 | |||
1105 | static int enic_unset_port_profile(struct enic *enic) | ||
1106 | { | ||
1107 | memset(&enic->pp, 0, sizeof(enic->pp)); | ||
1108 | return enic_vnic_dev_deinit(enic); | ||
1109 | } | ||
1110 | |||
1111 | static int enic_set_vf_port(struct net_device *netdev, int vf, | ||
1112 | struct nlattr *port[]) | ||
1113 | { | ||
1114 | struct enic *enic = netdev_priv(netdev); | ||
1115 | char *name = NULL; | ||
1116 | u8 *instance_uuid = NULL; | ||
1117 | u8 *host_uuid = NULL; | ||
1118 | u8 request = PORT_REQUEST_DISASSOCIATE; | ||
1119 | |||
1120 | /* don't support VFs, yet */ | ||
1121 | if (vf != PORT_SELF_VF) | ||
1122 | return -EOPNOTSUPP; | ||
1123 | |||
1124 | if (port[IFLA_PORT_REQUEST]) | ||
1125 | request = nla_get_u8(port[IFLA_PORT_REQUEST]); | ||
1126 | |||
1127 | switch (request) { | ||
1128 | case PORT_REQUEST_ASSOCIATE: | ||
1129 | |||
1130 | if (port[IFLA_PORT_PROFILE]) | ||
1131 | name = nla_data(port[IFLA_PORT_PROFILE]); | ||
1132 | |||
1133 | if (port[IFLA_PORT_INSTANCE_UUID]) | ||
1134 | instance_uuid = | ||
1135 | nla_data(port[IFLA_PORT_INSTANCE_UUID]); | ||
1136 | |||
1137 | if (port[IFLA_PORT_HOST_UUID]) | ||
1138 | host_uuid = nla_data(port[IFLA_PORT_HOST_UUID]); | ||
1139 | |||
1140 | return enic_set_port_profile(enic, request, | ||
1141 | netdev->dev_addr, name, | ||
1142 | instance_uuid, host_uuid); | ||
1143 | |||
1144 | case PORT_REQUEST_DISASSOCIATE: | ||
1145 | |||
1146 | return enic_unset_port_profile(enic); | ||
1147 | |||
1148 | default: | ||
1149 | break; | ||
1150 | } | ||
1151 | |||
1152 | return -EOPNOTSUPP; | ||
1153 | } | ||
1154 | |||
1155 | static int enic_get_vf_port(struct net_device *netdev, int vf, | ||
1156 | struct sk_buff *skb) | ||
1157 | { | ||
1158 | struct enic *enic = netdev_priv(netdev); | ||
1159 | int err, error, done; | ||
1160 | u16 response = PORT_PROFILE_RESPONSE_SUCCESS; | ||
1161 | |||
1162 | /* don't support VFs, yet */ | ||
1163 | if (vf != PORT_SELF_VF) | ||
1164 | return -EOPNOTSUPP; | ||
1165 | |||
1166 | err = enic_dev_init_done(enic, &done, &error); | ||
1167 | |||
1168 | if (err) | ||
1169 | return err; | ||
1170 | |||
1171 | switch (error) { | ||
1172 | case ERR_SUCCESS: | ||
1173 | if (!done) | ||
1174 | response = PORT_PROFILE_RESPONSE_INPROGRESS; | ||
1175 | break; | ||
1176 | case ERR_EINVAL: | ||
1177 | response = PORT_PROFILE_RESPONSE_INVALID; | ||
1178 | break; | ||
1179 | case ERR_EBADSTATE: | ||
1180 | response = PORT_PROFILE_RESPONSE_BADSTATE; | ||
1181 | break; | ||
1182 | case ERR_ENOMEM: | ||
1183 | response = PORT_PROFILE_RESPONSE_INSUFFICIENT_RESOURCES; | ||
1184 | break; | ||
1185 | default: | ||
1186 | response = PORT_PROFILE_RESPONSE_ERROR; | ||
1187 | break; | ||
1188 | } | ||
1189 | |||
1190 | NLA_PUT_U16(skb, IFLA_PORT_REQUEST, enic->pp.request); | ||
1191 | NLA_PUT_U16(skb, IFLA_PORT_RESPONSE, response); | ||
1192 | NLA_PUT(skb, IFLA_PORT_PROFILE, PORT_PROFILE_MAX, | ||
1193 | enic->pp.name); | ||
1194 | NLA_PUT(skb, IFLA_PORT_INSTANCE_UUID, PORT_UUID_MAX, | ||
1195 | enic->pp.instance_uuid); | ||
1196 | NLA_PUT(skb, IFLA_PORT_HOST_UUID, PORT_UUID_MAX, | ||
1197 | enic->pp.host_uuid); | ||
1198 | |||
1199 | return 0; | ||
1200 | |||
1201 | nla_put_failure: | ||
1202 | return -EMSGSIZE; | ||
1203 | } | ||
1204 | |||
925 | static void enic_free_rq_buf(struct vnic_rq *rq, struct vnic_rq_buf *buf) | 1205 | static void enic_free_rq_buf(struct vnic_rq *rq, struct vnic_rq_buf *buf) |
926 | { | 1206 | { |
927 | struct enic *enic = vnic_dev_priv(rq->vdev); | 1207 | struct enic *enic = vnic_dev_priv(rq->vdev); |
@@ -1440,9 +1720,7 @@ static int enic_open(struct net_device *netdev) | |||
1440 | for (i = 0; i < enic->rq_count; i++) | 1720 | for (i = 0; i < enic->rq_count; i++) |
1441 | vnic_rq_enable(&enic->rq[i]); | 1721 | vnic_rq_enable(&enic->rq[i]); |
1442 | 1722 | ||
1443 | spin_lock(&enic->devcmd_lock); | 1723 | enic_dev_add_station_addr(enic); |
1444 | enic_add_station_addr(enic); | ||
1445 | spin_unlock(&enic->devcmd_lock); | ||
1446 | enic_set_multicast_list(netdev); | 1724 | enic_set_multicast_list(netdev); |
1447 | 1725 | ||
1448 | netif_wake_queue(netdev); | 1726 | netif_wake_queue(netdev); |
@@ -1489,6 +1767,8 @@ static int enic_stop(struct net_device *netdev) | |||
1489 | netif_carrier_off(netdev); | 1767 | netif_carrier_off(netdev); |
1490 | netif_tx_disable(netdev); | 1768 | netif_tx_disable(netdev); |
1491 | 1769 | ||
1770 | enic_dev_del_station_addr(enic); | ||
1771 | |||
1492 | for (i = 0; i < enic->wq_count; i++) { | 1772 | for (i = 0; i < enic->wq_count; i++) { |
1493 | err = vnic_wq_disable(&enic->wq[i]); | 1773 | err = vnic_wq_disable(&enic->wq[i]); |
1494 | if (err) | 1774 | if (err) |
@@ -1774,14 +2054,34 @@ static void enic_clear_intr_mode(struct enic *enic) | |||
1774 | vnic_dev_set_intr_mode(enic->vdev, VNIC_DEV_INTR_MODE_UNKNOWN); | 2054 | vnic_dev_set_intr_mode(enic->vdev, VNIC_DEV_INTR_MODE_UNKNOWN); |
1775 | } | 2055 | } |
1776 | 2056 | ||
2057 | static const struct net_device_ops enic_netdev_dynamic_ops = { | ||
2058 | .ndo_open = enic_open, | ||
2059 | .ndo_stop = enic_stop, | ||
2060 | .ndo_start_xmit = enic_hard_start_xmit, | ||
2061 | .ndo_get_stats = enic_get_stats, | ||
2062 | .ndo_validate_addr = eth_validate_addr, | ||
2063 | .ndo_set_multicast_list = enic_set_multicast_list, | ||
2064 | .ndo_set_mac_address = enic_set_mac_address_dynamic, | ||
2065 | .ndo_change_mtu = enic_change_mtu, | ||
2066 | .ndo_vlan_rx_register = enic_vlan_rx_register, | ||
2067 | .ndo_vlan_rx_add_vid = enic_vlan_rx_add_vid, | ||
2068 | .ndo_vlan_rx_kill_vid = enic_vlan_rx_kill_vid, | ||
2069 | .ndo_tx_timeout = enic_tx_timeout, | ||
2070 | .ndo_set_vf_port = enic_set_vf_port, | ||
2071 | .ndo_get_vf_port = enic_get_vf_port, | ||
2072 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
2073 | .ndo_poll_controller = enic_poll_controller, | ||
2074 | #endif | ||
2075 | }; | ||
2076 | |||
1777 | static const struct net_device_ops enic_netdev_ops = { | 2077 | static const struct net_device_ops enic_netdev_ops = { |
1778 | .ndo_open = enic_open, | 2078 | .ndo_open = enic_open, |
1779 | .ndo_stop = enic_stop, | 2079 | .ndo_stop = enic_stop, |
1780 | .ndo_start_xmit = enic_hard_start_xmit, | 2080 | .ndo_start_xmit = enic_hard_start_xmit, |
1781 | .ndo_get_stats = enic_get_stats, | 2081 | .ndo_get_stats = enic_get_stats, |
1782 | .ndo_validate_addr = eth_validate_addr, | 2082 | .ndo_validate_addr = eth_validate_addr, |
1783 | .ndo_set_mac_address = eth_mac_addr, | ||
1784 | .ndo_set_multicast_list = enic_set_multicast_list, | 2083 | .ndo_set_multicast_list = enic_set_multicast_list, |
2084 | .ndo_set_mac_address = enic_set_mac_address, | ||
1785 | .ndo_change_mtu = enic_change_mtu, | 2085 | .ndo_change_mtu = enic_change_mtu, |
1786 | .ndo_vlan_rx_register = enic_vlan_rx_register, | 2086 | .ndo_vlan_rx_register = enic_vlan_rx_register, |
1787 | .ndo_vlan_rx_add_vid = enic_vlan_rx_add_vid, | 2087 | .ndo_vlan_rx_add_vid = enic_vlan_rx_add_vid, |
@@ -2010,11 +2310,13 @@ static int __devinit enic_probe(struct pci_dev *pdev, | |||
2010 | 2310 | ||
2011 | netif_carrier_off(netdev); | 2311 | netif_carrier_off(netdev); |
2012 | 2312 | ||
2013 | err = vnic_dev_init(enic->vdev, 0); | 2313 | if (!enic_is_dynamic(enic)) { |
2014 | if (err) { | 2314 | err = vnic_dev_init(enic->vdev, 0); |
2015 | printk(KERN_ERR PFX | 2315 | if (err) { |
2016 | "vNIC dev init failed, aborting.\n"); | 2316 | printk(KERN_ERR PFX |
2017 | goto err_out_dev_close; | 2317 | "vNIC dev init failed, aborting.\n"); |
2318 | goto err_out_dev_close; | ||
2319 | } | ||
2018 | } | 2320 | } |
2019 | 2321 | ||
2020 | err = enic_dev_init(enic); | 2322 | err = enic_dev_init(enic); |
@@ -2054,12 +2356,15 @@ static int __devinit enic_probe(struct pci_dev *pdev, | |||
2054 | enic->tx_coalesce_usecs = enic->config.intr_timer_usec; | 2356 | enic->tx_coalesce_usecs = enic->config.intr_timer_usec; |
2055 | enic->rx_coalesce_usecs = enic->tx_coalesce_usecs; | 2357 | enic->rx_coalesce_usecs = enic->tx_coalesce_usecs; |
2056 | 2358 | ||
2057 | netdev->netdev_ops = &enic_netdev_ops; | 2359 | if (enic_is_dynamic(enic)) |
2360 | netdev->netdev_ops = &enic_netdev_dynamic_ops; | ||
2361 | else | ||
2362 | netdev->netdev_ops = &enic_netdev_ops; | ||
2363 | |||
2058 | netdev->watchdog_timeo = 2 * HZ; | 2364 | netdev->watchdog_timeo = 2 * HZ; |
2059 | netdev->ethtool_ops = &enic_ethtool_ops; | 2365 | netdev->ethtool_ops = &enic_ethtool_ops; |
2060 | 2366 | ||
2061 | netdev->features |= NETIF_F_HW_VLAN_TX | | 2367 | netdev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; |
2062 | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER; | ||
2063 | if (ENIC_SETTING(enic, TXCSUM)) | 2368 | if (ENIC_SETTING(enic, TXCSUM)) |
2064 | netdev->features |= NETIF_F_SG | NETIF_F_HW_CSUM; | 2369 | netdev->features |= NETIF_F_SG | NETIF_F_HW_CSUM; |
2065 | if (ENIC_SETTING(enic, TSO)) | 2370 | if (ENIC_SETTING(enic, TSO)) |
diff --git a/drivers/net/enic/enic_res.c b/drivers/net/enic/enic_res.c index 02839bf0fe8b..9b18840cba96 100644 --- a/drivers/net/enic/enic_res.c +++ b/drivers/net/enic/enic_res.c | |||
@@ -103,11 +103,6 @@ int enic_get_vnic_config(struct enic *enic) | |||
103 | return 0; | 103 | return 0; |
104 | } | 104 | } |
105 | 105 | ||
106 | void enic_add_station_addr(struct enic *enic) | ||
107 | { | ||
108 | vnic_dev_add_addr(enic->vdev, enic->mac_addr); | ||
109 | } | ||
110 | |||
111 | void enic_add_multicast_addr(struct enic *enic, u8 *addr) | 106 | void enic_add_multicast_addr(struct enic *enic, u8 *addr) |
112 | { | 107 | { |
113 | vnic_dev_add_addr(enic->vdev, addr); | 108 | vnic_dev_add_addr(enic->vdev, addr); |
diff --git a/drivers/net/enic/enic_res.h b/drivers/net/enic/enic_res.h index abc19741ab02..494664f7fccc 100644 --- a/drivers/net/enic/enic_res.h +++ b/drivers/net/enic/enic_res.h | |||
@@ -131,7 +131,6 @@ static inline void enic_queue_rq_desc(struct vnic_rq *rq, | |||
131 | struct enic; | 131 | struct enic; |
132 | 132 | ||
133 | int enic_get_vnic_config(struct enic *); | 133 | int enic_get_vnic_config(struct enic *); |
134 | void enic_add_station_addr(struct enic *enic); | ||
135 | void enic_add_multicast_addr(struct enic *enic, u8 *addr); | 134 | void enic_add_multicast_addr(struct enic *enic, u8 *addr); |
136 | void enic_del_multicast_addr(struct enic *enic, u8 *addr); | 135 | void enic_del_multicast_addr(struct enic *enic, u8 *addr); |
137 | void enic_add_vlan(struct enic *enic, u16 vlanid); | 136 | void enic_add_vlan(struct enic *enic, u16 vlanid); |
diff --git a/drivers/net/enic/vnic_dev.c b/drivers/net/enic/vnic_dev.c index cf22de71014e..2b3e16db5c82 100644 --- a/drivers/net/enic/vnic_dev.c +++ b/drivers/net/enic/vnic_dev.c | |||
@@ -530,7 +530,7 @@ void vnic_dev_packet_filter(struct vnic_dev *vdev, int directed, int multicast, | |||
530 | printk(KERN_ERR "Can't set packet filter\n"); | 530 | printk(KERN_ERR "Can't set packet filter\n"); |
531 | } | 531 | } |
532 | 532 | ||
533 | void vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr) | 533 | int vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr) |
534 | { | 534 | { |
535 | u64 a0 = 0, a1 = 0; | 535 | u64 a0 = 0, a1 = 0; |
536 | int wait = 1000; | 536 | int wait = 1000; |
@@ -543,9 +543,11 @@ void vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr) | |||
543 | err = vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait); | 543 | err = vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait); |
544 | if (err) | 544 | if (err) |
545 | printk(KERN_ERR "Can't add addr [%pM], %d\n", addr, err); | 545 | printk(KERN_ERR "Can't add addr [%pM], %d\n", addr, err); |
546 | |||
547 | return err; | ||
546 | } | 548 | } |
547 | 549 | ||
548 | void vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr) | 550 | int vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr) |
549 | { | 551 | { |
550 | u64 a0 = 0, a1 = 0; | 552 | u64 a0 = 0, a1 = 0; |
551 | int wait = 1000; | 553 | int wait = 1000; |
@@ -558,6 +560,8 @@ void vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr) | |||
558 | err = vnic_dev_cmd(vdev, CMD_ADDR_DEL, &a0, &a1, wait); | 560 | err = vnic_dev_cmd(vdev, CMD_ADDR_DEL, &a0, &a1, wait); |
559 | if (err) | 561 | if (err) |
560 | printk(KERN_ERR "Can't del addr [%pM], %d\n", addr, err); | 562 | printk(KERN_ERR "Can't del addr [%pM], %d\n", addr, err); |
563 | |||
564 | return err; | ||
561 | } | 565 | } |
562 | 566 | ||
563 | int vnic_dev_raise_intr(struct vnic_dev *vdev, u16 intr) | 567 | int vnic_dev_raise_intr(struct vnic_dev *vdev, u16 intr) |
@@ -574,22 +578,18 @@ int vnic_dev_raise_intr(struct vnic_dev *vdev, u16 intr) | |||
574 | return err; | 578 | return err; |
575 | } | 579 | } |
576 | 580 | ||
577 | int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr) | 581 | int vnic_dev_notify_setcmd(struct vnic_dev *vdev, |
582 | void *notify_addr, dma_addr_t notify_pa, u16 intr) | ||
578 | { | 583 | { |
579 | u64 a0, a1; | 584 | u64 a0, a1; |
580 | int wait = 1000; | 585 | int wait = 1000; |
581 | int r; | 586 | int r; |
582 | 587 | ||
583 | if (!vdev->notify) { | 588 | memset(notify_addr, 0, sizeof(struct vnic_devcmd_notify)); |
584 | vdev->notify = pci_alloc_consistent(vdev->pdev, | 589 | vdev->notify = notify_addr; |
585 | sizeof(struct vnic_devcmd_notify), | 590 | vdev->notify_pa = notify_pa; |
586 | &vdev->notify_pa); | ||
587 | if (!vdev->notify) | ||
588 | return -ENOMEM; | ||
589 | memset(vdev->notify, 0, sizeof(struct vnic_devcmd_notify)); | ||
590 | } | ||
591 | 591 | ||
592 | a0 = vdev->notify_pa; | 592 | a0 = (u64)notify_pa; |
593 | a1 = ((u64)intr << 32) & 0x0000ffff00000000ULL; | 593 | a1 = ((u64)intr << 32) & 0x0000ffff00000000ULL; |
594 | a1 += sizeof(struct vnic_devcmd_notify); | 594 | a1 += sizeof(struct vnic_devcmd_notify); |
595 | 595 | ||
@@ -598,7 +598,27 @@ int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr) | |||
598 | return r; | 598 | return r; |
599 | } | 599 | } |
600 | 600 | ||
601 | void vnic_dev_notify_unset(struct vnic_dev *vdev) | 601 | int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr) |
602 | { | ||
603 | void *notify_addr; | ||
604 | dma_addr_t notify_pa; | ||
605 | |||
606 | if (vdev->notify || vdev->notify_pa) { | ||
607 | printk(KERN_ERR "notify block %p still allocated", | ||
608 | vdev->notify); | ||
609 | return -EINVAL; | ||
610 | } | ||
611 | |||
612 | notify_addr = pci_alloc_consistent(vdev->pdev, | ||
613 | sizeof(struct vnic_devcmd_notify), | ||
614 | ¬ify_pa); | ||
615 | if (!notify_addr) | ||
616 | return -ENOMEM; | ||
617 | |||
618 | return vnic_dev_notify_setcmd(vdev, notify_addr, notify_pa, intr); | ||
619 | } | ||
620 | |||
621 | void vnic_dev_notify_unsetcmd(struct vnic_dev *vdev) | ||
602 | { | 622 | { |
603 | u64 a0, a1; | 623 | u64 a0, a1; |
604 | int wait = 1000; | 624 | int wait = 1000; |
@@ -608,9 +628,23 @@ void vnic_dev_notify_unset(struct vnic_dev *vdev) | |||
608 | a1 += sizeof(struct vnic_devcmd_notify); | 628 | a1 += sizeof(struct vnic_devcmd_notify); |
609 | 629 | ||
610 | vnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait); | 630 | vnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait); |
631 | vdev->notify = NULL; | ||
632 | vdev->notify_pa = 0; | ||
611 | vdev->notify_sz = 0; | 633 | vdev->notify_sz = 0; |
612 | } | 634 | } |
613 | 635 | ||
636 | void vnic_dev_notify_unset(struct vnic_dev *vdev) | ||
637 | { | ||
638 | if (vdev->notify) { | ||
639 | pci_free_consistent(vdev->pdev, | ||
640 | sizeof(struct vnic_devcmd_notify), | ||
641 | vdev->notify, | ||
642 | vdev->notify_pa); | ||
643 | } | ||
644 | |||
645 | vnic_dev_notify_unsetcmd(vdev); | ||
646 | } | ||
647 | |||
614 | static int vnic_dev_notify_ready(struct vnic_dev *vdev) | 648 | static int vnic_dev_notify_ready(struct vnic_dev *vdev) |
615 | { | 649 | { |
616 | u32 *words; | 650 | u32 *words; |
@@ -652,6 +686,56 @@ int vnic_dev_init(struct vnic_dev *vdev, int arg) | |||
652 | return r; | 686 | return r; |
653 | } | 687 | } |
654 | 688 | ||
689 | int vnic_dev_init_done(struct vnic_dev *vdev, int *done, int *err) | ||
690 | { | ||
691 | u64 a0 = 0, a1 = 0; | ||
692 | int wait = 1000; | ||
693 | int ret; | ||
694 | |||
695 | *done = 0; | ||
696 | |||
697 | ret = vnic_dev_cmd(vdev, CMD_INIT_STATUS, &a0, &a1, wait); | ||
698 | if (ret) | ||
699 | return ret; | ||
700 | |||
701 | *done = (a0 == 0); | ||
702 | |||
703 | *err = (a0 == 0) ? a1 : 0; | ||
704 | |||
705 | return 0; | ||
706 | } | ||
707 | |||
708 | int vnic_dev_init_prov(struct vnic_dev *vdev, u8 *buf, u32 len) | ||
709 | { | ||
710 | u64 a0, a1 = len; | ||
711 | int wait = 1000; | ||
712 | u64 prov_pa; | ||
713 | void *prov_buf; | ||
714 | int ret; | ||
715 | |||
716 | prov_buf = pci_alloc_consistent(vdev->pdev, len, &prov_pa); | ||
717 | if (!prov_buf) | ||
718 | return -ENOMEM; | ||
719 | |||
720 | memcpy(prov_buf, buf, len); | ||
721 | |||
722 | a0 = prov_pa; | ||
723 | |||
724 | ret = vnic_dev_cmd(vdev, CMD_INIT_PROV_INFO, &a0, &a1, wait); | ||
725 | |||
726 | pci_free_consistent(vdev->pdev, len, prov_buf, prov_pa); | ||
727 | |||
728 | return ret; | ||
729 | } | ||
730 | |||
731 | int vnic_dev_deinit(struct vnic_dev *vdev) | ||
732 | { | ||
733 | u64 a0 = 0, a1 = 0; | ||
734 | int wait = 1000; | ||
735 | |||
736 | return vnic_dev_cmd(vdev, CMD_DEINIT, &a0, &a1, wait); | ||
737 | } | ||
738 | |||
655 | int vnic_dev_link_status(struct vnic_dev *vdev) | 739 | int vnic_dev_link_status(struct vnic_dev *vdev) |
656 | { | 740 | { |
657 | if (vdev->linkstatus) | 741 | if (vdev->linkstatus) |
diff --git a/drivers/net/enic/vnic_dev.h b/drivers/net/enic/vnic_dev.h index fc5e3eb35a5e..caccce36957b 100644 --- a/drivers/net/enic/vnic_dev.h +++ b/drivers/net/enic/vnic_dev.h | |||
@@ -103,11 +103,14 @@ int vnic_dev_stats_dump(struct vnic_dev *vdev, struct vnic_stats **stats); | |||
103 | int vnic_dev_hang_notify(struct vnic_dev *vdev); | 103 | int vnic_dev_hang_notify(struct vnic_dev *vdev); |
104 | void vnic_dev_packet_filter(struct vnic_dev *vdev, int directed, int multicast, | 104 | void vnic_dev_packet_filter(struct vnic_dev *vdev, int directed, int multicast, |
105 | int broadcast, int promisc, int allmulti); | 105 | int broadcast, int promisc, int allmulti); |
106 | void vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr); | 106 | int vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr); |
107 | void vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr); | 107 | int vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr); |
108 | int vnic_dev_mac_addr(struct vnic_dev *vdev, u8 *mac_addr); | 108 | int vnic_dev_mac_addr(struct vnic_dev *vdev, u8 *mac_addr); |
109 | int vnic_dev_raise_intr(struct vnic_dev *vdev, u16 intr); | 109 | int vnic_dev_raise_intr(struct vnic_dev *vdev, u16 intr); |
110 | int vnic_dev_notify_setcmd(struct vnic_dev *vdev, | ||
111 | void *notify_addr, dma_addr_t notify_pa, u16 intr); | ||
110 | int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr); | 112 | int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr); |
113 | void vnic_dev_notify_unsetcmd(struct vnic_dev *vdev); | ||
111 | void vnic_dev_notify_unset(struct vnic_dev *vdev); | 114 | void vnic_dev_notify_unset(struct vnic_dev *vdev); |
112 | int vnic_dev_link_status(struct vnic_dev *vdev); | 115 | int vnic_dev_link_status(struct vnic_dev *vdev); |
113 | u32 vnic_dev_port_speed(struct vnic_dev *vdev); | 116 | u32 vnic_dev_port_speed(struct vnic_dev *vdev); |
@@ -121,6 +124,9 @@ int vnic_dev_disable(struct vnic_dev *vdev); | |||
121 | int vnic_dev_open(struct vnic_dev *vdev, int arg); | 124 | int vnic_dev_open(struct vnic_dev *vdev, int arg); |
122 | int vnic_dev_open_done(struct vnic_dev *vdev, int *done); | 125 | int vnic_dev_open_done(struct vnic_dev *vdev, int *done); |
123 | int vnic_dev_init(struct vnic_dev *vdev, int arg); | 126 | int vnic_dev_init(struct vnic_dev *vdev, int arg); |
127 | int vnic_dev_init_done(struct vnic_dev *vdev, int *done, int *err); | ||
128 | int vnic_dev_init_prov(struct vnic_dev *vdev, u8 *buf, u32 len); | ||
129 | int vnic_dev_deinit(struct vnic_dev *vdev); | ||
124 | int vnic_dev_soft_reset(struct vnic_dev *vdev, int arg); | 130 | int vnic_dev_soft_reset(struct vnic_dev *vdev, int arg); |
125 | int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done); | 131 | int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done); |
126 | void vnic_dev_set_intr_mode(struct vnic_dev *vdev, | 132 | void vnic_dev_set_intr_mode(struct vnic_dev *vdev, |
diff --git a/drivers/net/enic/vnic_rq.c b/drivers/net/enic/vnic_rq.c index e186efaf9da1..cc580cfec41d 100644 --- a/drivers/net/enic/vnic_rq.c +++ b/drivers/net/enic/vnic_rq.c | |||
@@ -168,10 +168,10 @@ int vnic_rq_disable(struct vnic_rq *rq) | |||
168 | iowrite32(0, &rq->ctrl->enable); | 168 | iowrite32(0, &rq->ctrl->enable); |
169 | 169 | ||
170 | /* Wait for HW to ACK disable request */ | 170 | /* Wait for HW to ACK disable request */ |
171 | for (wait = 0; wait < 100; wait++) { | 171 | for (wait = 0; wait < 1000; wait++) { |
172 | if (!(ioread32(&rq->ctrl->running))) | 172 | if (!(ioread32(&rq->ctrl->running))) |
173 | return 0; | 173 | return 0; |
174 | udelay(1); | 174 | udelay(10); |
175 | } | 175 | } |
176 | 176 | ||
177 | printk(KERN_ERR "Failed to disable RQ[%d]\n", rq->index); | 177 | printk(KERN_ERR "Failed to disable RQ[%d]\n", rq->index); |
diff --git a/drivers/net/enic/vnic_vic.c b/drivers/net/enic/vnic_vic.c new file mode 100644 index 000000000000..d769772998c6 --- /dev/null +++ b/drivers/net/enic/vnic_vic.c | |||
@@ -0,0 +1,73 @@ | |||
1 | /* | ||
2 | * Copyright 2010 Cisco Systems, Inc. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you may redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; version 2 of the License. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
9 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
10 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
11 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
12 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
14 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
15 | * SOFTWARE. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/errno.h> | ||
21 | #include <linux/types.h> | ||
22 | #include <linux/slab.h> | ||
23 | |||
24 | #include "vnic_vic.h" | ||
25 | |||
26 | struct vic_provinfo *vic_provinfo_alloc(gfp_t flags, u8 *oui, u8 type) | ||
27 | { | ||
28 | struct vic_provinfo *vp = kzalloc(VIC_PROVINFO_MAX_DATA, flags); | ||
29 | |||
30 | if (!vp || !oui) | ||
31 | return NULL; | ||
32 | |||
33 | memcpy(vp->oui, oui, sizeof(vp->oui)); | ||
34 | vp->type = type; | ||
35 | vp->length = htonl(sizeof(vp->num_tlvs)); | ||
36 | |||
37 | return vp; | ||
38 | } | ||
39 | |||
40 | void vic_provinfo_free(struct vic_provinfo *vp) | ||
41 | { | ||
42 | kfree(vp); | ||
43 | } | ||
44 | |||
45 | int vic_provinfo_add_tlv(struct vic_provinfo *vp, u16 type, u16 length, | ||
46 | void *value) | ||
47 | { | ||
48 | struct vic_provinfo_tlv *tlv; | ||
49 | |||
50 | if (!vp || !value) | ||
51 | return -EINVAL; | ||
52 | |||
53 | if (ntohl(vp->length) + sizeof(*tlv) + length > | ||
54 | VIC_PROVINFO_MAX_TLV_DATA) | ||
55 | return -ENOMEM; | ||
56 | |||
57 | tlv = (struct vic_provinfo_tlv *)((u8 *)vp->tlv + | ||
58 | ntohl(vp->length) - sizeof(vp->num_tlvs)); | ||
59 | |||
60 | tlv->type = htons(type); | ||
61 | tlv->length = htons(length); | ||
62 | memcpy(tlv->value, value, length); | ||
63 | |||
64 | vp->num_tlvs = htonl(ntohl(vp->num_tlvs) + 1); | ||
65 | vp->length = htonl(ntohl(vp->length) + sizeof(*tlv) + length); | ||
66 | |||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | size_t vic_provinfo_size(struct vic_provinfo *vp) | ||
71 | { | ||
72 | return vp ? ntohl(vp->length) + sizeof(*vp) - sizeof(vp->num_tlvs) : 0; | ||
73 | } | ||
diff --git a/drivers/net/enic/vnic_vic.h b/drivers/net/enic/vnic_vic.h new file mode 100644 index 000000000000..085c2a274cb1 --- /dev/null +++ b/drivers/net/enic/vnic_vic.h | |||
@@ -0,0 +1,59 @@ | |||
1 | /* | ||
2 | * Copyright 2010 Cisco Systems, Inc. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you may redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; version 2 of the License. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
9 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
10 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
11 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
12 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
14 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
15 | * SOFTWARE. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #ifndef _VNIC_VIC_H_ | ||
20 | #define _VNIC_VIC_H_ | ||
21 | |||
22 | /* Note: All integer fields in NETWORK byte order */ | ||
23 | |||
24 | /* Note: String field lengths include null char */ | ||
25 | |||
26 | #define VIC_PROVINFO_CISCO_OUI { 0x00, 0x00, 0x0c } | ||
27 | #define VIC_PROVINFO_LINUX_TYPE 0x2 | ||
28 | |||
29 | enum vic_linux_prov_tlv_type { | ||
30 | VIC_LINUX_PROV_TLV_PORT_PROFILE_NAME_STR = 0, | ||
31 | VIC_LINUX_PROV_TLV_CLIENT_MAC_ADDR = 1, /* u8[6] */ | ||
32 | VIC_LINUX_PROV_TLV_CLIENT_NAME_STR = 2, | ||
33 | VIC_LINUX_PROV_TLV_HOST_UUID_STR = 8, | ||
34 | VIC_LINUX_PROV_TLV_CLIENT_UUID_STR = 9, | ||
35 | }; | ||
36 | |||
37 | struct vic_provinfo { | ||
38 | u8 oui[3]; /* OUI of data provider */ | ||
39 | u8 type; /* provider-specific type */ | ||
40 | u32 length; /* length of data below */ | ||
41 | u32 num_tlvs; /* number of tlvs */ | ||
42 | struct vic_provinfo_tlv { | ||
43 | u16 type; | ||
44 | u16 length; | ||
45 | u8 value[0]; | ||
46 | } tlv[0]; | ||
47 | } __attribute__ ((packed)); | ||
48 | |||
49 | #define VIC_PROVINFO_MAX_DATA 1385 | ||
50 | #define VIC_PROVINFO_MAX_TLV_DATA (VIC_PROVINFO_MAX_DATA - \ | ||
51 | sizeof(struct vic_provinfo)) | ||
52 | |||
53 | struct vic_provinfo *vic_provinfo_alloc(gfp_t flags, u8 *oui, u8 type); | ||
54 | void vic_provinfo_free(struct vic_provinfo *vp); | ||
55 | int vic_provinfo_add_tlv(struct vic_provinfo *vp, u16 type, u16 length, | ||
56 | void *value); | ||
57 | size_t vic_provinfo_size(struct vic_provinfo *vp); | ||
58 | |||
59 | #endif /* _VNIC_VIC_H_ */ | ||
diff --git a/drivers/net/enic/vnic_wq.c b/drivers/net/enic/vnic_wq.c index d5f984357f5c..1378afbdfe67 100644 --- a/drivers/net/enic/vnic_wq.c +++ b/drivers/net/enic/vnic_wq.c | |||
@@ -161,10 +161,10 @@ int vnic_wq_disable(struct vnic_wq *wq) | |||
161 | iowrite32(0, &wq->ctrl->enable); | 161 | iowrite32(0, &wq->ctrl->enable); |
162 | 162 | ||
163 | /* Wait for HW to ACK disable request */ | 163 | /* Wait for HW to ACK disable request */ |
164 | for (wait = 0; wait < 100; wait++) { | 164 | for (wait = 0; wait < 1000; wait++) { |
165 | if (!(ioread32(&wq->ctrl->running))) | 165 | if (!(ioread32(&wq->ctrl->running))) |
166 | return 0; | 166 | return 0; |
167 | udelay(1); | 167 | udelay(10); |
168 | } | 168 | } |
169 | 169 | ||
170 | printk(KERN_ERR "Failed to disable WQ[%d]\n", wq->index); | 170 | printk(KERN_ERR "Failed to disable WQ[%d]\n", wq->index); |