aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Fastabend <john.r.fastabend@intel.com>2011-02-10 09:40:01 -0500
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2011-02-11 11:47:15 -0500
commitd033d526a465c4bb8a499a0b5df65b3e7cf4da6f (patch)
tree570fba34e3fe39dd158dbf38296ca486298b2548
parent55320cb58baebd1795ec92f4550a1e8b38bf9ddf (diff)
ixgbe: DCB, implement 802.1Qaz routines
Implements 802.1Qaz support for ixgbe driver. Additionally, this adds IEEE_8021QAZ_TSA_{} defines to dcbnl.h this is to avoid having to use cryptic numeric codes for the TSA type. Signed-off-by: John Fastabend <john.r.fastabend@intel.com> Tested-by: Ross Brattain <ross.b.brattain@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
-rw-r--r--drivers/net/ixgbe/ixgbe.h4
-rw-r--r--drivers/net/ixgbe/ixgbe_dcb.c103
-rw-r--r--drivers/net/ixgbe/ixgbe_dcb.h4
-rw-r--r--drivers/net/ixgbe/ixgbe_dcb_82598.c2
-rw-r--r--drivers/net/ixgbe/ixgbe_dcb_nl.c91
-rw-r--r--drivers/net/ixgbe/ixgbe_main.c4
-rw-r--r--include/linux/dcbnl.h5
7 files changed, 212 insertions, 1 deletions
diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h
index 3b8c92463617..d04afdeee035 100644
--- a/drivers/net/ixgbe/ixgbe.h
+++ b/drivers/net/ixgbe/ixgbe.h
@@ -334,6 +334,10 @@ struct ixgbe_adapter {
334 u16 bd_number; 334 u16 bd_number;
335 struct work_struct reset_task; 335 struct work_struct reset_task;
336 struct ixgbe_q_vector *q_vector[MAX_MSIX_Q_VECTORS]; 336 struct ixgbe_q_vector *q_vector[MAX_MSIX_Q_VECTORS];
337
338 /* DCB parameters */
339 struct ieee_pfc *ixgbe_ieee_pfc;
340 struct ieee_ets *ixgbe_ieee_ets;
337 struct ixgbe_dcb_config dcb_cfg; 341 struct ixgbe_dcb_config dcb_cfg;
338 struct ixgbe_dcb_config temp_dcb_cfg; 342 struct ixgbe_dcb_config temp_dcb_cfg;
339 u8 dcb_set_bitmap; 343 u8 dcb_set_bitmap;
diff --git a/drivers/net/ixgbe/ixgbe_dcb.c b/drivers/net/ixgbe/ixgbe_dcb.c
index d9bb670ae258..13c962efbfc9 100644
--- a/drivers/net/ixgbe/ixgbe_dcb.c
+++ b/drivers/net/ixgbe/ixgbe_dcb.c
@@ -34,6 +34,42 @@
34#include "ixgbe_dcb_82599.h" 34#include "ixgbe_dcb_82599.h"
35 35
36/** 36/**
37 * ixgbe_ieee_credits - This calculates the ieee traffic class
38 * credits from the configured bandwidth percentages. Credits
39 * are the smallest unit programable into the underlying
40 * hardware. The IEEE 802.1Qaz specification do not use bandwidth
41 * groups so this is much simplified from the CEE case.
42 */
43s32 ixgbe_ieee_credits(__u8 *bw, __u16 *refill, __u16 *max, int max_frame)
44{
45 int min_percent = 100;
46 int min_credit, multiplier;
47 int i;
48
49 min_credit = ((max_frame / 2) + DCB_CREDIT_QUANTUM - 1) /
50 DCB_CREDIT_QUANTUM;
51
52 for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
53 if (bw[i] < min_percent && bw[i])
54 min_percent = bw[i];
55 }
56
57 multiplier = (min_credit / min_percent) + 1;
58
59 /* Find out the hw credits for each TC */
60 for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
61 int val = min(bw[i] * multiplier, MAX_CREDIT_REFILL);
62
63 if (val < min_credit)
64 val = min_credit;
65 refill[i] = val;
66
67 max[i] = (bw[i] * MAX_CREDIT)/100;
68 }
69 return 0;
70}
71
72/**
37 * ixgbe_dcb_calculate_tc_credits - Calculates traffic class credits 73 * ixgbe_dcb_calculate_tc_credits - Calculates traffic class credits
38 * @ixgbe_dcb_config: Struct containing DCB settings. 74 * @ixgbe_dcb_config: Struct containing DCB settings.
39 * @direction: Configuring either Tx or Rx. 75 * @direction: Configuring either Tx or Rx.
@@ -236,3 +272,70 @@ s32 ixgbe_dcb_hw_config(struct ixgbe_hw *hw,
236 return ret; 272 return ret;
237} 273}
238 274
275/* Helper routines to abstract HW specifics from DCB netlink ops */
276s32 ixgbe_dcb_hw_pfc_config(struct ixgbe_hw *hw, u8 pfc_en)
277{
278 int ret = -EINVAL;
279
280 switch (hw->mac.type) {
281 case ixgbe_mac_82598EB:
282 ret = ixgbe_dcb_config_pfc_82598(hw, pfc_en);
283 break;
284 case ixgbe_mac_82599EB:
285 case ixgbe_mac_X540:
286 ret = ixgbe_dcb_config_pfc_82599(hw, pfc_en);
287 break;
288 default:
289 break;
290 }
291 return ret;
292}
293
294s32 ixgbe_dcb_hw_ets_config(struct ixgbe_hw *hw,
295 u16 *refill, u16 *max, u8 *bwg_id, u8 *tsa)
296{
297 int i;
298 u8 prio_type[IEEE_8021QAZ_MAX_TCS];
299
300 /* Map TSA onto CEE prio type */
301 for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
302 switch (tsa[i]) {
303 case IEEE_8021QAZ_TSA_STRICT:
304 prio_type[i] = 2;
305 break;
306 case IEEE_8021QAZ_TSA_ETS:
307 prio_type[i] = 0;
308 break;
309 default:
310 /* Hardware only supports priority strict or
311 * ETS transmission selection algorithms if
312 * we receive some other value from dcbnl
313 * throw an error
314 */
315 return -EINVAL;
316 }
317 }
318
319 switch (hw->mac.type) {
320 case ixgbe_mac_82598EB:
321 ixgbe_dcb_config_rx_arbiter_82598(hw, refill, max,
322 prio_type);
323 ixgbe_dcb_config_tx_desc_arbiter_82598(hw, refill, max,
324 bwg_id, prio_type);
325 ixgbe_dcb_config_tx_data_arbiter_82598(hw, refill, max,
326 bwg_id, prio_type);
327 break;
328 case ixgbe_mac_82599EB:
329 case ixgbe_mac_X540:
330 ixgbe_dcb_config_rx_arbiter_82599(hw, refill, max,
331 bwg_id, prio_type);
332 ixgbe_dcb_config_tx_desc_arbiter_82599(hw, refill, max,
333 bwg_id, prio_type);
334 ixgbe_dcb_config_tx_data_arbiter_82599(hw, refill, max,
335 bwg_id, prio_type);
336 break;
337 default:
338 break;
339 }
340 return 0;
341}
diff --git a/drivers/net/ixgbe/ixgbe_dcb.h b/drivers/net/ixgbe/ixgbe_dcb.h
index aa6cb5f9ebf4..4e4a641f3d53 100644
--- a/drivers/net/ixgbe/ixgbe_dcb.h
+++ b/drivers/net/ixgbe/ixgbe_dcb.h
@@ -150,10 +150,14 @@ struct ixgbe_dcb_config {
150void ixgbe_dcb_unpack_pfc(struct ixgbe_dcb_config *cfg, u8 *pfc_en); 150void ixgbe_dcb_unpack_pfc(struct ixgbe_dcb_config *cfg, u8 *pfc_en);
151 151
152/* DCB credits calculation */ 152/* DCB credits calculation */
153s32 ixgbe_ieee_credits(__u8 *bw, __u16 *refill, __u16 *max, int max_frame);
153s32 ixgbe_dcb_calculate_tc_credits(struct ixgbe_hw *, 154s32 ixgbe_dcb_calculate_tc_credits(struct ixgbe_hw *,
154 struct ixgbe_dcb_config *, int, u8); 155 struct ixgbe_dcb_config *, int, u8);
155 156
156/* DCB hw initialization */ 157/* DCB hw initialization */
158s32 ixgbe_dcb_hw_ets_config(struct ixgbe_hw *hw,
159 u16 *refill, u16 *max, u8 *bwg_id, u8 *prio_type);
160s32 ixgbe_dcb_hw_pfc_config(struct ixgbe_hw *hw, u8 pfc_en);
157s32 ixgbe_dcb_hw_config(struct ixgbe_hw *, struct ixgbe_dcb_config *); 161s32 ixgbe_dcb_hw_config(struct ixgbe_hw *, struct ixgbe_dcb_config *);
158 162
159/* DCB definitions for credit calculation */ 163/* DCB definitions for credit calculation */
diff --git a/drivers/net/ixgbe/ixgbe_dcb_82598.c b/drivers/net/ixgbe/ixgbe_dcb_82598.c
index d1288060cbd0..2965edcdac7b 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_82598.c
+++ b/drivers/net/ixgbe/ixgbe_dcb_82598.c
@@ -291,7 +291,7 @@ out:
291 * Configure queue statistics registers, all queues belonging to same traffic 291 * Configure queue statistics registers, all queues belonging to same traffic
292 * class uses a single set of queue statistics counters. 292 * class uses a single set of queue statistics counters.
293 */ 293 */
294static s32 ixgbe_dcb_config_tc_stats_82598(struct ixgbe_hw *hw) 294s32 ixgbe_dcb_config_tc_stats_82598(struct ixgbe_hw *hw)
295{ 295{
296 u32 reg = 0; 296 u32 reg = 0;
297 u8 i = 0; 297 u8 i = 0;
diff --git a/drivers/net/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ixgbe/ixgbe_dcb_nl.c
index 6ab1f1abaa01..e75a3c91198d 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_nl.c
+++ b/drivers/net/ixgbe/ixgbe_dcb_nl.c
@@ -606,7 +606,98 @@ static u8 ixgbe_dcbnl_setapp(struct net_device *netdev,
606 return rval; 606 return rval;
607} 607}
608 608
609static int ixgbe_dcbnl_ieee_getets(struct net_device *dev,
610 struct ieee_ets *ets)
611{
612 struct ixgbe_adapter *adapter = netdev_priv(dev);
613 struct ieee_ets *my_ets = adapter->ixgbe_ieee_ets;
614
615 /* No IEEE PFC settings available */
616 if (!my_ets)
617 return -EINVAL;
618
619 ets->ets_cap = MAX_TRAFFIC_CLASS;
620 ets->cbs = my_ets->cbs;
621 memcpy(ets->tc_tx_bw, my_ets->tc_tx_bw, sizeof(ets->tc_tx_bw));
622 memcpy(ets->tc_rx_bw, my_ets->tc_rx_bw, sizeof(ets->tc_rx_bw));
623 memcpy(ets->tc_tsa, my_ets->tc_tsa, sizeof(ets->tc_tsa));
624 memcpy(ets->prio_tc, my_ets->prio_tc, sizeof(ets->prio_tc));
625 return 0;
626}
627
628static int ixgbe_dcbnl_ieee_setets(struct net_device *dev,
629 struct ieee_ets *ets)
630{
631 struct ixgbe_adapter *adapter = netdev_priv(dev);
632 __u16 refill[IEEE_8021QAZ_MAX_TCS], max[IEEE_8021QAZ_MAX_TCS];
633 int max_frame = dev->mtu + ETH_HLEN + ETH_FCS_LEN;
634 int err;
635 /* naively give each TC a bwg to map onto CEE hardware */
636 __u8 bwg_id[IEEE_8021QAZ_MAX_TCS] = {0, 1, 2, 3, 4, 5, 6, 7};
637
638 if (!adapter->ixgbe_ieee_ets) {
639 adapter->ixgbe_ieee_ets = kmalloc(sizeof(struct ieee_ets),
640 GFP_KERNEL);
641 if (!adapter->ixgbe_ieee_ets)
642 return -ENOMEM;
643 }
644
645
646 memcpy(adapter->ixgbe_ieee_ets, ets, sizeof(*adapter->ixgbe_ieee_ets));
647
648 ixgbe_ieee_credits(ets->tc_tx_bw, refill, max, max_frame);
649 err = ixgbe_dcb_hw_ets_config(&adapter->hw, refill, max,
650 bwg_id, ets->tc_tsa);
651 return err;
652}
653
654static int ixgbe_dcbnl_ieee_getpfc(struct net_device *dev,
655 struct ieee_pfc *pfc)
656{
657 struct ixgbe_adapter *adapter = netdev_priv(dev);
658 struct ieee_pfc *my_pfc = adapter->ixgbe_ieee_pfc;
659 int i;
660
661 /* No IEEE PFC settings available */
662 if (!my_pfc)
663 return -EINVAL;
664
665 pfc->pfc_cap = MAX_TRAFFIC_CLASS;
666 pfc->pfc_en = my_pfc->pfc_en;
667 pfc->mbc = my_pfc->mbc;
668 pfc->delay = my_pfc->delay;
669
670 for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
671 pfc->requests[i] = adapter->stats.pxoffrxc[i];
672 pfc->indications[i] = adapter->stats.pxofftxc[i];
673 }
674
675 return 0;
676}
677
678static int ixgbe_dcbnl_ieee_setpfc(struct net_device *dev,
679 struct ieee_pfc *pfc)
680{
681 struct ixgbe_adapter *adapter = netdev_priv(dev);
682 int err;
683
684 if (!adapter->ixgbe_ieee_pfc) {
685 adapter->ixgbe_ieee_pfc = kmalloc(sizeof(struct ieee_pfc),
686 GFP_KERNEL);
687 if (!adapter->ixgbe_ieee_pfc)
688 return -ENOMEM;
689 }
690
691 memcpy(adapter->ixgbe_ieee_pfc, pfc, sizeof(*adapter->ixgbe_ieee_pfc));
692 err = ixgbe_dcb_hw_pfc_config(&adapter->hw, pfc->pfc_en);
693 return err;
694}
695
609const struct dcbnl_rtnl_ops dcbnl_ops = { 696const struct dcbnl_rtnl_ops dcbnl_ops = {
697 .ieee_getets = ixgbe_dcbnl_ieee_getets,
698 .ieee_setets = ixgbe_dcbnl_ieee_setets,
699 .ieee_getpfc = ixgbe_dcbnl_ieee_getpfc,
700 .ieee_setpfc = ixgbe_dcbnl_ieee_setpfc,
610 .getstate = ixgbe_dcbnl_get_state, 701 .getstate = ixgbe_dcbnl_get_state,
611 .setstate = ixgbe_dcbnl_set_state, 702 .setstate = ixgbe_dcbnl_set_state,
612 .getpermhwaddr = ixgbe_dcbnl_get_perm_hw_addr, 703 .getpermhwaddr = ixgbe_dcbnl_get_perm_hw_addr,
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 1e4814875945..c2e09b9cff46 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -5609,6 +5609,10 @@ static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake)
5609 } 5609 }
5610 5610
5611 ixgbe_clear_interrupt_scheme(adapter); 5611 ixgbe_clear_interrupt_scheme(adapter);
5612#ifdef CONFIG_DCB
5613 kfree(adapter->ixgbe_ieee_pfc);
5614 kfree(adapter->ixgbe_ieee_ets);
5615#endif
5612 5616
5613#ifdef CONFIG_PM 5617#ifdef CONFIG_PM
5614 retval = pci_save_state(pdev); 5618 retval = pci_save_state(pdev);
diff --git a/include/linux/dcbnl.h b/include/linux/dcbnl.h
index 68cd248f6d3e..cd8d518efa3b 100644
--- a/include/linux/dcbnl.h
+++ b/include/linux/dcbnl.h
@@ -25,6 +25,11 @@
25/* IEEE 802.1Qaz std supported values */ 25/* IEEE 802.1Qaz std supported values */
26#define IEEE_8021QAZ_MAX_TCS 8 26#define IEEE_8021QAZ_MAX_TCS 8
27 27
28#define IEEE_8021QAZ_TSA_STRICT 0
29#define IEEE_8021QAZ_TSA_CB_SHABER 1
30#define IEEE_8021QAZ_TSA_ETS 2
31#define IEEE_8021QAZ_TSA_VENDOR 255
32
28/* This structure contains the IEEE 802.1Qaz ETS managed object 33/* This structure contains the IEEE 802.1Qaz ETS managed object
29 * 34 *
30 * @willing: willing bit in ETS configuratin TLV 35 * @willing: willing bit in ETS configuratin TLV