-
Notifications
You must be signed in to change notification settings - Fork 13
ot_spi_device: discard all packets for a failed transaction
#263
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
|
I do understand the rationale. |
|
I tried that implementation, but the state ended up identical to I don't mind switching to a state if you'd prefer |
If it is not too much work and it does not clutter the code I would say otherwise it is preferable as it is always easier to debug with a single state that having to track a combination of multiple variables. If this ends up being harder to read, please leave it as is. |
9109cba to
3354aca
Compare
|
I've made the change and it passes my test, though I may not have got the ideal implementation edit: oops, let me fix formatting |
3354aca to
c1970f6
Compare
rivos-eblot
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.
I think you also want to add
* Copyright (c) 2025 lowRISC contributors.
to the file header.
AlexJones0
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.
Looks good to me after @rivos-eblot's comments are addressed.
It might also be nice to quickly document this behaviour in the "SPI device CharDev protocol" section of docs/opentitan/spi_device.md, given that the protocol is described in detail (including handling error states) there?
c1970f6 to
ea8242e
Compare
ea8242e to
d5144c4
Compare
|
Rebased on TPM changes |
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 think I totally lost track of what we want to achieve and how we handle it.
DISCARD_PACKET may not be not helping, as we actively store the incoming packet.
I really need to spend some time to understand this new state machine to be sure it does not introduce unexpected behavior.
I think this part is the most confusing:
switch (bus->state) {
case SPI_BUS_IDLE:
case SPI_BUS_FLASH:
case SPI_BUS_DISCARD_PACKET:
BUS_CHANGE_STATE(s, IDLE);
break;
case SPI_BUS_DISCARD:
case SPI_BUS_ERROR:
BUS_CHANGE_STATE(s, DISCARD_PACKET);
break;
default:
g_assert_not_reached();
break;
}- I do not think we should resume to IDLE till the full transaction is over. Maybe it is here, not sure (at least, we need some comments)
- Resuming from ERROR to DISCARD_PACKET is for sure, wrong. For example ERROR is set when the incoming header is invalid, which means there is no way we can recover from it, as we no longer understand the content of the incoming data.
May be flipping to a new state was not a good idea, I'm not sure, but something that is missing is that once we enter the state where we want to discard anything till the last byte of the last packet of a transaction is received (and the same amount of 0xFF bytes is sent back), we should not return to some regular state. Maybe we need one or more extra states to manage:
- ignoring bytes till the end of the current packet (DISCARD_PACKET)
- entering a special state to handle the header of the next packet if the transaction to discard is not over (IDLE_IGNORE?), only entering IDLE once the last byte of the packet of the ignored transaction has been received
- entering the above state when a new packet is received (DISCARD_PACKET)
DISCARD might also need to be renamed or removed: entering this state follows a flash error, so I guess that we want to enter DISCARD_PACKET in this case. It does not seem DISCARD is needed anymore.
|
Let me check my understanding:
So perhaps we need two state machines, one for the transaction and one for the current packet. The transaction might have states:
The packet might have states:
|
Yes, I think so.
If you think it is easier, why not. Questions:
|
@engdoreis can help me out here, but I think the TPM and flash have separate buffers and configuration registers that influence how incoming data it processed. Apparently both TPM and flash can be enabled simultaneously, but the chip select determines which mode to use for a transaction. We don't want to accept transactions which interleave flash and TPM packets, so we need to remember which mode the transaction is in.
My intention was to handle a case like this:
I think I'm not understanding what you mean by propagating the data to the end of the transaction. My plan was for |
Yes, that's correct, it's how the HW is implemented, it's possible to enable flash mode and TPM mode at the same time, and the different CS will define how the incoming package will be processed. |
If I got it right, as the SPI device CharDev protocol does not support this feature yet, and it has been chosen to not support it for now, I think this use case can be dismissed for now.
I'm really not sure this can be handled with 2 SMs as it seems both are inter-dependent, and/or I think the naming is confusing. The transport level, should decode the header, enter fatal error if some byte is deemed invalid, forward the payload, and inform the next layer whether it is the last packet of a transaction. So it needs an ERROR state whenever it is no longer able to parse the incoming stream, and leave this ERROR state only on SPI Device reset. I do not think it needs a "DISCARD" state. The next layer, and here starts my confusion about the naming, should enter the FLASH or TPM mode, enter a DISCARD mode if the current command no longer accept so extra bytes for the current -packet-. I'm not sure whether it needs both ERROR and DISCARD mode in this case. Please ignore my last response regarding the data, it is meaningless. |
|
We would never want to discard only some bytes in the middle of a transaction that has been marked as erroneous, and discarding should persist until after a packet with EOT=1 (which represents the de-assertion of chip select), so I understand the rationale of this change, but I think an additional I think the onus should fall on the |
9109cba to
b46c1d6
Compare
|
I have reverted back to the boolean flag separate from the state machine, but maybe the SPI device does need overhauling separately |
We must adjust the byte count by the number discarded to that we can return to `IDLE` when the packet ends. Signed-off-by: James Wainwright <[email protected]>
If one packet in a transaction triggers an error and needs discarding, we must continue discarding the remaining packets until CS is released. Signed-off-by: James Wainwright <[email protected]>
b46c1d6 to
8a9f6c3
Compare
rivos-eblot
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.
LGTM (not tested)
This changes the SPI device's discarding behaviour in two ways:
This is motivated by seeing that QEMU never stops discarding after it receives an unrecognised flash command as part of a multi-packet transaction (e.g. a "read" transaction which sends a "write read command" packet with EOT=0 followed by a "read bytes" packet with EOT=1).