Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit eefc48b0 authored by Takahiro Shimizu's avatar Takahiro Shimizu Committed by David S. Miller
Browse files

pch_gbe: reprogram multicast address register on reset



The reset logic after a Rx FIFO overrun will clear the programmed
multicast addresses. This patch fixes the issue by reprogramming the
registers after the reset.

[ RC - Rebased Takahiro's changes and wrote a commit message
  explaining the changes. ]

Signed-off-by: default avatarTakahiro Shimizu <tshimizu818@gmail.com>
Signed-off-by: default avatarRichard Cochran <richardcochran@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5481c8cd
Loading
Loading
Loading
Loading
+57 −3
Original line number Diff line number Diff line
@@ -382,32 +382,86 @@ static void pch_gbe_mac_mar_set(struct pch_gbe_hw *hw, u8 * addr, u32 index)
	pch_gbe_wait_clr_bit(&hw->reg->ADDR_MASK, PCH_GBE_BUSY);
}

/**
 * pch_gbe_mac_save_mac_addr_regs - Save MAC addresse registers
 * @hw:		Pointer to the HW structure
 * @addr:	Pointer to the MAC address
 * @index:  MAC address array register
 */
static void
pch_gbe_mac_save_mac_addr_regs(struct pch_gbe_hw *hw,
			struct pch_gbe_regs_mac_adr *mac_adr, u32 index)
{
	mac_adr->high = ioread32(&hw->reg->mac_adr[index].high);
	mac_adr->low = ioread32(&hw->reg->mac_adr[index].low);
}

/**
 * pch_gbe_mac_store_mac_addr_regs - Store MAC addresse registers
 * @hw:		Pointer to the HW structure
 * @addr:	Pointer to the MAC address
 * @index:  MAC address array register
 */
static void
pch_gbe_mac_store_mac_addr_regs(struct pch_gbe_hw *hw,
			struct pch_gbe_regs_mac_adr *mac_adr, u32 index)
{
	u32 adrmask;

	adrmask = ioread32(&hw->reg->ADDR_MASK);
	iowrite32((adrmask | (0x0001 << index)), &hw->reg->ADDR_MASK);
	/* wait busy */
	pch_gbe_wait_clr_bit(&hw->reg->ADDR_MASK, PCH_GBE_BUSY);
	/* Set the MAC address to the MAC address xA/xB register */
	iowrite32(mac_adr->high, &hw->reg->mac_adr[index].high);
	iowrite32(mac_adr->low, &hw->reg->mac_adr[index].low);
	iowrite32((adrmask & ~(0x0001 << index)), &hw->reg->ADDR_MASK);
	/* wait busy */
	pch_gbe_wait_clr_bit(&hw->reg->ADDR_MASK, PCH_GBE_BUSY);
}

#define MAC_ADDR_LIST_NUM 16
/**
 * pch_gbe_mac_reset_hw - Reset hardware
 * @hw:	Pointer to the HW structure
 */
static void pch_gbe_mac_reset_hw(struct pch_gbe_hw *hw)
{
	struct pch_gbe_regs_mac_adr mac_addr_list[MAC_ADDR_LIST_NUM];
	int i;

	/* Read the MAC address. and store to the private data */
	pch_gbe_mac_read_mac_addr(hw);
	/* Read other MAC addresses */
	for (i = 1; i < MAC_ADDR_LIST_NUM; i++)
		pch_gbe_mac_save_mac_addr_regs(hw, &mac_addr_list[i], i);
	iowrite32(PCH_GBE_ALL_RST, &hw->reg->RESET);
#ifdef PCH_GBE_MAC_IFOP_RGMII
	iowrite32(PCH_GBE_MODE_GMII_ETHER, &hw->reg->MODE);
#endif
	pch_gbe_wait_clr_bit(&hw->reg->RESET, PCH_GBE_ALL_RST);
	/* Setup the receive address */
	/* Setup the receive addresses */
	pch_gbe_mac_mar_set(hw, hw->mac.addr, 0);
	for (i = 1; i < MAC_ADDR_LIST_NUM; i++)
		pch_gbe_mac_store_mac_addr_regs(hw, &mac_addr_list[i], i);
	return;
}

static void pch_gbe_mac_reset_rx(struct pch_gbe_hw *hw)
{
	/* Read the MAC address. and store to the private data */
	struct pch_gbe_regs_mac_adr mac_addr_list[MAC_ADDR_LIST_NUM];
	int i;

	/* Read the MAC addresses. and store to the private data */
	pch_gbe_mac_read_mac_addr(hw);
	for (i = 1; i < MAC_ADDR_LIST_NUM; i++)
		pch_gbe_mac_save_mac_addr_regs(hw, &mac_addr_list[i], i);
	iowrite32(PCH_GBE_RX_RST, &hw->reg->RESET);
	pch_gbe_wait_clr_bit_irq(&hw->reg->RESET, PCH_GBE_RX_RST);
	/* Setup the MAC address */
	/* Setup the MAC addresses */
	pch_gbe_mac_mar_set(hw, hw->mac.addr, 0);
	for (i = 1; i < MAC_ADDR_LIST_NUM; i++)
		pch_gbe_mac_store_mac_addr_regs(hw, &mac_addr_list[i], i);
	return;
}