aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMaciej Sosnowski <maciej.sosnowski@intel.com>2010-11-24 12:29:38 -0500
committerRoland Dreier <rolandd@cisco.com>2011-01-16 16:23:34 -0500
commitea623455b736d82f476460647e8b5fe5dc36f4f2 (patch)
treec1e2343adc9b2e8f7e11d58dc561370905d60bb8 /drivers
parent2a4c97ead4b375a64063523210939b87ad225b85 (diff)
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/infiniband/hw/nes/nes_hw.c14
-rw-r--r--drivers/infiniband/hw/nes/nes_hw.h6
-rw-r--r--drivers/infiniband/hw/nes/nes_nic.c35
-rw-r--r--drivers/infiniband/hw/nes/nes_verbs.c37
4 files changed, 83 insertions, 9 deletions
diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c
index 1980a461c499..2b89b06ca7c3 100644
--- a/drivers/infiniband/hw/nes/nes_hw.c
+++ b/drivers/infiniband/hw/nes/nes_hw.c
@@ -2608,6 +2608,13 @@ static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number)
2608 netif_start_queue(nesvnic->netdev); 2608 netif_start_queue(nesvnic->netdev);
2609 nesvnic->linkup = 1; 2609 nesvnic->linkup = 1;
2610 netif_carrier_on(nesvnic->netdev); 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 } else { 2620 } else {
@@ -2633,6 +2640,13 @@ static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number)
2633 netif_stop_queue(nesvnic->netdev); 2640 netif_stop_queue(nesvnic->netdev);
2634 nesvnic->linkup = 0; 2641 nesvnic->linkup = 0;
2635 netif_carrier_off(nesvnic->netdev); 2642 netif_carrier_off(nesvnic->netdev);
2643
2644 spin_lock(&nesvnic->port_ibevent_lock);
2645 if (nesdev->iw_status == 1) {
2646 nesdev->iw_status = 0;
2647 nes_port_ibevent(nesvnic);
2648 }
2649 spin_unlock(&nesvnic->port_ibevent_lock);
2636 } 2650 }
2637 } 2651 }
2638 } 2652 }
diff --git a/drivers/infiniband/hw/nes/nes_hw.h b/drivers/infiniband/hw/nes/nes_hw.h
index 1204c3432b63..8a9ea9a4dc5d 100644
--- a/drivers/infiniband/hw/nes/nes_hw.h
+++ b/drivers/infiniband/hw/nes/nes_hw.h
@@ -1193,6 +1193,8 @@ struct nes_listener {
1193 1193
1194struct nes_ib_device; 1194struct nes_ib_device;
1195 1195
1196#define NES_EVENT_DELAY msecs_to_jiffies(100)
1197
1196struct nes_vnic { 1198struct nes_vnic {
1197 struct nes_ib_device *nesibdev; 1199 struct nes_ib_device *nesibdev;
1198 u64 sq_full; 1200 u64 sq_full;
@@ -1247,6 +1249,10 @@ struct nes_vnic {
1247 u32 lro_max_aggr; 1249 u32 lro_max_aggr;
1248 struct net_lro_mgr lro_mgr; 1250 struct net_lro_mgr lro_mgr;
1249 struct net_lro_desc lro_desc[NES_MAX_LRO_DESCRIPTORS]; 1251 struct net_lro_desc lro_desc[NES_MAX_LRO_DESCRIPTORS];
1252 struct timer_list event_timer;
1253 enum ib_event_type delayed_event;
1254 enum ib_event_type last_dispatched_event;
1255 spinlock_t port_ibevent_lock;
1250}; 1256};
1251 1257
1252struct nes_ib_device { 1258struct nes_ib_device {
diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c
index 5a4c36484722..81052fbcd9ba 100644
--- a/drivers/infiniband/hw/nes/nes_nic.c
+++ b/drivers/infiniband/hw/nes/nes_nic.c
@@ -144,6 +144,7 @@ static int nes_netdev_open(struct net_device *netdev)
144 u32 nic_active_bit; 144 u32 nic_active_bit;
145 u32 nic_active; 145 u32 nic_active;
146 struct list_head *list_pos, *list_temp; 146 struct list_head *list_pos, *list_temp;
147 unsigned long flags;
147 148
148 assert(nesdev != NULL); 149 assert(nesdev != NULL);
149 150
@@ -233,18 +234,27 @@ static int nes_netdev_open(struct net_device *netdev)
233 first_nesvnic = nesvnic; 234 first_nesvnic = nesvnic;
234 } 235 }
235 236
236 if (nesvnic->of_device_registered) {
237 nesdev->iw_status = 1;
238 nesdev->nesadapter->send_term_ok = 1;
239 nes_port_ibevent(nesvnic);
240 }
241
242 if (first_nesvnic->linkup) { 237 if (first_nesvnic->linkup) {
243 /* Enable network packets */ 238 /* Enable network packets */
244 nesvnic->linkup = 1; 239 nesvnic->linkup = 1;
245 netif_start_queue(netdev); 240 netif_start_queue(netdev);
246 netif_carrier_on(netdev); 241 netif_carrier_on(netdev);
247 } 242 }
243
244 spin_lock_irqsave(&nesvnic->port_ibevent_lock, flags);
245 if (nesvnic->of_device_registered) {
246 nesdev->nesadapter->send_term_ok = 1;
247 if (nesvnic->linkup == 1) {
248 if (nesdev->iw_status == 0) {
249 nesdev->iw_status = 1;
250 nes_port_ibevent(nesvnic);
251 }
252 } else {
253 nesdev->iw_status = 0;
254 }
255 }
256 spin_unlock_irqrestore(&nesvnic->port_ibevent_lock, flags);
257
248 napi_enable(&nesvnic->napi); 258 napi_enable(&nesvnic->napi);
249 nesvnic->netdev_open = 1; 259 nesvnic->netdev_open = 1;
250 260
@@ -263,6 +273,7 @@ static int nes_netdev_stop(struct net_device *netdev)
263 u32 nic_active; 273 u32 nic_active;
264 struct nes_vnic *first_nesvnic = NULL; 274 struct nes_vnic *first_nesvnic = NULL;
265 struct list_head *list_pos, *list_temp; 275 struct list_head *list_pos, *list_temp;
276 unsigned long flags;
266 277
267 nes_debug(NES_DBG_SHUTDOWN, "nesvnic=%p, nesdev=%p, netdev=%p %s\n", 278 nes_debug(NES_DBG_SHUTDOWN, "nesvnic=%p, nesdev=%p, netdev=%p %s\n",
268 nesvnic, nesdev, netdev, netdev->name); 279 nesvnic, nesdev, netdev, netdev->name);
@@ -315,12 +326,17 @@ static int nes_netdev_stop(struct net_device *netdev)
315 nic_active &= nic_active_mask; 326 nic_active &= nic_active_mask;
316 nes_write_indexed(nesdev, NES_IDX_NIC_BROADCAST_ON, nic_active); 327 nes_write_indexed(nesdev, NES_IDX_NIC_BROADCAST_ON, nic_active);
317 328
318 329 spin_lock_irqsave(&nesvnic->port_ibevent_lock, flags);
319 if (nesvnic->of_device_registered) { 330 if (nesvnic->of_device_registered) {
320 nesdev->nesadapter->send_term_ok = 0; 331 nesdev->nesadapter->send_term_ok = 0;
321 nesdev->iw_status = 0; 332 nesdev->iw_status = 0;
322 nes_port_ibevent(nesvnic); 333 if (nesvnic->linkup == 1)
334 nes_port_ibevent(nesvnic);
323 } 335 }
336 del_timer_sync(&nesvnic->event_timer);
337 nesvnic->event_timer.function = NULL;
338 spin_unlock_irqrestore(&nesvnic->port_ibevent_lock, flags);
339
324 nes_destroy_nic_qp(nesvnic); 340 nes_destroy_nic_qp(nesvnic);
325 341
326 nesvnic->netdev_open = 0; 342 nesvnic->netdev_open = 0;
@@ -1750,7 +1766,10 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev,
1750 nesvnic->rdma_enabled = 0; 1766 nesvnic->rdma_enabled = 0;
1751 } 1767 }
1752 nesvnic->nic_cq.cq_number = nesvnic->nic.qp_id; 1768 nesvnic->nic_cq.cq_number = nesvnic->nic.qp_id;
1769 init_timer(&nesvnic->event_timer);
1770 nesvnic->event_timer.function = NULL;
1753 spin_lock_init(&nesvnic->tx_lock); 1771 spin_lock_init(&nesvnic->tx_lock);
1772 spin_lock_init(&nesvnic->port_ibevent_lock);
1754 nesdev->netdev[nesdev->netdev_count] = netdev; 1773 nesdev->netdev[nesdev->netdev_count] = netdev;
1755 1774
1756 nes_debug(NES_DBG_INIT, "Adding nesvnic (%p) to the adapters nesvnic_list for MAC%d.\n", 1775 nes_debug(NES_DBG_INIT, "Adding nesvnic (%p) to the adapters nesvnic_list for MAC%d.\n",
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c
index 99933e4e48ff..26d8018c0a7c 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.c
+++ b/drivers/infiniband/hw/nes/nes_verbs.c
@@ -3936,6 +3936,30 @@ struct nes_ib_device *nes_init_ofa_device(struct net_device *netdev)
3936 return nesibdev; 3936 return nesibdev;
3937} 3937}
3938 3938
3939
3940/**
3941 * nes_handle_delayed_event
3942 */
3943static 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
3958stop_timer:
3959 nesvnic->event_timer.function = NULL;
3960}
3961
3962
3939void nes_port_ibevent(struct nes_vnic *nesvnic) 3963void nes_port_ibevent(struct nes_vnic *nesvnic)
3940{ 3964{
3941 struct nes_ib_device *nesibdev = nesvnic->nesibdev; 3965 struct nes_ib_device *nesibdev = nesvnic->nesibdev;
@@ -3944,7 +3968,18 @@ void nes_port_ibevent(struct nes_vnic *nesvnic)
3944 event.device = &nesibdev->ibdev; 3968 event.device = &nesibdev->ibdev;
3945 event.element.port_num = nesvnic->logical_port + 1; 3969 event.element.port_num = nesvnic->logical_port + 1;
3946 event.event = nesdev->iw_status ? IB_EVENT_PORT_ACTIVE : IB_EVENT_PORT_ERR; 3970 event.event = nesdev->iw_status ? IB_EVENT_PORT_ACTIVE : IB_EVENT_PORT_ERR;
3947 ib_dispatch_event(&event); 3971
3972 if (!nesvnic->event_timer.function) {
3973 ib_dispatch_event(&event);
3974 nesvnic->last_dispatched_event = event.event;
3975 nesvnic->event_timer.function = nes_handle_delayed_event;
3976 nesvnic->event_timer.data = (unsigned long) nesvnic;
3977 nesvnic->event_timer.expires = jiffies + NES_EVENT_DELAY;
3978 add_timer(&nesvnic->event_timer);
3979 } else {
3980 mod_timer(&nesvnic->event_timer, jiffies + NES_EVENT_DELAY);
3981 }
3982 nesvnic->delayed_event = event.event;
3948} 3983}
3949 3984
3950 3985