From cde9070d9970eef1f7ec2360586c802a16230ad8 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Fri, 10 May 2024 07:43:50 +0000 Subject: [PATCH] rtl88x2CE_WiFi_linux driver --- kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/dhd_debug_linux.c | 198 ++++++++++++++++++++++++++++++++++++------------- 1 files changed, 145 insertions(+), 53 deletions(-) diff --git a/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/dhd_debug_linux.c b/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/dhd_debug_linux.c index 3940f70..1d4438e 100644 --- a/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/dhd_debug_linux.c +++ b/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/dhd_debug_linux.c @@ -1,15 +1,18 @@ -/* SPDX-License-Identifier: GPL-2.0 */ /* * DHD debugability Linux os layer * - * Copyright (C) 1999-2019, Broadcom Corporation - * + * <<Broadcom-WL-IPTag/Open:>> + * + * Portions of this code are copyright (c) 2022 Cypress Semiconductor Corporation + * + * Copyright (C) 1999-2017, Broadcom Corporation + * * Unless you and Broadcom execute a separate written software license * agreement governing use of this software, this software is licensed to you * under the terms of the GNU General Public License version 2 (the "GPL"), * available at http://www.broadcom.com/licenses/GPLv2.php, with the * following added to such license: - * + * * As a special exception, the copyright holders of this software give you * permission to link this software with independent modules, and to copy and * distribute the resulting executable under terms of your choice, provided that @@ -17,21 +20,18 @@ * the license of that module. An independent module is a module which is not * derived from this software. The special exception does not apply to any * modifications of the software. - * + * * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_debug_linux.c 554441 2015-05-05 18:45:58Z $ + * $Id: dhd_debug_linux.c 696754 2017-04-28 00:21:58Z $ */ #include <typedefs.h> #include <osl.h> #include <bcmutils.h> #include <bcmendian.h> -#ifndef CUSTOMER_IPCAM -#include <bcmpcie.h> -#endif #include <dngl_stats.h> #include <dhd.h> #include <dhd_dbg.h> @@ -61,7 +61,13 @@ {1, WIFI_EVENT_DRIVER_EAPOL_FRAME_RECEIVED, "DRIVER EAPOL RX"}, {2, WIFI_EVENT_DRIVER_SCAN_REQUESTED, "SCAN_REQUESTED"}, {2, WIFI_EVENT_DRIVER_SCAN_COMPLETE, "SCAN COMPELETE"}, - {3, WIFI_EVENT_DRIVER_SCAN_RESULT_FOUND, "SCAN RESULT FOUND"} + {3, WIFI_EVENT_DRIVER_SCAN_RESULT_FOUND, "SCAN RESULT FOUND"}, + {2, WIFI_EVENT_DRIVER_PNO_ADD, "PNO ADD"}, + {2, WIFI_EVENT_DRIVER_PNO_REMOVE, "PNO REMOVE"}, + {2, WIFI_EVENT_DRIVER_PNO_NETWORK_FOUND, "PNO NETWORK FOUND"}, + {2, WIFI_EVENT_DRIVER_PNO_SCAN_REQUESTED, "PNO SCAN_REQUESTED"}, + {1, WIFI_EVENT_DRIVER_PNO_SCAN_RESULT_FOUND, "PNO SCAN RESULT FOUND"}, + {1, WIFI_EVENT_DRIVER_PNO_SCAN_COMPLETE, "PNO SCAN COMPELETE"} }; static void @@ -72,6 +78,8 @@ dbg_ring_send_sub_t ring_sub_send; ndev = dhd_linux_get_primary_netdev(dhdp); if (!ndev) + return; + if (!VALID_RING(ring_id)) return; if (ring_send_sub_cb[ring_id]) { ring_sub_send = ring_send_sub_cb[ring_id]; @@ -95,53 +103,76 @@ dbg_ring_poll_worker(struct work_struct *work) { struct delayed_work *d_work = to_delayed_work(work); + bool sched = TRUE; + dhd_dbg_ring_t *ring; +#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-qual" +#endif // endif linux_dbgring_info_t *ring_info = container_of(d_work, linux_dbgring_info_t, work); +#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) +#pragma GCC diagnostic pop +#endif // endif dhd_pub_t *dhdp = ring_info->dhdp; int ringid = ring_info->ring_id; dhd_dbg_ring_status_t ring_status; void *buf; dhd_dbg_ring_entry_t *hdr; uint32 buflen, rlen; + unsigned long flags; + ring = &dhdp->dbg->dbg_rings[ringid]; + DHD_DBG_RING_LOCK(ring->lock, flags); dhd_dbg_get_ring_status(dhdp, ringid, &ring_status); - if (ring_status.written_bytes > ring_status.read_bytes) - buflen = ring_status.written_bytes - ring_status.read_bytes; - else if (ring_status.written_bytes < ring_status.read_bytes) - buflen = 0xFFFFFFFF + ring_status.written_bytes - - ring_status.read_bytes; - else + + if (ring->wp > ring->rp) { + buflen = ring->wp - ring->rp; + } else if (ring->wp < ring->rp) { + buflen = ring->ring_size - ring->rp + ring->wp; + } else { goto exit; - buf = MALLOC(dhdp->osh, buflen); + } + + if (buflen > ring->ring_size) { + goto exit; + } + + buf = MALLOCZ(dhdp->osh, buflen); if (!buf) { DHD_ERROR(("%s failed to allocate read buf\n", __FUNCTION__)); - return; + sched = FALSE; + goto exit; } - rlen = dhd_dbg_ring_pull(dhdp, ringid, buf, buflen); + + rlen = dhd_dbg_pull_from_ring(dhdp, ringid, buf, buflen); + + if (!ring->sched_pull) { + ring->sched_pull = TRUE; + } + hdr = (dhd_dbg_ring_entry_t *)buf; while (rlen > 0) { ring_status.read_bytes += ENTRY_LENGTH(hdr); /* offset fw ts to host ts */ hdr->timestamp += ring_info->tsoffset; debug_data_send(dhdp, ringid, hdr, ENTRY_LENGTH(hdr), - ring_status); + ring_status); rlen -= ENTRY_LENGTH(hdr); - hdr = (dhd_dbg_ring_entry_t *)((void *)hdr + ENTRY_LENGTH(hdr)); + hdr = (dhd_dbg_ring_entry_t *)((char *)hdr + ENTRY_LENGTH(hdr)); } MFREE(dhdp->osh, buf, buflen); - if (!ring_info->interval) - return; - dhd_dbg_get_ring_status(dhdp, ring_info->ring_id, &ring_status); - exit: - if (ring_info->interval) { + if (sched) { /* retrigger the work at same interval */ - if (ring_status.written_bytes == ring_status.read_bytes) + if ((ring_status.written_bytes == ring_status.read_bytes) && + (ring_info->interval)) { schedule_delayed_work(d_work, ring_info->interval); - else - schedule_delayed_work(d_work, 0); + } } + + DHD_DBG_RING_UNLOCK(ring->lock, flags); return; } @@ -173,7 +204,6 @@ int ret = BCME_OK; int ring_id; linux_dbgring_info_t *os_priv, *ring_info; - uint32 ms; ring_id = dhd_dbg_find_ring_id(dhdp, ring_name); if (!VALID_RING(ring_id)) @@ -194,19 +224,13 @@ return BCME_ERROR; ring_info = &os_priv[ring_id]; ring_info->log_level = log_level; - if (ring_id == FW_VERBOSE_RING_ID || ring_id == FW_EVENT_RING_ID) { - ring_info->tsoffset = local_clock(); - if (dhd_wl_ioctl_get_intiovar(dhdp, "rte_timesync", &ms, WLC_GET_VAR, - FALSE, 0)) - DHD_ERROR(("%s rte_timesync failed\n", __FUNCTION__)); - do_div(ring_info->tsoffset, 1000000); - ring_info->tsoffset -= ms; - } + if (time_intval == 0 || log_level == 0) { ring_info->interval = 0; cancel_delayed_work_sync(&ring_info->work); } else { ring_info->interval = msecs_to_jiffies(time_intval * MSEC_PER_SEC); + cancel_delayed_work_sync(&ring_info->work); schedule_delayed_work(&ring_info->work, ring_info->interval); } @@ -257,12 +281,12 @@ if (!os_priv) return BCME_ERROR; - max_log_level = MAX(os_priv[FW_VERBOSE_RING_ID].log_level, - os_priv[FW_EVENT_RING_ID].log_level); + max_log_level = os_priv[FW_VERBOSE_RING_ID].log_level; + if (max_log_level == SUPPRESS_LOG_LEVEL) { /* suppress the logging in FW not to wake up host while device in suspend mode */ ret = dhd_iovar(dhdp, 0, "logtrace", (char *)&enable, sizeof(enable), NULL, 0, - TRUE); + TRUE); if (ret < 0 && (ret != BCME_UNSUPPORTED)) { DHD_ERROR(("logtrace is failed : %d\n", ret)); } @@ -305,17 +329,17 @@ { int ret = BCME_OK, i; dhd_dbg_ring_entry_t msg_hdr; - log_conn_event_t event_data; + log_conn_event_t *event_data = (log_conn_event_t *)data; linux_dbgring_info_t *os_priv, *ring_info = NULL; if (!VALID_RING(ring_id)) return BCME_UNSUPPORTED; - os_priv = dhd_dbg_get_priv(dhdp); - if (!os_priv) - return BCME_UNSUPPORTED; - ring_info = &os_priv[ring_id]; + if (os_priv) { + ring_info = &os_priv[ring_id]; + } else + return BCME_NORESOURCE; memset(&msg_hdr, 0, sizeof(dhd_dbg_ring_entry_t)); @@ -325,18 +349,17 @@ msg_hdr.flags |= DBG_RING_ENTRY_FLAGS_HAS_BINARY; msg_hdr.timestamp = local_clock(); /* convert to ms */ - do_div(msg_hdr.timestamp, 1000000); - msg_hdr.len = sizeof(event_data); - event_data.event = *((uint16 *)(data)); + msg_hdr.timestamp = DIV_U64_BY_U32(msg_hdr.timestamp, NSEC_PER_MSEC); + msg_hdr.len = data_len; /* filter the event for higher log level with current log level */ for (i = 0; i < ARRAYSIZE(dhd_event_map); i++) { - if ((dhd_event_map[i].tag == event_data.event) && + if ((dhd_event_map[i].tag == event_data->event) && dhd_event_map[i].log_level > ring_info->log_level) { return ret; } } } - ret = dhd_dbg_ring_push(dhdp, ring_id, &msg_hdr, &event_data); + ret = dhd_dbg_push_to_ring(dhdp, ring_id, &msg_hdr, event_data); if (ret) { DHD_ERROR(("%s : failed to push data into the ring (%d) with ret(%d)\n", __FUNCTION__, ring_id, ret)); @@ -345,11 +368,72 @@ return ret; } +#ifdef DBG_PKT_MON +int +dhd_os_dbg_attach_pkt_monitor(dhd_pub_t *dhdp) +{ + return dhd_dbg_attach_pkt_monitor(dhdp, dhd_os_dbg_monitor_tx_pkts, + dhd_os_dbg_monitor_tx_status, dhd_os_dbg_monitor_rx_pkts); +} + +int +dhd_os_dbg_start_pkt_monitor(dhd_pub_t *dhdp) +{ + return dhd_dbg_start_pkt_monitor(dhdp); +} + +int +dhd_os_dbg_monitor_tx_pkts(dhd_pub_t *dhdp, void *pkt, uint32 pktid) +{ + return dhd_dbg_monitor_tx_pkts(dhdp, pkt, pktid); +} + +int +dhd_os_dbg_monitor_tx_status(dhd_pub_t *dhdp, void *pkt, uint32 pktid, + uint16 status) +{ + return dhd_dbg_monitor_tx_status(dhdp, pkt, pktid, status); +} + +int +dhd_os_dbg_monitor_rx_pkts(dhd_pub_t *dhdp, void *pkt) +{ + return dhd_dbg_monitor_rx_pkts(dhdp, pkt); +} + +int +dhd_os_dbg_stop_pkt_monitor(dhd_pub_t *dhdp) +{ + return dhd_dbg_stop_pkt_monitor(dhdp); +} + +int +dhd_os_dbg_monitor_get_tx_pkts(dhd_pub_t *dhdp, void __user *user_buf, + uint16 req_count, uint16 *resp_count) +{ + return dhd_dbg_monitor_get_tx_pkts(dhdp, user_buf, req_count, resp_count); +} + +int +dhd_os_dbg_monitor_get_rx_pkts(dhd_pub_t *dhdp, void __user *user_buf, + uint16 req_count, uint16 *resp_count) +{ + return dhd_dbg_monitor_get_rx_pkts(dhdp, user_buf, req_count, resp_count); +} + +int +dhd_os_dbg_detach_pkt_monitor(dhd_pub_t *dhdp) +{ + return dhd_dbg_detach_pkt_monitor(dhdp); +} +#endif /* DBG_PKT_MON */ + int dhd_os_dbg_get_feature(dhd_pub_t *dhdp, int32 *features) { int ret = BCME_OK; *features = 0; +#ifdef DEBUGABILITY *features |= DBG_MEMORY_DUMP_SUPPORTED; if (FW_SUPPORTED(dhdp, logtrace)) { *features |= DBG_CONNECT_EVENT_SUPPORTED; @@ -358,6 +442,12 @@ if (FW_SUPPORTED(dhdp, hchk)) { *features |= DBG_HEALTH_CHECK_SUPPORTED; } +#ifdef DBG_PKT_MON + if (FW_SUPPORTED(dhdp, d11status)) { + *features |= DBG_PACKET_FATE_SUPPORTED; + } +#endif /* DBG_PKT_MON */ +#endif /* DEBUGABILITY */ return ret; } @@ -367,8 +457,8 @@ linux_dbgring_info_t *ring_info; ring_info = &((linux_dbgring_info_t *)os_priv)[ring_id]; - if (ring_info->interval != 0) - schedule_delayed_work(&ring_info->work, 0); + cancel_delayed_work(&ring_info->work); + schedule_delayed_work(&ring_info->work, 0); } int @@ -405,6 +495,8 @@ int ring_id; /* free os_dbg data */ os_priv = dhd_dbg_get_priv(dhdp); + if (!os_priv) + return; /* abort pending any job */ for (ring_id = DEBUG_RING_ID_INVALID + 1; ring_id < DEBUG_RING_ID_MAX; ring_id++) { ring_info = &os_priv[ring_id]; -- Gitblit v1.6.2