Skip to contentSkip to conversation

RDMA/nes: enable bonds on iw_nes

PATCH In review Maciej Sosnowski 2 participants 6 messages Nov 24, 2010 – Nov 26, 2010 3 messages not in the archive InfiniBand

lore
Share & tools
lore
#0 lore raw

PATCH 1/4 RDMA/nes: enable bonds on iw_nes

Enable configuring bonds on nes devices by adding missing support for master net_device to the driver

---

 drivers/infiniband/hw/nes/nes.c    |   24 +++++++++++++++++++-----
 drivers/infiniband/hw/nes/nes_cm.c |    8 +++++++-
 2 files changed, 26 insertions(+), 6 deletions(-)
drivers/infiniband/hw/nes/nes.c +19 -5
index 0c9f0aa..e17f52c 100644
@@ -144,6 +144,7 @@ static int nes_inetaddr_event(struct not
 	struct nes_device *nesdev;
 	struct net_device *netdev;
 	struct nes_vnic *nesvnic;
+	unsigned int is_bonded;
 
 	nes_debug(NES_DBG_NETDEV, "nes_inetaddr_event: ip address %pI4, netmask %pI4.\n",
 		  &ifa->ifa_address, &ifa->ifa_mask);
@@ -152,7 +153,8 @@ static int nes_inetaddr_event(struct not
 				nesdev, nesdev->netdev[0]->name);
 		netdev = nesdev->netdev[0];
 		nesvnic = netdev_priv(netdev);
-		if (netdev == event_netdev) {
+		is_bonded = (netdev->master == event_netdev);
+		if ((netdev == event_netdev) || is_bonded) {
 			if (nesvnic->rdma_enabled == 0) {
 				nes_debug(NES_DBG_NETDEV, "Returning without processing event for %s since"
 						" RDMA is not enabled.\n",
@@ -169,7 +171,10 @@ static int nes_inetaddr_event(struct not
 					nes_manage_arp_cache(netdev, netdev->dev_addr,
 							ntohl(nesvnic->local_ipaddr), NES_ARP_DELETE);
 					nesvnic->local_ipaddr = 0;
-					return NOTIFY_OK;
+					if (is_bonded)
+						continue;
+					else
+						return NOTIFY_OK;
 					break;
 				case NETDEV_UP:
 					nes_debug(NES_DBG_NETDEV, "event:UP\n");
@@ -178,15 +183,24 @@ static int nes_inetaddr_event(struct not
 						nes_debug(NES_DBG_NETDEV, "Interface already has local_ipaddr\n");
 						return NOTIFY_OK;
 					}
+					/* fall through */
+				case NETDEV_CHANGEADDR:
 					/* Add the address to the IP table */
-					nesvnic->local_ipaddr = ifa->ifa_address;
+					if (netdev->master)
+						nesvnic->local_ipaddr =
+							((struct in_device *)netdev->master->ip_ptr)->ifa_list->ifa_address;
+					else
+						nesvnic->local_ipaddr = ifa->ifa_address;
 
 					nes_write_indexed(nesdev,
 							NES_IDX_DST_IP_ADDR+(0x10*PCI_FUNC(nesdev->pcidev->devfn)),
-							ntohl(ifa->ifa_address));
+							ntohl(nesvnic->local_ipaddr));
 					nes_manage_arp_cache(netdev, netdev->dev_addr,
 							ntohl(nesvnic->local_ipaddr), NES_ARP_ADD);
-					return NOTIFY_OK;
+					if (is_bonded)
+						continue;
+					else
+						return NOTIFY_OK;
 					break;
 				default:
 					break;
drivers/infiniband/hw/nes/nes_cm.c +7 -1
index 25ad0f9..009ec81 100644
@@ -1107,6 +1107,7 @@ static int nes_addr_resolve_neigh(struct
 	struct flowi fl;
 	struct neighbour *neigh;
 	int rc = arpindex;
+	struct net_device *netdev;
 	struct nes_adapter *nesadapter = nesvnic->nesdev->nesadapter;
 
 	memset(&fl, 0, sizeof fl);
@@ -1117,7 +1118,12 @@ static int nes_addr_resolve_neigh(struct
 		return rc;
 	}
 
-	neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, nesvnic->netdev);
+	if (nesvnic->netdev->master)
+		netdev = nesvnic->netdev->master;
+	else
+		netdev = nesvnic->netdev;
+
+	neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, netdev);
 	if (neigh) {
 		if (neigh->nud_state & NUD_VALID) {
 			nes_debug(NES_DBG_CM, "Neighbor MAC address for 0x%08X"

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

#2 lore raw

PATCH 2/4 RDMA/nes: send IB_EVENT_PORT_ERR/PORT_ACTIVE event on link state interrupt

In reply to a message not in the archive

Depending on link state change IB_EVENT_PORT_ERR or IB_EVENT_PORT_ACTIVE should be dispatched in processing of mac interrupt.
Plug in the cable happen to result in series of interrupts changing driver's link state for a number of times before finally staying at link up (e.g. link up, link down, link up, link down, ..., link up). To prevent sending series of redundant IB_EVENT_PORT_ACTIVE
and IB_EVENT_PORT_ERR events they get filtered out by timer based nes_port_ibevent() routine.

---

 drivers/infiniband/hw/nes/nes_hw.c    |   14 ++++++++++++
 drivers/infiniband/hw/nes/nes_hw.h    |    6 +++++
 drivers/infiniband/hw/nes/nes_nic.c   |   35 ++++++++++++++++++++++++-------
 drivers/infiniband/hw/nes/nes_verbs.c |   37 ++++++++++++++++++++++++++++++++-
 4 files changed, 83 insertions(+), 9 deletions(-)
drivers/infiniband/hw/nes/nes_hw.c +14 -0
index 1980a46..2b89b06 100644
@@ -2608,6 +2608,13 @@ static void nes_process_mac_intr(struct 
 						netif_start_queue(nesvnic->netdev);
 					nesvnic->linkup = 1;
 					netif_carrier_on(nesvnic->netdev);
+
+					spin_lock(&nesvnic->port_ibevent_lock);
+					if (nesdev->iw_status == 0) {
+						nesdev->iw_status = 1;
+						nes_port_ibevent(nesvnic);
+					}
+					spin_unlock(&nesvnic->port_ibevent_lock);
 				}
 			}
 		} else {
@@ -2633,6 +2640,13 @@ static void nes_process_mac_intr(struct 
 						netif_stop_queue(nesvnic->netdev);
 					nesvnic->linkup = 0;
 					netif_carrier_off(nesvnic->netdev);
+
+					spin_lock(&nesvnic->port_ibevent_lock);
+					if (nesdev->iw_status == 1) {
+						nesdev->iw_status = 0;
+						nes_port_ibevent(nesvnic);
+					}
+					spin_unlock(&nesvnic->port_ibevent_lock);
 				}
 			}
 		}
drivers/infiniband/hw/nes/nes_hw.h +6 -0
index 1204c34..8a9ea9a 100644
@@ -1193,6 +1193,8 @@ struct nes_listener {
 
 struct nes_ib_device;
 
+#define NES_EVENT_DELAY msecs_to_jiffies(100)
+
 struct nes_vnic {
 	struct nes_ib_device *nesibdev;
 	u64 sq_full;
@@ -1247,6 +1249,10 @@ struct nes_vnic {
 	u32 lro_max_aggr;
 	struct net_lro_mgr lro_mgr;
 	struct net_lro_desc lro_desc[NES_MAX_LRO_DESCRIPTORS];
+	struct timer_list event_timer;
+	enum ib_event_type delayed_event;
+	enum ib_event_type last_dispatched_event;
+	spinlock_t port_ibevent_lock;
 };
 
 struct nes_ib_device {
drivers/infiniband/hw/nes/nes_nic.c +27 -8
index 3892e2c..b2101bc 100644
@@ -144,6 +144,7 @@ static int nes_netdev_open(struct net_de
 	u32 nic_active_bit;
 	u32 nic_active;
 	struct list_head *list_pos, *list_temp;
+	unsigned long flags;
 
 	assert(nesdev != NULL);
 
@@ -233,18 +234,27 @@ static int nes_netdev_open(struct net_de
 		first_nesvnic = nesvnic;
 	}
 
-	if (nesvnic->of_device_registered) {
-		nesdev->iw_status = 1;
-		nesdev->nesadapter->send_term_ok = 1;
-		nes_port_ibevent(nesvnic);
-	}
-
 	if (first_nesvnic->linkup) {
 		/* Enable network packets */
 		nesvnic->linkup = 1;
 		netif_start_queue(netdev);
 		netif_carrier_on(netdev);
 	}
+
+	spin_lock_irqsave(&nesvnic->port_ibevent_lock, flags);
+	if (nesvnic->of_device_registered) {
+		nesdev->nesadapter->send_term_ok = 1;
+		if (nesvnic->linkup == 1) {
+			if (nesdev->iw_status == 0) {
+				nesdev->iw_status = 1;
+				nes_port_ibevent(nesvnic);
+			}
+		} else {
+			nesdev->iw_status = 0;
+		}
+	}
+	spin_unlock_irqrestore(&nesvnic->port_ibevent_lock, flags);
+
 	napi_enable(&nesvnic->napi);
 	nesvnic->netdev_open = 1;
 
@@ -263,6 +273,7 @@ static int nes_netdev_stop(struct net_de
 	u32 nic_active;
 	struct nes_vnic *first_nesvnic = NULL;
 	struct list_head *list_pos, *list_temp;
+	unsigned long flags;
 
 	nes_debug(NES_DBG_SHUTDOWN, "nesvnic=%p, nesdev=%p, netdev=%p %s\n",
 			nesvnic, nesdev, netdev, netdev->name);
@@ -315,12 +326,17 @@ static int nes_netdev_stop(struct net_de
 	nic_active &= nic_active_mask;
 	nes_write_indexed(nesdev, NES_IDX_NIC_BROADCAST_ON, nic_active);
 
-
+	spin_lock_irqsave(&nesvnic->port_ibevent_lock, flags);
 	if (nesvnic->of_device_registered) {
 		nesdev->nesadapter->send_term_ok = 0;
 		nesdev->iw_status = 0;
-		nes_port_ibevent(nesvnic);
+		if (nesvnic->linkup == 1)
+			nes_port_ibevent(nesvnic);
 	}
+	del_timer_sync(&nesvnic->event_timer);
+	nesvnic->event_timer.function = NULL;
+	spin_unlock_irqrestore(&nesvnic->port_ibevent_lock, flags);
+
 	nes_destroy_nic_qp(nesvnic);
 
 	nesvnic->netdev_open = 0;
@@ -1750,7 +1766,10 @@ struct net_device *nes_netdev_init(struc
 		nesvnic->rdma_enabled = 0;
 	}
 	nesvnic->nic_cq.cq_number = nesvnic->nic.qp_id;
+	init_timer(&nesvnic->event_timer);
+	nesvnic->event_timer.function = NULL;
 	spin_lock_init(&nesvnic->tx_lock);
+	spin_lock_init(&nesvnic->port_ibevent_lock);
 	nesdev->netdev[nesdev->netdev_count] = netdev;
 
 	nes_debug(NES_DBG_INIT, "Adding nesvnic (%p) to the adapters nesvnic_list for MAC%d.\n",
drivers/infiniband/hw/nes/nes_verbs.c +36 -1
index 99933e4..26d8018 100644
@@ -3936,6 +3936,30 @@ struct nes_ib_device *nes_init_ofa_devic
 	return nesibdev;
 }
 
+
+/**
+ * nes_handle_delayed_event
+ */
+static void nes_handle_delayed_event(unsigned long data)
+{
+	struct nes_vnic *nesvnic = (void *) data;
+
+	if (nesvnic->delayed_event != nesvnic->last_dispatched_event) {
+		struct ib_event event;
+
+		event.device = &nesvnic->nesibdev->ibdev;
+		if (!event.device)
+			goto stop_timer;
+		event.event = nesvnic->delayed_event;
+		event.element.port_num = nesvnic->logical_port + 1;
+		ib_dispatch_event(&event);
+	}
+
+stop_timer:
+	nesvnic->event_timer.function = NULL;
+}
+
+
 void  nes_port_ibevent(struct nes_vnic *nesvnic)
 {
 	struct nes_ib_device *nesibdev = nesvnic->nesibdev;
@@ -3944,7 +3968,18 @@ void  nes_port_ibevent(struct nes_vnic *
 	event.device = &nesibdev->ibdev;
 	event.element.port_num = nesvnic->logical_port + 1;
 	event.event = nesdev->iw_status ? IB_EVENT_PORT_ACTIVE : IB_EVENT_PORT_ERR;
-	ib_dispatch_event(&event);
+
+	if (!nesvnic->event_timer.function) {
+		ib_dispatch_event(&event);
+		nesvnic->last_dispatched_event = event.event;
+		nesvnic->event_timer.function = nes_handle_delayed_event;
+		nesvnic->event_timer.data = (unsigned long) nesvnic;
+		nesvnic->event_timer.expires = jiffies + NES_EVENT_DELAY;
+		add_timer(&nesvnic->event_timer);
+	} else {
+		mod_timer(&nesvnic->event_timer, jiffies + NES_EVENT_DELAY);
+	}
+	nesvnic->delayed_event = event.event;
 }
 
 

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

#7 lore raw

PATCH 3/4 RDMA/nes: fix SFP link down detection issue with switch port disable

In reply to a message not in the archive

In case of SFP phy link status check at interrupt processing happen to give false results. For proper link status change detection delayed recheck is needed to give nes registers time to settle. Add periodic link status recheck scheduled at interrupt
to detect potential delayed registers state changes.

This patch fixes openfabrics bugzilla #2117:
http://bugs.openfabrics.org/bugzilla/show_bug.cgi?id=2117

---

 drivers/infiniband/hw/nes/nes.c    |   11 +++++
 drivers/infiniband/hw/nes/nes.h    |    4 ++
 drivers/infiniband/hw/nes/nes_hw.c |   81 ++++++++++++++++++++++++++++++++++++
 drivers/infiniband/hw/nes/nes_hw.h |    4 ++
 4 files changed, 100 insertions(+), 0 deletions(-)
drivers/infiniband/hw/nes/nes.c +11 -0
index e17f52c..3b4ec32 100644
@@ -674,6 +674,8 @@ static int __devinit nes_probe(struct pc
 	}
 	nes_notifiers_registered++;
 
+	INIT_DELAYED_WORK(&nesdev->work, nes_recheck_link_status);
+
 	/* Initialize network devices */
 	if ((netdev = nes_netdev_init(nesdev, mmio_regs)) == NULL)
 		goto bail7;
@@ -756,6 +758,7 @@ static void __devexit nes_remove(struct 
 	struct nes_device *nesdev = pci_get_drvdata(pcidev);
 	struct net_device *netdev;
 	int netdev_index = 0;
+	unsigned long flags;
 
 		if (nesdev->netdev_count) {
 			netdev = nesdev->netdev[netdev_index];
@@ -782,6 +785,14 @@ static void __devexit nes_remove(struct 
 	free_irq(pcidev->irq, nesdev);
 	tasklet_kill(&nesdev->dpc_tasklet);
 
+	spin_lock_irqsave(&nesdev->nesadapter->phy_lock, flags);
+	if (nesdev->link_recheck) {
+		spin_unlock_irqrestore(&nesdev->nesadapter->phy_lock, flags);
+		cancel_delayed_work_sync(&nesdev->work);
+	} else {
+		spin_unlock_irqrestore(&nesdev->nesadapter->phy_lock, flags);
+	}
+
 	/* Deallocate the Adapter Structure */
 	nes_destroy_adapter(nesdev->nesadapter);
 
drivers/infiniband/hw/nes/nes.h +4 -0
index b3d145e..6fe7987 100644
@@ -268,6 +268,9 @@ struct nes_device {
 	u8                     napi_isr_ran;
 	u8                     disable_rx_flow_control;
 	u8                     disable_tx_flow_control;
+
+	struct delayed_work    work;
+	u8                     link_recheck;
 };
 
 
@@ -507,6 +510,7 @@ void nes_nic_ce_handler(struct nes_devic
 void nes_iwarp_ce_handler(struct nes_device *, struct nes_hw_cq *);
 int nes_destroy_cqp(struct nes_device *);
 int nes_nic_cm_xmit(struct sk_buff *, struct net_device *);
+void nes_recheck_link_status(struct work_struct *work);
 
 /* nes_nic.c */
 struct net_device *nes_netdev_init(struct nes_device *, void __iomem *);
drivers/infiniband/hw/nes/nes_hw.c +81 -0

93 lines not on this page · raw message

drivers/infiniband/hw/nes/nes_hw.h +4 -0
index 8a9ea9a..d2abe07 100644
@@ -1354,6 +1354,10 @@ #define RDMA_READ_REQ_OPCODE	1
 #define BAD_FRAME_OFFSET	64
 #define CQE_MAJOR_DRV		0x8000
 
+/* Used for link status recheck after interrupt processing */
+#define NES_LINK_RECHECK_DELAY	msecs_to_jiffies(50)
+#define NES_LINK_RECHECK_MAX	60
+
 #define nes_vlan_rx vlan_hwaccel_receive_skb
 #define nes_netif_rx netif_receive_skb
 

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

#8 lore raw

PATCH 4/4 RDMA/nes: fix incorrect SFP link status detection on driver init

In reply to a message not in the archive

During iw_nes initialization link status for SFP phy is always detected as "up" regardless of real state (cable either connected or disconnected). Add SFP phy specific link status detection to iw_nes initialization procedure. Use link status recheck for netdev_open to detect delayed state updates.

---

 drivers/infiniband/hw/nes/nes_nic.c |   43 ++++++++++++++++++++++++++++++++---
 1 files changed, 39 insertions(+), 4 deletions(-)
drivers/infiniband/hw/nes/nes_nic.c +39 -4
index b2101bc..3c4191e 100644
@@ -241,6 +241,15 @@ static int nes_netdev_open(struct net_de
 		netif_carrier_on(netdev);
 	}
 
+	spin_lock_irqsave(&nesdev->nesadapter->phy_lock, flags);
+	if (nesdev->nesadapter->phy_type[nesdev->mac_index] == NES_PHY_TYPE_SFP_D) {
+		if (nesdev->link_recheck)
+			cancel_delayed_work(&nesdev->work);
+		nesdev->link_recheck = 1;
+		schedule_delayed_work(&nesdev->work, NES_LINK_RECHECK_DELAY);
+	}
+	spin_unlock_irqrestore(&nesdev->nesadapter->phy_lock, flags);
+
 	spin_lock_irqsave(&nesvnic->port_ibevent_lock, flags);
 	if (nesvnic->of_device_registered) {
 		nesdev->nesadapter->send_term_ok = 1;
@@ -1782,8 +1791,11 @@ struct net_device *nes_netdev_init(struc
 	      (((PCI_FUNC(nesdev->pcidev->devfn) == 1) && (nesdev->mac_index == 2)) ||
 	       ((PCI_FUNC(nesdev->pcidev->devfn) == 2) && (nesdev->mac_index == 1)))))) {
 		u32 u32temp;
-		u32 link_mask;
-		u32 link_val;
+		u32 link_mask = 0;
+		u32 link_val = 0;
+		u16 temp_phy_data;
+		u16 phy_data = 0;
+		unsigned long flags;
 
 		u32temp = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 +
 				(0x200 * (nesdev->mac_index & 1)));
@@ -1805,6 +1817,23 @@ struct net_device *nes_netdev_init(struc
 				link_val = 0x02020000;
 			}
 			break;
+		case NES_PHY_TYPE_SFP_D:
+			spin_lock_irqsave(&nesdev->nesadapter->phy_lock, flags);
+			nes_read_10G_phy_reg(nesdev,
+					     nesdev->nesadapter->phy_index[nesdev->mac_index],
+					     1, 0x9003);
+			temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
+			nes_read_10G_phy_reg(nesdev,
+					     nesdev->nesadapter->phy_index[nesdev->mac_index],
+					     3, 0x0021);
+			nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
+			nes_read_10G_phy_reg(nesdev,
+					     nesdev->nesadapter->phy_index[nesdev->mac_index],
+					     3, 0x0021);
+			phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
+			spin_unlock_irqrestore(&nesdev->nesadapter->phy_lock, flags);
+			phy_data = (!temp_phy_data && (phy_data == 0x8000)) ? 0x4 : 0x0;
+			break;
 		default:
 			link_mask = 0x0f1f0000;
 			link_val = 0x0f0f0000;
@@ -1814,8 +1843,14 @@ struct net_device *nes_netdev_init(struc
 		u32temp = nes_read_indexed(nesdev,
 					   NES_IDX_PHY_PCS_CONTROL_STATUS0 +
 					   (0x200 * (nesdev->mac_index & 1)));
-		if ((u32temp & link_mask) == link_val)
-			nesvnic->linkup = 1;
+
+		if (phy_type == NES_PHY_TYPE_SFP_D) {
+			if (phy_data & 0x0004)
+				nesvnic->linkup = 1;
+		} else {
+			if ((u32temp & link_mask) == link_val)
+				nesvnic->linkup = 1;
+		}
 
 		/* clear the MAC interrupt status, assumes direct logical to physical mapping */
 		u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (0x200 * nesdev->mac_index));

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

#4 lore raw

RE: [PATCH 2/4] RDMA/nes: send IB_EVENT_PORT_ERR/PORT_ACTIVE event on link state interrupt

In reply to a message not in the archive

Hi,

Quoted 16 lines

Depending on link state change IB_EVENT_PORT_ERR or IB_EVENT_PORT_ACTIVE should be dispatched in processing of mac interrupt.
Plug in the cable happen to result in series of interrupts changing driver's link state for a number of times before finally staying at link up (e.g. link up, link down, link up, link down, ..., link up). To prevent sending series of redundant IB_EVENT_PORT_ACTIVE
and IB_EVENT_PORT_ERR events they get filtered out by timer based nes_port_ibevent() routine.

drivers/infiniband/hw/nes/nes_hw.c +0 -0
index 1980a46..2b89b06 100644

drivers/infiniband/hw/nes/nes_hw.c static void nes_process_mac_intr(struct · line 2617

Quoted 10 lines
drivers/infiniband/hw/nes/nes_hw.c +7 -0
@@ -2608,6 +2608,13 @@ static void nes_process_mac_intr(struct
                                              netif_start_queue(nesvnic->netdev);
                                     nesvnic->linkup = 1;
                                       netif_carrier_on(nesvnic->netdev);
+
+                                       spin_lock(&nesvnic->port_ibevent_lock);
+                                       if (nesdev->iw_status == 0) {
+                                               nesdev->iw_status = 1;
+                                               nes_port_ibevent(nesvnic);
+                                       }
+                                       spin_unlock(&nesvnic->port_ibevent_lock);

Is it really "nes_port_ibevent" needed surrounded by spin_lock/unlock ?
To me it looks like setting iw_status to atomic_t and doing atomic operations are enough....

--
Viral

This Email may contain confidential or privileged information for the intended recipient (s) If you are not the intended recipient, please do not use or disseminate the information, notify the sender and delete it from your system.

______________________________________________________________________
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

#6 lore raw

RE: [PATCH 2/4] RDMA/nes: send IB_EVENT_PORT_ERR/PORT_ACTIVE event on link state interrupt

In reply to a message not in the archive
Quoted 33 lines · Viral Mehta

Hi,

Quoted 1 line

Depending on link state change IB_EVENT_PORT_ERR or

IB_EVENT_PORT_ACTIVE

Quoted 4 lines

should be dispatched in processing of mac interrupt.
Plug in the cable happen to result in series of interrupts changing driver's link state for a number of times before finally staying at link up (e.g. link up, link down, link up, link down, ...,

link up).

Review

Quoted 7 lines

To prevent sending series of redundant IB_EVENT_PORT_ACTIVE and IB_EVENT_PORT_ERR events they get filtered out by timer based nes_port_ibevent() routine.

(quoted diff) +0 -0

b/drivers/infiniband/hw/nes/nes_hw.c

drivers/infiniband/hw/nes/nes_hw.c static void nes_process_mac_intr(struct · line 2608

Quoted 5 lines

index 1980a46..2b89b06 100644

drivers/infiniband/hw/nes/nes_hw.c +0 -0
@@ -2608,6 +2608,13 @@ static void nes_process_mac_intr(struct
 

netif_start_queue(nesvnic->netdev);

drivers/infiniband/hw/nes/nes_hw.c static void nes_process_mac_intr(struct · line 2617

Quoted 9 lines
drivers/infiniband/hw/nes/nes_hw.c +5 -0
                                     nesvnic->linkup = 1;
                                       netif_carrier_on(nesvnic-
 netdev);
+
+                                       spin_lock(&nesvnic-
 port_ibevent_lock);
+                                       if (nesdev->iw_status == 0) {
+                                               nesdev->iw_status = 1;
+

nes_port_ibevent(nesvnic);

Quoted 8 lines

drivers/infiniband/hw/nes/nes_hw.c static void nes_process_mac_intr(struct · line 2620

Quoted 3 lines
drivers/infiniband/hw/nes/nes_hw.c +2 -0
+                                       }
+                                       spin_unlock(&nesvnic-
 port_ibevent_lock);

Is it really "nes_port_ibevent" needed surrounded by spin_lock/unlock ? To me it looks like setting iw_status to atomic_t and doing atomic operations are enough....

Hi Viral,

I am afraid it is not enough.
We need to keep locks around nes_port_ibevent as well to ensure that correct port state events get sent in correct order.

Regards,
Maciej

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html