diff options
-rw-r--r-- | drivers/net/Kconfig | 10 | ||||
-rw-r--r-- | drivers/net/ixgbe/Makefile | 2 | ||||
-rw-r--r-- | drivers/net/ixgbe/ixgbe.h | 25 | ||||
-rw-r--r-- | drivers/net/ixgbe/ixgbe_dcb.c | 332 | ||||
-rw-r--r-- | drivers/net/ixgbe/ixgbe_dcb.h | 157 | ||||
-rw-r--r-- | drivers/net/ixgbe/ixgbe_dcb_82598.c | 398 | ||||
-rw-r--r-- | drivers/net/ixgbe/ixgbe_dcb_82598.h | 94 | ||||
-rw-r--r-- | drivers/net/ixgbe/ixgbe_dcb_nl.c | 356 | ||||
-rw-r--r-- | drivers/net/ixgbe/ixgbe_ethtool.c | 30 | ||||
-rw-r--r-- | drivers/net/ixgbe/ixgbe_main.c | 200 | ||||
-rw-r--r-- | include/linux/dcbnl.h | 230 | ||||
-rw-r--r-- | include/linux/netdevice.h | 8 | ||||
-rw-r--r-- | include/linux/rtnetlink.h | 5 | ||||
-rw-r--r-- | include/net/dcbnl.h | 44 | ||||
-rw-r--r-- | net/Kconfig | 1 | ||||
-rw-r--r-- | net/Makefile | 3 | ||||
-rw-r--r-- | net/dcb/Kconfig | 12 | ||||
-rw-r--r-- | net/dcb/Makefile | 1 | ||||
-rw-r--r-- | net/dcb/dcbnl.c | 704 |
19 files changed, 2593 insertions, 19 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index afa206590ada..efd461d7c2bb 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
@@ -2451,6 +2451,16 @@ config IXGBE_DCA | |||
2451 | driver. DCA is a method for warming the CPU cache before data | 2451 | driver. DCA is a method for warming the CPU cache before data |
2452 | is used, with the intent of lessening the impact of cache misses. | 2452 | is used, with the intent of lessening the impact of cache misses. |
2453 | 2453 | ||
2454 | config IXGBE_DCBNL | ||
2455 | bool "Data Center Bridging (DCB) Support" | ||
2456 | default n | ||
2457 | depends on IXGBE && DCBNL | ||
2458 | ---help--- | ||
2459 | Say Y here if you want to use Data Center Bridging (DCB) in the | ||
2460 | driver. | ||
2461 | |||
2462 | If unsure, say N. | ||
2463 | |||
2454 | config IXGB | 2464 | config IXGB |
2455 | tristate "Intel(R) PRO/10GbE support" | 2465 | tristate "Intel(R) PRO/10GbE support" |
2456 | depends on PCI | 2466 | depends on PCI |
diff --git a/drivers/net/ixgbe/Makefile b/drivers/net/ixgbe/Makefile index ccd83d9f579e..3228e508e628 100644 --- a/drivers/net/ixgbe/Makefile +++ b/drivers/net/ixgbe/Makefile | |||
@@ -34,3 +34,5 @@ obj-$(CONFIG_IXGBE) += ixgbe.o | |||
34 | 34 | ||
35 | ixgbe-objs := ixgbe_main.o ixgbe_common.o ixgbe_ethtool.o \ | 35 | ixgbe-objs := ixgbe_main.o ixgbe_common.o ixgbe_ethtool.o \ |
36 | ixgbe_82598.o ixgbe_phy.o | 36 | ixgbe_82598.o ixgbe_phy.o |
37 | |||
38 | ixgbe-$(CONFIG_IXGBE_DCBNL) += ixgbe_dcb.o ixgbe_dcb_82598.o ixgbe_dcb_nl.o | ||
diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index 132854f646ba..796f189f3879 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h | |||
@@ -35,7 +35,7 @@ | |||
35 | 35 | ||
36 | #include "ixgbe_type.h" | 36 | #include "ixgbe_type.h" |
37 | #include "ixgbe_common.h" | 37 | #include "ixgbe_common.h" |
38 | 38 | #include "ixgbe_dcb.h" | |
39 | #ifdef CONFIG_IXGBE_DCA | 39 | #ifdef CONFIG_IXGBE_DCA |
40 | #include <linux/dca.h> | 40 | #include <linux/dca.h> |
41 | #endif | 41 | #endif |
@@ -84,6 +84,7 @@ | |||
84 | #define IXGBE_TX_FLAGS_TSO (u32)(1 << 2) | 84 | #define IXGBE_TX_FLAGS_TSO (u32)(1 << 2) |
85 | #define IXGBE_TX_FLAGS_IPV4 (u32)(1 << 3) | 85 | #define IXGBE_TX_FLAGS_IPV4 (u32)(1 << 3) |
86 | #define IXGBE_TX_FLAGS_VLAN_MASK 0xffff0000 | 86 | #define IXGBE_TX_FLAGS_VLAN_MASK 0xffff0000 |
87 | #define IXGBE_TX_FLAGS_VLAN_PRIO_MASK 0x0000e000 | ||
87 | #define IXGBE_TX_FLAGS_VLAN_SHIFT 16 | 88 | #define IXGBE_TX_FLAGS_VLAN_SHIFT 16 |
88 | 89 | ||
89 | #define IXGBE_MAX_LRO_DESCRIPTORS 8 | 90 | #define IXGBE_MAX_LRO_DESCRIPTORS 8 |
@@ -134,7 +135,7 @@ struct ixgbe_ring { | |||
134 | 135 | ||
135 | u16 reg_idx; /* holds the special value that gets the hardware register | 136 | u16 reg_idx; /* holds the special value that gets the hardware register |
136 | * offset associated with this ring, which is different | 137 | * offset associated with this ring, which is different |
137 | * for DCE and RSS modes */ | 138 | * for DCB and RSS modes */ |
138 | 139 | ||
139 | #ifdef CONFIG_IXGBE_DCA | 140 | #ifdef CONFIG_IXGBE_DCA |
140 | /* cpu for tx queue */ | 141 | /* cpu for tx queue */ |
@@ -152,8 +153,10 @@ struct ixgbe_ring { | |||
152 | u16 rx_buf_len; | 153 | u16 rx_buf_len; |
153 | }; | 154 | }; |
154 | 155 | ||
156 | #define RING_F_DCB 0 | ||
155 | #define RING_F_VMDQ 1 | 157 | #define RING_F_VMDQ 1 |
156 | #define RING_F_RSS 2 | 158 | #define RING_F_RSS 2 |
159 | #define IXGBE_MAX_DCB_INDICES 8 | ||
157 | #define IXGBE_MAX_RSS_INDICES 16 | 160 | #define IXGBE_MAX_RSS_INDICES 16 |
158 | #define IXGBE_MAX_VMDQ_INDICES 16 | 161 | #define IXGBE_MAX_VMDQ_INDICES 16 |
159 | struct ixgbe_ring_feature { | 162 | struct ixgbe_ring_feature { |
@@ -164,6 +167,10 @@ struct ixgbe_ring_feature { | |||
164 | #define MAX_RX_QUEUES 64 | 167 | #define MAX_RX_QUEUES 64 |
165 | #define MAX_TX_QUEUES 32 | 168 | #define MAX_TX_QUEUES 32 |
166 | 169 | ||
170 | #define MAX_RX_PACKET_BUFFERS ((adapter->flags & IXGBE_FLAG_DCB_ENABLED) \ | ||
171 | ? 8 : 1) | ||
172 | #define MAX_TX_PACKET_BUFFERS MAX_RX_PACKET_BUFFERS | ||
173 | |||
167 | /* MAX_MSIX_Q_VECTORS of these are allocated, | 174 | /* MAX_MSIX_Q_VECTORS of these are allocated, |
168 | * but we only use one per queue-specific vector. | 175 | * but we only use one per queue-specific vector. |
169 | */ | 176 | */ |
@@ -215,6 +222,9 @@ struct ixgbe_adapter { | |||
215 | struct work_struct reset_task; | 222 | struct work_struct reset_task; |
216 | struct ixgbe_q_vector q_vector[MAX_MSIX_Q_VECTORS]; | 223 | struct ixgbe_q_vector q_vector[MAX_MSIX_Q_VECTORS]; |
217 | char name[MAX_MSIX_COUNT][IFNAMSIZ + 5]; | 224 | char name[MAX_MSIX_COUNT][IFNAMSIZ + 5]; |
225 | struct ixgbe_dcb_config dcb_cfg; | ||
226 | struct ixgbe_dcb_config temp_dcb_cfg; | ||
227 | u8 dcb_set_bitmap; | ||
218 | 228 | ||
219 | /* Interrupt Throttle Rate */ | 229 | /* Interrupt Throttle Rate */ |
220 | u32 itr_setting; | 230 | u32 itr_setting; |
@@ -270,6 +280,7 @@ struct ixgbe_adapter { | |||
270 | #define IXGBE_FLAG_FAN_FAIL_CAPABLE (u32)(1 << 20) | 280 | #define IXGBE_FLAG_FAN_FAIL_CAPABLE (u32)(1 << 20) |
271 | #define IXGBE_FLAG_NEED_LINK_UPDATE (u32)(1 << 22) | 281 | #define IXGBE_FLAG_NEED_LINK_UPDATE (u32)(1 << 22) |
272 | #define IXGBE_FLAG_IN_WATCHDOG_TASK (u32)(1 << 23) | 282 | #define IXGBE_FLAG_IN_WATCHDOG_TASK (u32)(1 << 23) |
283 | #define IXGBE_FLAG_DCB_ENABLED (u32)(1 << 24) | ||
273 | 284 | ||
274 | /* default to trying for four seconds */ | 285 | /* default to trying for four seconds */ |
275 | #define IXGBE_TRY_LINK_TIMEOUT (4 * HZ) | 286 | #define IXGBE_TRY_LINK_TIMEOUT (4 * HZ) |
@@ -313,6 +324,12 @@ enum ixgbe_boards { | |||
313 | }; | 324 | }; |
314 | 325 | ||
315 | extern struct ixgbe_info ixgbe_82598_info; | 326 | extern struct ixgbe_info ixgbe_82598_info; |
327 | #ifdef CONFIG_IXGBE_DCBNL | ||
328 | extern struct dcbnl_rtnl_ops dcbnl_ops; | ||
329 | extern int ixgbe_copy_dcb_cfg(struct ixgbe_dcb_config *src_dcb_cfg, | ||
330 | struct ixgbe_dcb_config *dst_dcb_cfg, | ||
331 | int tc_max); | ||
332 | #endif | ||
316 | 333 | ||
317 | extern char ixgbe_driver_name[]; | 334 | extern char ixgbe_driver_name[]; |
318 | extern const char ixgbe_driver_version[]; | 335 | extern const char ixgbe_driver_version[]; |
@@ -327,5 +344,9 @@ extern int ixgbe_setup_tx_resources(struct ixgbe_adapter *, struct ixgbe_ring *) | |||
327 | extern void ixgbe_free_rx_resources(struct ixgbe_adapter *, struct ixgbe_ring *); | 344 | extern void ixgbe_free_rx_resources(struct ixgbe_adapter *, struct ixgbe_ring *); |
328 | extern void ixgbe_free_tx_resources(struct ixgbe_adapter *, struct ixgbe_ring *); | 345 | extern void ixgbe_free_tx_resources(struct ixgbe_adapter *, struct ixgbe_ring *); |
329 | extern void ixgbe_update_stats(struct ixgbe_adapter *adapter); | 346 | extern void ixgbe_update_stats(struct ixgbe_adapter *adapter); |
347 | extern void ixgbe_reset_interrupt_capability(struct ixgbe_adapter *adapter); | ||
348 | extern int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter); | ||
349 | void ixgbe_napi_add_all(struct ixgbe_adapter *adapter); | ||
350 | void ixgbe_napi_del_all(struct ixgbe_adapter *adapter); | ||
330 | 351 | ||
331 | #endif /* _IXGBE_H_ */ | 352 | #endif /* _IXGBE_H_ */ |
diff --git a/drivers/net/ixgbe/ixgbe_dcb.c b/drivers/net/ixgbe/ixgbe_dcb.c new file mode 100644 index 000000000000..e2e28ac63dec --- /dev/null +++ b/drivers/net/ixgbe/ixgbe_dcb.c | |||
@@ -0,0 +1,332 @@ | |||
1 | /******************************************************************************* | ||
2 | |||
3 | Intel 10 Gigabit PCI Express Linux driver | ||
4 | Copyright(c) 1999 - 2007 Intel Corporation. | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify it | ||
7 | under the terms and conditions of the GNU General Public License, | ||
8 | version 2, as published by the Free Software Foundation. | ||
9 | |||
10 | This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License along with | ||
16 | this program; if not, write to the Free Software Foundation, Inc., | ||
17 | 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
18 | |||
19 | The full GNU General Public License is included in this distribution in | ||
20 | the file called "COPYING". | ||
21 | |||
22 | Contact Information: | ||
23 | Linux NICS <linux.nics@intel.com> | ||
24 | e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> | ||
25 | Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
26 | |||
27 | *******************************************************************************/ | ||
28 | |||
29 | |||
30 | #include "ixgbe.h" | ||
31 | #include "ixgbe_type.h" | ||
32 | #include "ixgbe_dcb.h" | ||
33 | #include "ixgbe_dcb_82598.h" | ||
34 | |||
35 | /** | ||
36 | * ixgbe_dcb_config - Struct containing DCB settings. | ||
37 | * @dcb_config: Pointer to DCB config structure | ||
38 | * | ||
39 | * This function checks DCB rules for DCB settings. | ||
40 | * The following rules are checked: | ||
41 | * 1. The sum of bandwidth percentages of all Bandwidth Groups must total 100%. | ||
42 | * 2. The sum of bandwidth percentages of all Traffic Classes within a Bandwidth | ||
43 | * Group must total 100. | ||
44 | * 3. A Traffic Class should not be set to both Link Strict Priority | ||
45 | * and Group Strict Priority. | ||
46 | * 4. Link strict Bandwidth Groups can only have link strict traffic classes | ||
47 | * with zero bandwidth. | ||
48 | */ | ||
49 | s32 ixgbe_dcb_check_config(struct ixgbe_dcb_config *dcb_config) | ||
50 | { | ||
51 | struct tc_bw_alloc *p; | ||
52 | s32 ret_val = 0; | ||
53 | u8 i, j, bw = 0, bw_id; | ||
54 | u8 bw_sum[2][MAX_BW_GROUP]; | ||
55 | bool link_strict[2][MAX_BW_GROUP]; | ||
56 | |||
57 | memset(bw_sum, 0, sizeof(bw_sum)); | ||
58 | memset(link_strict, 0, sizeof(link_strict)); | ||
59 | |||
60 | /* First Tx, then Rx */ | ||
61 | for (i = 0; i < 2; i++) { | ||
62 | /* Check each traffic class for rule violation */ | ||
63 | for (j = 0; j < MAX_TRAFFIC_CLASS; j++) { | ||
64 | p = &dcb_config->tc_config[j].path[i]; | ||
65 | |||
66 | bw = p->bwg_percent; | ||
67 | bw_id = p->bwg_id; | ||
68 | |||
69 | if (bw_id >= MAX_BW_GROUP) { | ||
70 | ret_val = DCB_ERR_CONFIG; | ||
71 | goto err_config; | ||
72 | } | ||
73 | if (p->prio_type == prio_link) { | ||
74 | link_strict[i][bw_id] = true; | ||
75 | /* Link strict should have zero bandwidth */ | ||
76 | if (bw) { | ||
77 | ret_val = DCB_ERR_LS_BW_NONZERO; | ||
78 | goto err_config; | ||
79 | } | ||
80 | } else if (!bw) { | ||
81 | /* | ||
82 | * Traffic classes without link strict | ||
83 | * should have non-zero bandwidth. | ||
84 | */ | ||
85 | ret_val = DCB_ERR_TC_BW_ZERO; | ||
86 | goto err_config; | ||
87 | } | ||
88 | bw_sum[i][bw_id] += bw; | ||
89 | } | ||
90 | |||
91 | bw = 0; | ||
92 | |||
93 | /* Check each bandwidth group for rule violation */ | ||
94 | for (j = 0; j < MAX_BW_GROUP; j++) { | ||
95 | bw += dcb_config->bw_percentage[i][j]; | ||
96 | /* | ||
97 | * Sum of bandwidth percentages of all traffic classes | ||
98 | * within a Bandwidth Group must total 100 except for | ||
99 | * link strict group (zero bandwidth). | ||
100 | */ | ||
101 | if (link_strict[i][j]) { | ||
102 | if (bw_sum[i][j]) { | ||
103 | /* | ||
104 | * Link strict group should have zero | ||
105 | * bandwidth. | ||
106 | */ | ||
107 | ret_val = DCB_ERR_LS_BWG_NONZERO; | ||
108 | goto err_config; | ||
109 | } | ||
110 | } else if (bw_sum[i][j] != BW_PERCENT && | ||
111 | bw_sum[i][j] != 0) { | ||
112 | ret_val = DCB_ERR_TC_BW; | ||
113 | goto err_config; | ||
114 | } | ||
115 | } | ||
116 | |||
117 | if (bw != BW_PERCENT) { | ||
118 | ret_val = DCB_ERR_BW_GROUP; | ||
119 | goto err_config; | ||
120 | } | ||
121 | } | ||
122 | |||
123 | err_config: | ||
124 | return ret_val; | ||
125 | } | ||
126 | |||
127 | /** | ||
128 | * ixgbe_dcb_calculate_tc_credits - Calculates traffic class credits | ||
129 | * @ixgbe_dcb_config: Struct containing DCB settings. | ||
130 | * @direction: Configuring either Tx or Rx. | ||
131 | * | ||
132 | * This function calculates the credits allocated to each traffic class. | ||
133 | * It should be called only after the rules are checked by | ||
134 | * ixgbe_dcb_check_config(). | ||
135 | */ | ||
136 | s32 ixgbe_dcb_calculate_tc_credits(struct ixgbe_dcb_config *dcb_config, | ||
137 | u8 direction) | ||
138 | { | ||
139 | struct tc_bw_alloc *p; | ||
140 | s32 ret_val = 0; | ||
141 | /* Initialization values default for Tx settings */ | ||
142 | u32 credit_refill = 0; | ||
143 | u32 credit_max = 0; | ||
144 | u16 link_percentage = 0; | ||
145 | u8 bw_percent = 0; | ||
146 | u8 i; | ||
147 | |||
148 | if (dcb_config == NULL) { | ||
149 | ret_val = DCB_ERR_CONFIG; | ||
150 | goto out; | ||
151 | } | ||
152 | |||
153 | /* Find out the link percentage for each TC first */ | ||
154 | for (i = 0; i < MAX_TRAFFIC_CLASS; i++) { | ||
155 | p = &dcb_config->tc_config[i].path[direction]; | ||
156 | bw_percent = dcb_config->bw_percentage[direction][p->bwg_id]; | ||
157 | |||
158 | link_percentage = p->bwg_percent; | ||
159 | /* Must be careful of integer division for very small nums */ | ||
160 | link_percentage = (link_percentage * bw_percent) / 100; | ||
161 | if (p->bwg_percent > 0 && link_percentage == 0) | ||
162 | link_percentage = 1; | ||
163 | |||
164 | /* Save link_percentage for reference */ | ||
165 | p->link_percent = (u8)link_percentage; | ||
166 | |||
167 | /* Calculate credit refill and save it */ | ||
168 | credit_refill = link_percentage * MINIMUM_CREDIT_REFILL; | ||
169 | p->data_credits_refill = (u16)credit_refill; | ||
170 | |||
171 | /* Calculate maximum credit for the TC */ | ||
172 | credit_max = (link_percentage * MAX_CREDIT) / 100; | ||
173 | |||
174 | /* | ||
175 | * Adjustment based on rule checking, if the percentage | ||
176 | * of a TC is too small, the maximum credit may not be | ||
177 | * enough to send out a jumbo frame in data plane arbitration. | ||
178 | */ | ||
179 | if (credit_max && (credit_max < MINIMUM_CREDIT_FOR_JUMBO)) | ||
180 | credit_max = MINIMUM_CREDIT_FOR_JUMBO; | ||
181 | |||
182 | if (direction == DCB_TX_CONFIG) { | ||
183 | /* | ||
184 | * Adjustment based on rule checking, if the | ||
185 | * percentage of a TC is too small, the maximum | ||
186 | * credit may not be enough to send out a TSO | ||
187 | * packet in descriptor plane arbitration. | ||
188 | */ | ||
189 | if (credit_max && | ||
190 | (credit_max < MINIMUM_CREDIT_FOR_TSO)) | ||
191 | credit_max = MINIMUM_CREDIT_FOR_TSO; | ||
192 | |||
193 | dcb_config->tc_config[i].desc_credits_max = | ||
194 | (u16)credit_max; | ||
195 | } | ||
196 | |||
197 | p->data_credits_max = (u16)credit_max; | ||
198 | } | ||
199 | |||
200 | out: | ||
201 | return ret_val; | ||
202 | } | ||
203 | |||
204 | /** | ||
205 | * ixgbe_dcb_get_tc_stats - Returns status of each traffic class | ||
206 | * @hw: pointer to hardware structure | ||
207 | * @stats: pointer to statistics structure | ||
208 | * @tc_count: Number of elements in bwg_array. | ||
209 | * | ||
210 | * This function returns the status data for each of the Traffic Classes in use. | ||
211 | */ | ||
212 | s32 ixgbe_dcb_get_tc_stats(struct ixgbe_hw *hw, struct ixgbe_hw_stats *stats, | ||
213 | u8 tc_count) | ||
214 | { | ||
215 | s32 ret = 0; | ||
216 | if (hw->mac.type == ixgbe_mac_82598EB) | ||
217 | ret = ixgbe_dcb_get_tc_stats_82598(hw, stats, tc_count); | ||
218 | return ret; | ||
219 | } | ||
220 | |||
221 | /** | ||
222 | * ixgbe_dcb_get_pfc_stats - Returns CBFC status of each traffic class | ||
223 | * hw - pointer to hardware structure | ||
224 | * stats - pointer to statistics structure | ||
225 | * tc_count - Number of elements in bwg_array. | ||
226 | * | ||
227 | * This function returns the CBFC status data for each of the Traffic Classes. | ||
228 | */ | ||
229 | s32 ixgbe_dcb_get_pfc_stats(struct ixgbe_hw *hw, struct ixgbe_hw_stats *stats, | ||
230 | u8 tc_count) | ||
231 | { | ||
232 | s32 ret = 0; | ||
233 | if (hw->mac.type == ixgbe_mac_82598EB) | ||
234 | ret = ixgbe_dcb_get_pfc_stats_82598(hw, stats, tc_count); | ||
235 | return ret; | ||
236 | } | ||
237 | |||
238 | /** | ||
239 | * ixgbe_dcb_config_rx_arbiter - Config Rx arbiter | ||
240 | * @hw: pointer to hardware structure | ||
241 | * @dcb_config: pointer to ixgbe_dcb_config structure | ||
242 | * | ||
243 | * Configure Rx Data Arbiter and credits for each traffic class. | ||
244 | */ | ||
245 | s32 ixgbe_dcb_config_rx_arbiter(struct ixgbe_hw *hw, | ||
246 | struct ixgbe_dcb_config *dcb_config) | ||
247 | { | ||
248 | s32 ret = 0; | ||
249 | if (hw->mac.type == ixgbe_mac_82598EB) | ||
250 | ret = ixgbe_dcb_config_rx_arbiter_82598(hw, dcb_config); | ||
251 | return ret; | ||
252 | } | ||
253 | |||
254 | /** | ||
255 | * ixgbe_dcb_config_tx_desc_arbiter - Config Tx Desc arbiter | ||
256 | * @hw: pointer to hardware structure | ||
257 | * @dcb_config: pointer to ixgbe_dcb_config structure | ||
258 | * | ||
259 | * Configure Tx Descriptor Arbiter and credits for each traffic class. | ||
260 | */ | ||
261 | s32 ixgbe_dcb_config_tx_desc_arbiter(struct ixgbe_hw *hw, | ||
262 | struct ixgbe_dcb_config *dcb_config) | ||
263 | { | ||
264 | s32 ret = 0; | ||
265 | if (hw->mac.type == ixgbe_mac_82598EB) | ||
266 | ret = ixgbe_dcb_config_tx_desc_arbiter_82598(hw, dcb_config); | ||
267 | return ret; | ||
268 | } | ||
269 | |||
270 | /** | ||
271 | * ixgbe_dcb_config_tx_data_arbiter - Config Tx data arbiter | ||
272 | * @hw: pointer to hardware structure | ||
273 | * @dcb_config: pointer to ixgbe_dcb_config structure | ||
274 | * | ||
275 | * Configure Tx Data Arbiter and credits for each traffic class. | ||
276 | */ | ||
277 | s32 ixgbe_dcb_config_tx_data_arbiter(struct ixgbe_hw *hw, | ||
278 | struct ixgbe_dcb_config *dcb_config) | ||
279 | { | ||
280 | s32 ret = 0; | ||
281 | if (hw->mac.type == ixgbe_mac_82598EB) | ||
282 | ret = ixgbe_dcb_config_tx_data_arbiter_82598(hw, dcb_config); | ||
283 | return ret; | ||
284 | } | ||
285 | |||
286 | /** | ||
287 | * ixgbe_dcb_config_pfc - Config priority flow control | ||
288 | * @hw: pointer to hardware structure | ||
289 | * @dcb_config: pointer to ixgbe_dcb_config structure | ||
290 | * | ||
291 | * Configure Priority Flow Control for each traffic class. | ||
292 | */ | ||
293 | s32 ixgbe_dcb_config_pfc(struct ixgbe_hw *hw, | ||
294 | struct ixgbe_dcb_config *dcb_config) | ||
295 | { | ||
296 | s32 ret = 0; | ||
297 | if (hw->mac.type == ixgbe_mac_82598EB) | ||
298 | ret = ixgbe_dcb_config_pfc_82598(hw, dcb_config); | ||
299 | return ret; | ||
300 | } | ||
301 | |||
302 | /** | ||
303 | * ixgbe_dcb_config_tc_stats - Config traffic class statistics | ||
304 | * @hw: pointer to hardware structure | ||
305 | * | ||
306 | * Configure queue statistics registers, all queues belonging to same traffic | ||
307 | * class uses a single set of queue statistics counters. | ||
308 | */ | ||
309 | s32 ixgbe_dcb_config_tc_stats(struct ixgbe_hw *hw) | ||
310 | { | ||
311 | s32 ret = 0; | ||
312 | if (hw->mac.type == ixgbe_mac_82598EB) | ||
313 | ret = ixgbe_dcb_config_tc_stats_82598(hw); | ||
314 | return ret; | ||
315 | } | ||
316 | |||
317 | /** | ||
318 | * ixgbe_dcb_hw_config - Config and enable DCB | ||
319 | * @hw: pointer to hardware structure | ||
320 | * @dcb_config: pointer to ixgbe_dcb_config structure | ||
321 | * | ||
322 | * Configure dcb settings and enable dcb mode. | ||
323 | */ | ||
324 | s32 ixgbe_dcb_hw_config(struct ixgbe_hw *hw, | ||
325 | struct ixgbe_dcb_config *dcb_config) | ||
326 | { | ||
327 | s32 ret = 0; | ||
328 | if (hw->mac.type == ixgbe_mac_82598EB) | ||
329 | ret = ixgbe_dcb_hw_config_82598(hw, dcb_config); | ||
330 | return ret; | ||
331 | } | ||
332 | |||
diff --git a/drivers/net/ixgbe/ixgbe_dcb.h b/drivers/net/ixgbe/ixgbe_dcb.h new file mode 100644 index 000000000000..62dfd243bedc --- /dev/null +++ b/drivers/net/ixgbe/ixgbe_dcb.h | |||
@@ -0,0 +1,157 @@ | |||
1 | /******************************************************************************* | ||
2 | |||
3 | Intel 10 Gigabit PCI Express Linux driver | ||
4 | Copyright(c) 1999 - 2007 Intel Corporation. | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify it | ||
7 | under the terms and conditions of the GNU General Public License, | ||
8 | version 2, as published by the Free Software Foundation. | ||
9 | |||
10 | This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License along with | ||
16 | this program; if not, write to the Free Software Foundation, Inc., | ||
17 | 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
18 | |||
19 | The full GNU General Public License is included in this distribution in | ||
20 | the file called "COPYING". | ||
21 | |||
22 | Contact Information: | ||
23 | Linux NICS <linux.nics@intel.com> | ||
24 | e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> | ||
25 | Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
26 | |||
27 | *******************************************************************************/ | ||
28 | |||
29 | #ifndef _DCB_CONFIG_H_ | ||
30 | #define _DCB_CONFIG_H_ | ||
31 | |||
32 | #include "ixgbe_type.h" | ||
33 | |||
34 | /* DCB data structures */ | ||
35 | |||
36 | #define IXGBE_MAX_PACKET_BUFFERS 8 | ||
37 | #define MAX_USER_PRIORITY 8 | ||
38 | #define MAX_TRAFFIC_CLASS 8 | ||
39 | #define MAX_BW_GROUP 8 | ||
40 | #define BW_PERCENT 100 | ||
41 | |||
42 | #define DCB_TX_CONFIG 0 | ||
43 | #define DCB_RX_CONFIG 1 | ||
44 | |||
45 | /* DCB error Codes */ | ||
46 | #define DCB_SUCCESS 0 | ||
47 | #define DCB_ERR_CONFIG -1 | ||
48 | #define DCB_ERR_PARAM -2 | ||
49 | |||
50 | /* Transmit and receive Errors */ | ||
51 | /* Error in bandwidth group allocation */ | ||
52 | #define DCB_ERR_BW_GROUP -3 | ||
53 | /* Error in traffic class bandwidth allocation */ | ||
54 | #define DCB_ERR_TC_BW -4 | ||
55 | /* Traffic class has both link strict and group strict enabled */ | ||
56 | #define DCB_ERR_LS_GS -5 | ||
57 | /* Link strict traffic class has non zero bandwidth */ | ||
58 | #define DCB_ERR_LS_BW_NONZERO -6 | ||
59 | /* Link strict bandwidth group has non zero bandwidth */ | ||
60 | #define DCB_ERR_LS_BWG_NONZERO -7 | ||
61 | /* Traffic class has zero bandwidth */ | ||
62 | #define DCB_ERR_TC_BW_ZERO -8 | ||
63 | |||
64 | #define DCB_NOT_IMPLEMENTED 0x7FFFFFFF | ||
65 | |||
66 | struct dcb_pfc_tc_debug { | ||
67 | u8 tc; | ||
68 | u8 pause_status; | ||
69 | u64 pause_quanta; | ||
70 | }; | ||
71 | |||
72 | enum strict_prio_type { | ||
73 | prio_none = 0, | ||
74 | prio_group, | ||
75 | prio_link | ||
76 | }; | ||
77 | |||
78 | /* Traffic class bandwidth allocation per direction */ | ||
79 | struct tc_bw_alloc { | ||
80 | u8 bwg_id; /* Bandwidth Group (BWG) ID */ | ||
81 | u8 bwg_percent; /* % of BWG's bandwidth */ | ||
82 | u8 link_percent; /* % of link bandwidth */ | ||
83 | u8 up_to_tc_bitmap; /* User Priority to Traffic Class mapping */ | ||
84 | u16 data_credits_refill; /* Credit refill amount in 64B granularity */ | ||
85 | u16 data_credits_max; /* Max credits for a configured packet buffer | ||
86 | * in 64B granularity.*/ | ||
87 | enum strict_prio_type prio_type; /* Link or Group Strict Priority */ | ||
88 | }; | ||
89 | |||
90 | enum dcb_pfc_type { | ||
91 | pfc_disabled = 0, | ||
92 | pfc_enabled_full, | ||
93 | pfc_enabled_tx, | ||
94 | pfc_enabled_rx | ||
95 | }; | ||
96 | |||
97 | /* Traffic class configuration */ | ||
98 | struct tc_configuration { | ||
99 | struct tc_bw_alloc path[2]; /* One each for Tx/Rx */ | ||
100 | enum dcb_pfc_type dcb_pfc; /* Class based flow control setting */ | ||
101 | |||
102 | u16 desc_credits_max; /* For Tx Descriptor arbitration */ | ||
103 | u8 tc; /* Traffic class (TC) */ | ||
104 | }; | ||
105 | |||
106 | enum dcb_rx_pba_cfg { | ||
107 | pba_equal, /* PBA[0-7] each use 64KB FIFO */ | ||
108 | pba_80_48 /* PBA[0-3] each use 80KB, PBA[4-7] each use 48KB */ | ||
109 | }; | ||
110 | |||
111 | struct ixgbe_dcb_config { | ||
112 | struct tc_configuration tc_config[MAX_TRAFFIC_CLASS]; | ||
113 | u8 bw_percentage[2][MAX_BW_GROUP]; /* One each for Tx/Rx */ | ||
114 | |||
115 | bool round_robin_enable; | ||
116 | |||
117 | enum dcb_rx_pba_cfg rx_pba_cfg; | ||
118 | |||
119 | u32 dcb_cfg_version; /* Not used...OS-specific? */ | ||
120 | u32 link_speed; /* For bandwidth allocation validation purpose */ | ||
121 | }; | ||
122 | |||
123 | /* DCB driver APIs */ | ||
124 | |||
125 | /* DCB rule checking function.*/ | ||
126 | s32 ixgbe_dcb_check_config(struct ixgbe_dcb_config *config); | ||
127 | |||
128 | /* DCB credits calculation */ | ||
129 | s32 ixgbe_dcb_calculate_tc_credits(struct ixgbe_dcb_config *, u8); | ||
130 | |||
131 | /* DCB PFC functions */ | ||
132 | s32 ixgbe_dcb_config_pfc(struct ixgbe_hw *, struct ixgbe_dcb_config *g); | ||
133 | s32 ixgbe_dcb_get_pfc_stats(struct ixgbe_hw *, struct ixgbe_hw_stats *, u8); | ||
134 | |||
135 | /* DCB traffic class stats */ | ||
136 | s32 ixgbe_dcb_config_tc_stats(struct ixgbe_hw *); | ||
137 | s32 ixgbe_dcb_get_tc_stats(struct ixgbe_hw *, struct ixgbe_hw_stats *, u8); | ||
138 | |||
139 | /* DCB config arbiters */ | ||
140 | s32 ixgbe_dcb_config_tx_desc_arbiter(struct ixgbe_hw *, | ||
141 | struct ixgbe_dcb_config *); | ||
142 | s32 ixgbe_dcb_config_tx_data_arbiter(struct ixgbe_hw *, | ||
143 | struct ixgbe_dcb_config *); | ||
144 | s32 ixgbe_dcb_config_rx_arbiter(struct ixgbe_hw *, struct ixgbe_dcb_config *); | ||
145 | |||
146 | /* DCB hw initialization */ | ||
147 | s32 ixgbe_dcb_hw_config(struct ixgbe_hw *, struct ixgbe_dcb_config *); | ||
148 | |||
149 | /* DCB definitions for credit calculation */ | ||
150 | #define MAX_CREDIT_REFILL 511 /* 0x1FF * 64B = 32704B */ | ||
151 | #define MINIMUM_CREDIT_REFILL 5 /* 5*64B = 320B */ | ||
152 | #define MINIMUM_CREDIT_FOR_JUMBO 145 /* 145= UpperBound((9*1024+54)/64B) for 9KB jumbo frame */ | ||
153 | #define DCB_MAX_TSO_SIZE (32*1024) /* MAX TSO packet size supported in DCB mode */ | ||
154 | #define MINIMUM_CREDIT_FOR_TSO (DCB_MAX_TSO_SIZE/64 + 1) /* 513 for 32KB TSO packet */ | ||
155 | #define MAX_CREDIT 4095 /* Maximum credit supported: 256KB * 1204 / 64B */ | ||
156 | |||
157 | #endif /* _DCB_CONFIG_H */ | ||
diff --git a/drivers/net/ixgbe/ixgbe_dcb_82598.c b/drivers/net/ixgbe/ixgbe_dcb_82598.c new file mode 100644 index 000000000000..fce6867a4517 --- /dev/null +++ b/drivers/net/ixgbe/ixgbe_dcb_82598.c | |||
@@ -0,0 +1,398 @@ | |||
1 | /******************************************************************************* | ||
2 | |||
3 | Intel 10 Gigabit PCI Express Linux driver | ||
4 | Copyright(c) 1999 - 2007 Intel Corporation. | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify it | ||
7 | under the terms and conditions of the GNU General Public License, | ||
8 | version 2, as published by the Free Software Foundation. | ||
9 | |||
10 | This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License along with | ||
16 | this program; if not, write to the Free Software Foundation, Inc., | ||
17 | 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
18 | |||
19 | The full GNU General Public License is included in this distribution in | ||
20 | the file called "COPYING". | ||
21 | |||
22 | Contact Information: | ||
23 | Linux NICS <linux.nics@intel.com> | ||
24 | e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> | ||
25 | Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
26 | |||
27 | *******************************************************************************/ | ||
28 | |||
29 | #include "ixgbe.h" | ||
30 | #include "ixgbe_type.h" | ||
31 | #include "ixgbe_dcb.h" | ||
32 | #include "ixgbe_dcb_82598.h" | ||
33 | |||
34 | /** | ||
35 | * ixgbe_dcb_get_tc_stats_82598 - Return status data for each traffic class | ||
36 | * @hw: pointer to hardware structure | ||
37 | * @stats: pointer to statistics structure | ||
38 | * @tc_count: Number of elements in bwg_array. | ||
39 | * | ||
40 | * This function returns the status data for each of the Traffic Classes in use. | ||
41 | */ | ||
42 | s32 ixgbe_dcb_get_tc_stats_82598(struct ixgbe_hw *hw, | ||
43 | struct ixgbe_hw_stats *stats, | ||
44 | u8 tc_count) | ||
45 | { | ||
46 | int tc; | ||
47 | |||
48 | if (tc_count > MAX_TRAFFIC_CLASS) | ||
49 | return DCB_ERR_PARAM; | ||
50 | |||
51 | /* Statistics pertaining to each traffic class */ | ||
52 | for (tc = 0; tc < tc_count; tc++) { | ||
53 | /* Transmitted Packets */ | ||
54 | stats->qptc[tc] += IXGBE_READ_REG(hw, IXGBE_QPTC(tc)); | ||
55 | /* Transmitted Bytes */ | ||
56 | stats->qbtc[tc] += IXGBE_READ_REG(hw, IXGBE_QBTC(tc)); | ||
57 | /* Received Packets */ | ||
58 | stats->qprc[tc] += IXGBE_READ_REG(hw, IXGBE_QPRC(tc)); | ||
59 | /* Received Bytes */ | ||
60 | stats->qbrc[tc] += IXGBE_READ_REG(hw, IXGBE_QBRC(tc)); | ||
61 | } | ||
62 | |||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | /** | ||
67 | * ixgbe_dcb_get_pfc_stats_82598 - Returns CBFC status data | ||
68 | * @hw: pointer to hardware structure | ||
69 | * @stats: pointer to statistics structure | ||
70 | * @tc_count: Number of elements in bwg_array. | ||
71 | * | ||
72 | * This function returns the CBFC status data for each of the Traffic Classes. | ||
73 | */ | ||
74 | s32 ixgbe_dcb_get_pfc_stats_82598(struct ixgbe_hw *hw, | ||
75 | struct ixgbe_hw_stats *stats, | ||
76 | u8 tc_count) | ||
77 | { | ||
78 | int tc; | ||
79 | |||
80 | if (tc_count > MAX_TRAFFIC_CLASS) | ||
81 | return DCB_ERR_PARAM; | ||
82 | |||
83 | for (tc = 0; tc < tc_count; tc++) { | ||
84 | /* Priority XOFF Transmitted */ | ||
85 | stats->pxofftxc[tc] += IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(tc)); | ||
86 | /* Priority XOFF Received */ | ||
87 | stats->pxoffrxc[tc] += IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(tc)); | ||
88 | } | ||
89 | |||
90 | return 0; | ||
91 | } | ||
92 | |||
93 | /** | ||
94 | * ixgbe_dcb_config_packet_buffers_82598 - Configure packet buffers | ||
95 | * @hw: pointer to hardware structure | ||
96 | * @dcb_config: pointer to ixgbe_dcb_config structure | ||
97 | * | ||
98 | * Configure packet buffers for DCB mode. | ||
99 | */ | ||
100 | s32 ixgbe_dcb_config_packet_buffers_82598(struct ixgbe_hw *hw, | ||
101 | struct ixgbe_dcb_config *dcb_config) | ||
102 | { | ||
103 | s32 ret_val = 0; | ||
104 | u32 value = IXGBE_RXPBSIZE_64KB; | ||
105 | u8 i = 0; | ||
106 | |||
107 | /* Setup Rx packet buffer sizes */ | ||
108 | switch (dcb_config->rx_pba_cfg) { | ||
109 | case pba_80_48: | ||
110 | /* Setup the first four at 80KB */ | ||
111 | value = IXGBE_RXPBSIZE_80KB; | ||
112 | for (; i < 4; i++) | ||
113 | IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), value); | ||
114 | /* Setup the last four at 48KB...don't re-init i */ | ||
115 | value = IXGBE_RXPBSIZE_48KB; | ||
116 | /* Fall Through */ | ||
117 | case pba_equal: | ||
118 | default: | ||
119 | for (; i < IXGBE_MAX_PACKET_BUFFERS; i++) | ||
120 | IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), value); | ||
121 | |||
122 | /* Setup Tx packet buffer sizes */ | ||
123 | for (i = 0; i < IXGBE_MAX_PACKET_BUFFERS; i++) { | ||
124 | IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), | ||
125 | IXGBE_TXPBSIZE_40KB); | ||
126 | } | ||
127 | break; | ||
128 | } | ||
129 | |||
130 | return ret_val; | ||
131 | } | ||
132 | |||
133 | /** | ||
134 | * ixgbe_dcb_config_rx_arbiter_82598 - Config Rx data arbiter | ||
135 | * @hw: pointer to hardware structure | ||
136 | * @dcb_config: pointer to ixgbe_dcb_config structure | ||
137 | * | ||
138 | * Configure Rx Data Arbiter and credits for each traffic class. | ||
139 | */ | ||
140 | s32 ixgbe_dcb_config_rx_arbiter_82598(struct ixgbe_hw *hw, | ||
141 | struct ixgbe_dcb_config *dcb_config) | ||
142 | { | ||
143 | struct tc_bw_alloc *p; | ||
144 | u32 reg = 0; | ||
145 | u32 credit_refill = 0; | ||
146 | u32 credit_max = 0; | ||
147 | u8 i = 0; | ||
148 | |||
149 | reg = IXGBE_READ_REG(hw, IXGBE_RUPPBMR) | IXGBE_RUPPBMR_MQA; | ||
150 | IXGBE_WRITE_REG(hw, IXGBE_RUPPBMR, reg); | ||
151 | |||
152 | reg = IXGBE_READ_REG(hw, IXGBE_RMCS); | ||
153 | /* Enable Arbiter */ | ||
154 | reg &= ~IXGBE_RMCS_ARBDIS; | ||
155 | /* Enable Receive Recycle within the BWG */ | ||
156 | reg |= IXGBE_RMCS_RRM; | ||
157 | /* Enable Deficit Fixed Priority arbitration*/ | ||
158 | reg |= IXGBE_RMCS_DFP; | ||
159 | |||
160 | IXGBE_WRITE_REG(hw, IXGBE_RMCS, reg); | ||
161 | |||
162 | /* Configure traffic class credits and priority */ | ||
163 | for (i = 0; i < MAX_TRAFFIC_CLASS; i++) { | ||
164 | p = &dcb_config->tc_config[i].path[DCB_RX_CONFIG]; | ||
165 | credit_refill = p->data_credits_refill; | ||
166 | credit_max = p->data_credits_max; | ||
167 | |||
168 | reg = credit_refill | (credit_max << IXGBE_RT2CR_MCL_SHIFT); | ||
169 | |||
170 | if (p->prio_type == prio_link) | ||
171 | reg |= IXGBE_RT2CR_LSP; | ||
172 | |||
173 | IXGBE_WRITE_REG(hw, IXGBE_RT2CR(i), reg); | ||
174 | } | ||
175 | |||
176 | reg = IXGBE_READ_REG(hw, IXGBE_RDRXCTL); | ||
177 | reg |= IXGBE_RDRXCTL_RDMTS_1_2; | ||
178 | reg |= IXGBE_RDRXCTL_MPBEN; | ||
179 | reg |= IXGBE_RDRXCTL_MCEN; | ||
180 | IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, reg); | ||
181 | |||
182 | reg = IXGBE_READ_REG(hw, IXGBE_RXCTRL); | ||
183 | /* Make sure there is enough descriptors before arbitration */ | ||
184 | reg &= ~IXGBE_RXCTRL_DMBYPS; | ||
185 | IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, reg); | ||
186 | |||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | /** | ||
191 | * ixgbe_dcb_config_tx_desc_arbiter_82598 - Config Tx Desc. arbiter | ||
192 | * @hw: pointer to hardware structure | ||
193 | * @dcb_config: pointer to ixgbe_dcb_config structure | ||
194 | * | ||
195 | * Configure Tx Descriptor Arbiter and credits for each traffic class. | ||
196 | */ | ||
197 | s32 ixgbe_dcb_config_tx_desc_arbiter_82598(struct ixgbe_hw *hw, | ||
198 | struct ixgbe_dcb_config *dcb_config) | ||
199 | { | ||
200 | struct tc_bw_alloc *p; | ||
201 | u32 reg, max_credits; | ||
202 | u8 i; | ||
203 | |||
204 | reg = IXGBE_READ_REG(hw, IXGBE_DPMCS); | ||
205 | |||
206 | /* Enable arbiter */ | ||
207 | reg &= ~IXGBE_DPMCS_ARBDIS; | ||
208 | if (!(dcb_config->round_robin_enable)) { | ||
209 | /* Enable DFP and Recycle mode */ | ||
210 | reg |= (IXGBE_DPMCS_TDPAC | IXGBE_DPMCS_TRM); | ||
211 | } | ||
212 | reg |= IXGBE_DPMCS_TSOEF; | ||
213 | /* Configure Max TSO packet size 34KB including payload and headers */ | ||
214 | reg |= (0x4 << IXGBE_DPMCS_MTSOS_SHIFT); | ||
215 | |||
216 | IXGBE_WRITE_REG(hw, IXGBE_DPMCS, reg); | ||
217 | |||
218 | /* Configure traffic class credits and priority */ | ||
219 | for (i = 0; i < MAX_TRAFFIC_CLASS; i++) { | ||
220 | p = &dcb_config->tc_config[i].path[DCB_TX_CONFIG]; | ||
221 | max_credits = dcb_config->tc_config[i].desc_credits_max; | ||
222 | reg = max_credits << IXGBE_TDTQ2TCCR_MCL_SHIFT; | ||
223 | reg |= p->data_credits_refill; | ||
224 | reg |= (u32)(p->bwg_id) << IXGBE_TDTQ2TCCR_BWG_SHIFT; | ||
225 | |||
226 | if (p->prio_type == prio_group) | ||
227 | reg |= IXGBE_TDTQ2TCCR_GSP; | ||
228 | |||
229 | if (p->prio_type == prio_link) | ||
230 | reg |= IXGBE_TDTQ2TCCR_LSP; | ||
231 | |||
232 | IXGBE_WRITE_REG(hw, IXGBE_TDTQ2TCCR(i), reg); | ||
233 | } | ||
234 | |||
235 | return 0; | ||
236 | } | ||
237 | |||
238 | /** | ||
239 | * ixgbe_dcb_config_tx_data_arbiter_82598 - Config Tx data arbiter | ||
240 | * @hw: pointer to hardware structure | ||
241 | * @dcb_config: pointer to ixgbe_dcb_config structure | ||
242 | * | ||
243 | * Configure Tx Data Arbiter and credits for each traffic class. | ||
244 | */ | ||
245 | s32 ixgbe_dcb_config_tx_data_arbiter_82598(struct ixgbe_hw *hw, | ||
246 | struct ixgbe_dcb_config *dcb_config) | ||
247 | { | ||
248 | struct tc_bw_alloc *p; | ||
249 | u32 reg; | ||
250 | u8 i; | ||
251 | |||
252 | reg = IXGBE_READ_REG(hw, IXGBE_PDPMCS); | ||
253 | /* Enable Data Plane Arbiter */ | ||
254 | reg &= ~IXGBE_PDPMCS_ARBDIS; | ||
255 | /* Enable DFP and Transmit Recycle Mode */ | ||
256 | reg |= (IXGBE_PDPMCS_TPPAC | IXGBE_PDPMCS_TRM); | ||
257 | |||
258 | IXGBE_WRITE_REG(hw, IXGBE_PDPMCS, reg); | ||
259 | |||
260 | /* Configure traffic class credits and priority */ | ||
261 | for (i = 0; i < MAX_TRAFFIC_CLASS; i++) { | ||
262 | p = &dcb_config->tc_config[i].path[DCB_TX_CONFIG]; | ||
263 | reg = p->data_credits_refill; | ||
264 | reg |= (u32)(p->data_credits_max) << IXGBE_TDPT2TCCR_MCL_SHIFT; | ||
265 | reg |= (u32)(p->bwg_id) << IXGBE_TDPT2TCCR_BWG_SHIFT; | ||
266 | |||
267 | if (p->prio_type == prio_group) | ||
268 | reg |= IXGBE_TDPT2TCCR_GSP; | ||
269 | |||
270 | if (p->prio_type == prio_link) | ||
271 | reg |= IXGBE_TDPT2TCCR_LSP; | ||
272 | |||
273 | IXGBE_WRITE_REG(hw, IXGBE_TDPT2TCCR(i), reg); | ||
274 | } | ||
275 | |||
276 | /* Enable Tx packet buffer division */ | ||
277 | reg = IXGBE_READ_REG(hw, IXGBE_DTXCTL); | ||
278 | reg |= IXGBE_DTXCTL_ENDBUBD; | ||
279 | IXGBE_WRITE_REG(hw, IXGBE_DTXCTL, reg); | ||
280 | |||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | /** | ||
285 | * ixgbe_dcb_config_pfc_82598 - Config priority flow control | ||
286 | * @hw: pointer to hardware structure | ||
287 | * @dcb_config: pointer to ixgbe_dcb_config structure | ||
288 | * | ||
289 | * Configure Priority Flow Control for each traffic class. | ||
290 | */ | ||
291 | s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *hw, | ||
292 | struct ixgbe_dcb_config *dcb_config) | ||
293 | { | ||
294 | u32 reg, rx_pba_size; | ||
295 | u8 i; | ||
296 | |||
297 | /* Enable Transmit Priority Flow Control */ | ||
298 | reg = IXGBE_READ_REG(hw, IXGBE_RMCS); | ||
299 | reg &= ~IXGBE_RMCS_TFCE_802_3X; | ||
300 | /* correct the reporting of our flow control status */ | ||
301 | hw->fc.type = ixgbe_fc_none; | ||
302 | reg |= IXGBE_RMCS_TFCE_PRIORITY; | ||
303 | IXGBE_WRITE_REG(hw, IXGBE_RMCS, reg); | ||
304 | |||
305 | /* Enable Receive Priority Flow Control */ | ||
306 | reg = IXGBE_READ_REG(hw, IXGBE_FCTRL); | ||
307 | reg &= ~IXGBE_FCTRL_RFCE; | ||
308 | reg |= IXGBE_FCTRL_RPFCE; | ||
309 | IXGBE_WRITE_REG(hw, IXGBE_FCTRL, reg); | ||
310 | |||
311 | /* | ||
312 | * Configure flow control thresholds and enable priority flow control | ||
313 | * for each traffic class. | ||
314 | */ | ||
315 | for (i = 0; i < MAX_TRAFFIC_CLASS; i++) { | ||
316 | if (dcb_config->rx_pba_cfg == pba_equal) { | ||
317 | rx_pba_size = IXGBE_RXPBSIZE_64KB; | ||
318 | } else { | ||
319 | rx_pba_size = (i < 4) ? IXGBE_RXPBSIZE_80KB | ||
320 | : IXGBE_RXPBSIZE_48KB; | ||
321 | } | ||
322 | |||
323 | reg = ((rx_pba_size >> 5) & 0xFFF0); | ||
324 | if (dcb_config->tc_config[i].dcb_pfc == pfc_enabled_tx || | ||
325 | dcb_config->tc_config[i].dcb_pfc == pfc_enabled_full) | ||
326 | reg |= IXGBE_FCRTL_XONE; | ||
327 | |||
328 | IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), reg); | ||
329 | |||
330 | reg = ((rx_pba_size >> 2) & 0xFFF0); | ||
331 | if (dcb_config->tc_config[i].dcb_pfc == pfc_enabled_tx || | ||
332 | dcb_config->tc_config[i].dcb_pfc == pfc_enabled_full) | ||
333 | reg |= IXGBE_FCRTH_FCEN; | ||
334 | |||
335 | IXGBE_WRITE_REG(hw, IXGBE_FCRTH(i), reg); | ||
336 | } | ||
337 | |||
338 | /* Configure pause time */ | ||
339 | for (i = 0; i < (MAX_TRAFFIC_CLASS >> 1); i++) | ||
340 | IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), 0x68006800); | ||
341 | |||
342 | /* Configure flow control refresh threshold value */ | ||
343 | IXGBE_WRITE_REG(hw, IXGBE_FCRTV, 0x3400); | ||
344 | |||
345 | return 0; | ||
346 | } | ||
347 | |||
348 | /** | ||
349 | * ixgbe_dcb_config_tc_stats_82598 - Configure traffic class statistics | ||
350 | * @hw: pointer to hardware structure | ||
351 | * | ||
352 | * Configure queue statistics registers, all queues belonging to same traffic | ||
353 | * class uses a single set of queue statistics counters. | ||
354 | */ | ||
355 | s32 ixgbe_dcb_config_tc_stats_82598(struct ixgbe_hw *hw) | ||
356 | { | ||
357 | u32 reg = 0; | ||
358 | u8 i = 0; | ||
359 | u8 j = 0; | ||
360 | |||
361 | /* Receive Queues stats setting - 8 queues per statistics reg */ | ||
362 | for (i = 0, j = 0; i < 15 && j < 8; i = i + 2, j++) { | ||
363 | reg = IXGBE_READ_REG(hw, IXGBE_RQSMR(i)); | ||
364 | reg |= ((0x1010101) * j); | ||
365 | IXGBE_WRITE_REG(hw, IXGBE_RQSMR(i), reg); | ||
366 | reg = IXGBE_READ_REG(hw, IXGBE_RQSMR(i + 1)); | ||
367 | reg |= ((0x1010101) * j); | ||
368 | IXGBE_WRITE_REG(hw, IXGBE_RQSMR(i + 1), reg); | ||
369 | } | ||
370 | /* Transmit Queues stats setting - 4 queues per statistics reg */ | ||
371 | for (i = 0; i < 8; i++) { | ||
372 | reg = IXGBE_READ_REG(hw, IXGBE_TQSMR(i)); | ||
373 | reg |= ((0x1010101) * i); | ||
374 | IXGBE_WRITE_REG(hw, IXGBE_TQSMR(i), reg); | ||
375 | } | ||
376 | |||
377 | return 0; | ||
378 | } | ||
379 | |||
380 | /** | ||
381 | * ixgbe_dcb_hw_config_82598 - Config and enable DCB | ||
382 | * @hw: pointer to hardware structure | ||
383 | * @dcb_config: pointer to ixgbe_dcb_config structure | ||
384 | * | ||
385 | * Configure dcb settings and enable dcb mode. | ||
386 | */ | ||
387 | s32 ixgbe_dcb_hw_config_82598(struct ixgbe_hw *hw, | ||
388 | struct ixgbe_dcb_config *dcb_config) | ||
389 | { | ||
390 | ixgbe_dcb_config_packet_buffers_82598(hw, dcb_config); | ||
391 | ixgbe_dcb_config_rx_arbiter_82598(hw, dcb_config); | ||
392 | ixgbe_dcb_config_tx_desc_arbiter_82598(hw, dcb_config); | ||
393 | ixgbe_dcb_config_tx_data_arbiter_82598(hw, dcb_config); | ||
394 | ixgbe_dcb_config_pfc_82598(hw, dcb_config); | ||
395 | ixgbe_dcb_config_tc_stats_82598(hw); | ||
396 | |||
397 | return 0; | ||
398 | } | ||
diff --git a/drivers/net/ixgbe/ixgbe_dcb_82598.h b/drivers/net/ixgbe/ixgbe_dcb_82598.h new file mode 100644 index 000000000000..1e6a313719d7 --- /dev/null +++ b/drivers/net/ixgbe/ixgbe_dcb_82598.h | |||
@@ -0,0 +1,94 @@ | |||
1 | /******************************************************************************* | ||
2 | |||
3 | Intel 10 Gigabit PCI Express Linux driver | ||
4 | Copyright(c) 1999 - 2007 Intel Corporation. | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify it | ||
7 | under the terms and conditions of the GNU General Public License, | ||
8 | version 2, as published by the Free Software Foundation. | ||
9 | |||
10 | This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License along with | ||
16 | this program; if not, write to the Free Software Foundation, Inc., | ||
17 | 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
18 | |||
19 | The full GNU General Public License is included in this distribution in | ||
20 | the file called "COPYING". | ||
21 | |||
22 | Contact Information: | ||
23 | Linux NICS <linux.nics@intel.com> | ||
24 | e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> | ||
25 | Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
26 | |||
27 | *******************************************************************************/ | ||
28 | |||
29 | #ifndef _DCB_82598_CONFIG_H_ | ||
30 | #define _DCB_82598_CONFIG_H_ | ||
31 | |||
32 | /* DCB register definitions */ | ||
33 | |||
34 | #define IXGBE_DPMCS_MTSOS_SHIFT 16 | ||
35 | #define IXGBE_DPMCS_TDPAC 0x00000001 /* 0 Round Robin, 1 DFP - Deficit Fixed Priority */ | ||
36 | #define IXGBE_DPMCS_TRM 0x00000010 /* Transmit Recycle Mode */ | ||
37 | #define IXGBE_DPMCS_ARBDIS 0x00000040 /* DCB arbiter disable */ | ||
38 | #define IXGBE_DPMCS_TSOEF 0x00080000 /* TSO Expand Factor: 0=x4, 1=x2 */ | ||
39 | |||
40 | #define IXGBE_RUPPBMR_MQA 0x80000000 /* Enable UP to queue mapping */ | ||
41 | |||
42 | #define IXGBE_RT2CR_MCL_SHIFT 12 /* Offset to Max Credit Limit setting */ | ||
43 | #define IXGBE_RT2CR_LSP 0x80000000 /* LSP enable bit */ | ||
44 | |||
45 | #define IXGBE_RDRXCTL_MPBEN 0x00000010 /* DMA config for multiple packet buffers enable */ | ||
46 | #define IXGBE_RDRXCTL_MCEN 0x00000040 /* DMA config for multiple cores (RSS) enable */ | ||
47 | |||
48 | #define IXGBE_TDTQ2TCCR_MCL_SHIFT 12 | ||
49 | #define IXGBE_TDTQ2TCCR_BWG_SHIFT 9 | ||
50 | #define IXGBE_TDTQ2TCCR_GSP 0x40000000 | ||
51 | #define IXGBE_TDTQ2TCCR_LSP 0x80000000 | ||
52 | |||
53 | #define IXGBE_TDPT2TCCR_MCL_SHIFT 12 | ||
54 | #define IXGBE_TDPT2TCCR_BWG_SHIFT 9 | ||
55 | #define IXGBE_TDPT2TCCR_GSP 0x40000000 | ||
56 | #define IXGBE_TDPT2TCCR_LSP 0x80000000 | ||
57 | |||
58 | #define IXGBE_PDPMCS_TPPAC 0x00000020 /* 0 Round Robin, 1 for DFP - Deficit Fixed Priority */ | ||
59 | #define IXGBE_PDPMCS_ARBDIS 0x00000040 /* Arbiter disable */ | ||
60 | #define IXGBE_PDPMCS_TRM 0x00000100 /* Transmit Recycle Mode enable */ | ||
61 | |||
62 | #define IXGBE_DTXCTL_ENDBUBD 0x00000004 /* Enable DBU buffer division */ | ||
63 | |||
64 | #define IXGBE_TXPBSIZE_40KB 0x0000A000 /* 40KB Packet Buffer */ | ||
65 | #define IXGBE_RXPBSIZE_48KB 0x0000C000 /* 48KB Packet Buffer */ | ||
66 | #define IXGBE_RXPBSIZE_64KB 0x00010000 /* 64KB Packet Buffer */ | ||
67 | #define IXGBE_RXPBSIZE_80KB 0x00014000 /* 80KB Packet Buffer */ | ||
68 | |||
69 | #define IXGBE_RDRXCTL_RDMTS_1_2 0x00000000 | ||
70 | |||
71 | /* DCB hardware-specific driver APIs */ | ||
72 | |||
73 | /* DCB PFC functions */ | ||
74 | s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *, struct ixgbe_dcb_config *); | ||
75 | s32 ixgbe_dcb_get_pfc_stats_82598(struct ixgbe_hw *, struct ixgbe_hw_stats *, | ||
76 | u8); | ||
77 | |||
78 | /* DCB traffic class stats */ | ||
79 | s32 ixgbe_dcb_config_tc_stats_82598(struct ixgbe_hw *); | ||
80 | s32 ixgbe_dcb_get_tc_stats_82598(struct ixgbe_hw *, struct ixgbe_hw_stats *, | ||
81 | u8); | ||
82 | |||
83 | /* DCB config arbiters */ | ||
84 | s32 ixgbe_dcb_config_tx_desc_arbiter_82598(struct ixgbe_hw *, | ||
85 | struct ixgbe_dcb_config *); | ||
86 | s32 ixgbe_dcb_config_tx_data_arbiter_82598(struct ixgbe_hw *, | ||
87 | struct ixgbe_dcb_config *); | ||
88 | s32 ixgbe_dcb_config_rx_arbiter_82598(struct ixgbe_hw *, | ||
89 | struct ixgbe_dcb_config *); | ||
90 | |||
91 | /* DCB hw initialization */ | ||
92 | s32 ixgbe_dcb_hw_config_82598(struct ixgbe_hw *, struct ixgbe_dcb_config *); | ||
93 | |||
94 | #endif /* _DCB_82598_CONFIG_H */ | ||
diff --git a/drivers/net/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ixgbe/ixgbe_dcb_nl.c new file mode 100644 index 000000000000..50bff2af6b04 --- /dev/null +++ b/drivers/net/ixgbe/ixgbe_dcb_nl.c | |||
@@ -0,0 +1,356 @@ | |||
1 | /******************************************************************************* | ||
2 | |||
3 | Intel 10 Gigabit PCI Express Linux driver | ||
4 | Copyright(c) 1999 - 2008 Intel Corporation. | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify it | ||
7 | under the terms and conditions of the GNU General Public License, | ||
8 | version 2, as published by the Free Software Foundation. | ||
9 | |||
10 | This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License along with | ||
16 | this program; if not, write to the Free Software Foundation, Inc., | ||
17 | 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
18 | |||
19 | The full GNU General Public License is included in this distribution in | ||
20 | the file called "COPYING". | ||
21 | |||
22 | Contact Information: | ||
23 | Linux NICS <linux.nics@intel.com> | ||
24 | e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> | ||
25 | Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
26 | |||
27 | *******************************************************************************/ | ||
28 | |||
29 | #include "ixgbe.h" | ||
30 | #include <linux/dcbnl.h> | ||
31 | |||
32 | /* Callbacks for DCB netlink in the kernel */ | ||
33 | #define BIT_DCB_MODE 0x01 | ||
34 | #define BIT_PFC 0x02 | ||
35 | #define BIT_PG_RX 0x04 | ||
36 | #define BIT_PG_TX 0x08 | ||
37 | |||
38 | int ixgbe_copy_dcb_cfg(struct ixgbe_dcb_config *src_dcb_cfg, | ||
39 | struct ixgbe_dcb_config *dst_dcb_cfg, int tc_max) | ||
40 | { | ||
41 | struct tc_configuration *src_tc_cfg = NULL; | ||
42 | struct tc_configuration *dst_tc_cfg = NULL; | ||
43 | int i; | ||
44 | |||
45 | if (!src_dcb_cfg || !dst_dcb_cfg) | ||
46 | return -EINVAL; | ||
47 | |||
48 | for (i = DCB_PG_ATTR_TC_0; i < tc_max + DCB_PG_ATTR_TC_0; i++) { | ||
49 | src_tc_cfg = &src_dcb_cfg->tc_config[i - DCB_PG_ATTR_TC_0]; | ||
50 | dst_tc_cfg = &dst_dcb_cfg->tc_config[i - DCB_PG_ATTR_TC_0]; | ||
51 | |||
52 | dst_tc_cfg->path[DCB_TX_CONFIG].prio_type = | ||
53 | src_tc_cfg->path[DCB_TX_CONFIG].prio_type; | ||
54 | |||
55 | dst_tc_cfg->path[DCB_TX_CONFIG].bwg_id = | ||
56 | src_tc_cfg->path[DCB_TX_CONFIG].bwg_id; | ||
57 | |||
58 | dst_tc_cfg->path[DCB_TX_CONFIG].bwg_percent = | ||
59 | src_tc_cfg->path[DCB_TX_CONFIG].bwg_percent; | ||
60 | |||
61 | dst_tc_cfg->path[DCB_TX_CONFIG].up_to_tc_bitmap = | ||
62 | src_tc_cfg->path[DCB_TX_CONFIG].up_to_tc_bitmap; | ||
63 | |||
64 | dst_tc_cfg->path[DCB_RX_CONFIG].prio_type = | ||
65 | src_tc_cfg->path[DCB_RX_CONFIG].prio_type; | ||
66 | |||
67 | dst_tc_cfg->path[DCB_RX_CONFIG].bwg_id = | ||
68 | src_tc_cfg->path[DCB_RX_CONFIG].bwg_id; | ||
69 | |||
70 | dst_tc_cfg->path[DCB_RX_CONFIG].bwg_percent = | ||
71 | src_tc_cfg->path[DCB_RX_CONFIG].bwg_percent; | ||
72 | |||
73 | dst_tc_cfg->path[DCB_RX_CONFIG].up_to_tc_bitmap = | ||
74 | src_tc_cfg->path[DCB_RX_CONFIG].up_to_tc_bitmap; | ||
75 | } | ||
76 | |||
77 | for (i = DCB_PG_ATTR_BW_ID_0; i < DCB_PG_ATTR_BW_ID_MAX; i++) { | ||
78 | dst_dcb_cfg->bw_percentage[DCB_TX_CONFIG] | ||
79 | [i-DCB_PG_ATTR_BW_ID_0] = src_dcb_cfg->bw_percentage | ||
80 | [DCB_TX_CONFIG][i-DCB_PG_ATTR_BW_ID_0]; | ||
81 | dst_dcb_cfg->bw_percentage[DCB_RX_CONFIG] | ||
82 | [i-DCB_PG_ATTR_BW_ID_0] = src_dcb_cfg->bw_percentage | ||
83 | [DCB_RX_CONFIG][i-DCB_PG_ATTR_BW_ID_0]; | ||
84 | } | ||
85 | |||
86 | for (i = DCB_PFC_UP_ATTR_0; i < DCB_PFC_UP_ATTR_MAX; i++) { | ||
87 | dst_dcb_cfg->tc_config[i - DCB_PFC_UP_ATTR_0].dcb_pfc = | ||
88 | src_dcb_cfg->tc_config[i - DCB_PFC_UP_ATTR_0].dcb_pfc; | ||
89 | } | ||
90 | |||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | static u8 ixgbe_dcbnl_get_state(struct net_device *netdev) | ||
95 | { | ||
96 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | ||
97 | |||
98 | DPRINTK(DRV, INFO, "Get DCB Admin Mode.\n"); | ||
99 | |||
100 | return !!(adapter->flags & IXGBE_FLAG_DCB_ENABLED); | ||
101 | } | ||
102 | |||
103 | static u16 ixgbe_dcb_select_queue(struct net_device *dev, struct sk_buff *skb) | ||
104 | { | ||
105 | /* All traffic should default to class 0 */ | ||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | static void ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state) | ||
110 | { | ||
111 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | ||
112 | |||
113 | DPRINTK(DRV, INFO, "Set DCB Admin Mode.\n"); | ||
114 | |||
115 | if (state > 0) { | ||
116 | /* Turn on DCB */ | ||
117 | if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { | ||
118 | return; | ||
119 | } else { | ||
120 | if (netif_running(netdev)) | ||
121 | netdev->stop(netdev); | ||
122 | ixgbe_reset_interrupt_capability(adapter); | ||
123 | ixgbe_napi_del_all(adapter); | ||
124 | kfree(adapter->tx_ring); | ||
125 | kfree(adapter->rx_ring); | ||
126 | adapter->tx_ring = NULL; | ||
127 | adapter->rx_ring = NULL; | ||
128 | netdev->select_queue = &ixgbe_dcb_select_queue; | ||
129 | |||
130 | adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED; | ||
131 | adapter->flags |= IXGBE_FLAG_DCB_ENABLED; | ||
132 | ixgbe_init_interrupt_scheme(adapter); | ||
133 | ixgbe_napi_add_all(adapter); | ||
134 | if (netif_running(netdev)) | ||
135 | netdev->open(netdev); | ||
136 | } | ||
137 | } else { | ||
138 | /* Turn off DCB */ | ||
139 | if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { | ||
140 | if (netif_running(netdev)) | ||
141 | netdev->stop(netdev); | ||
142 | ixgbe_reset_interrupt_capability(adapter); | ||
143 | ixgbe_napi_del_all(adapter); | ||
144 | kfree(adapter->tx_ring); | ||
145 | kfree(adapter->rx_ring); | ||
146 | adapter->tx_ring = NULL; | ||
147 | adapter->rx_ring = NULL; | ||
148 | netdev->select_queue = NULL; | ||
149 | |||
150 | adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED; | ||
151 | adapter->flags |= IXGBE_FLAG_RSS_ENABLED; | ||
152 | ixgbe_init_interrupt_scheme(adapter); | ||
153 | ixgbe_napi_add_all(adapter); | ||
154 | if (netif_running(netdev)) | ||
155 | netdev->open(netdev); | ||
156 | } else { | ||
157 | return; | ||
158 | } | ||
159 | } | ||
160 | } | ||
161 | |||
162 | static void ixgbe_dcbnl_get_perm_hw_addr(struct net_device *netdev, | ||
163 | u8 *perm_addr) | ||
164 | { | ||
165 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | ||
166 | int i; | ||
167 | |||
168 | for (i = 0; i < netdev->addr_len; i++) | ||
169 | perm_addr[i] = adapter->hw.mac.perm_addr[i]; | ||
170 | } | ||
171 | |||
172 | static void ixgbe_dcbnl_set_pg_tc_cfg_tx(struct net_device *netdev, int tc, | ||
173 | u8 prio, u8 bwg_id, u8 bw_pct, | ||
174 | u8 up_map) | ||
175 | { | ||
176 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | ||
177 | |||
178 | if (prio != DCB_ATTR_VALUE_UNDEFINED) | ||
179 | adapter->temp_dcb_cfg.tc_config[tc].path[0].prio_type = prio; | ||
180 | if (bwg_id != DCB_ATTR_VALUE_UNDEFINED) | ||
181 | adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_id = bwg_id; | ||
182 | if (bw_pct != DCB_ATTR_VALUE_UNDEFINED) | ||
183 | adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_percent = | ||
184 | bw_pct; | ||
185 | if (up_map != DCB_ATTR_VALUE_UNDEFINED) | ||
186 | adapter->temp_dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap = | ||
187 | up_map; | ||
188 | |||
189 | if ((adapter->temp_dcb_cfg.tc_config[tc].path[0].prio_type != | ||
190 | adapter->dcb_cfg.tc_config[tc].path[0].prio_type) || | ||
191 | (adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_id != | ||
192 | adapter->dcb_cfg.tc_config[tc].path[0].bwg_id) || | ||
193 | (adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_percent != | ||
194 | adapter->dcb_cfg.tc_config[tc].path[0].bwg_percent) || | ||
195 | (adapter->temp_dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap != | ||
196 | adapter->dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap)) | ||
197 | adapter->dcb_set_bitmap |= BIT_PG_TX; | ||
198 | } | ||
199 | |||
200 | static void ixgbe_dcbnl_set_pg_bwg_cfg_tx(struct net_device *netdev, int bwg_id, | ||
201 | u8 bw_pct) | ||
202 | { | ||
203 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | ||
204 | |||
205 | adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] = bw_pct; | ||
206 | |||
207 | if (adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] != | ||
208 | adapter->dcb_cfg.bw_percentage[0][bwg_id]) | ||
209 | adapter->dcb_set_bitmap |= BIT_PG_RX; | ||
210 | } | ||
211 | |||
212 | static void ixgbe_dcbnl_set_pg_tc_cfg_rx(struct net_device *netdev, int tc, | ||
213 | u8 prio, u8 bwg_id, u8 bw_pct, | ||
214 | u8 up_map) | ||
215 | { | ||
216 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | ||
217 | |||
218 | if (prio != DCB_ATTR_VALUE_UNDEFINED) | ||
219 | adapter->temp_dcb_cfg.tc_config[tc].path[1].prio_type = prio; | ||
220 | if (bwg_id != DCB_ATTR_VALUE_UNDEFINED) | ||
221 | adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_id = bwg_id; | ||
222 | if (bw_pct != DCB_ATTR_VALUE_UNDEFINED) | ||
223 | adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_percent = | ||
224 | bw_pct; | ||
225 | if (up_map != DCB_ATTR_VALUE_UNDEFINED) | ||
226 | adapter->temp_dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap = | ||
227 | up_map; | ||
228 | |||
229 | if ((adapter->temp_dcb_cfg.tc_config[tc].path[1].prio_type != | ||
230 | adapter->dcb_cfg.tc_config[tc].path[1].prio_type) || | ||
231 | (adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_id != | ||
232 | adapter->dcb_cfg.tc_config[tc].path[1].bwg_id) || | ||
233 | (adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_percent != | ||
234 | adapter->dcb_cfg.tc_config[tc].path[1].bwg_percent) || | ||
235 | (adapter->temp_dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap != | ||
236 | adapter->dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap)) | ||
237 | adapter->dcb_set_bitmap |= BIT_PG_RX; | ||
238 | } | ||
239 | |||
240 | static void ixgbe_dcbnl_set_pg_bwg_cfg_rx(struct net_device *netdev, int bwg_id, | ||
241 | u8 bw_pct) | ||
242 | { | ||
243 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | ||
244 | |||
245 | adapter->temp_dcb_cfg.bw_percentage[1][bwg_id] = bw_pct; | ||
246 | |||
247 | if (adapter->temp_dcb_cfg.bw_percentage[1][bwg_id] != | ||
248 | adapter->dcb_cfg.bw_percentage[1][bwg_id]) | ||
249 | adapter->dcb_set_bitmap |= BIT_PG_RX; | ||
250 | } | ||
251 | |||
252 | static void ixgbe_dcbnl_get_pg_tc_cfg_tx(struct net_device *netdev, int tc, | ||
253 | u8 *prio, u8 *bwg_id, u8 *bw_pct, | ||
254 | u8 *up_map) | ||
255 | { | ||
256 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | ||
257 | |||
258 | *prio = adapter->dcb_cfg.tc_config[tc].path[0].prio_type; | ||
259 | *bwg_id = adapter->dcb_cfg.tc_config[tc].path[0].bwg_id; | ||
260 | *bw_pct = adapter->dcb_cfg.tc_config[tc].path[0].bwg_percent; | ||
261 | *up_map = adapter->dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap; | ||
262 | } | ||
263 | |||
264 | static void ixgbe_dcbnl_get_pg_bwg_cfg_tx(struct net_device *netdev, int bwg_id, | ||
265 | u8 *bw_pct) | ||
266 | { | ||
267 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | ||
268 | |||
269 | *bw_pct = adapter->dcb_cfg.bw_percentage[0][bwg_id]; | ||
270 | } | ||
271 | |||
272 | static void ixgbe_dcbnl_get_pg_tc_cfg_rx(struct net_device *netdev, int tc, | ||
273 | u8 *prio, u8 *bwg_id, u8 *bw_pct, | ||
274 | u8 *up_map) | ||
275 | { | ||
276 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | ||
277 | |||
278 | *prio = adapter->dcb_cfg.tc_config[tc].path[1].prio_type; | ||
279 | *bwg_id = adapter->dcb_cfg.tc_config[tc].path[1].bwg_id; | ||
280 | *bw_pct = adapter->dcb_cfg.tc_config[tc].path[1].bwg_percent; | ||
281 | *up_map = adapter->dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap; | ||
282 | } | ||
283 | |||
284 | static void ixgbe_dcbnl_get_pg_bwg_cfg_rx(struct net_device *netdev, int bwg_id, | ||
285 | u8 *bw_pct) | ||
286 | { | ||
287 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | ||
288 | |||
289 | *bw_pct = adapter->dcb_cfg.bw_percentage[1][bwg_id]; | ||
290 | } | ||
291 | |||
292 | static void ixgbe_dcbnl_set_pfc_cfg(struct net_device *netdev, int priority, | ||
293 | u8 setting) | ||
294 | { | ||
295 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | ||
296 | |||
297 | adapter->temp_dcb_cfg.tc_config[priority].dcb_pfc = setting; | ||
298 | if (adapter->temp_dcb_cfg.tc_config[priority].dcb_pfc != | ||
299 | adapter->dcb_cfg.tc_config[priority].dcb_pfc) | ||
300 | adapter->dcb_set_bitmap |= BIT_PFC; | ||
301 | } | ||
302 | |||
303 | static void ixgbe_dcbnl_get_pfc_cfg(struct net_device *netdev, int priority, | ||
304 | u8 *setting) | ||
305 | { | ||
306 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | ||
307 | |||
308 | *setting = adapter->dcb_cfg.tc_config[priority].dcb_pfc; | ||
309 | } | ||
310 | |||
311 | static u8 ixgbe_dcbnl_set_all(struct net_device *netdev) | ||
312 | { | ||
313 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | ||
314 | int ret; | ||
315 | |||
316 | if (!adapter->dcb_set_bitmap) | ||
317 | return 1; | ||
318 | |||
319 | while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state)) | ||
320 | msleep(1); | ||
321 | |||
322 | if (netif_running(netdev)) | ||
323 | ixgbe_down(adapter); | ||
324 | |||
325 | ret = ixgbe_copy_dcb_cfg(&adapter->temp_dcb_cfg, &adapter->dcb_cfg, | ||
326 | adapter->ring_feature[RING_F_DCB].indices); | ||
327 | if (ret) { | ||
328 | clear_bit(__IXGBE_RESETTING, &adapter->state); | ||
329 | return ret; | ||
330 | } | ||
331 | |||
332 | if (netif_running(netdev)) | ||
333 | ixgbe_up(adapter); | ||
334 | |||
335 | adapter->dcb_set_bitmap = 0x00; | ||
336 | clear_bit(__IXGBE_RESETTING, &adapter->state); | ||
337 | return ret; | ||
338 | } | ||
339 | |||
340 | struct dcbnl_rtnl_ops dcbnl_ops = { | ||
341 | .getstate = ixgbe_dcbnl_get_state, | ||
342 | .setstate = ixgbe_dcbnl_set_state, | ||
343 | .getpermhwaddr = ixgbe_dcbnl_get_perm_hw_addr, | ||
344 | .setpgtccfgtx = ixgbe_dcbnl_set_pg_tc_cfg_tx, | ||
345 | .setpgbwgcfgtx = ixgbe_dcbnl_set_pg_bwg_cfg_tx, | ||
346 | .setpgtccfgrx = ixgbe_dcbnl_set_pg_tc_cfg_rx, | ||
347 | .setpgbwgcfgrx = ixgbe_dcbnl_set_pg_bwg_cfg_rx, | ||
348 | .getpgtccfgtx = ixgbe_dcbnl_get_pg_tc_cfg_tx, | ||
349 | .getpgbwgcfgtx = ixgbe_dcbnl_get_pg_bwg_cfg_tx, | ||
350 | .getpgtccfgrx = ixgbe_dcbnl_get_pg_tc_cfg_rx, | ||
351 | .getpgbwgcfgrx = ixgbe_dcbnl_get_pg_bwg_cfg_rx, | ||
352 | .setpfccfg = ixgbe_dcbnl_set_pfc_cfg, | ||
353 | .getpfccfg = ixgbe_dcbnl_get_pfc_cfg, | ||
354 | .setall = ixgbe_dcbnl_set_all | ||
355 | }; | ||
356 | |||
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index a610016a0172..aaa4404e7c5f 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c | |||
@@ -97,9 +97,18 @@ static struct ixgbe_stats ixgbe_gstrings_stats[] = { | |||
97 | ((((struct ixgbe_adapter *)netdev_priv(netdev))->num_tx_queues + \ | 97 | ((((struct ixgbe_adapter *)netdev_priv(netdev))->num_tx_queues + \ |
98 | ((struct ixgbe_adapter *)netdev_priv(netdev))->num_rx_queues) * \ | 98 | ((struct ixgbe_adapter *)netdev_priv(netdev))->num_rx_queues) * \ |
99 | (sizeof(struct ixgbe_queue_stats) / sizeof(u64))) | 99 | (sizeof(struct ixgbe_queue_stats) / sizeof(u64))) |
100 | #define IXGBE_STATS_LEN (IXGBE_GLOBAL_STATS_LEN + IXGBE_QUEUE_STATS_LEN) | ||
101 | #define IXGBE_GLOBAL_STATS_LEN ARRAY_SIZE(ixgbe_gstrings_stats) | 100 | #define IXGBE_GLOBAL_STATS_LEN ARRAY_SIZE(ixgbe_gstrings_stats) |
102 | #define IXGBE_STATS_LEN (IXGBE_GLOBAL_STATS_LEN + IXGBE_QUEUE_STATS_LEN) | 101 | #define IXGBE_PB_STATS_LEN ( \ |
102 | (((struct ixgbe_adapter *)netdev->priv)->flags & \ | ||
103 | IXGBE_FLAG_DCB_ENABLED) ? \ | ||
104 | (sizeof(((struct ixgbe_adapter *)0)->stats.pxonrxc) + \ | ||
105 | sizeof(((struct ixgbe_adapter *)0)->stats.pxontxc) + \ | ||
106 | sizeof(((struct ixgbe_adapter *)0)->stats.pxoffrxc) + \ | ||
107 | sizeof(((struct ixgbe_adapter *)0)->stats.pxofftxc)) \ | ||
108 | / sizeof(u64) : 0) | ||
109 | #define IXGBE_STATS_LEN (IXGBE_GLOBAL_STATS_LEN + \ | ||
110 | IXGBE_PB_STATS_LEN + \ | ||
111 | IXGBE_QUEUE_STATS_LEN) | ||
103 | 112 | ||
104 | static int ixgbe_get_settings(struct net_device *netdev, | 113 | static int ixgbe_get_settings(struct net_device *netdev, |
105 | struct ethtool_cmd *ecmd) | 114 | struct ethtool_cmd *ecmd) |
@@ -831,6 +840,16 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev, | |||
831 | data[i + k] = queue_stat[k]; | 840 | data[i + k] = queue_stat[k]; |
832 | i += k; | 841 | i += k; |
833 | } | 842 | } |
843 | if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { | ||
844 | for (j = 0; j < MAX_TX_PACKET_BUFFERS; j++) { | ||
845 | data[i++] = adapter->stats.pxontxc[j]; | ||
846 | data[i++] = adapter->stats.pxofftxc[j]; | ||
847 | } | ||
848 | for (j = 0; j < MAX_RX_PACKET_BUFFERS; j++) { | ||
849 | data[i++] = adapter->stats.pxonrxc[j]; | ||
850 | data[i++] = adapter->stats.pxoffrxc[j]; | ||
851 | } | ||
852 | } | ||
834 | } | 853 | } |
835 | 854 | ||
836 | static void ixgbe_get_strings(struct net_device *netdev, u32 stringset, | 855 | static void ixgbe_get_strings(struct net_device *netdev, u32 stringset, |
@@ -859,6 +878,13 @@ static void ixgbe_get_strings(struct net_device *netdev, u32 stringset, | |||
859 | sprintf(p, "rx_queue_%u_bytes", i); | 878 | sprintf(p, "rx_queue_%u_bytes", i); |
860 | p += ETH_GSTRING_LEN; | 879 | p += ETH_GSTRING_LEN; |
861 | } | 880 | } |
881 | if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { | ||
882 | for (i = 0; i < MAX_TX_PACKET_BUFFERS; i++) { | ||
883 | sprintf(p, "tx_pb_%u_pxon", i); | ||
884 | } | ||
885 | for (i = 0; i < MAX_RX_PACKET_BUFFERS; i++) { | ||
886 | } | ||
887 | } | ||
862 | /* BUG_ON(p - data != IXGBE_STATS_LEN * ETH_GSTRING_LEN); */ | 888 | /* BUG_ON(p - data != IXGBE_STATS_LEN * ETH_GSTRING_LEN); */ |
863 | break; | 889 | break; |
864 | } | 890 | } |
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 40108523377f..91dde9cdab66 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c | |||
@@ -404,7 +404,7 @@ static void ixgbe_receive_skb(struct ixgbe_adapter *adapter, | |||
404 | 404 | ||
405 | if (adapter->netdev->features & NETIF_F_LRO && | 405 | if (adapter->netdev->features & NETIF_F_LRO && |
406 | skb->ip_summed == CHECKSUM_UNNECESSARY) { | 406 | skb->ip_summed == CHECKSUM_UNNECESSARY) { |
407 | if (adapter->vlgrp && is_vlan) | 407 | if (adapter->vlgrp && is_vlan && (tag != 0)) |
408 | lro_vlan_hwaccel_receive_skb(&ring->lro_mgr, skb, | 408 | lro_vlan_hwaccel_receive_skb(&ring->lro_mgr, skb, |
409 | adapter->vlgrp, tag, | 409 | adapter->vlgrp, tag, |
410 | rx_desc); | 410 | rx_desc); |
@@ -413,12 +413,12 @@ static void ixgbe_receive_skb(struct ixgbe_adapter *adapter, | |||
413 | ring->lro_used = true; | 413 | ring->lro_used = true; |
414 | } else { | 414 | } else { |
415 | if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) { | 415 | if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) { |
416 | if (adapter->vlgrp && is_vlan) | 416 | if (adapter->vlgrp && is_vlan && (tag != 0)) |
417 | vlan_hwaccel_receive_skb(skb, adapter->vlgrp, tag); | 417 | vlan_hwaccel_receive_skb(skb, adapter->vlgrp, tag); |
418 | else | 418 | else |
419 | netif_receive_skb(skb); | 419 | netif_receive_skb(skb); |
420 | } else { | 420 | } else { |
421 | if (adapter->vlgrp && is_vlan) | 421 | if (adapter->vlgrp && is_vlan && (tag != 0)) |
422 | vlan_hwaccel_rx(skb, adapter->vlgrp, tag); | 422 | vlan_hwaccel_rx(skb, adapter->vlgrp, tag); |
423 | else | 423 | else |
424 | netif_rx(skb); | 424 | netif_rx(skb); |
@@ -1670,10 +1670,12 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) | |||
1670 | * effects of setting this bit are only that SRRCTL must be | 1670 | * effects of setting this bit are only that SRRCTL must be |
1671 | * fully programmed [0..15] | 1671 | * fully programmed [0..15] |
1672 | */ | 1672 | */ |
1673 | rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL); | 1673 | if (adapter->flags & |
1674 | rdrxctl |= IXGBE_RDRXCTL_MVMEN; | 1674 | (IXGBE_FLAG_RSS_ENABLED | IXGBE_FLAG_VMDQ_ENABLED)) { |
1675 | IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rdrxctl); | 1675 | rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL); |
1676 | 1676 | rdrxctl |= IXGBE_RDRXCTL_MVMEN; | |
1677 | IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rdrxctl); | ||
1678 | } | ||
1677 | 1679 | ||
1678 | if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) { | 1680 | if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) { |
1679 | /* Fill out redirection table */ | 1681 | /* Fill out redirection table */ |
@@ -1732,6 +1734,16 @@ static void ixgbe_vlan_rx_register(struct net_device *netdev, | |||
1732 | ixgbe_irq_disable(adapter); | 1734 | ixgbe_irq_disable(adapter); |
1733 | adapter->vlgrp = grp; | 1735 | adapter->vlgrp = grp; |
1734 | 1736 | ||
1737 | /* | ||
1738 | * For a DCB driver, always enable VLAN tag stripping so we can | ||
1739 | * still receive traffic from a DCB-enabled host even if we're | ||
1740 | * not in DCB mode. | ||
1741 | */ | ||
1742 | ctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_VLNCTRL); | ||
1743 | ctrl |= IXGBE_VLNCTRL_VME; | ||
1744 | ctrl &= ~IXGBE_VLNCTRL_CFIEN; | ||
1745 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_VLNCTRL, ctrl); | ||
1746 | |||
1735 | if (grp) { | 1747 | if (grp) { |
1736 | /* enable VLAN tag insert/strip */ | 1748 | /* enable VLAN tag insert/strip */ |
1737 | ctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_VLNCTRL); | 1749 | ctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_VLNCTRL); |
@@ -1896,6 +1908,44 @@ static void ixgbe_napi_disable_all(struct ixgbe_adapter *adapter) | |||
1896 | } | 1908 | } |
1897 | } | 1909 | } |
1898 | 1910 | ||
1911 | #ifdef CONFIG_IXGBE_DCBNL | ||
1912 | /* | ||
1913 | * ixgbe_configure_dcb - Configure DCB hardware | ||
1914 | * @adapter: ixgbe adapter struct | ||
1915 | * | ||
1916 | * This is called by the driver on open to configure the DCB hardware. | ||
1917 | * This is also called by the gennetlink interface when reconfiguring | ||
1918 | * the DCB state. | ||
1919 | */ | ||
1920 | static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter) | ||
1921 | { | ||
1922 | struct ixgbe_hw *hw = &adapter->hw; | ||
1923 | u32 txdctl, vlnctrl; | ||
1924 | int i, j; | ||
1925 | |||
1926 | ixgbe_dcb_check_config(&adapter->dcb_cfg); | ||
1927 | ixgbe_dcb_calculate_tc_credits(&adapter->dcb_cfg, DCB_TX_CONFIG); | ||
1928 | ixgbe_dcb_calculate_tc_credits(&adapter->dcb_cfg, DCB_RX_CONFIG); | ||
1929 | |||
1930 | /* reconfigure the hardware */ | ||
1931 | ixgbe_dcb_hw_config(&adapter->hw, &adapter->dcb_cfg); | ||
1932 | |||
1933 | for (i = 0; i < adapter->num_tx_queues; i++) { | ||
1934 | j = adapter->tx_ring[i].reg_idx; | ||
1935 | txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j)); | ||
1936 | /* PThresh workaround for Tx hang with DFP enabled. */ | ||
1937 | txdctl |= 32; | ||
1938 | IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(j), txdctl); | ||
1939 | } | ||
1940 | /* Enable VLAN tag insert/strip */ | ||
1941 | vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL); | ||
1942 | vlnctrl |= IXGBE_VLNCTRL_VME | IXGBE_VLNCTRL_VFE; | ||
1943 | vlnctrl &= ~IXGBE_VLNCTRL_CFIEN; | ||
1944 | IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl); | ||
1945 | hw->mac.ops.set_vfta(&adapter->hw, 0, 0, true); | ||
1946 | } | ||
1947 | |||
1948 | #endif | ||
1899 | static void ixgbe_configure(struct ixgbe_adapter *adapter) | 1949 | static void ixgbe_configure(struct ixgbe_adapter *adapter) |
1900 | { | 1950 | { |
1901 | struct net_device *netdev = adapter->netdev; | 1951 | struct net_device *netdev = adapter->netdev; |
@@ -1904,6 +1954,16 @@ static void ixgbe_configure(struct ixgbe_adapter *adapter) | |||
1904 | ixgbe_set_rx_mode(netdev); | 1954 | ixgbe_set_rx_mode(netdev); |
1905 | 1955 | ||
1906 | ixgbe_restore_vlan(adapter); | 1956 | ixgbe_restore_vlan(adapter); |
1957 | #ifdef CONFIG_IXGBE_DCBNL | ||
1958 | if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { | ||
1959 | netif_set_gso_max_size(netdev, 32768); | ||
1960 | ixgbe_configure_dcb(adapter); | ||
1961 | } else { | ||
1962 | netif_set_gso_max_size(netdev, 65536); | ||
1963 | } | ||
1964 | #else | ||
1965 | netif_set_gso_max_size(netdev, 65536); | ||
1966 | #endif | ||
1907 | 1967 | ||
1908 | ixgbe_configure_tx(adapter); | 1968 | ixgbe_configure_tx(adapter); |
1909 | ixgbe_configure_rx(adapter); | 1969 | ixgbe_configure_rx(adapter); |
@@ -1995,9 +2055,6 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) | |||
1995 | 2055 | ||
1996 | ixgbe_irq_enable(adapter); | 2056 | ixgbe_irq_enable(adapter); |
1997 | 2057 | ||
1998 | /* enable transmits */ | ||
1999 | netif_tx_start_all_queues(netdev); | ||
2000 | |||
2001 | /* bring the link up in the watchdog, this could race with our first | 2058 | /* bring the link up in the watchdog, this could race with our first |
2002 | * link up interrupt but shouldn't be a problem */ | 2059 | * link up interrupt but shouldn't be a problem */ |
2003 | adapter->flags |= IXGBE_FLAG_NEED_LINK_UPDATE; | 2060 | adapter->flags |= IXGBE_FLAG_NEED_LINK_UPDATE; |
@@ -2260,6 +2317,11 @@ static void ixgbe_reset_task(struct work_struct *work) | |||
2260 | struct ixgbe_adapter *adapter; | 2317 | struct ixgbe_adapter *adapter; |
2261 | adapter = container_of(work, struct ixgbe_adapter, reset_task); | 2318 | adapter = container_of(work, struct ixgbe_adapter, reset_task); |
2262 | 2319 | ||
2320 | /* If we're already down or resetting, just bail */ | ||
2321 | if (test_bit(__IXGBE_DOWN, &adapter->state) || | ||
2322 | test_bit(__IXGBE_RESETTING, &adapter->state)) | ||
2323 | return; | ||
2324 | |||
2263 | adapter->tx_timeout_count++; | 2325 | adapter->tx_timeout_count++; |
2264 | 2326 | ||
2265 | ixgbe_reinit_locked(adapter); | 2327 | ixgbe_reinit_locked(adapter); |
@@ -2269,15 +2331,31 @@ static void ixgbe_set_num_queues(struct ixgbe_adapter *adapter) | |||
2269 | { | 2331 | { |
2270 | int nrq = 1, ntq = 1; | 2332 | int nrq = 1, ntq = 1; |
2271 | int feature_mask = 0, rss_i, rss_m; | 2333 | int feature_mask = 0, rss_i, rss_m; |
2334 | int dcb_i, dcb_m; | ||
2272 | 2335 | ||
2273 | /* Number of supported queues */ | 2336 | /* Number of supported queues */ |
2274 | switch (adapter->hw.mac.type) { | 2337 | switch (adapter->hw.mac.type) { |
2275 | case ixgbe_mac_82598EB: | 2338 | case ixgbe_mac_82598EB: |
2339 | dcb_i = adapter->ring_feature[RING_F_DCB].indices; | ||
2340 | dcb_m = 0; | ||
2276 | rss_i = adapter->ring_feature[RING_F_RSS].indices; | 2341 | rss_i = adapter->ring_feature[RING_F_RSS].indices; |
2277 | rss_m = 0; | 2342 | rss_m = 0; |
2278 | feature_mask |= IXGBE_FLAG_RSS_ENABLED; | 2343 | feature_mask |= IXGBE_FLAG_RSS_ENABLED; |
2344 | feature_mask |= IXGBE_FLAG_DCB_ENABLED; | ||
2279 | 2345 | ||
2280 | switch (adapter->flags & feature_mask) { | 2346 | switch (adapter->flags & feature_mask) { |
2347 | case (IXGBE_FLAG_RSS_ENABLED | IXGBE_FLAG_DCB_ENABLED): | ||
2348 | dcb_m = 0x7 << 3; | ||
2349 | rss_i = min(8, rss_i); | ||
2350 | rss_m = 0x7; | ||
2351 | nrq = dcb_i * rss_i; | ||
2352 | ntq = min(MAX_TX_QUEUES, dcb_i * rss_i); | ||
2353 | break; | ||
2354 | case (IXGBE_FLAG_DCB_ENABLED): | ||
2355 | dcb_m = 0x7 << 3; | ||
2356 | nrq = dcb_i; | ||
2357 | ntq = dcb_i; | ||
2358 | break; | ||
2281 | case (IXGBE_FLAG_RSS_ENABLED): | 2359 | case (IXGBE_FLAG_RSS_ENABLED): |
2282 | rss_m = 0xF; | 2360 | rss_m = 0xF; |
2283 | nrq = rss_i; | 2361 | nrq = rss_i; |
@@ -2285,6 +2363,8 @@ static void ixgbe_set_num_queues(struct ixgbe_adapter *adapter) | |||
2285 | break; | 2363 | break; |
2286 | case 0: | 2364 | case 0: |
2287 | default: | 2365 | default: |
2366 | dcb_i = 0; | ||
2367 | dcb_m = 0; | ||
2288 | rss_i = 0; | 2368 | rss_i = 0; |
2289 | rss_m = 0; | 2369 | rss_m = 0; |
2290 | nrq = 1; | 2370 | nrq = 1; |
@@ -2292,6 +2372,12 @@ static void ixgbe_set_num_queues(struct ixgbe_adapter *adapter) | |||
2292 | break; | 2372 | break; |
2293 | } | 2373 | } |
2294 | 2374 | ||
2375 | /* Sanity check, we should never have zero queues */ | ||
2376 | nrq = (nrq ?:1); | ||
2377 | ntq = (ntq ?:1); | ||
2378 | |||
2379 | adapter->ring_feature[RING_F_DCB].indices = dcb_i; | ||
2380 | adapter->ring_feature[RING_F_DCB].mask = dcb_m; | ||
2295 | adapter->ring_feature[RING_F_RSS].indices = rss_i; | 2381 | adapter->ring_feature[RING_F_RSS].indices = rss_i; |
2296 | adapter->ring_feature[RING_F_RSS].mask = rss_m; | 2382 | adapter->ring_feature[RING_F_RSS].mask = rss_m; |
2297 | break; | 2383 | break; |
@@ -2343,6 +2429,7 @@ static void ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter, | |||
2343 | adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED; | 2429 | adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED; |
2344 | kfree(adapter->msix_entries); | 2430 | kfree(adapter->msix_entries); |
2345 | adapter->msix_entries = NULL; | 2431 | adapter->msix_entries = NULL; |
2432 | adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED; | ||
2346 | adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED; | 2433 | adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED; |
2347 | ixgbe_set_num_queues(adapter); | 2434 | ixgbe_set_num_queues(adapter); |
2348 | } else { | 2435 | } else { |
@@ -2362,15 +2449,42 @@ static void __devinit ixgbe_cache_ring_register(struct ixgbe_adapter *adapter) | |||
2362 | { | 2449 | { |
2363 | int feature_mask = 0, rss_i; | 2450 | int feature_mask = 0, rss_i; |
2364 | int i, txr_idx, rxr_idx; | 2451 | int i, txr_idx, rxr_idx; |
2452 | int dcb_i; | ||
2365 | 2453 | ||
2366 | /* Number of supported queues */ | 2454 | /* Number of supported queues */ |
2367 | switch (adapter->hw.mac.type) { | 2455 | switch (adapter->hw.mac.type) { |
2368 | case ixgbe_mac_82598EB: | 2456 | case ixgbe_mac_82598EB: |
2457 | dcb_i = adapter->ring_feature[RING_F_DCB].indices; | ||
2369 | rss_i = adapter->ring_feature[RING_F_RSS].indices; | 2458 | rss_i = adapter->ring_feature[RING_F_RSS].indices; |
2370 | txr_idx = 0; | 2459 | txr_idx = 0; |
2371 | rxr_idx = 0; | 2460 | rxr_idx = 0; |
2461 | feature_mask |= IXGBE_FLAG_DCB_ENABLED; | ||
2372 | feature_mask |= IXGBE_FLAG_RSS_ENABLED; | 2462 | feature_mask |= IXGBE_FLAG_RSS_ENABLED; |
2373 | switch (adapter->flags & feature_mask) { | 2463 | switch (adapter->flags & feature_mask) { |
2464 | case (IXGBE_FLAG_RSS_ENABLED | IXGBE_FLAG_DCB_ENABLED): | ||
2465 | for (i = 0; i < dcb_i; i++) { | ||
2466 | int j; | ||
2467 | /* Rx first */ | ||
2468 | for (j = 0; j < adapter->num_rx_queues; j++) { | ||
2469 | adapter->rx_ring[rxr_idx].reg_idx = | ||
2470 | i << 3 | j; | ||
2471 | rxr_idx++; | ||
2472 | } | ||
2473 | /* Tx now */ | ||
2474 | for (j = 0; j < adapter->num_tx_queues; j++) { | ||
2475 | adapter->tx_ring[txr_idx].reg_idx = | ||
2476 | i << 2 | (j >> 1); | ||
2477 | if (j & 1) | ||
2478 | txr_idx++; | ||
2479 | } | ||
2480 | } | ||
2481 | case (IXGBE_FLAG_DCB_ENABLED): | ||
2482 | /* the number of queues is assumed to be symmetric */ | ||
2483 | for (i = 0; i < dcb_i; i++) { | ||
2484 | adapter->rx_ring[i].reg_idx = i << 3; | ||
2485 | adapter->tx_ring[i].reg_idx = i << 2; | ||
2486 | } | ||
2487 | break; | ||
2374 | case (IXGBE_FLAG_RSS_ENABLED): | 2488 | case (IXGBE_FLAG_RSS_ENABLED): |
2375 | for (i = 0; i < adapter->num_rx_queues; i++) | 2489 | for (i = 0; i < adapter->num_rx_queues; i++) |
2376 | adapter->rx_ring[i].reg_idx = i; | 2490 | adapter->rx_ring[i].reg_idx = i; |
@@ -2395,7 +2509,7 @@ static void __devinit ixgbe_cache_ring_register(struct ixgbe_adapter *adapter) | |||
2395 | * number of queues at compile-time. The polling_netdev array is | 2509 | * number of queues at compile-time. The polling_netdev array is |
2396 | * intended for Multiqueue, but should work fine with a single queue. | 2510 | * intended for Multiqueue, but should work fine with a single queue. |
2397 | **/ | 2511 | **/ |
2398 | static int __devinit ixgbe_alloc_queues(struct ixgbe_adapter *adapter) | 2512 | static int ixgbe_alloc_queues(struct ixgbe_adapter *adapter) |
2399 | { | 2513 | { |
2400 | int i; | 2514 | int i; |
2401 | 2515 | ||
@@ -2465,6 +2579,7 @@ static int __devinit ixgbe_set_interrupt_capability(struct ixgbe_adapter | |||
2465 | adapter->msix_entries = kcalloc(v_budget, | 2579 | adapter->msix_entries = kcalloc(v_budget, |
2466 | sizeof(struct msix_entry), GFP_KERNEL); | 2580 | sizeof(struct msix_entry), GFP_KERNEL); |
2467 | if (!adapter->msix_entries) { | 2581 | if (!adapter->msix_entries) { |
2582 | adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED; | ||
2468 | adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED; | 2583 | adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED; |
2469 | ixgbe_set_num_queues(adapter); | 2584 | ixgbe_set_num_queues(adapter); |
2470 | kfree(adapter->tx_ring); | 2585 | kfree(adapter->tx_ring); |
@@ -2505,7 +2620,7 @@ out: | |||
2505 | return err; | 2620 | return err; |
2506 | } | 2621 | } |
2507 | 2622 | ||
2508 | static void ixgbe_reset_interrupt_capability(struct ixgbe_adapter *adapter) | 2623 | void ixgbe_reset_interrupt_capability(struct ixgbe_adapter *adapter) |
2509 | { | 2624 | { |
2510 | if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { | 2625 | if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { |
2511 | adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED; | 2626 | adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED; |
@@ -2529,7 +2644,7 @@ static void ixgbe_reset_interrupt_capability(struct ixgbe_adapter *adapter) | |||
2529 | * - Hardware queue count (num_*_queues) | 2644 | * - Hardware queue count (num_*_queues) |
2530 | * - defined by miscellaneous hardware support/features (RSS, etc.) | 2645 | * - defined by miscellaneous hardware support/features (RSS, etc.) |
2531 | **/ | 2646 | **/ |
2532 | static int __devinit ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter) | 2647 | int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter) |
2533 | { | 2648 | { |
2534 | int err; | 2649 | int err; |
2535 | 2650 | ||
@@ -2577,6 +2692,10 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) | |||
2577 | struct ixgbe_hw *hw = &adapter->hw; | 2692 | struct ixgbe_hw *hw = &adapter->hw; |
2578 | struct pci_dev *pdev = adapter->pdev; | 2693 | struct pci_dev *pdev = adapter->pdev; |
2579 | unsigned int rss; | 2694 | unsigned int rss; |
2695 | #ifdef CONFIG_IXGBE_DCBNL | ||
2696 | int j; | ||
2697 | struct tc_configuration *tc; | ||
2698 | #endif | ||
2580 | 2699 | ||
2581 | /* PCI config space info */ | 2700 | /* PCI config space info */ |
2582 | 2701 | ||
@@ -2590,6 +2709,27 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) | |||
2590 | rss = min(IXGBE_MAX_RSS_INDICES, (int)num_online_cpus()); | 2709 | rss = min(IXGBE_MAX_RSS_INDICES, (int)num_online_cpus()); |
2591 | adapter->ring_feature[RING_F_RSS].indices = rss; | 2710 | adapter->ring_feature[RING_F_RSS].indices = rss; |
2592 | adapter->flags |= IXGBE_FLAG_RSS_ENABLED; | 2711 | adapter->flags |= IXGBE_FLAG_RSS_ENABLED; |
2712 | adapter->ring_feature[RING_F_DCB].indices = IXGBE_MAX_DCB_INDICES; | ||
2713 | |||
2714 | #ifdef CONFIG_IXGBE_DCBNL | ||
2715 | /* Configure DCB traffic classes */ | ||
2716 | for (j = 0; j < MAX_TRAFFIC_CLASS; j++) { | ||
2717 | tc = &adapter->dcb_cfg.tc_config[j]; | ||
2718 | tc->path[DCB_TX_CONFIG].bwg_id = 0; | ||
2719 | tc->path[DCB_TX_CONFIG].bwg_percent = 12 + (j & 1); | ||
2720 | tc->path[DCB_RX_CONFIG].bwg_id = 0; | ||
2721 | tc->path[DCB_RX_CONFIG].bwg_percent = 12 + (j & 1); | ||
2722 | tc->dcb_pfc = pfc_disabled; | ||
2723 | } | ||
2724 | adapter->dcb_cfg.bw_percentage[DCB_TX_CONFIG][0] = 100; | ||
2725 | adapter->dcb_cfg.bw_percentage[DCB_RX_CONFIG][0] = 100; | ||
2726 | adapter->dcb_cfg.rx_pba_cfg = pba_equal; | ||
2727 | adapter->dcb_cfg.round_robin_enable = false; | ||
2728 | adapter->dcb_set_bitmap = 0x00; | ||
2729 | ixgbe_copy_dcb_cfg(&adapter->dcb_cfg, &adapter->temp_dcb_cfg, | ||
2730 | adapter->ring_feature[RING_F_DCB].indices); | ||
2731 | |||
2732 | #endif | ||
2593 | if (hw->mac.ops.get_media_type && | 2733 | if (hw->mac.ops.get_media_type && |
2594 | (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_copper)) | 2734 | (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_copper)) |
2595 | adapter->flags |= IXGBE_FLAG_FAN_FAIL_CAPABLE; | 2735 | adapter->flags |= IXGBE_FLAG_FAN_FAIL_CAPABLE; |
@@ -2967,7 +3107,7 @@ static int ixgbe_close(struct net_device *netdev) | |||
2967 | * @adapter: private struct | 3107 | * @adapter: private struct |
2968 | * helper function to napi_add each possible q_vector->napi | 3108 | * helper function to napi_add each possible q_vector->napi |
2969 | */ | 3109 | */ |
2970 | static void ixgbe_napi_add_all(struct ixgbe_adapter *adapter) | 3110 | void ixgbe_napi_add_all(struct ixgbe_adapter *adapter) |
2971 | { | 3111 | { |
2972 | int q_idx, q_vectors; | 3112 | int q_idx, q_vectors; |
2973 | int (*poll)(struct napi_struct *, int); | 3113 | int (*poll)(struct napi_struct *, int); |
@@ -2988,7 +3128,7 @@ static void ixgbe_napi_add_all(struct ixgbe_adapter *adapter) | |||
2988 | } | 3128 | } |
2989 | } | 3129 | } |
2990 | 3130 | ||
2991 | static void ixgbe_napi_del_all(struct ixgbe_adapter *adapter) | 3131 | void ixgbe_napi_del_all(struct ixgbe_adapter *adapter) |
2992 | { | 3132 | { |
2993 | int q_idx; | 3133 | int q_idx; |
2994 | int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; | 3134 | int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; |
@@ -3109,6 +3249,18 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter) | |||
3109 | adapter->stats.mpc[i] += mpc; | 3249 | adapter->stats.mpc[i] += mpc; |
3110 | total_mpc += adapter->stats.mpc[i]; | 3250 | total_mpc += adapter->stats.mpc[i]; |
3111 | adapter->stats.rnbc[i] += IXGBE_READ_REG(hw, IXGBE_RNBC(i)); | 3251 | adapter->stats.rnbc[i] += IXGBE_READ_REG(hw, IXGBE_RNBC(i)); |
3252 | adapter->stats.qptc[i] += IXGBE_READ_REG(hw, IXGBE_QPTC(i)); | ||
3253 | adapter->stats.qbtc[i] += IXGBE_READ_REG(hw, IXGBE_QBTC(i)); | ||
3254 | adapter->stats.qprc[i] += IXGBE_READ_REG(hw, IXGBE_QPRC(i)); | ||
3255 | adapter->stats.qbrc[i] += IXGBE_READ_REG(hw, IXGBE_QBRC(i)); | ||
3256 | adapter->stats.pxonrxc[i] += IXGBE_READ_REG(hw, | ||
3257 | IXGBE_PXONRXC(i)); | ||
3258 | adapter->stats.pxontxc[i] += IXGBE_READ_REG(hw, | ||
3259 | IXGBE_PXONTXC(i)); | ||
3260 | adapter->stats.pxoffrxc[i] += IXGBE_READ_REG(hw, | ||
3261 | IXGBE_PXOFFRXC(i)); | ||
3262 | adapter->stats.pxofftxc[i] += IXGBE_READ_REG(hw, | ||
3263 | IXGBE_PXOFFTXC(i)); | ||
3112 | } | 3264 | } |
3113 | adapter->stats.gprc += IXGBE_READ_REG(hw, IXGBE_GPRC); | 3265 | adapter->stats.gprc += IXGBE_READ_REG(hw, IXGBE_GPRC); |
3114 | /* work around hardware counting issue */ | 3266 | /* work around hardware counting issue */ |
@@ -3248,6 +3400,7 @@ static void ixgbe_watchdog_task(struct work_struct *work) | |||
3248 | (FLOW_TX ? "TX" : "None")))); | 3400 | (FLOW_TX ? "TX" : "None")))); |
3249 | 3401 | ||
3250 | netif_carrier_on(netdev); | 3402 | netif_carrier_on(netdev); |
3403 | netif_tx_wake_all_queues(netdev); | ||
3251 | } else { | 3404 | } else { |
3252 | /* Force detection of hung controller */ | 3405 | /* Force detection of hung controller */ |
3253 | adapter->detect_tx_hung = true; | 3406 | adapter->detect_tx_hung = true; |
@@ -3258,6 +3411,7 @@ static void ixgbe_watchdog_task(struct work_struct *work) | |||
3258 | if (netif_carrier_ok(netdev)) { | 3411 | if (netif_carrier_ok(netdev)) { |
3259 | DPRINTK(LINK, INFO, "NIC Link is Down\n"); | 3412 | DPRINTK(LINK, INFO, "NIC Link is Down\n"); |
3260 | netif_carrier_off(netdev); | 3413 | netif_carrier_off(netdev); |
3414 | netif_tx_stop_all_queues(netdev); | ||
3261 | } | 3415 | } |
3262 | } | 3416 | } |
3263 | 3417 | ||
@@ -3604,6 +3758,14 @@ static int ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
3604 | 3758 | ||
3605 | if (adapter->vlgrp && vlan_tx_tag_present(skb)) { | 3759 | if (adapter->vlgrp && vlan_tx_tag_present(skb)) { |
3606 | tx_flags |= vlan_tx_tag_get(skb); | 3760 | tx_flags |= vlan_tx_tag_get(skb); |
3761 | if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { | ||
3762 | tx_flags &= ~IXGBE_TX_FLAGS_VLAN_PRIO_MASK; | ||
3763 | tx_flags |= (skb->queue_mapping << 13); | ||
3764 | } | ||
3765 | tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT; | ||
3766 | tx_flags |= IXGBE_TX_FLAGS_VLAN; | ||
3767 | } else if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { | ||
3768 | tx_flags |= (skb->queue_mapping << 13); | ||
3607 | tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT; | 3769 | tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT; |
3608 | tx_flags |= IXGBE_TX_FLAGS_VLAN; | 3770 | tx_flags |= IXGBE_TX_FLAGS_VLAN; |
3609 | } | 3771 | } |
@@ -3878,6 +4040,13 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, | |||
3878 | netdev->vlan_features |= NETIF_F_IP_CSUM; | 4040 | netdev->vlan_features |= NETIF_F_IP_CSUM; |
3879 | netdev->vlan_features |= NETIF_F_SG; | 4041 | netdev->vlan_features |= NETIF_F_SG; |
3880 | 4042 | ||
4043 | if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) | ||
4044 | adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED; | ||
4045 | |||
4046 | #ifdef CONFIG_IXGBE_DCBNL | ||
4047 | netdev->dcbnl_ops = &dcbnl_ops; | ||
4048 | #endif | ||
4049 | |||
3881 | if (pci_using_dac) | 4050 | if (pci_using_dac) |
3882 | netdev->features |= NETIF_F_HIGHDMA; | 4051 | netdev->features |= NETIF_F_HIGHDMA; |
3883 | 4052 | ||
@@ -3946,6 +4115,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, | |||
3946 | } | 4115 | } |
3947 | 4116 | ||
3948 | netif_carrier_off(netdev); | 4117 | netif_carrier_off(netdev); |
4118 | netif_tx_stop_all_queues(netdev); | ||
3949 | 4119 | ||
3950 | ixgbe_napi_add_all(adapter); | 4120 | ixgbe_napi_add_all(adapter); |
3951 | 4121 | ||
diff --git a/include/linux/dcbnl.h b/include/linux/dcbnl.h new file mode 100644 index 000000000000..32d32c1ee410 --- /dev/null +++ b/include/linux/dcbnl.h | |||
@@ -0,0 +1,230 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008, Intel Corporation. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms and conditions of the GNU General Public License, | ||
6 | * version 2, as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
11 | * more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License along with | ||
14 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple | ||
15 | * Place - Suite 330, Boston, MA 02111-1307 USA. | ||
16 | * | ||
17 | * Author: Lucy Liu <lucy.liu@intel.com> | ||
18 | */ | ||
19 | |||
20 | #ifndef __LINUX_DCBNL_H__ | ||
21 | #define __LINUX_DCBNL_H__ | ||
22 | |||
23 | #define DCB_PROTO_VERSION 1 | ||
24 | |||
25 | struct dcbmsg { | ||
26 | unsigned char dcb_family; | ||
27 | __u8 cmd; | ||
28 | __u16 dcb_pad; | ||
29 | }; | ||
30 | |||
31 | /** | ||
32 | * enum dcbnl_commands - supported DCB commands | ||
33 | * | ||
34 | * @DCB_CMD_UNDEFINED: unspecified command to catch errors | ||
35 | * @DCB_CMD_GSTATE: request the state of DCB in the device | ||
36 | * @DCB_CMD_SSTATE: set the state of DCB in the device | ||
37 | * @DCB_CMD_PGTX_GCFG: request the priority group configuration for Tx | ||
38 | * @DCB_CMD_PGTX_SCFG: set the priority group configuration for Tx | ||
39 | * @DCB_CMD_PGRX_GCFG: request the priority group configuration for Rx | ||
40 | * @DCB_CMD_PGRX_SCFG: set the priority group configuration for Rx | ||
41 | * @DCB_CMD_PFC_GCFG: request the priority flow control configuration | ||
42 | * @DCB_CMD_PFC_SCFG: set the priority flow control configuration | ||
43 | * @DCB_CMD_SET_ALL: apply all changes to the underlying device | ||
44 | * @DCB_CMD_GPERM_HWADDR: get the permanent MAC address of the underlying | ||
45 | * device. Only useful when using bonding. | ||
46 | */ | ||
47 | enum dcbnl_commands { | ||
48 | DCB_CMD_UNDEFINED, | ||
49 | |||
50 | DCB_CMD_GSTATE, | ||
51 | DCB_CMD_SSTATE, | ||
52 | |||
53 | DCB_CMD_PGTX_GCFG, | ||
54 | DCB_CMD_PGTX_SCFG, | ||
55 | DCB_CMD_PGRX_GCFG, | ||
56 | DCB_CMD_PGRX_SCFG, | ||
57 | |||
58 | DCB_CMD_PFC_GCFG, | ||
59 | DCB_CMD_PFC_SCFG, | ||
60 | |||
61 | DCB_CMD_SET_ALL, | ||
62 | DCB_CMD_GPERM_HWADDR, | ||
63 | |||
64 | __DCB_CMD_ENUM_MAX, | ||
65 | DCB_CMD_MAX = __DCB_CMD_ENUM_MAX - 1, | ||
66 | }; | ||
67 | |||
68 | |||
69 | /** | ||
70 | * enum dcbnl_attrs - DCB top-level netlink attributes | ||
71 | * | ||
72 | * @DCB_ATTR_UNDEFINED: unspecified attribute to catch errors | ||
73 | * @DCB_ATTR_IFNAME: interface name of the underlying device (NLA_STRING) | ||
74 | * @DCB_ATTR_STATE: enable state of DCB in the device (NLA_U8) | ||
75 | * @DCB_ATTR_PFC_STATE: enable state of PFC in the device (NLA_U8) | ||
76 | * @DCB_ATTR_PFC_CFG: priority flow control configuration (NLA_NESTED) | ||
77 | * @DCB_ATTR_NUM_TC: number of traffic classes supported in the device (NLA_U8) | ||
78 | * @DCB_ATTR_PG_CFG: priority group configuration (NLA_NESTED) | ||
79 | * @DCB_ATTR_SET_ALL: bool to commit changes to hardware or not (NLA_U8) | ||
80 | * @DCB_ATTR_PERM_HWADDR: MAC address of the physical device (NLA_NESTED) | ||
81 | */ | ||
82 | enum dcbnl_attrs { | ||
83 | DCB_ATTR_UNDEFINED, | ||
84 | |||
85 | DCB_ATTR_IFNAME, | ||
86 | DCB_ATTR_STATE, | ||
87 | DCB_ATTR_PFC_STATE, | ||
88 | DCB_ATTR_PFC_CFG, | ||
89 | DCB_ATTR_NUM_TC, | ||
90 | DCB_ATTR_PG_CFG, | ||
91 | DCB_ATTR_SET_ALL, | ||
92 | DCB_ATTR_PERM_HWADDR, | ||
93 | |||
94 | __DCB_ATTR_ENUM_MAX, | ||
95 | DCB_ATTR_MAX = __DCB_ATTR_ENUM_MAX - 1, | ||
96 | }; | ||
97 | |||
98 | /** | ||
99 | * enum dcbnl_pfc_attrs - DCB Priority Flow Control user priority nested attrs | ||
100 | * | ||
101 | * @DCB_PFC_UP_ATTR_UNDEFINED: unspecified attribute to catch errors | ||
102 | * @DCB_PFC_UP_ATTR_0: Priority Flow Control value for User Priority 0 (NLA_U8) | ||
103 | * @DCB_PFC_UP_ATTR_1: Priority Flow Control value for User Priority 1 (NLA_U8) | ||
104 | * @DCB_PFC_UP_ATTR_2: Priority Flow Control value for User Priority 2 (NLA_U8) | ||
105 | * @DCB_PFC_UP_ATTR_3: Priority Flow Control value for User Priority 3 (NLA_U8) | ||
106 | * @DCB_PFC_UP_ATTR_4: Priority Flow Control value for User Priority 4 (NLA_U8) | ||
107 | * @DCB_PFC_UP_ATTR_5: Priority Flow Control value for User Priority 5 (NLA_U8) | ||
108 | * @DCB_PFC_UP_ATTR_6: Priority Flow Control value for User Priority 6 (NLA_U8) | ||
109 | * @DCB_PFC_UP_ATTR_7: Priority Flow Control value for User Priority 7 (NLA_U8) | ||
110 | * @DCB_PFC_UP_ATTR_MAX: highest attribute number currently defined | ||
111 | * @DCB_PFC_UP_ATTR_ALL: apply to all priority flow control attrs (NLA_FLAG) | ||
112 | * | ||
113 | */ | ||
114 | enum dcbnl_pfc_up_attrs { | ||
115 | DCB_PFC_UP_ATTR_UNDEFINED, | ||
116 | |||
117 | DCB_PFC_UP_ATTR_0, | ||
118 | DCB_PFC_UP_ATTR_1, | ||
119 | DCB_PFC_UP_ATTR_2, | ||
120 | DCB_PFC_UP_ATTR_3, | ||
121 | DCB_PFC_UP_ATTR_4, | ||
122 | DCB_PFC_UP_ATTR_5, | ||
123 | DCB_PFC_UP_ATTR_6, | ||
124 | DCB_PFC_UP_ATTR_7, | ||
125 | DCB_PFC_UP_ATTR_ALL, | ||
126 | |||
127 | __DCB_PFC_UP_ATTR_ENUM_MAX, | ||
128 | DCB_PFC_UP_ATTR_MAX = __DCB_PFC_UP_ATTR_ENUM_MAX - 1, | ||
129 | }; | ||
130 | |||
131 | /** | ||
132 | * enum dcbnl_pg_attrs - DCB Priority Group attributes | ||
133 | * | ||
134 | * @DCB_PG_ATTR_UNDEFINED: unspecified attribute to catch errors | ||
135 | * @DCB_PG_ATTR_TC_0: Priority Group Traffic Class 0 configuration (NLA_NESTED) | ||
136 | * @DCB_PG_ATTR_TC_1: Priority Group Traffic Class 1 configuration (NLA_NESTED) | ||
137 | * @DCB_PG_ATTR_TC_2: Priority Group Traffic Class 2 configuration (NLA_NESTED) | ||
138 | * @DCB_PG_ATTR_TC_3: Priority Group Traffic Class 3 configuration (NLA_NESTED) | ||
139 | * @DCB_PG_ATTR_TC_4: Priority Group Traffic Class 4 configuration (NLA_NESTED) | ||
140 | * @DCB_PG_ATTR_TC_5: Priority Group Traffic Class 5 configuration (NLA_NESTED) | ||
141 | * @DCB_PG_ATTR_TC_6: Priority Group Traffic Class 6 configuration (NLA_NESTED) | ||
142 | * @DCB_PG_ATTR_TC_7: Priority Group Traffic Class 7 configuration (NLA_NESTED) | ||
143 | * @DCB_PG_ATTR_TC_MAX: highest attribute number currently defined | ||
144 | * @DCB_PG_ATTR_TC_ALL: apply to all traffic classes (NLA_NESTED) | ||
145 | * @DCB_PG_ATTR_BW_ID_0: Percent of link bandwidth for Priority Group 0 (NLA_U8) | ||
146 | * @DCB_PG_ATTR_BW_ID_1: Percent of link bandwidth for Priority Group 1 (NLA_U8) | ||
147 | * @DCB_PG_ATTR_BW_ID_2: Percent of link bandwidth for Priority Group 2 (NLA_U8) | ||
148 | * @DCB_PG_ATTR_BW_ID_3: Percent of link bandwidth for Priority Group 3 (NLA_U8) | ||
149 | * @DCB_PG_ATTR_BW_ID_4: Percent of link bandwidth for Priority Group 4 (NLA_U8) | ||
150 | * @DCB_PG_ATTR_BW_ID_5: Percent of link bandwidth for Priority Group 5 (NLA_U8) | ||
151 | * @DCB_PG_ATTR_BW_ID_6: Percent of link bandwidth for Priority Group 6 (NLA_U8) | ||
152 | * @DCB_PG_ATTR_BW_ID_7: Percent of link bandwidth for Priority Group 7 (NLA_U8) | ||
153 | * @DCB_PG_ATTR_BW_ID_MAX: highest attribute number currently defined | ||
154 | * @DCB_PG_ATTR_BW_ID_ALL: apply to all priority groups (NLA_FLAG) | ||
155 | * | ||
156 | */ | ||
157 | enum dcbnl_pg_attrs { | ||
158 | DCB_PG_ATTR_UNDEFINED, | ||
159 | |||
160 | DCB_PG_ATTR_TC_0, | ||
161 | DCB_PG_ATTR_TC_1, | ||
162 | DCB_PG_ATTR_TC_2, | ||
163 | DCB_PG_ATTR_TC_3, | ||
164 | DCB_PG_ATTR_TC_4, | ||
165 | DCB_PG_ATTR_TC_5, | ||
166 | DCB_PG_ATTR_TC_6, | ||
167 | DCB_PG_ATTR_TC_7, | ||
168 | DCB_PG_ATTR_TC_MAX, | ||
169 | DCB_PG_ATTR_TC_ALL, | ||
170 | |||
171 | DCB_PG_ATTR_BW_ID_0, | ||
172 | DCB_PG_ATTR_BW_ID_1, | ||
173 | DCB_PG_ATTR_BW_ID_2, | ||
174 | DCB_PG_ATTR_BW_ID_3, | ||
175 | DCB_PG_ATTR_BW_ID_4, | ||
176 | DCB_PG_ATTR_BW_ID_5, | ||
177 | DCB_PG_ATTR_BW_ID_6, | ||
178 | DCB_PG_ATTR_BW_ID_7, | ||
179 | DCB_PG_ATTR_BW_ID_MAX, | ||
180 | DCB_PG_ATTR_BW_ID_ALL, | ||
181 | |||
182 | __DCB_PG_ATTR_ENUM_MAX, | ||
183 | DCB_PG_ATTR_MAX = __DCB_PG_ATTR_ENUM_MAX - 1, | ||
184 | }; | ||
185 | |||
186 | /** | ||
187 | * enum dcbnl_tc_attrs - DCB Traffic Class attributes | ||
188 | * | ||
189 | * @DCB_TC_ATTR_PARAM_UNDEFINED: unspecified attribute to catch errors | ||
190 | * @DCB_TC_ATTR_PARAM_PGID: (NLA_U8) Priority group the traffic class belongs to | ||
191 | * Valid values are: 0-7 | ||
192 | * @DCB_TC_ATTR_PARAM_UP_MAPPING: (NLA_U8) Traffic class to user priority map | ||
193 | * Some devices may not support changing the | ||
194 | * user priority map of a TC. | ||
195 | * @DCB_TC_ATTR_PARAM_STRICT_PRIO: (NLA_U8) Strict priority setting | ||
196 | * 0 - none | ||
197 | * 1 - group strict | ||
198 | * 2 - link strict | ||
199 | * @DCB_TC_ATTR_PARAM_BW_PCT: optional - (NLA_U8) If supported by the device and | ||
200 | * not configured to use link strict priority, | ||
201 | * this is the percentage of bandwidth of the | ||
202 | * priority group this traffic class belongs to | ||
203 | * @DCB_TC_ATTR_PARAM_ALL: (NLA_FLAG) all traffic class parameters | ||
204 | * | ||
205 | */ | ||
206 | enum dcbnl_tc_attrs { | ||
207 | DCB_TC_ATTR_PARAM_UNDEFINED, | ||
208 | |||
209 | DCB_TC_ATTR_PARAM_PGID, | ||
210 | DCB_TC_ATTR_PARAM_UP_MAPPING, | ||
211 | DCB_TC_ATTR_PARAM_STRICT_PRIO, | ||
212 | DCB_TC_ATTR_PARAM_BW_PCT, | ||
213 | DCB_TC_ATTR_PARAM_ALL, | ||
214 | |||
215 | __DCB_TC_ATTR_PARAM_ENUM_MAX, | ||
216 | DCB_TC_ATTR_PARAM_MAX = __DCB_TC_ATTR_PARAM_ENUM_MAX - 1, | ||
217 | }; | ||
218 | |||
219 | /** | ||
220 | * enum dcb_general_attr_values - general DCB attribute values | ||
221 | * | ||
222 | * @DCB_ATTR_UNDEFINED: value used to indicate an attribute is not supported | ||
223 | * | ||
224 | */ | ||
225 | enum dcb_general_attr_values { | ||
226 | DCB_ATTR_VALUE_UNDEFINED = 0xff | ||
227 | }; | ||
228 | |||
229 | |||
230 | #endif /* __LINUX_DCBNL_H__ */ | ||
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index d8fb23679ee3..6095af572dfd 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -43,6 +43,9 @@ | |||
43 | 43 | ||
44 | #include <net/net_namespace.h> | 44 | #include <net/net_namespace.h> |
45 | #include <net/dsa.h> | 45 | #include <net/dsa.h> |
46 | #ifdef CONFIG_DCBNL | ||
47 | #include <net/dcbnl.h> | ||
48 | #endif | ||
46 | 49 | ||
47 | struct vlan_group; | 50 | struct vlan_group; |
48 | struct ethtool_ops; | 51 | struct ethtool_ops; |
@@ -843,6 +846,11 @@ struct net_device | |||
843 | #define GSO_MAX_SIZE 65536 | 846 | #define GSO_MAX_SIZE 65536 |
844 | unsigned int gso_max_size; | 847 | unsigned int gso_max_size; |
845 | 848 | ||
849 | #ifdef CONFIG_DCBNL | ||
850 | /* Data Center Bridging netlink ops */ | ||
851 | struct dcbnl_rtnl_ops *dcbnl_ops; | ||
852 | #endif | ||
853 | |||
846 | #ifdef CONFIG_COMPAT_NET_DEV_OPS | 854 | #ifdef CONFIG_COMPAT_NET_DEV_OPS |
847 | struct { | 855 | struct { |
848 | int (*init)(struct net_device *dev); | 856 | int (*init)(struct net_device *dev); |
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index 2b3d51c6ec9c..e88f7058b3a1 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h | |||
@@ -107,6 +107,11 @@ enum { | |||
107 | RTM_GETADDRLABEL, | 107 | RTM_GETADDRLABEL, |
108 | #define RTM_GETADDRLABEL RTM_GETADDRLABEL | 108 | #define RTM_GETADDRLABEL RTM_GETADDRLABEL |
109 | 109 | ||
110 | RTM_GETDCB = 78, | ||
111 | #define RTM_GETDCB RTM_GETDCB | ||
112 | RTM_SETDCB, | ||
113 | #define RTM_SETDCB RTM_SETDCB | ||
114 | |||
110 | __RTM_MAX, | 115 | __RTM_MAX, |
111 | #define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1) | 116 | #define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1) |
112 | }; | 117 | }; |
diff --git a/include/net/dcbnl.h b/include/net/dcbnl.h new file mode 100644 index 000000000000..0ef0c5a46d8b --- /dev/null +++ b/include/net/dcbnl.h | |||
@@ -0,0 +1,44 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008, Intel Corporation. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms and conditions of the GNU General Public License, | ||
6 | * version 2, as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
11 | * more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License along with | ||
14 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple | ||
15 | * Place - Suite 330, Boston, MA 02111-1307 USA. | ||
16 | * | ||
17 | * Author: Lucy Liu <lucy.liu@intel.com> | ||
18 | */ | ||
19 | |||
20 | #ifndef __NET_DCBNL_H__ | ||
21 | #define __NET_DCBNL_H__ | ||
22 | |||
23 | /* | ||
24 | * Ops struct for the netlink callbacks. Used by DCB-enabled drivers through | ||
25 | * the netdevice struct. | ||
26 | */ | ||
27 | struct dcbnl_rtnl_ops { | ||
28 | u8 (*getstate)(struct net_device *); | ||
29 | void (*setstate)(struct net_device *, u8); | ||
30 | void (*getpermhwaddr)(struct net_device *, u8 *); | ||
31 | void (*setpgtccfgtx)(struct net_device *, int, u8, u8, u8, u8); | ||
32 | void (*setpgbwgcfgtx)(struct net_device *, int, u8); | ||
33 | void (*setpgtccfgrx)(struct net_device *, int, u8, u8, u8, u8); | ||
34 | void (*setpgbwgcfgrx)(struct net_device *, int, u8); | ||
35 | void (*getpgtccfgtx)(struct net_device *, int, u8 *, u8 *, u8 *, u8 *); | ||
36 | void (*getpgbwgcfgtx)(struct net_device *, int, u8 *); | ||
37 | void (*getpgtccfgrx)(struct net_device *, int, u8 *, u8 *, u8 *, u8 *); | ||
38 | void (*getpgbwgcfgrx)(struct net_device *, int, u8 *); | ||
39 | void (*setpfccfg)(struct net_device *, int, u8); | ||
40 | void (*getpfccfg)(struct net_device *, int, u8 *); | ||
41 | u8 (*setall)(struct net_device *); | ||
42 | }; | ||
43 | |||
44 | #endif /* __NET_DCBNL_H__ */ | ||
diff --git a/net/Kconfig b/net/Kconfig index 4e2e40ba8ba6..c7d01c3a23c5 100644 --- a/net/Kconfig +++ b/net/Kconfig | |||
@@ -194,6 +194,7 @@ source "net/lapb/Kconfig" | |||
194 | source "net/econet/Kconfig" | 194 | source "net/econet/Kconfig" |
195 | source "net/wanrouter/Kconfig" | 195 | source "net/wanrouter/Kconfig" |
196 | source "net/sched/Kconfig" | 196 | source "net/sched/Kconfig" |
197 | source "net/dcb/Kconfig" | ||
197 | 198 | ||
198 | menu "Network testing" | 199 | menu "Network testing" |
199 | 200 | ||
diff --git a/net/Makefile b/net/Makefile index 27d1f10dc0e0..83b064651f1d 100644 --- a/net/Makefile +++ b/net/Makefile | |||
@@ -57,6 +57,9 @@ obj-$(CONFIG_NETLABEL) += netlabel/ | |||
57 | obj-$(CONFIG_IUCV) += iucv/ | 57 | obj-$(CONFIG_IUCV) += iucv/ |
58 | obj-$(CONFIG_RFKILL) += rfkill/ | 58 | obj-$(CONFIG_RFKILL) += rfkill/ |
59 | obj-$(CONFIG_NET_9P) += 9p/ | 59 | obj-$(CONFIG_NET_9P) += 9p/ |
60 | ifeq ($(CONFIG_DCBNL),y) | ||
61 | obj-$(CONFIG_DCB) += dcb/ | ||
62 | endif | ||
60 | 63 | ||
61 | ifeq ($(CONFIG_NET),y) | 64 | ifeq ($(CONFIG_NET),y) |
62 | obj-$(CONFIG_SYSCTL) += sysctl_net.o | 65 | obj-$(CONFIG_SYSCTL) += sysctl_net.o |
diff --git a/net/dcb/Kconfig b/net/dcb/Kconfig new file mode 100644 index 000000000000..bdf38802d339 --- /dev/null +++ b/net/dcb/Kconfig | |||
@@ -0,0 +1,12 @@ | |||
1 | config DCB | ||
2 | tristate "Data Center Bridging support" | ||
3 | |||
4 | config DCBNL | ||
5 | bool "Data Center Bridging netlink interface support" | ||
6 | depends on DCB | ||
7 | default n | ||
8 | ---help--- | ||
9 | This option turns on the netlink interface | ||
10 | (dcbnl) for Data Center Bridging capable devices. | ||
11 | |||
12 | If unsure, say N. | ||
diff --git a/net/dcb/Makefile b/net/dcb/Makefile new file mode 100644 index 000000000000..9930f4cde818 --- /dev/null +++ b/net/dcb/Makefile | |||
@@ -0,0 +1 @@ | |||
obj-$(CONFIG_DCB) += dcbnl.o | |||
diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c new file mode 100644 index 000000000000..516e8be83d72 --- /dev/null +++ b/net/dcb/dcbnl.c | |||
@@ -0,0 +1,704 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008, Intel Corporation. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms and conditions of the GNU General Public License, | ||
6 | * version 2, as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
11 | * more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License along with | ||
14 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple | ||
15 | * Place - Suite 330, Boston, MA 02111-1307 USA. | ||
16 | * | ||
17 | * Author: Lucy Liu <lucy.liu@intel.com> | ||
18 | */ | ||
19 | |||
20 | #include <linux/netdevice.h> | ||
21 | #include <linux/netlink.h> | ||
22 | #include <net/netlink.h> | ||
23 | #include <net/rtnetlink.h> | ||
24 | #include <linux/dcbnl.h> | ||
25 | #include <linux/rtnetlink.h> | ||
26 | #include <net/sock.h> | ||
27 | |||
28 | /** | ||
29 | * Data Center Bridging (DCB) is a collection of Ethernet enhancements | ||
30 | * intended to allow network traffic with differing requirements | ||
31 | * (highly reliable, no drops vs. best effort vs. low latency) to operate | ||
32 | * and co-exist on Ethernet. Current DCB features are: | ||
33 | * | ||
34 | * Enhanced Transmission Selection (aka Priority Grouping [PG]) - provides a | ||
35 | * framework for assigning bandwidth guarantees to traffic classes. | ||
36 | * | ||
37 | * Priority-based Flow Control (PFC) - provides a flow control mechanism which | ||
38 | * can work independently for each 802.1p priority. | ||
39 | * | ||
40 | * Congestion Notification - provides a mechanism for end-to-end congestion | ||
41 | * control for protocols which do not have built-in congestion management. | ||
42 | * | ||
43 | * More information about the emerging standards for these Ethernet features | ||
44 | * can be found at: http://www.ieee802.org/1/pages/dcbridges.html | ||
45 | * | ||
46 | * This file implements an rtnetlink interface to allow configuration of DCB | ||
47 | * features for capable devices. | ||
48 | */ | ||
49 | |||
50 | MODULE_AUTHOR("Lucy Liu, <lucy.liu@intel.com>"); | ||
51 | MODULE_DESCRIPTION("Data Center Bridging generic netlink interface"); | ||
52 | MODULE_LICENSE("GPL"); | ||
53 | |||
54 | /**************** DCB attribute policies *************************************/ | ||
55 | |||
56 | /* DCB netlink attributes policy */ | ||
57 | static struct nla_policy dcbnl_rtnl_policy[DCB_ATTR_MAX + 1] = { | ||
58 | [DCB_ATTR_IFNAME] = {.type = NLA_STRING, .len = IFNAMSIZ - 1}, | ||
59 | [DCB_ATTR_STATE] = {.type = NLA_U8}, | ||
60 | [DCB_ATTR_PFC_CFG] = {.type = NLA_NESTED}, | ||
61 | [DCB_ATTR_PG_CFG] = {.type = NLA_NESTED}, | ||
62 | [DCB_ATTR_SET_ALL] = {.type = NLA_U8}, | ||
63 | [DCB_ATTR_PERM_HWADDR] = {.type = NLA_FLAG}, | ||
64 | }; | ||
65 | |||
66 | /* DCB priority flow control to User Priority nested attributes */ | ||
67 | static struct nla_policy dcbnl_pfc_up_nest[DCB_PFC_UP_ATTR_MAX + 1] = { | ||
68 | [DCB_PFC_UP_ATTR_0] = {.type = NLA_U8}, | ||
69 | [DCB_PFC_UP_ATTR_1] = {.type = NLA_U8}, | ||
70 | [DCB_PFC_UP_ATTR_2] = {.type = NLA_U8}, | ||
71 | [DCB_PFC_UP_ATTR_3] = {.type = NLA_U8}, | ||
72 | [DCB_PFC_UP_ATTR_4] = {.type = NLA_U8}, | ||
73 | [DCB_PFC_UP_ATTR_5] = {.type = NLA_U8}, | ||
74 | [DCB_PFC_UP_ATTR_6] = {.type = NLA_U8}, | ||
75 | [DCB_PFC_UP_ATTR_7] = {.type = NLA_U8}, | ||
76 | [DCB_PFC_UP_ATTR_ALL] = {.type = NLA_FLAG}, | ||
77 | }; | ||
78 | |||
79 | /* DCB priority grouping nested attributes */ | ||
80 | static struct nla_policy dcbnl_pg_nest[DCB_PG_ATTR_MAX + 1] = { | ||
81 | [DCB_PG_ATTR_TC_0] = {.type = NLA_NESTED}, | ||
82 | [DCB_PG_ATTR_TC_1] = {.type = NLA_NESTED}, | ||
83 | [DCB_PG_ATTR_TC_2] = {.type = NLA_NESTED}, | ||
84 | [DCB_PG_ATTR_TC_3] = {.type = NLA_NESTED}, | ||
85 | [DCB_PG_ATTR_TC_4] = {.type = NLA_NESTED}, | ||
86 | [DCB_PG_ATTR_TC_5] = {.type = NLA_NESTED}, | ||
87 | [DCB_PG_ATTR_TC_6] = {.type = NLA_NESTED}, | ||
88 | [DCB_PG_ATTR_TC_7] = {.type = NLA_NESTED}, | ||
89 | [DCB_PG_ATTR_TC_ALL] = {.type = NLA_NESTED}, | ||
90 | [DCB_PG_ATTR_BW_ID_0] = {.type = NLA_U8}, | ||
91 | [DCB_PG_ATTR_BW_ID_1] = {.type = NLA_U8}, | ||
92 | [DCB_PG_ATTR_BW_ID_2] = {.type = NLA_U8}, | ||
93 | [DCB_PG_ATTR_BW_ID_3] = {.type = NLA_U8}, | ||
94 | [DCB_PG_ATTR_BW_ID_4] = {.type = NLA_U8}, | ||
95 | [DCB_PG_ATTR_BW_ID_5] = {.type = NLA_U8}, | ||
96 | [DCB_PG_ATTR_BW_ID_6] = {.type = NLA_U8}, | ||
97 | [DCB_PG_ATTR_BW_ID_7] = {.type = NLA_U8}, | ||
98 | [DCB_PG_ATTR_BW_ID_ALL] = {.type = NLA_FLAG}, | ||
99 | }; | ||
100 | |||
101 | /* DCB traffic class nested attributes. */ | ||
102 | static struct nla_policy dcbnl_tc_param_nest[DCB_TC_ATTR_PARAM_MAX + 1] = { | ||
103 | [DCB_TC_ATTR_PARAM_PGID] = {.type = NLA_U8}, | ||
104 | [DCB_TC_ATTR_PARAM_UP_MAPPING] = {.type = NLA_U8}, | ||
105 | [DCB_TC_ATTR_PARAM_STRICT_PRIO] = {.type = NLA_U8}, | ||
106 | [DCB_TC_ATTR_PARAM_BW_PCT] = {.type = NLA_U8}, | ||
107 | [DCB_TC_ATTR_PARAM_ALL] = {.type = NLA_FLAG}, | ||
108 | }; | ||
109 | |||
110 | |||
111 | /* standard netlink reply call */ | ||
112 | static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid, | ||
113 | u32 seq, u16 flags) | ||
114 | { | ||
115 | struct sk_buff *dcbnl_skb; | ||
116 | struct dcbmsg *dcb; | ||
117 | struct nlmsghdr *nlh; | ||
118 | int ret = -EINVAL; | ||
119 | |||
120 | dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
121 | if (!dcbnl_skb) | ||
122 | return ret; | ||
123 | |||
124 | nlh = NLMSG_NEW(dcbnl_skb, pid, seq, event, sizeof(*dcb), flags); | ||
125 | |||
126 | dcb = NLMSG_DATA(nlh); | ||
127 | dcb->dcb_family = AF_UNSPEC; | ||
128 | dcb->cmd = cmd; | ||
129 | dcb->dcb_pad = 0; | ||
130 | |||
131 | ret = nla_put_u8(dcbnl_skb, attr, value); | ||
132 | if (ret) | ||
133 | goto err; | ||
134 | |||
135 | /* end the message, assign the nlmsg_len. */ | ||
136 | nlmsg_end(dcbnl_skb, nlh); | ||
137 | ret = rtnl_unicast(dcbnl_skb, &init_net, pid); | ||
138 | if (ret) | ||
139 | goto err; | ||
140 | |||
141 | return 0; | ||
142 | nlmsg_failure: | ||
143 | err: | ||
144 | kfree(dcbnl_skb); | ||
145 | return ret; | ||
146 | } | ||
147 | |||
148 | static int dcbnl_getstate(struct net_device *netdev, struct nlattr **tb, | ||
149 | u32 pid, u32 seq, u16 flags) | ||
150 | { | ||
151 | int ret = -EINVAL; | ||
152 | |||
153 | /* if (!tb[DCB_ATTR_STATE] || !netdev->dcbnl_ops->getstate) */ | ||
154 | if (!netdev->dcbnl_ops->getstate) | ||
155 | return ret; | ||
156 | |||
157 | ret = dcbnl_reply(netdev->dcbnl_ops->getstate(netdev), RTM_GETDCB, | ||
158 | DCB_CMD_GSTATE, DCB_ATTR_STATE, pid, seq, flags); | ||
159 | |||
160 | return ret; | ||
161 | } | ||
162 | |||
163 | static int dcbnl_getpfccfg(struct net_device *netdev, struct nlattr **tb, | ||
164 | u32 pid, u32 seq, u16 flags) | ||
165 | { | ||
166 | struct sk_buff *dcbnl_skb; | ||
167 | struct nlmsghdr *nlh; | ||
168 | struct dcbmsg *dcb; | ||
169 | struct nlattr *data[DCB_PFC_UP_ATTR_MAX + 1], *nest; | ||
170 | u8 value; | ||
171 | int ret = -EINVAL; | ||
172 | int i; | ||
173 | int getall = 0; | ||
174 | |||
175 | if (!tb[DCB_ATTR_PFC_CFG] || !netdev->dcbnl_ops->getpfccfg) | ||
176 | return ret; | ||
177 | |||
178 | ret = nla_parse_nested(data, DCB_PFC_UP_ATTR_MAX, | ||
179 | tb[DCB_ATTR_PFC_CFG], | ||
180 | dcbnl_pfc_up_nest); | ||
181 | if (ret) | ||
182 | goto err_out; | ||
183 | |||
184 | dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
185 | if (!dcbnl_skb) | ||
186 | goto err_out; | ||
187 | |||
188 | nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); | ||
189 | |||
190 | dcb = NLMSG_DATA(nlh); | ||
191 | dcb->dcb_family = AF_UNSPEC; | ||
192 | dcb->cmd = DCB_CMD_PFC_GCFG; | ||
193 | |||
194 | nest = nla_nest_start(dcbnl_skb, DCB_ATTR_PFC_CFG); | ||
195 | if (!nest) | ||
196 | goto err; | ||
197 | |||
198 | if (data[DCB_PFC_UP_ATTR_ALL]) | ||
199 | getall = 1; | ||
200 | |||
201 | for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) { | ||
202 | if (!getall && !data[i]) | ||
203 | continue; | ||
204 | |||
205 | netdev->dcbnl_ops->getpfccfg(netdev, i - DCB_PFC_UP_ATTR_0, | ||
206 | &value); | ||
207 | ret = nla_put_u8(dcbnl_skb, i, value); | ||
208 | |||
209 | if (ret) { | ||
210 | nla_nest_cancel(dcbnl_skb, nest); | ||
211 | goto err; | ||
212 | } | ||
213 | } | ||
214 | nla_nest_end(dcbnl_skb, nest); | ||
215 | |||
216 | nlmsg_end(dcbnl_skb, nlh); | ||
217 | |||
218 | ret = rtnl_unicast(dcbnl_skb, &init_net, pid); | ||
219 | if (ret) | ||
220 | goto err; | ||
221 | |||
222 | return 0; | ||
223 | nlmsg_failure: | ||
224 | err: | ||
225 | kfree(dcbnl_skb); | ||
226 | err_out: | ||
227 | return -EINVAL; | ||
228 | } | ||
229 | |||
230 | static int dcbnl_getperm_hwaddr(struct net_device *netdev, struct nlattr **tb, | ||
231 | u32 pid, u32 seq, u16 flags) | ||
232 | { | ||
233 | struct sk_buff *dcbnl_skb; | ||
234 | struct nlmsghdr *nlh; | ||
235 | struct dcbmsg *dcb; | ||
236 | u8 perm_addr[MAX_ADDR_LEN]; | ||
237 | int ret = -EINVAL; | ||
238 | |||
239 | if (!netdev->dcbnl_ops->getpermhwaddr) | ||
240 | return ret; | ||
241 | |||
242 | dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
243 | if (!dcbnl_skb) | ||
244 | goto err_out; | ||
245 | |||
246 | nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); | ||
247 | |||
248 | dcb = NLMSG_DATA(nlh); | ||
249 | dcb->dcb_family = AF_UNSPEC; | ||
250 | dcb->cmd = DCB_CMD_GPERM_HWADDR; | ||
251 | |||
252 | netdev->dcbnl_ops->getpermhwaddr(netdev, perm_addr); | ||
253 | |||
254 | ret = nla_put(dcbnl_skb, DCB_ATTR_PERM_HWADDR, sizeof(perm_addr), | ||
255 | perm_addr); | ||
256 | |||
257 | nlmsg_end(dcbnl_skb, nlh); | ||
258 | |||
259 | ret = rtnl_unicast(dcbnl_skb, &init_net, pid); | ||
260 | if (ret) | ||
261 | goto err; | ||
262 | |||
263 | return 0; | ||
264 | |||
265 | nlmsg_failure: | ||
266 | err: | ||
267 | kfree(dcbnl_skb); | ||
268 | err_out: | ||
269 | return -EINVAL; | ||
270 | } | ||
271 | |||
272 | static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlattr **tb, | ||
273 | u32 pid, u32 seq, u16 flags, int dir) | ||
274 | { | ||
275 | struct sk_buff *dcbnl_skb; | ||
276 | struct nlmsghdr *nlh; | ||
277 | struct dcbmsg *dcb; | ||
278 | struct nlattr *pg_nest, *param_nest, *data; | ||
279 | struct nlattr *pg_tb[DCB_PG_ATTR_MAX + 1]; | ||
280 | struct nlattr *param_tb[DCB_TC_ATTR_PARAM_MAX + 1]; | ||
281 | u8 prio, pgid, tc_pct, up_map; | ||
282 | int ret = -EINVAL; | ||
283 | int getall = 0; | ||
284 | int i; | ||
285 | |||
286 | if (!tb[DCB_ATTR_PG_CFG] || | ||
287 | !netdev->dcbnl_ops->getpgtccfgtx || | ||
288 | !netdev->dcbnl_ops->getpgtccfgrx || | ||
289 | !netdev->dcbnl_ops->getpgbwgcfgtx || | ||
290 | !netdev->dcbnl_ops->getpgbwgcfgrx) | ||
291 | return ret; | ||
292 | |||
293 | ret = nla_parse_nested(pg_tb, DCB_PG_ATTR_MAX, | ||
294 | tb[DCB_ATTR_PG_CFG], dcbnl_pg_nest); | ||
295 | |||
296 | if (ret) | ||
297 | goto err_out; | ||
298 | |||
299 | dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
300 | if (!dcbnl_skb) | ||
301 | goto err_out; | ||
302 | |||
303 | nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); | ||
304 | |||
305 | dcb = NLMSG_DATA(nlh); | ||
306 | dcb->dcb_family = AF_UNSPEC; | ||
307 | dcb->cmd = (dir) ? DCB_CMD_PGRX_GCFG : DCB_CMD_PGTX_GCFG; | ||
308 | |||
309 | pg_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_PG_CFG); | ||
310 | if (!pg_nest) | ||
311 | goto err; | ||
312 | |||
313 | if (pg_tb[DCB_PG_ATTR_TC_ALL]) | ||
314 | getall = 1; | ||
315 | |||
316 | for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) { | ||
317 | if (!getall && !pg_tb[i]) | ||
318 | continue; | ||
319 | |||
320 | if (pg_tb[DCB_PG_ATTR_TC_ALL]) | ||
321 | data = pg_tb[DCB_PG_ATTR_TC_ALL]; | ||
322 | else | ||
323 | data = pg_tb[i]; | ||
324 | ret = nla_parse_nested(param_tb, DCB_TC_ATTR_PARAM_MAX, | ||
325 | data, dcbnl_tc_param_nest); | ||
326 | if (ret) | ||
327 | goto err_pg; | ||
328 | |||
329 | param_nest = nla_nest_start(dcbnl_skb, i); | ||
330 | if (!param_nest) | ||
331 | goto err_pg; | ||
332 | |||
333 | pgid = DCB_ATTR_VALUE_UNDEFINED; | ||
334 | prio = DCB_ATTR_VALUE_UNDEFINED; | ||
335 | tc_pct = DCB_ATTR_VALUE_UNDEFINED; | ||
336 | up_map = DCB_ATTR_VALUE_UNDEFINED; | ||
337 | |||
338 | if (dir) { | ||
339 | /* Rx */ | ||
340 | netdev->dcbnl_ops->getpgtccfgrx(netdev, | ||
341 | i - DCB_PG_ATTR_TC_0, &prio, | ||
342 | &pgid, &tc_pct, &up_map); | ||
343 | } else { | ||
344 | /* Tx */ | ||
345 | netdev->dcbnl_ops->getpgtccfgtx(netdev, | ||
346 | i - DCB_PG_ATTR_TC_0, &prio, | ||
347 | &pgid, &tc_pct, &up_map); | ||
348 | } | ||
349 | |||
350 | if (param_tb[DCB_TC_ATTR_PARAM_PGID] || | ||
351 | param_tb[DCB_TC_ATTR_PARAM_ALL]) { | ||
352 | ret = nla_put_u8(dcbnl_skb, | ||
353 | DCB_TC_ATTR_PARAM_PGID, pgid); | ||
354 | if (ret) | ||
355 | goto err_param; | ||
356 | } | ||
357 | if (param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING] || | ||
358 | param_tb[DCB_TC_ATTR_PARAM_ALL]) { | ||
359 | ret = nla_put_u8(dcbnl_skb, | ||
360 | DCB_TC_ATTR_PARAM_UP_MAPPING, up_map); | ||
361 | if (ret) | ||
362 | goto err_param; | ||
363 | } | ||
364 | if (param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO] || | ||
365 | param_tb[DCB_TC_ATTR_PARAM_ALL]) { | ||
366 | ret = nla_put_u8(dcbnl_skb, | ||
367 | DCB_TC_ATTR_PARAM_STRICT_PRIO, prio); | ||
368 | if (ret) | ||
369 | goto err_param; | ||
370 | } | ||
371 | if (param_tb[DCB_TC_ATTR_PARAM_BW_PCT] || | ||
372 | param_tb[DCB_TC_ATTR_PARAM_ALL]) { | ||
373 | ret = nla_put_u8(dcbnl_skb, DCB_TC_ATTR_PARAM_BW_PCT, | ||
374 | tc_pct); | ||
375 | if (ret) | ||
376 | goto err_param; | ||
377 | } | ||
378 | nla_nest_end(dcbnl_skb, param_nest); | ||
379 | } | ||
380 | |||
381 | if (pg_tb[DCB_PG_ATTR_BW_ID_ALL]) | ||
382 | getall = 1; | ||
383 | else | ||
384 | getall = 0; | ||
385 | |||
386 | for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) { | ||
387 | if (!getall && !pg_tb[i]) | ||
388 | continue; | ||
389 | |||
390 | tc_pct = DCB_ATTR_VALUE_UNDEFINED; | ||
391 | |||
392 | if (dir) { | ||
393 | /* Rx */ | ||
394 | netdev->dcbnl_ops->getpgbwgcfgrx(netdev, | ||
395 | i - DCB_PG_ATTR_BW_ID_0, &tc_pct); | ||
396 | } else { | ||
397 | /* Tx */ | ||
398 | netdev->dcbnl_ops->getpgbwgcfgtx(netdev, | ||
399 | i - DCB_PG_ATTR_BW_ID_0, &tc_pct); | ||
400 | } | ||
401 | ret = nla_put_u8(dcbnl_skb, i, tc_pct); | ||
402 | |||
403 | if (ret) | ||
404 | goto err_pg; | ||
405 | } | ||
406 | |||
407 | nla_nest_end(dcbnl_skb, pg_nest); | ||
408 | |||
409 | nlmsg_end(dcbnl_skb, nlh); | ||
410 | |||
411 | ret = rtnl_unicast(dcbnl_skb, &init_net, pid); | ||
412 | if (ret) | ||
413 | goto err; | ||
414 | |||
415 | return 0; | ||
416 | |||
417 | err_param: | ||
418 | nla_nest_cancel(dcbnl_skb, param_nest); | ||
419 | err_pg: | ||
420 | nla_nest_cancel(dcbnl_skb, pg_nest); | ||
421 | nlmsg_failure: | ||
422 | err: | ||
423 | kfree(dcbnl_skb); | ||
424 | err_out: | ||
425 | ret = -EINVAL; | ||
426 | return ret; | ||
427 | } | ||
428 | |||
429 | static int dcbnl_pgtx_getcfg(struct net_device *netdev, struct nlattr **tb, | ||
430 | u32 pid, u32 seq, u16 flags) | ||
431 | { | ||
432 | return __dcbnl_pg_getcfg(netdev, tb, pid, seq, flags, 0); | ||
433 | } | ||
434 | |||
435 | static int dcbnl_pgrx_getcfg(struct net_device *netdev, struct nlattr **tb, | ||
436 | u32 pid, u32 seq, u16 flags) | ||
437 | { | ||
438 | return __dcbnl_pg_getcfg(netdev, tb, pid, seq, flags, 1); | ||
439 | } | ||
440 | |||
441 | static int dcbnl_setstate(struct net_device *netdev, struct nlattr **tb, | ||
442 | u32 pid, u32 seq, u16 flags) | ||
443 | { | ||
444 | int ret = -EINVAL; | ||
445 | u8 value; | ||
446 | |||
447 | if (!tb[DCB_ATTR_STATE] || !netdev->dcbnl_ops->setstate) | ||
448 | return ret; | ||
449 | |||
450 | value = nla_get_u8(tb[DCB_ATTR_STATE]); | ||
451 | |||
452 | netdev->dcbnl_ops->setstate(netdev, value); | ||
453 | |||
454 | ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_SSTATE, DCB_ATTR_STATE, | ||
455 | pid, seq, flags); | ||
456 | |||
457 | return ret; | ||
458 | } | ||
459 | |||
460 | static int dcbnl_setpfccfg(struct net_device *netdev, struct nlattr **tb, | ||
461 | u32 pid, u32 seq, u16 flags) | ||
462 | { | ||
463 | struct nlattr *data[DCB_PFC_UP_ATTR_MAX + 1]; | ||
464 | int i; | ||
465 | int ret = -EINVAL; | ||
466 | u8 value; | ||
467 | |||
468 | if (!tb[DCB_ATTR_PFC_CFG] || !netdev->dcbnl_ops->setpfccfg) | ||
469 | return ret; | ||
470 | |||
471 | ret = nla_parse_nested(data, DCB_PFC_UP_ATTR_MAX, | ||
472 | tb[DCB_ATTR_PFC_CFG], | ||
473 | dcbnl_pfc_up_nest); | ||
474 | if (ret) | ||
475 | goto err; | ||
476 | |||
477 | for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) { | ||
478 | if (data[i] == NULL) | ||
479 | continue; | ||
480 | value = nla_get_u8(data[i]); | ||
481 | netdev->dcbnl_ops->setpfccfg(netdev, | ||
482 | data[i]->nla_type - DCB_PFC_UP_ATTR_0, value); | ||
483 | } | ||
484 | |||
485 | ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_PFC_SCFG, DCB_ATTR_PFC_CFG, | ||
486 | pid, seq, flags); | ||
487 | err: | ||
488 | return ret; | ||
489 | } | ||
490 | |||
491 | static int dcbnl_setall(struct net_device *netdev, struct nlattr **tb, | ||
492 | u32 pid, u32 seq, u16 flags) | ||
493 | { | ||
494 | int ret = -EINVAL; | ||
495 | |||
496 | if (!tb[DCB_ATTR_SET_ALL] || !netdev->dcbnl_ops->setall) | ||
497 | return ret; | ||
498 | |||
499 | ret = dcbnl_reply(netdev->dcbnl_ops->setall(netdev), RTM_SETDCB, | ||
500 | DCB_CMD_SET_ALL, DCB_ATTR_SET_ALL, pid, seq, flags); | ||
501 | |||
502 | return ret; | ||
503 | } | ||
504 | |||
505 | static int __dcbnl_pg_setcfg(struct net_device *netdev, struct nlattr **tb, | ||
506 | u32 pid, u32 seq, u16 flags, int dir) | ||
507 | { | ||
508 | struct nlattr *pg_tb[DCB_PG_ATTR_MAX + 1]; | ||
509 | struct nlattr *param_tb[DCB_TC_ATTR_PARAM_MAX + 1]; | ||
510 | int ret = -EINVAL; | ||
511 | int i; | ||
512 | u8 pgid; | ||
513 | u8 up_map; | ||
514 | u8 prio; | ||
515 | u8 tc_pct; | ||
516 | |||
517 | if (!tb[DCB_ATTR_PG_CFG] || | ||
518 | !netdev->dcbnl_ops->setpgtccfgtx || | ||
519 | !netdev->dcbnl_ops->setpgtccfgrx || | ||
520 | !netdev->dcbnl_ops->setpgbwgcfgtx || | ||
521 | !netdev->dcbnl_ops->setpgbwgcfgrx) | ||
522 | return ret; | ||
523 | |||
524 | ret = nla_parse_nested(pg_tb, DCB_PG_ATTR_MAX, | ||
525 | tb[DCB_ATTR_PG_CFG], dcbnl_pg_nest); | ||
526 | if (ret) | ||
527 | goto err; | ||
528 | |||
529 | for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) { | ||
530 | if (!pg_tb[i]) | ||
531 | continue; | ||
532 | |||
533 | ret = nla_parse_nested(param_tb, DCB_TC_ATTR_PARAM_MAX, | ||
534 | pg_tb[i], dcbnl_tc_param_nest); | ||
535 | if (ret) | ||
536 | goto err; | ||
537 | |||
538 | pgid = DCB_ATTR_VALUE_UNDEFINED; | ||
539 | prio = DCB_ATTR_VALUE_UNDEFINED; | ||
540 | tc_pct = DCB_ATTR_VALUE_UNDEFINED; | ||
541 | up_map = DCB_ATTR_VALUE_UNDEFINED; | ||
542 | |||
543 | if (param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO]) | ||
544 | prio = | ||
545 | nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO]); | ||
546 | |||
547 | if (param_tb[DCB_TC_ATTR_PARAM_PGID]) | ||
548 | pgid = nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_PGID]); | ||
549 | |||
550 | if (param_tb[DCB_TC_ATTR_PARAM_BW_PCT]) | ||
551 | tc_pct = nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_BW_PCT]); | ||
552 | |||
553 | if (param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING]) | ||
554 | up_map = | ||
555 | nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING]); | ||
556 | |||
557 | /* dir: Tx = 0, Rx = 1 */ | ||
558 | if (dir) { | ||
559 | /* Rx */ | ||
560 | netdev->dcbnl_ops->setpgtccfgrx(netdev, | ||
561 | i - DCB_PG_ATTR_TC_0, | ||
562 | prio, pgid, tc_pct, up_map); | ||
563 | } else { | ||
564 | /* Tx */ | ||
565 | netdev->dcbnl_ops->setpgtccfgtx(netdev, | ||
566 | i - DCB_PG_ATTR_TC_0, | ||
567 | prio, pgid, tc_pct, up_map); | ||
568 | } | ||
569 | } | ||
570 | |||
571 | for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) { | ||
572 | if (!pg_tb[i]) | ||
573 | continue; | ||
574 | |||
575 | tc_pct = nla_get_u8(pg_tb[i]); | ||
576 | |||
577 | /* dir: Tx = 0, Rx = 1 */ | ||
578 | if (dir) { | ||
579 | /* Rx */ | ||
580 | netdev->dcbnl_ops->setpgbwgcfgrx(netdev, | ||
581 | i - DCB_PG_ATTR_BW_ID_0, tc_pct); | ||
582 | } else { | ||
583 | /* Tx */ | ||
584 | netdev->dcbnl_ops->setpgbwgcfgtx(netdev, | ||
585 | i - DCB_PG_ATTR_BW_ID_0, tc_pct); | ||
586 | } | ||
587 | } | ||
588 | |||
589 | ret = dcbnl_reply(0, RTM_SETDCB, | ||
590 | (dir ? DCB_CMD_PGRX_SCFG : DCB_CMD_PGTX_SCFG), | ||
591 | DCB_ATTR_PG_CFG, pid, seq, flags); | ||
592 | |||
593 | err: | ||
594 | return ret; | ||
595 | } | ||
596 | |||
597 | static int dcbnl_pgtx_setcfg(struct net_device *netdev, struct nlattr **tb, | ||
598 | u32 pid, u32 seq, u16 flags) | ||
599 | { | ||
600 | return __dcbnl_pg_setcfg(netdev, tb, pid, seq, flags, 0); | ||
601 | } | ||
602 | |||
603 | static int dcbnl_pgrx_setcfg(struct net_device *netdev, struct nlattr **tb, | ||
604 | u32 pid, u32 seq, u16 flags) | ||
605 | { | ||
606 | return __dcbnl_pg_setcfg(netdev, tb, pid, seq, flags, 1); | ||
607 | } | ||
608 | |||
609 | static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | ||
610 | { | ||
611 | struct net *net = sock_net(skb->sk); | ||
612 | struct net_device *netdev; | ||
613 | struct dcbmsg *dcb = (struct dcbmsg *)NLMSG_DATA(nlh); | ||
614 | struct nlattr *tb[DCB_ATTR_MAX + 1]; | ||
615 | u32 pid = skb ? NETLINK_CB(skb).pid : 0; | ||
616 | int ret = -EINVAL; | ||
617 | |||
618 | if (net != &init_net) | ||
619 | return -EINVAL; | ||
620 | |||
621 | ret = nlmsg_parse(nlh, sizeof(*dcb), tb, DCB_ATTR_MAX, | ||
622 | dcbnl_rtnl_policy); | ||
623 | if (ret < 0) | ||
624 | return ret; | ||
625 | |||
626 | if (!tb[DCB_ATTR_IFNAME]) | ||
627 | return -EINVAL; | ||
628 | |||
629 | netdev = dev_get_by_name(&init_net, nla_data(tb[DCB_ATTR_IFNAME])); | ||
630 | if (!netdev) | ||
631 | return -EINVAL; | ||
632 | |||
633 | if (!netdev->dcbnl_ops) | ||
634 | goto errout; | ||
635 | |||
636 | switch (dcb->cmd) { | ||
637 | case DCB_CMD_GSTATE: | ||
638 | ret = dcbnl_getstate(netdev, tb, pid, nlh->nlmsg_seq, | ||
639 | nlh->nlmsg_flags); | ||
640 | goto out; | ||
641 | case DCB_CMD_PFC_GCFG: | ||
642 | ret = dcbnl_getpfccfg(netdev, tb, pid, nlh->nlmsg_seq, | ||
643 | nlh->nlmsg_flags); | ||
644 | goto out; | ||
645 | case DCB_CMD_GPERM_HWADDR: | ||
646 | ret = dcbnl_getperm_hwaddr(netdev, tb, pid, nlh->nlmsg_seq, | ||
647 | nlh->nlmsg_flags); | ||
648 | goto out; | ||
649 | case DCB_CMD_PGTX_GCFG: | ||
650 | ret = dcbnl_pgtx_getcfg(netdev, tb, pid, nlh->nlmsg_seq, | ||
651 | nlh->nlmsg_flags); | ||
652 | goto out; | ||
653 | case DCB_CMD_PGRX_GCFG: | ||
654 | ret = dcbnl_pgrx_getcfg(netdev, tb, pid, nlh->nlmsg_seq, | ||
655 | nlh->nlmsg_flags); | ||
656 | goto out; | ||
657 | case DCB_CMD_SSTATE: | ||
658 | ret = dcbnl_setstate(netdev, tb, pid, nlh->nlmsg_seq, | ||
659 | nlh->nlmsg_flags); | ||
660 | goto out; | ||
661 | case DCB_CMD_PFC_SCFG: | ||
662 | ret = dcbnl_setpfccfg(netdev, tb, pid, nlh->nlmsg_seq, | ||
663 | nlh->nlmsg_flags); | ||
664 | goto out; | ||
665 | |||
666 | case DCB_CMD_SET_ALL: | ||
667 | ret = dcbnl_setall(netdev, tb, pid, nlh->nlmsg_seq, | ||
668 | nlh->nlmsg_flags); | ||
669 | goto out; | ||
670 | case DCB_CMD_PGTX_SCFG: | ||
671 | ret = dcbnl_pgtx_setcfg(netdev, tb, pid, nlh->nlmsg_seq, | ||
672 | nlh->nlmsg_flags); | ||
673 | goto out; | ||
674 | case DCB_CMD_PGRX_SCFG: | ||
675 | ret = dcbnl_pgrx_setcfg(netdev, tb, pid, nlh->nlmsg_seq, | ||
676 | nlh->nlmsg_flags); | ||
677 | goto out; | ||
678 | default: | ||
679 | goto errout; | ||
680 | } | ||
681 | errout: | ||
682 | ret = -EINVAL; | ||
683 | out: | ||
684 | dev_put(netdev); | ||
685 | return ret; | ||
686 | } | ||
687 | |||
688 | static int __init dcbnl_init(void) | ||
689 | { | ||
690 | rtnl_register(PF_UNSPEC, RTM_GETDCB, dcb_doit, NULL); | ||
691 | rtnl_register(PF_UNSPEC, RTM_SETDCB, dcb_doit, NULL); | ||
692 | |||
693 | return 0; | ||
694 | } | ||
695 | module_init(dcbnl_init); | ||
696 | |||
697 | static void __exit dcbnl_exit(void) | ||
698 | { | ||
699 | rtnl_unregister(PF_UNSPEC, RTM_GETDCB); | ||
700 | rtnl_unregister(PF_UNSPEC, RTM_SETDCB); | ||
701 | } | ||
702 | module_exit(dcbnl_exit); | ||
703 | |||
704 | |||