#include "../scsc/scsc_mx_impl.h" /* TODO */
#include <scsc/scsc_mx.h>
+#ifdef CONFIG_SCSC_LOG_COLLECTION
+#include <scsc/scsc_log_collector.h>
+#endif
static bool EnableTestMode;
module_param(EnableTestMode, bool, S_IRUGO | S_IWUSR);
struct slsi_dev *sdev;
struct device *dev;
struct scsc_service_client mx_wlan_client;
+#ifdef CONFIG_SCSC_LOG_COLLECTION
+ char buf[SCSC_LOG_FAPI_VERSION_SIZE];
+#endif
SLSI_UNUSED_PARAMETER(module_client);
#ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING
hip4_sampler_create(sdev, mx);
+#endif
+#ifdef CONFIG_SCSC_LOG_COLLECTION
+ memset(buf, 0, SCSC_LOG_FAPI_VERSION_SIZE);
+ /* Write FAPI VERSION to collector header */
+ /* IMPORTANT - Do not change the formatting as User space tooling is parsing the string
+ * to read SAP fapi versions.
+ */
+ snprintf(buf, SCSC_LOG_FAPI_VERSION_SIZE, "ma:%u.%u, mlme:%u.%u, debug:%u.%u, test:%u.%u",
+ FAPI_MAJOR_VERSION(FAPI_DATA_SAP_VERSION), FAPI_MINOR_VERSION(FAPI_DATA_SAP_VERSION),
+ FAPI_MAJOR_VERSION(FAPI_CONTROL_SAP_VERSION), FAPI_MINOR_VERSION(FAPI_CONTROL_SAP_VERSION),
+ FAPI_MAJOR_VERSION(FAPI_DEBUG_SAP_VERSION), FAPI_MINOR_VERSION(FAPI_DEBUG_SAP_VERSION),
+ FAPI_MAJOR_VERSION(FAPI_TEST_SAP_VERSION), FAPI_MINOR_VERSION(FAPI_TEST_SAP_VERSION));
+
+ scsc_log_collector_write_fapi(buf, SCSC_LOG_FAPI_VERSION_SIZE);
#endif
}
#include "nl80211_vendor.h"
#include "traffic_monitor.h"
+#define FAPI_MAJOR_VERSION(v) (((v) >> 8) & 0xFF)
+#define FAPI_MINOR_VERSION(v) ((v) & 0xFF)
+
#ifdef CONFIG_SCSC_WLAN_DEBUG
/* the FAPI definition should be in fapi.h auto-generated file.
* But until a new FAPI version is generated, the definition for
#include <linux/ktime.h>
#include <linux/kthread.h>
#include <scsc/scsc_logring.h>
+#ifdef CONFIG_SCSC_LOG_COLLECTION
+#include <scsc/scsc_log_collector.h>
+#endif
#include "hip4.h"
#include "mbulk.h"
};
#endif
+#ifdef CONFIG_SCSC_LOG_COLLECTION
+static int hip4_collect(struct scsc_log_collector_client *collect_client, size_t size)
+{
+ struct slsi_hip4 *hip = (struct slsi_hip4 *)collect_client->prv;
+ struct hip4_priv *hip_priv;
+ int ret = 0;
+
+ if (!hip)
+ return 0;
+
+ hip_priv = hip->hip_priv;
+ if (!hip_priv)
+ return 0;
+
+ if (!hip_priv->mib_collect || !hip_priv->mib_sz)
+ return 0;
+
+ SLSI_INFO_NODEV("Hip4 collecting HCF\n");
+ mutex_lock(&hip_priv->in_collection);
+ ret = scsc_log_collector_write(hip_priv->mib_collect, hip_priv->mib_sz, 1);
+ mutex_unlock(&hip_priv->in_collection);
+ return ret;
+}
+
+/* Collect client registration for HCF file*/
+struct scsc_log_collector_client hip4_collect_hcf_client = {
+ .name = "wlan_hcf",
+ .type = SCSC_LOG_CHUNK_WLAN_HCF,
+ .collect_init = NULL,
+ .collect = hip4_collect,
+ .collect_end = NULL,
+ .prv = NULL,
+};
+#endif
+
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
static inline ktime_t ktime_add_ms(const ktime_t kt, const u64 msec)
{
#endif
mem = scsc_mx_service_mif_addr_to_ptr(service, ref);
m = (struct mbulk *)mem;
-
if (!m) {
- SLSI_ERR_NODEV("FB: Mbulk is NULL\n");
+ SLSI_ERR_NODEV("FB: Mbulk is NULL 0x%x\n", ref);
goto consume_fb_mbulk;
}
/* colour is defined as: */
#endif
mem = scsc_mx_service_mif_addr_to_ptr(service, ref);
m = (struct mbulk *)(mem);
+ if (!m) {
+ SLSI_ERR_NODEV("Ctrl: Mbulk is NULL 0x%x\n", ref);
+ goto consume_ctl_mbulk;
+ }
/* Process Control Signal */
skb = hip4_mbulk_to_skb(service, m, to_free, false);
#endif
mem = scsc_mx_service_mif_addr_to_ptr(service, ref);
m = (struct mbulk *)(mem);
+ if (!m) {
+ SLSI_ERR_NODEV("Dat: Mbulk is NULL 0x%x\n", ref);
+ goto consume_dat_mbulk;
+ }
+
skb = hip4_mbulk_to_skb(service, m, to_free, false);
if (!skb) {
SLSI_ERR_NODEV("Dat: Error parsing skb\n");
hip_control->config_v4.mib_sz = 0;
hip_control->config_v3.mib_loc = 0;
hip_control->config_v3.mib_sz = 0;
+ total_mib_len = 0;
} else if (total_mib_len) {
SLSI_INFO_NODEV("Loading MIB into shared memory, size (%d)\n", total_mib_len);
/* Load each MIB file into shared DRAM region */
SLSI_WARN(sdev, "failed to add PM QoS request\n");
}
}
+
+#ifdef CONFIG_SCSC_LOG_COLLECTION
+ /* Register with log collector to collect wlan hcf file */
+ /* Make a copy for collection */
+ mutex_init(&hip->hip_priv->in_collection);
+ if (total_mib_len) {
+ hip->hip_priv->mib_collect = vmalloc(total_mib_len);
+ if (hip->hip_priv->mib_collect) {
+ memcpy(hip->hip_priv->mib_collect, (u8 *)hip_ptr + HIP4_WLAN_MIB_OFFSET, total_mib_len);
+ hip->hip_priv->mib_sz = total_mib_len;
+ hip4_collect_hcf_client.prv = hip;
+ scsc_log_collector_register_client(&hip4_collect_hcf_client);
+ } else {
+ SLSI_WARN(sdev, "failed to allocate memory for hcf file backup\n");
+ }
+ }
+#endif
return 0;
}
service = sdev->service;
+#ifdef CONFIG_SCSC_LOG_COLLECTION
+ mutex_lock(&hip->hip_priv->in_collection);
+ hip4_collect_hcf_client.prv = NULL;
+ scsc_log_collector_unregister_client(&hip4_collect_hcf_client);
+ if (hip->hip_priv->mib_collect) {
+ hip->hip_priv->mib_sz = 0;
+ vfree(hip->hip_priv->mib_collect);
+ }
+ mutex_unlock(&hip->hip_priv->in_collection);
+#endif
+
/* de-register with traffic monitor */
slsi_traffic_mon_client_unregister(sdev, hip);
scsc_service_pm_qos_remove_request(service);
/* PM QoS control */
struct work_struct pm_qos_work;
/* PM QoS control spinlock */
- spinlock_t pm_qos_lock;
+ spinlock_t pm_qos_lock;
u8 pm_qos_state;
+
+ /* Collection artificats */
+ void *mib_collect;
+ u16 mib_sz;
+ /* Mutex to protect hcf file collection if a tear down is triggered */
+ struct mutex in_collection;
};
struct scsc_service;
#include <linux/cdev.h>
#include <linux/device.h>
#include <scsc/scsc_mx.h>
+#ifdef CONFIG_SCSC_LOG_COLLECTION
+#include <scsc/scsc_log_collector.h>
+#endif
#include <linux/delay.h>
#include <linux/mutex.h>
#include "hip4_sampler.h"
static atomic_t in_read;
-static bool hip4_sampler_enable;
+static bool hip4_sampler_enable = true;
module_param(hip4_sampler_enable, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(hip4_sampler_enable, "Enable hip4_sampler_enable. Run-time option - (default: N)");
+MODULE_PARM_DESC(hip4_sampler_enable, "Enable hip4_sampler_enable. Run-time option - (default: Y)");
static bool hip4_sampler_dynamic = true;
module_param(hip4_sampler_dynamic, bool, S_IRUGO | S_IWUSR);
}
}
+#ifdef CONFIG_SCSC_LOG_COLLECTION
+int hip4_collect_init(struct scsc_log_collector_client *collect_client)
+{
+ /* Stop Sampling */
+ atomic_set(&in_read, 1);
+ return 0;
+}
+
+int hip4_collect(struct scsc_log_collector_client *collect_client, size_t size)
+{
+ int i = SCSC_HIP4_DEBUG_INTERFACES;
+ int ret = 0;
+ unsigned long flags;
+ u32 num_samples;
+ struct hip4_sampler_dev *hip4_dev;
+ void *buf;
+
+ SLSI_INFO_NODEV("Triggered log collection in hip4_sampler\n");
+
+ if (!hip4_sampler_enable)
+ return 0;
+
+ while (i--)
+ if (hip4_sampler.devs[i].mx == collect_client->prv && hip4_sampler.devs[i].type == OFFLINE) {
+ hip4_dev = &hip4_sampler.devs[i];
+ num_samples = kfifo_len(&hip4_dev->fifo);
+ if (!num_samples)
+ continue;
+ buf = vmalloc(num_samples * sizeof(struct hip4_record));
+ if (!buf)
+ continue;
+ spin_lock_irqsave(&hip4_dev->spinlock, flags);
+ ret = kfifo_out(&hip4_dev->fifo, buf, num_samples);
+ spin_unlock_irqrestore(&hip4_dev->spinlock, flags);
+ if (!ret)
+ goto error;
+ SLSI_DBG1_NODEV(SLSI_HIP, "num_samples %d ret %d size of hip4_record %zu\n", num_samples, ret, sizeof(struct hip4_record));
+ ret = scsc_log_collector_write(buf, ret * sizeof(struct hip4_record), 1);
+ if (ret)
+ goto error;
+ vfree(buf);
+ }
+ return 0;
+error:
+ vfree(buf);
+ return ret;
+}
+
+int hip4_collect_end(struct scsc_log_collector_client *collect_client)
+{
+ /* Restart sampling */
+ atomic_set(&in_read, 0);
+ return 0;
+}
+
+/* Collect client registration */
+struct scsc_log_collector_client hip4_collect_client = {
+ .name = "HIP4 Sampler",
+ .type = SCSC_LOG_CHUNK_HIP4_SAMPLER,
+ .collect_init = hip4_collect_init,
+ .collect = hip4_collect,
+ .collect_end = hip4_collect_end,
+ .prv = NULL,
+};
+#endif
+
static int hip4_sampler_open(struct inode *inode, struct file *filp)
{
struct hip4_sampler_dev *hip4_dev;
SLSI_INFO_NODEV("hip4_sampler version: %d.%d\n", VER_MAJOR, VER_MINOR);
+ memset(&hip4_sampler, 0, sizeof(hip4_sampler));
/* Check whether exists */
if (!hip4_sampler.init) {
ret = alloc_chrdev_region(&hip4_sampler.device, 0, SCSC_HIP4_DEBUG_INTERFACES, "hip4_sampler_char");
set_bit(minor, bitmap_hip4_sampler_minor);
}
+#ifdef CONFIG_SCSC_LOG_COLLECTION
+ hip4_collect_client.prv = mx;
+ scsc_log_collector_register_client(&hip4_collect_client);
+#endif
hip4_sampler.init = true;
SLSI_INFO_NODEV("%s: Ready to start sampling....\n", DRV_NAME);
hip4_sampler.devs[i].mx = NULL;
clear_bit(i, bitmap_hip4_sampler_minor);
}
+#ifdef CONFIG_SCSC_LOG_COLLECTION
+ scsc_log_collector_unregister_client(&hip4_collect_client);
+#endif
class_destroy(hip4_sampler.class_hip4_sampler);
unregister_chrdev_region(hip4_sampler.device, SCSC_HIP4_DEBUG_INTERFACES);
hip4_sampler.init = false;
#include "mib.h"
-#define FAPI_MAJOR_VERSION(v) ((v >> 8) & 0xFF)
-#define FAPI_MINOR_VERSION(v) ((v) & 0xFF)
-
int slsi_procfs_open_file_generic(struct inode *inode, struct file *file)
{
file->private_data = SLSI_PDE_DATA(inode);
file->private_data = client;
slsi_procfs_inc_node();
+#ifdef CONFIG_SCSC_MXLOGGER
+ scsc_service_register_observer(NULL, "udi");
+#endif
+
SLSI_DBG1_NODEV(SLSI_UDI, "Client:%d added\n", indx);
return 0;
kfree(client);
slsi_procfs_dec_node();
+#ifdef CONFIG_SCSC_MXLOGGER
+ scsc_service_unregister_observer(NULL, "udi");
+#endif
+
SLSI_DBG1_NODEV(SLSI_UDI, "Client:%d removed\n", indx);
return 0;
/* wait until getting a signal */
if (wait_event_interruptible(client->log_wq, skb_queue_len(&client->log_list))) {
- SLSI_ERR_NODEV("slsi_cdev_read: wait_event_interruptible failed.");
+ SLSI_ERR_NODEV("slsi_cdev_read: wait_event_interruptible failed.\n");
return -ERESTARTSYS;
}
}