@@ -190,6 +190,101 @@ cros_ec_sensor_ring_process_event(struct cros_ec_sensorhub *sensorhub,
190
190
return true;
191
191
}
192
192
193
+ /*
194
+ * cros_ec_sensor_ring_spread_add: Calculate proper timestamps then add to
195
+ * ringbuffer.
196
+ *
197
+ * If there is a sample with a proper timestamp
198
+ *
199
+ * timestamp | count
200
+ * -----------------
201
+ * older_unprocess_out --> TS1 | 1
202
+ * TS1 | 2
203
+ * out --> TS1 | 3
204
+ * next_out --> TS2 |
205
+ *
206
+ * We spread time for the samples [older_unprocess_out .. out]
207
+ * between TS1 and TS2: [TS1+1/4, TS1+2/4, TS1+3/4, TS2].
208
+ *
209
+ * If we reach the end of the samples, we compare with the
210
+ * current timestamp:
211
+ *
212
+ * older_unprocess_out --> TS1 | 1
213
+ * TS1 | 2
214
+ * out --> TS1 | 3
215
+ *
216
+ * We know have [TS1+1/3, TS1+2/3, current timestamp]
217
+ */
218
+ static void cros_ec_sensor_ring_spread_add (struct cros_ec_sensorhub * sensorhub ,
219
+ unsigned long sensor_mask ,
220
+ s64 current_timestamp ,
221
+ struct cros_ec_sensors_ring_sample
222
+ * last_out )
223
+ {
224
+ struct cros_ec_sensors_ring_sample * out ;
225
+ int i ;
226
+
227
+ for_each_set_bit (i , & sensor_mask , sensorhub -> sensor_num ) {
228
+ s64 older_timestamp ;
229
+ s64 timestamp ;
230
+ struct cros_ec_sensors_ring_sample * older_unprocess_out =
231
+ sensorhub -> ring ;
232
+ struct cros_ec_sensors_ring_sample * next_out ;
233
+ int count = 1 ;
234
+
235
+ for (out = sensorhub -> ring ; out < last_out ; out = next_out ) {
236
+ s64 time_period ;
237
+
238
+ next_out = out + 1 ;
239
+ if (out -> sensor_id != i )
240
+ continue ;
241
+
242
+ /* Timestamp to start with */
243
+ older_timestamp = out -> timestamp ;
244
+
245
+ /* Find next sample. */
246
+ while (next_out < last_out && next_out -> sensor_id != i )
247
+ next_out ++ ;
248
+
249
+ if (next_out >= last_out ) {
250
+ timestamp = current_timestamp ;
251
+ } else {
252
+ timestamp = next_out -> timestamp ;
253
+ if (timestamp == older_timestamp ) {
254
+ count ++ ;
255
+ continue ;
256
+ }
257
+ }
258
+
259
+ /*
260
+ * The next sample has a new timestamp, spread the
261
+ * unprocessed samples.
262
+ */
263
+ if (next_out < last_out )
264
+ count ++ ;
265
+ time_period = div_s64 (timestamp - older_timestamp ,
266
+ count );
267
+
268
+ for (; older_unprocess_out <= out ;
269
+ older_unprocess_out ++ ) {
270
+ if (older_unprocess_out -> sensor_id != i )
271
+ continue ;
272
+ older_timestamp += time_period ;
273
+ older_unprocess_out -> timestamp =
274
+ older_timestamp ;
275
+ }
276
+ count = 1 ;
277
+ /* The next_out sample has a valid timestamp, skip. */
278
+ next_out ++ ;
279
+ older_unprocess_out = next_out ;
280
+ }
281
+ }
282
+
283
+ /* Push the event into the kfifo */
284
+ for (out = sensorhub -> ring ; out < last_out ; out ++ )
285
+ cros_sensorhub_send_sample (sensorhub , out );
286
+ }
287
+
193
288
/**
194
289
* cros_ec_sensorhub_ring_handler() - The trigger handler function
195
290
*
@@ -204,6 +299,7 @@ static void cros_ec_sensorhub_ring_handler(struct cros_ec_sensorhub *sensorhub)
204
299
struct cros_ec_dev * ec = sensorhub -> ec ;
205
300
ktime_t fifo_timestamp , current_timestamp ;
206
301
int i , j , number_data , ret ;
302
+ unsigned long sensor_mask = 0 ;
207
303
struct ec_response_motion_sensor_data * in ;
208
304
struct cros_ec_sensors_ring_sample * out , * last_out ;
209
305
@@ -289,8 +385,10 @@ static void cros_ec_sensorhub_ring_handler(struct cros_ec_sensorhub *sensorhub)
289
385
sensorhub , fifo_info ,
290
386
fifo_timestamp ,
291
387
& current_timestamp ,
292
- in , out ))
388
+ in , out )) {
389
+ sensor_mask |= BIT (in -> sensor_num );
293
390
out ++ ;
391
+ }
294
392
}
295
393
}
296
394
mutex_unlock (& sensorhub -> cmd_lock );
@@ -301,10 +399,10 @@ static void cros_ec_sensorhub_ring_handler(struct cros_ec_sensorhub *sensorhub)
301
399
goto ring_handler_end ;
302
400
303
401
/*
304
- * Check if current_timestamp is ahead of the last sample.
305
- * Normally, the EC appends a timestamp after the last sample, but if
306
- * the AP is slow to respond to the IRQ, the EC may have added new
307
- * samples. Use the FIFO info timestamp as last timestamp then.
402
+ * Check if current_timestamp is ahead of the last sample. Normally,
403
+ * the EC appends a timestamp after the last sample, but if the AP
404
+ * is slow to respond to the IRQ, the EC may have added new samples.
405
+ * Use the FIFO info timestamp as last timestamp then.
308
406
*/
309
407
if ((last_out - 1 )-> timestamp == current_timestamp )
310
408
current_timestamp = fifo_timestamp ;
@@ -319,9 +417,12 @@ static void cros_ec_sensorhub_ring_handler(struct cros_ec_sensorhub *sensorhub)
319
417
fifo_info -> total_lost );
320
418
}
321
419
322
- /* Push the event into the FIFO. */
323
- for (out = sensorhub -> ring ; out < last_out ; out ++ )
324
- cros_sensorhub_send_sample (sensorhub , out );
420
+ /*
421
+ * Spread samples in case of batching, then add them to the
422
+ * ringbuffer.
423
+ */
424
+ cros_ec_sensor_ring_spread_add (sensorhub , sensor_mask ,
425
+ current_timestamp , last_out );
325
426
326
427
ring_handler_end :
327
428
sensorhub -> fifo_timestamp [CROS_EC_SENSOR_LAST_TS ] = current_timestamp ;
0 commit comments