RDMA/nes: Generate IB_EVENT_PORT_ERR/PORT_ACTIVE events

Depending on link state change, IB_EVENT_PORT_ERR or
IB_EVENT_PORT_ACTIVE should be generated when handling MAC interrupts.

Plugging in a cable happens to result in series of interrupts changing
driver's link state 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, we use a timer to debounce them in
nes_port_ibevent().

Signed-off-by: Maciej Sosnowski <maciej.sosnowski@intel.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>

authored by Maciej Sosnowski and committed by Roland Dreier ea623455 2a4c97ea

+83 -9
+14
drivers/infiniband/hw/nes/nes_hw.c
··· 2608 netif_start_queue(nesvnic->netdev); 2609 nesvnic->linkup = 1; 2610 netif_carrier_on(nesvnic->netdev); 2611 } 2612 } 2613 } else { ··· 2640 netif_stop_queue(nesvnic->netdev); 2641 nesvnic->linkup = 0; 2642 netif_carrier_off(nesvnic->netdev); 2643 } 2644 } 2645 }
··· 2608 netif_start_queue(nesvnic->netdev); 2609 nesvnic->linkup = 1; 2610 netif_carrier_on(nesvnic->netdev); 2611 + 2612 + spin_lock(&nesvnic->port_ibevent_lock); 2613 + if (nesdev->iw_status == 0) { 2614 + nesdev->iw_status = 1; 2615 + nes_port_ibevent(nesvnic); 2616 + } 2617 + spin_unlock(&nesvnic->port_ibevent_lock); 2618 } 2619 } 2620 } else { ··· 2633 netif_stop_queue(nesvnic->netdev); 2634 nesvnic->linkup = 0; 2635 netif_carrier_off(nesvnic->netdev); 2636 + 2637 + spin_lock(&nesvnic->port_ibevent_lock); 2638 + if (nesdev->iw_status == 1) { 2639 + nesdev->iw_status = 0; 2640 + nes_port_ibevent(nesvnic); 2641 + } 2642 + spin_unlock(&nesvnic->port_ibevent_lock); 2643 } 2644 } 2645 }
+6
drivers/infiniband/hw/nes/nes_hw.h
··· 1193 1194 struct nes_ib_device; 1195 1196 struct nes_vnic { 1197 struct nes_ib_device *nesibdev; 1198 u64 sq_full; ··· 1249 u32 lro_max_aggr; 1250 struct net_lro_mgr lro_mgr; 1251 struct net_lro_desc lro_desc[NES_MAX_LRO_DESCRIPTORS]; 1252 }; 1253 1254 struct nes_ib_device {
··· 1193 1194 struct nes_ib_device; 1195 1196 + #define NES_EVENT_DELAY msecs_to_jiffies(100) 1197 + 1198 struct nes_vnic { 1199 struct nes_ib_device *nesibdev; 1200 u64 sq_full; ··· 1247 u32 lro_max_aggr; 1248 struct net_lro_mgr lro_mgr; 1249 struct net_lro_desc lro_desc[NES_MAX_LRO_DESCRIPTORS]; 1250 + struct timer_list event_timer; 1251 + enum ib_event_type delayed_event; 1252 + enum ib_event_type last_dispatched_event; 1253 + spinlock_t port_ibevent_lock; 1254 }; 1255 1256 struct nes_ib_device {
+27 -8
drivers/infiniband/hw/nes/nes_nic.c
··· 144 u32 nic_active_bit; 145 u32 nic_active; 146 struct list_head *list_pos, *list_temp; 147 148 assert(nesdev != NULL); 149 ··· 234 first_nesvnic = nesvnic; 235 } 236 237 - if (nesvnic->of_device_registered) { 238 - nesdev->iw_status = 1; 239 - nesdev->nesadapter->send_term_ok = 1; 240 - nes_port_ibevent(nesvnic); 241 - } 242 - 243 if (first_nesvnic->linkup) { 244 /* Enable network packets */ 245 nesvnic->linkup = 1; 246 netif_start_queue(netdev); 247 netif_carrier_on(netdev); 248 } 249 napi_enable(&nesvnic->napi); 250 nesvnic->netdev_open = 1; 251 ··· 273 u32 nic_active; 274 struct nes_vnic *first_nesvnic = NULL; 275 struct list_head *list_pos, *list_temp; 276 277 nes_debug(NES_DBG_SHUTDOWN, "nesvnic=%p, nesdev=%p, netdev=%p %s\n", 278 nesvnic, nesdev, netdev, netdev->name); ··· 326 nic_active &= nic_active_mask; 327 nes_write_indexed(nesdev, NES_IDX_NIC_BROADCAST_ON, nic_active); 328 329 - 330 if (nesvnic->of_device_registered) { 331 nesdev->nesadapter->send_term_ok = 0; 332 nesdev->iw_status = 0; 333 - nes_port_ibevent(nesvnic); 334 } 335 nes_destroy_nic_qp(nesvnic); 336 337 nesvnic->netdev_open = 0; ··· 1766 nesvnic->rdma_enabled = 0; 1767 } 1768 nesvnic->nic_cq.cq_number = nesvnic->nic.qp_id; 1769 spin_lock_init(&nesvnic->tx_lock); 1770 nesdev->netdev[nesdev->netdev_count] = netdev; 1771 1772 nes_debug(NES_DBG_INIT, "Adding nesvnic (%p) to the adapters nesvnic_list for MAC%d.\n",
··· 144 u32 nic_active_bit; 145 u32 nic_active; 146 struct list_head *list_pos, *list_temp; 147 + unsigned long flags; 148 149 assert(nesdev != NULL); 150 ··· 233 first_nesvnic = nesvnic; 234 } 235 236 if (first_nesvnic->linkup) { 237 /* Enable network packets */ 238 nesvnic->linkup = 1; 239 netif_start_queue(netdev); 240 netif_carrier_on(netdev); 241 } 242 + 243 + spin_lock_irqsave(&nesvnic->port_ibevent_lock, flags); 244 + if (nesvnic->of_device_registered) { 245 + nesdev->nesadapter->send_term_ok = 1; 246 + if (nesvnic->linkup == 1) { 247 + if (nesdev->iw_status == 0) { 248 + nesdev->iw_status = 1; 249 + nes_port_ibevent(nesvnic); 250 + } 251 + } else { 252 + nesdev->iw_status = 0; 253 + } 254 + } 255 + spin_unlock_irqrestore(&nesvnic->port_ibevent_lock, flags); 256 + 257 napi_enable(&nesvnic->napi); 258 nesvnic->netdev_open = 1; 259 ··· 263 u32 nic_active; 264 struct nes_vnic *first_nesvnic = NULL; 265 struct list_head *list_pos, *list_temp; 266 + unsigned long flags; 267 268 nes_debug(NES_DBG_SHUTDOWN, "nesvnic=%p, nesdev=%p, netdev=%p %s\n", 269 nesvnic, nesdev, netdev, netdev->name); ··· 315 nic_active &= nic_active_mask; 316 nes_write_indexed(nesdev, NES_IDX_NIC_BROADCAST_ON, nic_active); 317 318 + spin_lock_irqsave(&nesvnic->port_ibevent_lock, flags); 319 if (nesvnic->of_device_registered) { 320 nesdev->nesadapter->send_term_ok = 0; 321 nesdev->iw_status = 0; 322 + if (nesvnic->linkup == 1) 323 + nes_port_ibevent(nesvnic); 324 } 325 + del_timer_sync(&nesvnic->event_timer); 326 + nesvnic->event_timer.function = NULL; 327 + spin_unlock_irqrestore(&nesvnic->port_ibevent_lock, flags); 328 + 329 nes_destroy_nic_qp(nesvnic); 330 331 nesvnic->netdev_open = 0; ··· 1750 nesvnic->rdma_enabled = 0; 1751 } 1752 nesvnic->nic_cq.cq_number = nesvnic->nic.qp_id; 1753 + init_timer(&nesvnic->event_timer); 1754 + nesvnic->event_timer.function = NULL; 1755 spin_lock_init(&nesvnic->tx_lock); 1756 + spin_lock_init(&nesvnic->port_ibevent_lock); 1757 nesdev->netdev[nesdev->netdev_count] = netdev; 1758 1759 nes_debug(NES_DBG_INIT, "Adding nesvnic (%p) to the adapters nesvnic_list for MAC%d.\n",
+36 -1
drivers/infiniband/hw/nes/nes_verbs.c
··· 3936 return nesibdev; 3937 } 3938 3939 void nes_port_ibevent(struct nes_vnic *nesvnic) 3940 { 3941 struct nes_ib_device *nesibdev = nesvnic->nesibdev; ··· 3968 event.device = &nesibdev->ibdev; 3969 event.element.port_num = nesvnic->logical_port + 1; 3970 event.event = nesdev->iw_status ? IB_EVENT_PORT_ACTIVE : IB_EVENT_PORT_ERR; 3971 - ib_dispatch_event(&event); 3972 } 3973 3974
··· 3936 return nesibdev; 3937 } 3938 3939 + 3940 + /** 3941 + * nes_handle_delayed_event 3942 + */ 3943 + static void nes_handle_delayed_event(unsigned long data) 3944 + { 3945 + struct nes_vnic *nesvnic = (void *) data; 3946 + 3947 + if (nesvnic->delayed_event != nesvnic->last_dispatched_event) { 3948 + struct ib_event event; 3949 + 3950 + event.device = &nesvnic->nesibdev->ibdev; 3951 + if (!event.device) 3952 + goto stop_timer; 3953 + event.event = nesvnic->delayed_event; 3954 + event.element.port_num = nesvnic->logical_port + 1; 3955 + ib_dispatch_event(&event); 3956 + } 3957 + 3958 + stop_timer: 3959 + nesvnic->event_timer.function = NULL; 3960 + } 3961 + 3962 + 3963 void nes_port_ibevent(struct nes_vnic *nesvnic) 3964 { 3965 struct nes_ib_device *nesibdev = nesvnic->nesibdev; ··· 3944 event.device = &nesibdev->ibdev; 3945 event.element.port_num = nesvnic->logical_port + 1; 3946 event.event = nesdev->iw_status ? IB_EVENT_PORT_ACTIVE : IB_EVENT_PORT_ERR; 3947 + 3948 + if (!nesvnic->event_timer.function) { 3949 + ib_dispatch_event(&event); 3950 + nesvnic->last_dispatched_event = event.event; 3951 + nesvnic->event_timer.function = nes_handle_delayed_event; 3952 + nesvnic->event_timer.data = (unsigned long) nesvnic; 3953 + nesvnic->event_timer.expires = jiffies + NES_EVENT_DELAY; 3954 + add_timer(&nesvnic->event_timer); 3955 + } else { 3956 + mod_timer(&nesvnic->event_timer, jiffies + NES_EVENT_DELAY); 3957 + } 3958 + nesvnic->delayed_event = event.event; 3959 } 3960 3961