static int convert_t()

in slaves/w1_therm.c [1047:1147]


static int convert_t(struct w1_slave *sl, struct therm_info *info)
{
	struct w1_master *dev_master = sl->master;
	int max_trying = W1_THERM_MAX_TRY;
	int t_conv;
	int ret = -ENODEV;
	bool strong_pullup;

	if (!sl->family_data)
		goto error;

	strong_pullup = (w1_strong_pullup == 2 ||
					(!SLAVE_POWERMODE(sl) &&
					w1_strong_pullup));

	if (strong_pullup && SLAVE_FEATURES(sl) & W1_THERM_POLL_COMPLETION) {
		dev_warn(&sl->dev,
			"%s: Disabling W1_THERM_POLL_COMPLETION in parasite power mode.\n",
			__func__);
		SLAVE_FEATURES(sl) &= ~W1_THERM_POLL_COMPLETION;
	}

	/* get conversion duration device and id dependent */
	t_conv = conversion_time(sl);

	memset(info->rom, 0, sizeof(info->rom));

	/* prevent the slave from going away in sleep */
	atomic_inc(THERM_REFCNT(sl->family_data));

	if (!bus_mutex_lock(&dev_master->bus_mutex)) {
		ret = -EAGAIN;	/* Didn't acquire the mutex */
		goto dec_refcnt;
	}

	while (max_trying-- && ret) { /* ret should be 0 */

		info->verdict = 0;
		info->crc = 0;
		/* safe version to select slave */
		if (!reset_select_slave(sl)) {
			unsigned long sleep_rem;

			/* 750ms strong pullup (or delay) after the convert */
			if (strong_pullup)
				w1_next_pullup(dev_master, t_conv);

			w1_write_8(dev_master, W1_CONVERT_TEMP);

			if (strong_pullup) { /*some device need pullup */
				sleep_rem = msleep_interruptible(t_conv);
				if (sleep_rem != 0) {
					ret = -EINTR;
					goto mt_unlock;
				}
				mutex_unlock(&dev_master->bus_mutex);
			} else { /*no device need pullup */
				if (SLAVE_FEATURES(sl) & W1_THERM_POLL_COMPLETION) {
					ret = w1_poll_completion(dev_master, W1_POLL_CONVERT_TEMP);
					if (ret) {
						dev_dbg(&sl->dev, "%s: Timeout\n", __func__);
						goto mt_unlock;
					}
					mutex_unlock(&dev_master->bus_mutex);
				} else {
					/* Fixed delay */
					mutex_unlock(&dev_master->bus_mutex);
					sleep_rem = msleep_interruptible(t_conv);
					if (sleep_rem != 0) {
						ret = -EINTR;
						goto dec_refcnt;
					}
				}
			}
			ret = read_scratchpad(sl, info);

			/* If enabled, check for conversion success */
			if ((SLAVE_FEATURES(sl) & W1_THERM_CHECK_RESULT) &&
				(info->rom[6] == 0xC) &&
				((info->rom[1] == 0x5 && info->rom[0] == 0x50) ||
				(info->rom[1] == 0x7 && info->rom[0] == 0xFF))
			) {
				/* Invalid reading (scratchpad byte 6 = 0xC)
				 * due to insufficient conversion time
				 * or power failure.
				 */
				ret = -EIO;
			}

			goto dec_refcnt;
		}

	}

mt_unlock:
	mutex_unlock(&dev_master->bus_mutex);
dec_refcnt:
	atomic_dec(THERM_REFCNT(sl->family_data));
error:
	return ret;
}