Index: if_umb.c =================================================================== RCS file: /cvs/src/sys/dev/usb/if_umb.c,v retrieving revision 1.52 diff -u -p -r1.52 if_umb.c --- if_umb.c 26 Aug 2023 11:33:46 -0000 1.52 +++ if_umb.c 27 Aug 2023 03:32:33 -0000 @@ -23,13 +23,16 @@ * Compliance testing guide * https://www.usb.org/sites/default/files/MBIM-Compliance-1.0.pdf */ + #include "bpfilter.h" +#include "kstat.h" #include #include #include #include #include +#include #if NBPFILTER > 0 #include @@ -203,6 +206,17 @@ void umb_decode_qmi(struct umb_softc * void umb_intr(struct usbd_xfer *, void *, usbd_status); +#if NKSTAT > 0 +void umb_kstat_attach(struct umb_softc *); +void umb_kstat_detach(struct umb_softc *); + +struct umb_kstat_signal { + struct kstat_kv rssi; + struct kstat_kv error_rate; + struct kstat_kv reports; +}; +#endif + int umb_xfer_tout = USBD_DEFAULT_TIMEOUT; uint8_t umb_uuid_basic_connect[] = MBIM_UUID_BASIC_CONNECT; @@ -618,6 +632,11 @@ umb_attach(struct device *parent, struct #if NBPFILTER > 0 bpfattach(&ifp->if_bpf, ifp, DLT_LOOP, sizeof(uint32_t)); #endif + +#if NKSTAT > 0 + umb_kstat_attach(sc); +#endif + /* * Open the device now so that we are able to query device information. * XXX maybe close when done? @@ -626,6 +645,10 @@ umb_attach(struct device *parent, struct splx(s); DPRINTF("%s: vers %d.%d\n", DEVNAM(sc), sc->sc_ver_maj, sc->sc_ver_min); + +#if NKSTAT > 0 + umb_kstat_attach(sc); +#endif return; fail: @@ -645,6 +668,10 @@ umb_detach(struct device *self, int flag umb_down(sc, 1); umb_close(sc); +#if NKSTAT > 0 + umb_kstat_detach(sc); +#endif + usb_rem_wait_task(sc->sc_udev, &sc->sc_get_response_task); if (timeout_initialized(&sc->sc_statechg_timer)) timeout_del(&sc->sc_statechg_timer); @@ -1670,6 +1697,9 @@ umb_decode_signal_state(struct umb_softc struct mbim_cid_signal_state *ss = data; struct ifnet *ifp = GET_IFP(sc); int rssi; +#if NKSTAT > 0 + struct kstat *ks; +#endif if (len < sizeof (*ss)) return 0; @@ -1686,6 +1716,35 @@ umb_decode_signal_state(struct umb_softc sc->sc_info.ber = letoh32(ss->err_rate); if (sc->sc_info.ber == -99) sc->sc_info.ber = UMB_VALUE_UNKNOWN; + +#if NKSTAT > 0 + ks = sc->sc_kstat_signal; + if (ks != NULL) { + struct umb_kstat_signal *uks = ks->ks_data; + + rw_enter_write(&sc->sc_kstat_lock); + kstat_kv_u64(&uks->reports)++; + + if (sc->sc_info.rssi == UMB_VALUE_UNKNOWN) + uks->rssi.kv_type = KSTAT_KV_T_NULL; + else { + uks->rssi.kv_type = KSTAT_KV_T_INT32; + kstat_kv_s32(&uks->rssi) = sc->sc_info.rssi; + } + + if (sc->sc_info.ber == UMB_VALUE_UNKNOWN) + uks->error_rate.kv_type = KSTAT_KV_T_NULL; + else { + uks->error_rate.kv_type = KSTAT_KV_T_INT32; + kstat_kv_s32(&uks->error_rate) = sc->sc_info.ber; + } + + ks->ks_interval.tv_sec = letoh32(ss->ss_intvl); + getnanouptime(&ks->ks_updated); + rw_exit_write(&sc->sc_kstat_lock); + } +#endif + return 1; } @@ -3146,3 +3205,51 @@ umb_dump(void *buf, int len) addlog("\n"); } #endif /* UMB_DEBUG */ + +#if NKSTAT > 0 + +void +umb_kstat_attach(struct umb_softc *sc) +{ + struct kstat *ks; + struct umb_kstat_signal *uks; + + rw_init(&sc->sc_kstat_lock, "umbkstat"); + + ks = kstat_create(DEVNAM(sc), 0, "mbim-signal", 0, KSTAT_T_KV, 0); + if (ks == NULL) + return; + + uks = malloc(sizeof(*uks), M_DEVBUF, M_WAITOK|M_ZERO); + kstat_kv_init(&uks->rssi, "rssi", KSTAT_KV_T_NULL); + kstat_kv_init(&uks->error_rate, "error rate", KSTAT_KV_T_NULL); + kstat_kv_init(&uks->reports, "reports", KSTAT_KV_T_COUNTER64); + + kstat_set_rlock(ks, &sc->sc_kstat_lock); + ks->ks_data = uks; + ks->ks_datalen = sizeof(*uks); + ks->ks_read = kstat_read_nop; + + ks->ks_softc = sc; + sc->sc_kstat_signal = ks; + kstat_install(ks); +} + +void +umb_kstat_detach(struct umb_softc *sc) +{ + struct kstat *ks = sc->sc_kstat_signal; + struct umb_kstat_signal *uks; + + if (ks == NULL) + return; + + kstat_remove(ks); + sc->sc_kstat_signal = NULL; + + uks = ks->ks_data; + free(uks, M_DEVBUF, sizeof(*uks)); + + kstat_destroy(ks); +} +#endif /* NKSTAT > 0 */