Skip to content

Commit ac10d4f

Browse files
amd-anathjonmason
authored andcommitted
NTB: send DB event when driver is loaded or un-loaded
When the driver on the local side is loaded, it sets SIDE_READY bit in SIDE_INFO register. Likewise, when it is un-loaded, it clears the bit. Also just after being loaded, the driver polls for peer SIDE_READY bit to be set. Since that bit is set when the peer side driver has loaded, the polling on local side breaks as soon as this condition is met. But the situation is different when the driver is un-loaded. Since the polling has already been stopped as mentioned before, if the peer side driver gets un-loaded, the driver on the local side is not notified implicitly. So, we improvise using existing doorbell mechanism. We reserve the highest order bit of the DB register to send a notification to peer when the driver on local side is un-loaded. This also means that now we are one short of 16 DB events and that is taken care of in the valid DB mask. Signed-off-by: Arindam Nath <[email protected]> Signed-off-by: Jon Mason <[email protected]>
1 parent 41dfc3f commit ac10d4f

File tree

2 files changed

+56
-2
lines changed

2 files changed

+56
-2
lines changed

drivers/ntb/hw/amd/ntb_hw_amd.c

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -647,15 +647,47 @@ static void amd_handle_event(struct amd_ntb_dev *ndev, int vec)
647647
writel(status, mmio + AMD_INTSTAT_OFFSET);
648648
}
649649

650+
static void amd_handle_db_event(struct amd_ntb_dev *ndev, int vec)
651+
{
652+
struct device *dev = &ndev->ntb.pdev->dev;
653+
u64 status;
654+
655+
status = amd_ntb_db_read(&ndev->ntb);
656+
657+
dev_dbg(dev, "status = 0x%llx and vec = %d\n", status, vec);
658+
659+
/*
660+
* Since we had reserved highest order bit of DB for signaling peer of
661+
* a special event, this is the only status bit we should be concerned
662+
* here now.
663+
*/
664+
if (status & BIT(ndev->db_last_bit)) {
665+
ntb_db_clear(&ndev->ntb, BIT(ndev->db_last_bit));
666+
/* send link down event notification */
667+
ntb_link_event(&ndev->ntb);
668+
669+
/*
670+
* If we are here, that means the peer has signalled a special
671+
* event which notifies that the peer driver has been
672+
* un-loaded for some reason. Since there is a chance that the
673+
* peer will load its driver again sometime, we schedule link
674+
* polling routine.
675+
*/
676+
schedule_delayed_work(&ndev->hb_timer, AMD_LINK_HB_TIMEOUT);
677+
}
678+
}
679+
650680
static irqreturn_t ndev_interrupt(struct amd_ntb_dev *ndev, int vec)
651681
{
652682
dev_dbg(&ndev->ntb.pdev->dev, "vec %d\n", vec);
653683

654684
if (vec > (AMD_DB_CNT - 1) || (ndev->msix_vec_count == 1))
655685
amd_handle_event(ndev, vec);
656686

657-
if (vec < AMD_DB_CNT)
687+
if (vec < AMD_DB_CNT) {
688+
amd_handle_db_event(ndev, vec);
658689
ntb_db_event(&ndev->ntb, vec);
690+
}
659691

660692
return IRQ_HANDLED;
661693
}
@@ -1096,6 +1128,21 @@ static int amd_init_dev(struct amd_ntb_dev *ndev)
10961128
return rc;
10971129
}
10981130

1131+
ndev->db_valid_mask = BIT_ULL(ndev->db_count) - 1;
1132+
/*
1133+
* We reserve the highest order bit of the DB register which will
1134+
* be used to notify peer when the driver on this side is being
1135+
* un-loaded.
1136+
*/
1137+
ndev->db_last_bit =
1138+
find_last_bit((unsigned long *)&ndev->db_valid_mask,
1139+
hweight64(ndev->db_valid_mask));
1140+
writew((u16)~BIT(ndev->db_last_bit), mmio + AMD_DBMASK_OFFSET);
1141+
/*
1142+
* Since now there is one less bit to account for, the DB count
1143+
* and DB mask should be adjusted accordingly.
1144+
*/
1145+
ndev->db_count -= 1;
10991146
ndev->db_valid_mask = BIT_ULL(ndev->db_count) - 1;
11001147

11011148
/* Enable Link-Up and Link-Down event interrupts */
@@ -1235,9 +1282,15 @@ static void amd_ntb_pci_remove(struct pci_dev *pdev)
12351282
{
12361283
struct amd_ntb_dev *ndev = pci_get_drvdata(pdev);
12371284

1285+
/*
1286+
* Clear the READY bit in SIDEINFO register before sending DB event
1287+
* to the peer. This will make sure that when the peer handles the
1288+
* DB event, it correctly reads this bit as being 0.
1289+
*/
1290+
amd_deinit_side_info(ndev);
1291+
ntb_peer_db_set(&ndev->ntb, BIT_ULL(ndev->db_last_bit));
12381292
ntb_unregister_device(&ndev->ntb);
12391293
ndev_deinit_debugfs(ndev);
1240-
amd_deinit_side_info(ndev);
12411294
amd_deinit_dev(ndev);
12421295
amd_ntb_deinit_pci(ndev);
12431296
kfree(ndev);

drivers/ntb/hw/amd/ntb_hw_amd.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ struct amd_ntb_dev {
193193

194194
u64 db_valid_mask;
195195
u64 db_mask;
196+
u64 db_last_bit;
196197
u32 int_mask;
197198

198199
struct msix_entry *msix;

0 commit comments

Comments
 (0)