diff options
Diffstat (limited to 'drivers/infiniband/hw/nes/nes.c')
-rw-r--r-- | drivers/infiniband/hw/nes/nes.c | 35 |
1 files changed, 30 insertions, 5 deletions
diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c index 0c9f0aa5d4ea..3b4ec3238ceb 100644 --- a/drivers/infiniband/hw/nes/nes.c +++ b/drivers/infiniband/hw/nes/nes.c | |||
@@ -144,6 +144,7 @@ static int nes_inetaddr_event(struct notifier_block *notifier, | |||
144 | struct nes_device *nesdev; | 144 | struct nes_device *nesdev; |
145 | struct net_device *netdev; | 145 | struct net_device *netdev; |
146 | struct nes_vnic *nesvnic; | 146 | struct nes_vnic *nesvnic; |
147 | unsigned int is_bonded; | ||
147 | 148 | ||
148 | nes_debug(NES_DBG_NETDEV, "nes_inetaddr_event: ip address %pI4, netmask %pI4.\n", | 149 | nes_debug(NES_DBG_NETDEV, "nes_inetaddr_event: ip address %pI4, netmask %pI4.\n", |
149 | &ifa->ifa_address, &ifa->ifa_mask); | 150 | &ifa->ifa_address, &ifa->ifa_mask); |
@@ -152,7 +153,8 @@ static int nes_inetaddr_event(struct notifier_block *notifier, | |||
152 | nesdev, nesdev->netdev[0]->name); | 153 | nesdev, nesdev->netdev[0]->name); |
153 | netdev = nesdev->netdev[0]; | 154 | netdev = nesdev->netdev[0]; |
154 | nesvnic = netdev_priv(netdev); | 155 | nesvnic = netdev_priv(netdev); |
155 | if (netdev == event_netdev) { | 156 | is_bonded = (netdev->master == event_netdev); |
157 | if ((netdev == event_netdev) || is_bonded) { | ||
156 | if (nesvnic->rdma_enabled == 0) { | 158 | if (nesvnic->rdma_enabled == 0) { |
157 | nes_debug(NES_DBG_NETDEV, "Returning without processing event for %s since" | 159 | nes_debug(NES_DBG_NETDEV, "Returning without processing event for %s since" |
158 | " RDMA is not enabled.\n", | 160 | " RDMA is not enabled.\n", |
@@ -169,7 +171,10 @@ static int nes_inetaddr_event(struct notifier_block *notifier, | |||
169 | nes_manage_arp_cache(netdev, netdev->dev_addr, | 171 | nes_manage_arp_cache(netdev, netdev->dev_addr, |
170 | ntohl(nesvnic->local_ipaddr), NES_ARP_DELETE); | 172 | ntohl(nesvnic->local_ipaddr), NES_ARP_DELETE); |
171 | nesvnic->local_ipaddr = 0; | 173 | nesvnic->local_ipaddr = 0; |
172 | return NOTIFY_OK; | 174 | if (is_bonded) |
175 | continue; | ||
176 | else | ||
177 | return NOTIFY_OK; | ||
173 | break; | 178 | break; |
174 | case NETDEV_UP: | 179 | case NETDEV_UP: |
175 | nes_debug(NES_DBG_NETDEV, "event:UP\n"); | 180 | nes_debug(NES_DBG_NETDEV, "event:UP\n"); |
@@ -178,15 +183,24 @@ static int nes_inetaddr_event(struct notifier_block *notifier, | |||
178 | nes_debug(NES_DBG_NETDEV, "Interface already has local_ipaddr\n"); | 183 | nes_debug(NES_DBG_NETDEV, "Interface already has local_ipaddr\n"); |
179 | return NOTIFY_OK; | 184 | return NOTIFY_OK; |
180 | } | 185 | } |
186 | /* fall through */ | ||
187 | case NETDEV_CHANGEADDR: | ||
181 | /* Add the address to the IP table */ | 188 | /* Add the address to the IP table */ |
182 | nesvnic->local_ipaddr = ifa->ifa_address; | 189 | if (netdev->master) |
190 | nesvnic->local_ipaddr = | ||
191 | ((struct in_device *)netdev->master->ip_ptr)->ifa_list->ifa_address; | ||
192 | else | ||
193 | nesvnic->local_ipaddr = ifa->ifa_address; | ||
183 | 194 | ||
184 | nes_write_indexed(nesdev, | 195 | nes_write_indexed(nesdev, |
185 | NES_IDX_DST_IP_ADDR+(0x10*PCI_FUNC(nesdev->pcidev->devfn)), | 196 | NES_IDX_DST_IP_ADDR+(0x10*PCI_FUNC(nesdev->pcidev->devfn)), |
186 | ntohl(ifa->ifa_address)); | 197 | ntohl(nesvnic->local_ipaddr)); |
187 | nes_manage_arp_cache(netdev, netdev->dev_addr, | 198 | nes_manage_arp_cache(netdev, netdev->dev_addr, |
188 | ntohl(nesvnic->local_ipaddr), NES_ARP_ADD); | 199 | ntohl(nesvnic->local_ipaddr), NES_ARP_ADD); |
189 | return NOTIFY_OK; | 200 | if (is_bonded) |
201 | continue; | ||
202 | else | ||
203 | return NOTIFY_OK; | ||
190 | break; | 204 | break; |
191 | default: | 205 | default: |
192 | break; | 206 | break; |
@@ -660,6 +674,8 @@ static int __devinit nes_probe(struct pci_dev *pcidev, const struct pci_device_i | |||
660 | } | 674 | } |
661 | nes_notifiers_registered++; | 675 | nes_notifiers_registered++; |
662 | 676 | ||
677 | INIT_DELAYED_WORK(&nesdev->work, nes_recheck_link_status); | ||
678 | |||
663 | /* Initialize network devices */ | 679 | /* Initialize network devices */ |
664 | if ((netdev = nes_netdev_init(nesdev, mmio_regs)) == NULL) | 680 | if ((netdev = nes_netdev_init(nesdev, mmio_regs)) == NULL) |
665 | goto bail7; | 681 | goto bail7; |
@@ -742,6 +758,7 @@ static void __devexit nes_remove(struct pci_dev *pcidev) | |||
742 | struct nes_device *nesdev = pci_get_drvdata(pcidev); | 758 | struct nes_device *nesdev = pci_get_drvdata(pcidev); |
743 | struct net_device *netdev; | 759 | struct net_device *netdev; |
744 | int netdev_index = 0; | 760 | int netdev_index = 0; |
761 | unsigned long flags; | ||
745 | 762 | ||
746 | if (nesdev->netdev_count) { | 763 | if (nesdev->netdev_count) { |
747 | netdev = nesdev->netdev[netdev_index]; | 764 | netdev = nesdev->netdev[netdev_index]; |
@@ -768,6 +785,14 @@ static void __devexit nes_remove(struct pci_dev *pcidev) | |||
768 | free_irq(pcidev->irq, nesdev); | 785 | free_irq(pcidev->irq, nesdev); |
769 | tasklet_kill(&nesdev->dpc_tasklet); | 786 | tasklet_kill(&nesdev->dpc_tasklet); |
770 | 787 | ||
788 | spin_lock_irqsave(&nesdev->nesadapter->phy_lock, flags); | ||
789 | if (nesdev->link_recheck) { | ||
790 | spin_unlock_irqrestore(&nesdev->nesadapter->phy_lock, flags); | ||
791 | cancel_delayed_work_sync(&nesdev->work); | ||
792 | } else { | ||
793 | spin_unlock_irqrestore(&nesdev->nesadapter->phy_lock, flags); | ||
794 | } | ||
795 | |||
771 | /* Deallocate the Adapter Structure */ | 796 | /* Deallocate the Adapter Structure */ |
772 | nes_destroy_adapter(nesdev->nesadapter); | 797 | nes_destroy_adapter(nesdev->nesadapter); |
773 | 798 | ||