diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2010-12-09 12:17:25 -0500 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2010-12-09 12:17:25 -0500 |
commit | d834a9dcecae834cd6b2bc5e50e1907738d9cf6a (patch) | |
tree | 0589d753465d3fe359ba451ba6cb7798df03aaa2 /net/9p | |
parent | a38c5380ef9f088be9f49b6e4c5d80af8b1b5cd4 (diff) | |
parent | f658bcfb2607bf0808966a69cf74135ce98e5c2d (diff) |
Merge branch 'x86/amd-nb' into x86/apic-cleanups
Reason: apic cleanup series depends on x86/apic, x86/amd-nb x86/platform
Conflicts:
arch/x86/include/asm/io_apic.h
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'net/9p')
-rw-r--r-- | net/9p/client.c | 233 | ||||
-rw-r--r-- | net/9p/protocol.c | 5 | ||||
-rw-r--r-- | net/9p/trans_fd.c | 2 | ||||
-rw-r--r-- | net/9p/trans_virtio.c | 76 |
4 files changed, 224 insertions, 92 deletions
diff --git a/net/9p/client.c b/net/9p/client.c index 9eb72505308f..a848bca9fbff 100644 --- a/net/9p/client.c +++ b/net/9p/client.c | |||
@@ -61,13 +61,13 @@ static const match_table_t tokens = { | |||
61 | 61 | ||
62 | inline int p9_is_proto_dotl(struct p9_client *clnt) | 62 | inline int p9_is_proto_dotl(struct p9_client *clnt) |
63 | { | 63 | { |
64 | return (clnt->proto_version == p9_proto_2000L); | 64 | return clnt->proto_version == p9_proto_2000L; |
65 | } | 65 | } |
66 | EXPORT_SYMBOL(p9_is_proto_dotl); | 66 | EXPORT_SYMBOL(p9_is_proto_dotl); |
67 | 67 | ||
68 | inline int p9_is_proto_dotu(struct p9_client *clnt) | 68 | inline int p9_is_proto_dotu(struct p9_client *clnt) |
69 | { | 69 | { |
70 | return (clnt->proto_version == p9_proto_2000u); | 70 | return clnt->proto_version == p9_proto_2000u; |
71 | } | 71 | } |
72 | EXPORT_SYMBOL(p9_is_proto_dotu); | 72 | EXPORT_SYMBOL(p9_is_proto_dotu); |
73 | 73 | ||
@@ -450,32 +450,43 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req) | |||
450 | return err; | 450 | return err; |
451 | } | 451 | } |
452 | 452 | ||
453 | if (type == P9_RERROR) { | 453 | if (type == P9_RERROR || type == P9_RLERROR) { |
454 | int ecode; | 454 | int ecode; |
455 | char *ename; | ||
456 | 455 | ||
457 | err = p9pdu_readf(req->rc, c->proto_version, "s?d", | 456 | if (!p9_is_proto_dotl(c)) { |
458 | &ename, &ecode); | 457 | char *ename; |
459 | if (err) { | ||
460 | P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse error%d\n", | ||
461 | err); | ||
462 | return err; | ||
463 | } | ||
464 | 458 | ||
465 | if (p9_is_proto_dotu(c) || | 459 | err = p9pdu_readf(req->rc, c->proto_version, "s?d", |
466 | p9_is_proto_dotl(c)) | 460 | &ename, &ecode); |
467 | err = -ecode; | 461 | if (err) |
462 | goto out_err; | ||
463 | |||
464 | if (p9_is_proto_dotu(c)) | ||
465 | err = -ecode; | ||
468 | 466 | ||
469 | if (!err || !IS_ERR_VALUE(err)) | 467 | if (!err || !IS_ERR_VALUE(err)) { |
470 | err = p9_errstr2errno(ename, strlen(ename)); | 468 | err = p9_errstr2errno(ename, strlen(ename)); |
469 | |||
470 | P9_DPRINTK(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", -ecode, ename); | ||
471 | |||
472 | kfree(ename); | ||
473 | } | ||
474 | } else { | ||
475 | err = p9pdu_readf(req->rc, c->proto_version, "d", &ecode); | ||
476 | err = -ecode; | ||
471 | 477 | ||
472 | P9_DPRINTK(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", -ecode, ename); | 478 | P9_DPRINTK(P9_DEBUG_9P, "<<< RLERROR (%d)\n", -ecode); |
479 | } | ||
473 | 480 | ||
474 | kfree(ename); | ||
475 | } else | 481 | } else |
476 | err = 0; | 482 | err = 0; |
477 | 483 | ||
478 | return err; | 484 | return err; |
485 | |||
486 | out_err: | ||
487 | P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse error%d\n", err); | ||
488 | |||
489 | return err; | ||
479 | } | 490 | } |
480 | 491 | ||
481 | /** | 492 | /** |
@@ -568,11 +579,14 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) | |||
568 | va_start(ap, fmt); | 579 | va_start(ap, fmt); |
569 | err = p9pdu_vwritef(req->tc, c->proto_version, fmt, ap); | 580 | err = p9pdu_vwritef(req->tc, c->proto_version, fmt, ap); |
570 | va_end(ap); | 581 | va_end(ap); |
582 | if (err) | ||
583 | goto reterr; | ||
571 | p9pdu_finalize(req->tc); | 584 | p9pdu_finalize(req->tc); |
572 | 585 | ||
573 | err = c->trans_mod->request(c, req); | 586 | err = c->trans_mod->request(c, req); |
574 | if (err < 0) { | 587 | if (err < 0) { |
575 | c->status = Disconnected; | 588 | if (err != -ERESTARTSYS) |
589 | c->status = Disconnected; | ||
576 | goto reterr; | 590 | goto reterr; |
577 | } | 591 | } |
578 | 592 | ||
@@ -671,7 +685,7 @@ static void p9_fid_destroy(struct p9_fid *fid) | |||
671 | kfree(fid); | 685 | kfree(fid); |
672 | } | 686 | } |
673 | 687 | ||
674 | int p9_client_version(struct p9_client *c) | 688 | static int p9_client_version(struct p9_client *c) |
675 | { | 689 | { |
676 | int err = 0; | 690 | int err = 0; |
677 | struct p9_req_t *req; | 691 | struct p9_req_t *req; |
@@ -730,7 +744,6 @@ error: | |||
730 | 744 | ||
731 | return err; | 745 | return err; |
732 | } | 746 | } |
733 | EXPORT_SYMBOL(p9_client_version); | ||
734 | 747 | ||
735 | struct p9_client *p9_client_create(const char *dev_name, char *options) | 748 | struct p9_client *p9_client_create(const char *dev_name, char *options) |
736 | { | 749 | { |
@@ -887,54 +900,6 @@ error: | |||
887 | } | 900 | } |
888 | EXPORT_SYMBOL(p9_client_attach); | 901 | EXPORT_SYMBOL(p9_client_attach); |
889 | 902 | ||
890 | struct p9_fid * | ||
891 | p9_client_auth(struct p9_client *clnt, char *uname, u32 n_uname, char *aname) | ||
892 | { | ||
893 | int err; | ||
894 | struct p9_req_t *req; | ||
895 | struct p9_qid qid; | ||
896 | struct p9_fid *afid; | ||
897 | |||
898 | P9_DPRINTK(P9_DEBUG_9P, ">>> TAUTH uname %s aname %s\n", uname, aname); | ||
899 | err = 0; | ||
900 | |||
901 | afid = p9_fid_create(clnt); | ||
902 | if (IS_ERR(afid)) { | ||
903 | err = PTR_ERR(afid); | ||
904 | afid = NULL; | ||
905 | goto error; | ||
906 | } | ||
907 | |||
908 | req = p9_client_rpc(clnt, P9_TAUTH, "dss?d", | ||
909 | afid ? afid->fid : P9_NOFID, uname, aname, n_uname); | ||
910 | if (IS_ERR(req)) { | ||
911 | err = PTR_ERR(req); | ||
912 | goto error; | ||
913 | } | ||
914 | |||
915 | err = p9pdu_readf(req->rc, clnt->proto_version, "Q", &qid); | ||
916 | if (err) { | ||
917 | p9pdu_dump(1, req->rc); | ||
918 | p9_free_req(clnt, req); | ||
919 | goto error; | ||
920 | } | ||
921 | |||
922 | P9_DPRINTK(P9_DEBUG_9P, "<<< RAUTH qid %x.%llx.%x\n", | ||
923 | qid.type, | ||
924 | (unsigned long long)qid.path, | ||
925 | qid.version); | ||
926 | |||
927 | memmove(&afid->qid, &qid, sizeof(struct p9_qid)); | ||
928 | p9_free_req(clnt, req); | ||
929 | return afid; | ||
930 | |||
931 | error: | ||
932 | if (afid) | ||
933 | p9_fid_destroy(afid); | ||
934 | return ERR_PTR(err); | ||
935 | } | ||
936 | EXPORT_SYMBOL(p9_client_auth); | ||
937 | |||
938 | struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames, | 903 | struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames, |
939 | int clone) | 904 | int clone) |
940 | { | 905 | { |
@@ -1200,12 +1165,44 @@ int p9_client_link(struct p9_fid *dfid, struct p9_fid *oldfid, char *newname) | |||
1200 | } | 1165 | } |
1201 | EXPORT_SYMBOL(p9_client_link); | 1166 | EXPORT_SYMBOL(p9_client_link); |
1202 | 1167 | ||
1168 | int p9_client_fsync(struct p9_fid *fid, int datasync) | ||
1169 | { | ||
1170 | int err; | ||
1171 | struct p9_client *clnt; | ||
1172 | struct p9_req_t *req; | ||
1173 | |||
1174 | P9_DPRINTK(P9_DEBUG_9P, ">>> TFSYNC fid %d datasync:%d\n", | ||
1175 | fid->fid, datasync); | ||
1176 | err = 0; | ||
1177 | clnt = fid->clnt; | ||
1178 | |||
1179 | req = p9_client_rpc(clnt, P9_TFSYNC, "dd", fid->fid, datasync); | ||
1180 | if (IS_ERR(req)) { | ||
1181 | err = PTR_ERR(req); | ||
1182 | goto error; | ||
1183 | } | ||
1184 | |||
1185 | P9_DPRINTK(P9_DEBUG_9P, "<<< RFSYNC fid %d\n", fid->fid); | ||
1186 | |||
1187 | p9_free_req(clnt, req); | ||
1188 | |||
1189 | error: | ||
1190 | return err; | ||
1191 | } | ||
1192 | EXPORT_SYMBOL(p9_client_fsync); | ||
1193 | |||
1203 | int p9_client_clunk(struct p9_fid *fid) | 1194 | int p9_client_clunk(struct p9_fid *fid) |
1204 | { | 1195 | { |
1205 | int err; | 1196 | int err; |
1206 | struct p9_client *clnt; | 1197 | struct p9_client *clnt; |
1207 | struct p9_req_t *req; | 1198 | struct p9_req_t *req; |
1208 | 1199 | ||
1200 | if (!fid) { | ||
1201 | P9_EPRINTK(KERN_WARNING, "Trying to clunk with NULL fid\n"); | ||
1202 | dump_stack(); | ||
1203 | return 0; | ||
1204 | } | ||
1205 | |||
1209 | P9_DPRINTK(P9_DEBUG_9P, ">>> TCLUNK fid %d\n", fid->fid); | 1206 | P9_DPRINTK(P9_DEBUG_9P, ">>> TCLUNK fid %d\n", fid->fid); |
1210 | err = 0; | 1207 | err = 0; |
1211 | clnt = fid->clnt; | 1208 | clnt = fid->clnt; |
@@ -1289,16 +1286,13 @@ p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset, | |||
1289 | 1286 | ||
1290 | if (data) { | 1287 | if (data) { |
1291 | memmove(data, dataptr, count); | 1288 | memmove(data, dataptr, count); |
1292 | } | 1289 | } else { |
1293 | |||
1294 | if (udata) { | ||
1295 | err = copy_to_user(udata, dataptr, count); | 1290 | err = copy_to_user(udata, dataptr, count); |
1296 | if (err) { | 1291 | if (err) { |
1297 | err = -EFAULT; | 1292 | err = -EFAULT; |
1298 | goto free_and_error; | 1293 | goto free_and_error; |
1299 | } | 1294 | } |
1300 | } | 1295 | } |
1301 | |||
1302 | p9_free_req(clnt, req); | 1296 | p9_free_req(clnt, req); |
1303 | return count; | 1297 | return count; |
1304 | 1298 | ||
@@ -1810,3 +1804,96 @@ error: | |||
1810 | 1804 | ||
1811 | } | 1805 | } |
1812 | EXPORT_SYMBOL(p9_client_mkdir_dotl); | 1806 | EXPORT_SYMBOL(p9_client_mkdir_dotl); |
1807 | |||
1808 | int p9_client_lock_dotl(struct p9_fid *fid, struct p9_flock *flock, u8 *status) | ||
1809 | { | ||
1810 | int err; | ||
1811 | struct p9_client *clnt; | ||
1812 | struct p9_req_t *req; | ||
1813 | |||
1814 | err = 0; | ||
1815 | clnt = fid->clnt; | ||
1816 | P9_DPRINTK(P9_DEBUG_9P, ">>> TLOCK fid %d type %i flags %d " | ||
1817 | "start %lld length %lld proc_id %d client_id %s\n", | ||
1818 | fid->fid, flock->type, flock->flags, flock->start, | ||
1819 | flock->length, flock->proc_id, flock->client_id); | ||
1820 | |||
1821 | req = p9_client_rpc(clnt, P9_TLOCK, "dbdqqds", fid->fid, flock->type, | ||
1822 | flock->flags, flock->start, flock->length, | ||
1823 | flock->proc_id, flock->client_id); | ||
1824 | |||
1825 | if (IS_ERR(req)) | ||
1826 | return PTR_ERR(req); | ||
1827 | |||
1828 | err = p9pdu_readf(req->rc, clnt->proto_version, "b", status); | ||
1829 | if (err) { | ||
1830 | p9pdu_dump(1, req->rc); | ||
1831 | goto error; | ||
1832 | } | ||
1833 | P9_DPRINTK(P9_DEBUG_9P, "<<< RLOCK status %i\n", *status); | ||
1834 | error: | ||
1835 | p9_free_req(clnt, req); | ||
1836 | return err; | ||
1837 | |||
1838 | } | ||
1839 | EXPORT_SYMBOL(p9_client_lock_dotl); | ||
1840 | |||
1841 | int p9_client_getlock_dotl(struct p9_fid *fid, struct p9_getlock *glock) | ||
1842 | { | ||
1843 | int err; | ||
1844 | struct p9_client *clnt; | ||
1845 | struct p9_req_t *req; | ||
1846 | |||
1847 | err = 0; | ||
1848 | clnt = fid->clnt; | ||
1849 | P9_DPRINTK(P9_DEBUG_9P, ">>> TGETLOCK fid %d, type %i start %lld " | ||
1850 | "length %lld proc_id %d client_id %s\n", fid->fid, glock->type, | ||
1851 | glock->start, glock->length, glock->proc_id, glock->client_id); | ||
1852 | |||
1853 | req = p9_client_rpc(clnt, P9_TGETLOCK, "dbqqds", fid->fid, glock->type, | ||
1854 | glock->start, glock->length, glock->proc_id, glock->client_id); | ||
1855 | |||
1856 | if (IS_ERR(req)) | ||
1857 | return PTR_ERR(req); | ||
1858 | |||
1859 | err = p9pdu_readf(req->rc, clnt->proto_version, "bqqds", &glock->type, | ||
1860 | &glock->start, &glock->length, &glock->proc_id, | ||
1861 | &glock->client_id); | ||
1862 | if (err) { | ||
1863 | p9pdu_dump(1, req->rc); | ||
1864 | goto error; | ||
1865 | } | ||
1866 | P9_DPRINTK(P9_DEBUG_9P, "<<< RGETLOCK type %i start %lld length %lld " | ||
1867 | "proc_id %d client_id %s\n", glock->type, glock->start, | ||
1868 | glock->length, glock->proc_id, glock->client_id); | ||
1869 | error: | ||
1870 | p9_free_req(clnt, req); | ||
1871 | return err; | ||
1872 | } | ||
1873 | EXPORT_SYMBOL(p9_client_getlock_dotl); | ||
1874 | |||
1875 | int p9_client_readlink(struct p9_fid *fid, char **target) | ||
1876 | { | ||
1877 | int err; | ||
1878 | struct p9_client *clnt; | ||
1879 | struct p9_req_t *req; | ||
1880 | |||
1881 | err = 0; | ||
1882 | clnt = fid->clnt; | ||
1883 | P9_DPRINTK(P9_DEBUG_9P, ">>> TREADLINK fid %d\n", fid->fid); | ||
1884 | |||
1885 | req = p9_client_rpc(clnt, P9_TREADLINK, "d", fid->fid); | ||
1886 | if (IS_ERR(req)) | ||
1887 | return PTR_ERR(req); | ||
1888 | |||
1889 | err = p9pdu_readf(req->rc, clnt->proto_version, "s", target); | ||
1890 | if (err) { | ||
1891 | p9pdu_dump(1, req->rc); | ||
1892 | goto error; | ||
1893 | } | ||
1894 | P9_DPRINTK(P9_DEBUG_9P, "<<< RREADLINK target %s\n", *target); | ||
1895 | error: | ||
1896 | p9_free_req(clnt, req); | ||
1897 | return err; | ||
1898 | } | ||
1899 | EXPORT_SYMBOL(p9_client_readlink); | ||
diff --git a/net/9p/protocol.c b/net/9p/protocol.c index 3acd3afb20c8..45c15f491401 100644 --- a/net/9p/protocol.c +++ b/net/9p/protocol.c | |||
@@ -122,9 +122,8 @@ static size_t | |||
122 | pdu_write_u(struct p9_fcall *pdu, const char __user *udata, size_t size) | 122 | pdu_write_u(struct p9_fcall *pdu, const char __user *udata, size_t size) |
123 | { | 123 | { |
124 | size_t len = MIN(pdu->capacity - pdu->size, size); | 124 | size_t len = MIN(pdu->capacity - pdu->size, size); |
125 | int err = copy_from_user(&pdu->sdata[pdu->size], udata, len); | 125 | if (copy_from_user(&pdu->sdata[pdu->size], udata, len)) |
126 | if (err) | 126 | len = 0; |
127 | printk(KERN_WARNING "pdu_write_u returning: %d\n", err); | ||
128 | 127 | ||
129 | pdu->size += len; | 128 | pdu->size += len; |
130 | return size - len; | 129 | return size - len; |
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index c85109d809ca..078eb162d9bf 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c | |||
@@ -222,7 +222,7 @@ static void p9_conn_cancel(struct p9_conn *m, int err) | |||
222 | } | 222 | } |
223 | } | 223 | } |
224 | 224 | ||
225 | static unsigned int | 225 | static int |
226 | p9_fd_poll(struct p9_client *client, struct poll_table_struct *pt) | 226 | p9_fd_poll(struct p9_client *client, struct poll_table_struct *pt) |
227 | { | 227 | { |
228 | int ret, n; | 228 | int ret, n; |
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index b88515936e4b..c8f3f72ab20e 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c | |||
@@ -75,6 +75,8 @@ struct virtio_chan { | |||
75 | struct p9_client *client; | 75 | struct p9_client *client; |
76 | struct virtio_device *vdev; | 76 | struct virtio_device *vdev; |
77 | struct virtqueue *vq; | 77 | struct virtqueue *vq; |
78 | int ring_bufs_avail; | ||
79 | wait_queue_head_t *vc_wq; | ||
78 | 80 | ||
79 | /* Scatterlist: can be too big for stack. */ | 81 | /* Scatterlist: can be too big for stack. */ |
80 | struct scatterlist sg[VIRTQUEUE_NUM]; | 82 | struct scatterlist sg[VIRTQUEUE_NUM]; |
@@ -134,16 +136,30 @@ static void req_done(struct virtqueue *vq) | |||
134 | struct p9_fcall *rc; | 136 | struct p9_fcall *rc; |
135 | unsigned int len; | 137 | unsigned int len; |
136 | struct p9_req_t *req; | 138 | struct p9_req_t *req; |
139 | unsigned long flags; | ||
137 | 140 | ||
138 | P9_DPRINTK(P9_DEBUG_TRANS, ": request done\n"); | 141 | P9_DPRINTK(P9_DEBUG_TRANS, ": request done\n"); |
139 | 142 | ||
140 | while ((rc = virtqueue_get_buf(chan->vq, &len)) != NULL) { | 143 | do { |
141 | P9_DPRINTK(P9_DEBUG_TRANS, ": rc %p\n", rc); | 144 | spin_lock_irqsave(&chan->lock, flags); |
142 | P9_DPRINTK(P9_DEBUG_TRANS, ": lookup tag %d\n", rc->tag); | 145 | rc = virtqueue_get_buf(chan->vq, &len); |
143 | req = p9_tag_lookup(chan->client, rc->tag); | 146 | |
144 | req->status = REQ_STATUS_RCVD; | 147 | if (rc != NULL) { |
145 | p9_client_cb(chan->client, req); | 148 | if (!chan->ring_bufs_avail) { |
146 | } | 149 | chan->ring_bufs_avail = 1; |
150 | wake_up(chan->vc_wq); | ||
151 | } | ||
152 | spin_unlock_irqrestore(&chan->lock, flags); | ||
153 | P9_DPRINTK(P9_DEBUG_TRANS, ": rc %p\n", rc); | ||
154 | P9_DPRINTK(P9_DEBUG_TRANS, ": lookup tag %d\n", | ||
155 | rc->tag); | ||
156 | req = p9_tag_lookup(chan->client, rc->tag); | ||
157 | req->status = REQ_STATUS_RCVD; | ||
158 | p9_client_cb(chan->client, req); | ||
159 | } else { | ||
160 | spin_unlock_irqrestore(&chan->lock, flags); | ||
161 | } | ||
162 | } while (rc != NULL); | ||
147 | } | 163 | } |
148 | 164 | ||
149 | /** | 165 | /** |
@@ -199,23 +215,43 @@ p9_virtio_request(struct p9_client *client, struct p9_req_t *req) | |||
199 | int in, out; | 215 | int in, out; |
200 | struct virtio_chan *chan = client->trans; | 216 | struct virtio_chan *chan = client->trans; |
201 | char *rdata = (char *)req->rc+sizeof(struct p9_fcall); | 217 | char *rdata = (char *)req->rc+sizeof(struct p9_fcall); |
218 | unsigned long flags; | ||
219 | int err; | ||
202 | 220 | ||
203 | P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio request\n"); | 221 | P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio request\n"); |
204 | 222 | ||
223 | req_retry: | ||
224 | req->status = REQ_STATUS_SENT; | ||
225 | |||
226 | spin_lock_irqsave(&chan->lock, flags); | ||
205 | out = pack_sg_list(chan->sg, 0, VIRTQUEUE_NUM, req->tc->sdata, | 227 | out = pack_sg_list(chan->sg, 0, VIRTQUEUE_NUM, req->tc->sdata, |
206 | req->tc->size); | 228 | req->tc->size); |
207 | in = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM-out, rdata, | 229 | in = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM-out, rdata, |
208 | client->msize); | 230 | client->msize); |
209 | 231 | ||
210 | req->status = REQ_STATUS_SENT; | 232 | err = virtqueue_add_buf(chan->vq, chan->sg, out, in, req->tc); |
211 | 233 | if (err < 0) { | |
212 | if (virtqueue_add_buf(chan->vq, chan->sg, out, in, req->tc) < 0) { | 234 | if (err == -ENOSPC) { |
213 | P9_DPRINTK(P9_DEBUG_TRANS, | 235 | chan->ring_bufs_avail = 0; |
214 | "9p debug: virtio rpc add_buf returned failure"); | 236 | spin_unlock_irqrestore(&chan->lock, flags); |
215 | return -EIO; | 237 | err = wait_event_interruptible(*chan->vc_wq, |
238 | chan->ring_bufs_avail); | ||
239 | if (err == -ERESTARTSYS) | ||
240 | return err; | ||
241 | |||
242 | P9_DPRINTK(P9_DEBUG_TRANS, "9p:Retry virtio request\n"); | ||
243 | goto req_retry; | ||
244 | } else { | ||
245 | spin_unlock_irqrestore(&chan->lock, flags); | ||
246 | P9_DPRINTK(P9_DEBUG_TRANS, | ||
247 | "9p debug: " | ||
248 | "virtio rpc add_buf returned failure"); | ||
249 | return -EIO; | ||
250 | } | ||
216 | } | 251 | } |
217 | 252 | ||
218 | virtqueue_kick(chan->vq); | 253 | virtqueue_kick(chan->vq); |
254 | spin_unlock_irqrestore(&chan->lock, flags); | ||
219 | 255 | ||
220 | P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio request kicked\n"); | 256 | P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio request kicked\n"); |
221 | return 0; | 257 | return 0; |
@@ -290,14 +326,23 @@ static int p9_virtio_probe(struct virtio_device *vdev) | |||
290 | chan->tag_len = tag_len; | 326 | chan->tag_len = tag_len; |
291 | err = sysfs_create_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); | 327 | err = sysfs_create_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); |
292 | if (err) { | 328 | if (err) { |
293 | kfree(tag); | 329 | goto out_free_tag; |
294 | goto out_free_vq; | ||
295 | } | 330 | } |
331 | chan->vc_wq = kmalloc(sizeof(wait_queue_head_t), GFP_KERNEL); | ||
332 | if (!chan->vc_wq) { | ||
333 | err = -ENOMEM; | ||
334 | goto out_free_tag; | ||
335 | } | ||
336 | init_waitqueue_head(chan->vc_wq); | ||
337 | chan->ring_bufs_avail = 1; | ||
338 | |||
296 | mutex_lock(&virtio_9p_lock); | 339 | mutex_lock(&virtio_9p_lock); |
297 | list_add_tail(&chan->chan_list, &virtio_chan_list); | 340 | list_add_tail(&chan->chan_list, &virtio_chan_list); |
298 | mutex_unlock(&virtio_9p_lock); | 341 | mutex_unlock(&virtio_9p_lock); |
299 | return 0; | 342 | return 0; |
300 | 343 | ||
344 | out_free_tag: | ||
345 | kfree(tag); | ||
301 | out_free_vq: | 346 | out_free_vq: |
302 | vdev->config->del_vqs(vdev); | 347 | vdev->config->del_vqs(vdev); |
303 | kfree(chan); | 348 | kfree(chan); |
@@ -371,6 +416,7 @@ static void p9_virtio_remove(struct virtio_device *vdev) | |||
371 | mutex_unlock(&virtio_9p_lock); | 416 | mutex_unlock(&virtio_9p_lock); |
372 | sysfs_remove_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); | 417 | sysfs_remove_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); |
373 | kfree(chan->tag); | 418 | kfree(chan->tag); |
419 | kfree(chan->vc_wq); | ||
374 | kfree(chan); | 420 | kfree(chan); |
375 | 421 | ||
376 | } | 422 | } |