Skip to content

Commit f34343c

Browse files
ahduyckPaolo Abeni
authored andcommitted
fbnic: Fix initialization of mailbox descriptor rings
Address to issues with the FW mailbox descriptor initialization. We need to reverse the order of accesses when we invalidate an entry versus writing an entry. When writing an entry we write upper and then lower as the lower 32b contain the valid bit that makes the entire address valid. However for invalidation we should write it in the reverse order so that the upper is marked invalid before we update it. Without this change we may see FW attempt to access pages with the upper 32b of the address set to 0 which will likely result in DMAR faults due to write access failures on mailbox shutdown. Fixes: da3cde0 ("eth: fbnic: Add FW communication mechanism") Signed-off-by: Alexander Duyck <alexanderduyck@fb.com> Reviewed-by: Simon Horman <horms@kernel.org> Reviewed-by: Jacob Keller <jacob.e.keller@intel.com> Link: https://patch.msgid.link/174654717972.499179.8083789731819297034.stgit@ahduyck-xeon-server.home.arpa Reviewed-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
1 parent bdc6470 commit f34343c

File tree

1 file changed

+23
-9
lines changed

1 file changed

+23
-9
lines changed

drivers/net/ethernet/meta/fbnic/fbnic_fw.c

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,29 @@ static void __fbnic_mbx_wr_desc(struct fbnic_dev *fbd, int mbx_idx,
1717
{
1818
u32 desc_offset = FBNIC_IPC_MBX(mbx_idx, desc_idx);
1919

20+
/* Write the upper 32b and then the lower 32b. Doing this the
21+
* FW can then read lower, upper, lower to verify that the state
22+
* of the descriptor wasn't changed mid-transaction.
23+
*/
2024
fw_wr32(fbd, desc_offset + 1, upper_32_bits(desc));
2125
fw_wrfl(fbd);
2226
fw_wr32(fbd, desc_offset, lower_32_bits(desc));
2327
}
2428

29+
static void __fbnic_mbx_invalidate_desc(struct fbnic_dev *fbd, int mbx_idx,
30+
int desc_idx, u32 desc)
31+
{
32+
u32 desc_offset = FBNIC_IPC_MBX(mbx_idx, desc_idx);
33+
34+
/* For initialization we write the lower 32b of the descriptor first.
35+
* This way we can set the state to mark it invalid before we clear the
36+
* upper 32b.
37+
*/
38+
fw_wr32(fbd, desc_offset, desc);
39+
fw_wrfl(fbd);
40+
fw_wr32(fbd, desc_offset + 1, 0);
41+
}
42+
2543
static u64 __fbnic_mbx_rd_desc(struct fbnic_dev *fbd, int mbx_idx, int desc_idx)
2644
{
2745
u32 desc_offset = FBNIC_IPC_MBX(mbx_idx, desc_idx);
@@ -41,21 +59,17 @@ static void fbnic_mbx_init_desc_ring(struct fbnic_dev *fbd, int mbx_idx)
4159
* solid stop for the firmware to hit when it is done looping
4260
* through the ring.
4361
*/
44-
__fbnic_mbx_wr_desc(fbd, mbx_idx, 0, 0);
45-
46-
fw_wrfl(fbd);
62+
__fbnic_mbx_invalidate_desc(fbd, mbx_idx, 0, 0);
4763

4864
/* We then fill the rest of the ring starting at the end and moving
4965
* back toward descriptor 0 with skip descriptors that have no
5066
* length nor address, and tell the firmware that they can skip
5167
* them and just move past them to the one we initialized to 0.
5268
*/
53-
for (desc_idx = FBNIC_IPC_MBX_DESC_LEN; --desc_idx;) {
54-
__fbnic_mbx_wr_desc(fbd, mbx_idx, desc_idx,
55-
FBNIC_IPC_MBX_DESC_FW_CMPL |
56-
FBNIC_IPC_MBX_DESC_HOST_CMPL);
57-
fw_wrfl(fbd);
58-
}
69+
for (desc_idx = FBNIC_IPC_MBX_DESC_LEN; --desc_idx;)
70+
__fbnic_mbx_invalidate_desc(fbd, mbx_idx, desc_idx,
71+
FBNIC_IPC_MBX_DESC_FW_CMPL |
72+
FBNIC_IPC_MBX_DESC_HOST_CMPL);
5973
}
6074

6175
void fbnic_mbx_init(struct fbnic_dev *fbd)

0 commit comments

Comments
 (0)