diff options
author | Alexander Duyck <alexander.h.duyck@intel.com> | 2011-08-26 03:45:52 -0400 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2011-10-08 01:45:46 -0400 |
commit | 4be000c874576541cd1d4d0498a0a72a1c60bf0b (patch) | |
tree | 31b4e5467e9189a5475df028d0211b3540bff7a9 /drivers/net/ethernet/intel | |
parent | 0ba829943c5180d458cd8fc37c37fa08773209e1 (diff) |
igb: cleanup IVAR configuration
This change is meant to cleanup some of the IVAR register configuration.
igb_assign_vector had become pretty large with multiple copies of the same
general code for setting the IVAR. This change consolidates most of that
code by adding the igb_write_ivar function which allows us just to compute
the index and offset and then use that information to setup the IVAR.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet/intel')
-rw-r--r-- | drivers/net/ethernet/intel/igb/igb_main.c | 120 |
1 files changed, 56 insertions, 64 deletions
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 8dc04e0e0a04..ec715f45a449 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c | |||
@@ -754,15 +754,40 @@ err: | |||
754 | return -ENOMEM; | 754 | return -ENOMEM; |
755 | } | 755 | } |
756 | 756 | ||
757 | /** | ||
758 | * igb_write_ivar - configure ivar for given MSI-X vector | ||
759 | * @hw: pointer to the HW structure | ||
760 | * @msix_vector: vector number we are allocating to a given ring | ||
761 | * @index: row index of IVAR register to write within IVAR table | ||
762 | * @offset: column offset of in IVAR, should be multiple of 8 | ||
763 | * | ||
764 | * This function is intended to handle the writing of the IVAR register | ||
765 | * for adapters 82576 and newer. The IVAR table consists of 2 columns, | ||
766 | * each containing an cause allocation for an Rx and Tx ring, and a | ||
767 | * variable number of rows depending on the number of queues supported. | ||
768 | **/ | ||
769 | static void igb_write_ivar(struct e1000_hw *hw, int msix_vector, | ||
770 | int index, int offset) | ||
771 | { | ||
772 | u32 ivar = array_rd32(E1000_IVAR0, index); | ||
773 | |||
774 | /* clear any bits that are currently set */ | ||
775 | ivar &= ~((u32)0xFF << offset); | ||
776 | |||
777 | /* write vector and valid bit */ | ||
778 | ivar |= (msix_vector | E1000_IVAR_VALID) << offset; | ||
779 | |||
780 | array_wr32(E1000_IVAR0, index, ivar); | ||
781 | } | ||
782 | |||
757 | #define IGB_N0_QUEUE -1 | 783 | #define IGB_N0_QUEUE -1 |
758 | static void igb_assign_vector(struct igb_q_vector *q_vector, int msix_vector) | 784 | static void igb_assign_vector(struct igb_q_vector *q_vector, int msix_vector) |
759 | { | 785 | { |
760 | u32 msixbm = 0; | ||
761 | struct igb_adapter *adapter = q_vector->adapter; | 786 | struct igb_adapter *adapter = q_vector->adapter; |
762 | struct e1000_hw *hw = &adapter->hw; | 787 | struct e1000_hw *hw = &adapter->hw; |
763 | u32 ivar, index; | ||
764 | int rx_queue = IGB_N0_QUEUE; | 788 | int rx_queue = IGB_N0_QUEUE; |
765 | int tx_queue = IGB_N0_QUEUE; | 789 | int tx_queue = IGB_N0_QUEUE; |
790 | u32 msixbm = 0; | ||
766 | 791 | ||
767 | if (q_vector->rx.ring) | 792 | if (q_vector->rx.ring) |
768 | rx_queue = q_vector->rx.ring->reg_idx; | 793 | rx_queue = q_vector->rx.ring->reg_idx; |
@@ -785,72 +810,39 @@ static void igb_assign_vector(struct igb_q_vector *q_vector, int msix_vector) | |||
785 | q_vector->eims_value = msixbm; | 810 | q_vector->eims_value = msixbm; |
786 | break; | 811 | break; |
787 | case e1000_82576: | 812 | case e1000_82576: |
788 | /* 82576 uses a table-based method for assigning vectors. | 813 | /* |
789 | Each queue has a single entry in the table to which we write | 814 | * 82576 uses a table that essentially consists of 2 columns |
790 | a vector number along with a "valid" bit. Sadly, the layout | 815 | * with 8 rows. The ordering is column-major so we use the |
791 | of the table is somewhat counterintuitive. */ | 816 | * lower 3 bits as the row index, and the 4th bit as the |
792 | if (rx_queue > IGB_N0_QUEUE) { | 817 | * column offset. |
793 | index = (rx_queue & 0x7); | 818 | */ |
794 | ivar = array_rd32(E1000_IVAR0, index); | 819 | if (rx_queue > IGB_N0_QUEUE) |
795 | if (rx_queue < 8) { | 820 | igb_write_ivar(hw, msix_vector, |
796 | /* vector goes into low byte of register */ | 821 | rx_queue & 0x7, |
797 | ivar = ivar & 0xFFFFFF00; | 822 | (rx_queue & 0x8) << 1); |
798 | ivar |= msix_vector | E1000_IVAR_VALID; | 823 | if (tx_queue > IGB_N0_QUEUE) |
799 | } else { | 824 | igb_write_ivar(hw, msix_vector, |
800 | /* vector goes into third byte of register */ | 825 | tx_queue & 0x7, |
801 | ivar = ivar & 0xFF00FFFF; | 826 | ((tx_queue & 0x8) << 1) + 8); |
802 | ivar |= (msix_vector | E1000_IVAR_VALID) << 16; | ||
803 | } | ||
804 | array_wr32(E1000_IVAR0, index, ivar); | ||
805 | } | ||
806 | if (tx_queue > IGB_N0_QUEUE) { | ||
807 | index = (tx_queue & 0x7); | ||
808 | ivar = array_rd32(E1000_IVAR0, index); | ||
809 | if (tx_queue < 8) { | ||
810 | /* vector goes into second byte of register */ | ||
811 | ivar = ivar & 0xFFFF00FF; | ||
812 | ivar |= (msix_vector | E1000_IVAR_VALID) << 8; | ||
813 | } else { | ||
814 | /* vector goes into high byte of register */ | ||
815 | ivar = ivar & 0x00FFFFFF; | ||
816 | ivar |= (msix_vector | E1000_IVAR_VALID) << 24; | ||
817 | } | ||
818 | array_wr32(E1000_IVAR0, index, ivar); | ||
819 | } | ||
820 | q_vector->eims_value = 1 << msix_vector; | 827 | q_vector->eims_value = 1 << msix_vector; |
821 | break; | 828 | break; |
822 | case e1000_82580: | 829 | case e1000_82580: |
823 | case e1000_i350: | 830 | case e1000_i350: |
824 | /* 82580 uses the same table-based approach as 82576 but has fewer | 831 | /* |
825 | entries as a result we carry over for queues greater than 4. */ | 832 | * On 82580 and newer adapters the scheme is similar to 82576 |
826 | if (rx_queue > IGB_N0_QUEUE) { | 833 | * however instead of ordering column-major we have things |
827 | index = (rx_queue >> 1); | 834 | * ordered row-major. So we traverse the table by using |
828 | ivar = array_rd32(E1000_IVAR0, index); | 835 | * bit 0 as the column offset, and the remaining bits as the |
829 | if (rx_queue & 0x1) { | 836 | * row index. |
830 | /* vector goes into third byte of register */ | 837 | */ |
831 | ivar = ivar & 0xFF00FFFF; | 838 | if (rx_queue > IGB_N0_QUEUE) |
832 | ivar |= (msix_vector | E1000_IVAR_VALID) << 16; | 839 | igb_write_ivar(hw, msix_vector, |
833 | } else { | 840 | rx_queue >> 1, |
834 | /* vector goes into low byte of register */ | 841 | (rx_queue & 0x1) << 4); |
835 | ivar = ivar & 0xFFFFFF00; | 842 | if (tx_queue > IGB_N0_QUEUE) |
836 | ivar |= msix_vector | E1000_IVAR_VALID; | 843 | igb_write_ivar(hw, msix_vector, |
837 | } | 844 | tx_queue >> 1, |
838 | array_wr32(E1000_IVAR0, index, ivar); | 845 | ((tx_queue & 0x1) << 4) + 8); |
839 | } | ||
840 | if (tx_queue > IGB_N0_QUEUE) { | ||
841 | index = (tx_queue >> 1); | ||
842 | ivar = array_rd32(E1000_IVAR0, index); | ||
843 | if (tx_queue & 0x1) { | ||
844 | /* vector goes into high byte of register */ | ||
845 | ivar = ivar & 0x00FFFFFF; | ||
846 | ivar |= (msix_vector | E1000_IVAR_VALID) << 24; | ||
847 | } else { | ||
848 | /* vector goes into second byte of register */ | ||
849 | ivar = ivar & 0xFFFF00FF; | ||
850 | ivar |= (msix_vector | E1000_IVAR_VALID) << 8; | ||
851 | } | ||
852 | array_wr32(E1000_IVAR0, index, ivar); | ||
853 | } | ||
854 | q_vector->eims_value = 1 << msix_vector; | 846 | q_vector->eims_value = 1 << msix_vector; |
855 | break; | 847 | break; |
856 | default: | 848 | default: |