diff options
author | Maciej S. Szmigiero <mail@maciej.szmigiero.name> | 2017-01-18 15:31:11 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-03-12 00:41:48 -0500 |
commit | c259832acf57c51971582c84c89b2941a8a9e1ef (patch) | |
tree | 095a5e58219cddc11a1e75838774659bf6279d20 /drivers/w1 | |
parent | 1de86951101be4a3bcee9355a10f327bba491ec5 (diff) |
w1: ds2490: USB transfer buffers need to be DMAable
commit 61cd1b4cd1e8f7f7642ab64529d9bd52e8374641 upstream.
ds2490 driver was doing USB transfers from / to buffers on a stack.
This is not permitted and made the driver non-working with vmapped stacks.
Since all these transfers are done under the same bus_mutex lock we can
simply use shared buffers in a device private structure for two most common
of them.
While we are at it, let's also fix a comparison between int and size_t in
ds9490r_search() which made the driver spin in this function if state
register get requests were failing.
Signed-off-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name>
Acked-by: Evgeniy Polyakov <zbr@ioremap.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/w1')
-rw-r--r-- | drivers/w1/masters/ds2490.c | 142 |
1 files changed, 84 insertions, 58 deletions
diff --git a/drivers/w1/masters/ds2490.c b/drivers/w1/masters/ds2490.c index 049a884a756f..59d74d1b47a8 100644 --- a/drivers/w1/masters/ds2490.c +++ b/drivers/w1/masters/ds2490.c | |||
@@ -153,6 +153,9 @@ struct ds_device | |||
153 | */ | 153 | */ |
154 | u16 spu_bit; | 154 | u16 spu_bit; |
155 | 155 | ||
156 | u8 st_buf[ST_SIZE]; | ||
157 | u8 byte_buf; | ||
158 | |||
156 | struct w1_bus_master master; | 159 | struct w1_bus_master master; |
157 | }; | 160 | }; |
158 | 161 | ||
@@ -174,7 +177,6 @@ struct ds_status | |||
174 | u8 data_in_buffer_status; | 177 | u8 data_in_buffer_status; |
175 | u8 reserved1; | 178 | u8 reserved1; |
176 | u8 reserved2; | 179 | u8 reserved2; |
177 | |||
178 | }; | 180 | }; |
179 | 181 | ||
180 | static struct usb_device_id ds_id_table [] = { | 182 | static struct usb_device_id ds_id_table [] = { |
@@ -244,28 +246,6 @@ static int ds_send_control(struct ds_device *dev, u16 value, u16 index) | |||
244 | return err; | 246 | return err; |
245 | } | 247 | } |
246 | 248 | ||
247 | static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st, | ||
248 | unsigned char *buf, int size) | ||
249 | { | ||
250 | int count, err; | ||
251 | |||
252 | memset(st, 0, sizeof(*st)); | ||
253 | |||
254 | count = 0; | ||
255 | err = usb_interrupt_msg(dev->udev, usb_rcvintpipe(dev->udev, | ||
256 | dev->ep[EP_STATUS]), buf, size, &count, 1000); | ||
257 | if (err < 0) { | ||
258 | pr_err("Failed to read 1-wire data from 0x%x: err=%d.\n", | ||
259 | dev->ep[EP_STATUS], err); | ||
260 | return err; | ||
261 | } | ||
262 | |||
263 | if (count >= sizeof(*st)) | ||
264 | memcpy(st, buf, sizeof(*st)); | ||
265 | |||
266 | return count; | ||
267 | } | ||
268 | |||
269 | static inline void ds_print_msg(unsigned char *buf, unsigned char *str, int off) | 249 | static inline void ds_print_msg(unsigned char *buf, unsigned char *str, int off) |
270 | { | 250 | { |
271 | pr_info("%45s: %8x\n", str, buf[off]); | 251 | pr_info("%45s: %8x\n", str, buf[off]); |
@@ -324,6 +304,35 @@ static void ds_dump_status(struct ds_device *dev, unsigned char *buf, int count) | |||
324 | } | 304 | } |
325 | } | 305 | } |
326 | 306 | ||
307 | static int ds_recv_status(struct ds_device *dev, struct ds_status *st, | ||
308 | bool dump) | ||
309 | { | ||
310 | int count, err; | ||
311 | |||
312 | if (st) | ||
313 | memset(st, 0, sizeof(*st)); | ||
314 | |||
315 | count = 0; | ||
316 | err = usb_interrupt_msg(dev->udev, | ||
317 | usb_rcvintpipe(dev->udev, | ||
318 | dev->ep[EP_STATUS]), | ||
319 | dev->st_buf, sizeof(dev->st_buf), | ||
320 | &count, 1000); | ||
321 | if (err < 0) { | ||
322 | pr_err("Failed to read 1-wire data from 0x%x: err=%d.\n", | ||
323 | dev->ep[EP_STATUS], err); | ||
324 | return err; | ||
325 | } | ||
326 | |||
327 | if (dump) | ||
328 | ds_dump_status(dev, dev->st_buf, count); | ||
329 | |||
330 | if (st && count >= sizeof(*st)) | ||
331 | memcpy(st, dev->st_buf, sizeof(*st)); | ||
332 | |||
333 | return count; | ||
334 | } | ||
335 | |||
327 | static void ds_reset_device(struct ds_device *dev) | 336 | static void ds_reset_device(struct ds_device *dev) |
328 | { | 337 | { |
329 | ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0); | 338 | ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0); |
@@ -344,7 +353,6 @@ static void ds_reset_device(struct ds_device *dev) | |||
344 | static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size) | 353 | static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size) |
345 | { | 354 | { |
346 | int count, err; | 355 | int count, err; |
347 | struct ds_status st; | ||
348 | 356 | ||
349 | /* Careful on size. If size is less than what is available in | 357 | /* Careful on size. If size is less than what is available in |
350 | * the input buffer, the device fails the bulk transfer and | 358 | * the input buffer, the device fails the bulk transfer and |
@@ -359,14 +367,9 @@ static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size) | |||
359 | err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]), | 367 | err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]), |
360 | buf, size, &count, 1000); | 368 | buf, size, &count, 1000); |
361 | if (err < 0) { | 369 | if (err < 0) { |
362 | u8 buf[ST_SIZE]; | ||
363 | int count; | ||
364 | |||
365 | pr_info("Clearing ep0x%x.\n", dev->ep[EP_DATA_IN]); | 370 | pr_info("Clearing ep0x%x.\n", dev->ep[EP_DATA_IN]); |
366 | usb_clear_halt(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN])); | 371 | usb_clear_halt(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN])); |
367 | 372 | ds_recv_status(dev, NULL, true); | |
368 | count = ds_recv_status_nodump(dev, &st, buf, sizeof(buf)); | ||
369 | ds_dump_status(dev, buf, count); | ||
370 | return err; | 373 | return err; |
371 | } | 374 | } |
372 | 375 | ||
@@ -404,7 +407,6 @@ int ds_stop_pulse(struct ds_device *dev, int limit) | |||
404 | { | 407 | { |
405 | struct ds_status st; | 408 | struct ds_status st; |
406 | int count = 0, err = 0; | 409 | int count = 0, err = 0; |
407 | u8 buf[ST_SIZE]; | ||
408 | 410 | ||
409 | do { | 411 | do { |
410 | err = ds_send_control(dev, CTL_HALT_EXE_IDLE, 0); | 412 | err = ds_send_control(dev, CTL_HALT_EXE_IDLE, 0); |
@@ -413,7 +415,7 @@ int ds_stop_pulse(struct ds_device *dev, int limit) | |||
413 | err = ds_send_control(dev, CTL_RESUME_EXE, 0); | 415 | err = ds_send_control(dev, CTL_RESUME_EXE, 0); |
414 | if (err) | 416 | if (err) |
415 | break; | 417 | break; |
416 | err = ds_recv_status_nodump(dev, &st, buf, sizeof(buf)); | 418 | err = ds_recv_status(dev, &st, false); |
417 | if (err) | 419 | if (err) |
418 | break; | 420 | break; |
419 | 421 | ||
@@ -456,18 +458,17 @@ int ds_detect(struct ds_device *dev, struct ds_status *st) | |||
456 | 458 | ||
457 | static int ds_wait_status(struct ds_device *dev, struct ds_status *st) | 459 | static int ds_wait_status(struct ds_device *dev, struct ds_status *st) |
458 | { | 460 | { |
459 | u8 buf[ST_SIZE]; | ||
460 | int err, count = 0; | 461 | int err, count = 0; |
461 | 462 | ||
462 | do { | 463 | do { |
463 | st->status = 0; | 464 | st->status = 0; |
464 | err = ds_recv_status_nodump(dev, st, buf, sizeof(buf)); | 465 | err = ds_recv_status(dev, st, false); |
465 | #if 0 | 466 | #if 0 |
466 | if (err >= 0) { | 467 | if (err >= 0) { |
467 | int i; | 468 | int i; |
468 | printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], err); | 469 | printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], err); |
469 | for (i=0; i<err; ++i) | 470 | for (i=0; i<err; ++i) |
470 | printk("%02x ", buf[i]); | 471 | printk("%02x ", dev->st_buf[i]); |
471 | printk("\n"); | 472 | printk("\n"); |
472 | } | 473 | } |
473 | #endif | 474 | #endif |
@@ -485,7 +486,7 @@ static int ds_wait_status(struct ds_device *dev, struct ds_status *st) | |||
485 | * can do something with it). | 486 | * can do something with it). |
486 | */ | 487 | */ |
487 | if (err > 16 || count >= 100 || err < 0) | 488 | if (err > 16 || count >= 100 || err < 0) |
488 | ds_dump_status(dev, buf, err); | 489 | ds_dump_status(dev, dev->st_buf, err); |
489 | 490 | ||
490 | /* Extended data isn't an error. Well, a short is, but the dump | 491 | /* Extended data isn't an error. Well, a short is, but the dump |
491 | * would have already told the user that and we can't do anything | 492 | * would have already told the user that and we can't do anything |
@@ -608,7 +609,6 @@ static int ds_write_byte(struct ds_device *dev, u8 byte) | |||
608 | { | 609 | { |
609 | int err; | 610 | int err; |
610 | struct ds_status st; | 611 | struct ds_status st; |
611 | u8 rbyte; | ||
612 | 612 | ||
613 | err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM | dev->spu_bit, byte); | 613 | err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM | dev->spu_bit, byte); |
614 | if (err) | 614 | if (err) |
@@ -621,11 +621,11 @@ static int ds_write_byte(struct ds_device *dev, u8 byte) | |||
621 | if (err) | 621 | if (err) |
622 | return err; | 622 | return err; |
623 | 623 | ||
624 | err = ds_recv_data(dev, &rbyte, sizeof(rbyte)); | 624 | err = ds_recv_data(dev, &dev->byte_buf, 1); |
625 | if (err < 0) | 625 | if (err < 0) |
626 | return err; | 626 | return err; |
627 | 627 | ||
628 | return !(byte == rbyte); | 628 | return !(byte == dev->byte_buf); |
629 | } | 629 | } |
630 | 630 | ||
631 | static int ds_read_byte(struct ds_device *dev, u8 *byte) | 631 | static int ds_read_byte(struct ds_device *dev, u8 *byte) |
@@ -712,7 +712,6 @@ static void ds9490r_search(void *data, struct w1_master *master, | |||
712 | int err; | 712 | int err; |
713 | u16 value, index; | 713 | u16 value, index; |
714 | struct ds_status st; | 714 | struct ds_status st; |
715 | u8 st_buf[ST_SIZE]; | ||
716 | int search_limit; | 715 | int search_limit; |
717 | int found = 0; | 716 | int found = 0; |
718 | int i; | 717 | int i; |
@@ -724,7 +723,12 @@ static void ds9490r_search(void *data, struct w1_master *master, | |||
724 | /* FIFO 128 bytes, bulk packet size 64, read a multiple of the | 723 | /* FIFO 128 bytes, bulk packet size 64, read a multiple of the |
725 | * packet size. | 724 | * packet size. |
726 | */ | 725 | */ |
727 | u64 buf[2*64/8]; | 726 | const size_t bufsize = 2 * 64; |
727 | u64 *buf; | ||
728 | |||
729 | buf = kmalloc(bufsize, GFP_KERNEL); | ||
730 | if (!buf) | ||
731 | return; | ||
728 | 732 | ||
729 | mutex_lock(&master->bus_mutex); | 733 | mutex_lock(&master->bus_mutex); |
730 | 734 | ||
@@ -745,10 +749,9 @@ static void ds9490r_search(void *data, struct w1_master *master, | |||
745 | do { | 749 | do { |
746 | schedule_timeout(jtime); | 750 | schedule_timeout(jtime); |
747 | 751 | ||
748 | if (ds_recv_status_nodump(dev, &st, st_buf, sizeof(st_buf)) < | 752 | err = ds_recv_status(dev, &st, false); |
749 | sizeof(st)) { | 753 | if (err < 0 || err < sizeof(st)) |
750 | break; | 754 | break; |
751 | } | ||
752 | 755 | ||
753 | if (st.data_in_buffer_status) { | 756 | if (st.data_in_buffer_status) { |
754 | /* Bulk in can receive partial ids, but when it does | 757 | /* Bulk in can receive partial ids, but when it does |
@@ -758,7 +761,7 @@ static void ds9490r_search(void *data, struct w1_master *master, | |||
758 | * bulk without first checking if status says there | 761 | * bulk without first checking if status says there |
759 | * is data to read. | 762 | * is data to read. |
760 | */ | 763 | */ |
761 | err = ds_recv_data(dev, (u8 *)buf, sizeof(buf)); | 764 | err = ds_recv_data(dev, (u8 *)buf, bufsize); |
762 | if (err < 0) | 765 | if (err < 0) |
763 | break; | 766 | break; |
764 | for (i = 0; i < err/8; ++i) { | 767 | for (i = 0; i < err/8; ++i) { |
@@ -794,9 +797,14 @@ static void ds9490r_search(void *data, struct w1_master *master, | |||
794 | } | 797 | } |
795 | search_out: | 798 | search_out: |
796 | mutex_unlock(&master->bus_mutex); | 799 | mutex_unlock(&master->bus_mutex); |
800 | kfree(buf); | ||
797 | } | 801 | } |
798 | 802 | ||
799 | #if 0 | 803 | #if 0 |
804 | /* | ||
805 | * FIXME: if this disabled code is ever used in the future all ds_send_data() | ||
806 | * calls must be changed to use a DMAable buffer. | ||
807 | */ | ||
800 | static int ds_match_access(struct ds_device *dev, u64 init) | 808 | static int ds_match_access(struct ds_device *dev, u64 init) |
801 | { | 809 | { |
802 | int err; | 810 | int err; |
@@ -845,13 +853,12 @@ static int ds_set_path(struct ds_device *dev, u64 init) | |||
845 | 853 | ||
846 | static u8 ds9490r_touch_bit(void *data, u8 bit) | 854 | static u8 ds9490r_touch_bit(void *data, u8 bit) |
847 | { | 855 | { |
848 | u8 ret; | ||
849 | struct ds_device *dev = data; | 856 | struct ds_device *dev = data; |
850 | 857 | ||
851 | if (ds_touch_bit(dev, bit, &ret)) | 858 | if (ds_touch_bit(dev, bit, &dev->byte_buf)) |
852 | return 0; | 859 | return 0; |
853 | 860 | ||
854 | return ret; | 861 | return dev->byte_buf; |
855 | } | 862 | } |
856 | 863 | ||
857 | #if 0 | 864 | #if 0 |
@@ -866,13 +873,12 @@ static u8 ds9490r_read_bit(void *data) | |||
866 | { | 873 | { |
867 | struct ds_device *dev = data; | 874 | struct ds_device *dev = data; |
868 | int err; | 875 | int err; |
869 | u8 bit = 0; | ||
870 | 876 | ||
871 | err = ds_touch_bit(dev, 1, &bit); | 877 | err = ds_touch_bit(dev, 1, &dev->byte_buf); |
872 | if (err) | 878 | if (err) |
873 | return 0; | 879 | return 0; |
874 | 880 | ||
875 | return bit & 1; | 881 | return dev->byte_buf & 1; |
876 | } | 882 | } |
877 | #endif | 883 | #endif |
878 | 884 | ||
@@ -887,32 +893,52 @@ static u8 ds9490r_read_byte(void *data) | |||
887 | { | 893 | { |
888 | struct ds_device *dev = data; | 894 | struct ds_device *dev = data; |
889 | int err; | 895 | int err; |
890 | u8 byte = 0; | ||
891 | 896 | ||
892 | err = ds_read_byte(dev, &byte); | 897 | err = ds_read_byte(dev, &dev->byte_buf); |
893 | if (err) | 898 | if (err) |
894 | return 0; | 899 | return 0; |
895 | 900 | ||
896 | return byte; | 901 | return dev->byte_buf; |
897 | } | 902 | } |
898 | 903 | ||
899 | static void ds9490r_write_block(void *data, const u8 *buf, int len) | 904 | static void ds9490r_write_block(void *data, const u8 *buf, int len) |
900 | { | 905 | { |
901 | struct ds_device *dev = data; | 906 | struct ds_device *dev = data; |
907 | u8 *tbuf; | ||
908 | |||
909 | if (len <= 0) | ||
910 | return; | ||
911 | |||
912 | tbuf = kmalloc(len, GFP_KERNEL); | ||
913 | if (!tbuf) | ||
914 | return; | ||
902 | 915 | ||
903 | ds_write_block(dev, (u8 *)buf, len); | 916 | memcpy(tbuf, buf, len); |
917 | ds_write_block(dev, tbuf, len); | ||
918 | |||
919 | kfree(tbuf); | ||
904 | } | 920 | } |
905 | 921 | ||
906 | static u8 ds9490r_read_block(void *data, u8 *buf, int len) | 922 | static u8 ds9490r_read_block(void *data, u8 *buf, int len) |
907 | { | 923 | { |
908 | struct ds_device *dev = data; | 924 | struct ds_device *dev = data; |
909 | int err; | 925 | int err; |
926 | u8 *tbuf; | ||
910 | 927 | ||
911 | err = ds_read_block(dev, buf, len); | 928 | if (len <= 0) |
912 | if (err < 0) | 929 | return 0; |
930 | |||
931 | tbuf = kmalloc(len, GFP_KERNEL); | ||
932 | if (!tbuf) | ||
913 | return 0; | 933 | return 0; |
914 | 934 | ||
915 | return len; | 935 | err = ds_read_block(dev, tbuf, len); |
936 | if (err >= 0) | ||
937 | memcpy(buf, tbuf, len); | ||
938 | |||
939 | kfree(tbuf); | ||
940 | |||
941 | return err >= 0 ? len : 0; | ||
916 | } | 942 | } |
917 | 943 | ||
918 | static u8 ds9490r_reset(void *data) | 944 | static u8 ds9490r_reset(void *data) |