[PATCH linux 1/7] hwmon: Add core On-Chip Controller support for POWER CPUs

Andrew Jeffery andrew at aj.id.au
Tue Dec 20 11:05:36 AEDT 2016


Hi Eddie,

On Mon, 2016-12-19 at 17:05 -0600, Eddie James wrote:
...
> > > +
> > > +static int parse_occ_response(struct occ *driver, u8 *data,
> > > > +                         struct occ_response *resp)
> > > 
> > > +{
> > > > +   int b;
> > > > +   int s;
> > > > +   int rc;
> > > > +   int offset = SENSOR_BLOCK_OFFSET;
> > > > +   int sensor_type;
> > > > +   u8 sensor_block_num;
> > > 
> > > +     char sensor_type_string[5] = { 0 };
> > 
> > Given how you rearranged things below, do you think we can get away
> > with removing sensor_type_string? Also, struct sensor_data_block_type
> > defines sensor_type as a char * that can't be null-terminated as its
> > size is 4, which still makes me feel uncomfortable. What are your
> > thoughts here?
> 
> The idea of sensor_type_string was to have a null-terminated string
> that I could use in the debug statements below. sensor_type is
> restricted to 4 chars because that's how its' formatted in the OCC
> data block. Anywhere I use sensor_type I use the length-limited string
> function, such as strncmp or the like, and restrict it to 4 chars. I
> feel this is an acceptable solution, but you're right,
> sensor_type_string isn't strictly necessary, just useful to be able to
> print that out.

Okay, I'm happy with that.

> 
> > > +
> > > +static u8 occ_send_cmd(struct occ *driver, u8 seq, u8 type, u16
> > > length,
> > > > +                  u8 *data, u8 *resp)
> > > 
> > > +{
> > > > +   u32 cmd1, cmd2;
> > > > +   u16 checksum = 0;
> > > > +   u16 length_be = cpu_to_be16(length);
> > > > +   int i, rc, tries = 0;
> > > 
> > > +     const int max_tries = (OCC_BMC_TIMEOUT_S * 1000) /
> > > CMD_IN_PRG_INT_MS;
> > 
> > I expect we should just #define the expression?
> > 
> > > +
> > > > +   cmd1 = (seq << 24) | (type << 16) | length_be;
> > > > +   memcpy(&cmd2, data, length);
> > > > +   cmd2 <<= ((4 - length) * 8);
> > > 
> > > +
> > > > +   /* checksum: sum of every bytes of cmd1, cmd2 */
> > > > +   for (i = 0; i < 4; i++) {
> > > > +           checksum += (cmd1 >> (i * 8)) & 0xFF;
> > > 
> > > +             checksum += (cmd2 >> (i * 8)) & 0xFF;
> > 
> > I have to apologise here, as my review was wrong: Addition is
> > commutative, but not when we're masking the result! So the original
> > approach is probably more correct, and it only occurred to me when
> > reading over this patch. Sorry! Did you get checksum errors as a
> > result?
> 
> No worries, I didn't catch it either, but I think it worked out OK
> since the mask is really applied to the shifted cmd, 

Yes, I thought about this further after I sent the email and I agree.

> but I will test
> both ways to make sure... Thanks!
> 
> > 
> > > +     }
> > > +
> > > > +   cmd2 |= checksum << ((2 - length) * 8);
> > > 
> > > +
> > > > +   /* Init OCB */
> > > > +   rc = driver->bus_ops.putscom(driver->bus,
> > > > OCB_STATUS_CONTROL_OR,
> > > > +                                OCB_OR_INIT0, OCB_OR_INIT1);
> > > > +   if (rc)
> > > > +           goto err;
> > > 
> > > +
> > > > +   rc = driver->bus_ops.putscom(driver->bus,
> > > > OCB_STATUS_CONTROL_AND,
> > > > +                                OCB_AND_INIT0,
> > > > OCB_AND_INIT1);
> > > > +   if (rc)
> > > > +           goto err;
> > > 
> > > +
> > > > +   /* Send command, 2nd half of the 64-bit addr is unused
> > > > (write 0) */
> > > > +   rc = driver->bus_ops.putscom(driver->bus, OCB_ADDRESS,
> > > > +                                driver->config.command_addr,
> > > > 0);
> > > > +   if (rc)
> > > > +           goto err;
> > > 
> > > +
> > > > +   rc = driver->bus_ops.putscom(driver->bus, OCB_ADDRESS,
> > > > +                                driver->config.command_addr,
> > > > 0);
> > > > +   if (rc)
> > > 
> > > +             goto err;
> > 
> > This change highlighted to me that we're sending command_addr twice -
> > is this necessary?
> 
> I'm not sure... I'll test both without and see if everything works OK.
> I noticed it was sent twice, but I assumed Yi had some reason for
> doing it.

I think this will be a win either way: Either we remove one, or we
document why we send it twice.

> 
> > 
> > > +
> > > > +   rc = driver->bus_ops.putscom(driver->bus, OCB_DATA, cmd1,
> > > > cmd2);
> > > > +   if (rc)
> > > > +           goto err;
> > > 
> > > +
> > > > +   /* Trigger attention */
> > > > +   rc = driver->bus_ops.putscom(driver->bus, ATTN_DATA,
> > > > ATTN0, ATTN1);
> > > > +   if (rc)
> > > > +           goto err;
> > > 
> > > +
> > > > +   /* Get response data */
> > > > +   rc = driver->bus_ops.putscom(driver->bus, OCB_ADDRESS,
> > > > +                                driver->config.response_addr,
> > > > 0);
> > > > +   if (rc)
> > > > +           goto err;
> > > 
> > > +
> > > > +   do {
> > > > +           rc = driver->bus_ops.getscom(driver->bus,
> > > > OCB_DATA, resp);
> > > > +           if (rc)
> > > > +                   goto err;
> > > 
> > > +
> > > > +           /* retry if we get "command in progress" return
> > > > status */
> > > > +           if (resp[RESP_RETURN_STATUS] ==
> > > > RESP_RETURN_CMD_IN_PRG) {
> > > > +                   set_current_state(TASK_INTERRUPTIBLE);
> > > > +                   schedule_timeout(msecs_to_jiffies(CMD_IN_P
> > > > RG_INT_MS));
> > > > +                   tries++;
> > > > +           } else
> > > > +                   break;
> > > 
> > > +     } while (tries < max_tries);
> > 
> > I'll bikeshed this to try save the break and a timeout, which is really
> > picking at the nits but reduces cyclomatic complexity and saves some
> > time. What do you think of:
> > 
> >     bool retry = false;
> >     int tries = 0;
> > 
> >     ...
> > 
> >     do {
> >         if (retry) {
> >             set_current_state(TASK_INTERRUPTIBLE);
> >             shedule_timeout(msecs_to_jiffies(CMD_IN_PRG_INT_MS));
> >         }
> > 
> >         rc = driver->bus_ops.getscom(driver->bus, OCB_DATA, resp);
> >         if (rc)
> >             goto err;
> > 
> >         retry = (resp[RESP_RETURN_STATUS] == RESP_RETURN_CMD_IN_PRG) && tries++ < max_tries);
> >     } while (retry);
> > 
> > Are we okay with returning RESP_RETURN_CMD_IN_PRG to the caller?
> > Because that's what happens in either case if we exceed max_tries.
> 
> Looks a little bit cleaner, I'll incorporate this. And yes, any
> non-zero return will be flagged as an error. If we timeout and are are
> still getting the busy response we do want an error.

But a "kernel" error? Or the value RESP_RETURN_CMD_IN_PRG?

Andrew
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: This is a digitally signed message part
URL: <http://lists.ozlabs.org/pipermail/openbmc/attachments/20161220/b1dedcaf/attachment.sig>


More information about the openbmc mailing list