Re: [PATCH net-next v3 2/2] ptp: Add a ptp clock driver for IDT 82P33 SMU.

From: Richard Cochran
Date: Fri Feb 21 2020 - 06:51:36 EST


On Thu, Feb 20, 2020 at 04:28:29PM -0500, min.li.xe@xxxxxxxxxxx wrote:

> +module_param(phase_snap_threshold, uint, 0);
> +MODULE_PARM_DESC(phase_snap_threshold,
> +"threshold in nanosecond below which adjtime would ignore and do nothing");

If it is important not to snap small offsets, can't the driver
calculate the threshold itself? It will be difficult for users to
guess this value.

> +/* static function declaration for ptp_clock_info*/
> +
> +static int idt82p33_enable(struct ptp_clock_info *ptp,
> + struct ptp_clock_request *rq, int on);
> +
> +static int idt82p33_adjfreq(struct ptp_clock_info *ptp, s32 ppb);
> +
> +static int idt82p33_settime(struct ptp_clock_info *ptp,
> + const struct timespec64 *ts);
> +
> +static int idt82p33_adjtime(struct ptp_clock_info *ptp, s64 delta_ns);
> +
> +static int idt82p33_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts);
> +
> +static void idt82p33_sync_tod_work_handler(struct work_struct *work);

As a matter of coding style, forward declarations are to be avoided in
network drivers. You can avoid these by moving the functions,
idt82p33_channel_init() and idt82p33_caps_init() further down.

> +static void idt82p33_byte_array_to_timespec(struct timespec64 *ts,
> +static void idt82p33_timespec_to_byte_array(struct timespec64 const *ts,
> +static int idt82p33_xfer(struct idt82p33 *idt82p33,

These three are identical to the functions in ptp_clockmatrix.c. Why
not introduce a common, shared source file to refactor this code?

> +static int idt82p33_page_offset(struct idt82p33 *idt82p33, unsigned char val)
> +static int idt82p33_rdwr(struct idt82p33 *idt82p33, unsigned int regaddr,
> +static int idt82p33_read(struct idt82p33 *idt82p33, unsigned int regaddr,
> +static int idt82p33_write(struct idt82p33 *idt82p33, unsigned int regaddr,

If I am not wrong, these are identical as well.

> +static int idt82p33_enable_channel(struct idt82p33 *idt82p33, u32 index)
> +{
> + struct idt82p33_channel *channel;
> + int err;
> +
> + if (!(index < MAX_PHC_PLL))
> + return -EINVAL;
> +
> + channel = &idt82p33->channel[index];
> +
> + err = idt82p33_channel_init(channel, index);
> + if (err)
> + return err;
> +
> + channel->idt82p33 = idt82p33;
> +
> + idt82p33_caps_init(&channel->caps);
> + snprintf(channel->caps.name, sizeof(channel->caps.name),
> + "IDT 82P33 PLL%u", index);
> + channel->caps.n_per_out = hweight8(channel->output_mask);
> +
> + err = idt82p33_dpll_set_mode(channel, PLL_MODE_DCO);
> + if (err)
> + return err;
> +
> + err = idt82p33_enable_tod(channel);
> + if (err)
> + return err;
> +
> + channel->ptp_clock = ptp_clock_register(&channel->caps, NULL);
> +
> + if (IS_ERR(channel->ptp_clock)) {
> + err = PTR_ERR(channel->ptp_clock);
> + channel->ptp_clock = NULL;
> + return err;
> + }

The function, ptp_clock_register(), can also return NULL. Please
handle that case as well.

> +
> + if (!channel->ptp_clock)
> + return -ENOTSUPP;
> +
> + dev_info(&idt82p33->client->dev, "PLL%d registered as ptp%d\n",
> + index, channel->ptp_clock->index);
> +
> + return 0;
> +}


> +static int idt82p33_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
> +{

Please implement the .adjfine() method instead. It offers better
resolution.

(The .adjfreq() method is deprecated.)

> + struct idt82p33_channel *channel =
> + container_of(ptp, struct idt82p33_channel, caps);
> + struct idt82p33 *idt82p33 = channel->idt82p33;
> + int err;
> +
> + mutex_lock(&idt82p33->reg_lock);
> + err = _idt82p33_adjfreq(channel, ppb);
> + mutex_unlock(&idt82p33->reg_lock);
> +
> + return err;
> +}

Thanks,
Richard