Files
open-gpu-kernel-modules/src/common/nvswitch/kernel/inc/intr_nvswitch.h
Andy Ritger eb5c7665a1 535.43.02
2023-05-30 10:11:36 -07:00

212 lines
12 KiB
C

/*
* SPDX-FileCopyrightText: Copyright (c) 2018-2020 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef _INTR_NVSWITCH_H_
#define _INTR_NVSWITCH_H_
#include "error_nvswitch.h"
//
// Wrapper to track interrupt servicing
//
#define NVSWITCH_UNHANDLED_INIT(val) (unhandled = (val))
#define NVSWITCH_HANDLED(mask) (unhandled &= ~(mask))
#define NVSWITCH_UNHANDLED_CHECK(_device, _unhandled) \
do \
{ \
if (_unhandled) \
{ \
NVSWITCH_PRINT(_device, ERROR, \
"%s:%d unhandled interrupt! %x\n", \
__FUNCTION__, __LINE__, _unhandled); \
NVSWITCH_PRINT_SXID(_device, \
NVSWITCH_ERR_HW_HOST_UNHANDLED_INTERRUPT, \
"Fatal, unhandled interrupt\n"); \
NVSWITCH_LOG_FATAL_DATA(_device, _HW, \
_HW_HOST_UNHANDLED_INTERRUPT, 0, 0, NV_FALSE, &_unhandled);\
} \
} while(0)
//
// Wrappers for basic leaf interrupt handling
//
#define NVSWITCH_PENDING(_bit) ((bit = (_bit)) && (pending & (_bit)))
#define NVSWITCH_FIRST() (bit & report.raw_first) ? " (First)" : ""
//
// Report/log error interrupt helper.
//
//
// Print an intermediate point (non-leaf) in the interrupt tree.
//
#define NVSWITCH_REPORT_TREE(_logenum) \
do \
{ \
NVSWITCH_PRINT(device, ERROR, "Intermediate, Link %02d \n", link); \
} while(0)
// Log correctable errors
#define NVSWITCH_REPORT_CORRECTABLE(_logenum, _str) \
do \
{ \
NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR ## _logenum, \
"Correctable, Link %02d %s%s\n", link, _str, NVSWITCH_FIRST()); \
NVSWITCH_LOG_NONFATAL_DATA(device, _HW, _logenum, \
link, 0, NV_TRUE, &report); \
if (nvswitch_lib_notify_client_events(device, \
NVSWITCH_DEVICE_EVENT_NONFATAL) != NVL_SUCCESS) \
{ \
NVSWITCH_PRINT(device, ERROR, "%s: Failed to notify event\n", \
__FUNCTION__); \
} \
} while(0)
// Log uncorrectable error that is not fatal to the fabric
#define NVSWITCH_REPORT_NONFATAL(_logenum, _str) \
do \
{ \
NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR ## _logenum, \
"Non-fatal, Link %02d %s%s\n", link, _str, NVSWITCH_FIRST()); \
NVSWITCH_LOG_NONFATAL_DATA(device, _HW, _logenum, \
link, 0, NV_FALSE, &report, _str); \
if (nvswitch_lib_notify_client_events(device, \
NVSWITCH_DEVICE_EVENT_NONFATAL) != NVL_SUCCESS) \
{ \
NVSWITCH_PRINT(device, ERROR, "%s: Failed to notify event\n", \
__FUNCTION__); \
} \
} while(0)
// Log uncorrectable error that is fatal to the fabric
#define NVSWITCH_REPORT_FATAL(_logenum, _str, device_fatal) \
do \
{ \
NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR ## _logenum, \
"Fatal, Link %02d %s%s\n", link, _str, NVSWITCH_FIRST()); \
NVSWITCH_LOG_FATAL_DATA(device, _HW, _logenum, \
link, 0, NV_FALSE, &report, _str); \
nvswitch_set_fatal_error(device, device_fatal, link); \
if (nvswitch_lib_notify_client_events(device, \
NVSWITCH_DEVICE_EVENT_FATAL) != NVL_SUCCESS) \
{ \
NVSWITCH_PRINT(device, ERROR, "%s: Failed to notify event\n",\
__FUNCTION__); \
} \
} while(0)
#define NVSWITCH_REPORT_PRI_ERROR_NONFATAL(_logenum, _str, instance, chiplet, err_data) \
do \
{ \
NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR ## _logenum, \
"Non-fatal, %s, instance=%d, chiplet=%d\n", _str, instance, chiplet); \
NVSWITCH_LOG_NONFATAL_DATA(device, _HW, _logenum, \
instance, chiplet, NV_FALSE, &err_data, _str); \
if (nvswitch_lib_notify_client_events(device, \
NVSWITCH_DEVICE_EVENT_NONFATAL) != NVL_SUCCESS) \
{ \
NVSWITCH_PRINT(device, ERROR, "%s: Failed to notify event\n", \
__FUNCTION__); \
} \
} while(0)
#define NVSWITCH_REPORT_PRI_ERROR_FATAL(_logenum, _str, device_fatal, instance, chiplet, err_data) \
do \
{ \
NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR ## _logenum, \
"Fatal, %s, instance=%d, chiplet=%d\n", _str, instance, chiplet); \
NVSWITCH_LOG_FATAL_DATA(device, _HW, _logenum, \
instance, chiplet, NV_FALSE, &err_data, _str); \
nvswitch_set_fatal_error(device, device_fatal, 0); \
if (nvswitch_lib_notify_client_events(device, \
NVSWITCH_DEVICE_EVENT_FATAL) != NVL_SUCCESS) \
{ \
NVSWITCH_PRINT(device, ERROR, "%s: Failed to notify event\n", \
__FUNCTION__); \
} \
} while(0)
/*
* Automatically determine if error is fatal to the fabric based on
* if it is contained and will lock the port.
*/
#define NVSWITCH_REPORT_CONTAIN(_logenum, _str, device_fatal) \
do \
{ \
if (bit & contain) \
{ \
NVSWITCH_REPORT_FATAL(_logenum, _str, device_fatal); \
} \
else \
{ \
NVSWITCH_REPORT_NONFATAL(_logenum, _str); \
} \
} while (0)
/*
* REPORT_*_DATA macros - optionally log data record for additional HW state. This
* is typically a captured packet, but there are a few other cases.
*
* Most interrupt controllers only latch additional data for errors tagged as first.
* For those cases use _FIRST to only log the data record when it is accurate. If
* two errors are detected in the same cycle, they will both be set in first.
*/
#define NVSWITCH_REPORT_DATA(_logenum, _data) \
NVSWITCH_LOG_NONFATAL_DATA(device, _HW, _logenum, link, 0, NV_TRUE, &_data)
#define NVSWITCH_REPORT_DATA_FIRST(_logenum, _data) \
do \
{ \
if (report.raw_first & bit) \
{ \
NVSWITCH_REPORT_DATA(_logenum, _data); \
} \
} while(0)
#define NVSWITCH_REPORT_CONTAIN_DATA(_logenum, _data) \
do \
{ \
if (bit & contain) \
{ \
NVSWITCH_LOG_FATAL_DATA(device, _HW, _logenum, link, \
0, NV_FALSE, &_data); \
} \
else \
{ \
NVSWITCH_LOG_NONFATAL_DATA(device, _HW, _logenum, link, \
0, NV_FALSE, &data); \
} \
} while(0)
#define NVSWITCH_REPORT_CONTAIN_DATA_FIRST(_logenum, _data) \
do \
{ \
if (bit & report.raw_first) \
{ \
NVSWITCH_REPORT_CONTAIN_DATA(_logenum, _data); \
} \
} while(0)
#endif //_INTR_NVSWITCH_H_