static int abituguru_probe()

in abituguru.c [1257:1429]


static int abituguru_probe(struct platform_device *pdev)
{
	struct abituguru_data *data;
	int i, j, used, sysfs_names_free, sysfs_attr_i, res = -ENODEV;
	char *sysfs_filename;

	/*
	 * El weirdo probe order, to keep the sysfs order identical to the
	 * BIOS and window-appliction listing order.
	 */
	static const u8 probe_order[ABIT_UGURU_MAX_BANK1_SENSORS] = {
		0x00, 0x01, 0x03, 0x04, 0x0A, 0x08, 0x0E, 0x02,
		0x09, 0x06, 0x05, 0x0B, 0x0F, 0x0D, 0x07, 0x0C };

	data = devm_kzalloc(&pdev->dev, sizeof(struct abituguru_data),
			    GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start;
	mutex_init(&data->update_lock);
	platform_set_drvdata(pdev, data);

	/* See if the uGuru is ready */
	if (inb_p(data->addr + ABIT_UGURU_DATA) == ABIT_UGURU_STATUS_INPUT)
		data->uguru_ready = 1;

	/*
	 * Completely read the uGuru this has 2 purposes:
	 * - testread / see if one really is there.
	 * - make an in memory copy of all the uguru settings for future use.
	 */
	if (abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0,
			data->alarms, 3, ABIT_UGURU_MAX_RETRIES) != 3)
		goto abituguru_probe_error;

	for (i = 0; i < ABIT_UGURU_MAX_BANK1_SENSORS; i++) {
		if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1, i,
				&data->bank1_value[i], 1,
				ABIT_UGURU_MAX_RETRIES) != 1)
			goto abituguru_probe_error;
		if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1+1, i,
				data->bank1_settings[i], 3,
				ABIT_UGURU_MAX_RETRIES) != 3)
			goto abituguru_probe_error;
	}
	/*
	 * Note: We don't know how many bank2 sensors / pwms there really are,
	 * but in order to "detect" this we need to read the maximum amount
	 * anyways. If we read sensors/pwms not there we'll just read crap
	 * this can't hurt. We need the detection because we don't want
	 * unwanted writes, which will hurt!
	 */
	for (i = 0; i < ABIT_UGURU_MAX_BANK2_SENSORS; i++) {
		if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK2, i,
				&data->bank2_value[i], 1,
				ABIT_UGURU_MAX_RETRIES) != 1)
			goto abituguru_probe_error;
		if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK2+1, i,
				data->bank2_settings[i], 2,
				ABIT_UGURU_MAX_RETRIES) != 2)
			goto abituguru_probe_error;
	}
	for (i = 0; i < ABIT_UGURU_MAX_PWMS; i++) {
		if (abituguru_read(data, ABIT_UGURU_FAN_PWM, i,
				data->pwm_settings[i], 5,
				ABIT_UGURU_MAX_RETRIES) != 5)
			goto abituguru_probe_error;
	}
	data->last_updated = jiffies;

	/* Detect sensor types and fill the sysfs attr for bank1 */
	sysfs_attr_i = 0;
	sysfs_filename = data->sysfs_names;
	sysfs_names_free = ABITUGURU_SYSFS_NAMES_LENGTH;
	for (i = 0; i < ABIT_UGURU_MAX_BANK1_SENSORS; i++) {
		res = abituguru_detect_bank1_sensor_type(data, probe_order[i]);
		if (res < 0)
			goto abituguru_probe_error;
		if (res == ABIT_UGURU_NC)
			continue;

		/* res 1 (temp) sensors have 7 sysfs entries, 0 (in) 9 */
		for (j = 0; j < (res ? 7 : 9); j++) {
			used = snprintf(sysfs_filename, sysfs_names_free,
				abituguru_sysfs_bank1_templ[res][j].dev_attr.
				attr.name, data->bank1_sensors[res] + res)
				+ 1;
			data->sysfs_attr[sysfs_attr_i] =
				abituguru_sysfs_bank1_templ[res][j];
			data->sysfs_attr[sysfs_attr_i].dev_attr.attr.name =
				sysfs_filename;
			data->sysfs_attr[sysfs_attr_i].index = probe_order[i];
			sysfs_filename += used;
			sysfs_names_free -= used;
			sysfs_attr_i++;
		}
		data->bank1_max_value[probe_order[i]] =
			abituguru_bank1_max_value[res];
		data->bank1_address[res][data->bank1_sensors[res]] =
			probe_order[i];
		data->bank1_sensors[res]++;
	}
	/* Detect number of sensors and fill the sysfs attr for bank2 (fans) */
	abituguru_detect_no_bank2_sensors(data);
	for (i = 0; i < data->bank2_sensors; i++) {
		for (j = 0; j < ARRAY_SIZE(abituguru_sysfs_fan_templ); j++) {
			used = snprintf(sysfs_filename, sysfs_names_free,
				abituguru_sysfs_fan_templ[j].dev_attr.attr.name,
				i + 1) + 1;
			data->sysfs_attr[sysfs_attr_i] =
				abituguru_sysfs_fan_templ[j];
			data->sysfs_attr[sysfs_attr_i].dev_attr.attr.name =
				sysfs_filename;
			data->sysfs_attr[sysfs_attr_i].index = i;
			sysfs_filename += used;
			sysfs_names_free -= used;
			sysfs_attr_i++;
		}
	}
	/* Detect number of sensors and fill the sysfs attr for pwms */
	abituguru_detect_no_pwms(data);
	for (i = 0; i < data->pwms; i++) {
		for (j = 0; j < ARRAY_SIZE(abituguru_sysfs_pwm_templ); j++) {
			used = snprintf(sysfs_filename, sysfs_names_free,
				abituguru_sysfs_pwm_templ[j].dev_attr.attr.name,
				i + 1) + 1;
			data->sysfs_attr[sysfs_attr_i] =
				abituguru_sysfs_pwm_templ[j];
			data->sysfs_attr[sysfs_attr_i].dev_attr.attr.name =
				sysfs_filename;
			data->sysfs_attr[sysfs_attr_i].index = i;
			sysfs_filename += used;
			sysfs_names_free -= used;
			sysfs_attr_i++;
		}
	}
	/* Fail safe check, this should never happen! */
	if (sysfs_names_free < 0) {
		pr_err("Fatal error ran out of space for sysfs attr names. %s %s",
		       never_happen, report_this);
		res = -ENAMETOOLONG;
		goto abituguru_probe_error;
	}
	pr_info("found Abit uGuru\n");

	/* Register sysfs hooks */
	for (i = 0; i < sysfs_attr_i; i++) {
		res = device_create_file(&pdev->dev,
					 &data->sysfs_attr[i].dev_attr);
		if (res)
			goto abituguru_probe_error;
	}
	for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++) {
		res = device_create_file(&pdev->dev,
					 &abituguru_sysfs_attr[i].dev_attr);
		if (res)
			goto abituguru_probe_error;
	}

	data->hwmon_dev = hwmon_device_register(&pdev->dev);
	if (!IS_ERR(data->hwmon_dev))
		return 0; /* success */

	res = PTR_ERR(data->hwmon_dev);
abituguru_probe_error:
	for (i = 0; data->sysfs_attr[i].dev_attr.attr.name; i++)
		device_remove_file(&pdev->dev, &data->sysfs_attr[i].dev_attr);
	for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++)
		device_remove_file(&pdev->dev,
			&abituguru_sysfs_attr[i].dev_attr);
	return res;
}