-
Notifications
You must be signed in to change notification settings - Fork 350
ipc2: introduce IPC2 ABI. #3207
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
Conversation
About
----
IPC2 is a MAJOR ABI update that is not fully backwards compatible with
IPC1.x (using MAJOR 3 today).
IPC2 has the following high level aims
1) Straight forward message life cycle management. Add/deprecate/modify
messages with minimal pain across all messengers.
2) Provide a transition path for code that uses existing or legacy IPC
ABI's so that it can incrementally add IPC2.x features and support.
3) Provide high density messaging similar to vanilla C structs.
4) Message discovery - clients can determine supported message types
and fields at runtime.
5) Standard metadata for all messages with optional extra metadata.
Message Header
--------------
IPC2 messages will all use a standard header that contains generic
message metadata with optional mesage metedata. This will be used
by messengers to help process the message efficiently and securely.
Messages are now catergorized into class, subclass and action in order
to cleanly integrate into the correct driver, feature and use case
infrastrcture within FW and SW.
See header.h
Messaging Enumeration
---------------------
The FW extended manifest data will contain a list of supported messages
classes, subclasses and actions for this individual FW release. This
allows SW to scan the manifest and determine which driver, feature and
use cases are supported. The SW can then make decisions at runtime to
correctly support this individual FW release.
See manifest.h
Message Data Format
-------------------
Each piece of data sent in a message must be tagged with an ID that the
messengers all understand. This {id, data} tuple is the basis for all IPC2
communication as it's generic and has relatively simple life cycle
requirements. i.e. tuples can be easily added, removed without breaking
breaking binary ABIs or requiring all code to be rebuilt.
IPC2 also provides a pathway for migrating legacy code to IPC2. i.e. IPC2
allows existing data messages to be sent using IPC2 with the small
addition of a 1 word header that can be initially ignored by older
messengers.
See message.h
Signed-off-by: Liam Girdwood <[email protected]>
cujomalainey
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What implications will this have for backporting?
| uint32_t route : 1; /**< routing data follows */ | ||
| uint32_t size : 1; /**< size follows */ | ||
| uint32_t elems : 1; /**< data elems follows */ | ||
| uint32_t block : 1; /**< data block follows */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this mutually exclusive to any other values?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes - I did think about use cases where you could have a legacy C struct and some new tuples but that added a bit more complexity. It would be better in this situation (where legacy C structures have to be extended fro new features) to just change to the IPC2 struct for the new feature.
"ack" and "nak" are also mutually exclusive - I will mark these up in the comments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm just wondering if maybe we should make those mutually exclusive field n bit enum fields for safety
| uint32_t num_actions; /**< number of actions in this subclass */ | ||
|
|
||
| /* action data follows here */ | ||
| struct sof_ipc2_action actions[0]; /**< actions - size is num_actions */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not define this as flexible array? Or does that break packing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have not yet checked the packing, only just compiled the headers - this could be a flex array.
| * to perform this action. Tuples are uint16_t. Structure is aligned on | ||
| * word. | ||
| */ | ||
| struct sof_ipc2_action { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are there going to be helpers to help traverse these items? it seems you need to go all the way to the bottom to get the next top level element.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point - we can currently get to next class, subclass and action by adding "size" to the current ptr. The use case would be the :
- common high level code would read each class ID only and send the class data to each driver - e.g. audio class to audio driver, sensing class to sensor driver.
- feature driver (like audio) would then read each subclass ID and forward each subclass to the correct feature logic to parse the actions i.e. PCM subclass to pcm code, control subclass to kcontrol code.
- use case file (like pcm.c) parses each action
The MAJOR ABI update is really just the mandatory prefixing of this 1 word struct on all messages. struct sof_ipc2_hdr {
uint32_t klass : 8; /**< class ID */
uint32_t subklass : 8; /**< subclass ID */
uint32_t action : 8; /**< action ID */
uint32_t ack : 1; /**< message is a reply - success */
uint32_t nack : 1; /**< message is a reply - fail */
uint32_t priority : 1; /**< 0 normal, 1 high */
uint32_t datagram : 1; /**< is datagram - no reply needed */
uint32_t route : 1; /**< routing data follows */
uint32_t size : 1; /**< size follows */
uint32_t elems : 1; /**< data elems follows */
uint32_t block : 1; /**< data block follows */
} __attribute__((packed));The driver will support both IPC MAJOR ABI versions and would detect correct version from FW manifest. i.e. old FW binaries will be able to use new kernels (using MAJOR 3) FW will only use one IPC MAJOR ABI at runtime. If IPC2 needs back ported to older FW releases (say to back port a new feature to an old FW release) , my intention is to make it as simple as possible i.e. diff --git a/src/include/ipc/header.h b/src/include/ipc/header.h
index 436b150a..153bc379 100644
--- a/src/include/ipc/header.h
+++ b/src/include/ipc/header.h
@@ -207,6 +207,7 @@ struct sof_ipc_hdr {
* arrays.
*/
struct sof_ipc_cmd_hdr {
+ #if CONFIG_IPC2
+ struct sof_ipc2_hdr ipc2; /**< Ignored by FW, set to const value for driver */
+ #endif
uint32_t size; /**< size of structure */
uint32_t cmd; /**< SOF_IPC_GLB_ + cmd */
} __attribute__((packed));
diff --git a/src/include/ipc2/manifest.h b/src/include/ipc2/manifest.hFW would ignore the new IPC2 header for all features except the new back ported feature. The driver would know it would have a mixed IPC based on the FW manifest data (generated by rimage - new version would need to be used here too).
|
|
I assume this one needs to be reopened. |
About
IPC2 is a MAJOR ABI update that is not fully backwards compatible with
IPC1.x (using MAJOR 3 today).
IPC2 has the following high level aims
Straight forward message life cycle management. Add/deprecate/modify
messages with minimal pain across all messengers.
Provide a transition path for code that uses existing or legacy IPC
ABI's so that it can incrementally add IPC2.x features and support.
Provide high density messaging similar to vanilla C structs.
Message discovery - clients can determine supported message types
and fields at runtime.
Standard metadata for all messages with optional extra metadata.
Message Header
IPC2 messages will all use a standard header that contains generic
message metadata with optional mesage metedata. This will be used
by messengers to help process the message efficiently and securely.
Messages are now catergorized into class, subclass and action in order
to cleanly integrate into the correct driver, feature and use case
infrastrcture within FW and SW.
See header.h
Messaging Enumeration
The FW extended manifest data will contain a list of supported messages
classes, subclasses and actions for this individual FW release. This
allows SW to scan the manifest and determine which driver, feature and
use cases are supported. The SW can then make decisions at runtime to
correctly support this individual FW release.
See manifest.h
Message Data Format
Each piece of data sent in a message must be tagged with an ID that the
messengers all understand. This {id, data} tuple is the basis for all IPC2
communication as it's generic and has relatively simple life cycle
requirements. i.e. tuples can be easily added, removed without breaking
breaking binary ABIs or requiring all code to be rebuilt.
IPC2 also provides a pathway for migrating legacy code to IPC2. i.e. IPC2
allows existing data messages to be sent using IPC2 with the small
addition of a 1 word header that can be initially ignored by older
messengers.
See message.h
Signed-off-by: Liam Girdwood [email protected]