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; }
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); }
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; }
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; }
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; }
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; }
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; }