blob: 8cbeddf072656b5802b22306a3da06fd5ce4ef30 [file] [log] [blame]
Shad Ansari2f7f9be2017-06-07 13:34:53 -07001/*
2<:copyright-BRCM:2016:DUAL/GPL:standard
3
4 Broadcom Proprietary and Confidential.(c) 2016 Broadcom
5 All Rights Reserved
6
7Unless you and Broadcom execute a separate written software license
8agreement governing use of this software, this software is licensed
9to you under the terms of the GNU General Public License version 2
10(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
11with the following added to such license:
12
13 As a special exception, the copyright holders of this software give
14 you permission to link this software with independent modules, and
15 to copy and distribute the resulting executable under terms of your
16 choice, provided that you also meet, for each linked independent
17 module, the terms and conditions of the license of that module.
18 An independent module is a module which is not derived from this
19 software. The special exception does not apply to any modifications
20 of the software.
21
22Not withstanding the above, under no circumstances may you combine
23this software in any way with any other Broadcom software provided
24under a license other than the GPL, without Broadcom's express prior
25written consent.
26
27:>
28*/
29
30#include <bcmos_system.h>
31#include <bcm_dev_log.h>
32#include <bcmolt_api.h>
33#include <bcmolt_model_types.h>
34#include "bcmolt_user_appl_remote_logger.h"
35
36static struct
37{
38 FILE *file_handle;
39 uint64_t file_size;
40 bcmolt_remote_logger_cfg cfg;
41 bcmos_task task;
42 bcmos_timer timer;
43 dev_log_id log_id;
44} remote_logger[BCMTR_MAX_OLTS] = {};
45
46static bcmos_timer_rc remote_logger_timer_handler(bcmos_timer *timer, long data)
47{
48 bcmolt_devid device = (bcmolt_devid)data;
49 int written;
50 bcmos_errno err;
51 bcmolt_logger_cfg cfg;
52 bcmolt_logger_key key = { .file_id = BCMOLT_LOG_FILE_ID_DDR };
53
54 BCMOLT_CFG_INIT(&cfg, logger, key);
55 BCMOLT_CFG_PROP_GET(&cfg, logger, buffer);
56 err = bcmolt_cfg_get(device, &cfg.hdr);
57 if (err != BCM_ERR_OK)
58 {
59 BCM_LOG(ERROR, remote_logger[device].log_id, "Logger get API returned '%s' (%d)\n", bcmos_strerror(err), err);
60 bcmolt_remote_logger_appl_stop(device);
61 return BCMOS_TIMER_OK;
62 }
63
64 written = fprintf(
65 remote_logger[device].file_handle,
66 "%.*s",
67 (int)sizeof(cfg.data.buffer.buff),
68 cfg.data.buffer.buff);
69 if (written < 0)
70 {
71 BCM_LOG(ERROR, remote_logger[device].log_id, "File write returned %d\n", written);
72 bcmolt_remote_logger_appl_stop(device);
73 return BCMOS_TIMER_OK;
74 }
75
76 fflush(remote_logger[device].file_handle);
77
78 /* Check to see if we will exceed the max file size next time we write a chunk. */
79 remote_logger[device].file_size += written;
80 if (remote_logger[device].file_size + sizeof(cfg.data.buffer.buff) > remote_logger[device].cfg.max_file_size)
81 {
82 switch (remote_logger[device].cfg.max_file_size_reached_behavior)
83 {
84 case BCMOLT_REMOTE_LOGGER_FILE_SIZE_REACHED_BEHAVIOR_STOP:
85 BCM_LOG(INFO, remote_logger[device].log_id, "Max file size reached - remote logger stopped\n");
86 bcmolt_remote_logger_appl_stop(device);
87 return BCMOS_TIMER_OK;
88 case BCMOLT_REMOTE_LOGGER_FILE_SIZE_REACHED_BEHAVIOR_CLEAR:
89 BCM_LOG(INFO, remote_logger[device].log_id, "Max file size reached - log file cleared\n");
90 /* the easiest way to clear the file is to close/re-open it */
91 fclose(remote_logger[device].file_handle);
92 remote_logger[device].file_handle = fopen(remote_logger[device].cfg.filename, "w");
93 BUG_ON(remote_logger[device].file_handle == NULL);
94 break;
95 default:
96 break;
97 }
98 }
99
100 if (cfg.data.buffer.msg_to_read == 0)
101 {
102 /* There are no more messages to read right now, wait for the entire polling interval. */
103 bcmos_timer_start(
104 &remote_logger[device].timer,
105 remote_logger[device].cfg.polling_period_ms * 1000); /* ms to us */
106 }
107 else
108 {
109 /* There are more messages to read - wait for only the 'subsequent delay' time. */
110 bcmos_timer_start(
111 &remote_logger[device].timer,
112 remote_logger[device].cfg.subsequent_delay_ms * 1000); /* ms to us */
113 }
114
115 return BCMOS_TIMER_OK;
116}
117
118void bcmolt_remote_logger_appl_init()
119{
120 static bcmos_task_parm task_params =
121 {
122 .priority = TASK_PRIORITY_USER_APPL_REMOTE_LOGGER,
123 .core = BCMOS_CPU_CORE_ANY, /* No CPU affinity */
124 .init_handler = NULL
125 };
126 static bcmos_module_parm module_params =
127 {
128 .qparm = { .size = 1 } /* just the timer message */
129 };
130 static bcmos_timer_parm timer_params =
131 {
132 .periodic = BCMOS_FALSE, /* we will re-enable the timer after each tick */
133 .handler = remote_logger_timer_handler
134 };
135
136 bcmos_errno err;
137 bcmolt_devid device;
138
139 for (device = 0; device < BCMTR_MAX_OLTS; device++)
140 {
141 bcmos_module_id module_id = BCMOS_MODULE_ID_USER_APPL_REMOTE_LOGGER_DEV0 + device;
142 snprintf(
143 remote_logger[device].task.name,
144 sizeof(remote_logger[device].task.name),
145 "user_appl_remote_logger%u",
146 device);
147
148 task_params.name = remote_logger[device].task.name;
149 module_params.qparm.name = remote_logger[device].task.name;
150 timer_params.owner = module_id;
151 timer_params.name = remote_logger[device].task.name;
152 timer_params.data = (long)device;
153
154 err = bcmos_task_create(&remote_logger[device].task, &task_params);
155 BUG_ON(err != BCM_ERR_OK);
156
157 err = bcmos_module_create(module_id, &remote_logger[device].task, &module_params);
158 BUG_ON(err != BCM_ERR_OK);
159
160 err = bcmos_timer_create(&remote_logger[device].timer, &timer_params);
161 BUG_ON(err != BCM_ERR_OK);
162
163 remote_logger[device].log_id =
164 bcm_dev_log_id_register(remote_logger[device].task.name, DEV_LOG_LEVEL_WARNING, DEV_LOG_ID_TYPE_BOTH);
165 }
166}
167
168bcmos_errno bcmolt_remote_logger_appl_start(bcmolt_devid device)
169{
170 bcmos_errno err;
171 bcmolt_logger_cfg cfg;
172 bcmolt_logger_key key = { .file_id = BCMOLT_LOG_FILE_ID_DDR };
173
174 if (bcmolt_remote_logger_appl_is_running(device))
175 {
176 BCM_LOG(ERROR, remote_logger[device].log_id, "Remote logger application is already running.\n");
177 return BCM_ERR_ALREADY;
178 }
179
180 /* configure DDR log file to clear on read so we can always stay up-to-date */
181 BCMOLT_CFG_INIT(&cfg, logger, key);
182 BCMOLT_CFG_PROP_SET(&cfg, logger, enable_log, BCMOS_TRUE);
183 BCMOLT_CFG_PROP_SET(&cfg, logger, clear_after_read, BCMOS_TRUE);
184 err = bcmolt_cfg_set(0, &cfg.hdr);
185 if (err != BCM_ERR_OK)
186 {
187 BCM_LOG(ERROR, remote_logger[device].log_id, "Logger set API returned '%s' (%d)\n", bcmos_strerror(err), err);
188 return err;
189 }
190
191 remote_logger[device].file_handle = fopen(remote_logger[device].cfg.filename, "w");
192 if (remote_logger[device].file_handle == NULL)
193 {
194 BCM_LOG(ERROR, remote_logger[device].log_id, "Could not open file '%s'\n", remote_logger[device].cfg.filename);
195 return BCM_ERR_IO;
196 }
197 remote_logger[device].file_size = 0;
198
199 bcmos_timer_start(&remote_logger[device].timer, remote_logger[device].cfg.polling_period_ms * 1000); /* ms to us */
200 return BCM_ERR_OK;
201}
202
203bcmos_errno bcmolt_remote_logger_appl_stop(bcmolt_devid device)
204{
205 if (!bcmolt_remote_logger_appl_is_running(device))
206 {
207 BCM_LOG(ERROR, remote_logger[device].log_id, "Remote logger application is not running.\n");
208 return BCM_ERR_ALREADY;
209 }
210
211 bcmos_timer_stop(&remote_logger[device].timer);
212 fclose(remote_logger[device].file_handle);
213 remote_logger[device].file_handle = NULL;
214 return BCM_ERR_OK;
215}
216
217bcmos_bool bcmolt_remote_logger_appl_is_running(bcmolt_devid device)
218{
219 return bcmos_timer_is_running(&remote_logger[device].timer);
220}
221
222bcmos_errno bcmolt_remote_logger_appl_cfg_get(bcmolt_devid device, bcmolt_remote_logger_cfg *cfg)
223{
224 *cfg = remote_logger[device].cfg;
225 return BCM_ERR_OK;
226}
227
228bcmos_errno bcmolt_remote_logger_appl_cfg_update(bcmolt_devid device, const bcmolt_remote_logger_cfg *cfg)
229{
230 remote_logger[device].cfg = *cfg;
231 return BCM_ERR_OK;
232}