git://ftp.safe.ca
/
safe
/
jmp
/
linux-2.6
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[safe/jmp/linux-2.6]
/
drivers
/
infiniband
/
core
/
iwcm.c
diff --git
a/drivers/infiniband/core/iwcm.c
b/drivers/infiniband/core/iwcm.c
index
0cfd784
..
bfead5b
100644
(file)
--- a/
drivers/infiniband/core/iwcm.c
+++ b/
drivers/infiniband/core/iwcm.c
@@
-39,11
+39,12
@@
#include <linux/err.h>
#include <linux/idr.h>
#include <linux/interrupt.h>
#include <linux/err.h>
#include <linux/idr.h>
#include <linux/interrupt.h>
-#include <linux/pci.h>
#include <linux/rbtree.h>
#include <linux/rbtree.h>
+#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>
#include <linux/completion.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>
#include <linux/completion.h>
+#include <linux/slab.h>
#include <rdma/iw_cm.h>
#include <rdma/ib_addr.h>
#include <rdma/iw_cm.h>
#include <rdma/ib_addr.h>
@@
-80,7
+81,7
@@
struct iwcm_work {
* 1) in the event upcall, cm_event_handler(), for a listening cm_id. If
* the backlog is exceeded, then no more connection request events will
* be processed. cm_event_handler() returns -ENOMEM in this case. Its up
* 1) in the event upcall, cm_event_handler(), for a listening cm_id. If
* the backlog is exceeded, then no more connection request events will
* be processed. cm_event_handler() returns -ENOMEM in this case. Its up
- * to the provider to reject the connecti
no
request.
+ * to the provider to reject the connecti
on
request.
* 2) in the connection request workqueue handler, cm_conn_req_handler().
* If work elements cannot be allocated for the new connect request cm_id,
* then IWCM will call the provider reject method. This is ok since
* 2) in the connection request workqueue handler, cm_conn_req_handler().
* If work elements cannot be allocated for the new connect request cm_id,
* then IWCM will call the provider reject method. This is ok since
@@
-131,12
+132,11
@@
static int alloc_work_entries(struct iwcm_id_private *cm_id_priv, int count)
}
/*
}
/*
- * Save private data from incoming connection requests
in the
- *
cm_id_priv so the low level driver doesn't have to.
Adjust
+ * Save private data from incoming connection requests
to
+ *
iw_cm_event, so the low level driver doesn't have to.
Adjust
* the event ptr to point to the local copy.
*/
* the event ptr to point to the local copy.
*/
-static int copy_private_data(struct iwcm_id_private *cm_id_priv,
- struct iw_cm_event *event)
+static int copy_private_data(struct iw_cm_event *event)
{
void *p;
{
void *p;
@@
-147,27
+147,27
@@
static int copy_private_data(struct iwcm_id_private *cm_id_priv,
return 0;
}
return 0;
}
+static void free_cm_id(struct iwcm_id_private *cm_id_priv)
+{
+ dealloc_work_entries(cm_id_priv);
+ kfree(cm_id_priv);
+}
+
/*
/*
- * Release a reference on cm_id. If the last reference is being removed
- * and iw_destroy_cm_id is waiting, wake up the waiting thread.
+ * Release a reference on cm_id. If the last reference is being
+ * released, enable the waiting thread (in iw_destroy_cm_id) to
+ * get woken up, and return 1 if a thread is already waiting.
*/
static int iwcm_deref_id(struct iwcm_id_private *cm_id_priv)
{
*/
static int iwcm_deref_id(struct iwcm_id_private *cm_id_priv)
{
- int ret = 0;
-
BUG_ON(atomic_read(&cm_id_priv->refcount)==0);
if (atomic_dec_and_test(&cm_id_priv->refcount)) {
BUG_ON(!list_empty(&cm_id_priv->work_list));
BUG_ON(atomic_read(&cm_id_priv->refcount)==0);
if (atomic_dec_and_test(&cm_id_priv->refcount)) {
BUG_ON(!list_empty(&cm_id_priv->work_list));
- if (waitqueue_active(&cm_id_priv->destroy_comp.wait)) {
- BUG_ON(cm_id_priv->state != IW_CM_STATE_DESTROYING);
- BUG_ON(test_bit(IWCM_F_CALLBACK_DESTROY,
- &cm_id_priv->flags));
- ret = 1;
- }
complete(&cm_id_priv->destroy_comp);
complete(&cm_id_priv->destroy_comp);
+ return 1;
}
}
- return
ret
;
+ return
0
;
}
static void add_ref(struct iw_cm_id *cm_id)
}
static void add_ref(struct iw_cm_id *cm_id)
@@
-181,7
+181,11
@@
static void rem_ref(struct iw_cm_id *cm_id)
{
struct iwcm_id_private *cm_id_priv;
cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
{
struct iwcm_id_private *cm_id_priv;
cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
- iwcm_deref_id(cm_id_priv);
+ if (iwcm_deref_id(cm_id_priv) &&
+ test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags)) {
+ BUG_ON(!list_empty(&cm_id_priv->work_list));
+ free_cm_id(cm_id_priv);
+ }
}
static int cm_event_handler(struct iw_cm_id *cm_id, struct iw_cm_event *event);
}
static int cm_event_handler(struct iw_cm_id *cm_id, struct iw_cm_event *event);
@@
-242,7
+246,7
@@
static int iwcm_modify_qp_sqd(struct ib_qp *qp)
/*
* CM_ID <-- CLOSING
*
/*
* CM_ID <-- CLOSING
*
- * Block if a passive or active connection is curren
lt
y being processed. Then
+ * Block if a passive or active connection is curren
tl
y being processed. Then
* process the event as follows:
* - If we are ESTABLISHED, move to CLOSING and modify the QP state
* based on the abrupt flag
* process the event as follows:
* - If we are ESTABLISHED, move to CLOSING and modify the QP state
* based on the abrupt flag
@@
-355,9
+359,14
@@
static void destroy_cm_id(struct iw_cm_id *cm_id)
case IW_CM_STATE_CONN_RECV:
/*
* App called destroy before/without calling accept after
case IW_CM_STATE_CONN_RECV:
/*
* App called destroy before/without calling accept after
- * receiving connection request event notification.
+ * receiving connection request event notification or
+ * returned non zero from the event callback function.
+ * In either case, must tell the provider to reject.
*/
cm_id_priv->state = IW_CM_STATE_DESTROYING;
*/
cm_id_priv->state = IW_CM_STATE_DESTROYING;
+ spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ cm_id->device->iwcm->reject(cm_id, NULL, 0);
+ spin_lock_irqsave(&cm_id_priv->lock, flags);
break;
case IW_CM_STATE_CONN_SENT:
case IW_CM_STATE_DESTROYING:
break;
case IW_CM_STATE_CONN_SENT:
case IW_CM_STATE_DESTROYING:
@@
-391,9
+400,7
@@
void iw_destroy_cm_id(struct iw_cm_id *cm_id)
wait_for_completion(&cm_id_priv->destroy_comp);
wait_for_completion(&cm_id_priv->destroy_comp);
- dealloc_work_entries(cm_id_priv);
-
- kfree(cm_id_priv);
+ free_cm_id(cm_id_priv);
}
EXPORT_SYMBOL(iw_destroy_cm_id);
}
EXPORT_SYMBOL(iw_destroy_cm_id);
@@
-407,7
+414,7
@@
int iw_cm_listen(struct iw_cm_id *cm_id, int backlog)
{
struct iwcm_id_private *cm_id_priv;
unsigned long flags;
{
struct iwcm_id_private *cm_id_priv;
unsigned long flags;
- int ret
= 0
;
+ int ret;
cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
@@
-534,7
+541,7
@@
EXPORT_SYMBOL(iw_cm_accept);
int iw_cm_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param)
{
struct iwcm_id_private *cm_id_priv;
int iw_cm_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param)
{
struct iwcm_id_private *cm_id_priv;
- int ret
= 0
;
+ int ret;
unsigned long flags;
struct ib_qp *qp;
unsigned long flags;
struct ib_qp *qp;
@@
-647,10
+654,11
@@
static void cm_conn_req_handler(struct iwcm_id_private *listen_id_priv,
/* Call the client CM handler */
ret = cm_id->cm_handler(cm_id, iw_event);
if (ret) {
/* Call the client CM handler */
ret = cm_id->cm_handler(cm_id, iw_event);
if (ret) {
+ iw_cm_reject(cm_id, NULL, 0);
set_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags);
destroy_cm_id(cm_id);
if (atomic_read(&cm_id_priv->refcount)==0)
set_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags);
destroy_cm_id(cm_id);
if (atomic_read(&cm_id_priv->refcount)==0)
-
kfree(cm_id
);
+
free_cm_id(cm_id_priv
);
}
out:
}
out:
@@
-674,7
+682,7
@@
static int cm_conn_est_handler(struct iwcm_id_private *cm_id_priv,
struct iw_cm_event *iw_event)
{
unsigned long flags;
struct iw_cm_event *iw_event)
{
unsigned long flags;
- int ret
= 0
;
+ int ret;
spin_lock_irqsave(&cm_id_priv->lock, flags);
spin_lock_irqsave(&cm_id_priv->lock, flags);
@@
-704,7
+712,7
@@
static int cm_conn_rep_handler(struct iwcm_id_private *cm_id_priv,
struct iw_cm_event *iw_event)
{
unsigned long flags;
struct iw_cm_event *iw_event)
{
unsigned long flags;
- int ret
= 0
;
+ int ret;
spin_lock_irqsave(&cm_id_priv->lock, flags);
/*
spin_lock_irqsave(&cm_id_priv->lock, flags);
/*
@@
-828,14
+836,15
@@
static int process_event(struct iwcm_id_private *cm_id_priv,
* thread asleep on the destroy_comp list vs. an object destroyed
* here synchronously when the last reference is removed.
*/
* thread asleep on the destroy_comp list vs. an object destroyed
* here synchronously when the last reference is removed.
*/
-static void cm_work_handler(
void *arg
)
+static void cm_work_handler(
struct work_struct *_work
)
{
{
- struct iwcm_work *work =
arg
;
+ struct iwcm_work *work =
container_of(_work, struct iwcm_work, work)
;
struct iw_cm_event levent;
struct iwcm_id_private *cm_id_priv = work->cm_id;
unsigned long flags;
int empty;
int ret = 0;
struct iw_cm_event levent;
struct iwcm_id_private *cm_id_priv = work->cm_id;
unsigned long flags;
int empty;
int ret = 0;
+ int destroy_id;
spin_lock_irqsave(&cm_id_priv->lock, flags);
empty = list_empty(&cm_id_priv->work_list);
spin_lock_irqsave(&cm_id_priv->lock, flags);
empty = list_empty(&cm_id_priv->work_list);
@@
-854,13
+863,12
@@
static void cm_work_handler(void *arg)
destroy_cm_id(&cm_id_priv->id);
}
BUG_ON(atomic_read(&cm_id_priv->refcount)==0);
destroy_cm_id(&cm_id_priv->id);
}
BUG_ON(atomic_read(&cm_id_priv->refcount)==0);
- if (iwcm_deref_id(cm_id_priv))
- return;
-
- if (atomic_read(&cm_id_priv->refcount)==0 &&
- test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags)) {
- dealloc_work_entries(cm_id_priv);
- kfree(cm_id_priv);
+ destroy_id = test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags);
+ if (iwcm_deref_id(cm_id_priv)) {
+ if (destroy_id) {
+ BUG_ON(!list_empty(&cm_id_priv->work_list));
+ free_cm_id(cm_id_priv);
+ }
return;
}
spin_lock_irqsave(&cm_id_priv->lock, flags);
return;
}
spin_lock_irqsave(&cm_id_priv->lock, flags);
@@
-900,14
+908,14
@@
static int cm_event_handler(struct iw_cm_id *cm_id,
goto out;
}
goto out;
}
- INIT_WORK(&work->work, cm_work_handler
, work
);
+ INIT_WORK(&work->work, cm_work_handler);
work->cm_id = cm_id_priv;
work->event = *iw_event;
if ((work->event.event == IW_CM_EVENT_CONNECT_REQUEST ||
work->event.event == IW_CM_EVENT_CONNECT_REPLY) &&
work->event.private_data_len) {
work->cm_id = cm_id_priv;
work->event = *iw_event;
if ((work->event.event == IW_CM_EVENT_CONNECT_REQUEST ||
work->event.event == IW_CM_EVENT_CONNECT_REPLY) &&
work->event.private_data_len) {
- ret = copy_private_data(
cm_id_priv,
&work->event);
+ ret = copy_private_data(&work->event);
if (ret) {
put_work(work);
goto out;
if (ret) {
put_work(work);
goto out;
@@
-939,8
+947,7
@@
static int iwcm_init_qp_init_attr(struct iwcm_id_private *cm_id_priv,
case IW_CM_STATE_CONN_RECV:
case IW_CM_STATE_ESTABLISHED:
*qp_attr_mask = IB_QP_STATE | IB_QP_ACCESS_FLAGS;
case IW_CM_STATE_CONN_RECV:
case IW_CM_STATE_ESTABLISHED:
*qp_attr_mask = IB_QP_STATE | IB_QP_ACCESS_FLAGS;
- qp_attr->qp_access_flags = IB_ACCESS_LOCAL_WRITE |
- IB_ACCESS_REMOTE_WRITE|
+ qp_attr->qp_access_flags = IB_ACCESS_REMOTE_WRITE|
IB_ACCESS_REMOTE_READ;
ret = 0;
break;
IB_ACCESS_REMOTE_READ;
ret = 0;
break;