static void
handle_recv(struct p9_client *client, struct p9_trans_rdma *rdma,
	    struct p9_rdma_context *c, enum ib_wc_status status, u32 byte_len)
{
	struct p9_req_t *req;
	int err = 0;
	int16_t tag;

	req = NULL;
	ib_dma_unmap_single(rdma->cm_id->device, c->busa, client->msize,
							 DMA_FROM_DEVICE);

	if (status != IB_WC_SUCCESS)
		goto err_out;

	err = p9_parse_header(c->rc, NULL, NULL, &tag, 1);
	if (err)
		goto err_out;

	req = p9_tag_lookup(client, tag);
	if (!req)
		goto err_out;

	req->rc = c->rc;
	p9_client_cb(client, req);

	return;

 err_out:
	P9_DPRINTK(P9_DEBUG_ERROR, "req %p err %d status %d\n",
		   req, err, status);
	rdma->state = P9_RDMA_FLUSHING;
	client->status = Disconnected;
	return;
}
Esempio n. 2
0
static void p9_xosclient_rerror(struct p9_req_t *req)
{
	struct p9_fcall *rcall;
	u16 tag;
	struct p9_xos_device *dev = (struct p9_xos_device *)req->aux;
	struct p9_xos_endpoint *ep = &dev->driver->ep[RD_EP];
	unsigned long flags;

	if (p9_parse_header(req->tc, &req->tc->size, &req->tc->id, &tag, 1))
		warning("Failed to decode header !");
	kfree(req->tc);
	spin_lock_irqsave(&dev->driver->ep_lock, flags);
	p9_xos_deque_push(ep->rqueue, a2n(req->tc->sdata - 8, ep), ep);
	nb_free_packets++;
	spin_unlock_irqrestore(&dev->driver->ep_lock, flags);

	rcall = kmalloc(sizeof(struct p9_fcall) + 32, GFP_KERNEL);
	p9pdu_reset(rcall);
	rcall->sdata = (u8 *) (rcall + sizeof(struct p9_fcall));
	p9pdu_writef(rcall, 0, "dbwT", 0, P9_RERROR, tag,
		     "9P destination service closed");
	p9pdu_finalize(rcall);

	req->rc = rcall;
	req->tc = NULL;

	spin_lock(&dev->lock);
	dev->ack_count += 1;
	spin_unlock(&dev->lock);

	p9_xos_add_write_request(req, 0);
}
Esempio n. 3
0
static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq)
{
	struct p9_req_t *req;
	int16_t oldtag;
	int err;

	err = p9_parse_header(oldreq->tc, NULL, NULL, &oldtag, 1);
	if (err)
		return err;

	P9_DPRINTK(P9_DEBUG_9P, ">>> TFLUSH tag %d\n", oldtag);

	req = p9_client_rpc(c, P9_TFLUSH, "w", oldtag);
	if (IS_ERR(req))
		return PTR_ERR(req);


	/* if we haven't received a response for oldreq,
	   remove it from the list. */
	spin_lock(&c->lock);
	if (oldreq->status == REQ_STATUS_FLSH)
		list_del(&oldreq->req_list);
	spin_unlock(&c->lock);

	p9_free_req(c, req);
	return 0;
}
Esempio n. 4
0
static void
recv_done(struct ib_cq *cq, struct ib_wc *wc)
{
	struct p9_client *client = cq->cq_context;
	struct p9_trans_rdma *rdma = client->trans;
	struct p9_rdma_context *c =
		container_of(wc->wr_cqe, struct p9_rdma_context, cqe);
	struct p9_req_t *req;
	int err = 0;
	int16_t tag;

	req = NULL;
	ib_dma_unmap_single(rdma->cm_id->device, c->busa, client->msize,
							 DMA_FROM_DEVICE);

	if (wc->status != IB_WC_SUCCESS)
		goto err_out;

	c->rc.size = wc->byte_len;
	err = p9_parse_header(&c->rc, NULL, NULL, &tag, 1);
	if (err)
		goto err_out;

	req = p9_tag_lookup(client, tag);
	if (!req)
		goto err_out;

	/* Check that we have not yet received a reply for this request.
	 */
	if (unlikely(req->rc.sdata)) {
		pr_err("Duplicate reply for request %d", tag);
		goto err_out;
	}

	req->rc.size = c->rc.size;
	req->rc.sdata = c->rc.sdata;
	p9_client_cb(client, req, REQ_STATUS_RCVD);

 out:
	up(&rdma->rq_sem);
	kfree(c);
	return;

 err_out:
	p9_debug(P9_DEBUG_ERROR, "req %p err %d status %d\n",
			req, err, wc->status);
	rdma->state = P9_RDMA_FLUSHING;
	client->status = Disconnected;
	goto out;
}
Esempio n. 5
0
static int p9_check_errors(struct p9_client *c, struct p9_req_t *req)
{
	int8_t type;
	int err;

	err = p9_parse_header(req->rc, NULL, &type, NULL, 0);
	if (err) {
		P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse header %d\n", err);
		return err;
	}

	if (type == P9_RERROR) {
		int ecode;
		char *ename;

		err = p9pdu_readf(req->rc, c->dotu, "s?d", &ename, &ecode);
		if (err) {
			P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse error%d\n",
									err);
			return err;
		}

		if (c->dotu)
			err = -ecode;

		if (!err) {
			err = p9_errstr2errno(ename, strlen(ename));

			/* string match failed */
			if (!err)
				err = -ESERVERFAULT;
		}

		P9_DPRINTK(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", -ecode, ename);

		kfree(ename);
	} else
		err = 0;

	return err;
}
Esempio n. 6
0
static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq)
{
	struct p9_req_t *req;
	int16_t oldtag;
	int err;

	err = p9_parse_header(oldreq->tc, NULL, NULL, &oldtag, 1);
	if (err)
		return err;

	P9_DPRINTK(P9_DEBUG_9P, ">>> TFLUSH tag %d\n", oldtag);

	req = p9_client_rpc(c, P9_TFLUSH, "w", oldtag);
	if (IS_ERR(req))
		return PTR_ERR(req);

	req->flush_tag = oldtag;

	/* we don't free anything here because RPC isn't complete */
	return 0;
}
Esempio n. 7
0
static void
handle_recv(struct p9_client *client, struct p9_trans_rdma *rdma,
	    struct p9_rdma_context *c, enum ib_wc_status status, u32 byte_len)
{
	struct p9_req_t *req;
	int err = 0;
	int16_t tag;

	req = NULL;
	ib_dma_unmap_single(rdma->cm_id->device, c->busa, client->msize,
							 DMA_FROM_DEVICE);

	if (status != IB_WC_SUCCESS)
		goto err_out;

	err = p9_parse_header(c->rc, NULL, NULL, &tag, 1);
	if (err)
		goto err_out;

	req = p9_tag_lookup(client, tag);
	if (!req)
		goto err_out;

	/* Check that we have not yet received a reply for this request.
	 */
	if (unlikely(req->rc)) {
		pr_err("Duplicate reply for request %d", tag);
		goto err_out;
	}

	req->rc = c->rc;
	p9_client_cb(client, req, REQ_STATUS_RCVD);

	return;

 err_out:
	p9_debug(P9_DEBUG_ERROR, "req %p err %d status %d\n", req, err, status);
	rdma->state = P9_RDMA_FLUSHING;
	client->status = Disconnected;
}