drivers/watchdog/nv_tco.c
Source file repositories/reference/linux-study-clean/drivers/watchdog/nv_tco.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/watchdog/nv_tco.c- Extension
.c- Size
- 12275 bytes
- Lines
- 513
- Domain
- Driver Families
- Bucket
- drivers/watchdog
- Inferred role
- Driver Families: operation-table or driver-model contract
- Status
- pattern implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Defines an operation table; this is where Linux turns generic core objects into subsystem-specific behavior.
- Touches user memory; correctness depends on fault-safe copying and privilege boundary handling.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/module.hlinux/moduleparam.hlinux/types.hlinux/miscdevice.hlinux/watchdog.hlinux/init.hlinux/fs.hlinux/pci.hlinux/ioport.hlinux/jiffies.hlinux/platform_device.hlinux/uaccess.hlinux/io.hnv_tco.h
Detected Declarations
function seconds_to_ticksfunction tco_timer_startfunction tco_timer_stopfunction tco_timer_keepalivefunction tco_timer_set_heartbeatfunction nv_tco_openfunction nv_tco_releasefunction nv_tco_writefunction nv_tco_ioctlfunction nv_tco_getdevicefunction nv_tco_initfunction nv_tco_cleanupfunction nv_tco_removefunction nv_tco_shutdownfunction nv_tco_init_modulefunction nv_tco_cleanup_modulemodule init nv_tco_init_module
Annotated Snippet
static const struct file_operations nv_tco_fops = {
.owner = THIS_MODULE,
.write = nv_tco_write,
.unlocked_ioctl = nv_tco_ioctl,
.compat_ioctl = compat_ptr_ioctl,
.open = nv_tco_open,
.release = nv_tco_release,
};
static struct miscdevice nv_tco_miscdev = {
.minor = WATCHDOG_MINOR,
.name = "watchdog",
.fops = &nv_tco_fops,
};
/*
* Data for PCI driver interface
*
* This data only exists for exporting the supported
* PCI ids via MODULE_DEVICE_TABLE. We do not actually
* register a pci_driver, because someone else might one day
* want to register another driver on the same PCI id.
*/
static const struct pci_device_id tco_pci_tbl[] = {
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS,
PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS,
PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP78S_SMBUS,
PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP79_SMBUS,
PCI_ANY_ID, PCI_ANY_ID, },
{ 0, }, /* End of list */
};
MODULE_DEVICE_TABLE(pci, tco_pci_tbl);
/*
* Init & exit routines
*/
static unsigned char nv_tco_getdevice(void)
{
struct pci_dev *dev = NULL;
u32 val;
/* Find the PCI device */
for_each_pci_dev(dev) {
if (pci_match_id(tco_pci_tbl, dev) != NULL) {
tco_pci = dev;
break;
}
}
if (!tco_pci)
return 0;
/* Find the base io port */
pci_read_config_dword(tco_pci, 0x64, &val);
val &= 0xffff;
if (val == 0x0001 || val == 0x0000) {
/* Something is wrong here, bar isn't setup */
pr_err("failed to get tcobase address\n");
return 0;
}
val &= 0xff00;
tcobase = val + 0x40;
if (!request_region(tcobase, 0x10, "NV TCO")) {
pr_err("I/O address 0x%04x already in use\n", tcobase);
return 0;
}
/* Set a reasonable heartbeat before we stop the timer */
tco_timer_set_heartbeat(30);
/*
* Stop the TCO before we change anything so we don't race with
* a zeroed timer.
*/
tco_timer_keepalive();
tco_timer_stop();
/* Disable SMI caused by TCO */
if (!request_region(MCP51_SMI_EN(tcobase), 4, "NV TCO")) {
pr_err("I/O address 0x%04x already in use\n",
MCP51_SMI_EN(tcobase));
goto out;
}
val = inl(MCP51_SMI_EN(tcobase));
val &= ~MCP51_SMI_EN_TCO;
Annotation
- Immediate include surface: `linux/module.h`, `linux/moduleparam.h`, `linux/types.h`, `linux/miscdevice.h`, `linux/watchdog.h`, `linux/init.h`, `linux/fs.h`, `linux/pci.h`.
- Detected declarations: `function seconds_to_ticks`, `function tco_timer_start`, `function tco_timer_stop`, `function tco_timer_keepalive`, `function tco_timer_set_heartbeat`, `function nv_tco_open`, `function nv_tco_release`, `function nv_tco_write`, `function nv_tco_ioctl`, `function nv_tco_getdevice`.
- Atlas domain: Driver Families / drivers/watchdog.
- Implementation status: pattern implementation candidate.
- This snippet crosses the user/kernel memory boundary; validate fault handling and access checks before translating the pattern.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.