mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 09:11:26 +03:00
virt oops: Establish IVC channel on LCPU-2
The IVC channel establishment has to be done on LCPU-2 to avoid timeouts during boot. Jira SSV-13035 Signed-off-by: Sanjith T D <std@nvidia.com> Change-Id: Ib647c318621a1b4435909d8a76f25f341bdb2c95 Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3366612 Reviewed-by: Sreenivas Velpula <svelpula@nvidia.com> GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com> Reviewed-by: svcacv <svcacv@nvidia.com> Reviewed-by: Vipin Kumar <vipink@nvidia.com>
This commit is contained in:
@@ -181,7 +181,8 @@ static ssize_t vblk_oops_read(char *buf, size_t bytes, loff_t pos)
|
|||||||
*/
|
*/
|
||||||
if (in_atomic()) {
|
if (in_atomic()) {
|
||||||
dev_warn(vblkdev_oops->device,
|
dev_warn(vblkdev_oops->device,
|
||||||
"%s invoked in atomic context..aborting\n", __func__);
|
"%s invoked in atomic context..returning EBUSY to retry from workqueue\n",
|
||||||
|
__func__);
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -768,6 +769,7 @@ static int vblk_oops_get_configinfo(struct vblk_dev *vblkdev)
|
|||||||
}
|
}
|
||||||
memset(vblkdev->ufs_buf, 0,
|
memset(vblkdev->ufs_buf, 0,
|
||||||
PAGE_SIZE << (get_order(vblkdev_oops->pstore_kmsg_size)));
|
PAGE_SIZE << (get_order(vblkdev_oops->pstore_kmsg_size)));
|
||||||
|
|
||||||
vblkdev->ufs_iova = dma_map_single(vblkdev->device, vblkdev->ufs_buf,
|
vblkdev->ufs_iova = dma_map_single(vblkdev->device, vblkdev->ufs_buf,
|
||||||
vblkdev_oops->pstore_kmsg_size, DMA_BIDIRECTIONAL);
|
vblkdev_oops->pstore_kmsg_size, DMA_BIDIRECTIONAL);
|
||||||
if (dma_mapping_error(vblkdev->device, vblkdev->ufs_iova)) {
|
if (dma_mapping_error(vblkdev->device, vblkdev->ufs_iova)) {
|
||||||
@@ -822,8 +824,10 @@ static void vblk_oops_init_device(struct work_struct *ws)
|
|||||||
if (tegra_hv_ivc_channel_notified(vblkdev->ivck) != 0) {
|
if (tegra_hv_ivc_channel_notified(vblkdev->ivck) != 0) {
|
||||||
dev_warn(vblkdev->device,
|
dev_warn(vblkdev->device,
|
||||||
"%s: IVC channel reset not complete...retry\n", __func__);
|
"%s: IVC channel reset not complete...retry\n", __func__);
|
||||||
schedule_delayed_work(&vblkdev->init,
|
schedule_delayed_work_on(((vblkdev->is_cpu_bound == false) ? DEFAULT_INIT_VCPU :
|
||||||
msecs_to_jiffies(VSC_RESPONSE_WAIT_MS));
|
vblkdev_oops->schedulable_vcpu_number),
|
||||||
|
&vblkdev_oops->init,
|
||||||
|
msecs_to_jiffies(VSC_RESPONSE_WAIT_MS));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -877,6 +881,8 @@ static int tegra_hv_vblk_oops_probe(struct platform_device *pdev)
|
|||||||
static struct device_node *vblk_node;
|
static struct device_node *vblk_node;
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
int ret;
|
int ret;
|
||||||
|
struct device_node *schedulable_vcpu_number_node;
|
||||||
|
bool is_cpu_bound = true;
|
||||||
|
|
||||||
if (!is_tegra_hypervisor_mode()) {
|
if (!is_tegra_hypervisor_mode()) {
|
||||||
dev_err(dev, "Hypervisor is not present\n");
|
dev_err(dev, "Hypervisor is not present\n");
|
||||||
@@ -937,6 +943,30 @@ static int tegra_hv_vblk_oops_probe(struct platform_device *pdev)
|
|||||||
/* defer alignment and minimum size check for later */
|
/* defer alignment and minimum size check for later */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
schedulable_vcpu_number_node = of_find_node_by_name(NULL,
|
||||||
|
"virt-storage-request-submit-cpu-mapping");
|
||||||
|
/* read lcpu_affinity from dts */
|
||||||
|
if (schedulable_vcpu_number_node == NULL) {
|
||||||
|
dev_err(dev, "%s: virt-storage-request-submit-cpu-mapping DT not found\n",
|
||||||
|
__func__);
|
||||||
|
is_cpu_bound = false;
|
||||||
|
} else if (of_property_read_u32(schedulable_vcpu_number_node, "lcpu2tovcpu",
|
||||||
|
&(vblkdev_oops->schedulable_vcpu_number)) != 0) {
|
||||||
|
dev_err(dev, "%s: lcpu2tovcpu affinity is not found\n", __func__);
|
||||||
|
is_cpu_bound = false;
|
||||||
|
}
|
||||||
|
if (vblkdev_oops->schedulable_vcpu_number >= num_online_cpus()) {
|
||||||
|
dev_err(dev, "%s: cpu affinity (%d) > online cpus (%d)\n", __func__,
|
||||||
|
vblkdev_oops->schedulable_vcpu_number, num_online_cpus());
|
||||||
|
is_cpu_bound = false;
|
||||||
|
}
|
||||||
|
if (false == is_cpu_bound) {
|
||||||
|
dev_err(dev, "%s: WARN: CPU is unbound\n", __func__);
|
||||||
|
vblkdev_oops->schedulable_vcpu_number = num_possible_cpus();
|
||||||
|
}
|
||||||
|
|
||||||
|
vblkdev_oops->is_cpu_bound = is_cpu_bound;
|
||||||
|
|
||||||
vblkdev_oops->ivck = tegra_hv_ivc_reserve(NULL, vblkdev_oops->ivc_id, NULL);
|
vblkdev_oops->ivck = tegra_hv_ivc_reserve(NULL, vblkdev_oops->ivc_id, NULL);
|
||||||
if (IS_ERR_OR_NULL(vblkdev_oops->ivck)) {
|
if (IS_ERR_OR_NULL(vblkdev_oops->ivck)) {
|
||||||
dev_err(dev, "Failed to reserve IVC channel %d\n",
|
dev_err(dev, "Failed to reserve IVC channel %d\n",
|
||||||
@@ -958,7 +988,8 @@ static int tegra_hv_vblk_oops_probe(struct platform_device *pdev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* postpone init work that needs response */
|
/* postpone init work that needs response */
|
||||||
schedule_delayed_work(&vblkdev_oops->init,
|
schedule_delayed_work_on(((is_cpu_bound == false) ? DEFAULT_INIT_VCPU :
|
||||||
|
vblkdev_oops->schedulable_vcpu_number), &vblkdev_oops->init,
|
||||||
msecs_to_jiffies(VSC_RESPONSE_WAIT_MS));
|
msecs_to_jiffies(VSC_RESPONSE_WAIT_MS));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -991,7 +1022,7 @@ static int tegra_hv_vblk_oops_remove(struct platform_device *pdev)
|
|||||||
/**
|
/**
|
||||||
* @brief Suspend the OOPS storage device
|
* @brief Suspend the OOPS storage device
|
||||||
*
|
*
|
||||||
* Resets the IVC channel during system suspend.
|
* No Operation is done during system suspend.
|
||||||
*
|
*
|
||||||
* @param[in] dev Device structure pointer
|
* @param[in] dev Device structure pointer
|
||||||
* @return 0 on success
|
* @return 0 on success
|
||||||
@@ -1012,11 +1043,7 @@ static int tegra_hv_vblk_oops_remove(struct platform_device *pdev)
|
|||||||
*/
|
*/
|
||||||
static int tegra_hv_vblk_oops_suspend(struct device *dev)
|
static int tegra_hv_vblk_oops_suspend(struct device *dev)
|
||||||
{
|
{
|
||||||
/* Reset the channel */
|
/* No Op */
|
||||||
mutex_lock(&vblkdev_oops->ivc_lock);
|
|
||||||
tegra_hv_ivc_channel_reset(vblkdev_oops->ivck);
|
|
||||||
mutex_unlock(&vblkdev_oops->ivc_lock);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
* SPDX-FileCopyrightText: Copyright (c) 2023-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _TEGRA_VBLK_H_
|
#ifndef _TEGRA_VBLK_H_
|
||||||
@@ -31,6 +31,8 @@
|
|||||||
/* PSTORE defaults */
|
/* PSTORE defaults */
|
||||||
#define PSTORE_KMSG_RECORD_SIZE (64*1024)
|
#define PSTORE_KMSG_RECORD_SIZE (64*1024)
|
||||||
|
|
||||||
|
/* Default VCPU to run the init work */
|
||||||
|
#define DEFAULT_INIT_VCPU (0U)
|
||||||
|
|
||||||
struct vsc_request {
|
struct vsc_request {
|
||||||
struct vs_request vs_req;
|
struct vs_request vs_req;
|
||||||
@@ -71,6 +73,8 @@ struct vblk_dev {
|
|||||||
bool use_vm_address; /* whether it's on UFS */
|
bool use_vm_address; /* whether it's on UFS */
|
||||||
void *ufs_buf; /* buffer used for UFS DMA, size equals pstore_kmsg_size */
|
void *ufs_buf; /* buffer used for UFS DMA, size equals pstore_kmsg_size */
|
||||||
dma_addr_t ufs_iova; /* IOVA of ufs_buf */
|
dma_addr_t ufs_iova; /* IOVA of ufs_buf */
|
||||||
|
uint32_t schedulable_vcpu_number;
|
||||||
|
bool is_cpu_bound;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user