All of lore.kernel.org
 help / color / mirror / Atom feed
From: Vadim Fedorenko <vadim.fedorenko@linux.dev>
To: Jiri Pirko <jiri@resnulli.us>, Vadim Fedorenko <vadfed@meta.com>
Cc: Jakub Kicinski <kuba@kernel.org>,
	Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>,
	Jonathan Lemon <jonathan.lemon@gmail.com>,
	Paolo Abeni <pabeni@redhat.com>,
	poros@redhat.com, mschmidt@redhat.com, netdev@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, linux-clk@vger.kernel.org
Subject: Re: [PATCH RFC v6 6/6] ptp_ocp: implement DPLL ops
Date: Wed, 15 Mar 2023 00:10:33 +0000	[thread overview]
Message-ID: <d192e0ac-3fa3-c799-ac93-84a17e6f6d50@linux.dev> (raw)
In-Reply-To: <ZBBG2xRhLOIPMD0+@nanopsycho>

On 14/03/2023 10:05, Jiri Pirko wrote:
> Sun, Mar 12, 2023 at 03:28:07AM CET, vadfed@meta.com wrote:
>> Implement basic DPLL operations in ptp_ocp driver as the
>> simplest example of using new subsystem.
>>
>> Signed-off-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
>> ---
>> drivers/ptp/Kconfig   |   1 +
>> drivers/ptp/ptp_ocp.c | 209 ++++++++++++++++++++++++++++++++++++++++--
>> 2 files changed, 200 insertions(+), 10 deletions(-)
>>
>> diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig
>> index fe4971b65c64..8c4cfabc1bfa 100644
>> --- a/drivers/ptp/Kconfig
>> +++ b/drivers/ptp/Kconfig
>> @@ -177,6 +177,7 @@ config PTP_1588_CLOCK_OCP
>> 	depends on COMMON_CLK
>> 	select NET_DEVLINK
>> 	select CRC16
>> +	select DPLL
>> 	help
>> 	  This driver adds support for an OpenCompute time card.
>>
>> diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
>> index 4bbaccd543ad..02c95e724ec8 100644
>> --- a/drivers/ptp/ptp_ocp.c
>> +++ b/drivers/ptp/ptp_ocp.c
>> @@ -23,6 +23,8 @@
>> #include <linux/mtd/mtd.h>
>> #include <linux/nvmem-consumer.h>
>> #include <linux/crc16.h>
>> +#include <linux/dpll.h>
>> +#include <uapi/linux/dpll.h>
> 
> Don't include UAPI directly. I'm pretty sure I had this comment earlier.
> 

Ah, yeah, you've mentioned it for ice driver last time, but I forgot to 
check it here. Removed.

> 
>>
>> #define PCI_VENDOR_ID_FACEBOOK			0x1d9b
>> #define PCI_DEVICE_ID_FACEBOOK_TIMECARD		0x0400
>> @@ -267,6 +269,7 @@ struct ptp_ocp_sma_connector {
>> 	bool	fixed_dir;
>> 	bool	disabled;
>> 	u8	default_fcn;
>> +	struct dpll_pin *dpll_pin;
>> };
>>
>> struct ocp_attr_group {
>> @@ -353,6 +356,7 @@ struct ptp_ocp {
>> 	struct ptp_ocp_signal	signal[4];
>> 	struct ptp_ocp_sma_connector sma[4];
> 
> It is quite customary to use defines for const numbers like this. Why
> don't you do that in ptp_ocp?

Historical reasons. Jonathan might answer this question.
I will add it to my TODO list for the driver.

>> 	const struct ocp_sma_op *sma_op;
>> +	struct dpll_device *dpll;
>> };
>>
>> #define OCP_REQ_TIMESTAMP	BIT(0)
>> @@ -2689,16 +2693,9 @@ sma4_show(struct device *dev, struct device_attribute *attr, char *buf)
>> }
>>
>> static int
>> -ptp_ocp_sma_store(struct ptp_ocp *bp, const char *buf, int sma_nr)
>> +ptp_ocp_sma_store_val(struct ptp_ocp *bp, int val, enum ptp_ocp_sma_mode mode, int sma_nr)
>> {
>> 	struct ptp_ocp_sma_connector *sma = &bp->sma[sma_nr - 1];
>> -	enum ptp_ocp_sma_mode mode;
>> -	int val;
>> -
>> -	mode = sma->mode;
>> -	val = sma_parse_inputs(bp->sma_op->tbl, buf, &mode);
>> -	if (val < 0)
>> -		return val;
>>
>> 	if (sma->fixed_dir && (mode != sma->mode || val & SMA_DISABLE))
>> 		return -EOPNOTSUPP;
>> @@ -2733,6 +2730,21 @@ ptp_ocp_sma_store(struct ptp_ocp *bp, const char *buf, int sma_nr)
>> 	return val;
>> }
>>
>> +static int
>> +ptp_ocp_sma_store(struct ptp_ocp *bp, const char *buf, int sma_nr)
>> +{
>> +	struct ptp_ocp_sma_connector *sma = &bp->sma[sma_nr - 1];
>> +	enum ptp_ocp_sma_mode mode;
>> +	int val;
>> +
>> +	mode = sma->mode;
>> +	val = sma_parse_inputs(bp->sma_op->tbl, buf, &mode);
>> +	if (val < 0)
>> +		return val;
>> +
>> +	return ptp_ocp_sma_store_val(bp, val, mode, sma_nr);
>> +}
>> +
>> static ssize_t
>> sma1_store(struct device *dev, struct device_attribute *attr,
>> 	   const char *buf, size_t count)
>> @@ -4171,12 +4183,151 @@ ptp_ocp_detach(struct ptp_ocp *bp)
>> 	device_unregister(&bp->dev);
>> }
>>
>> +static int ptp_ocp_dpll_pin_to_sma(const struct ptp_ocp *bp, const struct dpll_pin *pin)
>> +{
>> +	int i;
>> +
>> +	for (i = 0; i < 4; i++) {
>> +		if (bp->sma[i].dpll_pin == pin)
>> +			return i;
> 
> Just pass &bp->sma[i] as a priv to dpll_pin_register().
> and get that pointer directly in pin ops. No need for lookup and use of
> sma_nr at all.

I'm still thinking about the change that you proposed to remove these
_priv() helpers. I have to look into ice code to be sure we won't break
any assumptions in it with moving to additional (void *) parameter.

> 
>> +	}
>> +	return -1;
>> +}
>> +
>> +static int ptp_ocp_dpll_lock_status_get(const struct dpll_device *dpll,
>> +				    enum dpll_lock_status *status,
>> +				    struct netlink_ext_ack *extack)
>> +{
>> +	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
> 
> No need to cast (void *), remove it.
> 
Fixed everywhere in the code, thanks.


> 
>> +	int sync;
>> +
>> +	sync = ioread32(&bp->reg->status) & OCP_STATUS_IN_SYNC;
>> +	*status = sync ? DPLL_LOCK_STATUS_LOCKED : DPLL_LOCK_STATUS_UNLOCKED;
>> +
>> +	return 0;
>> +}
>> +
>> +static int ptp_ocp_dpll_source_idx_get(const struct dpll_device *dpll,
>> +				    u32 *idx, struct netlink_ext_ack *extack)
>> +{
>> +	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
>> +
>> +	if (bp->pps_select) {
>> +		*idx = ioread32(&bp->pps_select->gpio1);
>> +		return 0;
>> +	}
>> +	return -EINVAL;
>> +}
>> +
>> +static int ptp_ocp_dpll_mode_get(const struct dpll_device *dpll,
>> +				    u32 *mode, struct netlink_ext_ack *extack)
>> +{
>> +	*mode = DPLL_MODE_AUTOMATIC;
>> +
> 
> No need for empty line, I believe.

Ok.

>> +	return 0;
>> +}
>> +
>> +static bool ptp_ocp_dpll_mode_supported(const struct dpll_device *dpll,
>> +				    const enum dpll_mode mode,
>> +				    struct netlink_ext_ack *extack)
>> +{
>> +	if (mode == DPLL_MODE_AUTOMATIC)
>> +		return true;
>> +
>> +	return false;
> 
> Just:
> 	return mode == DPLL_MODE_AUTOMATIC;
> 
Done, thanks!

>> +}
>> +
>> +static int ptp_ocp_dpll_direction_get(const struct dpll_pin *pin,
>> +				     const struct dpll_device *dpll,
>> +				     enum dpll_pin_direction *direction,
>> +				     struct netlink_ext_ack *extack)
>> +{
>> +	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
>> +	int sma_nr = ptp_ocp_dpll_pin_to_sma(bp, pin);
>> +
>> +	if (sma_nr < 0)
>> +		return -EINVAL;
>> +
>> +	*direction = bp->sma[sma_nr].mode == SMA_MODE_IN ? DPLL_PIN_DIRECTION_SOURCE :
>> +							   DPLL_PIN_DIRECTION_OUTPUT;
>> +	return 0;
>> +}
>> +
>> +static int ptp_ocp_dpll_direction_set(const struct dpll_pin *pin,
>> +				     const struct dpll_device *dpll,
>> +				     enum dpll_pin_direction direction,
>> +				     struct netlink_ext_ack *extack)
>> +{
>> +	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
>> +	int sma_nr = ptp_ocp_dpll_pin_to_sma(bp, pin);
>> +	enum ptp_ocp_sma_mode mode;
>> +
>> +	if (sma_nr < 0)
>> +		return -EINVAL;
>> +
>> +	mode = direction == DPLL_PIN_DIRECTION_SOURCE ? SMA_MODE_IN : SMA_MODE_OUT;
>> +	return ptp_ocp_sma_store_val(bp, 0, mode, sma_nr);
>> +}
>> +
>> +static int ptp_ocp_dpll_frequency_set(const struct dpll_pin *pin,
>> +			      const struct dpll_device *dpll,
>> +			      const u32 frequency,
> 
> Why you need const for u32?

No need, true, removed.

> 
>> +			      struct netlink_ext_ack *extack)
>> +{
>> +	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
>> +	int sma_nr = ptp_ocp_dpll_pin_to_sma(bp, pin);
>> +	int val = frequency == 10000000 ? 0 : 1;
> 
> This is weird. I believe you should handle unsupported frequencies
> gracefully.
> 

Currently hardware supports fixed frequencies only. That's why I have to
do this kind of "dance". Hopefully we will improve it to support 
variable frequency.

> 
>> +
>> +	if (sma_nr < 0)
>> +		return -EINVAL;
>> +
>> +
> 
> Avoid double empty lines.
> 

Yep.

> 
>> +	return ptp_ocp_sma_store_val(bp, val, bp->sma[sma_nr].mode, sma_nr);
>> +}
>> +
>> +static int ptp_ocp_dpll_frequency_get(const struct dpll_pin *pin,
>> +			      const struct dpll_device *dpll,
>> +			      u32 *frequency,
>> +			      struct netlink_ext_ack *extack)
>> +{
>> +	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
>> +	int sma_nr = ptp_ocp_dpll_pin_to_sma(bp, pin);
>> +	u32 val;
>> +
>> +	if (sma_nr < 0)
>> +		return -EINVAL;
>> +
>> +	val = bp->sma_op->get(bp, sma_nr);
>> +	if (!val)
>> +		*frequency = 1000000;
>> +	else
>> +		*frequency = 0;
> 
> I don't follow. How the frequency could be 0? Does that mean that the
> pin is disabled? If yes, you should rather implement
> .state_on_dpll_get
> .state_on_dpll_set
> 
> and leave the frequency constant.

It's actually a mistake. It should be 1 which means 1Hz, PPS. The value 
returned by sma_op->get is actually the type of the signal where 0 is 
1PPS, 1 is 10Mhz and so on.

> 
> 
>> +	return 0;
>> +}
>> +
>> +static struct dpll_device_ops dpll_ops = {
> 
> const
> 

Will change it together with API part. Otherwise it doesn't compile.

> 
>> +	.lock_status_get = ptp_ocp_dpll_lock_status_get,
>> +	.source_pin_idx_get = ptp_ocp_dpll_source_idx_get,
> 
> Should be called "source_pin_get" and return (struct dpll_pin *)
> On the driver api level, no reason to pass indexes. Work with objects.
> 

Good point, will improve it.

> 
>> +	.mode_get = ptp_ocp_dpll_mode_get,
>> +	.mode_supported = ptp_ocp_dpll_mode_supported,
>> +};
>> +
>> +static struct dpll_pin_ops dpll_pins_ops = {
> 
> const
> 

Yep.

> 
>> +	.frequency_get = ptp_ocp_dpll_frequency_get,
>> +	.frequency_set = ptp_ocp_dpll_frequency_set,
>> +	.direction_get = ptp_ocp_dpll_direction_get,
>> +	.direction_set = ptp_ocp_dpll_direction_set,
>> +};
>> +
>> static int
>> ptp_ocp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>> {
>> +	struct dpll_pin_properties prop;
>> 	struct devlink *devlink;
>> +	char sma[4] = "SMA0";
> 
> Won't fit. Just use:
> char *sma = "SMA0"
> to be safe
> 
Got it.

> 
>> 	struct ptp_ocp *bp;
>> -	int err;
>> +	int err, i;
>> +	u64 clkid;
>>
>> 	devlink = devlink_alloc(&ptp_ocp_devlink_ops, sizeof(*bp), &pdev->dev);
>> 	if (!devlink) {
>> @@ -4226,8 +4377,44 @@ ptp_ocp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>>
>> 	ptp_ocp_info(bp);
>> 	devlink_register(devlink);
>> -	return 0;
>>
>> +	clkid = pci_get_dsn(pdev);
>> +	bp->dpll = dpll_device_get(clkid, 0, THIS_MODULE);
>> +	if (!bp->dpll) {
>> +		dev_err(&pdev->dev, "dpll_device_alloc failed\n");
>> +		goto out;
>> +	}
>> +
>> +	err = dpll_device_register(bp->dpll, DPLL_TYPE_PPS, &dpll_ops, bp, &pdev->dev);
>> +	if (err)
>> +		goto out;
>> +
>> +	prop.description = &sma[0];
>> +	prop.freq_supported = DPLL_PIN_FREQ_SUPP_MAX;
>> +	prop.type = DPLL_PIN_TYPE_EXT;
>> +	prop.any_freq_max = 10000000;
>> +	prop.any_freq_min = 0;
>> +	prop.capabilities = DPLL_PIN_CAPS_DIRECTION_CAN_CHANGE;
>> +
>> +	for (i = 0; i < 4; i++) {
>> +		sma[3] = 0x31 + i;
> 
> Ugh. Just use the static const array as I suggested in the dpll patch
> reply. Helps you avoid this sort of "magic".
> 
well, yes. but at the same time Arkadiusz raised a good question about
accessing driver's memory from the subsystem code - doesn't look clean.

> 
>> +		bp->sma[i].dpll_pin = dpll_pin_get(clkid, i, THIS_MODULE, &prop);
>> +		if (IS_ERR_OR_NULL(bp->sma[i].dpll_pin)) {
> 
> How it could be NULL?
> 

Allocation fail?

> 
>> +			bp->sma[i].dpll_pin = NULL;
> 
> This would not be needed if the error path iterates over
> indexes which were successul.
> 

Yeah, I'll make it the same way it's done in ice.


> 
>> +			goto out_dpll;
>> +		}
>> +		err = dpll_pin_register(bp->dpll, bp->sma[i].dpll_pin, &dpll_pins_ops, bp, NULL);
>> +		if (err)
>> +			goto out_dpll;
>> +	}
>> +
>> +	return 0;
>> +out_dpll:
>> +	for (i = 0; i < 4; i++) {
>> +		if (bp->sma[i].dpll_pin)
> 
> You don't do unregister of pin here.
> 
Yeah, actually error path and unload path should be re-implemented.

> 
>> +			dpll_pin_put(bp->sma[i].dpll_pin);
>> +	}
>> +	dpll_device_put(bp->dpll);
>> out:
>> 	ptp_ocp_detach(bp);
>> out_disable:
>> @@ -4243,6 +4430,8 @@ ptp_ocp_remove(struct pci_dev *pdev)
>> 	struct ptp_ocp *bp = pci_get_drvdata(pdev);
>> 	struct devlink *devlink = priv_to_devlink(bp);
>>
>> +	dpll_device_unregister(bp->dpll);
>> +	dpll_device_put(bp->dpll);
>> 	devlink_unregister(devlink);
>> 	ptp_ocp_detach(bp);
>> 	pci_disable_device(pdev);
>> -- 
>> 2.34.1
>>


WARNING: multiple messages have this Message-ID (diff)
From: Vadim Fedorenko <vadim.fedorenko@linux.dev>
To: Jiri Pirko <jiri@resnulli.us>, Vadim Fedorenko <vadfed@meta.com>
Cc: Jakub Kicinski <kuba@kernel.org>,
	Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>,
	Jonathan Lemon <jonathan.lemon@gmail.com>,
	Paolo Abeni <pabeni@redhat.com>,
	poros@redhat.com, mschmidt@redhat.com, netdev@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, linux-clk@vger.kernel.org
Subject: Re: [PATCH RFC v6 6/6] ptp_ocp: implement DPLL ops
Date: Wed, 15 Mar 2023 00:10:33 +0000	[thread overview]
Message-ID: <d192e0ac-3fa3-c799-ac93-84a17e6f6d50@linux.dev> (raw)
In-Reply-To: <ZBBG2xRhLOIPMD0+@nanopsycho>

On 14/03/2023 10:05, Jiri Pirko wrote:
> Sun, Mar 12, 2023 at 03:28:07AM CET, vadfed@meta.com wrote:
>> Implement basic DPLL operations in ptp_ocp driver as the
>> simplest example of using new subsystem.
>>
>> Signed-off-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
>> ---
>> drivers/ptp/Kconfig   |   1 +
>> drivers/ptp/ptp_ocp.c | 209 ++++++++++++++++++++++++++++++++++++++++--
>> 2 files changed, 200 insertions(+), 10 deletions(-)
>>
>> diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig
>> index fe4971b65c64..8c4cfabc1bfa 100644
>> --- a/drivers/ptp/Kconfig
>> +++ b/drivers/ptp/Kconfig
>> @@ -177,6 +177,7 @@ config PTP_1588_CLOCK_OCP
>> 	depends on COMMON_CLK
>> 	select NET_DEVLINK
>> 	select CRC16
>> +	select DPLL
>> 	help
>> 	  This driver adds support for an OpenCompute time card.
>>
>> diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
>> index 4bbaccd543ad..02c95e724ec8 100644
>> --- a/drivers/ptp/ptp_ocp.c
>> +++ b/drivers/ptp/ptp_ocp.c
>> @@ -23,6 +23,8 @@
>> #include <linux/mtd/mtd.h>
>> #include <linux/nvmem-consumer.h>
>> #include <linux/crc16.h>
>> +#include <linux/dpll.h>
>> +#include <uapi/linux/dpll.h>
> 
> Don't include UAPI directly. I'm pretty sure I had this comment earlier.
> 

Ah, yeah, you've mentioned it for ice driver last time, but I forgot to 
check it here. Removed.

> 
>>
>> #define PCI_VENDOR_ID_FACEBOOK			0x1d9b
>> #define PCI_DEVICE_ID_FACEBOOK_TIMECARD		0x0400
>> @@ -267,6 +269,7 @@ struct ptp_ocp_sma_connector {
>> 	bool	fixed_dir;
>> 	bool	disabled;
>> 	u8	default_fcn;
>> +	struct dpll_pin *dpll_pin;
>> };
>>
>> struct ocp_attr_group {
>> @@ -353,6 +356,7 @@ struct ptp_ocp {
>> 	struct ptp_ocp_signal	signal[4];
>> 	struct ptp_ocp_sma_connector sma[4];
> 
> It is quite customary to use defines for const numbers like this. Why
> don't you do that in ptp_ocp?

Historical reasons. Jonathan might answer this question.
I will add it to my TODO list for the driver.

>> 	const struct ocp_sma_op *sma_op;
>> +	struct dpll_device *dpll;
>> };
>>
>> #define OCP_REQ_TIMESTAMP	BIT(0)
>> @@ -2689,16 +2693,9 @@ sma4_show(struct device *dev, struct device_attribute *attr, char *buf)
>> }
>>
>> static int
>> -ptp_ocp_sma_store(struct ptp_ocp *bp, const char *buf, int sma_nr)
>> +ptp_ocp_sma_store_val(struct ptp_ocp *bp, int val, enum ptp_ocp_sma_mode mode, int sma_nr)
>> {
>> 	struct ptp_ocp_sma_connector *sma = &bp->sma[sma_nr - 1];
>> -	enum ptp_ocp_sma_mode mode;
>> -	int val;
>> -
>> -	mode = sma->mode;
>> -	val = sma_parse_inputs(bp->sma_op->tbl, buf, &mode);
>> -	if (val < 0)
>> -		return val;
>>
>> 	if (sma->fixed_dir && (mode != sma->mode || val & SMA_DISABLE))
>> 		return -EOPNOTSUPP;
>> @@ -2733,6 +2730,21 @@ ptp_ocp_sma_store(struct ptp_ocp *bp, const char *buf, int sma_nr)
>> 	return val;
>> }
>>
>> +static int
>> +ptp_ocp_sma_store(struct ptp_ocp *bp, const char *buf, int sma_nr)
>> +{
>> +	struct ptp_ocp_sma_connector *sma = &bp->sma[sma_nr - 1];
>> +	enum ptp_ocp_sma_mode mode;
>> +	int val;
>> +
>> +	mode = sma->mode;
>> +	val = sma_parse_inputs(bp->sma_op->tbl, buf, &mode);
>> +	if (val < 0)
>> +		return val;
>> +
>> +	return ptp_ocp_sma_store_val(bp, val, mode, sma_nr);
>> +}
>> +
>> static ssize_t
>> sma1_store(struct device *dev, struct device_attribute *attr,
>> 	   const char *buf, size_t count)
>> @@ -4171,12 +4183,151 @@ ptp_ocp_detach(struct ptp_ocp *bp)
>> 	device_unregister(&bp->dev);
>> }
>>
>> +static int ptp_ocp_dpll_pin_to_sma(const struct ptp_ocp *bp, const struct dpll_pin *pin)
>> +{
>> +	int i;
>> +
>> +	for (i = 0; i < 4; i++) {
>> +		if (bp->sma[i].dpll_pin == pin)
>> +			return i;
> 
> Just pass &bp->sma[i] as a priv to dpll_pin_register().
> and get that pointer directly in pin ops. No need for lookup and use of
> sma_nr at all.

I'm still thinking about the change that you proposed to remove these
_priv() helpers. I have to look into ice code to be sure we won't break
any assumptions in it with moving to additional (void *) parameter.

> 
>> +	}
>> +	return -1;
>> +}
>> +
>> +static int ptp_ocp_dpll_lock_status_get(const struct dpll_device *dpll,
>> +				    enum dpll_lock_status *status,
>> +				    struct netlink_ext_ack *extack)
>> +{
>> +	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
> 
> No need to cast (void *), remove it.
> 
Fixed everywhere in the code, thanks.


> 
>> +	int sync;
>> +
>> +	sync = ioread32(&bp->reg->status) & OCP_STATUS_IN_SYNC;
>> +	*status = sync ? DPLL_LOCK_STATUS_LOCKED : DPLL_LOCK_STATUS_UNLOCKED;
>> +
>> +	return 0;
>> +}
>> +
>> +static int ptp_ocp_dpll_source_idx_get(const struct dpll_device *dpll,
>> +				    u32 *idx, struct netlink_ext_ack *extack)
>> +{
>> +	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
>> +
>> +	if (bp->pps_select) {
>> +		*idx = ioread32(&bp->pps_select->gpio1);
>> +		return 0;
>> +	}
>> +	return -EINVAL;
>> +}
>> +
>> +static int ptp_ocp_dpll_mode_get(const struct dpll_device *dpll,
>> +				    u32 *mode, struct netlink_ext_ack *extack)
>> +{
>> +	*mode = DPLL_MODE_AUTOMATIC;
>> +
> 
> No need for empty line, I believe.

Ok.

>> +	return 0;
>> +}
>> +
>> +static bool ptp_ocp_dpll_mode_supported(const struct dpll_device *dpll,
>> +				    const enum dpll_mode mode,
>> +				    struct netlink_ext_ack *extack)
>> +{
>> +	if (mode == DPLL_MODE_AUTOMATIC)
>> +		return true;
>> +
>> +	return false;
> 
> Just:
> 	return mode == DPLL_MODE_AUTOMATIC;
> 
Done, thanks!

>> +}
>> +
>> +static int ptp_ocp_dpll_direction_get(const struct dpll_pin *pin,
>> +				     const struct dpll_device *dpll,
>> +				     enum dpll_pin_direction *direction,
>> +				     struct netlink_ext_ack *extack)
>> +{
>> +	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
>> +	int sma_nr = ptp_ocp_dpll_pin_to_sma(bp, pin);
>> +
>> +	if (sma_nr < 0)
>> +		return -EINVAL;
>> +
>> +	*direction = bp->sma[sma_nr].mode == SMA_MODE_IN ? DPLL_PIN_DIRECTION_SOURCE :
>> +							   DPLL_PIN_DIRECTION_OUTPUT;
>> +	return 0;
>> +}
>> +
>> +static int ptp_ocp_dpll_direction_set(const struct dpll_pin *pin,
>> +				     const struct dpll_device *dpll,
>> +				     enum dpll_pin_direction direction,
>> +				     struct netlink_ext_ack *extack)
>> +{
>> +	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
>> +	int sma_nr = ptp_ocp_dpll_pin_to_sma(bp, pin);
>> +	enum ptp_ocp_sma_mode mode;
>> +
>> +	if (sma_nr < 0)
>> +		return -EINVAL;
>> +
>> +	mode = direction == DPLL_PIN_DIRECTION_SOURCE ? SMA_MODE_IN : SMA_MODE_OUT;
>> +	return ptp_ocp_sma_store_val(bp, 0, mode, sma_nr);
>> +}
>> +
>> +static int ptp_ocp_dpll_frequency_set(const struct dpll_pin *pin,
>> +			      const struct dpll_device *dpll,
>> +			      const u32 frequency,
> 
> Why you need const for u32?

No need, true, removed.

> 
>> +			      struct netlink_ext_ack *extack)
>> +{
>> +	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
>> +	int sma_nr = ptp_ocp_dpll_pin_to_sma(bp, pin);
>> +	int val = frequency == 10000000 ? 0 : 1;
> 
> This is weird. I believe you should handle unsupported frequencies
> gracefully.
> 

Currently hardware supports fixed frequencies only. That's why I have to
do this kind of "dance". Hopefully we will improve it to support 
variable frequency.

> 
>> +
>> +	if (sma_nr < 0)
>> +		return -EINVAL;
>> +
>> +
> 
> Avoid double empty lines.
> 

Yep.

> 
>> +	return ptp_ocp_sma_store_val(bp, val, bp->sma[sma_nr].mode, sma_nr);
>> +}
>> +
>> +static int ptp_ocp_dpll_frequency_get(const struct dpll_pin *pin,
>> +			      const struct dpll_device *dpll,
>> +			      u32 *frequency,
>> +			      struct netlink_ext_ack *extack)
>> +{
>> +	struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll);
>> +	int sma_nr = ptp_ocp_dpll_pin_to_sma(bp, pin);
>> +	u32 val;
>> +
>> +	if (sma_nr < 0)
>> +		return -EINVAL;
>> +
>> +	val = bp->sma_op->get(bp, sma_nr);
>> +	if (!val)
>> +		*frequency = 1000000;
>> +	else
>> +		*frequency = 0;
> 
> I don't follow. How the frequency could be 0? Does that mean that the
> pin is disabled? If yes, you should rather implement
> .state_on_dpll_get
> .state_on_dpll_set
> 
> and leave the frequency constant.

It's actually a mistake. It should be 1 which means 1Hz, PPS. The value 
returned by sma_op->get is actually the type of the signal where 0 is 
1PPS, 1 is 10Mhz and so on.

> 
> 
>> +	return 0;
>> +}
>> +
>> +static struct dpll_device_ops dpll_ops = {
> 
> const
> 

Will change it together with API part. Otherwise it doesn't compile.

> 
>> +	.lock_status_get = ptp_ocp_dpll_lock_status_get,
>> +	.source_pin_idx_get = ptp_ocp_dpll_source_idx_get,
> 
> Should be called "source_pin_get" and return (struct dpll_pin *)
> On the driver api level, no reason to pass indexes. Work with objects.
> 

Good point, will improve it.

> 
>> +	.mode_get = ptp_ocp_dpll_mode_get,
>> +	.mode_supported = ptp_ocp_dpll_mode_supported,
>> +};
>> +
>> +static struct dpll_pin_ops dpll_pins_ops = {
> 
> const
> 

Yep.

> 
>> +	.frequency_get = ptp_ocp_dpll_frequency_get,
>> +	.frequency_set = ptp_ocp_dpll_frequency_set,
>> +	.direction_get = ptp_ocp_dpll_direction_get,
>> +	.direction_set = ptp_ocp_dpll_direction_set,
>> +};
>> +
>> static int
>> ptp_ocp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>> {
>> +	struct dpll_pin_properties prop;
>> 	struct devlink *devlink;
>> +	char sma[4] = "SMA0";
> 
> Won't fit. Just use:
> char *sma = "SMA0"
> to be safe
> 
Got it.

> 
>> 	struct ptp_ocp *bp;
>> -	int err;
>> +	int err, i;
>> +	u64 clkid;
>>
>> 	devlink = devlink_alloc(&ptp_ocp_devlink_ops, sizeof(*bp), &pdev->dev);
>> 	if (!devlink) {
>> @@ -4226,8 +4377,44 @@ ptp_ocp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>>
>> 	ptp_ocp_info(bp);
>> 	devlink_register(devlink);
>> -	return 0;
>>
>> +	clkid = pci_get_dsn(pdev);
>> +	bp->dpll = dpll_device_get(clkid, 0, THIS_MODULE);
>> +	if (!bp->dpll) {
>> +		dev_err(&pdev->dev, "dpll_device_alloc failed\n");
>> +		goto out;
>> +	}
>> +
>> +	err = dpll_device_register(bp->dpll, DPLL_TYPE_PPS, &dpll_ops, bp, &pdev->dev);
>> +	if (err)
>> +		goto out;
>> +
>> +	prop.description = &sma[0];
>> +	prop.freq_supported = DPLL_PIN_FREQ_SUPP_MAX;
>> +	prop.type = DPLL_PIN_TYPE_EXT;
>> +	prop.any_freq_max = 10000000;
>> +	prop.any_freq_min = 0;
>> +	prop.capabilities = DPLL_PIN_CAPS_DIRECTION_CAN_CHANGE;
>> +
>> +	for (i = 0; i < 4; i++) {
>> +		sma[3] = 0x31 + i;
> 
> Ugh. Just use the static const array as I suggested in the dpll patch
> reply. Helps you avoid this sort of "magic".
> 
well, yes. but at the same time Arkadiusz raised a good question about
accessing driver's memory from the subsystem code - doesn't look clean.

> 
>> +		bp->sma[i].dpll_pin = dpll_pin_get(clkid, i, THIS_MODULE, &prop);
>> +		if (IS_ERR_OR_NULL(bp->sma[i].dpll_pin)) {
> 
> How it could be NULL?
> 

Allocation fail?

> 
>> +			bp->sma[i].dpll_pin = NULL;
> 
> This would not be needed if the error path iterates over
> indexes which were successul.
> 

Yeah, I'll make it the same way it's done in ice.


> 
>> +			goto out_dpll;
>> +		}
>> +		err = dpll_pin_register(bp->dpll, bp->sma[i].dpll_pin, &dpll_pins_ops, bp, NULL);
>> +		if (err)
>> +			goto out_dpll;
>> +	}
>> +
>> +	return 0;
>> +out_dpll:
>> +	for (i = 0; i < 4; i++) {
>> +		if (bp->sma[i].dpll_pin)
> 
> You don't do unregister of pin here.
> 
Yeah, actually error path and unload path should be re-implemented.

> 
>> +			dpll_pin_put(bp->sma[i].dpll_pin);
>> +	}
>> +	dpll_device_put(bp->dpll);
>> out:
>> 	ptp_ocp_detach(bp);
>> out_disable:
>> @@ -4243,6 +4430,8 @@ ptp_ocp_remove(struct pci_dev *pdev)
>> 	struct ptp_ocp *bp = pci_get_drvdata(pdev);
>> 	struct devlink *devlink = priv_to_devlink(bp);
>>
>> +	dpll_device_unregister(bp->dpll);
>> +	dpll_device_put(bp->dpll);
>> 	devlink_unregister(devlink);
>> 	ptp_ocp_detach(bp);
>> 	pci_disable_device(pdev);
>> -- 
>> 2.34.1
>>


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

  reply	other threads:[~2023-03-15  0:10 UTC|newest]

Thread overview: 202+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-03-12  2:28 [PATCH RFC v6 0/6] Create common DPLL/clock configuration API Vadim Fedorenko
2023-03-12  2:28 ` Vadim Fedorenko
2023-03-12  2:28 ` [PATCH RFC v6 1/6] dpll: spec: Add Netlink spec in YAML Vadim Fedorenko
2023-03-12  2:28   ` Vadim Fedorenko
2023-03-14 14:44   ` Jiri Pirko
2023-03-14 14:44     ` Jiri Pirko
2023-03-16 13:15     ` Kubalewski, Arkadiusz
2023-03-16 13:15       ` Kubalewski, Arkadiusz
2023-03-16 13:45       ` Jiri Pirko
2023-03-16 13:45         ` Jiri Pirko
2023-03-16 15:19         ` Jiri Pirko
2023-03-16 15:19           ` Jiri Pirko
2023-03-17  0:53           ` Kubalewski, Arkadiusz
2023-03-17  0:53             ` Kubalewski, Arkadiusz
2023-03-17 10:07             ` Jiri Pirko
2023-03-17 10:07               ` Jiri Pirko
2023-03-17  0:52         ` Kubalewski, Arkadiusz
2023-03-17  0:52           ` Kubalewski, Arkadiusz
2023-03-17 10:05           ` Jiri Pirko
2023-03-17 10:05             ` Jiri Pirko
2023-03-17 14:29             ` Jiri Pirko
2023-03-17 14:29               ` Jiri Pirko
2023-03-17 15:14             ` Kubalewski, Arkadiusz
2023-03-17 15:14               ` Kubalewski, Arkadiusz
2023-03-17 16:20               ` Jiri Pirko
2023-03-17 16:20                 ` Jiri Pirko
2023-03-17 18:22                 ` Kubalewski, Arkadiusz
2023-03-17 18:22                   ` Kubalewski, Arkadiusz
2023-03-20  8:10                   ` Jiri Pirko
2023-03-20  8:10                     ` Jiri Pirko
2023-03-21  4:05       ` Jakub Kicinski
2023-03-21  4:05         ` Jakub Kicinski
2023-03-21  4:13         ` Jakub Kicinski
2023-03-21  4:13           ` Jakub Kicinski
2023-03-21  4:20           ` Jakub Kicinski
2023-03-21  4:20             ` Jakub Kicinski
2023-03-17 16:23   ` Jiri Pirko
2023-03-17 16:23     ` Jiri Pirko
2023-03-21  4:00     ` Jakub Kicinski
2023-03-21  4:00       ` Jakub Kicinski
2023-03-17 16:53   ` Jiri Pirko
2023-03-17 16:53     ` Jiri Pirko
2023-03-17 18:50     ` Kubalewski, Arkadiusz
2023-03-17 18:50       ` Kubalewski, Arkadiusz
2023-03-12  2:28 ` [PATCH RFC v6 2/6] dpll: Add DPLL framework base functions Vadim Fedorenko
2023-03-12  2:28   ` Vadim Fedorenko
2023-03-13 16:21   ` Jiri Pirko
2023-03-13 16:21     ` Jiri Pirko
2023-03-13 22:59     ` Vadim Fedorenko
2023-03-13 22:59       ` Vadim Fedorenko
2023-03-14  9:21       ` Jiri Pirko
2023-03-14 17:50         ` Kubalewski, Arkadiusz
2023-03-14 17:50           ` Kubalewski, Arkadiusz
2023-03-15  9:22           ` Jiri Pirko
2023-03-15  9:22             ` Jiri Pirko
2023-03-16 12:31             ` Jiri Pirko
2023-03-16 12:31               ` Jiri Pirko
2023-03-28 15:22             ` Vadim Fedorenko
2023-03-28 15:22               ` Vadim Fedorenko
2023-04-01 12:49               ` Jiri Pirko
2023-04-01 12:49                 ` Jiri Pirko
2023-04-03 18:18             ` Jakub Kicinski
2023-04-03 18:18               ` Jakub Kicinski
2023-04-09  7:51               ` Jiri Pirko
2023-04-09  7:51                 ` Jiri Pirko
     [not found]                 ` <20230410153149.602c6bad@kernel.org>
2023-04-16 16:23                   ` Jiri Pirko
2023-04-16 16:23                     ` Jiri Pirko
2023-04-17 15:53                     ` Vadim Fedorenko
2023-04-17 15:53                       ` Vadim Fedorenko
     [not found]                     ` <20230417124942.4305abfa@kernel.org>
2023-04-27  8:05                       ` Paolo Abeni
2023-04-27  8:05                         ` Paolo Abeni
2023-04-27 10:20                         ` Vadim Fedorenko
2023-04-27 10:20                           ` Vadim Fedorenko
     [not found]                       ` <ZFDPaXlJainSOqmV@nanopsycho>
     [not found]                         ` <20230502083244.19543d26@kernel.org>
2023-05-03  7:56                           ` Jiri Pirko
2023-05-03  7:56                             ` Jiri Pirko
2023-05-04  2:16                             ` Jakub Kicinski
2023-05-04  2:16                               ` Jakub Kicinski
2023-05-04 11:00                               ` Jiri Pirko
2023-05-04 11:00                                 ` Jiri Pirko
2023-05-04 11:14                                 ` Jiri Pirko
2023-05-04 11:14                                   ` Jiri Pirko
2023-05-04 16:04                                 ` Jakub Kicinski
2023-05-04 16:04                                   ` Jakub Kicinski
2023-05-04 17:51                                   ` Jiri Pirko
2023-05-04 17:51                                     ` Jiri Pirko
2023-05-04 18:44                                     ` Jakub Kicinski
2023-05-04 18:44                                       ` Jakub Kicinski
2023-05-05 10:41                                       ` Jiri Pirko
2023-05-05 10:41                                         ` Jiri Pirko
2023-05-05 15:35                                         ` Jakub Kicinski
2023-05-05 15:35                                           ` Jakub Kicinski
2023-05-07  7:58                                           ` Jiri Pirko
2023-05-07  7:58                                             ` Jiri Pirko
2023-05-08  6:50                                             ` Paolo Abeni
2023-05-08 12:17                                               ` Jiri Pirko
2023-05-08 19:42                                                 ` Jakub Kicinski
2023-05-09  7:53                                                   ` Jiri Pirko
2023-05-09 14:52                                                     ` Jakub Kicinski
2023-05-09 15:21                                                       ` Jiri Pirko
2023-05-09 17:53                                                         ` Jakub Kicinski
2023-05-10  6:17                                                           ` Jiri Pirko
2023-03-14 16:43       ` Kubalewski, Arkadiusz
2023-03-14 16:43         ` Kubalewski, Arkadiusz
2023-03-15 12:14         ` Jiri Pirko
2023-03-15 12:14           ` Jiri Pirko
2023-03-14  9:30   ` Jiri Pirko
2023-03-14 15:45   ` Jiri Pirko
2023-03-14 15:45     ` Jiri Pirko
2023-03-14 18:35     ` Kubalewski, Arkadiusz
2023-03-14 18:35       ` Kubalewski, Arkadiusz
2023-03-15 14:43       ` Jiri Pirko
2023-03-15 14:43         ` Jiri Pirko
2023-03-15 15:29   ` Jiri Pirko
2023-03-15 15:29     ` Jiri Pirko
2023-03-16 12:20   ` Jiri Pirko
2023-03-16 12:20     ` Jiri Pirko
2023-03-16 12:37   ` Jiri Pirko
2023-03-16 12:37     ` Jiri Pirko
2023-03-16 13:53   ` Jiri Pirko
2023-03-16 13:53     ` Jiri Pirko
2023-03-16 16:16   ` Jiri Pirko
2023-03-16 16:16     ` Jiri Pirko
2023-03-17 16:21   ` Jiri Pirko
2023-03-17 16:21     ` Jiri Pirko
2023-03-20 10:24   ` Jiri Pirko
2023-03-20 10:24     ` Jiri Pirko
2023-03-21 13:34   ` Jiri Pirko
2023-03-21 13:34     ` Jiri Pirko
2023-03-23 11:18   ` Jiri Pirko
2023-03-23 11:18     ` Jiri Pirko
2023-03-24  9:29   ` Jiri Pirko
2023-03-24  9:29     ` Jiri Pirko
2023-03-12  2:28 ` [PATCH RFC v6 3/6] dpll: documentation on DPLL subsystem interface Vadim Fedorenko
2023-03-12  2:28   ` Vadim Fedorenko
2023-03-14 16:14   ` Jiri Pirko
2023-03-14 16:14     ` Jiri Pirko
2023-04-03 10:21     ` Kubalewski, Arkadiusz
2023-04-03 10:21       ` Kubalewski, Arkadiusz
2023-03-16 13:46   ` Jiri Pirko
2023-03-16 13:46     ` Jiri Pirko
2023-04-03 10:23     ` Kubalewski, Arkadiusz
2023-04-03 10:23       ` Kubalewski, Arkadiusz
2023-03-12  2:28 ` [PATCH RFC v6 4/6] ice: add admin commands to access cgu configuration Vadim Fedorenko
2023-03-12  2:28   ` Vadim Fedorenko
2023-03-12  7:05   ` kernel test robot
2023-03-12  2:28 ` [PATCH RFC v6 5/6] ice: implement dpll interface to control cgu Vadim Fedorenko
2023-03-12  2:28   ` Vadim Fedorenko
2023-03-12  6:04   ` kernel test robot
2023-03-12  2:28 ` [PATCH RFC v6 6/6] ptp_ocp: implement DPLL ops Vadim Fedorenko
2023-03-12  2:28   ` Vadim Fedorenko
2023-03-12  5:12   ` kernel test robot
2023-03-14 10:05   ` Jiri Pirko
2023-03-15  0:10     ` Vadim Fedorenko [this message]
2023-03-15  0:10       ` Vadim Fedorenko
2023-03-15 12:24       ` Jiri Pirko
2023-03-15 12:24         ` Jiri Pirko
2023-03-31 23:28         ` Vadim Fedorenko
2023-03-31 23:28           ` Vadim Fedorenko
2023-04-01 12:53           ` Jiri Pirko
2023-04-01 12:53             ` Jiri Pirko
2023-03-15 15:34   ` Jiri Pirko
2023-03-15 15:34     ` Jiri Pirko
2023-03-15 15:52     ` Vadim Fedorenko
2023-03-15 15:52       ` Vadim Fedorenko
2023-03-16 12:12   ` Jiri Pirko
2023-03-16 12:12     ` Jiri Pirko
2023-03-13 12:20 ` [PATCH RFC v6 0/6] Create common DPLL/clock configuration API Jiri Pirko
2023-03-13 12:20   ` Jiri Pirko
2023-03-13 15:33   ` Vadim Fedorenko
2023-03-13 15:33     ` Vadim Fedorenko
2023-03-13 16:22     ` Jiri Pirko
2023-03-13 16:22       ` Jiri Pirko
2023-03-13 16:31       ` Vadim Fedorenko
2023-03-13 16:31         ` Vadim Fedorenko
2023-03-17 16:10     ` Jiri Pirko
2023-03-17 16:10       ` Jiri Pirko
2023-03-18  5:01       ` Jakub Kicinski
2023-03-18  5:01         ` Jakub Kicinski
2023-03-23 11:21 ` Jiri Pirko
2023-03-23 11:21   ` Jiri Pirko
2023-03-23 18:00   ` Vadim Fedorenko
2023-03-23 18:00     ` Vadim Fedorenko
2023-03-26 17:00 ` [patch dpll-rfc 0/7] dpll: initial patchset extension by mlx5 implementation Jiri Pirko
2023-03-26 17:00   ` Jiri Pirko
2023-03-26 17:00   ` [patch dpll-rfc 1/7] dpll: make ops function args const Jiri Pirko
2023-03-26 17:00     ` Jiri Pirko
2023-03-26 17:00   ` [patch dpll-rfc 2/7] dpll: allow to call device register multiple times Jiri Pirko
2023-03-26 17:00     ` Jiri Pirko
2023-03-26 17:00   ` [patch dpll-rfc 3/7] dpll: introduce a helper to get first dpll ref and use it Jiri Pirko
2023-03-26 17:00     ` Jiri Pirko
2023-03-26 17:00   ` [patch dpll-rfc 4/7] dpll: allow to call pin register multiple times Jiri Pirko
2023-03-26 17:00     ` Jiri Pirko
2023-03-26 17:00   ` [patch dpll-rfc 5/7] dpll: export dpll_pin_notify() Jiri Pirko
2023-03-26 17:00     ` Jiri Pirko
2023-03-26 17:00   ` [patch dpll-rfc 6/7] netdev: expose DPLL pin handle for netdevice Jiri Pirko
2023-03-26 17:00     ` Jiri Pirko
2023-03-26 17:00   ` [patch dpll-rfc 7/7] mlx5: Implement SyncE support using DPLL infrastructure Jiri Pirko
2023-03-26 17:00     ` Jiri Pirko
2023-03-28 16:36   ` [patch dpll-rfc 0/7] dpll: initial patchset extension by mlx5 implementation Vadim Fedorenko
2023-03-28 16:36     ` Vadim Fedorenko
2023-04-01 12:54     ` Jiri Pirko
2023-04-01 12:54       ` Jiri Pirko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=d192e0ac-3fa3-c799-ac93-84a17e6f6d50@linux.dev \
    --to=vadim.fedorenko@linux.dev \
    --cc=arkadiusz.kubalewski@intel.com \
    --cc=jiri@resnulli.us \
    --cc=jonathan.lemon@gmail.com \
    --cc=kuba@kernel.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-clk@vger.kernel.org \
    --cc=mschmidt@redhat.com \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=poros@redhat.com \
    --cc=vadfed@meta.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.