aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRon Mercer <ron.mercer@qlogic.com>2009-07-02 02:06:11 -0400
committerDavid S. Miller <davem@davemloft.net>2009-07-03 22:10:41 -0400
commit7fab3bfe08a2c5c4221685499ec4fef83ad82f83 (patch)
tree1c1baca2eabb0c4185aa8641854a3cb306cf5e28
parent13cfd5be53d01a9316907512f17f34d3858450e8 (diff)
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: Ron Mercer <ron.mercer@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/qlge/qlge_main.c50
1 files changed, 43 insertions, 7 deletions
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c
index 74ed84a288c2..46dea2bd94d0 100644
--- a/drivers/net/qlge/qlge_main.c
+++ b/drivers/net/qlge/qlge_main.c
@@ -413,6 +413,41 @@ exit:
413 return status; 413 return status;
414} 414}
415 415
416/* Set or clear MAC address in hardware. We sometimes
417 * have to clear it to prevent wrong frame routing
418 * especially in a bonding environment.
419 */
420static int ql_set_mac_addr(struct ql_adapter *qdev, int set)
421{
422 int status;
423 char zero_mac_addr[ETH_ALEN];
424 char *addr;
425
426 if (set) {
427 addr = &qdev->ndev->dev_addr[0];
428 QPRINTK(qdev, IFUP, DEBUG,
429 "Set Mac addr %02x:%02x:%02x:%02x:%02x:%02x\n",
430 addr[0], addr[1], addr[2], addr[3],
431 addr[4], addr[5]);
432 } else {
433 memset(zero_mac_addr, 0, ETH_ALEN);
434 addr = &zero_mac_addr[0];
435 QPRINTK(qdev, IFUP, DEBUG,
436 "Clearing MAC address on %s\n",
437 qdev->ndev->name);
438 }
439 status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK);
440 if (status)
441 return status;
442 status = ql_set_mac_addr_reg(qdev, (u8 *) addr,
443 MAC_ADDR_TYPE_CAM_MAC, qdev->func * MAX_CQ);
444 ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK);
445 if (status)
446 QPRINTK(qdev, IFUP, ERR, "Failed to init mac "
447 "address.\n");
448 return status;
449}
450
416/* Get a specific frame routing value from the CAM. 451/* Get a specific frame routing value from the CAM.
417 * Used for debug and reg dump. 452 * Used for debug and reg dump.
418 */ 453 */
@@ -3112,14 +3147,15 @@ exit:
3112 3147
3113int ql_cam_route_initialize(struct ql_adapter *qdev) 3148int ql_cam_route_initialize(struct ql_adapter *qdev)
3114{ 3149{
3115 int status; 3150 int status, set;
3116 3151
3117 status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK); 3152 /* If check if the link is up and use to
3118 if (status) 3153 * determine if we are setting or clearing
3119 return status; 3154 * the MAC address in the CAM.
3120 status = ql_set_mac_addr_reg(qdev, (u8 *) qdev->ndev->perm_addr, 3155 */
3121 MAC_ADDR_TYPE_CAM_MAC, qdev->func * MAX_CQ); 3156 set = ql_read32(qdev, STS);
3122 ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK); 3157 set &= qdev->port_link_up;
3158 status = ql_set_mac_addr(qdev, set);
3123 if (status) { 3159 if (status) {
3124 QPRINTK(qdev, IFUP, ERR, "Failed to init mac address.\n"); 3160 QPRINTK(qdev, IFUP, ERR, "Failed to init mac address.\n");
3125 return status; 3161 return status;