On Thu, 18 Mar 2021 12:01:50 -0700
Guenter Roeck <li...@roeck-us.net> wrote:

> On Thu, Mar 18, 2021 at 03:17:14PM +0100, Wilken Gottwalt wrote:
> > Adds support for reading the critical values of the temperature sensors
> > and the rail sensors (voltage and current) once and caches them. Updates
> > the naming of the constants following a more clear scheme. Also updates
> > the documentation and fixes some typos. Updates is_visible and ops_read
> > functions to be more readable.
> > 
> > The new sensors output of a Corsair HX850i will look like this:
> > corsairpsu-hid-3-1
> > Adapter: HID adapter
> > v_in:        230.00 V
> > v_out +12v:   12.14 V  (crit min =  +8.41 V, crit max = +15.59 V)
> > v_out +5v:     5.03 V  (crit min =  +3.50 V, crit max =  +6.50 V)
> > v_out +3.3v:   3.30 V  (crit min =  +2.31 V, crit max =  +4.30 V)
> > psu fan:        0 RPM
> > vrm temp:     +46.2°C  (crit = +70.0°C)
> > case temp:    +39.8°C  (crit = +70.0°C)
> > power total: 152.00 W
> > power +12v:  108.00 W
> > power +5v:    41.00 W
> > power +3.3v:   5.00 W
> > curr +12v:     9.00 A  (crit max = +85.00 A)
> > curr +5v:      8.31 A  (crit max = +40.00 A)
> > curr +3.3v:    1.62 A  (crit max = +40.00 A)
> > 
> > Signed-off-by: Wilken Gottwalt <wilken.gottw...@posteo.net>
> 
> Applied.

Thank very much. Hmm, I actually could calculate the in_curr value from total
power and the ac input as a replacement if the value can not be read. What do
you think?

> Thanks,
> Guenter
> 
> > ---
> > Changed in v4:
> >   - simplified private data structure and collection of critical values and
> >     unsupported command check
> > 
> > Changes in v3:
> >   - introduced a quirk check function to catch non-working commands
> >   - split is_visible function into subfunctions
> >   - moved the "is value valid" checks into the is_visibility subfunction
> >   - simplified hwmon_ops_read function
> >   - rearranged sysfs entries in the documentation like suggested
> > 
> > Changes in v2:
> >   - simplified reading/caching of critical values and hwmon_ops_read 
> > function
> >   - removed unnecessary debug output and comments
> > ---
> >  Documentation/hwmon/corsair-psu.rst |  13 +-
> >  drivers/hwmon/corsair-psu.c         | 325 +++++++++++++++++++++++-----
> >  2 files changed, 282 insertions(+), 56 deletions(-)
> > 
> > diff --git a/Documentation/hwmon/corsair-psu.rst 
> > b/Documentation/hwmon/corsair-psu.rst
> > index 396b95c9a76a..e8378e7a1d8c 100644
> > --- a/Documentation/hwmon/corsair-psu.rst
> > +++ b/Documentation/hwmon/corsair-psu.rst
> > @@ -47,19 +47,30 @@ Sysfs entries
> >  =======================    
> > ========================================================
> >  curr1_input                Total current usage
> >  curr2_input                Current on the 12v psu rail
> > +curr2_crit         Current max critical value on the 12v psu rail
> >  curr3_input                Current on the 5v psu rail
> > +curr3_crit         Current max critical value on the 5v psu rail
> >  curr4_input                Current on the 3.3v psu rail
> > +curr4_crit         Current max critical value on the 3.3v psu rail
> >  fan1_input         RPM of psu fan
> >  in0_input          Voltage of the psu ac input
> >  in1_input          Voltage of the 12v psu rail
> > +in1_crit           Voltage max critical value on the 12v psu rail
> > +in1_lcrit          Voltage min critical value on the 12v psu rail
> >  in2_input          Voltage of the 5v psu rail
> > -in3_input          Voltage of the 3.3 psu rail
> > +in2_crit           Voltage max critical value on the 5v psu rail
> > +in2_lcrit          Voltage min critical value on the 5v psu rail
> > +in3_input          Voltage of the 3.3v psu rail
> > +in3_crit           Voltage max critical value on the 3.3v psu rail
> > +in3_lcrit          Voltage min critical value on the 3.3v psu rail
> >  power1_input               Total power usage
> >  power2_input               Power usage of the 12v psu rail
> >  power3_input               Power usage of the 5v psu rail
> >  power4_input               Power usage of the 3.3v psu rail
> >  temp1_input                Temperature of the psu vrm component
> > +temp1_crit         Temperature max cirtical value of the psu vrm component
> >  temp2_input                Temperature of the psu case
> > +temp2_crit         Temperature max critical value of psu case
> >  =======================    
> > ========================================================
> >  
> >  Usage Notes
> > diff --git a/drivers/hwmon/corsair-psu.c b/drivers/hwmon/corsair-psu.c
> > index b0953eeeb2d3..3a5807e4a2ef 100644
> > --- a/drivers/hwmon/corsair-psu.c
> > +++ b/drivers/hwmon/corsair-psu.c
> > @@ -53,11 +53,17 @@
> >  #define CMD_TIMEOUT_MS             250
> >  #define SECONDS_PER_HOUR   (60 * 60)
> >  #define SECONDS_PER_DAY            (SECONDS_PER_HOUR * 24)
> > +#define RAIL_COUNT         3 /* 3v3 + 5v + 12v */
> > +#define TEMP_COUNT         2
> >  
> >  #define PSU_CMD_SELECT_RAIL        0x00 /* expects length 2 */
> > -#define PSU_CMD_IN_VOLTS   0x88 /* the rest of the commands expect length 
> > 3 */
> > +#define PSU_CMD_RAIL_VOLTS_HCRIT 0x40 /* the rest of the commands expect 
> > length 3 */
> > +#define PSU_CMD_RAIL_VOLTS_LCRIT 0x44
> > +#define PSU_CMD_RAIL_AMPS_HCRIT    0x46
> > +#define PSU_CMD_TEMP_HCRIT 0x4F
> > +#define PSU_CMD_IN_VOLTS   0x88
> >  #define PSU_CMD_IN_AMPS            0x89
> > -#define PSU_CMD_RAIL_OUT_VOLTS     0x8B
> > +#define PSU_CMD_RAIL_VOLTS 0x8B
> >  #define PSU_CMD_RAIL_AMPS  0x8C
> >  #define PSU_CMD_TEMP0              0x8D
> >  #define PSU_CMD_TEMP1              0x8E
> > @@ -116,6 +122,15 @@ struct corsairpsu_data {
> >     u8 *cmd_buffer;
> >     char vendor[REPLY_SIZE];
> >     char product[REPLY_SIZE];
> > +   long temp_crit[TEMP_COUNT];
> > +   long in_crit[RAIL_COUNT];
> > +   long in_lcrit[RAIL_COUNT];
> > +   long curr_crit[RAIL_COUNT];
> > +   u8 temp_crit_support;
> > +   u8 in_crit_support;
> > +   u8 in_lcrit_support;
> > +   u8 curr_crit_support;
> > +   bool in_curr_cmd_support; /* not all commands are supported on every 
> > PSU */
> >  };
> >  
> >  /* some values are SMBus LINEAR11 data which need a conversion */
> > @@ -193,7 +208,10 @@ static int corsairpsu_request(struct corsairpsu_data 
> > *priv, u8 cmd, u8
> > rail, voi 
> >     mutex_lock(&priv->lock);
> >     switch (cmd) {
> > -   case PSU_CMD_RAIL_OUT_VOLTS:
> > +   case PSU_CMD_RAIL_VOLTS_HCRIT:
> > +   case PSU_CMD_RAIL_VOLTS_LCRIT:
> > +   case PSU_CMD_RAIL_AMPS_HCRIT:
> > +   case PSU_CMD_RAIL_VOLTS:
> >     case PSU_CMD_RAIL_AMPS:
> >     case PSU_CMD_RAIL_WATTS:
> >             ret = corsairpsu_usb_cmd(priv, 2, PSU_CMD_SELECT_RAIL, rail, 
> > NULL);
> > @@ -229,9 +247,13 @@ static int corsairpsu_get_value(struct corsairpsu_data 
> > *priv, u8 cmd, u8
> > rail, l */
> >     tmp = ((long)data[3] << 24) + (data[2] << 16) + (data[1] << 8) + 
> > data[0];
> >     switch (cmd) {
> > +   case PSU_CMD_RAIL_VOLTS_HCRIT:
> > +   case PSU_CMD_RAIL_VOLTS_LCRIT:
> > +   case PSU_CMD_RAIL_AMPS_HCRIT:
> > +   case PSU_CMD_TEMP_HCRIT:
> >     case PSU_CMD_IN_VOLTS:
> >     case PSU_CMD_IN_AMPS:
> > -   case PSU_CMD_RAIL_OUT_VOLTS:
> > +   case PSU_CMD_RAIL_VOLTS:
> >     case PSU_CMD_RAIL_AMPS:
> >     case PSU_CMD_TEMP0:
> >     case PSU_CMD_TEMP1:
> > @@ -256,75 +278,265 @@ static int corsairpsu_get_value(struct 
> > corsairpsu_data *priv, u8 cmd, u8
> > rail, l return ret;
> >  }
> >  
> > -static umode_t corsairpsu_hwmon_ops_is_visible(const void *data, enum 
> > hwmon_sensor_types type,
> > -                                          u32 attr, int channel)
> > +static void corsairpsu_get_criticals(struct corsairpsu_data *priv)
> >  {
> > -   if (type == hwmon_temp && (attr == hwmon_temp_input || attr == 
> > hwmon_temp_label))
> > -           return 0444;
> > -   else if (type == hwmon_fan && (attr == hwmon_fan_input || attr == 
> > hwmon_fan_label))
> > -           return 0444;
> > -   else if (type == hwmon_power && (attr == hwmon_power_input || attr ==
> > hwmon_power_label))
> > -           return 0444;
> > -   else if (type == hwmon_in && (attr == hwmon_in_input || attr == 
> > hwmon_in_label))
> > +   long tmp;
> > +   int rail;
> > +
> > +   for (rail = 0; rail < TEMP_COUNT; ++rail) {
> > +           if (!corsairpsu_get_value(priv, PSU_CMD_TEMP_HCRIT, rail, 
> > &tmp)) {
> > +                   priv->temp_crit_support |= BIT(rail);
> > +                   priv->temp_crit[rail] = tmp;
> > +           }
> > +   }
> > +
> > +   for (rail = 0; rail < RAIL_COUNT; ++rail) {
> > +           if (!corsairpsu_get_value(priv, PSU_CMD_RAIL_VOLTS_HCRIT, rail, 
> > &tmp)) {
> > +                   priv->in_crit_support |= BIT(rail);
> > +                   priv->in_crit[rail] = tmp;
> > +           }
> > +
> > +           if (!corsairpsu_get_value(priv, PSU_CMD_RAIL_VOLTS_LCRIT, rail, 
> > &tmp)) {
> > +                   priv->in_lcrit_support |= BIT(rail);
> > +                   priv->in_lcrit[rail] = tmp;
> > +           }
> > +
> > +           if (!corsairpsu_get_value(priv, PSU_CMD_RAIL_AMPS_HCRIT, rail, 
> > &tmp)) {
> > +                   priv->curr_crit_support |= BIT(rail);
> > +                   priv->curr_crit[rail] = tmp;
> > +           }
> > +   }
> > +}
> > +
> > +static void corsairpsu_check_cmd_support(struct corsairpsu_data *priv)
> > +{
> > +   long tmp;
> > +
> > +   priv->in_curr_cmd_support = !corsairpsu_get_value(priv, 
> > PSU_CMD_IN_AMPS, 0, &tmp);
> > +}
> > +
> > +static umode_t corsairpsu_hwmon_temp_is_visible(const struct 
> > corsairpsu_data *priv, u32 attr,
> > +                                           int channel)
> > +{
> > +   umode_t res = 0444;
> > +
> > +   switch (attr) {
> > +   case hwmon_temp_input:
> > +   case hwmon_temp_label:
> > +   case hwmon_temp_crit:
> > +           if (channel > 0 && !(priv->temp_crit_support & BIT(channel - 
> > 1)))
> > +                   res = 0;
> > +           break;
> > +   default:
> > +           break;
> > +   }
> > +
> > +   return res;
> > +}
> > +
> > +static umode_t corsairpsu_hwmon_fan_is_visible(const struct 
> > corsairpsu_data *priv, u32 attr,
> > +                                          int channel)
> > +{
> > +   switch (attr) {
> > +   case hwmon_fan_input:
> > +   case hwmon_fan_label:
> >             return 0444;
> > -   else if (type == hwmon_curr && (attr == hwmon_curr_input || attr == 
> > hwmon_curr_label))
> > +   default:
> > +           return 0;
> > +   }
> > +}
> > +
> > +static umode_t corsairpsu_hwmon_power_is_visible(const struct 
> > corsairpsu_data *priv, u32 attr,
> > +                                            int channel)
> > +{
> > +   switch (attr) {
> > +   case hwmon_power_input:
> > +   case hwmon_power_label:
> >             return 0444;
> > +   default:
> > +           return 0;
> > +   };
> > +}
> >  
> > -   return 0;
> > +static umode_t corsairpsu_hwmon_in_is_visible(const struct corsairpsu_data 
> > *priv, u32 attr,
> > +                                         int channel)
> > +{
> > +   umode_t res = 0444;
> > +
> > +   switch (attr) {
> > +   case hwmon_in_input:
> > +   case hwmon_in_label:
> > +   case hwmon_in_crit:
> > +           if (channel > 0 && !(priv->in_crit_support & BIT(channel - 1)))
> > +                   res = 0;
> > +           break;
> > +   case hwmon_in_lcrit:
> > +           if (channel > 0 && !(priv->in_lcrit_support & BIT(channel - 1)))
> > +                   res = 0;
> > +           break;
> > +   default:
> > +           break;
> > +   };
> > +
> > +   return res;
> >  }
> >  
> > -static int corsairpsu_hwmon_ops_read(struct device *dev, enum 
> > hwmon_sensor_types type, u32
> > attr,
> > -                                int channel, long *val)
> > +static umode_t corsairpsu_hwmon_curr_is_visible(const struct 
> > corsairpsu_data *priv, u32 attr,
> > +                                           int channel)
> >  {
> > -   struct corsairpsu_data *priv = dev_get_drvdata(dev);
> > -   int ret;
> > +   umode_t res = 0444;
> >  
> > -   if (type == hwmon_temp && attr == hwmon_temp_input && channel < 2) {
> > -           ret = corsairpsu_get_value(priv, channel ? PSU_CMD_TEMP1 : 
> > PSU_CMD_TEMP0,
> > channel,
> > -                                      val);
> > -   } else if (type == hwmon_fan && attr == hwmon_fan_input) {
> > -           ret = corsairpsu_get_value(priv, PSU_CMD_FAN, 0, val);
> > -   } else if (type == hwmon_power && attr == hwmon_power_input) {
> > +   switch (attr) {
> > +   case hwmon_curr_input:
> > +           if (channel == 0 && !priv->in_curr_cmd_support)
> > +                   res = 0;
> > +           break;
> > +   case hwmon_curr_label:
> > +   case hwmon_curr_crit:
> > +           if (channel > 0 && !(priv->curr_crit_support & BIT(channel - 
> > 1)))
> > +                   res = 0;
> > +           break;
> > +   default:
> > +           break;
> > +   }
> > +
> > +   return res;
> > +}
> > +
> > +static umode_t corsairpsu_hwmon_ops_is_visible(const void *data, enum 
> > hwmon_sensor_types type,
> > +                                          u32 attr, int channel)
> > +{
> > +   const struct corsairpsu_data *priv = data;
> > +
> > +   switch (type) {
> > +   case hwmon_temp:
> > +           return corsairpsu_hwmon_temp_is_visible(priv, attr, channel);
> > +   case hwmon_fan:
> > +           return corsairpsu_hwmon_fan_is_visible(priv, attr, channel);
> > +   case hwmon_power:
> > +           return corsairpsu_hwmon_power_is_visible(priv, attr, channel);
> > +   case hwmon_in:
> > +           return corsairpsu_hwmon_in_is_visible(priv, attr, channel);
> > +   case hwmon_curr:
> > +           return corsairpsu_hwmon_curr_is_visible(priv, attr, channel);
> > +   default:
> > +           return 0;
> > +   }
> > +}
> > +
> > +static int corsairpsu_hwmon_temp_read(struct corsairpsu_data *priv, u32 
> > attr, int channel,
> > +                                 long *val)
> > +{
> > +   int err = -EOPNOTSUPP;
> > +
> > +   switch (attr) {
> > +   case hwmon_temp_input:
> > +           return corsairpsu_get_value(priv, channel ? PSU_CMD_TEMP1 : 
> > PSU_CMD_TEMP0,
> > +                                       channel, val);
> > +   case hwmon_temp_crit:
> > +           *val = priv->temp_crit[channel];
> > +           err = 0;
> > +           break;
> > +   default:
> > +           break;
> > +   }
> > +
> > +   return err;
> > +}
> > +
> > +static int corsairpsu_hwmon_power_read(struct corsairpsu_data *priv, u32 
> > attr, int channel,
> > +                                  long *val)
> > +{
> > +   if (attr == hwmon_power_input) {
> >             switch (channel) {
> >             case 0:
> > -                   ret = corsairpsu_get_value(priv, PSU_CMD_TOTAL_WATTS, 
> > 0, val);
> > -                   break;
> > +                   return corsairpsu_get_value(priv, PSU_CMD_TOTAL_WATTS, 
> > 0, val);
> >             case 1 ... 3:
> > -                   ret = corsairpsu_get_value(priv, PSU_CMD_RAIL_WATTS, 
> > channel - 1, val);
> > -                   break;
> > +                   return corsairpsu_get_value(priv, PSU_CMD_RAIL_WATTS, 
> > channel - 1,
> > val); default:
> > -                   return -EOPNOTSUPP;
> > +                   break;
> >             }
> > -   } else if (type == hwmon_in && attr == hwmon_in_input) {
> > +   }
> > +
> > +   return -EOPNOTSUPP;
> > +}
> > +
> > +static int corsairpsu_hwmon_in_read(struct corsairpsu_data *priv, u32 
> > attr, int channel, long
> > *val) +{
> > +   int err = -EOPNOTSUPP;
> > +
> > +   switch (attr) {
> > +   case hwmon_in_input:
> >             switch (channel) {
> >             case 0:
> > -                   ret = corsairpsu_get_value(priv, PSU_CMD_IN_VOLTS, 0, 
> > val);
> > -                   break;
> > +                   return corsairpsu_get_value(priv, PSU_CMD_IN_VOLTS, 0, 
> > val);
> >             case 1 ... 3:
> > -                   ret = corsairpsu_get_value(priv, 
> > PSU_CMD_RAIL_OUT_VOLTS, channel - 1,
> > val);
> > -                   break;
> > +                   return corsairpsu_get_value(priv, PSU_CMD_RAIL_VOLTS, 
> > channel - 1,
> > val); default:
> > -                   return -EOPNOTSUPP;
> > +                   break;
> >             }
> > -   } else if (type == hwmon_curr && attr == hwmon_curr_input) {
> > +           break;
> > +   case hwmon_in_crit:
> > +           *val = priv->in_crit[channel - 1];
> > +           err = 0;
> > +           break;
> > +   case hwmon_in_lcrit:
> > +           *val = priv->in_lcrit[channel - 1];
> > +           err = 0;
> > +           break;
> > +   }
> > +
> > +   return err;
> > +}
> > +
> > +static int corsairpsu_hwmon_curr_read(struct corsairpsu_data *priv, u32 
> > attr, int channel,
> > +                                 long *val)
> > +{
> > +   int err = -EOPNOTSUPP;
> > +
> > +   switch (attr) {
> > +   case hwmon_curr_input:
> >             switch (channel) {
> >             case 0:
> > -                   ret = corsairpsu_get_value(priv, PSU_CMD_IN_AMPS, 0, 
> > val);
> > -                   break;
> > +                   return corsairpsu_get_value(priv, PSU_CMD_IN_AMPS, 0, 
> > val);
> >             case 1 ... 3:
> > -                   ret = corsairpsu_get_value(priv, PSU_CMD_RAIL_AMPS, 
> > channel - 1, val);
> > -                   break;
> > +                   return corsairpsu_get_value(priv, PSU_CMD_RAIL_AMPS, 
> > channel - 1, val);
> >             default:
> > -                   return -EOPNOTSUPP;
> > +                   break;
> >             }
> > -   } else {
> > -           return -EOPNOTSUPP;
> > +           break;
> > +   case hwmon_curr_crit:
> > +           *val = priv->curr_crit[channel - 1];
> > +           err = 0;
> > +           break;
> > +   default:
> > +           break;
> >     }
> >  
> > -   if (ret < 0)
> > -           return ret;
> > +   return err;
> > +}
> >  
> > -   return 0;
> > +static int corsairpsu_hwmon_ops_read(struct device *dev, enum 
> > hwmon_sensor_types type, u32
> > attr,
> > +                                int channel, long *val)
> > +{
> > +   struct corsairpsu_data *priv = dev_get_drvdata(dev);
> > +
> > +   switch (type) {
> > +   case hwmon_temp:
> > +           return corsairpsu_hwmon_temp_read(priv, attr, channel, val);
> > +   case hwmon_fan:
> > +           if (attr == hwmon_fan_input)
> > +                   return corsairpsu_get_value(priv, PSU_CMD_FAN, 0, val);
> > +           return -EOPNOTSUPP;
> > +   case hwmon_power:
> > +           return corsairpsu_hwmon_power_read(priv, attr, channel, val);
> > +   case hwmon_in:
> > +           return corsairpsu_hwmon_in_read(priv, attr, channel, val);
> > +   case hwmon_curr:
> > +           return corsairpsu_hwmon_curr_read(priv, attr, channel, val);
> > +   default:
> > +           return -EOPNOTSUPP;
> > +   }
> >  }
> >  
> >  static int corsairpsu_hwmon_ops_read_string(struct device *dev, enum 
> > hwmon_sensor_types type,
> > @@ -360,8 +572,8 @@ static const struct hwmon_channel_info 
> > *corsairpsu_info[] = {
> >     HWMON_CHANNEL_INFO(chip,
> >                        HWMON_C_REGISTER_TZ),
> >     HWMON_CHANNEL_INFO(temp,
> > -                      HWMON_T_INPUT | HWMON_T_LABEL,
> > -                      HWMON_T_INPUT | HWMON_T_LABEL),
> > +                      HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_CRIT,
> > +                      HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_CRIT),
> >     HWMON_CHANNEL_INFO(fan,
> >                        HWMON_F_INPUT | HWMON_F_LABEL),
> >     HWMON_CHANNEL_INFO(power,
> > @@ -371,14 +583,14 @@ static const struct hwmon_channel_info 
> > *corsairpsu_info[] = {
> >                        HWMON_P_INPUT | HWMON_P_LABEL),
> >     HWMON_CHANNEL_INFO(in,
> >                        HWMON_I_INPUT | HWMON_I_LABEL,
> > -                      HWMON_I_INPUT | HWMON_I_LABEL,
> > -                      HWMON_I_INPUT | HWMON_I_LABEL,
> > -                      HWMON_I_INPUT | HWMON_I_LABEL),
> > +                      HWMON_I_INPUT | HWMON_I_LABEL | HWMON_I_LCRIT | 
> > HWMON_I_CRIT,
> > +                      HWMON_I_INPUT | HWMON_I_LABEL | HWMON_I_LCRIT | 
> > HWMON_I_CRIT,
> > +                      HWMON_I_INPUT | HWMON_I_LABEL | HWMON_I_LCRIT | 
> > HWMON_I_CRIT),
> >     HWMON_CHANNEL_INFO(curr,
> >                        HWMON_C_INPUT | HWMON_C_LABEL,
> > -                      HWMON_C_INPUT | HWMON_C_LABEL,
> > -                      HWMON_C_INPUT | HWMON_C_LABEL,
> > -                      HWMON_C_INPUT | HWMON_C_LABEL),
> > +                      HWMON_C_INPUT | HWMON_C_LABEL | HWMON_C_CRIT,
> > +                      HWMON_C_INPUT | HWMON_C_LABEL | HWMON_C_CRIT,
> > +                      HWMON_C_INPUT | HWMON_C_LABEL | HWMON_C_CRIT),
> >     NULL
> >  };
> >  
> > @@ -513,6 +725,9 @@ static int corsairpsu_probe(struct hid_device *hdev, 
> > const struct
> > hid_device_id goto fail_and_stop;
> >     }
> >  
> > +   corsairpsu_get_criticals(priv);
> > +   corsairpsu_check_cmd_support(priv);
> > +
> >     priv->hwmon_dev = hwmon_device_register_with_info(&hdev->dev, 
> > "corsairpsu", priv,
> >                                                       
> > &corsairpsu_chip_info, 0);
> >  

Reply via email to