[ofa-general] [PATCH 3/3] V2 libmlx4 - Fix fixes after QP buffers alloc optimization patch to allow build
sebastien dugue
sebastien.dugue at bull.net
Thu Jun 18 01:54:35 PDT 2009
The patches in 'fixes/' need to be refreshed after the previous patch in
order to build properly.
Signed-off-by: Sebastien Dugue <sebastien.dugue at bull.net>
---
fixes/lim_qp_resources.patch | 20 ++++-------
fixes/resize_cq_owner_bit.patch | 4 +--
fixes/userspace_dev_lims.patch | 12 ++----
fixes/xrc_consolidated_v2.patch | 68 ++++++++++++++------------------------
fixes/xrc_fix_close_domain.patch | 8 ++---
fixes/xrc_rcv_qp_v2.patch | 12 ++-----
6 files changed, 44 insertions(+), 80 deletions(-)
diff --git a/fixes/lim_qp_resources.patch b/fixes/lim_qp_resources.patch
index 1f89256..54cc63e 100644
--- a/fixes/lim_qp_resources.patch
+++ b/fixes/lim_qp_resources.patch
@@ -7,11 +7,9 @@ qp creation also lie within the reported device limits.
Signed-off-by: Jack Morgenstein <jackm at dev.mellanox.co.il>
-Index: libmlx4/src/qp.c
-===================================================================
---- libmlx4.orig/src/qp.c 2008-06-04 08:24:45.000000000 +0300
-+++ libmlx4/src/qp.c 2008-06-04 08:24:49.000000000 +0300
-@@ -619,6 +619,7 @@ void mlx4_set_sq_sizes(struct mlx4_qp *q
+--- a/src/qp.c
++++ b/src/qp.c
+@@ -622,6 +622,7 @@ void mlx4_set_sq_sizes(struct mlx4_qp *q
enum ibv_qp_type type)
{
int wqe_size;
@@ -19,7 +17,7 @@ Index: libmlx4/src/qp.c
wqe_size = (1 << qp->sq.wqe_shift) - sizeof (struct mlx4_wqe_ctrl_seg);
switch (type) {
-@@ -636,8 +637,9 @@ void mlx4_set_sq_sizes(struct mlx4_qp *q
+@@ -639,8 +640,9 @@ void mlx4_set_sq_sizes(struct mlx4_qp *q
}
qp->sq.max_gs = wqe_size / sizeof (struct mlx4_wqe_data_seg);
@@ -31,10 +29,8 @@ Index: libmlx4/src/qp.c
cap->max_send_wr = qp->sq.max_post;
/*
-Index: libmlx4/src/verbs.c
-===================================================================
---- libmlx4.orig/src/verbs.c 2008-06-04 08:24:45.000000000 +0300
-+++ libmlx4/src/verbs.c 2008-06-04 08:24:49.000000000 +0300
+--- a/src/verbs.c
++++ b/src/verbs.c
@@ -390,12 +390,14 @@ struct ibv_qp *mlx4_create_qp(struct ibv
struct ibv_create_qp_resp resp;
struct mlx4_qp *qp;
@@ -54,9 +50,9 @@ Index: libmlx4/src/verbs.c
attr->cap.max_inline_data > 1024)
return NULL;
-@@ -461,8 +463,14 @@ struct ibv_qp *mlx4_create_qp(struct ibv
- if (ret)
+@@ -464,8 +466,14 @@ struct ibv_qp *mlx4_create_qp(struct ibv
goto err_destroy;
+ pthread_mutex_unlock(&to_mctx(pd->context)->qp_table_mutex);
- qp->rq.wqe_cnt = qp->rq.max_post = attr->cap.max_recv_wr;
+ qp->rq.wqe_cnt = attr->cap.max_recv_wr;
diff --git a/fixes/resize_cq_owner_bit.patch b/fixes/resize_cq_owner_bit.patch
index 6557027..0a5b564 100644
--- a/fixes/resize_cq_owner_bit.patch
+++ b/fixes/resize_cq_owner_bit.patch
@@ -3,11 +3,9 @@ for the target buffer (and not left as it was in the source buffer).
Signed-off-by: Jack Morgenstein <jackm at dev.mellanox.co.il>
-diff --git a/src/cq.c b/src/cq.c
-index 68e16e9..8226b6b 100644
--- a/src/cq.c
+++ b/src/cq.c
-@@ -455,6 +455,8 @@ void mlx4_cq_resize_copy_cqes(struct mlx4_cq *cq, void *buf, int old_cqe)
+@@ -478,6 +478,8 @@ void mlx4_cq_resize_copy_cqes(struct mlx
cqe = get_cqe(cq, (i & old_cqe));
while ((cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) != MLX4_CQE_OPCODE_RESIZE) {
diff --git a/fixes/userspace_dev_lims.patch b/fixes/userspace_dev_lims.patch
index 07cf638..80d4d14 100644
--- a/fixes/userspace_dev_lims.patch
+++ b/fixes/userspace_dev_lims.patch
@@ -9,10 +9,8 @@ preferable to breaking the ABI.
Signed-off-by: Jack Morgenstein <jackm at dev.mellanox.co.il>
-Index: libmlx4/src/mlx4.c
-===================================================================
---- libmlx4.orig/src/mlx4.c 2008-06-03 15:45:18.000000000 +0300
-+++ libmlx4/src/mlx4.c 2008-06-04 08:24:10.000000000 +0300
+--- a/src/mlx4.c
++++ b/src/mlx4.c
@@ -104,6 +104,7 @@ static struct ibv_context *mlx4_alloc_co
struct ibv_get_context cmd;
struct mlx4_alloc_ucontext_resp resp;
@@ -42,10 +40,8 @@ Index: libmlx4/src/mlx4.c
err_free:
free(context);
return NULL;
-Index: libmlx4/src/mlx4.h
-===================================================================
---- libmlx4.orig/src/mlx4.h 2008-06-03 15:45:18.000000000 +0300
-+++ libmlx4/src/mlx4.h 2008-06-04 08:24:10.000000000 +0300
+--- a/src/mlx4.h
++++ b/src/mlx4.h
@@ -83,6 +83,20 @@
#define PFX "mlx4: "
diff --git a/fixes/xrc_consolidated_v2.patch b/fixes/xrc_consolidated_v2.patch
index 6fbd0a9..78a4f6c 100644
--- a/fixes/xrc_consolidated_v2.patch
+++ b/fixes/xrc_consolidated_v2.patch
@@ -18,8 +18,6 @@ V2:
2. Changed xrc_ops to more ops
3. Check for xrc verbs in ibv_more_ops via AC_CHECK_MEMBER
-diff --git a/configure.in b/configure.in
-index 25f27f7..46a3a64 100644
--- a/configure.in
+++ b/configure.in
@@ -42,6 +42,12 @@ AC_CHECK_HEADER(valgrind/memcheck.h,
@@ -35,11 +33,9 @@ index 25f27f7..46a3a64 100644
dnl Checks for library functions
AC_CHECK_FUNC(ibv_read_sysfs_file, [],
-diff --git a/src/cq.c b/src/cq.c
-index 68e16e9..c598b87 100644
--- a/src/cq.c
+++ b/src/cq.c
-@@ -194,8 +194,9 @@ static int mlx4_poll_one(struct mlx4_cq *cq,
+@@ -194,8 +194,9 @@ static int mlx4_poll_one(struct mlx4_cq
{
struct mlx4_wq *wq;
struct mlx4_cqe *cqe;
@@ -50,7 +46,7 @@ index 68e16e9..c598b87 100644
uint32_t g_mlpath_rqpn;
uint16_t wqe_index;
int is_error;
-@@ -221,20 +223,29 @@ static int mlx4_poll_one(struct mlx4_cq *cq,
+@@ -221,20 +222,29 @@ static int mlx4_poll_one(struct mlx4_cq
is_error = (cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) ==
MLX4_CQE_OPCODE_ERROR;
@@ -84,7 +80,7 @@ index 68e16e9..c598b87 100644
if (is_send) {
wq = &(*cur_qp)->sq;
-@@ -242,6 +254,10 @@ static int mlx4_poll_one(struct mlx4_cq *cq,
+@@ -242,6 +252,10 @@ static int mlx4_poll_one(struct mlx4_cq
wq->tail += (uint16_t) (wqe_index - (uint16_t) wq->tail);
wc->wr_id = wq->wrid[wq->tail & (wq->wqe_cnt - 1)];
++wq->tail;
@@ -95,7 +91,7 @@ index 68e16e9..c598b87 100644
} else if ((*cur_qp)->ibv_qp.srq) {
srq = to_msrq((*cur_qp)->ibv_qp.srq);
wqe_index = htons(cqe->wqe_index);
-@@ -387,6 +403,10 @@ void __mlx4_cq_clean(struct mlx4_cq *cq, uint32_t qpn, struct mlx4_srq *srq)
+@@ -387,6 +401,10 @@ void __mlx4_cq_clean(struct mlx4_cq *cq,
uint32_t prod_index;
uint8_t owner_bit;
int nfreed = 0;
@@ -106,7 +102,7 @@ index 68e16e9..c598b87 100644
/*
* First we need to find the current producer index, so we
-@@ -405,7 +425,12 @@ void __mlx4_cq_clean(struct mlx4_cq *cq, uint32_t qpn, struct mlx4_srq *srq)
+@@ -405,7 +423,12 @@ void __mlx4_cq_clean(struct mlx4_cq *cq,
*/
while ((int) --prod_index - (int) cq->cons_index >= 0) {
cqe = get_cqe(cq, prod_index & cq->ibv_cq.cqe);
@@ -120,8 +116,6 @@ index 68e16e9..c598b87 100644
if (srq && !(cqe->owner_sr_opcode & MLX4_CQE_IS_SEND_MASK))
mlx4_free_srq_wqe(srq, ntohs(cqe->wqe_index));
++nfreed;
-diff --git a/src/mlx4-abi.h b/src/mlx4-abi.h
-index 20a40c9..1b1253c 100644
--- a/src/mlx4-abi.h
+++ b/src/mlx4-abi.h
@@ -68,6 +68,14 @@ struct mlx4_resize_cq {
@@ -152,8 +146,6 @@ index 20a40c9..1b1253c 100644
+#endif
+
#endif /* MLX4_ABI_H */
-diff --git a/src/mlx4.c b/src/mlx4.c
-index 671e849..27ca75d 100644
--- a/src/mlx4.c
+++ b/src/mlx4.c
@@ -68,6 +68,16 @@ struct {
@@ -173,7 +165,7 @@ index 671e849..27ca75d 100644
static struct ibv_context_ops mlx4_ctx_ops = {
.query_device = mlx4_query_device,
.query_port = mlx4_query_port,
-@@ -124,6 +134,15 @@ static struct ibv_context *mlx4_alloc_context(struct ibv_device *ibdev, int cmd_
+@@ -124,6 +134,15 @@ static struct ibv_context *mlx4_alloc_co
for (i = 0; i < MLX4_QP_TABLE_SIZE; ++i)
context->qp_table[i].refcnt = 0;
@@ -189,7 +181,7 @@ index 671e849..27ca75d 100644
for (i = 0; i < MLX4_NUM_DB_TYPE; ++i)
context->db_list[i] = NULL;
-@@ -156,6 +175,9 @@ static struct ibv_context *mlx4_alloc_context(struct ibv_device *ibdev, int cmd_
+@@ -156,6 +175,9 @@ static struct ibv_context *mlx4_alloc_co
pthread_spin_init(&context->uar_lock, PTHREAD_PROCESS_PRIVATE);
context->ibv_ctx.ops = mlx4_ctx_ops;
@@ -199,8 +191,6 @@ index 671e849..27ca75d 100644
if (mlx4_query_device(&context->ibv_ctx, &dev_attrs))
goto query_free;
-diff --git a/src/mlx4.h b/src/mlx4.h
-index 8643d8f..3eadb98 100644
--- a/src/mlx4.h
+++ b/src/mlx4.h
@@ -79,6 +79,11 @@
@@ -248,7 +238,7 @@ index 8643d8f..3eadb98 100644
struct mlx4_db_page *db_list[MLX4_NUM_DB_TYPE];
pthread_mutex_t db_list_mutex;
};
-@@ -260,6 +284,11 @@ struct mlx4_ah {
+@@ -266,6 +290,11 @@ struct mlx4_ah {
struct mlx4_av av;
};
@@ -260,7 +250,7 @@ index 8643d8f..3eadb98 100644
static inline unsigned long align(unsigned long val, unsigned long align)
{
return (val + align - 1) & ~(align - 1);
-@@ -304,6 +333,13 @@ static inline struct mlx4_ah *to_mah(struct ibv_ah *ibah)
+@@ -310,6 +339,13 @@ static inline struct mlx4_ah *to_mah(str
return to_mxxx(ah, ah);
}
@@ -272,9 +262,9 @@ index 8643d8f..3eadb98 100644
+#endif
+
int mlx4_alloc_buf(struct mlx4_buf *buf, size_t size, int page_size);
+ int mlx4_alloc_page(struct mlx4_buf *buf, size_t size, int page_size);
void mlx4_free_buf(struct mlx4_buf *buf);
-
-@@ -350,6 +386,10 @@ void mlx4_free_srq_wqe(struct mlx4_srq *srq, int ind);
+@@ -357,6 +393,10 @@ void mlx4_free_srq_wqe(struct mlx4_srq *
int mlx4_post_srq_recv(struct ibv_srq *ibsrq,
struct ibv_recv_wr *wr,
struct ibv_recv_wr **bad_wr);
@@ -285,7 +275,7 @@ index 8643d8f..3eadb98 100644
struct ibv_qp *mlx4_create_qp(struct ibv_pd *pd, struct ibv_qp_init_attr *attr);
int mlx4_query_qp(struct ibv_qp *qp, struct ibv_qp_attr *attr,
-@@ -380,5 +420,16 @@ int mlx4_alloc_av(struct mlx4_pd *pd, struct ibv_ah_attr *attr,
+@@ -387,5 +427,16 @@ int mlx4_alloc_av(struct mlx4_pd *pd, st
void mlx4_free_av(struct mlx4_ah *ah);
int mlx4_attach_mcast(struct ibv_qp *qp, union ibv_gid *gid, uint16_t lid);
int mlx4_detach_mcast(struct ibv_qp *qp, union ibv_gid *gid, uint16_t lid);
@@ -302,11 +292,9 @@ index 8643d8f..3eadb98 100644
+
#endif /* MLX4_H */
-diff --git a/src/qp.c b/src/qp.c
-index 01e8580..2f02430 100644
--- a/src/qp.c
+++ b/src/qp.c
-@@ -226,7 +226,7 @@ int mlx4_post_send(struct ibv_qp *ibqp, struct ibv_send_wr *wr,
+@@ -226,7 +226,7 @@ int mlx4_post_send(struct ibv_qp *ibqp,
ctrl = wqe = get_send_wqe(qp, ind & (qp->sq.wqe_cnt - 1));
qp->sq.wrid[ind & (qp->sq.wqe_cnt - 1)] = wr->wr_id;
@@ -315,7 +303,7 @@ index 01e8580..2f02430 100644
(wr->send_flags & IBV_SEND_SIGNALED ?
htonl(MLX4_WQE_CTRL_CQ_UPDATE) : 0) |
(wr->send_flags & IBV_SEND_SOLICITED ?
-@@ -243,6 +243,9 @@ int mlx4_post_send(struct ibv_qp *ibqp, struct ibv_send_wr *wr,
+@@ -243,6 +243,9 @@ int mlx4_post_send(struct ibv_qp *ibqp,
size = sizeof *ctrl / 16;
switch (ibqp->qp_type) {
@@ -325,7 +313,7 @@ index 01e8580..2f02430 100644
case IBV_QPT_RC:
case IBV_QPT_UC:
switch (wr->opcode) {
-@@ -543,6 +546,7 @@ void mlx4_calc_sq_wqe_size(struct ibv_qp_cap *cap, enum ibv_qp_type type,
+@@ -543,6 +546,7 @@ void mlx4_calc_sq_wqe_size(struct ibv_qp
size += sizeof (struct mlx4_wqe_raddr_seg);
break;
@@ -333,7 +321,7 @@ index 01e8580..2f02430 100644
case IBV_QPT_RC:
size += sizeof (struct mlx4_wqe_raddr_seg);
/*
-@@ -631,6 +635,7 @@ void mlx4_set_sq_sizes(struct mlx4_qp *qp, struct ibv_qp_cap *cap,
+@@ -632,6 +636,7 @@ void mlx4_set_sq_sizes(struct mlx4_qp *q
case IBV_QPT_UC:
case IBV_QPT_RC:
@@ -341,11 +329,9 @@ index 01e8580..2f02430 100644
wqe_size -= sizeof (struct mlx4_wqe_raddr_seg);
break;
-diff --git a/src/srq.c b/src/srq.c
-index ba2ceb9..1350792 100644
--- a/src/srq.c
+++ b/src/srq.c
-@@ -167,3 +167,53 @@ int mlx4_alloc_srq_buf(struct ibv_pd *pd, struct ibv_srq_attr *attr,
+@@ -167,3 +167,53 @@ int mlx4_alloc_srq_buf(struct ibv_pd *pd
return 0;
}
@@ -399,8 +385,6 @@ index ba2ceb9..1350792 100644
+ pthread_mutex_unlock(&ctx->xrc_srq_table_mutex);
+}
+
-diff --git a/src/verbs.c b/src/verbs.c
-index 400050c..b7c9c8e 100644
--- a/src/verbs.c
+++ b/src/verbs.c
@@ -368,18 +368,36 @@ int mlx4_query_srq(struct ibv_srq *srq,
@@ -447,7 +431,7 @@ index 400050c..b7c9c8e 100644
return 0;
}
-@@ -415,7 +433,7 @@ struct ibv_qp *mlx4_create_qp(struct ibv_pd *pd, struct ibv_qp_init_attr *attr)
+@@ -415,7 +433,7 @@ struct ibv_qp *mlx4_create_qp(struct ibv
qp->sq.wqe_cnt = align_queue_size(attr->cap.max_send_wr + qp->sq_spare_wqes);
qp->rq.wqe_cnt = align_queue_size(attr->cap.max_recv_wr);
@@ -456,7 +440,7 @@ index 400050c..b7c9c8e 100644
attr->cap.max_recv_wr = qp->rq.wqe_cnt = 0;
else {
if (attr->cap.max_recv_sge < 1)
-@@ -433,7 +451,7 @@ struct ibv_qp *mlx4_create_qp(struct ibv_pd *pd, struct ibv_qp_init_attr *attr)
+@@ -433,7 +451,7 @@ struct ibv_qp *mlx4_create_qp(struct ibv
pthread_spin_init(&qp->rq.lock, PTHREAD_PROCESS_PRIVATE))
goto err_free;
@@ -465,7 +449,7 @@ index 400050c..b7c9c8e 100644
qp->db = mlx4_alloc_db(to_mctx(pd->context), MLX4_DB_TYPE_RQ);
if (!qp->db)
goto err_free;
-@@ -442,7 +460,7 @@ struct ibv_qp *mlx4_create_qp(struct ibv_pd *pd, struct ibv_qp_init_attr *attr)
+@@ -442,7 +460,7 @@ struct ibv_qp *mlx4_create_qp(struct ibv
}
cmd.buf_addr = (uintptr_t) qp->buf.buf;
@@ -474,7 +458,7 @@ index 400050c..b7c9c8e 100644
cmd.db_addr = 0;
else
cmd.db_addr = (uintptr_t) qp->db;
-@@ -485,7 +503,7 @@ err_destroy:
+@@ -489,7 +507,7 @@ err_destroy:
err_rq_db:
pthread_mutex_unlock(&to_mctx(pd->context)->qp_table_mutex);
@@ -483,7 +467,7 @@ index 400050c..b7c9c8e 100644
mlx4_free_db(to_mctx(pd->context), MLX4_DB_TYPE_RQ, qp->db);
err_free:
-@@ -544,7 +562,7 @@ int mlx4_modify_qp(struct ibv_qp *qp, struct ibv_qp_attr *attr,
+@@ -548,7 +566,7 @@ int mlx4_modify_qp(struct ibv_qp *qp, st
mlx4_cq_clean(to_mcq(qp->send_cq), qp->qp_num, NULL);
mlx4_init_qp_indices(to_mqp(qp));
@@ -492,16 +476,16 @@ index 400050c..b7c9c8e 100644
*to_mqp(qp)->db = 0;
}
-@@ -603,7 +621,7 @@ int mlx4_destroy_qp(struct ibv_qp *ibqp)
-
+@@ -611,7 +629,7 @@ int mlx4_destroy_qp(struct ibv_qp *ibqp)
mlx4_unlock_cqs(ibqp);
+ pthread_mutex_unlock(&to_mctx(ibqp->context)->qp_table_mutex);
- if (!ibqp->srq)
+ if (!ibqp->srq && ibqp->qp_type != IBV_QPT_XRC)
mlx4_free_db(to_mctx(ibqp->context), MLX4_DB_TYPE_RQ, qp->db);
free(qp->sq.wrid);
if (qp->rq.wqe_cnt)
-@@ -661,3 +679,103 @@ int mlx4_detach_mcast(struct ibv_qp *qp, union ibv_gid *gid, uint16_t lid)
+@@ -669,3 +687,103 @@ int mlx4_detach_mcast(struct ibv_qp *qp,
{
return ibv_cmd_detach_mcast(qp, gid, lid);
}
@@ -605,8 +589,6 @@ index 400050c..b7c9c8e 100644
+ return 0;
+}
+#endif
-diff --git a/src/wqe.h b/src/wqe.h
-index 6f7f309..fa2f8ac 100644
--- a/src/wqe.h
+++ b/src/wqe.h
@@ -65,7 +65,7 @@ struct mlx4_wqe_ctrl_seg {
diff --git a/fixes/xrc_fix_close_domain.patch b/fixes/xrc_fix_close_domain.patch
index dfad7ac..3af2640 100644
--- a/fixes/xrc_fix_close_domain.patch
+++ b/fixes/xrc_fix_close_domain.patch
@@ -6,11 +6,9 @@ Need to pass this upward to caller.
Signed-off-by: Jack Morgenstein <jackm at dev.mellanox.co.il>
-Index: libmlx4/src/verbs.c
-===================================================================
---- libmlx4.orig/src/verbs.c 2008-09-01 10:51:11.000000000 +0300
-+++ libmlx4/src/verbs.c 2008-09-01 10:52:40.000000000 +0300
-@@ -774,9 +774,11 @@
+--- a/src/verbs.c
++++ b/src/verbs.c
+@@ -782,9 +782,11 @@ struct ibv_xrc_domain *mlx4_open_xrc_dom
int mlx4_close_xrc_domain(struct ibv_xrc_domain *d)
{
diff --git a/fixes/xrc_rcv_qp_v2.patch b/fixes/xrc_rcv_qp_v2.patch
index 311c500..00ffd53 100644
--- a/fixes/xrc_rcv_qp_v2.patch
+++ b/fixes/xrc_rcv_qp_v2.patch
@@ -5,11 +5,9 @@ Signed-off-by: Jack Morgenstein <jackm at dev.mellanox.co.il>
V2:
1. xrc_ops changed to more_ops
-diff --git a/src/mlx4.c b/src/mlx4.c
-index 27ca75d..e5ded78 100644
--- a/src/mlx4.c
+++ b/src/mlx4.c
-@@ -74,6 +74,11 @@ static struct ibv_more_ops mlx4_more_ops = {
+@@ -74,6 +74,11 @@ static struct ibv_more_ops mlx4_more_ops
.create_xrc_srq = mlx4_create_xrc_srq,
.open_xrc_domain = mlx4_open_xrc_domain,
.close_xrc_domain = mlx4_close_xrc_domain,
@@ -21,11 +19,9 @@ index 27ca75d..e5ded78 100644
#endif
};
#endif
-diff --git a/src/mlx4.h b/src/mlx4.h
-index 3eadb98..6307a2d 100644
--- a/src/mlx4.h
+++ b/src/mlx4.h
-@@ -429,6 +429,21 @@ struct ibv_xrc_domain *mlx4_open_xrc_domain(struct ibv_context *context,
+@@ -436,6 +436,21 @@ struct ibv_xrc_domain *mlx4_open_xrc_dom
int fd, int oflag);
int mlx4_close_xrc_domain(struct ibv_xrc_domain *d);
@@ -47,11 +43,9 @@ index 3eadb98..6307a2d 100644
#endif
-diff --git a/src/verbs.c b/src/verbs.c
-index b7c9c8e..8261eae 100644
--- a/src/verbs.c
+++ b/src/verbs.c
-@@ -778,4 +778,59 @@ int mlx4_close_xrc_domain(struct ibv_xrc_domain *d)
+@@ -786,4 +786,59 @@ int mlx4_close_xrc_domain(struct ibv_xrc
free(d);
return 0;
}
--
1.6.3.1
More information about the general
mailing list