diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2011-11-17 16:41:14 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-11-18 14:09:07 -0500 |
commit | 52fb743d3aa7ee27a4f3182816aa02dc3e513d9d (patch) | |
tree | c4ef377d4d501a1347203fbf296bcd44cdb2a6bb /drivers/usb/core/devio.c | |
parent | 86dc243cb2ddecb6984401463ebb0963ceff3cdc (diff) |
USB: unify some error pathways in usbfs
This patch (as1496) unifies the error-return pathways of several
functions in the usbfs driver. This is not a very important change by
itself; it merely prepares the way for the next patch in this series.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/core/devio.c')
-rw-r--r-- | drivers/usb/core/devio.c | 96 |
1 files changed, 50 insertions, 46 deletions
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index e3beaf229ee..e8ade68f64e 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c | |||
@@ -806,8 +806,8 @@ static int proc_control(struct dev_state *ps, void __user *arg) | |||
806 | if (ctrl.bRequestType & 0x80) { | 806 | if (ctrl.bRequestType & 0x80) { |
807 | if (ctrl.wLength && !access_ok(VERIFY_WRITE, ctrl.data, | 807 | if (ctrl.wLength && !access_ok(VERIFY_WRITE, ctrl.data, |
808 | ctrl.wLength)) { | 808 | ctrl.wLength)) { |
809 | free_page((unsigned long)tbuf); | 809 | ret = -EINVAL; |
810 | return -EINVAL; | 810 | goto done; |
811 | } | 811 | } |
812 | pipe = usb_rcvctrlpipe(dev, 0); | 812 | pipe = usb_rcvctrlpipe(dev, 0); |
813 | snoop_urb(dev, NULL, pipe, ctrl.wLength, tmo, SUBMIT, NULL, 0); | 813 | snoop_urb(dev, NULL, pipe, ctrl.wLength, tmo, SUBMIT, NULL, 0); |
@@ -821,15 +821,15 @@ static int proc_control(struct dev_state *ps, void __user *arg) | |||
821 | tbuf, max(i, 0)); | 821 | tbuf, max(i, 0)); |
822 | if ((i > 0) && ctrl.wLength) { | 822 | if ((i > 0) && ctrl.wLength) { |
823 | if (copy_to_user(ctrl.data, tbuf, i)) { | 823 | if (copy_to_user(ctrl.data, tbuf, i)) { |
824 | free_page((unsigned long)tbuf); | 824 | ret = -EFAULT; |
825 | return -EFAULT; | 825 | goto done; |
826 | } | 826 | } |
827 | } | 827 | } |
828 | } else { | 828 | } else { |
829 | if (ctrl.wLength) { | 829 | if (ctrl.wLength) { |
830 | if (copy_from_user(tbuf, ctrl.data, ctrl.wLength)) { | 830 | if (copy_from_user(tbuf, ctrl.data, ctrl.wLength)) { |
831 | free_page((unsigned long)tbuf); | 831 | ret = -EFAULT; |
832 | return -EFAULT; | 832 | goto done; |
833 | } | 833 | } |
834 | } | 834 | } |
835 | pipe = usb_sndctrlpipe(dev, 0); | 835 | pipe = usb_sndctrlpipe(dev, 0); |
@@ -843,14 +843,16 @@ static int proc_control(struct dev_state *ps, void __user *arg) | |||
843 | usb_lock_device(dev); | 843 | usb_lock_device(dev); |
844 | snoop_urb(dev, NULL, pipe, max(i, 0), min(i, 0), COMPLETE, NULL, 0); | 844 | snoop_urb(dev, NULL, pipe, max(i, 0), min(i, 0), COMPLETE, NULL, 0); |
845 | } | 845 | } |
846 | free_page((unsigned long)tbuf); | ||
847 | if (i < 0 && i != -EPIPE) { | 846 | if (i < 0 && i != -EPIPE) { |
848 | dev_printk(KERN_DEBUG, &dev->dev, "usbfs: USBDEVFS_CONTROL " | 847 | dev_printk(KERN_DEBUG, &dev->dev, "usbfs: USBDEVFS_CONTROL " |
849 | "failed cmd %s rqt %u rq %u len %u ret %d\n", | 848 | "failed cmd %s rqt %u rq %u len %u ret %d\n", |
850 | current->comm, ctrl.bRequestType, ctrl.bRequest, | 849 | current->comm, ctrl.bRequestType, ctrl.bRequest, |
851 | ctrl.wLength, i); | 850 | ctrl.wLength, i); |
852 | } | 851 | } |
853 | return i; | 852 | ret = i; |
853 | done: | ||
854 | free_page((unsigned long) tbuf); | ||
855 | return ret; | ||
854 | } | 856 | } |
855 | 857 | ||
856 | static int proc_bulk(struct dev_state *ps, void __user *arg) | 858 | static int proc_bulk(struct dev_state *ps, void __user *arg) |
@@ -884,8 +886,8 @@ static int proc_bulk(struct dev_state *ps, void __user *arg) | |||
884 | tmo = bulk.timeout; | 886 | tmo = bulk.timeout; |
885 | if (bulk.ep & 0x80) { | 887 | if (bulk.ep & 0x80) { |
886 | if (len1 && !access_ok(VERIFY_WRITE, bulk.data, len1)) { | 888 | if (len1 && !access_ok(VERIFY_WRITE, bulk.data, len1)) { |
887 | kfree(tbuf); | 889 | ret = -EINVAL; |
888 | return -EINVAL; | 890 | goto done; |
889 | } | 891 | } |
890 | snoop_urb(dev, NULL, pipe, len1, tmo, SUBMIT, NULL, 0); | 892 | snoop_urb(dev, NULL, pipe, len1, tmo, SUBMIT, NULL, 0); |
891 | 893 | ||
@@ -896,15 +898,15 @@ static int proc_bulk(struct dev_state *ps, void __user *arg) | |||
896 | 898 | ||
897 | if (!i && len2) { | 899 | if (!i && len2) { |
898 | if (copy_to_user(bulk.data, tbuf, len2)) { | 900 | if (copy_to_user(bulk.data, tbuf, len2)) { |
899 | kfree(tbuf); | 901 | ret = -EFAULT; |
900 | return -EFAULT; | 902 | goto done; |
901 | } | 903 | } |
902 | } | 904 | } |
903 | } else { | 905 | } else { |
904 | if (len1) { | 906 | if (len1) { |
905 | if (copy_from_user(tbuf, bulk.data, len1)) { | 907 | if (copy_from_user(tbuf, bulk.data, len1)) { |
906 | kfree(tbuf); | 908 | ret = -EFAULT; |
907 | return -EFAULT; | 909 | goto done; |
908 | } | 910 | } |
909 | } | 911 | } |
910 | snoop_urb(dev, NULL, pipe, len1, tmo, SUBMIT, tbuf, len1); | 912 | snoop_urb(dev, NULL, pipe, len1, tmo, SUBMIT, tbuf, len1); |
@@ -914,10 +916,10 @@ static int proc_bulk(struct dev_state *ps, void __user *arg) | |||
914 | usb_lock_device(dev); | 916 | usb_lock_device(dev); |
915 | snoop_urb(dev, NULL, pipe, len2, i, COMPLETE, NULL, 0); | 917 | snoop_urb(dev, NULL, pipe, len2, i, COMPLETE, NULL, 0); |
916 | } | 918 | } |
919 | ret = (i < 0 ? i : len2); | ||
920 | done: | ||
917 | kfree(tbuf); | 921 | kfree(tbuf); |
918 | if (i < 0) | 922 | return ret; |
919 | return i; | ||
920 | return len2; | ||
921 | } | 923 | } |
922 | 924 | ||
923 | static int proc_resetep(struct dev_state *ps, void __user *arg) | 925 | static int proc_resetep(struct dev_state *ps, void __user *arg) |
@@ -1062,7 +1064,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, | |||
1062 | { | 1064 | { |
1063 | struct usbdevfs_iso_packet_desc *isopkt = NULL; | 1065 | struct usbdevfs_iso_packet_desc *isopkt = NULL; |
1064 | struct usb_host_endpoint *ep; | 1066 | struct usb_host_endpoint *ep; |
1065 | struct async *as; | 1067 | struct async *as = NULL; |
1066 | struct usb_ctrlrequest *dr = NULL; | 1068 | struct usb_ctrlrequest *dr = NULL; |
1067 | unsigned int u, totlen, isofrmlen; | 1069 | unsigned int u, totlen, isofrmlen; |
1068 | int ret, ifnum = -1; | 1070 | int ret, ifnum = -1; |
@@ -1108,19 +1110,17 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, | |||
1108 | if (!dr) | 1110 | if (!dr) |
1109 | return -ENOMEM; | 1111 | return -ENOMEM; |
1110 | if (copy_from_user(dr, uurb->buffer, 8)) { | 1112 | if (copy_from_user(dr, uurb->buffer, 8)) { |
1111 | kfree(dr); | 1113 | ret = -EFAULT; |
1112 | return -EFAULT; | 1114 | goto error; |
1113 | } | 1115 | } |
1114 | if (uurb->buffer_length < (le16_to_cpup(&dr->wLength) + 8)) { | 1116 | if (uurb->buffer_length < (le16_to_cpup(&dr->wLength) + 8)) { |
1115 | kfree(dr); | 1117 | ret = -EINVAL; |
1116 | return -EINVAL; | 1118 | goto error; |
1117 | } | 1119 | } |
1118 | ret = check_ctrlrecip(ps, dr->bRequestType, dr->bRequest, | 1120 | ret = check_ctrlrecip(ps, dr->bRequestType, dr->bRequest, |
1119 | le16_to_cpup(&dr->wIndex)); | 1121 | le16_to_cpup(&dr->wIndex)); |
1120 | if (ret) { | 1122 | if (ret) |
1121 | kfree(dr); | 1123 | goto error; |
1122 | return ret; | ||
1123 | } | ||
1124 | uurb->number_of_packets = 0; | 1124 | uurb->number_of_packets = 0; |
1125 | uurb->buffer_length = le16_to_cpup(&dr->wLength); | 1125 | uurb->buffer_length = le16_to_cpup(&dr->wLength); |
1126 | uurb->buffer += 8; | 1126 | uurb->buffer += 8; |
@@ -1176,22 +1176,22 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, | |||
1176 | if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL))) | 1176 | if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL))) |
1177 | return -ENOMEM; | 1177 | return -ENOMEM; |
1178 | if (copy_from_user(isopkt, iso_frame_desc, isofrmlen)) { | 1178 | if (copy_from_user(isopkt, iso_frame_desc, isofrmlen)) { |
1179 | kfree(isopkt); | 1179 | ret = -EFAULT; |
1180 | return -EFAULT; | 1180 | goto error; |
1181 | } | 1181 | } |
1182 | for (totlen = u = 0; u < uurb->number_of_packets; u++) { | 1182 | for (totlen = u = 0; u < uurb->number_of_packets; u++) { |
1183 | /* arbitrary limit, | 1183 | /* arbitrary limit, |
1184 | * sufficient for USB 2.0 high-bandwidth iso */ | 1184 | * sufficient for USB 2.0 high-bandwidth iso */ |
1185 | if (isopkt[u].length > 8192) { | 1185 | if (isopkt[u].length > 8192) { |
1186 | kfree(isopkt); | 1186 | ret = -EINVAL; |
1187 | return -EINVAL; | 1187 | goto error; |
1188 | } | 1188 | } |
1189 | totlen += isopkt[u].length; | 1189 | totlen += isopkt[u].length; |
1190 | } | 1190 | } |
1191 | /* 3072 * 64 microframes */ | 1191 | /* 3072 * 64 microframes */ |
1192 | if (totlen > 196608) { | 1192 | if (totlen > 196608) { |
1193 | kfree(isopkt); | 1193 | ret = -EINVAL; |
1194 | return -EINVAL; | 1194 | goto error; |
1195 | } | 1195 | } |
1196 | uurb->buffer_length = totlen; | 1196 | uurb->buffer_length = totlen; |
1197 | break; | 1197 | break; |
@@ -1202,24 +1202,20 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, | |||
1202 | if (uurb->buffer_length > 0 && | 1202 | if (uurb->buffer_length > 0 && |
1203 | !access_ok(is_in ? VERIFY_WRITE : VERIFY_READ, | 1203 | !access_ok(is_in ? VERIFY_WRITE : VERIFY_READ, |
1204 | uurb->buffer, uurb->buffer_length)) { | 1204 | uurb->buffer, uurb->buffer_length)) { |
1205 | kfree(isopkt); | 1205 | ret = -EFAULT; |
1206 | kfree(dr); | 1206 | goto error; |
1207 | return -EFAULT; | ||
1208 | } | 1207 | } |
1209 | as = alloc_async(uurb->number_of_packets); | 1208 | as = alloc_async(uurb->number_of_packets); |
1210 | if (!as) { | 1209 | if (!as) { |
1211 | kfree(isopkt); | 1210 | ret = -ENOMEM; |
1212 | kfree(dr); | 1211 | goto error; |
1213 | return -ENOMEM; | ||
1214 | } | 1212 | } |
1215 | if (uurb->buffer_length > 0) { | 1213 | if (uurb->buffer_length > 0) { |
1216 | as->urb->transfer_buffer = kmalloc(uurb->buffer_length, | 1214 | as->urb->transfer_buffer = kmalloc(uurb->buffer_length, |
1217 | GFP_KERNEL); | 1215 | GFP_KERNEL); |
1218 | if (!as->urb->transfer_buffer) { | 1216 | if (!as->urb->transfer_buffer) { |
1219 | kfree(isopkt); | 1217 | ret = -ENOMEM; |
1220 | kfree(dr); | 1218 | goto error; |
1221 | free_async(as); | ||
1222 | return -ENOMEM; | ||
1223 | } | 1219 | } |
1224 | /* Isochronous input data may end up being discontiguous | 1220 | /* Isochronous input data may end up being discontiguous |
1225 | * if some of the packets are short. Clear the buffer so | 1221 | * if some of the packets are short. Clear the buffer so |
@@ -1253,6 +1249,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, | |||
1253 | 1249 | ||
1254 | as->urb->transfer_buffer_length = uurb->buffer_length; | 1250 | as->urb->transfer_buffer_length = uurb->buffer_length; |
1255 | as->urb->setup_packet = (unsigned char *)dr; | 1251 | as->urb->setup_packet = (unsigned char *)dr; |
1252 | dr = NULL; | ||
1256 | as->urb->start_frame = uurb->start_frame; | 1253 | as->urb->start_frame = uurb->start_frame; |
1257 | as->urb->number_of_packets = uurb->number_of_packets; | 1254 | as->urb->number_of_packets = uurb->number_of_packets; |
1258 | if (uurb->type == USBDEVFS_URB_TYPE_ISO || | 1255 | if (uurb->type == USBDEVFS_URB_TYPE_ISO || |
@@ -1268,6 +1265,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, | |||
1268 | totlen += isopkt[u].length; | 1265 | totlen += isopkt[u].length; |
1269 | } | 1266 | } |
1270 | kfree(isopkt); | 1267 | kfree(isopkt); |
1268 | isopkt = NULL; | ||
1271 | as->ps = ps; | 1269 | as->ps = ps; |
1272 | as->userurb = arg; | 1270 | as->userurb = arg; |
1273 | if (is_in && uurb->buffer_length > 0) | 1271 | if (is_in && uurb->buffer_length > 0) |
@@ -1282,8 +1280,8 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, | |||
1282 | if (!is_in && uurb->buffer_length > 0) { | 1280 | if (!is_in && uurb->buffer_length > 0) { |
1283 | if (copy_from_user(as->urb->transfer_buffer, uurb->buffer, | 1281 | if (copy_from_user(as->urb->transfer_buffer, uurb->buffer, |
1284 | uurb->buffer_length)) { | 1282 | uurb->buffer_length)) { |
1285 | free_async(as); | 1283 | ret = -EFAULT; |
1286 | return -EFAULT; | 1284 | goto error; |
1287 | } | 1285 | } |
1288 | } | 1286 | } |
1289 | snoop_urb(ps->dev, as->userurb, as->urb->pipe, | 1287 | snoop_urb(ps->dev, as->userurb, as->urb->pipe, |
@@ -1329,10 +1327,16 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, | |||
1329 | snoop_urb(ps->dev, as->userurb, as->urb->pipe, | 1327 | snoop_urb(ps->dev, as->userurb, as->urb->pipe, |
1330 | 0, ret, COMPLETE, NULL, 0); | 1328 | 0, ret, COMPLETE, NULL, 0); |
1331 | async_removepending(as); | 1329 | async_removepending(as); |
1332 | free_async(as); | 1330 | goto error; |
1333 | return ret; | ||
1334 | } | 1331 | } |
1335 | return 0; | 1332 | return 0; |
1333 | |||
1334 | error: | ||
1335 | kfree(isopkt); | ||
1336 | kfree(dr); | ||
1337 | if (as) | ||
1338 | free_async(as); | ||
1339 | return ret; | ||
1336 | } | 1340 | } |
1337 | 1341 | ||
1338 | static int proc_submiturb(struct dev_state *ps, void __user *arg) | 1342 | static int proc_submiturb(struct dev_state *ps, void __user *arg) |