summaryrefslogtreecommitdiffstats
path: root/drivers/w1/masters/ds2490.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/w1/masters/ds2490.c')
-rw-r--r--drivers/w1/masters/ds2490.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/drivers/w1/masters/ds2490.c b/drivers/w1/masters/ds2490.c
index 9a7fd71e146..0f356939b34 100644
--- a/drivers/w1/masters/ds2490.c
+++ b/drivers/w1/masters/ds2490.c
@@ -316,6 +316,15 @@ static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size)
int count, err;
struct ds_status st;
+ /* Careful on size. If size is less than what is available in
+ * the input buffer, the device fails the bulk transfer and
+ * clears the input buffer. It could read the maximum size of
+ * the data buffer, but then do you return the first, last, or
+ * some set of the middle size bytes? As long as the rest of
+ * the code is correct there will be size bytes waiting. A
+ * call to ds_wait_status will wait until the device is idle
+ * and any data to be received would have been available.
+ */
count = 0;
err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]),
buf, size, &count, 1000);
@@ -824,6 +833,18 @@ static int ds_w1_init(struct ds_device *dev)
{
memset(&dev->master, 0, sizeof(struct w1_bus_master));
+ /* Reset the device as it can be in a bad state.
+ * This is necessary because a block write will wait for data
+ * to be placed in the output buffer and block any later
+ * commands which will keep accumulating and the device will
+ * not be idle. Another case is removing the ds2490 module
+ * while a bus search is in progress, somehow a few commands
+ * get through, but the input transfers fail leaving data in
+ * the input buffer. This will cause the next read to fail
+ * see the note in ds_recv_data.
+ */
+ ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0);
+
dev->master.data = dev;
dev->master.touch_bit = &ds9490r_touch_bit;
/* read_bit and write_bit in w1_bus_master are expected to set and