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>
This commit is contained in:
parent
c7482b81c8
commit
11e0704b7e
1 changed files with 36 additions and 16 deletions
|
@ -148,14 +148,15 @@ static int nes_netdev_open(struct net_device *netdev)
|
||||||
struct nes_device *nesdev = nesvnic->nesdev;
|
struct nes_device *nesdev = nesvnic->nesdev;
|
||||||
int ret;
|
int ret;
|
||||||
int i;
|
int i;
|
||||||
struct nes_vnic *first_nesvnic;
|
struct nes_vnic *first_nesvnic = NULL;
|
||||||
u32 nic_active_bit;
|
u32 nic_active_bit;
|
||||||
u32 nic_active;
|
u32 nic_active;
|
||||||
|
struct list_head *list_pos, *list_temp;
|
||||||
|
|
||||||
assert(nesdev != NULL);
|
assert(nesdev != NULL);
|
||||||
|
|
||||||
first_nesvnic = list_entry(nesdev->nesadapter->nesvnic_list[nesdev->mac_index].next,
|
if (nesvnic->netdev_open == 1)
|
||||||
struct nes_vnic, list);
|
return 0;
|
||||||
|
|
||||||
if (netif_msg_ifup(nesvnic))
|
if (netif_msg_ifup(nesvnic))
|
||||||
printk(KERN_INFO PFX "%s: enabling interface\n", netdev->name);
|
printk(KERN_INFO PFX "%s: enabling interface\n", netdev->name);
|
||||||
|
@ -225,7 +226,18 @@ static int nes_netdev_open(struct net_device *netdev)
|
||||||
nes_write32(nesdev->regs+NES_CQE_ALLOC, NES_CQE_ALLOC_NOTIFY_NEXT |
|
nes_write32(nesdev->regs+NES_CQE_ALLOC, NES_CQE_ALLOC_NOTIFY_NEXT |
|
||||||
nesvnic->nic_cq.cq_number);
|
nesvnic->nic_cq.cq_number);
|
||||||
nes_read32(nesdev->regs+NES_CQE_ALLOC);
|
nes_read32(nesdev->regs+NES_CQE_ALLOC);
|
||||||
|
list_for_each_safe(list_pos, list_temp, &nesdev->nesadapter->nesvnic_list[nesdev->mac_index]) {
|
||||||
|
first_nesvnic = container_of(list_pos, struct nes_vnic, list);
|
||||||
|
if (first_nesvnic->netdev_open == 1)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (first_nesvnic->netdev_open == 0) {
|
||||||
|
nes_debug(NES_DBG_INIT, "Setting up MAC interrupt mask.\n");
|
||||||
|
nes_write_indexed(nesdev, NES_IDX_MAC_INT_MASK + (0x200 * nesdev->mac_index),
|
||||||
|
~(NES_MAC_INT_LINK_STAT_CHG | NES_MAC_INT_XGMII_EXT |
|
||||||
|
NES_MAC_INT_TX_UNDERFLOW | NES_MAC_INT_TX_ERROR));
|
||||||
|
first_nesvnic = nesvnic;
|
||||||
|
}
|
||||||
if (first_nesvnic->linkup) {
|
if (first_nesvnic->linkup) {
|
||||||
/* Enable network packets */
|
/* Enable network packets */
|
||||||
nesvnic->linkup = 1;
|
nesvnic->linkup = 1;
|
||||||
|
@ -248,6 +260,8 @@ static int nes_netdev_stop(struct net_device *netdev)
|
||||||
struct nes_device *nesdev = nesvnic->nesdev;
|
struct nes_device *nesdev = nesvnic->nesdev;
|
||||||
u32 nic_active_mask;
|
u32 nic_active_mask;
|
||||||
u32 nic_active;
|
u32 nic_active;
|
||||||
|
struct nes_vnic *first_nesvnic = NULL;
|
||||||
|
struct list_head *list_pos, *list_temp;
|
||||||
|
|
||||||
nes_debug(NES_DBG_SHUTDOWN, "nesvnic=%p, nesdev=%p, netdev=%p %s\n",
|
nes_debug(NES_DBG_SHUTDOWN, "nesvnic=%p, nesdev=%p, netdev=%p %s\n",
|
||||||
nesvnic, nesdev, netdev, netdev->name);
|
nesvnic, nesdev, netdev, netdev->name);
|
||||||
|
@ -260,9 +274,20 @@ static int nes_netdev_stop(struct net_device *netdev)
|
||||||
/* Disable network packets */
|
/* Disable network packets */
|
||||||
napi_disable(&nesvnic->napi);
|
napi_disable(&nesvnic->napi);
|
||||||
netif_stop_queue(netdev);
|
netif_stop_queue(netdev);
|
||||||
if ((nesdev->netdev[0] == netdev) & (nesvnic->logical_port == nesdev->mac_index)) {
|
list_for_each_safe(list_pos, list_temp, &nesdev->nesadapter->nesvnic_list[nesdev->mac_index]) {
|
||||||
nes_write_indexed(nesdev,
|
first_nesvnic = container_of(list_pos, struct nes_vnic, list);
|
||||||
NES_IDX_MAC_INT_MASK+(0x200*nesdev->mac_index), 0xffffffff);
|
if ((first_nesvnic->netdev_open == 1) && (first_nesvnic != nesvnic))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (first_nesvnic->netdev_open == 0)
|
||||||
|
nes_write_indexed(nesdev, NES_IDX_MAC_INT_MASK+(0x200*nesdev->mac_index), 0xffffffff);
|
||||||
|
else if ((first_nesvnic != nesvnic) &&
|
||||||
|
(PCI_FUNC(first_nesvnic->nesdev->pcidev->devfn) != PCI_FUNC(nesvnic->nesdev->pcidev->devfn))) {
|
||||||
|
nes_write_indexed(nesdev, NES_IDX_MAC_INT_MASK + (0x200 * nesdev->mac_index), 0xffffffff);
|
||||||
|
nes_write_indexed(first_nesvnic->nesdev, NES_IDX_MAC_INT_MASK + (0x200 * first_nesvnic->nesdev->mac_index),
|
||||||
|
~(NES_MAC_INT_LINK_STAT_CHG | NES_MAC_INT_XGMII_EXT |
|
||||||
|
NES_MAC_INT_TX_UNDERFLOW | NES_MAC_INT_TX_ERROR));
|
||||||
}
|
}
|
||||||
|
|
||||||
nic_active_mask = ~((u32)(1 << nesvnic->nic_index));
|
nic_active_mask = ~((u32)(1 << nesvnic->nic_index));
|
||||||
|
@ -859,7 +884,6 @@ void nes_netdev_set_multicast_list(struct net_device *netdev)
|
||||||
for (mc_index=0; mc_index < NES_MULTICAST_PF_MAX; mc_index++) {
|
for (mc_index=0; mc_index < NES_MULTICAST_PF_MAX; mc_index++) {
|
||||||
while (multicast_addr && nesvnic->mcrq_mcast_filter && ((mc_nic_index = nesvnic->mcrq_mcast_filter(nesvnic, multicast_addr->dmi_addr)) == 0))
|
while (multicast_addr && nesvnic->mcrq_mcast_filter && ((mc_nic_index = nesvnic->mcrq_mcast_filter(nesvnic, multicast_addr->dmi_addr)) == 0))
|
||||||
multicast_addr = multicast_addr->next;
|
multicast_addr = multicast_addr->next;
|
||||||
|
|
||||||
if (mc_nic_index < 0)
|
if (mc_nic_index < 0)
|
||||||
mc_nic_index = nesvnic->nic_index;
|
mc_nic_index = nesvnic->nic_index;
|
||||||
if (multicast_addr) {
|
if (multicast_addr) {
|
||||||
|
@ -1610,7 +1634,7 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev,
|
||||||
list_add_tail(&nesvnic->list, &nesdev->nesadapter->nesvnic_list[nesdev->mac_index]);
|
list_add_tail(&nesvnic->list, &nesdev->nesadapter->nesvnic_list[nesdev->mac_index]);
|
||||||
|
|
||||||
if ((nesdev->netdev_count == 0) &&
|
if ((nesdev->netdev_count == 0) &&
|
||||||
(PCI_FUNC(nesdev->pcidev->devfn) == nesdev->mac_index)) {
|
(PCI_FUNC(nesdev->pcidev->devfn) == nesdev->mac_index)) {
|
||||||
nes_debug(NES_DBG_INIT, "Setting up PHY interrupt mask. Using register index 0x%04X\n",
|
nes_debug(NES_DBG_INIT, "Setting up PHY interrupt mask. Using register index 0x%04X\n",
|
||||||
NES_IDX_PHY_PCS_CONTROL_STATUS0+(0x200*(nesvnic->logical_port&1)));
|
NES_IDX_PHY_PCS_CONTROL_STATUS0+(0x200*(nesvnic->logical_port&1)));
|
||||||
u32temp = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 +
|
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,
|
||||||
nesvnic->linkup = 1;
|
nesvnic->linkup = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nes_debug(NES_DBG_INIT, "Setting up MAC interrupt mask.\n");
|
|
||||||
/* clear the MAC interrupt status, assumes direct logical to physical mapping */
|
/* clear the MAC interrupt status, assumes direct logical to physical mapping */
|
||||||
u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS+(0x200*nesvnic->logical_port));
|
u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (0x200 * nesdev->mac_index));
|
||||||
nes_debug(NES_DBG_INIT, "Phy interrupt status = 0x%X.\n", u32temp);
|
nes_debug(NES_DBG_INIT, "Phy interrupt status = 0x%X.\n", u32temp);
|
||||||
nes_write_indexed(nesdev, NES_IDX_MAC_INT_STATUS+(0x200*nesvnic->logical_port), u32temp);
|
nes_write_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (0x200 * nesdev->mac_index), u32temp);
|
||||||
|
|
||||||
if (nesdev->nesadapter->phy_type[nesvnic->logical_port] != NES_PHY_TYPE_IRIS)
|
if (nesdev->nesadapter->phy_type[nesdev->mac_index] != NES_PHY_TYPE_IRIS)
|
||||||
nes_init_phy(nesdev);
|
nes_init_phy(nesdev);
|
||||||
|
|
||||||
nes_write_indexed(nesdev, NES_IDX_MAC_INT_MASK+(0x200*nesvnic->logical_port),
|
|
||||||
~(NES_MAC_INT_LINK_STAT_CHG | NES_MAC_INT_XGMII_EXT |
|
|
||||||
NES_MAC_INT_TX_UNDERFLOW | NES_MAC_INT_TX_ERROR));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return netdev;
|
return netdev;
|
||||||
|
|
Loading…
Add table
Reference in a new issue