Jean Delvare wrote: > The new-style fschmd driver implements the optional detect() callback > to cover the use cases of the legacy driver. > > Signed-off-by: Jean Delvare <khali at linux-fr.org> > Cc: Hans de Goede <j.w.r.degoede at hhs.nl> Tested as promised, still works fine. Signed-off-by: Hans de Goede <j.w.r.degoede at hhs.nl> Regards, Hans > --- > drivers/hwmon/fschmd.c | 112 ++++++++++++++++++++++++------------------------ > 1 file changed, 57 insertions(+), 55 deletions(-) > > --- linux-2.6.26-rc9.orig/drivers/hwmon/fschmd.c 2008-07-12 09:20:30.000000000 +0200 > +++ linux-2.6.26-rc9/drivers/hwmon/fschmd.c 2008-07-12 10:27:23.000000000 +0200 > @@ -171,20 +171,37 @@ static const int FSCHMD_NO_TEMP_SENSORS[ > * Functions declarations > */ > > -static int fschmd_attach_adapter(struct i2c_adapter *adapter); > -static int fschmd_detach_client(struct i2c_client *client); > +static int fschmd_probe(struct i2c_client *client, > + const struct i2c_device_id *id); > +static int fschmd_detect(struct i2c_client *client, int kind, > + struct i2c_board_info *info); > +static int fschmd_remove(struct i2c_client *client); > static struct fschmd_data *fschmd_update_device(struct device *dev); > > /* > * Driver data (common to all clients) > */ > > +static const struct i2c_device_id fschmd_id[] = { > + { "fscpos", fscpos }, > + { "fscher", fscher }, > + { "fscscy", fscscy }, > + { "fschrc", fschrc }, > + { "fschmd", fschmd }, > + { } > +}; > +MODULE_DEVICE_TABLE(i2c, fschmd_id); > + > static struct i2c_driver fschmd_driver = { > + .class = I2C_CLASS_HWMON, > .driver = { > .name = FSCHMD_NAME, > }, > - .attach_adapter = fschmd_attach_adapter, > - .detach_client = fschmd_detach_client, > + .probe = fschmd_probe, > + .remove = fschmd_remove, > + .id_table = fschmd_id, > + .detect = fschmd_detect, > + .address_data = &addr_data, > }; > > /* > @@ -192,7 +209,6 @@ static struct i2c_driver fschmd_driver = > */ > > struct fschmd_data { > - struct i2c_client client; > struct device *hwmon_dev; > struct mutex update_lock; > int kind; > @@ -269,7 +285,7 @@ static ssize_t store_temp_max(struct dev > v = SENSORS_LIMIT(v, -128, 127) + 128; > > mutex_lock(&data->update_lock); > - i2c_smbus_write_byte_data(&data->client, > + i2c_smbus_write_byte_data(to_i2c_client(dev), > FSCHMD_REG_TEMP_LIMIT[data->kind][index], v); > data->temp_max[index] = v; > mutex_unlock(&data->update_lock); > @@ -346,14 +362,14 @@ static ssize_t store_fan_div(struct devi > > mutex_lock(&data->update_lock); > > - reg = i2c_smbus_read_byte_data(&data->client, > + reg = i2c_smbus_read_byte_data(to_i2c_client(dev), > FSCHMD_REG_FAN_RIPPLE[data->kind][index]); > > /* bits 2..7 reserved => mask with 0x03 */ > reg &= ~0x03; > reg |= v; > > - i2c_smbus_write_byte_data(&data->client, > + i2c_smbus_write_byte_data(to_i2c_client(dev), > FSCHMD_REG_FAN_RIPPLE[data->kind][index], reg); > > data->fan_ripple[index] = reg; > @@ -416,7 +432,7 @@ static ssize_t store_pwm_auto_point1_pwm > > mutex_lock(&data->update_lock); > > - i2c_smbus_write_byte_data(&data->client, > + i2c_smbus_write_byte_data(to_i2c_client(dev), > FSCHMD_REG_FAN_MIN[data->kind][index], v); > data->fan_min[index] = v; > > @@ -448,14 +464,14 @@ static ssize_t store_alert_led(struct de > > mutex_lock(&data->update_lock); > > - reg = i2c_smbus_read_byte_data(&data->client, FSCHMD_REG_CONTROL); > + reg = i2c_smbus_read_byte_data(to_i2c_client(dev), FSCHMD_REG_CONTROL); > > if (v) > reg |= FSCHMD_CONTROL_ALERT_LED_MASK; > else > reg &= ~FSCHMD_CONTROL_ALERT_LED_MASK; > > - i2c_smbus_write_byte_data(&data->client, FSCHMD_REG_CONTROL, reg); > + i2c_smbus_write_byte_data(to_i2c_client(dev), FSCHMD_REG_CONTROL, reg); > > data->global_control = reg; > > @@ -600,32 +616,15 @@ static void fschmd_dmi_decode(const stru > } > } > > -static int fschmd_detect(struct i2c_adapter *adapter, int address, int kind) > +static int fschmd_detect(struct i2c_client *client, int kind, > + struct i2c_board_info *info) > { > - struct i2c_client *client; > - struct fschmd_data *data; > - u8 revision; > - const char * const names[5] = { "Poseidon", "Hermes", "Scylla", > - "Heracles", "Heimdall" }; > + struct i2c_adapter *adapter = client->adapter; > const char * const client_names[5] = { "fscpos", "fscher", "fscscy", > "fschrc", "fschmd" }; > - int i, err = 0; > > if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) > - return 0; > - > - /* OK. For now, we presume we have a valid client. We now create the > - * client structure, even though we cannot fill it completely yet. > - * But it allows us to access i2c_smbus_read_byte_data. */ > - if (!(data = kzalloc(sizeof(struct fschmd_data), GFP_KERNEL))) > - return -ENOMEM; > - > - client = &data->client; > - i2c_set_clientdata(client, data); > - client->addr = address; > - client->adapter = adapter; > - client->driver = &fschmd_driver; > - mutex_init(&data->update_lock); > + return -ENODEV; > > /* Detect & Identify the chip */ > if (kind <= 0) { > @@ -650,9 +649,31 @@ static int fschmd_detect(struct i2c_adap > else if (!strcmp(id, "HMD")) > kind = fschmd; > else > - goto exit_free; > + return -ENODEV; > } > > + strlcpy(info->type, client_names[kind - 1], I2C_NAME_SIZE); > + > + return 0; > +} > + > +static int fschmd_probe(struct i2c_client *client, > + const struct i2c_device_id *id) > +{ > + struct fschmd_data *data; > + u8 revision; > + const char * const names[5] = { "Poseidon", "Hermes", "Scylla", > + "Heracles", "Heimdall" }; > + int i, err; > + enum chips kind = id->driver_data; > + > + data = kzalloc(sizeof(struct fschmd_data), GFP_KERNEL); > + if (!data) > + return -ENOMEM; > + > + i2c_set_clientdata(client, data); > + mutex_init(&data->update_lock); > + > if (kind == fscpos) { > /* The Poseidon has hardwired temp limits, fill these > in for the alarm resetting code */ > @@ -674,11 +695,6 @@ static int fschmd_detect(struct i2c_adap > > /* i2c kind goes from 1-5, we want from 0-4 to address arrays */ > data->kind = kind - 1; > - strlcpy(client->name, client_names[data->kind], I2C_NAME_SIZE); > - > - /* Tell the I2C layer a new client has arrived */ > - if ((err = i2c_attach_client(client))) > - goto exit_free; > > for (i = 0; i < ARRAY_SIZE(fschmd_attr); i++) { > err = device_create_file(&client->dev, > @@ -726,25 +742,14 @@ static int fschmd_detect(struct i2c_adap > return 0; > > exit_detach: > - fschmd_detach_client(client); /* will also free data for us */ > - return err; > - > -exit_free: > - kfree(data); > + fschmd_remove(client); /* will also free data for us */ > return err; > } > > -static int fschmd_attach_adapter(struct i2c_adapter *adapter) > -{ > - if (!(adapter->class & I2C_CLASS_HWMON)) > - return 0; > - return i2c_probe(adapter, &addr_data, fschmd_detect); > -} > - > -static int fschmd_detach_client(struct i2c_client *client) > +static int fschmd_remove(struct i2c_client *client) > { > struct fschmd_data *data = i2c_get_clientdata(client); > - int i, err; > + int i; > > /* Check if registered in case we're called from fschmd_detect > to cleanup after an error */ > @@ -760,9 +765,6 @@ static int fschmd_detach_client(struct i > device_remove_file(&client->dev, > &fschmd_fan_attr[i].dev_attr); > > - if ((err = i2c_detach_client(client))) > - return err; > - > kfree(data); > return 0; > } > >