nvethernet: Add IVC fix

Issue: rt_spinlock causes IVC failures.

Fix:
1. Change rt_spinlock to spinlock.
2. Add timeout to ivc_can_read.

Bug 2694285

Change-Id: Ib603c304e750a33262e8509ed3f869030b934958
Signed-off-by: Nagaraj Annaiah <nannaiah@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2497217
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: Srinivas Ramachandran <srinivasra@nvidia.com>
Reviewed-by: Ashutosh Jha <ajha@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
GVS: Gerrit_Virtual_Submit
This commit is contained in:
nannaiah
2021-03-11 11:09:17 -08:00
committed by Revanth Kumar Uppala
parent f4d30eb89b
commit 8c8eceeeb7
3 changed files with 33 additions and 11 deletions

View File

@@ -760,7 +760,7 @@ static void ether_start_ivc(struct ether_priv_data *pdata)
}
ictxt->ivc_state = 1;
// initialize
raw_spin_lock_init(&ictxt->ivck_lock);
spin_lock_init(&ictxt->ivck_lock);
}
}

View File

@@ -128,6 +128,23 @@
*/
#define ETHER_TX_MAX_FRAME_SIZE GSO_MAX_SIZE
/**
* @brief IVC wait timeout.
*/
#define IVC_WAIT_TIMEOUT (msecs_to_jiffies(100))
/**
* @brief IVC read timeout cnt.
* used as 20*IVC_WAIT_TIMEOUT hence Max is 2 sec timeout.
*/
#define IVC_READ_TIMEOUT_CNT 20
/**
* @brief IVC channel timeout.
* Used with 1 millisec so max timeout is 50 ms.
*/
#define IVC_CHANNEL_TIMEOUT_CNT 50
/**
* @brief Check if Tx data buffer length is within bounds.
*
@@ -241,7 +258,7 @@ struct ether_ivc_ctxt {
/** ivc cookie */
struct tegra_hv_ivc_cookie *ivck;
/** ivc lock */
raw_spinlock_t ivck_lock;
spinlock_t ivck_lock;
/** ivc work */
struct work_struct ivc_work;
/** wait for event */

View File

@@ -17,8 +17,6 @@
#include "ether_linux.h"
#include <ivc_core.h>
#define IVC_WAIT_TIMEOUT (msecs_to_jiffies(1000))
/**
* @brief Adds delay in micro seconds.
*
@@ -439,7 +437,7 @@ int osd_ivc_send_cmd(void *priv, void *data, unsigned int len)
struct ether_ivc_ctxt *ictxt = &pdata->ictxt;
struct tegra_hv_ivc_cookie *ivck =
(struct tegra_hv_ivc_cookie *) ictxt->ivck;
int dcnt = 50;
int dcnt = IVC_CHANNEL_TIMEOUT_CNT;
int is_atomic = 0;
if (len > ETHER_MAX_IVC_BUF) {
dev_err(pdata->dev, "Invalid IVC len\n");
@@ -447,7 +445,7 @@ int osd_ivc_send_cmd(void *priv, void *data, unsigned int len)
}
ivc_buf->status = -1;
raw_spin_lock_irqsave(&ictxt->ivck_lock, flags);
spin_lock_irqsave(&ictxt->ivck_lock, flags);
if (in_atomic()) {
preempt_enable();
is_atomic = 1;
@@ -458,7 +456,7 @@ int osd_ivc_send_cmd(void *priv, void *data, unsigned int len)
osd_msleep(1);
dcnt--;
if (!dcnt) {
pr_err("IVC recv timeout\n");
dev_err(pdata->dev, "IVC channel timeout\n");
goto fail;
}
}
@@ -470,19 +468,26 @@ int osd_ivc_send_cmd(void *priv, void *data, unsigned int len)
len, ret, ivc_buf->cmd);
goto fail;
}
while (!tegra_hv_ivc_can_read(ictxt->ivck)) {
dcnt = IVC_READ_TIMEOUT_CNT;
while ((!tegra_hv_ivc_can_read(ictxt->ivck))) {
wait_for_completion_timeout(&ictxt->msg_complete, IVC_WAIT_TIMEOUT);
dcnt--;
if (!dcnt) {
dev_err(pdata->dev, "IVC read timeout\n");
break;
}
}
ret = tegra_hv_ivc_read(ivck, ivc_buf, len);
if (ret < 0) {
dev_err(pdata->dev, "IVC read failed: %d\n", ret);
}
ret = ivc_buf->status;
fail:
if (is_atomic) {
preempt_disable();
}
ret = ivc_buf->status;
fail:
raw_spin_unlock_irqrestore(&ictxt->ivck_lock, flags);
spin_unlock_irqrestore(&ictxt->ivck_lock, flags);
return ret;
}