提交 7fab3bfe 编写于 作者: R Ron Mercer 提交者: David S. Miller

qlge: Fix MAC address bonding issue.

This addes functionality to set/clear the MAC address in the hardware
when the link goes up/down.
The MAC address register is persistent across function resets. In
bonding the same address can bounce from one port to the other.  This
can cause packets to be delivered to the wrong port.
This patch clears the MAC address in the hardware when the link is down
and sets it when the link comes up.
It was found that pulling/pushing the cable from one port to another
causes the same MAC address to be in both ports.
The next patch in this series will use this functionality as well.
Signed-off-by: NRon Mercer <ron.mercer@qlogic.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 13cfd5be
......@@ -413,6 +413,41 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type,
return status;
}
/* Set or clear MAC address in hardware. We sometimes
* have to clear it to prevent wrong frame routing
* especially in a bonding environment.
*/
static int ql_set_mac_addr(struct ql_adapter *qdev, int set)
{
int status;
char zero_mac_addr[ETH_ALEN];
char *addr;
if (set) {
addr = &qdev->ndev->dev_addr[0];
QPRINTK(qdev, IFUP, DEBUG,
"Set Mac addr %02x:%02x:%02x:%02x:%02x:%02x\n",
addr[0], addr[1], addr[2], addr[3],
addr[4], addr[5]);
} else {
memset(zero_mac_addr, 0, ETH_ALEN);
addr = &zero_mac_addr[0];
QPRINTK(qdev, IFUP, DEBUG,
"Clearing MAC address on %s\n",
qdev->ndev->name);
}
status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK);
if (status)
return status;
status = ql_set_mac_addr_reg(qdev, (u8 *) addr,
MAC_ADDR_TYPE_CAM_MAC, qdev->func * MAX_CQ);
ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK);
if (status)
QPRINTK(qdev, IFUP, ERR, "Failed to init mac "
"address.\n");
return status;
}
/* Get a specific frame routing value from the CAM.
* Used for debug and reg dump.
*/
......@@ -3112,14 +3147,15 @@ static int ql_route_initialize(struct ql_adapter *qdev)
int ql_cam_route_initialize(struct ql_adapter *qdev)
{
int status;
int status, set;
status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK);
if (status)
return status;
status = ql_set_mac_addr_reg(qdev, (u8 *) qdev->ndev->perm_addr,
MAC_ADDR_TYPE_CAM_MAC, qdev->func * MAX_CQ);
ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK);
/* If check if the link is up and use to
* determine if we are setting or clearing
* the MAC address in the CAM.
*/
set = ql_read32(qdev, STS);
set &= qdev->port_link_up;
status = ql_set_mac_addr(qdev, set);
if (status) {
QPRINTK(qdev, IFUP, ERR, "Failed to init mac address.\n");
return status;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册