aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/cxgb3
diff options
context:
space:
mode:
authorSteve Wise <swise@opengridcomputing.com>2009-09-05 23:22:38 -0400
committerRoland Dreier <rolandd@cisco.com>2009-09-05 23:22:38 -0400
commit6e47fe43502ba6dfe86d556661795d9bb0361309 (patch)
treebc29f159253320abf8d55ceac0b06dda3ddd3b7d /drivers/infiniband/hw/cxgb3
parentfa0d4c11c4b6eb49708b82b638ceb0761152f46a (diff)
RDMA/cxgb3: Don't free endpoints early
- Keep ref on connection request endpoints until either accepted or rejected so it doesn't get freed early. - Endpoint flags now need to be set via atomic bitops because they can be set on both the iw_cxgb3 workqueue thread and user disconnect threads. - Don't move out of CLOSING too early due to multiple calls to iwch_ep_disconnect. Signed-off-by: Steve Wise <swise@opengridcomputing.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/hw/cxgb3')
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_cm.c52
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_cm.h9
2 files changed, 33 insertions, 28 deletions
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c
index 52d7bb0c2a12..7f22f1797718 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_cm.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c
@@ -286,7 +286,7 @@ void __free_ep(struct kref *kref)
286 ep = container_of(container_of(kref, struct iwch_ep_common, kref), 286 ep = container_of(container_of(kref, struct iwch_ep_common, kref),
287 struct iwch_ep, com); 287 struct iwch_ep, com);
288 PDBG("%s ep %p state %s\n", __func__, ep, states[state_read(&ep->com)]); 288 PDBG("%s ep %p state %s\n", __func__, ep, states[state_read(&ep->com)]);
289 if (ep->com.flags & RELEASE_RESOURCES) { 289 if (test_bit(RELEASE_RESOURCES, &ep->com.flags)) {
290 cxgb3_remove_tid(ep->com.tdev, (void *)ep, ep->hwtid); 290 cxgb3_remove_tid(ep->com.tdev, (void *)ep, ep->hwtid);
291 dst_release(ep->dst); 291 dst_release(ep->dst);
292 l2t_release(L2DATA(ep->com.tdev), ep->l2t); 292 l2t_release(L2DATA(ep->com.tdev), ep->l2t);
@@ -297,7 +297,7 @@ void __free_ep(struct kref *kref)
297static void release_ep_resources(struct iwch_ep *ep) 297static void release_ep_resources(struct iwch_ep *ep)
298{ 298{
299 PDBG("%s ep %p tid %d\n", __func__, ep, ep->hwtid); 299 PDBG("%s ep %p tid %d\n", __func__, ep, ep->hwtid);
300 ep->com.flags |= RELEASE_RESOURCES; 300 set_bit(RELEASE_RESOURCES, &ep->com.flags);
301 put_ep(&ep->com); 301 put_ep(&ep->com);
302} 302}
303 303
@@ -786,10 +786,12 @@ static void connect_request_upcall(struct iwch_ep *ep)
786 event.private_data_len = ep->plen; 786 event.private_data_len = ep->plen;
787 event.private_data = ep->mpa_pkt + sizeof(struct mpa_message); 787 event.private_data = ep->mpa_pkt + sizeof(struct mpa_message);
788 event.provider_data = ep; 788 event.provider_data = ep;
789 if (state_read(&ep->parent_ep->com) != DEAD) 789 if (state_read(&ep->parent_ep->com) != DEAD) {
790 get_ep(&ep->com);
790 ep->parent_ep->com.cm_id->event_handler( 791 ep->parent_ep->com.cm_id->event_handler(
791 ep->parent_ep->com.cm_id, 792 ep->parent_ep->com.cm_id,
792 &event); 793 &event);
794 }
793 put_ep(&ep->parent_ep->com); 795 put_ep(&ep->parent_ep->com);
794 ep->parent_ep = NULL; 796 ep->parent_ep = NULL;
795} 797}
@@ -1156,8 +1158,7 @@ static int abort_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
1156 * We get 2 abort replies from the HW. The first one must 1158 * We get 2 abort replies from the HW. The first one must
1157 * be ignored except for scribbling that we need one more. 1159 * be ignored except for scribbling that we need one more.
1158 */ 1160 */
1159 if (!(ep->com.flags & ABORT_REQ_IN_PROGRESS)) { 1161 if (!test_and_set_bit(ABORT_REQ_IN_PROGRESS, &ep->com.flags)) {
1160 ep->com.flags |= ABORT_REQ_IN_PROGRESS;
1161 return CPL_RET_BUF_DONE; 1162 return CPL_RET_BUF_DONE;
1162 } 1163 }
1163 1164
@@ -1480,7 +1481,6 @@ static int peer_close(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
1480 * rejects the CR. 1481 * rejects the CR.
1481 */ 1482 */
1482 __state_set(&ep->com, CLOSING); 1483 __state_set(&ep->com, CLOSING);
1483 get_ep(&ep->com);
1484 break; 1484 break;
1485 case MPA_REP_SENT: 1485 case MPA_REP_SENT:
1486 __state_set(&ep->com, CLOSING); 1486 __state_set(&ep->com, CLOSING);
@@ -1561,8 +1561,7 @@ static int peer_abort(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
1561 * We get 2 peer aborts from the HW. The first one must 1561 * We get 2 peer aborts from the HW. The first one must
1562 * be ignored except for scribbling that we need one more. 1562 * be ignored except for scribbling that we need one more.
1563 */ 1563 */
1564 if (!(ep->com.flags & PEER_ABORT_IN_PROGRESS)) { 1564 if (!test_and_set_bit(PEER_ABORT_IN_PROGRESS, &ep->com.flags)) {
1565 ep->com.flags |= PEER_ABORT_IN_PROGRESS;
1566 return CPL_RET_BUF_DONE; 1565 return CPL_RET_BUF_DONE;
1567 } 1566 }
1568 1567
@@ -1591,7 +1590,6 @@ static int peer_abort(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
1591 * the reference on it until the ULP accepts or 1590 * the reference on it until the ULP accepts or
1592 * rejects the CR. 1591 * rejects the CR.
1593 */ 1592 */
1594 get_ep(&ep->com);
1595 break; 1593 break;
1596 case MORIBUND: 1594 case MORIBUND:
1597 case CLOSING: 1595 case CLOSING:
@@ -1797,6 +1795,7 @@ int iwch_reject_cr(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len)
1797 err = send_mpa_reject(ep, pdata, pdata_len); 1795 err = send_mpa_reject(ep, pdata, pdata_len);
1798 err = iwch_ep_disconnect(ep, 0, GFP_KERNEL); 1796 err = iwch_ep_disconnect(ep, 0, GFP_KERNEL);
1799 } 1797 }
1798 put_ep(&ep->com);
1800 return 0; 1799 return 0;
1801} 1800}
1802 1801
@@ -1810,8 +1809,10 @@ int iwch_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
1810 struct iwch_qp *qp = get_qhp(h, conn_param->qpn); 1809 struct iwch_qp *qp = get_qhp(h, conn_param->qpn);
1811 1810
1812 PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 1811 PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
1813 if (state_read(&ep->com) == DEAD) 1812 if (state_read(&ep->com) == DEAD) {
1814 return -ECONNRESET; 1813 err = -ECONNRESET;
1814 goto err;
1815 }
1815 1816
1816 BUG_ON(state_read(&ep->com) != MPA_REQ_RCVD); 1817 BUG_ON(state_read(&ep->com) != MPA_REQ_RCVD);
1817 BUG_ON(!qp); 1818 BUG_ON(!qp);
@@ -1819,7 +1820,8 @@ int iwch_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
1819 if ((conn_param->ord > qp->rhp->attr.max_rdma_read_qp_depth) || 1820 if ((conn_param->ord > qp->rhp->attr.max_rdma_read_qp_depth) ||
1820 (conn_param->ird > qp->rhp->attr.max_rdma_reads_per_qp)) { 1821 (conn_param->ird > qp->rhp->attr.max_rdma_reads_per_qp)) {
1821 abort_connection(ep, NULL, GFP_KERNEL); 1822 abort_connection(ep, NULL, GFP_KERNEL);
1822 return -EINVAL; 1823 err = -EINVAL;
1824 goto err;
1823 } 1825 }
1824 1826
1825 cm_id->add_ref(cm_id); 1827 cm_id->add_ref(cm_id);
@@ -1836,8 +1838,6 @@ int iwch_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
1836 1838
1837 PDBG("%s %d ird %d ord %d\n", __func__, __LINE__, ep->ird, ep->ord); 1839 PDBG("%s %d ird %d ord %d\n", __func__, __LINE__, ep->ird, ep->ord);
1838 1840
1839 get_ep(&ep->com);
1840
1841 /* bind QP to EP and move to RTS */ 1841 /* bind QP to EP and move to RTS */
1842 attrs.mpa_attr = ep->mpa_attr; 1842 attrs.mpa_attr = ep->mpa_attr;
1843 attrs.max_ird = ep->ird; 1843 attrs.max_ird = ep->ird;
@@ -1855,30 +1855,31 @@ int iwch_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
1855 err = iwch_modify_qp(ep->com.qp->rhp, 1855 err = iwch_modify_qp(ep->com.qp->rhp,
1856 ep->com.qp, mask, &attrs, 1); 1856 ep->com.qp, mask, &attrs, 1);
1857 if (err) 1857 if (err)
1858 goto err; 1858 goto err1;
1859 1859
1860 /* if needed, wait for wr_ack */ 1860 /* if needed, wait for wr_ack */
1861 if (iwch_rqes_posted(qp)) { 1861 if (iwch_rqes_posted(qp)) {
1862 wait_event(ep->com.waitq, ep->com.rpl_done); 1862 wait_event(ep->com.waitq, ep->com.rpl_done);
1863 err = ep->com.rpl_err; 1863 err = ep->com.rpl_err;
1864 if (err) 1864 if (err)
1865 goto err; 1865 goto err1;
1866 } 1866 }
1867 1867
1868 err = send_mpa_reply(ep, conn_param->private_data, 1868 err = send_mpa_reply(ep, conn_param->private_data,
1869 conn_param->private_data_len); 1869 conn_param->private_data_len);
1870 if (err) 1870 if (err)
1871 goto err; 1871 goto err1;
1872 1872
1873 1873
1874 state_set(&ep->com, FPDU_MODE); 1874 state_set(&ep->com, FPDU_MODE);
1875 established_upcall(ep); 1875 established_upcall(ep);
1876 put_ep(&ep->com); 1876 put_ep(&ep->com);
1877 return 0; 1877 return 0;
1878err: 1878err1:
1879 ep->com.cm_id = NULL; 1879 ep->com.cm_id = NULL;
1880 ep->com.qp = NULL; 1880 ep->com.qp = NULL;
1881 cm_id->rem_ref(cm_id); 1881 cm_id->rem_ref(cm_id);
1882err:
1882 put_ep(&ep->com); 1883 put_ep(&ep->com);
1883 return err; 1884 return err;
1884} 1885}
@@ -2097,14 +2098,17 @@ int iwch_ep_disconnect(struct iwch_ep *ep, int abrupt, gfp_t gfp)
2097 ep->com.state = CLOSING; 2098 ep->com.state = CLOSING;
2098 start_ep_timer(ep); 2099 start_ep_timer(ep);
2099 } 2100 }
2101 set_bit(CLOSE_SENT, &ep->com.flags);
2100 break; 2102 break;
2101 case CLOSING: 2103 case CLOSING:
2102 close = 1; 2104 if (!test_and_set_bit(CLOSE_SENT, &ep->com.flags)) {
2103 if (abrupt) { 2105 close = 1;
2104 stop_ep_timer(ep); 2106 if (abrupt) {
2105 ep->com.state = ABORTING; 2107 stop_ep_timer(ep);
2106 } else 2108 ep->com.state = ABORTING;
2107 ep->com.state = MORIBUND; 2109 } else
2110 ep->com.state = MORIBUND;
2111 }
2108 break; 2112 break;
2109 case MORIBUND: 2113 case MORIBUND:
2110 case ABORTING: 2114 case ABORTING:
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.h b/drivers/infiniband/hw/cxgb3/iwch_cm.h
index 43c0aea7eadc..b9efadfffb4f 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_cm.h
+++ b/drivers/infiniband/hw/cxgb3/iwch_cm.h
@@ -145,9 +145,10 @@ enum iwch_ep_state {
145}; 145};
146 146
147enum iwch_ep_flags { 147enum iwch_ep_flags {
148 PEER_ABORT_IN_PROGRESS = (1 << 0), 148 PEER_ABORT_IN_PROGRESS = 0,
149 ABORT_REQ_IN_PROGRESS = (1 << 1), 149 ABORT_REQ_IN_PROGRESS = 1,
150 RELEASE_RESOURCES = (1 << 2), 150 RELEASE_RESOURCES = 2,
151 CLOSE_SENT = 3,
151}; 152};
152 153
153struct iwch_ep_common { 154struct iwch_ep_common {
@@ -162,7 +163,7 @@ struct iwch_ep_common {
162 wait_queue_head_t waitq; 163 wait_queue_head_t waitq;
163 int rpl_done; 164 int rpl_done;
164 int rpl_err; 165 int rpl_err;
165 u32 flags; 166 unsigned long flags;
166}; 167};
167 168
168struct iwch_listen_ep { 169struct iwch_listen_ep {