Skip to content

Conversation

@danmois
Copy link
Contributor

@danmois danmois commented Nov 13, 2025

PR Description

Add DPD functionality to the Madura driver.

PR Type

  • Bug fix (a change that fixes an issue)
  • New feature (a change that adds new functionality)
  • Breaking change (a change that affects other repos or cause CIs to fail)

PR Checklist

  • I have conducted a self-review of my own code changes
  • I have compiled my changes, including the documentation
  • I have tested the changes on the relevant hardware
  • [] I have updated the documentation outside this repo accordingly
  • [] I have provided links for the relevant upstream lore

Copy link
Contributor

@gastmaier gastmaier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looked into the ci output to check sanity. the two new warnings seems to be valid, I highlighted with comments.
There are extra warnings outside touched lines, that would be nice to progressively resolve.

In the files changed tab, action summary page, and log file, you can see the ci warnings


ret = sysfs_create_bin_file(&indio_dev->dev.kobj, &phy->bin);
if (ret < 0)
return ret;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From ci: shouldn't this go to the error de-initialization path?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it should, thank you! I will update the function.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also do not use the above function. Directly accessing a fundamental thing as kobjects from a driver is a very strong sign of something very odd. Use the device_create_bin_file() wrapper.


ret = sscanf(line, "%hhu %hhu %hhu %hhu %s", &i, &j, &k, &lut, coef);
if (ret != 5)
return ret;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From ci: this is never a error code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True. I wonder if an error message should be displayed before returning -EINVAL?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Likely yes 😉

@danmois
Copy link
Contributor Author

danmois commented Nov 13, 2025

V2

  • fix error de-initialization path
  • display message and return correct value in case of error in adrv9025_parse_dpd_coef
  • use device_create_bin_file() instead of sysfs_create_bin_file()

return 0;

out_remove_device_bin:
device_remove_bin_file(&phy->indio_dev->dev, &phy->bin);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't you remove the bin file at the remove method as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Thanks!

!!(phy->cal_mask.calMask & val));
break;
case ADRV9025_CAL_MASK:
ret = sprintf(buf, "%d\n",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may be outside the scope of this PR as it looks like a minor addition, but sysfs_emit() should be used instead of sprintf() for sysfs attributes (proper bounds checking, preferred kernel way. Just a thought, might be a chance to modernise the sysfs methods of the driver.

Copy link
Contributor Author

@danmois danmois Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, Vas! You are right, thank you for the observation. However, I used sprintf to keep the current structure of the driver unchanged. I am also not completely sure that we should include this refactoring in this PR, since the current version was tested as it is. From my point of view, DPD is a fairly complex addition to the driver. Do you have any recommendation regarding this @gastmaier , @nunojsa ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I do agree we should modernize it (because copy paste is a fairly common practice for these devices and we do not want to copy old APIs all over).

That said, it needs to be in it's own patch (a precursor patch) and it should be pretty safe to do it even in this PR. I mean, it should be a matter of s/sprintf/sysfs_emit (or using an IDE replace kind of thing).

@danmois
Copy link
Contributor Author

danmois commented Nov 17, 2025

V3

  • remove bin file at the remove method as well

@danmois
Copy link
Contributor Author

danmois commented Nov 17, 2025

V4

  • use sysfs_emit instead of sprintf

@danmois
Copy link
Contributor Author

danmois commented Nov 17, 2025

V5

  • fix status display

@danmois danmois force-pushed the staging/madura_dpd branch 3 times, most recently from db4f953 to 523346f Compare November 18, 2025 07:53
@danmois
Copy link
Contributor Author

danmois commented Nov 18, 2025

V6

  • address CI warnings

Copy link
Contributor

@gastmaier gastmaier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Collaborator

@nunojsa nunojsa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some stuff from me

adi_adrv9025_FramerSel_e framerSel,
u32 *iqRate_kHz)
{
int recoveryAction = ADI_COMMON_ACT_NO_ACTION;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, is this about checkpatch? If so, I need to complain about the commit message. So the message is pretty much just stating what the subject already says. So if I do not look at the code, I have no idea about the change itself.

Also, the git subject could be better. Example, "Address/Fix coding style issues"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, checkpatch does not complain about this, but GihtHub Actions does. I will update the commit title and message, thanks.

rxQecStatus.percentComplete,
rxQecStatus.selfcheckIrrDb,
rxQecStatus.iterCount,
rxQecStatus.updateCount);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess I misunderstood what you meant in teams. Why can't we use sysgs_emit() in here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sysfs_emit works for sysfs, but not for debugfs.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeps, I realized we were talking debugfs later in the review

txQecStatus.percentComplete,
txQecStatus.correctionMetric,
txQecStatus.iterCount,
txQecStatus.updateCount);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto for all other places


if (!len)
len = snprintf(buf, sizeof(buf), "%llu\n", val);
len = scnprintf(buf, sizeof(buf), "%llu\n", val);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here it's a valid place where we cannot use it.

mutex_lock(&phy->lock);
ret = adi_adrv9025_TxToOrxMappingGet(phy->madDevice,
ADI_ADRV9025_ORX1 << (entry->cmd - DBGFS_ORX1_TO_TX),
(adi_adrv9025_TxChannels_e *)&val);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The above is the typical pattern when this would fall part for big endian architectures. Yes, we do not use them and today everything is mostly little endian but the kernel does support big endian archs and a driver is supposed to work in all archs.

struct adrv9025_rf_phy *phy = iio_priv(indio_dev);

if (off)
return 0;
Copy link
Collaborator

@nunojsa nunojsa Nov 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With memory_read_from_buffer() you do not need to to care about the above condition which is you hacking your way to use sysfs_emit() 😄

}

phy->dpdModelConfig->txChannelMask = 0;
phy->dpdModelConfig->dpdNumFeatures = dpdNumFeatures;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm puzzled... Here, you allow to write multiple entries for dpdFeatures but on the read side we just print one? I would say, either don't allow to read it or dump everything

{
struct iio_dev *indio_dev = dev_to_iio_dev(kobj_to_dev(kobj));
struct adrv9025_rf_phy *phy = iio_priv(indio_dev);

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the maximum size this can have? Any idea? If it fits a page (minimum 4096) I would not allow multiple writes on the file. If you force doing it in one go, simplifies things a lot in terms of concurrency. So, if possible I would add this:

https://github.com/analogdevicesinc/linux/blob/main/drivers/iio/adc/navassa/adrv9002.c#L4383

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It fits.


while ((line = strsep(&ptr, "\n"))) {
if (line >= data + size)
break;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a simple condition. So you could allow some comments in these files:

https://github.com/analogdevicesinc/linux/blob/main/drivers/iio/adc/navassa/adrv9002.c#L4383

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you help me out a bit with this comment? I didn’t quite get it. Could you explain it in more detail?

Copy link
Collaborator

@nunojsa nunojsa Nov 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I imagine you have the coefficients in a text file, right? So someone could want to add some comments on it (maybe in the beginning). Like:

# DPD coefficients for profile foo, ...
...

So # would mark a line comment (you could use something else but this one is already fairly standard) and you could put the coefficients in the other lines.

But this is kind of optional. Up to you... Just mentioned because It's something I did for adrv9002

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, will do that, it's a good addition, thanks.

txDpdStatus.dpdErrorCode,
txDpdStatus.dpdPercentComplete,
txDpdStatus.dpdIterCount,
txDpdStatus.dpdUpdateCount);
Copy link
Collaborator

@nunojsa nunojsa Nov 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as before. In here you should use scnprintf() together with simple_read_from_buffer()

I might have wrongly said in some comments before that sysfs_emit() could be used. If it's debugfs and we want to print a string like the above, you should use either the above pattern or a seq file

char coef[10];
char *line;
int ret;

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forgot to mention in the review but the it seems we are writing some global device state. It seems a mutex is needed.

@danmois
Copy link
Contributor Author

danmois commented Nov 19, 2025

V7

  • update commits messages where required
  • add possibility to consume DPD model files containing comments (marked with '#')
  • dump DPD model when reading bin attribute
  • add mutexes to added functions
  • write masks as hexadecimal values
  • DPD model as static attribute
  • make sure the correct RF ORx channel is enabled/has its hardwaregain changed
  • use sysfs_emit where possible

@danmois danmois force-pushed the staging/madura_dpd branch 2 times, most recently from ecf8570 to 02cc5f1 Compare November 19, 2025 16:59
@danmois
Copy link
Contributor Author

danmois commented Nov 19, 2025

V8

  • fix dpd_coef_model display (read once)

Copy link
Collaborator

@nunojsa nunojsa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still some stuff from me

struct adrv9025_rf_phy *phy = iio_priv(indio_dev);

u64 val;
u64 val = 0;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The above is a suspicious change. Is this really about coding style?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I don't know how to categorize it, this is signaled by GitHub actions as a problem.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created a separate commit for this.

chan_no = chan->channel;

if (chan_no > CHAN_RX4) {
// For observation channels, determine which specific channel is enabled
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not kernel style comment

break;

if (val <= 0x0F)
phy->cal_mask.channelMask = (u8)val;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need the cast? I would assume it's implicit


/* force a one write() call as it simplifies things a lot */
if (off) {
dev_err(&phy->spi->dev, "FH regions must be set in one write() call\n");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bad copy paste :)

phy->dpdModelConfig->dpdFeatures[dpdNumFeatures].i = i;
phy->dpdModelConfig->dpdFeatures[dpdNumFeatures].j = j;
phy->dpdModelConfig->dpdFeatures[dpdNumFeatures].k = k;
phy->dpdModelConfig->dpdFeatures[dpdNumFeatures].lut = (adi_adrv9025_DpdLut_e)lut;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't think we need the cast

phy->dpdModelConfig->dpdFeatures[dpdNumFeatures].coeffReal_xM = 0;
phy->dpdModelConfig->dpdFeatures[dpdNumFeatures].coeffImaginary_xM = 0;

dpdNumFeatures++;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should likely validate the above iterator for the maximum number of allowed entries

int ret;

mutex_lock(&phy->lock);
if (!off) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The above does not look correct. See how to use memory_read_from_buffer() as it handles off for you. And it properly return EOF when appropriate.

return -ENOMEM;
phy->dpdModelConfig = kzalloc(sizeof(adi_adrv9025_DpdModelConfig_v2_t), GFP_KERNEL);
if (!(phy->dpdModelConfig))
return -ENOMEM;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, when is the above memory released?

return -ENOMEM;
phy->dpdTrackingConfig = kzalloc(sizeof(adi_adrv9025_DpdTrackingConfig_t), GFP_KERNEL);
if (!(phy->dpdTrackingConfig))
return -ENOMEM;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question about memory? Seems like a leak

@danmois danmois force-pushed the staging/madura_dpd branch 6 times, most recently from ea6da4d to e2c54e3 Compare November 26, 2025 08:23
@danmois
Copy link
Contributor Author

danmois commented Nov 26, 2025

V9

  • split first commit so that titles correctly reflect the changes made
  • fix comment style
  • remove redundant cast operations
  • correct error message
  • validate DPD feature iterator against maximum allowable value
  • use memory_read_from_buffer() in DPD coefficient read function
  • solve memory leaks

Remove variables that are not needed, initialize local variables
where required, fix spacing, and remove redundant semicolons and
blank lines.
No functional change.

Signed-off-by: George Mois <[email protected]>
Initialize the val local variable to 0.
Initialize the rate local variable to 0.
Remove redundant blank line.

Signed-off-by: George Mois <[email protected]>
Use sysfs_emit instead of sprintf.
Use safe functions for formatting buffers.

Signed-off-by: George Mois <[email protected]>
Make sure that only one RF channel (ORx1 or ORx2, and ORx3 or ORx4,
respectively) is enabled per ORx data path.

Signed-off-by: George Mois <[email protected]>
Select the active ORx RF input for modifying the hardwaregain
corresponding to one of the two ORx datapaths.

Signed-off-by: George Mois <[email protected]>
Add Orx to Tx mapping setting functionality.

Signed-off-by: George Mois <[email protected]>
Add external path delay initial calibration selection.

Signed-off-by: George Mois <[email protected]>
Add an IIO attribute that allows changing the calibration mask.

Signed-off-by: George Mois <[email protected]>
Add a bin_attribute for loading the data structure to hold Tx DPD
Model initialization parameters, without floats.

Signed-off-by: George Mois <[email protected]>
Add IIO attribute for selecting the target Tx channel for DPD.

Signed-off-by: George Mois <[email protected]>
Add IIO attribute for resetting DPD.

Signed-off-by: George Mois <[email protected]>
Add DEBUGF attribut for getting DPD status on each of the 4 Tx
channels.

Signed-off-by: George Mois <[email protected]>
Add tracking configuration settings.

Signed-off-by: George Mois <[email protected]>
Add IIO attribute for enabling DPD.

Signed-off-by: George Mois <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants