RDMA/nes: enable bonds on iw_nes
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
@@ -144,6 +144,7 @@ static int nes_inetaddr_event(struct notstruct 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 notnes_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 notnes_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
@@ -1107,6 +1107,7 @@ static int nes_addr_resolve_neigh(structstruct 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(structreturn 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
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 archiveDepending 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
@@ -2608,6 +2608,13 @@ static void nes_process_mac_intr(structnetif_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(structnetif_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
@@ -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
@@ -144,6 +144,7 @@ static int nes_netdev_open(struct net_deu32 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_deu32 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
@@ -3936,6 +3936,30 @@ struct nes_ib_device *nes_init_ofa_devicreturn 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
PATCH 3/4 RDMA/nes: fix SFP link down detection issue with switch port disable
In reply to a message not in the archiveIn 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
@@ -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(structstruct 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(structfree_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
@@ -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_devicvoid 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
@@ -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
PATCH 4/4 RDMA/nes: fix incorrect SFP link status detection on driver init
In reply to a message not in the archiveDuring 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
@@ -241,6 +241,15 @@ static int nes_netdev_open(struct net_denetif_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
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 archiveHi,
Quoted 16 lines
Depending on link state change
IB_EVENT_PORT_ERRorIB_EVENT_PORT_ACTIVEshould 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 redundantIB_EVENT_PORT_ACTIVE
andIB_EVENT_PORT_ERRevents they get filtered out by timer basednes_port_ibevent()routine.Signed-off-by Maciej Sosnowski [email protected]drivers/infiniband/hw/nes/nes_hw.c +0
-0
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(structnetif_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
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 archiveQuoted 33 lines · Viral Mehta
Hi,
Quoted 1 line
Depending on link state change
IB_EVENT_PORT_ERRor
IB_EVENT_PORT_ACTIVEQuoted 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_ACTIVEandIB_EVENT_PORT_ERRevents they get filtered out by timer basednes_port_ibevent()routine.Signed-off-by Maciej Sosnowski [email protected](quoted diff) +0
-0
b/drivers/infiniband/hw/nes/nes_hw.cdrivers/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
-0nesvnic->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 settingiw_statustoatomic_tand 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