Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/amdsmu/amdsmu.c
| Show First 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | if (amdsmu_match(parent, NULL)) { | ||||
| if (device_add_child(parent, "amdsmu", -1) == NULL) | if (device_add_child(parent, "amdsmu", -1) == NULL) | ||||
| device_printf(parent, "add amdsmu child failed\n"); | device_printf(parent, "add amdsmu child failed\n"); | ||||
| } | } | ||||
| } | } | ||||
| static int | static int | ||||
| amdsmu_probe(device_t dev) | amdsmu_probe(device_t dev) | ||||
| { | { | ||||
| struct amdsmu_softc *sc; | |||||
| if (resource_disabled("amdsmu", 0)) | if (resource_disabled("amdsmu", 0)) | ||||
| return (ENXIO); | return (ENXIO); | ||||
| if (!amdsmu_match(device_get_parent(dev), NULL)) | sc = device_get_softc(dev); | ||||
| if (!amdsmu_match(device_get_parent(dev), &sc->product)) | |||||
| return (ENXIO); | return (ENXIO); | ||||
| device_set_descf(dev, "AMD System Management Unit"); | device_set_descf(dev, "AMD System Management Unit"); | ||||
| return (BUS_PROBE_GENERIC); | return (BUS_PROBE_GENERIC); | ||||
| } | } | ||||
| static enum amdsmu_res | static enum amdsmu_res | ||||
| amdsmu_wait_res(device_t dev) | amdsmu_wait_res(device_t dev) | ||||
| ▲ Show 20 Lines • Show All 77 Lines • ▼ Show 20 Lines | amdsmu_get_vers(device_t dev) | ||||
| return (0); | return (0); | ||||
| } | } | ||||
| static int | static int | ||||
| amdsmu_get_ip_blocks(device_t dev) | amdsmu_get_ip_blocks(device_t dev) | ||||
| { | { | ||||
| struct amdsmu_softc *sc = device_get_softc(dev); | struct amdsmu_softc *sc = device_get_softc(dev); | ||||
| const uint16_t deviceid = pci_get_device(dev); | |||||
| int err; | int err; | ||||
| struct amdsmu_metrics *m = &sc->metrics; | struct amdsmu_metrics *m = &sc->metrics; | ||||
| bool active; | bool active; | ||||
| char sysctl_descr[32]; | char sysctl_descr[32]; | ||||
| /* Get IP block count. */ | |||||
| switch (deviceid) { | |||||
| case PCI_DEVICEID_AMD_REMBRANDT_ROOT: | |||||
| sc->ip_block_count = 12; | |||||
| break; | |||||
| case PCI_DEVICEID_AMD_PHOENIX_ROOT: | |||||
| sc->ip_block_count = 21; | |||||
| break; | |||||
| /* TODO How many IP blocks does Strix Point (and the others) have? */ | |||||
| case PCI_DEVICEID_AMD_STRIX_POINT_ROOT: | |||||
| default: | |||||
| sc->ip_block_count = nitems(amdsmu_ip_blocks_names); | |||||
| } | |||||
| KASSERT(sc->ip_block_count <= nitems(amdsmu_ip_blocks_names), | |||||
| ("too many IP blocks for array")); | |||||
| /* Get and print out IP blocks. */ | /* Get and print out IP blocks. */ | ||||
| err = amdsmu_cmd(dev, SMU_MSG_GET_SUP_CONSTRAINTS, 0, | err = amdsmu_cmd(dev, SMU_MSG_GET_SUP_CONSTRAINTS, 0, | ||||
| &sc->active_ip_blocks); | &sc->active_ip_blocks); | ||||
| if (err != 0) { | if (err != 0) { | ||||
| device_printf(dev, "failed to get IP blocks\n"); | device_printf(dev, "failed to get IP blocks\n"); | ||||
| return (err); | return (err); | ||||
| } | } | ||||
| device_printf(dev, "Active IP blocks: "); | device_printf(dev, "Active IP blocks: "); | ||||
| for (size_t i = 0; i < sc->ip_block_count; i++) { | for (size_t i = 0; i < sc->product->ip_block_count; i++) { | ||||
| active = (sc->active_ip_blocks & (1 << i)) != 0; | active = (sc->active_ip_blocks & (1 << i)) != 0; | ||||
| sc->ip_blocks_active[i] = active; | sc->ip_blocks_active[i] = active; | ||||
| if (!active) | if (!active) | ||||
| continue; | continue; | ||||
| printf("%s%s", amdsmu_ip_blocks_names[i], | printf("%s%s", amdsmu_ip_blocks_names[i], | ||||
| i + 1 < sc->ip_block_count ? " " : "\n"); | i + 1 < sc->product->ip_block_count ? " " : "\n"); | ||||
| } | } | ||||
| /* Create a sysctl node for IP blocks. */ | /* Create a sysctl node for IP blocks. */ | ||||
| sc->ip_blocks_sysctlnode = SYSCTL_ADD_NODE(sc->sysctlctx, | sc->ip_blocks_sysctlnode = SYSCTL_ADD_NODE(sc->sysctlctx, | ||||
| SYSCTL_CHILDREN(sc->sysctlnode), OID_AUTO, "ip_blocks", | SYSCTL_CHILDREN(sc->sysctlnode), OID_AUTO, "ip_blocks", | ||||
| CTLFLAG_RD, NULL, "SMU metrics"); | CTLFLAG_RD, NULL, "SMU metrics"); | ||||
| if (sc->ip_blocks_sysctlnode == NULL) { | if (sc->ip_blocks_sysctlnode == NULL) { | ||||
| device_printf(dev, "could not add sysctl node for IP blocks\n"); | device_printf(dev, "could not add sysctl node for IP blocks\n"); | ||||
| return (ENOMEM); | return (ENOMEM); | ||||
| } | } | ||||
| /* Create a sysctl node for each IP block. */ | /* Create a sysctl node for each IP block. */ | ||||
| for (size_t i = 0; i < sc->ip_block_count; i++) { | for (size_t i = 0; i < sc->product->ip_block_count; i++) { | ||||
| /* Create the sysctl node itself for the IP block. */ | /* Create the sysctl node itself for the IP block. */ | ||||
| snprintf(sysctl_descr, sizeof sysctl_descr, | snprintf(sysctl_descr, sizeof sysctl_descr, | ||||
| "Metrics about the %s AMD IP block", | "Metrics about the %s AMD IP block", | ||||
| amdsmu_ip_blocks_names[i]); | amdsmu_ip_blocks_names[i]); | ||||
| sc->ip_block_sysctlnodes[i] = SYSCTL_ADD_NODE(sc->sysctlctx, | sc->ip_block_sysctlnodes[i] = SYSCTL_ADD_NODE(sc->sysctlctx, | ||||
| SYSCTL_CHILDREN(sc->ip_blocks_sysctlnode), OID_AUTO, | SYSCTL_CHILDREN(sc->ip_blocks_sysctlnode), OID_AUTO, | ||||
| amdsmu_ip_blocks_names[i], CTLFLAG_RD, NULL, sysctl_descr); | amdsmu_ip_blocks_names[i], CTLFLAG_RD, NULL, sysctl_descr); | ||||
| if (sc->ip_block_sysctlnodes[i] == NULL) { | if (sc->ip_block_sysctlnodes[i] == NULL) { | ||||
| ▲ Show 20 Lines • Show All 73 Lines • ▼ Show 20 Lines | amdsmu_dump_metrics(device_t dev) | ||||
| return (0); | return (0); | ||||
| } | } | ||||
| static void | static void | ||||
| amdsmu_fetch_idlemask(device_t dev) | amdsmu_fetch_idlemask(device_t dev) | ||||
| { | { | ||||
| struct amdsmu_softc *sc = device_get_softc(dev); | struct amdsmu_softc *sc = device_get_softc(dev); | ||||
| sc->idlemask = amdsmu_read4(sc, SMU_REG_IDLEMASK); | sc->idlemask = amdsmu_read4(sc, sc->product->idlemask_reg); | ||||
| } | } | ||||
| static void | static void | ||||
| amdsmu_suspend(device_t dev, enum power_stype stype) | amdsmu_suspend(device_t dev, enum power_stype stype) | ||||
| { | { | ||||
| if (stype != POWER_STYPE_SUSPEND_TO_IDLE) | if (stype != POWER_STYPE_SUSPEND_TO_IDLE) | ||||
| return; | return; | ||||
| /* | |||||
| * XXX It seems that Cezanne needs a special workaround here for | |||||
| * firmware versions < 64.53. See amd_pmc_verify_czn_rtc() in Linux. | |||||
| */ | |||||
| if (amdsmu_cmd(dev, SMU_MSG_SLEEP_HINT, true, NULL) != 0) | if (amdsmu_cmd(dev, SMU_MSG_SLEEP_HINT, true, NULL) != 0) | ||||
| device_printf(dev, "failed to hint to SMU to enter sleep"); | device_printf(dev, "failed to hint to SMU to enter sleep"); | ||||
| } | } | ||||
| static void | static void | ||||
| amdsmu_resume(device_t dev, enum power_stype stype) | amdsmu_resume(device_t dev, enum power_stype stype) | ||||
| { | { | ||||
| if (stype != POWER_STYPE_SUSPEND_TO_IDLE) | if (stype != POWER_STYPE_SUSPEND_TO_IDLE) | ||||
| ▲ Show 20 Lines • Show All 201 Lines • Show Last 20 Lines | |||||