Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DRAFT] Update MBQ regmap to handle more sizes and defers #5087

Closed

Conversation

charleskeepax
Copy link

Add support to the existing MBQ regmap for 8-bit and 32-bit reads, as well SDCA style deferred reads that require retrying once the device side has had a chance to get the result ready. Probably makes more sense to send this directly upstream rather than merging through the SOF repo, but thought I would push a version here so you guys can have a chance to express any strong opinions before we get upstream involved.

drivers/base/regmap/regmap-sdw-mbq.c Show resolved Hide resolved
include/linux/regmap.h Show resolved Hide resolved
break;
default:
return -EINVAL;
}
Copy link
Member

Choose a reason for hiding this comment

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

I have multiple objections to this patch

a) what makes you think the COMMAND_IGNORED will only happen for MBQs?

b) there's no concept of retry time, only a worst-case property, and the best solution is really to poll on the FunctionBusy bit. even if you only use the sleep and retry, for the final timeout case you'd want to log what the function busy bit value is.

c) DisCo has the concept of mipi-sdca-control-deferrable, so we should only use the deferred mechanism for the controls (and thus address ranges) that require this mechanism.

I would use another callback in addition to mbq_size to check if a control requires this check or not.

Copy link
Author

Choose a reason for hiding this comment

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

Using the function busy would perhaps be slightly more accurate, but it adds a fair amount of complexity without really much in the way of advantages. You still have all the same questions of how often to poll and how long to poll for, I wouldn't object to changing to a total poll time if that is preferred rather than a delay between polls but fairly close to equivalent.

I could perhaps add a callback to trigger this only for deferrable controls, the decision I made the first time through was that it wasn't really worth it. There are really two situations you could get a command ignored for a non-deferrable control, the control doesn't exist or something went wrong. In either case retrying didn't really feel like much of an issue. It will either fail eventually or succeed on the retry if it was an intermittent fault.

Copy link
Member

Choose a reason for hiding this comment

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

if you have an intermittent fault then something is really very wrong -> the device lost sync, interrupts are disabled and the audio transfers were stopped. I don't see much merit in trying to conceal such problems, fail big and fail early is better IMHO. I really think we should only have a different behavior when the spec requires us to do so...

Copy link
Author

Choose a reason for hiding this comment

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

Yeah that is a fair point, I do like to fail early and big :-) will add a callback for the deferrabililty of the control.

@charleskeepax
Copy link
Author

Finally managed to get some more time to look at this, updated version that includes polling the function busy bit rather than just retrying and a few minor tidy ups.

Copy link
Member

@plbossart plbossart left a comment

Choose a reason for hiding this comment

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

nice code @charleskeepax, I added a set of comments on possible conceptual issues (which could be a misunderstanding on my side as well).

return ret;
fallthrough;
case 1:
return sdw_write_no_pm(slave, reg, val & 0xff);
Copy link
Member

Choose a reason for hiding this comment

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

Maybe I need more coffee while reading this post-lunch, but now I wonder if we actually need two regmaps for 'regular' 8 bits registers and extended MBQ for more that one byte.

Could we unify the two existing regmap handling?

Copy link
Author

Choose a reason for hiding this comment

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

Oops missed this first comment, yeah my intention is that this patch unifies them and allows the MBQ register map to access 8-bit registers.

Copy link
Member

Choose a reason for hiding this comment

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

so there would be an additional step of conversion of all existing regmap-sdw.c users.

Or the other way around, maybe the easiest path would be to move all the code from regmap-sdw-mbq.c into regmap-sdw.c, and then transition the small set of users of the MBQ stuff?

Copy link
Author

Choose a reason for hiding this comment

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

I don't think we should get rid of the standard sdw regmap stuff, they serve different purposes. The regular map provides access to larger registers without MBQ, that isn't possible through the MBQ map, see all the 32-bit non-soundwire/SDCA registers on the cs42l43 or cs35l56.

Nothing should really "need" converted here, these changes should be entirely backwards compatible. So all existing code will work as is, although I would probably advise that the few codecs using multiple register maps for SDCA do get converted just because of the complexity and error prone-ness of implementing things that way, but that is up to the maintainers of those drivers.

Copy link
Member

Choose a reason for hiding this comment

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

not following the point about serving different purposes. I don't see much of a difference between a vendor-specific and a class-defined register, and I don't like giving people the option of hurting themselves. I don't also understand the "32-bit non-soundwire/SDCA registers on the cs42l43 or cs35l56", the only thing the regular regmap will support is 8-bit registers.

Copy link
Author

Choose a reason for hiding this comment

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

Loosely the way I see this is the MBQ register map is the SDCA regmap and the plain sdw one is just for plain soundwire devices.

Copy link
Member

Choose a reason for hiding this comment

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

that's not my interpretation at all. the plain sdw regmap was for 8 bit registers and larger registers had to use the mbq stuff.

by removing the size restrictions on all sides, Cirrus Logic created an interesting question of what regmap should be used when....

If both implementations of regmaps for soundwire support multiple sizes, I am not sure why we need 2.
The only thing the MBQ does is write the 8-bit values in a specific order to be standard, I can't think how this would impact access to non-SDCA registers?

Copy link
Author

Choose a reason for hiding this comment

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

The two register maps access data different for >1 bytes data. The sdw register maps just accesses the bytes sequentially, the mbq register maps uses the mbq protocol whilst accessing them. The mbq map also processes the whole thing as single byte calls to the soundwire core, whereas the regular map passes the whole transaction to the core allowing for slight efficiency improvements that are not possible in the mbq case.

The regular map is more of a direct mapping of the Linux soundwire API to a regmap, whereas the mbq one layers protocol on top. I am not sure I see that it creates any confusion other than arguably in the single byte case without defers where you could legitimately use either map but in that case it just doesn't really matter which you use. Although the standard would seem logical since you are using no mbq features. For higher sized registers only one of the two maps will actually work for a given device. But the differentiation between them seems pretty clear cut to me if you just want raw bytes over soundwire normal map, if you want mbq protocol on top of that mbq.

Copy link
Member

Choose a reason for hiding this comment

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

I am probably missing something or not up-to-speed on all this.
Do you have any examples where the regmap stuff updates multiple registers with "slight efficiency improvements that are not possible in the mbq case".
Also if you have an example of non-mbq registers with more than 8 bits, that would be useful.

Copy link
Author

Choose a reason for hiding this comment

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

For examples of non-MBQ registers with more than 8-bits you can look at any of cs42l43 registers (they are all 32-bit, non-mbq) the regmap_config is defined in drivers/mfd/cs42l43.c. I would be up for an actual chat if you want to go through the details of cs42l43s hardware more closely, that is probably best done offline. But I guess there are few reasons for this, but mostly Cirrus has been making soundwire chips a lot longer than MBQ has been a thing and our chips tend to offer multiple control buses (i2c/spi).

For the discussions of efficiency. A lot of it is really that the MBQ regmap is forced to use the reg_read/reg_write interface to regmap which processes a single transaction. This forces regmap to do additional processing/copies, particularly for larger bulk/raw read/writes, although those are less likely in an MBQ context anyway.
Secondly, the regmap-sdw-mbq is forced to use sdw_read, also because of the address changing between bytes of a single transaction. But regmap-sdw can use sdw_nwrite to pass the whole tranaction to the soundwire master at once letting it fill its whole internal FIFO and let rip. Using nwrite may also have some benefits if we were to look at integrating BRA into the system for larger transactions, I know you are currently favouring a separate API for BRA and I haven't spent enough time working through it to really form a solid opinion there yet, but it would be nice to not close doors earlier than we need to.

But fundamentally I think those things are fringe benefits and it really comes down to this, the two register maps access multiple byte quantities in different ways, so they should be different register maps. A chip either does things one way or the other way so its pretty easy to pick which map to use, and even if you get it wrong changing between costs a few minutes. Allowing them both to support 8-bit registers, even though those are handled identically in both, also makes sense because it avoid having to write drivers that have multiple regmaps which is error prone and really balloons code size when interfacing with ASoC.

return ret;
fallthrough;
case 1:
return sdw_write_no_pm(slave, reg, val & 0xff);
Copy link
Member

Choose a reason for hiding this comment

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

the other point that makes me tick is that in theory regular 8-bits SDCA registers could also be deferred. But this PR adds the deferrable property only for MBQs, so not sure if we are going in the right direction if we end-up having deferrable support in two places?

Copy link
Author

Choose a reason for hiding this comment

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

Not sure I totally follow this one, you can access regular 8-bit registers through this regmap there is no need to differentiate them the behaviour is identical.

drivers/base/regmap/regmap-sdw-mbq.c Show resolved Hide resolved
drivers/base/regmap/regmap-sdw-mbq.c Show resolved Hide resolved
@@ -503,11 +503,22 @@ struct regmap_range_cfg {
* struct regmap_sdw_mbq_cfg - Configuration for Multi-Byte Quantities
*
* @mbq_size: Callback returning the actual size of the given register.
* @deferrable: Callback returning true if the hardware can defer
* transactions to the given register.
Copy link
Member

Choose a reason for hiding this comment

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

@charleskeepax we should add a comment that only SDCA controls are allowed to be deferred, and for SDCA devices the DisCo spec provides a list of all SDCA controls and if each control can be deferred with a _DSD property. In other words this callback could be implemented either with a hard-coded switch table in the driver or by collecting information from platform firmware.

Copy link
Author

Choose a reason for hiding this comment

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

Sure, seems sensible will add that.

Compliment the existing macro to construct an SDCA control address with
additional macros to extract the constituent parts of such an address.
Also add defines for the FUNCTION_STATUS register.

Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
SoundWire MBQ register maps typically contain a variety of register
sizes, which doesn't map ideally to the regmap abstraction which
expects register maps to have a consistent size. Currently the MBQ
register map only allows 16-bit registers to be defined, however
this leads to complex CODEC driver implementations with an 8-bit
register map and a 16-bit MBQ, every control will then have a custom
get and put handler that allows them to access different register
maps. Further more 32-bit MBQ quantities are not currently supported.

Add support for additional MBQ sizes and to avoid the complexity
of multiple register maps treat the val_size as a maximum size for
the register map. Within the regmap use an ancillary callback to
determine how many bytes to actually read/write to the hardware for
a specific register. In the case that no callback is defined the
behaviour defaults back to the existing behaviour of a fixed size
register map.

Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
The SDCA specification allows for controls to be deferred. In the case
of a deferred control the device will return COMMAND_IGNORED to the
8-bit operation that would cause the value to commit. Which is the
final 8-bits on a write, or the first 8-bits on a read. In the case of
receiving a defer, the regmap will poll the SDCA function busy bit,
after which the transaction will be retried, returning an error if the
function busy does not clear within a chip specific timeout. Since
this is common SDCA functionality which is the 99% use-case for MBQs
it makes sense to incorporate this functionality into the register
map. If no MBQ configuration is specified, the behaviour will default
to the existing behaviour.

Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
@bardliao
Copy link
Collaborator

@charleskeepax Is this PR ready to merge?

@charleskeepax
Copy link
Author

I was thinking probably best if I send this one directly upstream, nothing that really depends on it in the sof tree yet, and in case it gets any major changes, but mostly happy either way.

@bardliao
Copy link
Collaborator

I was thinking probably best if I send this one directly upstream, nothing that really depends on it in the sof tree yet, and in case it gets any major changes, but mostly happy either way.

Yes, it would be appreciated if you could send it directly upstream. :)

@charleskeepax
Copy link
Author

Going to close this for now, will re-open if there are any significant changes, otherwise will get around to sending upstream for comments soon.

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.

3 participants