Exemple #1
0
/*
 * siw_post_send()
 *
 * Post a list of S-WR's to a SQ.
 *
 * @ofa_qp:	OFA QP contained in siw QP
 * @wr:		Null terminated list of user WR's
 * @bad_wr:	Points to failing WR in case of synchronous failure.
 */
int siw_post_send(struct ib_qp *ofa_qp, struct ib_send_wr *wr,
		  struct ib_send_wr **bad_wr)
{
	struct siw_wqe	*wqe = NULL;
	struct siw_qp	*qp = siw_qp_ofa2siw(ofa_qp);

	unsigned long flags;
	int rv = 0;

	dprint(DBG_WR|DBG_TX, "(QP%d): state=%d\n",
		QP_ID(qp), qp->attrs.state);

	/*
	 * Try to acquire QP state lock. Must be non-blocking
	 * to accommodate kernel clients needs.
	 */
	if (!down_read_trylock(&qp->state_lock)) {
		*bad_wr = wr;
		return -ENOTCONN;
	}

	if (qp->attrs.state != SIW_QP_STATE_RTS) {
		dprint(DBG_WR|DBG_ON, "(QP%d): state=%d\n",
			QP_ID(qp), qp->attrs.state);
		up_read(&qp->state_lock);
		*bad_wr = wr;
		return -ENOTCONN;
	}
	dprint(DBG_WR|DBG_TX, "(QP%d): sq_space(#1)=%d\n",
		QP_ID(qp), atomic_read(&qp->sq_space));

	while (wr) {
		wqe = siw_wqe_alloc(qp, opcode_ofa2siw(wr->opcode));
		if (!wqe) {
			dprint(DBG_ON, " siw_wqe_alloc\n");
			rv = -ENOMEM;
			break;
		}
		wr_type(wqe) = opcode_ofa2siw(wr->opcode);
		wr_id(wqe) = wr->wr_id;

		wr_flags(wqe) = wr->send_flags;
		if (qp->attrs.flags & SIW_SIGNAL_ALL_WR)
			wr_flags(wqe) |= IB_SEND_SIGNALED;

		if (wr->num_sge > qp->attrs.sq_max_sges) {
			/*
			 * NOTE: we allow for zero length wr's here.
			 */
			dprint(DBG_WR, "(QP%d): Num SGE: %d\n",
				QP_ID(qp), wr->num_sge);
			rv = -EINVAL;
			break;
		}

		switch (wr->opcode) {

		case IB_WR_SEND:
			if (!SIW_INLINED_DATA(wqe)) {
				rv = siw_copy_sgl(wr->sg_list,
						  wqe->wr.send.sge,
						  wr->num_sge);
				wqe->wr.send.num_sge = wr->num_sge;
			} else
				rv = siw_copy_inline_sgl(wr, wqe);

			if (rv < 0) {
				rv = -EINVAL;
				break;
			}
			wqe->bytes = rv;
			break;

		case IB_WR_RDMA_READ:
			/*
			 * OFED WR restricts RREAD sink to SGL containing
			 * 1 SGE only. we could relax to SGL with multiple
			 * elements referring the SAME ltag or even sending
			 * a private per-rreq tag referring to a checked
			 * local sgl with MULTIPLE ltag's. would be easy
			 * to do...
			 */
			if (wr->num_sge != 1) {
				rv = -EINVAL;
				break;
			}
			rv = siw_copy_sgl(wr->sg_list, wqe->wr.rread.sge, 1);
			/*
			 * NOTE: zero length RREAD is allowed!
			 */
			wqe->wr.rread.raddr = wr->wr.rdma.remote_addr;
			wqe->wr.rread.rtag = wr->wr.rdma.rkey;
			wqe->wr.rread.num_sge = 1;
			wqe->bytes = rv;
			break;

		case IB_WR_RDMA_WRITE:
			if (!SIW_INLINED_DATA(wqe)) {
				rv = siw_copy_sgl(wr->sg_list,
						  wqe->wr.send.sge,
						  wr->num_sge);
				wqe->wr.write.num_sge = wr->num_sge;
			} else
				rv = siw_copy_inline_sgl(wr, wqe);
			/*
			 * NOTE: zero length WRITE is allowed!
			 */
			if (rv < 0) {
				rv = -EINVAL;
				break;
			}
			wqe->wr.write.raddr = wr->wr.rdma.remote_addr;
			wqe->wr.write.rtag = wr->wr.rdma.rkey;
			wqe->bytes = rv;
			break;

		default:
			dprint(DBG_WR|DBG_TX|DBG_ON,
				"(QP%d): Opcode %d not yet implemented\n",
				QP_ID(qp), wr->opcode);
			wqe->wr.sgl.num_sge = 0;
			rv = -ENOSYS;
			break;
		}
		dprint(DBG_WR|DBG_TX, "(QP%d): opcode %d, bytes %d, "
				"flags 0x%x\n",
				QP_ID(qp), wr_type(wqe), wqe->bytes,
				wr_flags(wqe));
		if (rv < 0)
			break;

		wqe->wr_status = SR_WR_QUEUED;

		lock_sq_rxsave(qp, flags);
		list_add_tail(&wqe->list, &qp->sq);
		unlock_sq_rxsave(qp, flags);

		wr = wr->next;
	}
	/*
	 * Send directly if SQ processing is not in progress.
	 * Eventual immediate errors (rv < 0) do not affect the involved
	 * RI resources (Verbs, 8.3.1) and thus do not prevent from SQ
	 * processing, if new work is already pending. But rv must be passed
	 * to caller.
	 */
	lock_sq_rxsave(qp, flags);
	if (tx_wqe(qp) == NULL) {
		struct siw_wqe	*next = siw_next_tx_wqe(qp);
		if (next != NULL) {
			if (wr_type(next) != SIW_WR_RDMA_READ_REQ ||
			    !ORD_SUSPEND_SQ(qp)) {
				tx_wqe(qp) = next;
				if (wr_type(next) != SIW_WR_RDMA_READ_REQ)
					list_del_init(&next->list);
				else
					siw_rreq_queue(next, qp);

				unlock_sq_rxsave(qp, flags);

				dprint(DBG_WR|DBG_TX,
					"(QP%d): Direct sending...\n",
					QP_ID(qp));

				if (qp->attrs.flags & SIW_KERNEL_VERBS)
					siw_sq_queue_work(qp);
				else if (siw_qp_sq_process(qp, 1) != 0 &&
				    !(qp->tx_ctx.tx_suspend))
					siw_qp_cm_drop(qp, 0);
			} else
				unlock_sq_rxsave(qp, flags);
		} else
			unlock_sq_rxsave(qp, flags);
	} else
		unlock_sq_rxsave(qp, flags);

	up_read(&qp->state_lock);

	dprint(DBG_WR|DBG_TX, "(QP%d): sq_space(#2)=%d\n", QP_ID(qp),
		atomic_read(&qp->sq_space));
	if (rv >= 0)
		return 0;
	/*
	 * Immediate error
	 */
	dprint(DBG_WR|DBG_ON, "(QP%d): error=%d\n", QP_ID(qp), rv);

	if (wqe != NULL)
		siw_wqe_put(wqe);
	*bad_wr = wr;
	return rv;
}
Exemple #2
0
/*------------------------------------------------------------------------------
  Write mask data.

  Input: filename = name of file to write to;
  "" or "-" means write to standard output.
  fmt = pointer to format structure;
  if null, defaults to polygon format.
  polys = polygons to write.
  npolys = number of polygons to write.
  Return value: number of polygons written,
  or -1 if error occurred.
*/
int wrmask(char *filename, format *fmt, int npolys, 
           polygon *polys[/*npolys*/], int selfdestruct)
{
  int npoly;

  /* discard polygons with weight or area outside specified limits */
  npoly = discard_poly(npolys, polys);

  fprintf(stderr,"output format is %s\n", fmt->out);

  /* default polygon format */
  if (!fmt || strcmp(fmt->out, "polygon") == 0
      || strcmp(fmt->out, "spolygon") == 0) {
    npoly = wr_poly(filename, fmt, npolys, polys, npoly, selfdestruct);
      
    /* binary polygon format */
  } else if (!fmt || strcmp(fmt->out, "binary") == 0) {
    npoly = wr_binary(filename, fmt, npolys, polys, npoly, selfdestruct);
  
    /* circle format */
  } else if (strcmp(fmt->out, "circle") == 0) {
    npoly = wr_circ(filename, fmt, npolys, polys, npoly);

    /* edges, graphics, or vertices format */
  } else if (strcmp(fmt->out, "edges") == 0
             || strcmp(fmt->out, "graphics") == 0
             || strcmp(fmt->out, "vertices") == 0) {
    npoly = wr_edge(filename, fmt, npolys, polys, npoly);

    /* rectangle format */
  } else if (strcmp(fmt->out, "rectangle") == 0) {
    npoly = wr_rect(filename, fmt, npolys, polys, npoly);

    /* Region format */
  } else if (strcmp(fmt->out, "Region") == 0) {
    npoly = wr_Reg(filename, npolys, polys, npoly);

    /* area format */
  } else if (strcmp(fmt->out, "area") == 0) {
    npoly = wr_area(filename, fmt, npolys, polys, npoly);

    /* id format */
  } else if (strcmp(fmt->out, "id") == 0) {
    npoly = wr_id(filename, npolys, polys, npoly);

    /* midpoint format */
  } else if (strcmp(fmt->out, "midpoint") == 0) {
    npoly = wr_midpoint(filename, fmt, npolys, polys, npoly);

    /* weight format */
  } else if (strcmp(fmt->out, "weight") == 0) {
    npoly = wr_weight(filename, fmt, npolys, polys, npoly);

  } else {
    fprintf(stderr, "wrmask: format %s not recognized\n", fmt->out);
    npoly = -1;

  }

  return(npoly);
}
Exemple #3
0
/*
 * siw_post_receive()
 *
 * Post a list of R-WR's to a RQ.
 *
 * @ofa_qp:	OFA QP contained in siw QP
 * @wr:		Null terminated list of user WR's
 * @bad_wr:	Points to failing WR in case of synchronous failure.
 */
int siw_post_receive(struct ib_qp *ofa_qp, struct ib_recv_wr *wr,
		     struct ib_recv_wr **bad_wr)
{
	struct siw_wqe	*wqe = NULL;
	struct siw_qp	*qp = siw_qp_ofa2siw(ofa_qp);
	unsigned long	flags;
	int rv = 0;

	dprint(DBG_WR|DBG_TX, "(QP%d): state=%d\n", QP_ID(qp),
		qp->attrs.state);

	if (unlikely(qp->srq)) {
		*bad_wr = wr;
		return -EOPNOTSUPP; /* what else from errno.h? */
	}
	/*
	 * Try to acquire QP state lock. Must be non-blocking
	 * to accommodate kernel clients needs.
	 */
	if (!down_read_trylock(&qp->state_lock)) {
		*bad_wr = wr;
		return -ENOTCONN;
	}

	if (qp->attrs.state > SIW_QP_STATE_RTS) {
		up_read(&qp->state_lock);
		dprint(DBG_ON, " (QP%d): state=%d\n", QP_ID(qp),
			qp->attrs.state);
		*bad_wr = wr;
		return -EINVAL;
	}
	while (wr) {
		wqe = siw_wqe_alloc(qp, SIW_WR_RECEIVE);
		if (!wqe) {
			rv = -ENOMEM;
			break;
		}
		if (wr->num_sge > qp->attrs.rq_max_sges) {
			dprint(DBG_WR|DBG_ON, "(QP%d): Num SGE: %d\n",
				QP_ID(qp), wr->num_sge);
			rv = -EINVAL;
			break;
		}
		wr_type(wqe) = SIW_WR_RECEIVE;
		wr_id(wqe) = wr->wr_id;

		rv = siw_copy_sgl(wr->sg_list, wqe->wr.recv.sge, wr->num_sge);
		if (rv < 0) {
			/*
			 * XXX tentatively allow zero length receive
			 */
			rv = -EINVAL;
			break;
		}
		wqe->wr.recv.num_sge = wr->num_sge;
		wqe->bytes = rv;
		wqe->wr_status = SR_WR_QUEUED;

		lock_rq_rxsave(qp, flags);
		list_add_tail(&wqe->list, &qp->rq);
		unlock_rq_rxsave(qp, flags);

		wr = wr->next;
	}
	if (rv <= 0) {
		dprint(DBG_WR|DBG_ON, "(QP%d): error=%d\n", QP_ID(qp), rv);
		if (wqe != NULL)
			siw_wqe_put(wqe);
		*bad_wr = wr;
	}
	dprint(DBG_WR|DBG_RX, "(QP%d): rq_space=%d\n", QP_ID(qp),
		atomic_read(&qp->rq_space));

	up_read(&qp->state_lock);

	return rv > 0 ? 0 : rv;
}