aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/netxen/netxen_nic_hw.c
diff options
context:
space:
mode:
authorDhananjay Phadke <dhananjay@netxen.com>2009-05-05 15:05:07 -0400
committerDavid S. Miller <davem@davemloft.net>2009-05-06 18:33:36 -0400
commit5cf4d323f8864dab818d500ec74f2fcb9ad5bf89 (patch)
tree5f90365023b2b7a78852be460b770c5ae8731723 /drivers/net/netxen/netxen_nic_hw.c
parent22527864ed7ee6c50f3c4d4b03c83c963caf5c0b (diff)
netxen: fix mac list management
o use standard linked list api for mac addr list management in NX3031. o release mac addresses in firmware in dev close(). Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/netxen/netxen_nic_hw.c')
-rw-r--r--drivers/net/netxen/netxen_nic_hw.c124
1 files changed, 51 insertions, 73 deletions
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
index 23c974a7e0e4..be643ea35233 100644
--- a/drivers/net/netxen/netxen_nic_hw.c
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -470,45 +470,6 @@ void netxen_p2_nic_set_multi(struct net_device *netdev)
470 netxen_nic_set_mcast_addr(adapter, index, null_addr); 470 netxen_nic_set_mcast_addr(adapter, index, null_addr);
471} 471}
472 472
473static int nx_p3_nic_add_mac(struct netxen_adapter *adapter,
474 u8 *addr, nx_mac_list_t **add_list, nx_mac_list_t **del_list)
475{
476 nx_mac_list_t *cur, *prev;
477
478 /* if in del_list, move it to adapter->mac_list */
479 for (cur = *del_list, prev = NULL; cur;) {
480 if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0) {
481 if (prev == NULL)
482 *del_list = cur->next;
483 else
484 prev->next = cur->next;
485 cur->next = adapter->mac_list;
486 adapter->mac_list = cur;
487 return 0;
488 }
489 prev = cur;
490 cur = cur->next;
491 }
492
493 /* make sure to add each mac address only once */
494 for (cur = adapter->mac_list; cur; cur = cur->next) {
495 if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0)
496 return 0;
497 }
498 /* not in del_list, create new entry and add to add_list */
499 cur = kmalloc(sizeof(*cur), in_atomic()? GFP_ATOMIC : GFP_KERNEL);
500 if (cur == NULL) {
501 printk(KERN_ERR "%s: cannot allocate memory. MAC filtering may"
502 "not work properly from now.\n", __func__);
503 return -1;
504 }
505
506 memcpy(cur->mac_addr, addr, ETH_ALEN);
507 cur->next = *add_list;
508 *add_list = cur;
509 return 0;
510}
511
512static int 473static int
513netxen_send_cmd_descs(struct netxen_adapter *adapter, 474netxen_send_cmd_descs(struct netxen_adapter *adapter,
514 struct cmd_desc_type0 *cmd_desc_arr, int nr_desc) 475 struct cmd_desc_type0 *cmd_desc_arr, int nr_desc)
@@ -555,14 +516,12 @@ netxen_send_cmd_descs(struct netxen_adapter *adapter,
555 return 0; 516 return 0;
556} 517}
557 518
558static int nx_p3_sre_macaddr_change(struct net_device *dev, 519static int
559 u8 *addr, unsigned op) 520nx_p3_sre_macaddr_change(struct netxen_adapter *adapter, u8 *addr, unsigned op)
560{ 521{
561 struct netxen_adapter *adapter = netdev_priv(dev);
562 nx_nic_req_t req; 522 nx_nic_req_t req;
563 nx_mac_req_t *mac_req; 523 nx_mac_req_t *mac_req;
564 u64 word; 524 u64 word;
565 int rv;
566 525
567 memset(&req, 0, sizeof(nx_nic_req_t)); 526 memset(&req, 0, sizeof(nx_nic_req_t));
568 req.qhdr = cpu_to_le64(NX_NIC_REQUEST << 23); 527 req.qhdr = cpu_to_le64(NX_NIC_REQUEST << 23);
@@ -574,28 +533,51 @@ static int nx_p3_sre_macaddr_change(struct net_device *dev,
574 mac_req->op = op; 533 mac_req->op = op;
575 memcpy(mac_req->mac_addr, addr, 6); 534 memcpy(mac_req->mac_addr, addr, 6);
576 535
577 rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); 536 return netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
578 if (rv != 0) { 537}
579 printk(KERN_ERR "ERROR. Could not send mac update\n"); 538
580 return rv; 539static int nx_p3_nic_add_mac(struct netxen_adapter *adapter,
540 u8 *addr, struct list_head *del_list)
541{
542 struct list_head *head;
543 nx_mac_list_t *cur;
544
545 /* look up if already exists */
546 list_for_each(head, del_list) {
547 cur = list_entry(head, nx_mac_list_t, list);
548
549 if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0) {
550 list_move_tail(head, &adapter->mac_list);
551 return 0;
552 }
581 } 553 }
582 554
583 return 0; 555 cur = kzalloc(sizeof(nx_mac_list_t), GFP_ATOMIC);
556 if (cur == NULL) {
557 printk(KERN_ERR "%s: failed to add mac address filter\n",
558 adapter->netdev->name);
559 return -ENOMEM;
560 }
561 memcpy(cur->mac_addr, addr, ETH_ALEN);
562 list_add_tail(&cur->list, &adapter->mac_list);
563 return nx_p3_sre_macaddr_change(adapter,
564 cur->mac_addr, NETXEN_MAC_ADD);
584} 565}
585 566
586void netxen_p3_nic_set_multi(struct net_device *netdev) 567void netxen_p3_nic_set_multi(struct net_device *netdev)
587{ 568{
588 struct netxen_adapter *adapter = netdev_priv(netdev); 569 struct netxen_adapter *adapter = netdev_priv(netdev);
589 nx_mac_list_t *cur, *next, *del_list, *add_list = NULL;
590 struct dev_mc_list *mc_ptr; 570 struct dev_mc_list *mc_ptr;
591 u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 571 u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
592 u32 mode = VPORT_MISS_MODE_DROP; 572 u32 mode = VPORT_MISS_MODE_DROP;
573 LIST_HEAD(del_list);
574 struct list_head *head;
575 nx_mac_list_t *cur;
593 576
594 del_list = adapter->mac_list; 577 list_splice_tail_init(&adapter->mac_list, &del_list);
595 adapter->mac_list = NULL;
596 578
597 nx_p3_nic_add_mac(adapter, netdev->dev_addr, &add_list, &del_list); 579 nx_p3_nic_add_mac(adapter, netdev->dev_addr, &del_list);
598 nx_p3_nic_add_mac(adapter, bcast_addr, &add_list, &del_list); 580 nx_p3_nic_add_mac(adapter, bcast_addr, &del_list);
599 581
600 if (netdev->flags & IFF_PROMISC) { 582 if (netdev->flags & IFF_PROMISC) {
601 mode = VPORT_MISS_MODE_ACCEPT_ALL; 583 mode = VPORT_MISS_MODE_ACCEPT_ALL;
@@ -611,25 +593,20 @@ void netxen_p3_nic_set_multi(struct net_device *netdev)
611 if (netdev->mc_count > 0) { 593 if (netdev->mc_count > 0) {
612 for (mc_ptr = netdev->mc_list; mc_ptr; 594 for (mc_ptr = netdev->mc_list; mc_ptr;
613 mc_ptr = mc_ptr->next) { 595 mc_ptr = mc_ptr->next) {
614 nx_p3_nic_add_mac(adapter, mc_ptr->dmi_addr, 596 nx_p3_nic_add_mac(adapter, mc_ptr->dmi_addr, &del_list);
615 &add_list, &del_list);
616 } 597 }
617 } 598 }
618 599
619send_fw_cmd: 600send_fw_cmd:
620 adapter->set_promisc(adapter, mode); 601 adapter->set_promisc(adapter, mode);
621 for (cur = del_list; cur;) { 602 head = &del_list;
622 nx_p3_sre_macaddr_change(netdev, cur->mac_addr, NETXEN_MAC_DEL); 603 while (!list_empty(head)) {
623 next = cur->next; 604 cur = list_entry(head->next, nx_mac_list_t, list);
605
606 nx_p3_sre_macaddr_change(adapter,
607 cur->mac_addr, NETXEN_MAC_DEL);
608 list_del(&cur->list);
624 kfree(cur); 609 kfree(cur);
625 cur = next;
626 }
627 for (cur = add_list; cur;) {
628 nx_p3_sre_macaddr_change(netdev, cur->mac_addr, NETXEN_MAC_ADD);
629 next = cur->next;
630 cur->next = adapter->mac_list;
631 adapter->mac_list = cur;
632 cur = next;
633 } 610 }
634} 611}
635 612
@@ -654,14 +631,15 @@ int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32 mode)
654 631
655void netxen_p3_free_mac_list(struct netxen_adapter *adapter) 632void netxen_p3_free_mac_list(struct netxen_adapter *adapter)
656{ 633{
657 nx_mac_list_t *cur, *next; 634 nx_mac_list_t *cur;
658 635 struct list_head *head = &adapter->mac_list;
659 cur = adapter->mac_list; 636
660 637 while (!list_empty(head)) {
661 while (cur) { 638 cur = list_entry(head->next, nx_mac_list_t, list);
662 next = cur->next; 639 nx_p3_sre_macaddr_change(adapter,
640 cur->mac_addr, NETXEN_MAC_DEL);
641 list_del(&cur->list);
663 kfree(cur); 642 kfree(cur);
664 cur = next;
665 } 643 }
666} 644}
667 645