Skip to content

Commit 5f0856b

Browse files
amd-anathjonmason
authored andcommitted
NTB: return link up status correctly for PRI and SEC
Since NTB connects two physically separate systems, there can be scenarios where one system goes down while the other one remains active. In case of NTB primary, if the NTB secondary goes down, a Link-Down event is received. For the NTB secondary, if the NTB primary goes down, the PCIe hotplug mechanism ensures that the driver on the secondary side is also unloaded. But there are other scenarios to consider as well, when suppose the physical link remains active, but the driver on primary or secondary side is loaded or un-loaded. When the driver is loaded, on either side, it sets SIDE_READY bit(bit-1) of SIDE_INFO register. Similarly, when the driver is un-loaded, it resets the same bit. We consider the NTB link to be up and operational only when the driver on both sides of link are loaded and ready. But we also need to take account of Link Up and Down events which signify the physical link status. So amd_link_is_up() is modified to take care of the above scenarios. Signed-off-by: Arindam Nath <[email protected]> Signed-off-by: Jon Mason <[email protected]>
1 parent ae5f4bd commit 5f0856b

File tree

2 files changed

+60
-5
lines changed

2 files changed

+60
-5
lines changed

drivers/ntb/hw/amd/ntb_hw_amd.c

Lines changed: 59 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -245,12 +245,66 @@ static int amd_ntb_get_link_status(struct amd_ntb_dev *ndev)
245245

246246
static int amd_link_is_up(struct amd_ntb_dev *ndev)
247247
{
248-
if (!ndev->peer_sta)
249-
return ndev->cntl_sta;
248+
int ret;
249+
250+
/*
251+
* We consider the link to be up under two conditions:
252+
*
253+
* - When a link-up event is received. This is indicated by
254+
* AMD_LINK_UP_EVENT set in peer_sta.
255+
* - When driver on both sides of the link have been loaded.
256+
* This is indicated by bit 1 being set in the peer
257+
* SIDEINFO register.
258+
*
259+
* This function should return 1 when the latter of the above
260+
* two conditions is true.
261+
*
262+
* Now consider the sequence of events - Link-Up event occurs,
263+
* then the peer side driver loads. In this case, we would have
264+
* received LINK_UP event and bit 1 of peer SIDEINFO is also
265+
* set. What happens now if the link goes down? Bit 1 of
266+
* peer SIDEINFO remains set, but LINK_DOWN bit is set in
267+
* peer_sta. So we should return 0 from this function. Not only
268+
* that, we clear bit 1 of peer SIDEINFO to 0, since the peer
269+
* side driver did not even get a chance to clear it before
270+
* the link went down. This can be the case of surprise link
271+
* removal.
272+
*
273+
* LINK_UP event will always occur before the peer side driver
274+
* gets loaded the very first time. So there can be a case when
275+
* the LINK_UP event has occurred, but the peer side driver hasn't
276+
* yet loaded. We return 0 in that case.
277+
*
278+
* There is also a special case when the primary side driver is
279+
* unloaded and then loaded again. Since there is no change in
280+
* the status of NTB secondary in this case, there is no Link-Up
281+
* or Link-Down notification received. We recognize this condition
282+
* with peer_sta being set to 0.
283+
*
284+
* If bit 1 of peer SIDEINFO register is not set, then we
285+
* simply return 0 irrespective of the link up or down status
286+
* set in peer_sta.
287+
*/
288+
ret = amd_poll_link(ndev);
289+
if (ret) {
290+
/*
291+
* We need to check the below only for NTB primary. For NTB
292+
* secondary, simply checking the result of PSIDE_INFO
293+
* register will suffice.
294+
*/
295+
if (ndev->ntb.topo == NTB_TOPO_PRI) {
296+
if ((ndev->peer_sta & AMD_LINK_UP_EVENT) ||
297+
(ndev->peer_sta == 0))
298+
return ret;
299+
else if (ndev->peer_sta & AMD_LINK_DOWN_EVENT) {
300+
/* Clear peer sideinfo register */
301+
amd_clear_side_info_reg(ndev, true);
250302

251-
if (ndev->peer_sta & AMD_LINK_UP_EVENT) {
252-
ndev->peer_sta = 0;
253-
return 1;
303+
return 0;
304+
}
305+
} else { /* NTB_TOPO_SEC */
306+
return ret;
307+
}
254308
}
255309

256310
return 0;

drivers/ntb/hw/amd/ntb_hw_amd.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,5 +217,6 @@ struct amd_ntb_dev {
217217

218218
static void amd_set_side_info_reg(struct amd_ntb_dev *ndev, bool peer);
219219
static void amd_clear_side_info_reg(struct amd_ntb_dev *ndev, bool peer);
220+
static int amd_poll_link(struct amd_ntb_dev *ndev);
220221

221222
#endif

0 commit comments

Comments
 (0)