Skip to content

Commit 7371f2d

Browse files
ahduyckSasha Levin
authored andcommitted
fbnic: Do not allow mailbox to toggle to ready outside fbnic_mbx_poll_tx_ready
[ Upstream commit ce2fa1d ] We had originally thought to have the mailbox go to ready in the background while we were doing other things. One issue with this though is that we can't disable it by clearing the ready state without also blocking interrupts or calls to mbx_poll as it will just pop back to life during an interrupt. In order to prevent that from happening we can pull the code for toggling to ready out of the interrupt path and instead place it in the fbnic_mbx_poll_tx_ready path so that it becomes the only spot where the Rx/Tx can toggle to the ready state. By doing this we can prevent races where we disable the DMA and/or free buffers only to have an interrupt fire and undo what we have done. Fixes: da3cde0 ("eth: fbnic: Add FW communication mechanism") Signed-off-by: Alexander Duyck <alexanderduyck@fb.com> Reviewed-by: Jacob Keller <jacob.e.keller@intel.com> Link: https://patch.msgid.link/174654722518.499179.11612865740376848478.stgit@ahduyck-xeon-server.home.arpa Reviewed-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Paolo Abeni <pabeni@redhat.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent eb7dc47 commit 7371f2d

File tree

1 file changed

+10
-17
lines changed

1 file changed

+10
-17
lines changed

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

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -299,10 +299,6 @@ static void fbnic_mbx_init_desc_ring(struct fbnic_dev *fbd, int mbx_idx)
299299
{
300300
struct fbnic_fw_mbx *mbx = &fbd->mbx[mbx_idx];
301301

302-
/* This is a one time init, so just exit if it is completed */
303-
if (mbx->ready)
304-
return;
305-
306302
mbx->ready = true;
307303

308304
switch (mbx_idx) {
@@ -322,21 +318,18 @@ static void fbnic_mbx_init_desc_ring(struct fbnic_dev *fbd, int mbx_idx)
322318
}
323319
}
324320

325-
static void fbnic_mbx_postinit(struct fbnic_dev *fbd)
321+
static bool fbnic_mbx_event(struct fbnic_dev *fbd)
326322
{
327-
int i;
328-
329323
/* We only need to do this on the first interrupt following reset.
330324
* this primes the mailbox so that we will have cleared all the
331325
* skip descriptors.
332326
*/
333327
if (!(rd32(fbd, FBNIC_INTR_STATUS(0)) & (1u << FBNIC_FW_MSIX_ENTRY)))
334-
return;
328+
return false;
335329

336330
wr32(fbd, FBNIC_INTR_CLEAR(0), 1u << FBNIC_FW_MSIX_ENTRY);
337331

338-
for (i = 0; i < FBNIC_IPC_MBX_INDICES; i++)
339-
fbnic_mbx_init_desc_ring(fbd, i);
332+
return true;
340333
}
341334

342335
/**
@@ -737,7 +730,7 @@ static void fbnic_mbx_process_rx_msgs(struct fbnic_dev *fbd)
737730

738731
void fbnic_mbx_poll(struct fbnic_dev *fbd)
739732
{
740-
fbnic_mbx_postinit(fbd);
733+
fbnic_mbx_event(fbd);
741734

742735
fbnic_mbx_process_tx_msgs(fbd);
743736
fbnic_mbx_process_rx_msgs(fbd);
@@ -746,11 +739,9 @@ void fbnic_mbx_poll(struct fbnic_dev *fbd)
746739
int fbnic_mbx_poll_tx_ready(struct fbnic_dev *fbd)
747740
{
748741
unsigned long timeout = jiffies + 10 * HZ + 1;
749-
struct fbnic_fw_mbx *tx_mbx;
750-
int err;
742+
int err, i;
751743

752-
tx_mbx = &fbd->mbx[FBNIC_IPC_MBX_TX_IDX];
753-
while (!tx_mbx->ready) {
744+
do {
754745
if (!time_is_after_jiffies(timeout))
755746
return -ETIMEDOUT;
756747

@@ -765,9 +756,11 @@ int fbnic_mbx_poll_tx_ready(struct fbnic_dev *fbd)
765756
return -ENODEV;
766757

767758
msleep(20);
759+
} while (!fbnic_mbx_event(fbd));
768760

769-
fbnic_mbx_poll(fbd);
770-
}
761+
/* FW has shown signs of life. Enable DMA and start Tx/Rx */
762+
for (i = 0; i < FBNIC_IPC_MBX_INDICES; i++)
763+
fbnic_mbx_init_desc_ring(fbd, i);
771764

772765
/* Request an update from the firmware. This should overwrite
773766
* mgmt.version once we get the actual version from the firmware

0 commit comments

Comments
 (0)