diff options
author | Glenn Streiff <gstreiff@neteffect.com> | 2008-02-15 12:41:27 -0500 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2008-02-15 18:05:05 -0500 |
commit | 11e0704b7ec3abfeaee7e3a56f11c82024d1ae01 (patch) | |
tree | b4929f77a34339c47ee4863fed47d8bca717c538 | |
parent | c7482b81c8b524193d736488c149adbe27a7eb7f (diff) |
RDMA/nes: Fix MAC interrupt erroneously masked on ifdown
Only mask out MAC interrupt if necessary and re-enable on ifup. There
could be multiple netdevs going through the same MAC. MAC interrupts
should not be masked off until the last netdev is downed.
Signed-off-by: Chien Tung <ctung@neteffect.com>
Signed-off-by: Glenn Streiff <gstreiff@neteffect.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
-rw-r--r-- | drivers/infiniband/hw/nes/nes_nic.c | 52 |
1 files changed, 36 insertions, 16 deletions
diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c index b6cc265aa9a4..67827ad894e9 100644 --- a/drivers/infiniband/hw/nes/nes_nic.c +++ b/drivers/infiniband/hw/nes/nes_nic.c | |||
@@ -148,14 +148,15 @@ static int nes_netdev_open(struct net_device *netdev) | |||
148 | struct nes_device *nesdev = nesvnic->nesdev; | 148 | struct nes_device *nesdev = nesvnic->nesdev; |
149 | int ret; | 149 | int ret; |
150 | int i; | 150 | int i; |
151 | struct nes_vnic *first_nesvnic; | 151 | struct nes_vnic *first_nesvnic = NULL; |
152 | u32 nic_active_bit; | 152 | u32 nic_active_bit; |
153 | u32 nic_active; | 153 | u32 nic_active; |
154 | struct list_head *list_pos, *list_temp; | ||
154 | 155 | ||
155 | assert(nesdev != NULL); | 156 | assert(nesdev != NULL); |
156 | 157 | ||
157 | first_nesvnic = list_entry(nesdev->nesadapter->nesvnic_list[nesdev->mac_index].next, | 158 | if (nesvnic->netdev_open == 1) |
158 | struct nes_vnic, list); | 159 | return 0; |
159 | 160 | ||
160 | if (netif_msg_ifup(nesvnic)) | 161 | if (netif_msg_ifup(nesvnic)) |
161 | printk(KERN_INFO PFX "%s: enabling interface\n", netdev->name); | 162 | printk(KERN_INFO PFX "%s: enabling interface\n", netdev->name); |
@@ -225,7 +226,18 @@ static int nes_netdev_open(struct net_device *netdev) | |||
225 | nes_write32(nesdev->regs+NES_CQE_ALLOC, NES_CQE_ALLOC_NOTIFY_NEXT | | 226 | nes_write32(nesdev->regs+NES_CQE_ALLOC, NES_CQE_ALLOC_NOTIFY_NEXT | |
226 | nesvnic->nic_cq.cq_number); | 227 | nesvnic->nic_cq.cq_number); |
227 | nes_read32(nesdev->regs+NES_CQE_ALLOC); | 228 | nes_read32(nesdev->regs+NES_CQE_ALLOC); |
228 | 229 | list_for_each_safe(list_pos, list_temp, &nesdev->nesadapter->nesvnic_list[nesdev->mac_index]) { | |
230 | first_nesvnic = container_of(list_pos, struct nes_vnic, list); | ||
231 | if (first_nesvnic->netdev_open == 1) | ||
232 | break; | ||
233 | } | ||
234 | if (first_nesvnic->netdev_open == 0) { | ||
235 | nes_debug(NES_DBG_INIT, "Setting up MAC interrupt mask.\n"); | ||
236 | nes_write_indexed(nesdev, NES_IDX_MAC_INT_MASK + (0x200 * nesdev->mac_index), | ||
237 | ~(NES_MAC_INT_LINK_STAT_CHG | NES_MAC_INT_XGMII_EXT | | ||
238 | NES_MAC_INT_TX_UNDERFLOW | NES_MAC_INT_TX_ERROR)); | ||
239 | first_nesvnic = nesvnic; | ||
240 | } | ||
229 | if (first_nesvnic->linkup) { | 241 | if (first_nesvnic->linkup) { |
230 | /* Enable network packets */ | 242 | /* Enable network packets */ |
231 | nesvnic->linkup = 1; | 243 | nesvnic->linkup = 1; |
@@ -248,6 +260,8 @@ static int nes_netdev_stop(struct net_device *netdev) | |||
248 | struct nes_device *nesdev = nesvnic->nesdev; | 260 | struct nes_device *nesdev = nesvnic->nesdev; |
249 | u32 nic_active_mask; | 261 | u32 nic_active_mask; |
250 | u32 nic_active; | 262 | u32 nic_active; |
263 | struct nes_vnic *first_nesvnic = NULL; | ||
264 | struct list_head *list_pos, *list_temp; | ||
251 | 265 | ||
252 | nes_debug(NES_DBG_SHUTDOWN, "nesvnic=%p, nesdev=%p, netdev=%p %s\n", | 266 | nes_debug(NES_DBG_SHUTDOWN, "nesvnic=%p, nesdev=%p, netdev=%p %s\n", |
253 | nesvnic, nesdev, netdev, netdev->name); | 267 | nesvnic, nesdev, netdev, netdev->name); |
@@ -260,9 +274,20 @@ static int nes_netdev_stop(struct net_device *netdev) | |||
260 | /* Disable network packets */ | 274 | /* Disable network packets */ |
261 | napi_disable(&nesvnic->napi); | 275 | napi_disable(&nesvnic->napi); |
262 | netif_stop_queue(netdev); | 276 | netif_stop_queue(netdev); |
263 | if ((nesdev->netdev[0] == netdev) & (nesvnic->logical_port == nesdev->mac_index)) { | 277 | list_for_each_safe(list_pos, list_temp, &nesdev->nesadapter->nesvnic_list[nesdev->mac_index]) { |
264 | nes_write_indexed(nesdev, | 278 | first_nesvnic = container_of(list_pos, struct nes_vnic, list); |
265 | NES_IDX_MAC_INT_MASK+(0x200*nesdev->mac_index), 0xffffffff); | 279 | if ((first_nesvnic->netdev_open == 1) && (first_nesvnic != nesvnic)) |
280 | break; | ||
281 | } | ||
282 | |||
283 | if (first_nesvnic->netdev_open == 0) | ||
284 | nes_write_indexed(nesdev, NES_IDX_MAC_INT_MASK+(0x200*nesdev->mac_index), 0xffffffff); | ||
285 | else if ((first_nesvnic != nesvnic) && | ||
286 | (PCI_FUNC(first_nesvnic->nesdev->pcidev->devfn) != PCI_FUNC(nesvnic->nesdev->pcidev->devfn))) { | ||
287 | nes_write_indexed(nesdev, NES_IDX_MAC_INT_MASK + (0x200 * nesdev->mac_index), 0xffffffff); | ||
288 | nes_write_indexed(first_nesvnic->nesdev, NES_IDX_MAC_INT_MASK + (0x200 * first_nesvnic->nesdev->mac_index), | ||
289 | ~(NES_MAC_INT_LINK_STAT_CHG | NES_MAC_INT_XGMII_EXT | | ||
290 | NES_MAC_INT_TX_UNDERFLOW | NES_MAC_INT_TX_ERROR)); | ||
266 | } | 291 | } |
267 | 292 | ||
268 | nic_active_mask = ~((u32)(1 << nesvnic->nic_index)); | 293 | nic_active_mask = ~((u32)(1 << nesvnic->nic_index)); |
@@ -859,7 +884,6 @@ void nes_netdev_set_multicast_list(struct net_device *netdev) | |||
859 | for (mc_index=0; mc_index < NES_MULTICAST_PF_MAX; mc_index++) { | 884 | for (mc_index=0; mc_index < NES_MULTICAST_PF_MAX; mc_index++) { |
860 | while (multicast_addr && nesvnic->mcrq_mcast_filter && ((mc_nic_index = nesvnic->mcrq_mcast_filter(nesvnic, multicast_addr->dmi_addr)) == 0)) | 885 | while (multicast_addr && nesvnic->mcrq_mcast_filter && ((mc_nic_index = nesvnic->mcrq_mcast_filter(nesvnic, multicast_addr->dmi_addr)) == 0)) |
861 | multicast_addr = multicast_addr->next; | 886 | multicast_addr = multicast_addr->next; |
862 | |||
863 | if (mc_nic_index < 0) | 887 | if (mc_nic_index < 0) |
864 | mc_nic_index = nesvnic->nic_index; | 888 | mc_nic_index = nesvnic->nic_index; |
865 | if (multicast_addr) { | 889 | if (multicast_addr) { |
@@ -1610,7 +1634,7 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev, | |||
1610 | list_add_tail(&nesvnic->list, &nesdev->nesadapter->nesvnic_list[nesdev->mac_index]); | 1634 | list_add_tail(&nesvnic->list, &nesdev->nesadapter->nesvnic_list[nesdev->mac_index]); |
1611 | 1635 | ||
1612 | if ((nesdev->netdev_count == 0) && | 1636 | if ((nesdev->netdev_count == 0) && |
1613 | (PCI_FUNC(nesdev->pcidev->devfn) == nesdev->mac_index)) { | 1637 | (PCI_FUNC(nesdev->pcidev->devfn) == nesdev->mac_index)) { |
1614 | nes_debug(NES_DBG_INIT, "Setting up PHY interrupt mask. Using register index 0x%04X\n", | 1638 | nes_debug(NES_DBG_INIT, "Setting up PHY interrupt mask. Using register index 0x%04X\n", |
1615 | NES_IDX_PHY_PCS_CONTROL_STATUS0+(0x200*(nesvnic->logical_port&1))); | 1639 | NES_IDX_PHY_PCS_CONTROL_STATUS0+(0x200*(nesvnic->logical_port&1))); |
1616 | u32temp = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 + | 1640 | u32temp = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 + |
@@ -1648,18 +1672,14 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev, | |||
1648 | nesvnic->linkup = 1; | 1672 | nesvnic->linkup = 1; |
1649 | } | 1673 | } |
1650 | } | 1674 | } |
1651 | nes_debug(NES_DBG_INIT, "Setting up MAC interrupt mask.\n"); | ||
1652 | /* clear the MAC interrupt status, assumes direct logical to physical mapping */ | 1675 | /* clear the MAC interrupt status, assumes direct logical to physical mapping */ |
1653 | u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS+(0x200*nesvnic->logical_port)); | 1676 | u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (0x200 * nesdev->mac_index)); |
1654 | nes_debug(NES_DBG_INIT, "Phy interrupt status = 0x%X.\n", u32temp); | 1677 | nes_debug(NES_DBG_INIT, "Phy interrupt status = 0x%X.\n", u32temp); |
1655 | nes_write_indexed(nesdev, NES_IDX_MAC_INT_STATUS+(0x200*nesvnic->logical_port), u32temp); | 1678 | nes_write_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (0x200 * nesdev->mac_index), u32temp); |
1656 | 1679 | ||
1657 | if (nesdev->nesadapter->phy_type[nesvnic->logical_port] != NES_PHY_TYPE_IRIS) | 1680 | if (nesdev->nesadapter->phy_type[nesdev->mac_index] != NES_PHY_TYPE_IRIS) |
1658 | nes_init_phy(nesdev); | 1681 | nes_init_phy(nesdev); |
1659 | 1682 | ||
1660 | nes_write_indexed(nesdev, NES_IDX_MAC_INT_MASK+(0x200*nesvnic->logical_port), | ||
1661 | ~(NES_MAC_INT_LINK_STAT_CHG | NES_MAC_INT_XGMII_EXT | | ||
1662 | NES_MAC_INT_TX_UNDERFLOW | NES_MAC_INT_TX_ERROR)); | ||
1663 | } | 1683 | } |
1664 | 1684 | ||
1665 | return netdev; | 1685 | return netdev; |