Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

w1: ds2490 fix and enable hardware search

The hardware search was failing without the COMM_RST flag. Enabled
the flag and rewrote the function to handle more than one buffer of
results and to continuing where the search left off. Remove hardware
search note from the limitations now that it works. The "w1: ds2490
USB setup fixes" change went from 23.16 seconds to about 3 seconds,
this takes the time for the search down to .307346 seconds.

Signed-off-by: David Fries <David@Fries.net>
Acked-by: Evgeniy Polyakov <zbr@ioremap.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

David Fries and committed by
Greg Kroah-Hartman
d53f0a2c da78b7e7

+85 -23
-2
Documentation/w1/masters/ds2490
··· 21 21 - The weak pullup current is a minimum of 0.9mA and maximum of 6.0mA. 22 22 - The 5V strong pullup is supported with a minimum of 5.9mA and a 23 23 maximum of 30.4 mA. (From DS2490.pdf) 24 - - While the ds2490 supports a hardware search the code doesn't take 25 - advantage of it (in tested case it only returned first device). 26 24 - The hardware will detect when devices are attached to the bus on the 27 25 next bus (reset?) operation, however only a message is printed as 28 26 the core w1 code doesn't make use of the information. Connecting
+85 -21
drivers/w1/masters/ds2490.c
··· 698 698 return !(err == len); 699 699 } 700 700 701 - #if 0 702 - 703 - static int ds_search(struct ds_device *dev, u64 init, u64 *buf, u8 id_number, int conditional_search) 701 + static void ds9490r_search(void *data, struct w1_master *master, 702 + u8 search_type, w1_slave_found_callback callback) 704 703 { 704 + /* When starting with an existing id, the first id returned will 705 + * be that device (if it is still on the bus most likely). 706 + * 707 + * If the number of devices found is less than or equal to the 708 + * search_limit, that number of IDs will be returned. If there are 709 + * more, search_limit IDs will be returned followed by a non-zero 710 + * discrepency value. 711 + */ 712 + struct ds_device *dev = data; 705 713 int err; 706 714 u16 value, index; 707 715 struct ds_status st; 716 + u8 st_buf[ST_SIZE]; 717 + int search_limit; 718 + int found = 0; 719 + int i; 708 720 709 - memset(buf, 0, sizeof(buf)); 721 + /* DS18b20 spec, 13.16 ms per device, 75 per second, sleep for 722 + * discovering 8 devices (1 bulk transfer and 1/2 FIFO size) at a time. 723 + */ 724 + const unsigned long jtime = msecs_to_jiffies(1000*8/75); 725 + /* FIFO 128 bytes, bulk packet size 64, read a multiple of the 726 + * packet size. 727 + */ 728 + u64 buf[2*64/8]; 710 729 711 - err = ds_send_data(ds_dev, (unsigned char *)&init, 8); 712 - if (err) 713 - return err; 730 + /* address to start searching at */ 731 + if (ds_send_data(dev, (u8 *)&master->search_id, 8) < 0) 732 + return; 733 + master->search_id = 0; 714 734 715 - ds_wait_status(ds_dev, &st); 735 + value = COMM_SEARCH_ACCESS | COMM_IM | COMM_RST | COMM_SM | COMM_F | 736 + COMM_RTS; 737 + search_limit = master->max_slave_count; 738 + if (search_limit > 255) 739 + search_limit = 0; 740 + index = search_type | (search_limit << 8); 741 + if (ds_send_control(dev, value, index) < 0) 742 + return; 716 743 717 - value = COMM_SEARCH_ACCESS | COMM_IM | COMM_SM | COMM_F | COMM_RTS; 718 - index = (conditional_search ? 0xEC : 0xF0) | (id_number << 8); 719 - err = ds_send_control(ds_dev, value, index); 720 - if (err) 721 - return err; 744 + do { 745 + schedule_timeout(jtime); 722 746 723 - ds_wait_status(ds_dev, &st); 747 + if (ds_recv_status_nodump(dev, &st, st_buf, sizeof(st_buf)) < 748 + sizeof(st)) { 749 + break; 750 + } 724 751 725 - err = ds_recv_data(ds_dev, (unsigned char *)buf, 8*id_number); 726 - if (err < 0) 727 - return err; 752 + if (st.data_in_buffer_status) { 753 + /* Bulk in can receive partial ids, but when it does 754 + * they fail crc and will be discarded anyway. 755 + * That has only been seen when status in buffer 756 + * is 0 and bulk is read anyway, so don't read 757 + * bulk without first checking if status says there 758 + * is data to read. 759 + */ 760 + err = ds_recv_data(dev, (u8 *)buf, sizeof(buf)); 761 + if (err < 0) 762 + break; 763 + for (i = 0; i < err/8; ++i) { 764 + ++found; 765 + if (found <= search_limit) 766 + callback(master, buf[i]); 767 + /* can't know if there will be a discrepancy 768 + * value after until the next id */ 769 + if (found == search_limit) 770 + master->search_id = buf[i]; 771 + } 772 + } 728 773 729 - return err/8; 774 + if (test_bit(W1_ABORT_SEARCH, &master->flags)) 775 + break; 776 + } while (!(st.status & (ST_IDLE | ST_HALT))); 777 + 778 + /* only continue the search if some weren't found */ 779 + if (found <= search_limit) { 780 + master->search_id = 0; 781 + } else if (!test_bit(W1_WARN_MAX_COUNT, &master->flags)) { 782 + /* Only max_slave_count will be scanned in a search, 783 + * but it will start where it left off next search 784 + * until all ids are identified and then it will start 785 + * over. A continued search will report the previous 786 + * last id as the first id (provided it is still on the 787 + * bus). 788 + */ 789 + dev_info(&dev->udev->dev, "%s: max_slave_count %d reached, " 790 + "will continue next search.\n", __func__, 791 + master->max_slave_count); 792 + set_bit(W1_WARN_MAX_COUNT, &master->flags); 793 + } 730 794 } 731 795 796 + #if 0 732 797 static int ds_match_access(struct ds_device *dev, u64 init) 733 798 { 734 799 int err; ··· 967 902 dev->master.write_block = &ds9490r_write_block; 968 903 dev->master.reset_bus = &ds9490r_reset; 969 904 dev->master.set_pullup = &ds9490r_set_pullup; 905 + dev->master.search = &ds9490r_search; 970 906 971 907 return w1_add_master_device(&dev->master); 972 908 } ··· 986 920 struct ds_device *dev; 987 921 int i, err, alt; 988 922 989 - dev = kmalloc(sizeof(struct ds_device), GFP_KERNEL); 923 + dev = kzalloc(sizeof(struct ds_device), GFP_KERNEL); 990 924 if (!dev) { 991 925 printk(KERN_INFO "Failed to allocate new DS9490R structure.\n"); 992 926 return -ENOMEM; 993 927 } 994 - dev->spu_sleep = 0; 995 - dev->spu_bit = 0; 996 928 dev->udev = usb_get_dev(udev); 997 929 if (!dev->udev) { 998 930 err = -ENOMEM;