aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorFaisal Latif <faisal.latif@intel.com>2008-11-21 21:50:46 -0500
committerRoland Dreier <rolandd@cisco.com>2008-12-05 14:00:08 -0500
commit183ecfa3091cd4cdda329a7fe89d9544088f517d (patch)
tree5cccb1b5b0fdfe7ec1dbaddbe0de04ce087f99a8 /drivers/infiniband
parent879e5bd5a1a0a317fb67fa4dc550db092a7bdcb0 (diff)
RDMA/nes: Avoid race between MPA request and reset event to rdma_cm
In passive open, after indicating MPA request to rdma_cm, an incoming RST would fire a reset event to rdma_cm causing it to crash, since the current state is not connected. The solution is to wait for nes_accept() or nes_reject() before firing the reset event. If nes_accept() or nes_reject() is already done, then the reset event will be fired when RST is processed. Signed-off-by: Faisal Latif <faisal.latif@intel.com> Signed-off-by: Chien Tung <chien.tin.tung@intel.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/hw/nes/nes_cm.c50
-rw-r--r--drivers/infiniband/hw/nes/nes_cm.h5
2 files changed, 49 insertions, 6 deletions
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
index 257d994ec7b5..c259ddc8dd88 100644
--- a/drivers/infiniband/hw/nes/nes_cm.c
+++ b/drivers/infiniband/hw/nes/nes_cm.c
@@ -1360,6 +1360,7 @@ static void handle_rst_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
1360{ 1360{
1361 1361
1362 int reset = 0; /* whether to send reset in case of err.. */ 1362 int reset = 0; /* whether to send reset in case of err.. */
1363 int passive_state;
1363 atomic_inc(&cm_resets_recvd); 1364 atomic_inc(&cm_resets_recvd);
1364 nes_debug(NES_DBG_CM, "Received Reset, cm_node = %p, state = %u." 1365 nes_debug(NES_DBG_CM, "Received Reset, cm_node = %p, state = %u."
1365 " refcnt=%d\n", cm_node, cm_node->state, 1366 " refcnt=%d\n", cm_node, cm_node->state,
@@ -1373,7 +1374,14 @@ static void handle_rst_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
1373 cm_node->listener, cm_node->state); 1374 cm_node->listener, cm_node->state);
1374 active_open_err(cm_node, skb, reset); 1375 active_open_err(cm_node, skb, reset);
1375 break; 1376 break;
1376 /* For PASSIVE open states, remove the cm_node event */ 1377 case NES_CM_STATE_MPAREQ_RCVD:
1378 passive_state = atomic_add_return(1, &cm_node->passive_state);
1379 if (passive_state == NES_SEND_RESET_EVENT)
1380 create_event(cm_node, NES_CM_EVENT_RESET);
1381 cleanup_retrans_entry(cm_node);
1382 cm_node->state = NES_CM_STATE_CLOSED;
1383 dev_kfree_skb_any(skb);
1384 break;
1377 case NES_CM_STATE_ESTABLISHED: 1385 case NES_CM_STATE_ESTABLISHED:
1378 case NES_CM_STATE_SYN_RCVD: 1386 case NES_CM_STATE_SYN_RCVD:
1379 case NES_CM_STATE_LISTENING: 1387 case NES_CM_STATE_LISTENING:
@@ -1381,7 +1389,14 @@ static void handle_rst_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
1381 passive_open_err(cm_node, skb, reset); 1389 passive_open_err(cm_node, skb, reset);
1382 break; 1390 break;
1383 case NES_CM_STATE_TSA: 1391 case NES_CM_STATE_TSA:
1392 active_open_err(cm_node, skb, reset);
1393 break;
1394 case NES_CM_STATE_CLOSED:
1395 cleanup_retrans_entry(cm_node);
1396 drop_packet(skb);
1397 break;
1384 default: 1398 default:
1399 drop_packet(skb);
1385 break; 1400 break;
1386 } 1401 }
1387} 1402}
@@ -1410,6 +1425,9 @@ static void handle_rcv_mpa(struct nes_cm_node *cm_node, struct sk_buff *skb,
1410 dev_kfree_skb_any(skb); 1425 dev_kfree_skb_any(skb);
1411 if (type == NES_CM_EVENT_CONNECTED) 1426 if (type == NES_CM_EVENT_CONNECTED)
1412 cm_node->state = NES_CM_STATE_TSA; 1427 cm_node->state = NES_CM_STATE_TSA;
1428 else
1429 atomic_set(&cm_node->passive_state,
1430 NES_PASSIVE_STATE_INDICATED);
1413 create_event(cm_node, type); 1431 create_event(cm_node, type);
1414 1432
1415 } 1433 }
@@ -1986,6 +2004,7 @@ static int mini_cm_reject(struct nes_cm_core *cm_core,
1986 struct ietf_mpa_frame *mpa_frame, struct nes_cm_node *cm_node) 2004 struct ietf_mpa_frame *mpa_frame, struct nes_cm_node *cm_node)
1987{ 2005{
1988 int ret = 0; 2006 int ret = 0;
2007 int passive_state;
1989 2008
1990 nes_debug(NES_DBG_CM, "%s cm_node=%p type=%d state=%d\n", 2009 nes_debug(NES_DBG_CM, "%s cm_node=%p type=%d state=%d\n",
1991 __func__, cm_node, cm_node->tcp_cntxt.client, cm_node->state); 2010 __func__, cm_node, cm_node->tcp_cntxt.client, cm_node->state);
@@ -1993,9 +2012,13 @@ static int mini_cm_reject(struct nes_cm_core *cm_core,
1993 if (cm_node->tcp_cntxt.client) 2012 if (cm_node->tcp_cntxt.client)
1994 return ret; 2013 return ret;
1995 cleanup_retrans_entry(cm_node); 2014 cleanup_retrans_entry(cm_node);
1996 cm_node->state = NES_CM_STATE_CLOSED;
1997 2015
1998 ret = send_reset(cm_node, NULL); 2016 passive_state = atomic_add_return(1, &cm_node->passive_state);
2017 cm_node->state = NES_CM_STATE_CLOSED;
2018 if (passive_state == NES_SEND_RESET_EVENT)
2019 rem_ref_cm_node(cm_core, cm_node);
2020 else
2021 ret = send_reset(cm_node, NULL);
1999 return ret; 2022 return ret;
2000} 2023}
2001 2024
@@ -2413,7 +2436,6 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)
2413 atomic_inc(&cm_disconnects); 2436 atomic_inc(&cm_disconnects);
2414 cm_event.event = IW_CM_EVENT_DISCONNECT; 2437 cm_event.event = IW_CM_EVENT_DISCONNECT;
2415 if (last_ae == NES_AEQE_AEID_LLP_CONNECTION_RESET) { 2438 if (last_ae == NES_AEQE_AEID_LLP_CONNECTION_RESET) {
2416 issued_disconnect_reset = 1;
2417 cm_event.status = IW_CM_EVENT_STATUS_RESET; 2439 cm_event.status = IW_CM_EVENT_STATUS_RESET;
2418 nes_debug(NES_DBG_CM, "Generating a CM " 2440 nes_debug(NES_DBG_CM, "Generating a CM "
2419 "Disconnect Event (status reset) for " 2441 "Disconnect Event (status reset) for "
@@ -2563,6 +2585,7 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
2563 struct nes_v4_quad nes_quad; 2585 struct nes_v4_quad nes_quad;
2564 u32 crc_value; 2586 u32 crc_value;
2565 int ret; 2587 int ret;
2588 int passive_state;
2566 2589
2567 ibqp = nes_get_qp(cm_id->device, conn_param->qpn); 2590 ibqp = nes_get_qp(cm_id->device, conn_param->qpn);
2568 if (!ibqp) 2591 if (!ibqp)
@@ -2730,8 +2753,6 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
2730 conn_param->private_data_len + 2753 conn_param->private_data_len +
2731 sizeof(struct ietf_mpa_frame)); 2754 sizeof(struct ietf_mpa_frame));
2732 2755
2733 attr.qp_state = IB_QPS_RTS;
2734 nes_modify_qp(&nesqp->ibqp, &attr, IB_QP_STATE, NULL);
2735 2756
2736 /* notify OF layer that accept event was successfull */ 2757 /* notify OF layer that accept event was successfull */
2737 cm_id->add_ref(cm_id); 2758 cm_id->add_ref(cm_id);
@@ -2744,6 +2765,8 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
2744 cm_event.private_data = NULL; 2765 cm_event.private_data = NULL;
2745 cm_event.private_data_len = 0; 2766 cm_event.private_data_len = 0;
2746 ret = cm_id->event_handler(cm_id, &cm_event); 2767 ret = cm_id->event_handler(cm_id, &cm_event);
2768 attr.qp_state = IB_QPS_RTS;
2769 nes_modify_qp(&nesqp->ibqp, &attr, IB_QP_STATE, NULL);
2747 if (cm_node->loopbackpartner) { 2770 if (cm_node->loopbackpartner) {
2748 cm_node->loopbackpartner->mpa_frame_size = 2771 cm_node->loopbackpartner->mpa_frame_size =
2749 nesqp->private_data_len; 2772 nesqp->private_data_len;
@@ -2756,6 +2779,9 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
2756 printk(KERN_ERR "%s[%u] OFA CM event_handler returned, " 2779 printk(KERN_ERR "%s[%u] OFA CM event_handler returned, "
2757 "ret=%d\n", __func__, __LINE__, ret); 2780 "ret=%d\n", __func__, __LINE__, ret);
2758 2781
2782 passive_state = atomic_add_return(1, &cm_node->passive_state);
2783 if (passive_state == NES_SEND_RESET_EVENT)
2784 create_event(cm_node, NES_CM_EVENT_RESET);
2759 return 0; 2785 return 0;
2760} 2786}
2761 2787
@@ -3238,6 +3264,18 @@ static void cm_event_reset(struct nes_cm_event *event)
3238 cm_event.private_data_len = 0; 3264 cm_event.private_data_len = 0;
3239 3265
3240 ret = cm_id->event_handler(cm_id, &cm_event); 3266 ret = cm_id->event_handler(cm_id, &cm_event);
3267 cm_id->add_ref(cm_id);
3268 atomic_inc(&cm_closes);
3269 cm_event.event = IW_CM_EVENT_CLOSE;
3270 cm_event.status = IW_CM_EVENT_STATUS_OK;
3271 cm_event.provider_data = cm_id->provider_data;
3272 cm_event.local_addr = cm_id->local_addr;
3273 cm_event.remote_addr = cm_id->remote_addr;
3274 cm_event.private_data = NULL;
3275 cm_event.private_data_len = 0;
3276 nes_debug(NES_DBG_CM, "NODE %p Generating CLOSE\n", event->cm_node);
3277 ret = cm_id->event_handler(cm_id, &cm_event);
3278
3241 nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret); 3279 nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret);
3242 3280
3243 3281
diff --git a/drivers/infiniband/hw/nes/nes_cm.h b/drivers/infiniband/hw/nes/nes_cm.h
index 282a9cbe508f..25e2493abc6a 100644
--- a/drivers/infiniband/hw/nes/nes_cm.h
+++ b/drivers/infiniband/hw/nes/nes_cm.h
@@ -76,6 +76,10 @@ enum nes_timer_type {
76 NES_TIMER_TYPE_CLOSE, 76 NES_TIMER_TYPE_CLOSE,
77}; 77};
78 78
79#define NES_PASSIVE_STATE_INDICATED 0
80#define NES_DO_NOT_SEND_RESET_EVENT 1
81#define NES_SEND_RESET_EVENT 2
82
79#define MAX_NES_IFS 4 83#define MAX_NES_IFS 4
80 84
81#define SET_ACK 1 85#define SET_ACK 1
@@ -295,6 +299,7 @@ struct nes_cm_node {
295 struct list_head timer_entry; 299 struct list_head timer_entry;
296 struct list_head reset_entry; 300 struct list_head reset_entry;
297 struct nes_qp *nesqp; 301 struct nes_qp *nesqp;
302 atomic_t passive_state;
298}; 303};
299 304
300/* structure for client or CM to fill when making CM api calls. */ 305/* structure for client or CM to fill when making CM api calls. */