diff options
author | Dhananjay Phadke <dhananjay@netxen.com> | 2009-05-05 15:05:07 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-05-06 18:33:36 -0400 |
commit | 5cf4d323f8864dab818d500ec74f2fcb9ad5bf89 (patch) | |
tree | 5f90365023b2b7a78852be460b770c5ae8731723 /drivers/net/netxen/netxen_nic_hw.c | |
parent | 22527864ed7ee6c50f3c4d4b03c83c963caf5c0b (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.c | 124 |
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 | ||
473 | static 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 | |||
512 | static int | 473 | static int |
513 | netxen_send_cmd_descs(struct netxen_adapter *adapter, | 474 | netxen_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 | ||
558 | static int nx_p3_sre_macaddr_change(struct net_device *dev, | 519 | static int |
559 | u8 *addr, unsigned op) | 520 | nx_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; | 539 | static 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 | ||
586 | void netxen_p3_nic_set_multi(struct net_device *netdev) | 567 | void 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 | ||
619 | send_fw_cmd: | 600 | send_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 | ||
655 | void netxen_p3_free_mac_list(struct netxen_adapter *adapter) | 632 | void 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 | ||