PERFORCE change 128871 for review
Steve Wise
swise at FreeBSD.org
Fri Nov 9 10:56:38 PST 2007
http://perforce.freebsd.org/chv.cgi?CH=128871
Change 128871 by swise at swise:vic10:iwarp on 2007/11/09 18:55:42
rmda_iwcm compiles.
Affected files ...
.. //depot/projects/iwarp/sys/contrib/rdma/rdma_cma.c#4 edit
.. //depot/projects/iwarp/sys/contrib/rdma/rdma_iwcm.c#2 edit
.. //depot/projects/iwarp/sys/sys/linux_compat.h#4 edit
Differences ...
==== //depot/projects/iwarp/sys/contrib/rdma/rdma_cma.c#4 (text+ko) ====
@@ -2931,4 +2931,6 @@
};
MODULE_VERSION(rdma_cma, 1);
+MODULE_DEPEND(rdma_cma, rdma_core, 1, 1, 1);
+MODULE_DEPEND(rdma_cma, rdma_addr, 1, 1, 1);
DECLARE_MODULE(rdma_cma, mod_data, SI_SUB_EXEC, SI_ORDER_ANY);
==== //depot/projects/iwarp/sys/contrib/rdma/rdma_iwcm.c#2 (text+ko) ====
@@ -35,31 +35,68 @@
* SOFTWARE.
*
*/
-#include <linux/dma-mapping.h>
-#include <linux/err.h>
-#include <linux/idr.h>
-#include <linux/interrupt.h>
-#include <linux/rbtree.h>
-#include <linux/spinlock.h>
-#include <linux/workqueue.h>
-#include <linux/completion.h>
+
+#include <sys/cdefs.h>
+
+#include <sys/param.h>
+#include <sys/condvar.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/libkern.h>
+#include <sys/socket.h>
+#include <sys/module.h>
+#include <sys/linux_compat.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/rwlock.h>
+#include <sys/queue.h>
+#include <sys/taskqueue.h>
+#include <sys/priv.h>
+#include <sys/syslog.h>
+#include <sys/linux_compat.h>
-#include <rdma/iw_cm.h>
-#include <rdma/ib_addr.h>
+#include <netinet/in.h>
+#include <netinet/in_pcb.h>
-#include "iwcm.h"
+#include <contrib/rdma/iw_cm.h>
MODULE_AUTHOR("Tom Tucker");
MODULE_DESCRIPTION("iWARP CM");
MODULE_LICENSE("Dual BSD/GPL");
-static struct workqueue_struct *iwcm_wq;
+enum iw_cm_state {
+ IW_CM_STATE_IDLE, /* unbound, inactive */
+ IW_CM_STATE_LISTEN, /* listen waiting for connect */
+ IW_CM_STATE_CONN_RECV, /* inbound waiting for user accept */
+ IW_CM_STATE_CONN_SENT, /* outbound waiting for peer accept */
+ IW_CM_STATE_ESTABLISHED, /* established */
+ IW_CM_STATE_CLOSING, /* disconnect */
+ IW_CM_STATE_DESTROYING /* object being deleted */
+};
+
+struct iwcm_id_private {
+ struct iw_cm_id id;
+ enum iw_cm_state state;
+ unsigned long flags;
+ struct ib_qp *qp;
+ struct cv destroy_comp;
+ struct cv connect_wait;
+ TAILQ_HEAD(, iwcm_work) work_list;
+ struct mtx lock;
+ atomic_t refcount;
+ TAILQ_HEAD(, iwcm_work) work_free_list;
+};
+
+#define IWCM_F_CALLBACK_DESTROY 1
+#define IWCM_F_CONNECT_WAIT 2
+
+static struct taskqueue *iwcm_wq;
struct iwcm_work {
- struct work_struct work;
+ struct task task;
struct iwcm_id_private *cm_id;
- struct list_head list;
+ TAILQ_ENTRY(iwcm_work) list;
struct iw_cm_event event;
- struct list_head free_list;
+ TAILQ_ENTRY(iwcm_work) free_list;
};
/*
@@ -90,40 +127,38 @@
{
struct iwcm_work *work;
- if (TAILQ_EMPTY((&cm_id_priv->work_free_list))
+ if (TAILQ_EMPTY(&cm_id_priv->work_free_list))
return NULL;
- work = list_entry(cm_id_priv->work_free_list.next, struct iwcm_work,
- free_list);
- list_del_init(&work->free_list);
+ work = TAILQ_FIRST(&cm_id_priv->work_free_list);
+ TAILQ_REMOVE(&cm_id_priv->work_free_list, work, free_list);
return work;
}
static void put_work(struct iwcm_work *work)
{
- list_add(&work->free_list, &work->cm_id->work_free_list);
+ TAILQ_INSERT_HEAD(&work->cm_id->work_free_list, work, free_list);
}
static void dealloc_work_entries(struct iwcm_id_private *cm_id_priv)
{
- struct list_head *e, *tmp;
+ struct iwcm_work *e, *tmp;
- list_for_each_safe(e, tmp, &cm_id_priv->work_free_list)
- kfree(list_entry(e, struct iwcm_work, free_list));
+ TAILQ_FOREACH_SAFE(e, &cm_id_priv->work_free_list, free_list, tmp)
+ free(e, M_DEVBUF);
}
static int alloc_work_entries(struct iwcm_id_private *cm_id_priv, int count)
{
struct iwcm_work *work;
- BUG_ON(!TAILQ_EMPTY((&cm_id_priv->work_free_list));
+ BUG_ON(!TAILQ_EMPTY(&cm_id_priv->work_free_list));
while (count--) {
- work = kmalloc(sizeof(struct iwcm_work), GFP_KERNEL);
+ work = malloc(sizeof(struct iwcm_work), M_DEVBUF, M_WAITOK);
if (!work) {
dealloc_work_entries(cm_id_priv);
return (ENOMEM);
}
work->cm_id = cm_id_priv;
- INIT_LIST_HEAD(&work->list);
put_work(work);
}
return 0;
@@ -138,9 +173,10 @@
{
void *p;
- p = kmemdup(event->private_data, event->private_data_len, GFP_ATOMIC);
+ p = malloc(event->private_data_len, M_DEVBUF, M_NOWAIT);
if (!p)
return (ENOMEM);
+ bcopy(event->private_data, p, event->private_data_len);
event->private_data = p;
return 0;
}
@@ -148,7 +184,7 @@
static void free_cm_id(struct iwcm_id_private *cm_id_priv)
{
dealloc_work_entries(cm_id_priv);
- kfree(cm_id_priv);
+ free(cm_id_priv, M_DEVBUF);
}
/*
@@ -158,12 +194,15 @@
*/
static int iwcm_deref_id(struct iwcm_id_private *cm_id_priv)
{
+ mtx_lock(&cm_id_priv->lock);
BUG_ON(atomic_read(&cm_id_priv->refcount)==0);
if (atomic_dec_and_test(&cm_id_priv->refcount)) {
- BUG_ON(!TAILQ_EMPTY((&cm_id_priv->work_list));
- complete(&cm_id_priv->destroy_comp);
+ BUG_ON(!TAILQ_EMPTY(&cm_id_priv->work_list));
+ cv_broadcast(&cm_id_priv->destroy_comp);
+ mtx_unlock(&cm_id_priv->lock);
return 1;
}
+ mtx_unlock(&cm_id_priv->lock);
return 0;
}
@@ -181,7 +220,7 @@
cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
if (iwcm_deref_id(cm_id_priv) &&
test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags)) {
- BUG_ON(!TAILQ_EMPTY((&cm_id_priv->work_list));
+ BUG_ON(!TAILQ_EMPTY(&cm_id_priv->work_list));
free_cm_id(cm_id_priv);
}
}
@@ -194,9 +233,10 @@
{
struct iwcm_id_private *cm_id_priv;
- cm_id_priv = kzalloc(sizeof(*cm_id_priv), GFP_KERNEL);
+ cm_id_priv = malloc(sizeof(*cm_id_priv), M_DEVBUF, M_WAITOK);
if (!cm_id_priv)
return ERR_PTR(ENOMEM);
+ bzero(cm_id_priv, sizeof *cm_id_priv);
cm_id_priv->state = IW_CM_STATE_IDLE;
cm_id_priv->id.device = device;
@@ -205,10 +245,10 @@
cm_id_priv->id.event_handler = cm_event_handler;
cm_id_priv->id.add_ref = add_ref;
cm_id_priv->id.rem_ref = rem_ref;
- mtx_init(&cm_id_priv->lock, "cm id priv", NULL, MTX_DUPOK|MTX_DEF);
+ mtx_init(&cm_id_priv->lock, "cm_id_priv", NULL, MTX_DUPOK|MTX_SPIN);
atomic_set(&cm_id_priv->refcount, 1);
- cv_init(&cm_id_priv->connect_wait, "cm_id_priv connect wait");
- init_completion(&cm_id_priv->destroy_comp);
+ cv_init(&cm_id_priv->connect_wait, "cm_id_priv connect_wait");
+ cv_init(&cm_id_priv->destroy_comp, "cm_id_priv destroy_comp");
TAILQ_INIT(&cm_id_priv->work_list);
TAILQ_INIT(&cm_id_priv->work_free_list);
@@ -261,11 +301,10 @@
cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
/* Wait if we're currently in a connect or accept downcall */
+ mtx_lock(&cm_id_priv->lock);
if (test_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags))
- wait_event(&cm_id_priv->connect_wait, &cm_id_priv->lock)
-
+ cv_wait(&cm_id_priv->connect_wait, &cm_id_priv->lock);
- mtx_lock(&cm_id_priv->lock);
switch (cm_id_priv->state) {
case IW_CM_STATE_ESTABLISHED:
cm_id_priv->state = IW_CM_STATE_CLOSING;
@@ -330,10 +369,10 @@
* Wait if we're currently in a connect or accept downcall. A
* listening endpoint should never block here.
*/
+ mtx_lock(&cm_id_priv->lock);
if (test_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags))
- wait_event(&cm_id_priv->connect_wait, &cm_id_priv->lock);
+ cv_wait(&cm_id_priv->connect_wait, &cm_id_priv->lock);
- mtx_lock(&cm_id_priv->lock);
switch (cm_id_priv->state) {
case IW_CM_STATE_LISTEN:
cm_id_priv->state = IW_CM_STATE_DESTROYING;
@@ -380,7 +419,7 @@
/*
* This function is only called by the application thread and cannot
* be called by the event thread. The function will wait for all
- * references to be released on the cm_id and then kfree the cm_id
+ * references to be released on the cm_id and then free the cm_id
* object.
*/
void iw_destroy_cm_id(struct iw_cm_id *cm_id)
@@ -392,7 +431,8 @@
destroy_cm_id(cm_id);
- wait_for_completion(&cm_id_priv->destroy_comp);
+ mtx_lock(&cm_id_priv->lock);
+ cv_wait(&cm_id_priv->destroy_comp, &cm_id_priv->lock);
free_cm_id(cm_id_priv);
}
@@ -451,9 +491,9 @@
mtx_lock(&cm_id_priv->lock);
if (cm_id_priv->state != IW_CM_STATE_CONN_RECV) {
+ clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags);
+ cv_broadcast(&cm_id_priv->connect_wait);
mtx_unlock(&cm_id_priv->lock);
- clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags);
- wake_up_all(&cm_id_priv->connect_wait, &cm_id_priv->lock);
return (EINVAL);
}
cm_id_priv->state = IW_CM_STATE_IDLE;
@@ -462,8 +502,10 @@
ret = cm_id->device->iwcm->reject(cm_id, private_data,
private_data_len);
+ mtx_lock(&cm_id_priv->lock);
clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags);
- wake_up_all(&cm_id_priv->connect_wait, &cm_id_priv->lock);
+ cv_broadcast(&cm_id_priv->connect_wait);
+ mtx_unlock(&cm_id_priv->lock);
return ret;
}
@@ -488,9 +530,9 @@
mtx_lock(&cm_id_priv->lock);
if (cm_id_priv->state != IW_CM_STATE_CONN_RECV) {
+ clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags);
+ cv_broadcast(&cm_id_priv->connect_wait);
mtx_unlock(&cm_id_priv->lock);
- clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags);
- wake_up_all(&cm_id_priv->connect_wait, &cm_id_priv->lock);
return (EINVAL);
}
@@ -514,9 +556,9 @@
cm_id->device->iwcm->rem_ref(qp);
cm_id_priv->qp = NULL;
}
+ clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags);
+ cv_broadcast(&cm_id_priv->connect_wait);
mtx_unlock(&cm_id_priv->lock);
- clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags);
- wake_up_all(&cm_id_priv->connect_wait, &cm_id_priv->lock);
}
return ret;
@@ -546,9 +588,9 @@
mtx_lock(&cm_id_priv->lock);
if (cm_id_priv->state != IW_CM_STATE_IDLE) {
+ clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags);
+ cv_broadcast(&cm_id_priv->connect_wait);
mtx_unlock(&cm_id_priv->lock);
- clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags);
- wake_up_all(&cm_id_priv->connect_wait, &cm_id_priv->lock);
return (EINVAL);
}
@@ -571,11 +613,11 @@
cm_id->device->iwcm->rem_ref(qp);
cm_id_priv->qp = NULL;
}
- mtx_unlock(&cm_id_priv->lock);
BUG_ON(cm_id_priv->state != IW_CM_STATE_CONN_SENT);
cm_id_priv->state = IW_CM_STATE_IDLE;
clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags);
- wake_up_all(&cm_id_priv->connect_wait, &cm_id_priv->lock);
+ cv_broadcast(&cm_id_priv->connect_wait);
+ mtx_unlock(&cm_id_priv->lock);
}
@@ -655,7 +697,7 @@
out:
if (iw_event->private_data_len)
- kfree(iw_event->private_data);
+ free(iw_event->private_data, M_DEVBUF);
}
/*
@@ -685,9 +727,9 @@
clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags);
BUG_ON(cm_id_priv->state != IW_CM_STATE_CONN_RECV);
cm_id_priv->state = IW_CM_STATE_ESTABLISHED;
+ ret = cm_id_priv->id.cm_handler(&cm_id_priv->id, iw_event);
+ cv_broadcast(&cm_id_priv->connect_wait);
mtx_unlock(&cm_id_priv->lock);
- ret = cm_id_priv->id.cm_handler(&cm_id_priv->id, iw_event);
- wake_up_all(&cm_id_priv->connect_wait, &cm_id_priv->lock);
return ret;
}
@@ -724,11 +766,13 @@
mtx_unlock(&cm_id_priv->lock);
ret = cm_id_priv->id.cm_handler(&cm_id_priv->id, iw_event);
+ mtx_lock(&cm_id_priv->lock);
if (iw_event->private_data_len)
- kfree(iw_event->private_data);
+ free(iw_event->private_data, M_DEVBUF);
/* Wake up waiters on connect complete */
- wake_up_all(&cm_id_priv->connect_wait, &cm_id_priv->lock);
+ cv_broadcast(&cm_id_priv->connect_wait);
+ mtx_unlock(&cm_id_priv->lock);
return ret;
}
@@ -824,20 +868,20 @@
* thread asleep on the destroy_comp list vs. an object destroyed
* here synchronously when the last reference is removed.
*/
-static void cm_work_handler(struct work_struct *_work)
+static void cm_work_handler(void *context, int pending)
{
- struct iwcm_work *work = container_of(_work, struct iwcm_work, work);
+ struct iwcm_work *work = context;
struct iw_cm_event levent;
struct iwcm_id_private *cm_id_priv = work->cm_id;
int empty;
int ret = 0;
mtx_lock(&cm_id_priv->lock);
- empty = TAILQ_EMPTY((&cm_id_priv->work_list);
+ empty = TAILQ_EMPTY(&cm_id_priv->work_list);
while (!empty) {
work = TAILQ_FIRST(&cm_id_priv->work_list);
- TAILQ_REMOVE(&cm_id_priv->work_list, work, entry);
- empty = TAILQ_EMPTY((&cm_id_priv->work_list);
+ TAILQ_REMOVE(&cm_id_priv->work_list, work, list);
+ empty = TAILQ_EMPTY(&cm_id_priv->work_list);
levent = work->event;
put_work(work);
mtx_unlock(&cm_id_priv->lock);
@@ -851,7 +895,7 @@
if (iwcm_deref_id(cm_id_priv)) {
if (test_bit(IWCM_F_CALLBACK_DESTROY,
&cm_id_priv->flags)) {
- BUG_ON(!TAILQ_EMPTY((&cm_id_priv->work_list));
+ BUG_ON(!TAILQ_EMPTY(&cm_id_priv->work_list));
free_cm_id(cm_id_priv);
}
return;
@@ -892,7 +936,7 @@
goto out;
}
- INIT_WORK(&work->work, cm_work_handler);
+ TASK_INIT(&work->task, 0, cm_work_handler, work);
work->cm_id = cm_id_priv;
work->event = *iw_event;
@@ -907,11 +951,11 @@
}
atomic_inc(&cm_id_priv->refcount);
- if (TAILQ_EMPTY((&cm_id_priv->work_list)) {
- list_add_tail(&work->list, &cm_id_priv->work_list);
- taskqueue_enqueue(iwcm_wq, &work->work);
+ if (TAILQ_EMPTY(&cm_id_priv->work_list)) {
+ TAILQ_INSERT_TAIL(&cm_id_priv->work_list, work, list);
+ taskqueue_enqueue(iwcm_wq, &work->task);
} else
- list_add_tail(&work->list, &cm_id_priv->work_list);
+ TAILQ_INSERT_TAIL(&cm_id_priv->work_list, work, list);
out:
mtx_unlock(&cm_id_priv->lock);
return ret;
@@ -994,7 +1038,7 @@
static int __init iw_cm_init(void)
{
- iwcm_wq = taskqueue_create("iw_cm_wq", M_NOWAIT, taskqueue_thread_enqueue, &iwcm_wq);
+ iwcm_wq = taskqueue_create("iw_cm_wq", M_WAITOK, taskqueue_thread_enqueue, &iwcm_wq);
if (!iwcm_wq)
return (ENOMEM);
@@ -1007,5 +1051,39 @@
taskqueue_free(iwcm_wq);
}
-module_init(iw_cm_init);
-module_exit(iw_cm_cleanup);
+static int
+iw_cm_load(module_t mod, int cmd, void *arg)
+{
+ int err = 0;
+
+ switch (cmd) {
+ case MOD_LOAD:
+ printf("Loading iwcm.\n");
+
+ iw_cm_init();
+ break;
+ case MOD_QUIESCE:
+ break;
+ case MOD_UNLOAD:
+ printf("Unloading iwcm.\n");
+ iw_cm_cleanup();
+ break;
+ case MOD_SHUTDOWN:
+ break;
+ default:
+ err = EOPNOTSUPP;
+ break;
+ }
+
+ return (err);
+}
+
+static moduledata_t mod_data = {
+ "rdma_iwcm",
+ iw_cm_load,
+ 0
+};
+
+MODULE_VERSION(rdma_iwcm, 1);
+MODULE_DEPEND(rdma_iwcm, rdma_core, 1, 1, 1);
+DECLARE_MODULE(rdma_iwcm, mod_data, SI_SUB_EXEC, SI_ORDER_ANY);
==== //depot/projects/iwarp/sys/sys/linux_compat.h#4 (text+ko) ====
@@ -75,6 +75,13 @@
}
#define dst_mtu(rt) ((rt)->rt_rmx.rmx_mtu)
+
+static __inline void
+BUG(void)
+{
+ panic("BUG: %s:%d", __FILE__, __LINE__);
+}
+
#define BUG_ON(e) \
do { \
if (e) { \
@@ -153,6 +160,23 @@
}
}
+static __inline void
+set_bit(int b, volatile void *p)
+{
+ atomic_set_int(((volatile int *)p) + (b >> 5), 1 << (b & 0x1f));
+}
+
+static __inline int
+test_bit(int b, volatile void *p)
+{
+ return ((volatile int *)p)[b >> 5] & (1 << (b & 0x1f));
+}
+
+static __inline void
+clear_bit(int b, volatile void *p)
+{
+ atomic_clear_int(((volatile int *)p) + (b >> 5), 1 << (b & 0x1f));
+}
#define copy_from_user(a,b,c) copyin(b,a,c)
#define copy_to_user(a,b,c) copyout(b,a,c)
More information about the p4-projects
mailing list