Skip to content

Commit 7f83968

Browse files
Sasha NeftinJeff Kirsher
authored andcommitted
igc: Add set_rx_mode support
Add multicast addresses list to the MTA table. Implement basic Rx mode support. Add option for IPv6 address settings. Signed-off-by: Sasha Neftin <[email protected]> Tested-by: Aaron Brown <[email protected]> Signed-off-by: Jeff Kirsher <[email protected]>
1 parent f15bb6d commit 7f83968

File tree

5 files changed

+291
-0
lines changed

5 files changed

+291
-0
lines changed

drivers/net/ethernet/intel/igc/igc_defines.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,4 +402,7 @@
402402
#define IGC_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet Type of TCP */
403403
#define IGC_ADVTXD_TUCMD_L4T_SCTP 0x00001000 /* L4 packet TYPE of SCTP */
404404

405+
/* Maximum size of the MTA register table in all supported adapters */
406+
#define MAX_MTA_REG 128
407+
405408
#endif /* _IGC_DEFINES_H_ */

drivers/net/ethernet/intel/igc/igc_hw.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ struct igc_mac_info {
9191
u16 mta_reg_count;
9292
u16 uta_reg_count;
9393

94+
u32 mta_shadow[MAX_MTA_REG];
9495
u16 rar_entry_count;
9596

9697
u8 forced_speed_duplex;

drivers/net/ethernet/intel/igc/igc_mac.c

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -784,3 +784,107 @@ bool igc_enable_mng_pass_thru(struct igc_hw *hw)
784784
out:
785785
return ret_val;
786786
}
787+
788+
/**
789+
* igc_hash_mc_addr - Generate a multicast hash value
790+
* @hw: pointer to the HW structure
791+
* @mc_addr: pointer to a multicast address
792+
*
793+
* Generates a multicast address hash value which is used to determine
794+
* the multicast filter table array address and new table value. See
795+
* igc_mta_set()
796+
**/
797+
static u32 igc_hash_mc_addr(struct igc_hw *hw, u8 *mc_addr)
798+
{
799+
u32 hash_value, hash_mask;
800+
u8 bit_shift = 0;
801+
802+
/* Register count multiplied by bits per register */
803+
hash_mask = (hw->mac.mta_reg_count * 32) - 1;
804+
805+
/* For a mc_filter_type of 0, bit_shift is the number of left-shifts
806+
* where 0xFF would still fall within the hash mask.
807+
*/
808+
while (hash_mask >> bit_shift != 0xFF)
809+
bit_shift++;
810+
811+
/* The portion of the address that is used for the hash table
812+
* is determined by the mc_filter_type setting.
813+
* The algorithm is such that there is a total of 8 bits of shifting.
814+
* The bit_shift for a mc_filter_type of 0 represents the number of
815+
* left-shifts where the MSB of mc_addr[5] would still fall within
816+
* the hash_mask. Case 0 does this exactly. Since there are a total
817+
* of 8 bits of shifting, then mc_addr[4] will shift right the
818+
* remaining number of bits. Thus 8 - bit_shift. The rest of the
819+
* cases are a variation of this algorithm...essentially raising the
820+
* number of bits to shift mc_addr[5] left, while still keeping the
821+
* 8-bit shifting total.
822+
*
823+
* For example, given the following Destination MAC Address and an
824+
* MTA register count of 128 (thus a 4096-bit vector and 0xFFF mask),
825+
* we can see that the bit_shift for case 0 is 4. These are the hash
826+
* values resulting from each mc_filter_type...
827+
* [0] [1] [2] [3] [4] [5]
828+
* 01 AA 00 12 34 56
829+
* LSB MSB
830+
*
831+
* case 0: hash_value = ((0x34 >> 4) | (0x56 << 4)) & 0xFFF = 0x563
832+
* case 1: hash_value = ((0x34 >> 3) | (0x56 << 5)) & 0xFFF = 0xAC6
833+
* case 2: hash_value = ((0x34 >> 2) | (0x56 << 6)) & 0xFFF = 0x163
834+
* case 3: hash_value = ((0x34 >> 0) | (0x56 << 8)) & 0xFFF = 0x634
835+
*/
836+
switch (hw->mac.mc_filter_type) {
837+
default:
838+
case 0:
839+
break;
840+
case 1:
841+
bit_shift += 1;
842+
break;
843+
case 2:
844+
bit_shift += 2;
845+
break;
846+
case 3:
847+
bit_shift += 4;
848+
break;
849+
}
850+
851+
hash_value = hash_mask & (((mc_addr[4] >> (8 - bit_shift)) |
852+
(((u16)mc_addr[5]) << bit_shift)));
853+
854+
return hash_value;
855+
}
856+
857+
/**
858+
* igc_update_mc_addr_list - Update Multicast addresses
859+
* @hw: pointer to the HW structure
860+
* @mc_addr_list: array of multicast addresses to program
861+
* @mc_addr_count: number of multicast addresses to program
862+
*
863+
* Updates entire Multicast Table Array.
864+
* The caller must have a packed mc_addr_list of multicast addresses.
865+
**/
866+
void igc_update_mc_addr_list(struct igc_hw *hw,
867+
u8 *mc_addr_list, u32 mc_addr_count)
868+
{
869+
u32 hash_value, hash_bit, hash_reg;
870+
int i;
871+
872+
/* clear mta_shadow */
873+
memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow));
874+
875+
/* update mta_shadow from mc_addr_list */
876+
for (i = 0; (u32)i < mc_addr_count; i++) {
877+
hash_value = igc_hash_mc_addr(hw, mc_addr_list);
878+
879+
hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1);
880+
hash_bit = hash_value & 0x1F;
881+
882+
hw->mac.mta_shadow[hash_reg] |= BIT(hash_bit);
883+
mc_addr_list += ETH_ALEN;
884+
}
885+
886+
/* replace the entire MTA table */
887+
for (i = hw->mac.mta_reg_count - 1; i >= 0; i--)
888+
array_wr32(IGC_MTA, i, hw->mac.mta_shadow[i]);
889+
wrfl();
890+
}

drivers/net/ethernet/intel/igc/igc_mac.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ s32 igc_get_speed_and_duplex_copper(struct igc_hw *hw, u16 *speed,
2929
u16 *duplex);
3030

3131
bool igc_enable_mng_pass_thru(struct igc_hw *hw);
32+
void igc_update_mc_addr_list(struct igc_hw *hw,
33+
u8 *mc_addr_list, u32 mc_addr_count);
3234

3335
enum igc_mng_mode {
3436
igc_mng_mode_none = 0,

drivers/net/ethernet/intel/igc/igc_main.c

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,44 @@ static int igc_set_mac(struct net_device *netdev, void *p)
795795
return 0;
796796
}
797797

798+
/**
799+
* igc_write_mc_addr_list - write multicast addresses to MTA
800+
* @netdev: network interface device structure
801+
*
802+
* Writes multicast address list to the MTA hash table.
803+
* Returns: -ENOMEM on failure
804+
* 0 on no addresses written
805+
* X on writing X addresses to MTA
806+
**/
807+
static int igc_write_mc_addr_list(struct net_device *netdev)
808+
{
809+
struct igc_adapter *adapter = netdev_priv(netdev);
810+
struct igc_hw *hw = &adapter->hw;
811+
struct netdev_hw_addr *ha;
812+
u8 *mta_list;
813+
int i;
814+
815+
if (netdev_mc_empty(netdev)) {
816+
/* nothing to program, so clear mc list */
817+
igc_update_mc_addr_list(hw, NULL, 0);
818+
return 0;
819+
}
820+
821+
mta_list = kcalloc(netdev_mc_count(netdev), 6, GFP_ATOMIC);
822+
if (!mta_list)
823+
return -ENOMEM;
824+
825+
/* The shared function expects a packed array of only addresses. */
826+
i = 0;
827+
netdev_for_each_mc_addr(ha, netdev)
828+
memcpy(mta_list + (i++ * ETH_ALEN), ha->addr, ETH_ALEN);
829+
830+
igc_update_mc_addr_list(hw, mta_list, i);
831+
kfree(mta_list);
832+
833+
return netdev_mc_count(netdev);
834+
}
835+
798836
static void igc_tx_ctxtdesc(struct igc_ring *tx_ring,
799837
struct igc_tx_buffer *first,
800838
u32 vlan_macip_lens, u32 type_tucmd,
@@ -2518,6 +2556,110 @@ int igc_del_mac_steering_filter(struct igc_adapter *adapter,
25182556
IGC_MAC_STATE_QUEUE_STEERING | flags);
25192557
}
25202558

2559+
/* Add a MAC filter for 'addr' directing matching traffic to 'queue',
2560+
* 'flags' is used to indicate what kind of match is made, match is by
2561+
* default for the destination address, if matching by source address
2562+
* is desired the flag IGC_MAC_STATE_SRC_ADDR can be used.
2563+
*/
2564+
static int igc_add_mac_filter(struct igc_adapter *adapter,
2565+
const u8 *addr, const u8 queue)
2566+
{
2567+
struct igc_hw *hw = &adapter->hw;
2568+
int rar_entries = hw->mac.rar_entry_count;
2569+
int i;
2570+
2571+
if (is_zero_ether_addr(addr))
2572+
return -EINVAL;
2573+
2574+
/* Search for the first empty entry in the MAC table.
2575+
* Do not touch entries at the end of the table reserved for the VF MAC
2576+
* addresses.
2577+
*/
2578+
for (i = 0; i < rar_entries; i++) {
2579+
if (!igc_mac_entry_can_be_used(&adapter->mac_table[i],
2580+
addr, 0))
2581+
continue;
2582+
2583+
ether_addr_copy(adapter->mac_table[i].addr, addr);
2584+
adapter->mac_table[i].queue = queue;
2585+
adapter->mac_table[i].state |= IGC_MAC_STATE_IN_USE;
2586+
2587+
igc_rar_set_index(adapter, i);
2588+
return i;
2589+
}
2590+
2591+
return -ENOSPC;
2592+
}
2593+
2594+
/* Remove a MAC filter for 'addr' directing matching traffic to
2595+
* 'queue', 'flags' is used to indicate what kind of match need to be
2596+
* removed, match is by default for the destination address, if
2597+
* matching by source address is to be removed the flag
2598+
* IGC_MAC_STATE_SRC_ADDR can be used.
2599+
*/
2600+
static int igc_del_mac_filter(struct igc_adapter *adapter,
2601+
const u8 *addr, const u8 queue)
2602+
{
2603+
struct igc_hw *hw = &adapter->hw;
2604+
int rar_entries = hw->mac.rar_entry_count;
2605+
int i;
2606+
2607+
if (is_zero_ether_addr(addr))
2608+
return -EINVAL;
2609+
2610+
/* Search for matching entry in the MAC table based on given address
2611+
* and queue. Do not touch entries at the end of the table reserved
2612+
* for the VF MAC addresses.
2613+
*/
2614+
for (i = 0; i < rar_entries; i++) {
2615+
if (!(adapter->mac_table[i].state & IGC_MAC_STATE_IN_USE))
2616+
continue;
2617+
if (adapter->mac_table[i].state != 0)
2618+
continue;
2619+
if (adapter->mac_table[i].queue != queue)
2620+
continue;
2621+
if (!ether_addr_equal(adapter->mac_table[i].addr, addr))
2622+
continue;
2623+
2624+
/* When a filter for the default address is "deleted",
2625+
* we return it to its initial configuration
2626+
*/
2627+
if (adapter->mac_table[i].state & IGC_MAC_STATE_DEFAULT) {
2628+
adapter->mac_table[i].state =
2629+
IGC_MAC_STATE_DEFAULT | IGC_MAC_STATE_IN_USE;
2630+
adapter->mac_table[i].queue = 0;
2631+
} else {
2632+
adapter->mac_table[i].state = 0;
2633+
adapter->mac_table[i].queue = 0;
2634+
memset(adapter->mac_table[i].addr, 0, ETH_ALEN);
2635+
}
2636+
2637+
igc_rar_set_index(adapter, i);
2638+
return 0;
2639+
}
2640+
2641+
return -ENOENT;
2642+
}
2643+
2644+
static int igc_uc_sync(struct net_device *netdev, const unsigned char *addr)
2645+
{
2646+
struct igc_adapter *adapter = netdev_priv(netdev);
2647+
int ret;
2648+
2649+
ret = igc_add_mac_filter(adapter, addr, adapter->num_rx_queues);
2650+
2651+
return min_t(int, ret, 0);
2652+
}
2653+
2654+
static int igc_uc_unsync(struct net_device *netdev, const unsigned char *addr)
2655+
{
2656+
struct igc_adapter *adapter = netdev_priv(netdev);
2657+
2658+
igc_del_mac_filter(adapter, addr, adapter->num_rx_queues);
2659+
2660+
return 0;
2661+
}
2662+
25212663
/**
25222664
* igc_set_rx_mode - Secondary Unicast, Multicast and Promiscuous mode set
25232665
* @netdev: network interface device structure
@@ -2529,6 +2671,44 @@ int igc_del_mac_steering_filter(struct igc_adapter *adapter,
25292671
*/
25302672
static void igc_set_rx_mode(struct net_device *netdev)
25312673
{
2674+
struct igc_adapter *adapter = netdev_priv(netdev);
2675+
struct igc_hw *hw = &adapter->hw;
2676+
u32 rctl = 0, rlpml = MAX_JUMBO_FRAME_SIZE;
2677+
int count;
2678+
2679+
/* Check for Promiscuous and All Multicast modes */
2680+
if (netdev->flags & IFF_PROMISC) {
2681+
rctl |= IGC_RCTL_UPE | IGC_RCTL_MPE;
2682+
} else {
2683+
if (netdev->flags & IFF_ALLMULTI) {
2684+
rctl |= IGC_RCTL_MPE;
2685+
} else {
2686+
/* Write addresses to the MTA, if the attempt fails
2687+
* then we should just turn on promiscuous mode so
2688+
* that we can at least receive multicast traffic
2689+
*/
2690+
count = igc_write_mc_addr_list(netdev);
2691+
if (count < 0)
2692+
rctl |= IGC_RCTL_MPE;
2693+
}
2694+
}
2695+
2696+
/* Write addresses to available RAR registers, if there is not
2697+
* sufficient space to store all the addresses then enable
2698+
* unicast promiscuous mode
2699+
*/
2700+
if (__dev_uc_sync(netdev, igc_uc_sync, igc_uc_unsync))
2701+
rctl |= IGC_RCTL_UPE;
2702+
2703+
/* update state of unicast and multicast */
2704+
rctl |= rd32(IGC_RCTL) & ~(IGC_RCTL_UPE | IGC_RCTL_MPE);
2705+
wr32(IGC_RCTL, rctl);
2706+
2707+
#if (PAGE_SIZE < 8192)
2708+
if (adapter->max_frame_size <= IGC_MAX_FRAME_BUILD_SKB)
2709+
rlpml = IGC_MAX_FRAME_BUILD_SKB;
2710+
#endif
2711+
wr32(IGC_RLPML, rlpml);
25322712
}
25332713

25342714
/**
@@ -3982,6 +4162,7 @@ static const struct net_device_ops igc_netdev_ops = {
39824162
.ndo_open = igc_open,
39834163
.ndo_stop = igc_close,
39844164
.ndo_start_xmit = igc_xmit_frame,
4165+
.ndo_set_rx_mode = igc_set_rx_mode,
39854166
.ndo_set_mac_address = igc_set_mac,
39864167
.ndo_change_mtu = igc_change_mtu,
39874168
.ndo_get_stats = igc_get_stats,

0 commit comments

Comments
 (0)