diff options
-rw-r--r-- | drivers/net/igb/e1000_defines.h | 7 | ||||
-rw-r--r-- | drivers/net/igb/e1000_regs.h | 4 | ||||
-rw-r--r-- | drivers/net/igb/igb.h | 2 | ||||
-rw-r--r-- | drivers/net/igb/igb_main.c | 88 |
4 files changed, 99 insertions, 2 deletions
diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h index 6319ed902bc0..ff46c91520af 100644 --- a/drivers/net/igb/e1000_defines.h +++ b/drivers/net/igb/e1000_defines.h | |||
@@ -770,4 +770,11 @@ | |||
770 | #define E1000_PCIEMISC_LX_DECISION 0x00000080 /* Lx power decision based | 770 | #define E1000_PCIEMISC_LX_DECISION 0x00000080 /* Lx power decision based |
771 | on DMA coal */ | 771 | on DMA coal */ |
772 | 772 | ||
773 | /* Tx Rate-Scheduler Config fields */ | ||
774 | #define E1000_RTTBCNRC_RS_ENA 0x80000000 | ||
775 | #define E1000_RTTBCNRC_RF_DEC_MASK 0x00003FFF | ||
776 | #define E1000_RTTBCNRC_RF_INT_SHIFT 14 | ||
777 | #define E1000_RTTBCNRC_RF_INT_MASK \ | ||
778 | (E1000_RTTBCNRC_RF_DEC_MASK << E1000_RTTBCNRC_RF_INT_SHIFT) | ||
779 | |||
773 | #endif | 780 | #endif |
diff --git a/drivers/net/igb/e1000_regs.h b/drivers/net/igb/e1000_regs.h index 8ac83c5190d5..3a6f8471aea2 100644 --- a/drivers/net/igb/e1000_regs.h +++ b/drivers/net/igb/e1000_regs.h | |||
@@ -106,6 +106,10 @@ | |||
106 | 106 | ||
107 | #define E1000_RQDPC(_n) (0x0C030 + ((_n) * 0x40)) | 107 | #define E1000_RQDPC(_n) (0x0C030 + ((_n) * 0x40)) |
108 | 108 | ||
109 | /* TX Rate Limit Registers */ | ||
110 | #define E1000_RTTDQSEL 0x3604 /* Tx Desc Plane Queue Select - WO */ | ||
111 | #define E1000_RTTBCNRC 0x36B0 /* Tx BCN Rate-Scheduler Config - WO */ | ||
112 | |||
109 | /* Split and Replication RX Control - RW */ | 113 | /* Split and Replication RX Control - RW */ |
110 | #define E1000_RXPBS 0x02404 /* Rx Packet Buffer Size - RW */ | 114 | #define E1000_RXPBS 0x02404 /* Rx Packet Buffer Size - RW */ |
111 | /* | 115 | /* |
diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index 92a4ef09e55c..bbc5ebfe254a 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h | |||
@@ -77,6 +77,7 @@ struct vf_data_storage { | |||
77 | unsigned long last_nack; | 77 | unsigned long last_nack; |
78 | u16 pf_vlan; /* When set, guest VLAN config not allowed. */ | 78 | u16 pf_vlan; /* When set, guest VLAN config not allowed. */ |
79 | u16 pf_qos; | 79 | u16 pf_qos; |
80 | u16 tx_rate; | ||
80 | }; | 81 | }; |
81 | 82 | ||
82 | #define IGB_VF_FLAG_CTS 0x00000001 /* VF is clear to send data */ | 83 | #define IGB_VF_FLAG_CTS 0x00000001 /* VF is clear to send data */ |
@@ -323,6 +324,7 @@ struct igb_adapter { | |||
323 | u16 rx_ring_count; | 324 | u16 rx_ring_count; |
324 | unsigned int vfs_allocated_count; | 325 | unsigned int vfs_allocated_count; |
325 | struct vf_data_storage *vf_data; | 326 | struct vf_data_storage *vf_data; |
327 | int vf_rate_link_speed; | ||
326 | u32 rss_queues; | 328 | u32 rss_queues; |
327 | u32 wvbr; | 329 | u32 wvbr; |
328 | }; | 330 | }; |
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index cb6bf7b815ae..88f8925b2d85 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c | |||
@@ -150,6 +150,7 @@ static int igb_ndo_set_vf_vlan(struct net_device *netdev, | |||
150 | static int igb_ndo_set_vf_bw(struct net_device *netdev, int vf, int tx_rate); | 150 | static int igb_ndo_set_vf_bw(struct net_device *netdev, int vf, int tx_rate); |
151 | static int igb_ndo_get_vf_config(struct net_device *netdev, int vf, | 151 | static int igb_ndo_get_vf_config(struct net_device *netdev, int vf, |
152 | struct ifla_vf_info *ivi); | 152 | struct ifla_vf_info *ivi); |
153 | static void igb_check_vf_rate_limit(struct igb_adapter *); | ||
153 | 154 | ||
154 | #ifdef CONFIG_PM | 155 | #ifdef CONFIG_PM |
155 | static int igb_suspend(struct pci_dev *, pm_message_t); | 156 | static int igb_suspend(struct pci_dev *, pm_message_t); |
@@ -3511,6 +3512,7 @@ static void igb_watchdog_task(struct work_struct *work) | |||
3511 | netif_carrier_on(netdev); | 3512 | netif_carrier_on(netdev); |
3512 | 3513 | ||
3513 | igb_ping_all_vfs(adapter); | 3514 | igb_ping_all_vfs(adapter); |
3515 | igb_check_vf_rate_limit(adapter); | ||
3514 | 3516 | ||
3515 | /* link state has changed, schedule phy info update */ | 3517 | /* link state has changed, schedule phy info update */ |
3516 | if (!test_bit(__IGB_DOWN, &adapter->state)) | 3518 | if (!test_bit(__IGB_DOWN, &adapter->state)) |
@@ -6599,9 +6601,91 @@ static int igb_ndo_set_vf_mac(struct net_device *netdev, int vf, u8 *mac) | |||
6599 | return igb_set_vf_mac(adapter, vf, mac); | 6601 | return igb_set_vf_mac(adapter, vf, mac); |
6600 | } | 6602 | } |
6601 | 6603 | ||
6604 | static int igb_link_mbps(int internal_link_speed) | ||
6605 | { | ||
6606 | switch (internal_link_speed) { | ||
6607 | case SPEED_100: | ||
6608 | return 100; | ||
6609 | case SPEED_1000: | ||
6610 | return 1000; | ||
6611 | default: | ||
6612 | return 0; | ||
6613 | } | ||
6614 | } | ||
6615 | |||
6616 | static void igb_set_vf_rate_limit(struct e1000_hw *hw, int vf, int tx_rate, | ||
6617 | int link_speed) | ||
6618 | { | ||
6619 | int rf_dec, rf_int; | ||
6620 | u32 bcnrc_val; | ||
6621 | |||
6622 | if (tx_rate != 0) { | ||
6623 | /* Calculate the rate factor values to set */ | ||
6624 | rf_int = link_speed / tx_rate; | ||
6625 | rf_dec = (link_speed - (rf_int * tx_rate)); | ||
6626 | rf_dec = (rf_dec * (1<<E1000_RTTBCNRC_RF_INT_SHIFT)) / tx_rate; | ||
6627 | |||
6628 | bcnrc_val = E1000_RTTBCNRC_RS_ENA; | ||
6629 | bcnrc_val |= ((rf_int<<E1000_RTTBCNRC_RF_INT_SHIFT) & | ||
6630 | E1000_RTTBCNRC_RF_INT_MASK); | ||
6631 | bcnrc_val |= (rf_dec & E1000_RTTBCNRC_RF_DEC_MASK); | ||
6632 | } else { | ||
6633 | bcnrc_val = 0; | ||
6634 | } | ||
6635 | |||
6636 | wr32(E1000_RTTDQSEL, vf); /* vf X uses queue X */ | ||
6637 | wr32(E1000_RTTBCNRC, bcnrc_val); | ||
6638 | } | ||
6639 | |||
6640 | static void igb_check_vf_rate_limit(struct igb_adapter *adapter) | ||
6641 | { | ||
6642 | int actual_link_speed, i; | ||
6643 | bool reset_rate = false; | ||
6644 | |||
6645 | /* VF TX rate limit was not set or not supported */ | ||
6646 | if ((adapter->vf_rate_link_speed == 0) || | ||
6647 | (adapter->hw.mac.type != e1000_82576)) | ||
6648 | return; | ||
6649 | |||
6650 | actual_link_speed = igb_link_mbps(adapter->link_speed); | ||
6651 | if (actual_link_speed != adapter->vf_rate_link_speed) { | ||
6652 | reset_rate = true; | ||
6653 | adapter->vf_rate_link_speed = 0; | ||
6654 | dev_info(&adapter->pdev->dev, | ||
6655 | "Link speed has been changed. VF Transmit " | ||
6656 | "rate is disabled\n"); | ||
6657 | } | ||
6658 | |||
6659 | for (i = 0; i < adapter->vfs_allocated_count; i++) { | ||
6660 | if (reset_rate) | ||
6661 | adapter->vf_data[i].tx_rate = 0; | ||
6662 | |||
6663 | igb_set_vf_rate_limit(&adapter->hw, i, | ||
6664 | adapter->vf_data[i].tx_rate, | ||
6665 | actual_link_speed); | ||
6666 | } | ||
6667 | } | ||
6668 | |||
6602 | static int igb_ndo_set_vf_bw(struct net_device *netdev, int vf, int tx_rate) | 6669 | static int igb_ndo_set_vf_bw(struct net_device *netdev, int vf, int tx_rate) |
6603 | { | 6670 | { |
6604 | return -EOPNOTSUPP; | 6671 | struct igb_adapter *adapter = netdev_priv(netdev); |
6672 | struct e1000_hw *hw = &adapter->hw; | ||
6673 | int actual_link_speed; | ||
6674 | |||
6675 | if (hw->mac.type != e1000_82576) | ||
6676 | return -EOPNOTSUPP; | ||
6677 | |||
6678 | actual_link_speed = igb_link_mbps(adapter->link_speed); | ||
6679 | if ((vf >= adapter->vfs_allocated_count) || | ||
6680 | (!(rd32(E1000_STATUS) & E1000_STATUS_LU)) || | ||
6681 | (tx_rate < 0) || (tx_rate > actual_link_speed)) | ||
6682 | return -EINVAL; | ||
6683 | |||
6684 | adapter->vf_rate_link_speed = actual_link_speed; | ||
6685 | adapter->vf_data[vf].tx_rate = (u16)tx_rate; | ||
6686 | igb_set_vf_rate_limit(hw, vf, tx_rate, actual_link_speed); | ||
6687 | |||
6688 | return 0; | ||
6605 | } | 6689 | } |
6606 | 6690 | ||
6607 | static int igb_ndo_get_vf_config(struct net_device *netdev, | 6691 | static int igb_ndo_get_vf_config(struct net_device *netdev, |
@@ -6612,7 +6696,7 @@ static int igb_ndo_get_vf_config(struct net_device *netdev, | |||
6612 | return -EINVAL; | 6696 | return -EINVAL; |
6613 | ivi->vf = vf; | 6697 | ivi->vf = vf; |
6614 | memcpy(&ivi->mac, adapter->vf_data[vf].vf_mac_addresses, ETH_ALEN); | 6698 | memcpy(&ivi->mac, adapter->vf_data[vf].vf_mac_addresses, ETH_ALEN); |
6615 | ivi->tx_rate = 0; | 6699 | ivi->tx_rate = adapter->vf_data[vf].tx_rate; |
6616 | ivi->vlan = adapter->vf_data[vf].pf_vlan; | 6700 | ivi->vlan = adapter->vf_data[vf].pf_vlan; |
6617 | ivi->qos = adapter->vf_data[vf].pf_qos; | 6701 | ivi->qos = adapter->vf_data[vf].pf_qos; |
6618 | return 0; | 6702 | return 0; |