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 2608 netif_start_queue(nesvnic->netdev); 2609 2609 nesvnic->linkup = 1; 2610 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); 2611 2618 } 2612 2619 } 2613 2620 } else { ··· 2640 2633 netif_stop_queue(nesvnic->netdev); 2641 2634 nesvnic->linkup = 0; 2642 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 2643 } 2644 2644 } 2645 2645 }
+6
drivers/infiniband/hw/nes/nes_hw.h
··· 1193 1193 1194 1194 struct nes_ib_device; 1195 1195 1196 + #define NES_EVENT_DELAY msecs_to_jiffies(100) 1197 + 1196 1198 struct nes_vnic { 1197 1199 struct nes_ib_device *nesibdev; 1198 1200 u64 sq_full; ··· 1249 1247 u32 lro_max_aggr; 1250 1248 struct net_lro_mgr lro_mgr; 1251 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; 1252 1254 }; 1253 1255 1254 1256 struct nes_ib_device {
+27 -8
drivers/infiniband/hw/nes/nes_nic.c
··· 144 144 u32 nic_active_bit; 145 145 u32 nic_active; 146 146 struct list_head *list_pos, *list_temp; 147 + unsigned long flags; 147 148 148 149 assert(nesdev != NULL); 149 150 ··· 234 233 first_nesvnic = nesvnic; 235 234 } 236 235 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 236 if (first_nesvnic->linkup) { 244 237 /* Enable network packets */ 245 238 nesvnic->linkup = 1; 246 239 netif_start_queue(netdev); 247 240 netif_carrier_on(netdev); 248 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 + 249 257 napi_enable(&nesvnic->napi); 250 258 nesvnic->netdev_open = 1; 251 259 ··· 273 263 u32 nic_active; 274 264 struct nes_vnic *first_nesvnic = NULL; 275 265 struct list_head *list_pos, *list_temp; 266 + unsigned long flags; 276 267 277 268 nes_debug(NES_DBG_SHUTDOWN, "nesvnic=%p, nesdev=%p, netdev=%p %s\n", 278 269 nesvnic, nesdev, netdev, netdev->name); ··· 326 315 nic_active &= nic_active_mask; 327 316 nes_write_indexed(nesdev, NES_IDX_NIC_BROADCAST_ON, nic_active); 328 317 329 - 318 + spin_lock_irqsave(&nesvnic->port_ibevent_lock, flags); 330 319 if (nesvnic->of_device_registered) { 331 320 nesdev->nesadapter->send_term_ok = 0; 332 321 nesdev->iw_status = 0; 333 - nes_port_ibevent(nesvnic); 322 + if (nesvnic->linkup == 1) 323 + nes_port_ibevent(nesvnic); 334 324 } 325 + del_timer_sync(&nesvnic->event_timer); 326 + nesvnic->event_timer.function = NULL; 327 + spin_unlock_irqrestore(&nesvnic->port_ibevent_lock, flags); 328 + 335 329 nes_destroy_nic_qp(nesvnic); 336 330 337 331 nesvnic->netdev_open = 0; ··· 1766 1750 nesvnic->rdma_enabled = 0; 1767 1751 } 1768 1752 nesvnic->nic_cq.cq_number = nesvnic->nic.qp_id; 1753 + init_timer(&nesvnic->event_timer); 1754 + nesvnic->event_timer.function = NULL; 1769 1755 spin_lock_init(&nesvnic->tx_lock); 1756 + spin_lock_init(&nesvnic->port_ibevent_lock); 1770 1757 nesdev->netdev[nesdev->netdev_count] = netdev; 1771 1758 1772 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 3936 return nesibdev; 3937 3937 } 3938 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 + 3939 3963 void nes_port_ibevent(struct nes_vnic *nesvnic) 3940 3964 { 3941 3965 struct nes_ib_device *nesibdev = nesvnic->nesibdev; ··· 3968 3944 event.device = &nesibdev->ibdev; 3969 3945 event.element.port_num = nesvnic->logical_port + 1; 3970 3946 event.event = nesdev->iw_status ? IB_EVENT_PORT_ACTIVE : IB_EVENT_PORT_ERR; 3971 - ib_dispatch_event(&event); 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; 3972 3959 } 3973 3960 3974 3961