#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
*/
static unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
-static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END };
/*
* Insmod parameters
u8 fan_ripple[3]; /* divider for rps */
};
-/*
- * Internal variables
- */
-
-static int fscher_id = 0;
-
/*
* Sysfs stuff
*/
static DEVICE_ATTR(kind, S_IRUGO, show_##kind##0##sub, NULL);
#define sysfs_fan(offset, reg_status, reg_min, reg_ripple, reg_act) \
-sysfs_rw_n(fan, _pwm , offset, reg_min) \
+sysfs_rw_n(pwm, , offset, reg_min) \
sysfs_rw_n(fan, _status, offset, reg_status) \
sysfs_rw_n(fan, _div , offset, reg_ripple) \
sysfs_ro_n(fan, _input , offset, reg_act)
#define device_create_file_fan(client, offset) \
do { \
device_create_file(&client->dev, &dev_attr_fan##offset##_status); \
- device_create_file(&client->dev, &dev_attr_fan##offset##_pwm); \
+ device_create_file(&client->dev, &dev_attr_pwm##offset); \
device_create_file(&client->dev, &dev_attr_fan##offset##_div); \
device_create_file(&client->dev, &dev_attr_fan##offset##_input); \
} while (0)
/* Fill in the remaining client fields and put it into the
* global list */
strlcpy(new_client->name, "fscher", I2C_NAME_SIZE);
- new_client->id = fscher_id++;
data->valid = 0;
init_MUTEX(&data->update_lock);
down(&data->update_lock);
- if ((jiffies - data->last_updated > 2 * HZ) ||
- (jiffies < data->last_updated) || !data->valid) {
+ if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) {
dev_dbg(&client->dev, "Starting fscher update\n");
{
/* bits 0..1, 3..7 reserved => mask with 0x04 */
unsigned long v = simple_strtoul(buf, NULL, 10) & 0x04;
+
+ down(&data->update_lock);
data->fan_status[FAN_INDEX_FROM_NUM(nr)] &= ~v;
-
fscher_write_value(client, reg, v);
+ up(&data->update_lock);
return count;
}
return sprintf(buf, "%u\n", data->fan_status[FAN_INDEX_FROM_NUM(nr)] & 0x04);
}
-static ssize_t set_fan_pwm(struct i2c_client *client, struct fscher_data *data,
+static ssize_t set_pwm(struct i2c_client *client, struct fscher_data *data,
const char *buf, size_t count, int nr, int reg)
{
- data->fan_min[FAN_INDEX_FROM_NUM(nr)] = simple_strtoul(buf, NULL, 10) & 0xff;
+ unsigned long v = simple_strtoul(buf, NULL, 10);
+ down(&data->update_lock);
+ data->fan_min[FAN_INDEX_FROM_NUM(nr)] = v > 0xff ? 0xff : v;
fscher_write_value(client, reg, data->fan_min[FAN_INDEX_FROM_NUM(nr)]);
+ up(&data->update_lock);
return count;
}
-static ssize_t show_fan_pwm (struct fscher_data *data, char *buf, int nr)
+static ssize_t show_pwm(struct fscher_data *data, char *buf, int nr)
{
return sprintf(buf, "%u\n", data->fan_min[FAN_INDEX_FROM_NUM(nr)]);
}
return -EINVAL;
}
+ down(&data->update_lock);
+
/* bits 2..7 reserved => mask with 0x03 */
data->fan_ripple[FAN_INDEX_FROM_NUM(nr)] &= ~0x03;
data->fan_ripple[FAN_INDEX_FROM_NUM(nr)] |= v;
fscher_write_value(client, reg, data->fan_ripple[FAN_INDEX_FROM_NUM(nr)]);
+ up(&data->update_lock);
return count;
}
{
/* bits 2..7 reserved, 0 read only => mask with 0x02 */
unsigned long v = simple_strtoul(buf, NULL, 10) & 0x02;
- data->temp_status[TEMP_INDEX_FROM_NUM(nr)] &= ~v;
+ down(&data->update_lock);
+ data->temp_status[TEMP_INDEX_FROM_NUM(nr)] &= ~v;
fscher_write_value(client, reg, v);
+ up(&data->update_lock);
return count;
}
{
/* bits 1..7 reserved => mask with 0x01 */
unsigned long v = simple_strtoul(buf, NULL, 10) & 0x01;
- data->global_control &= ~v;
+ down(&data->update_lock);
+ data->global_control &= ~v;
fscher_write_value(client, reg, v);
+ up(&data->update_lock);
return count;
}
{
/* bits 0..3 reserved => mask with 0xf0 */
unsigned long v = simple_strtoul(buf, NULL, 10) & 0xf0;
+
+ down(&data->update_lock);
data->watchdog[2] &= ~0xf0;
data->watchdog[2] |= v;
-
fscher_write_value(client, reg, data->watchdog[2]);
+ up(&data->update_lock);
return count;
}
{
/* bits 0, 2..7 reserved => mask with 0x02 */
unsigned long v = simple_strtoul(buf, NULL, 10) & 0x02;
- data->watchdog[1] &= ~v;
+ down(&data->update_lock);
+ data->watchdog[1] &= ~v;
fscher_write_value(client, reg, v);
+ up(&data->update_lock);
return count;
}
static ssize_t set_watchdog_preset(struct i2c_client *client, struct fscher_data *data,
const char *buf, size_t count, int nr, int reg)
{
- data->watchdog[0] = simple_strtoul(buf, NULL, 10) & 0xff;
-
+ unsigned long v = simple_strtoul(buf, NULL, 10) & 0xff;
+
+ down(&data->update_lock);
+ data->watchdog[0] = v;
fscher_write_value(client, reg, data->watchdog[0]);
+ up(&data->update_lock);
return count;
}