aboutsummaryrefslogtreecommitdiffstats
path: root/net/9p
diff options
context:
space:
mode:
authorVenkateswararao Jujjuri (JV) <jvrao@linux.vnet.ibm.com>2010-09-29 21:06:54 -0400
committerEric Van Hensbergen <ericvh@gmail.com>2010-10-28 10:08:48 -0400
commit419b39561e698d73a42f8010655d22e0134486da (patch)
tree76b6bd98dcaaa89d27b2d804d1ed67f049f070bd /net/9p
parent329176cc2c50e63c580ddaabb385876db5af1360 (diff)
[net/9p]Serialize virtqueue operations to make VirtIO transport SMP safe.
Signed-off-by: Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com> Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
Diffstat (limited to 'net/9p')
-rw-r--r--net/9p/trans_virtio.c34
1 files changed, 24 insertions, 10 deletions
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c
index b88515936e4b..8ae08596aad8 100644
--- a/net/9p/trans_virtio.c
+++ b/net/9p/trans_virtio.c
@@ -134,16 +134,24 @@ static void req_done(struct virtqueue *vq)
134 struct p9_fcall *rc; 134 struct p9_fcall *rc;
135 unsigned int len; 135 unsigned int len;
136 struct p9_req_t *req; 136 struct p9_req_t *req;
137 unsigned long flags;
137 138
138 P9_DPRINTK(P9_DEBUG_TRANS, ": request done\n"); 139 P9_DPRINTK(P9_DEBUG_TRANS, ": request done\n");
139 140
140 while ((rc = virtqueue_get_buf(chan->vq, &len)) != NULL) { 141 do {
141 P9_DPRINTK(P9_DEBUG_TRANS, ": rc %p\n", rc); 142 spin_lock_irqsave(&chan->lock, flags);
142 P9_DPRINTK(P9_DEBUG_TRANS, ": lookup tag %d\n", rc->tag); 143 rc = virtqueue_get_buf(chan->vq, &len);
143 req = p9_tag_lookup(chan->client, rc->tag); 144 spin_unlock_irqrestore(&chan->lock, flags);
144 req->status = REQ_STATUS_RCVD; 145
145 p9_client_cb(chan->client, req); 146 if (rc != NULL) {
146 } 147 P9_DPRINTK(P9_DEBUG_TRANS, ": rc %p\n", rc);
148 P9_DPRINTK(P9_DEBUG_TRANS, ": lookup tag %d\n",
149 rc->tag);
150 req = p9_tag_lookup(chan->client, rc->tag);
151 req->status = REQ_STATUS_RCVD;
152 p9_client_cb(chan->client, req);
153 }
154 } while (rc != NULL);
147} 155}
148 156
149/** 157/**
@@ -199,23 +207,29 @@ p9_virtio_request(struct p9_client *client, struct p9_req_t *req)
199 int in, out; 207 int in, out;
200 struct virtio_chan *chan = client->trans; 208 struct virtio_chan *chan = client->trans;
201 char *rdata = (char *)req->rc+sizeof(struct p9_fcall); 209 char *rdata = (char *)req->rc+sizeof(struct p9_fcall);
210 unsigned long flags;
211 int err;
202 212
203 P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio request\n"); 213 P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio request\n");
204 214
215 req->status = REQ_STATUS_SENT;
216
217 spin_lock_irqsave(&chan->lock, flags);
205 out = pack_sg_list(chan->sg, 0, VIRTQUEUE_NUM, req->tc->sdata, 218 out = pack_sg_list(chan->sg, 0, VIRTQUEUE_NUM, req->tc->sdata,
206 req->tc->size); 219 req->tc->size);
207 in = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM-out, rdata, 220 in = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM-out, rdata,
208 client->msize); 221 client->msize);
209 222
210 req->status = REQ_STATUS_SENT; 223 err = virtqueue_add_buf(chan->vq, chan->sg, out, in, req->tc);
211 224 if (err < 0) {
212 if (virtqueue_add_buf(chan->vq, chan->sg, out, in, req->tc) < 0) { 225 spin_unlock_irqrestore(&chan->lock, flags);
213 P9_DPRINTK(P9_DEBUG_TRANS, 226 P9_DPRINTK(P9_DEBUG_TRANS,
214 "9p debug: virtio rpc add_buf returned failure"); 227 "9p debug: virtio rpc add_buf returned failure");
215 return -EIO; 228 return -EIO;
216 } 229 }
217 230
218 virtqueue_kick(chan->vq); 231 virtqueue_kick(chan->vq);
232 spin_unlock_irqrestore(&chan->lock, flags);
219 233
220 P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio request kicked\n"); 234 P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio request kicked\n");
221 return 0; 235 return 0;