mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-07 12:25:00 -04:00
Merge "wigig_sensing: handle SYS_ASSERT corner cases"
This commit is contained in:
commit
ed0190d5df
3 changed files with 197 additions and 133 deletions
|
|
@ -2,7 +2,6 @@
|
|||
/*
|
||||
* Copyright (c) 2019, The Linux foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/circ_buf.h>
|
||||
#include <linux/clk.h>
|
||||
|
|
@ -15,6 +14,7 @@
|
|||
#include <linux/io.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kfifo.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
|
|
@ -433,7 +433,8 @@ static int wigig_sensing_change_state(struct wigig_sensing_ctx *ctx,
|
|||
enum wigig_sensing_stm_e new_state)
|
||||
{
|
||||
enum wigig_sensing_stm_e curr_state;
|
||||
bool transition_allowed = false;
|
||||
bool transition_allowed = true;
|
||||
int rc = 0;
|
||||
|
||||
if (!state) {
|
||||
pr_err("state is NULL\n");
|
||||
|
|
@ -441,86 +442,60 @@ static int wigig_sensing_change_state(struct wigig_sensing_ctx *ctx,
|
|||
}
|
||||
if (new_state <= WIGIG_SENSING_STATE_MIN ||
|
||||
new_state >= WIGIG_SENSING_STATE_MAX) {
|
||||
pr_err("new_state is invalid\n");
|
||||
pr_err("new_state (%d) is invalid\n", new_state);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
curr_state = state->state;
|
||||
if (new_state == curr_state) {
|
||||
pr_debug("Already in the requested state, bailing out\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((new_state == WIGIG_SENSING_STATE_SYS_ASSERT &&
|
||||
!state->fw_is_ready) ||
|
||||
(new_state == WIGIG_SENSING_STATE_SPI_READY)) {
|
||||
transition_allowed = true;
|
||||
} else {
|
||||
switch (curr_state) {
|
||||
case WIGIG_SENSING_STATE_INITIALIZED:
|
||||
if (new_state == WIGIG_SENSING_STATE_SPI_READY &&
|
||||
state->fw_is_ready)
|
||||
transition_allowed = true;
|
||||
break;
|
||||
case WIGIG_SENSING_STATE_SPI_READY:
|
||||
if (new_state == WIGIG_SENSING_STATE_READY_STOPPED &&
|
||||
state->enabled)
|
||||
transition_allowed = true;
|
||||
break;
|
||||
case WIGIG_SENSING_STATE_READY_STOPPED:
|
||||
if (new_state == WIGIG_SENSING_STATE_SEARCH ||
|
||||
new_state == WIGIG_SENSING_STATE_FACIAL ||
|
||||
new_state == WIGIG_SENSING_STATE_GESTURE ||
|
||||
new_state == WIGIG_SENSING_STATE_CUSTOM ||
|
||||
new_state == WIGIG_SENSING_STATE_GET_PARAMS)
|
||||
transition_allowed = true;
|
||||
break;
|
||||
case WIGIG_SENSING_STATE_SEARCH:
|
||||
if (new_state == WIGIG_SENSING_STATE_READY_STOPPED ||
|
||||
new_state == WIGIG_SENSING_STATE_SEARCH ||
|
||||
new_state == WIGIG_SENSING_STATE_FACIAL ||
|
||||
new_state == WIGIG_SENSING_STATE_GESTURE)
|
||||
transition_allowed = true;
|
||||
break;
|
||||
case WIGIG_SENSING_STATE_FACIAL:
|
||||
if (new_state == WIGIG_SENSING_STATE_READY_STOPPED ||
|
||||
new_state == WIGIG_SENSING_STATE_SEARCH)
|
||||
transition_allowed = true;
|
||||
break;
|
||||
case WIGIG_SENSING_STATE_GESTURE:
|
||||
if (new_state == WIGIG_SENSING_STATE_READY_STOPPED ||
|
||||
new_state == WIGIG_SENSING_STATE_SEARCH)
|
||||
transition_allowed = true;
|
||||
break;
|
||||
case WIGIG_SENSING_STATE_CUSTOM:
|
||||
if (new_state == WIGIG_SENSING_STATE_READY_STOPPED)
|
||||
transition_allowed = true;
|
||||
break;
|
||||
case WIGIG_SENSING_STATE_GET_PARAMS:
|
||||
if (new_state == WIGIG_SENSING_STATE_READY_STOPPED)
|
||||
transition_allowed = true;
|
||||
break;
|
||||
case WIGIG_SENSING_STATE_SYS_ASSERT:
|
||||
if (new_state == WIGIG_SENSING_STATE_READY_STOPPED &&
|
||||
state->fw_is_ready)
|
||||
transition_allowed = true;
|
||||
break;
|
||||
default:
|
||||
pr_err("new_state is invalid\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Moving to SYS_ASSEERT state is always allowed */
|
||||
if (new_state == WIGIG_SENSING_STATE_SYS_ASSERT)
|
||||
goto skip;
|
||||
|
||||
/*
|
||||
* Moving from INITIALIZED state is allowed only to READY_STOPPED state
|
||||
*/
|
||||
else if (curr_state == WIGIG_SENSING_STATE_INITIALIZED &&
|
||||
new_state != WIGIG_SENSING_STATE_READY_STOPPED) {
|
||||
transition_allowed = false;
|
||||
rc = -EFAULT;
|
||||
}
|
||||
/*
|
||||
* Moving to GET_PARAMS state is allowed only from READY_STOPPED state
|
||||
*/
|
||||
else if (curr_state != WIGIG_SENSING_STATE_READY_STOPPED &&
|
||||
new_state == WIGIG_SENSING_STATE_GET_PARAMS) {
|
||||
transition_allowed = false;
|
||||
rc = -EFAULT;
|
||||
}
|
||||
/*
|
||||
* Moving from GET_PARAMS state is allowed only to READY_STOPPED state
|
||||
*/
|
||||
else if (curr_state == WIGIG_SENSING_STATE_GET_PARAMS &&
|
||||
new_state != WIGIG_SENSING_STATE_READY_STOPPED) {
|
||||
transition_allowed = false;
|
||||
rc = -EFAULT;
|
||||
}
|
||||
/*
|
||||
* Moving from SYS_ASSERT state is allowed only to READY_STOPPED state
|
||||
*/
|
||||
else if (curr_state == WIGIG_SENSING_STATE_SYS_ASSERT &&
|
||||
new_state != WIGIG_SENSING_STATE_READY_STOPPED) {
|
||||
transition_allowed = false;
|
||||
rc = -ENODEV;
|
||||
}
|
||||
|
||||
skip:
|
||||
if (transition_allowed) {
|
||||
pr_info("state transition (%d) --> (%d)\n", curr_state,
|
||||
new_state);
|
||||
state->state = new_state;
|
||||
} else {
|
||||
pr_info("state transition rejected (%d) xx> (%d)\n",
|
||||
curr_state, new_state);
|
||||
pr_err("state transition rejected (%d) xx> (%d)\n",
|
||||
curr_state, new_state);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int wigig_sensing_ioc_set_auto_recovery(struct wigig_sensing_ctx *ctx)
|
||||
|
|
@ -542,27 +517,31 @@ static int wigig_sensing_ioc_change_mode(struct wigig_sensing_ctx *ctx,
|
|||
struct wigig_sensing_change_mode req)
|
||||
{
|
||||
struct wigig_sensing_stm sim_state;
|
||||
enum wigig_sensing_stm_e new_state;
|
||||
int rc;
|
||||
u32 ch;
|
||||
|
||||
pr_info("mode = %d, channel = %d\n", req.mode, req.channel);
|
||||
pr_info("mode = %d, channel = %d, has_channel = %d\n",
|
||||
req.mode, req.channel, req.has_channel);
|
||||
if (!ctx)
|
||||
return -EINVAL;
|
||||
|
||||
/* Save the request for later use */
|
||||
ctx->stm.mode_request = req.mode;
|
||||
|
||||
/* Simulate a state change */
|
||||
new_state = convert_mode_to_state(req.mode);
|
||||
ctx->stm.state_request = convert_mode_to_state(req.mode);
|
||||
sim_state = ctx->stm;
|
||||
rc = wigig_sensing_change_state(ctx, &sim_state, new_state);
|
||||
if (rc || sim_state.state != new_state) {
|
||||
rc = wigig_sensing_change_state(ctx, &sim_state,
|
||||
ctx->stm.state_request);
|
||||
if (rc) {
|
||||
pr_err("State change not allowed\n");
|
||||
rc = -EFAULT;
|
||||
goto End;
|
||||
}
|
||||
|
||||
/* Send command to FW */
|
||||
ctx->stm.change_mode_in_progress = true;
|
||||
ch = req.has_channel ? req.channel : 0;
|
||||
ctx->stm.channel_request = ch;
|
||||
ctx->stm.burst_size_ready = false;
|
||||
/* Change mode command must not be called during DRI processing */
|
||||
mutex_lock(&ctx->dri_lock);
|
||||
|
|
@ -583,29 +562,28 @@ static int wigig_sensing_ioc_change_mode(struct wigig_sensing_ctx *ctx,
|
|||
/* Interrupted by a signal */
|
||||
pr_err("wait_event_interruptible_timeout() interrupted by a signal (%d)\n",
|
||||
rc);
|
||||
return rc;
|
||||
goto End;
|
||||
}
|
||||
if (rc == 0) {
|
||||
/* Timeout, FW did not respond in time */
|
||||
pr_err("wait_event_interruptible_timeout() timed out\n");
|
||||
return -ETIME;
|
||||
}
|
||||
|
||||
/* Change internal state */
|
||||
rc = wigig_sensing_change_state(ctx, &ctx->stm, new_state);
|
||||
if (rc || ctx->stm.state != new_state) {
|
||||
pr_err("wigig_sensing_change_state() failed\n");
|
||||
rc = -EFAULT;
|
||||
rc = -ETIME;
|
||||
goto End;
|
||||
}
|
||||
|
||||
ctx->dropped_bursts = 0;
|
||||
ctx->stm.channel_request = ch;
|
||||
ctx->stm.mode = req.mode;
|
||||
ctx->stm.change_mode_in_progress = false;
|
||||
if (ctx->stm.state != ctx->stm.state_request) {
|
||||
pr_err("%s() failed\n", __func__);
|
||||
if (ctx->stm.state == WIGIG_SENSING_STATE_SYS_ASSERT)
|
||||
rc = -ENODEV;
|
||||
else
|
||||
rc = -EFAULT;
|
||||
}
|
||||
|
||||
End:
|
||||
return ctx->stm.burst_size;
|
||||
ctx->stm.state_request = WIGIG_SENSING_STATE_MIN;
|
||||
ctx->stm.channel_request = 0;
|
||||
ctx->stm.mode_request = WIGIG_SENSING_MODE_STOP;
|
||||
return (rc == 0) ? ctx->stm.burst_size : rc;
|
||||
}
|
||||
|
||||
static int wigig_sensing_ioc_clear_data(struct wigig_sensing_ctx *ctx)
|
||||
|
|
@ -629,9 +607,29 @@ static int wigig_sensing_ioc_get_num_dropped_bursts(
|
|||
return ctx->dropped_bursts;
|
||||
}
|
||||
|
||||
static int wigig_sensing_ioc_get_event(struct wigig_sensing_ctx *ctx)
|
||||
static int wigig_sensing_ioc_get_num_avail_bursts(
|
||||
struct wigig_sensing_ctx *ctx)
|
||||
{
|
||||
return 0;
|
||||
if (ctx->stm.burst_size)
|
||||
return circ_cnt(&ctx->cir_data.b, ctx->cir_data.size_bytes) /
|
||||
ctx->stm.burst_size;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wigig_sensing_ioc_get_event(struct wigig_sensing_ctx *ctx,
|
||||
enum wigig_sensing_event *event)
|
||||
{
|
||||
u32 copied;
|
||||
|
||||
if (!ctx->event_pending)
|
||||
return -EINVAL;
|
||||
|
||||
if (kfifo_len(&ctx->events_fifo) == 1)
|
||||
ctx->event_pending = false;
|
||||
|
||||
return kfifo_to_user(&ctx->events_fifo, event,
|
||||
sizeof(enum wigig_sensing_event), &copied);
|
||||
}
|
||||
|
||||
static int wigig_sensing_open(struct inode *inode, struct file *filp)
|
||||
|
|
@ -662,7 +660,8 @@ static unsigned int wigig_sensing_poll(struct file *filp, poll_table *wait)
|
|||
|
||||
poll_wait(filp, &ctx->data_wait_q, wait);
|
||||
|
||||
if (circ_cnt(&ctx->cir_data.b, ctx->cir_data.size_bytes))
|
||||
if (!ctx->stm.change_mode_in_progress &&
|
||||
circ_cnt(&ctx->cir_data.b, ctx->cir_data.size_bytes))
|
||||
mask |= (POLLIN | POLLRDNORM);
|
||||
|
||||
if (ctx->event_pending)
|
||||
|
|
@ -681,11 +680,19 @@ static ssize_t wigig_sensing_read(struct file *filp, char __user *buf,
|
|||
struct cir_data *d = &ctx->cir_data;
|
||||
|
||||
/* Driver not ready to send data */
|
||||
if ((!ctx) ||
|
||||
(!ctx->spi_dev) ||
|
||||
(!d->b.buf))
|
||||
if (!ctx || !ctx->spi_dev || !d->b.buf ||
|
||||
ctx->stm.state == WIGIG_SENSING_STATE_SYS_ASSERT)
|
||||
return -ENODEV;
|
||||
|
||||
if (ctx->stm.change_mode_in_progress)
|
||||
return -EINVAL;
|
||||
|
||||
/* Read buffer too small */
|
||||
if (count < ctx->stm.burst_size) {
|
||||
pr_err("Read buffer must be larger than burst size\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* No data in the buffer */
|
||||
while (circ_cnt(&d->b, d->size_bytes) == 0) {
|
||||
if (filp->f_flags & O_NONBLOCK)
|
||||
|
|
@ -695,11 +702,11 @@ static ssize_t wigig_sensing_read(struct file *filp, char __user *buf,
|
|||
circ_cnt(&d->b, d->size_bytes) != 0))
|
||||
return -ERESTARTSYS;
|
||||
}
|
||||
|
||||
if (mutex_lock_interruptible(&d->lock))
|
||||
return -ERESTARTSYS;
|
||||
|
||||
copy_size = min_t(u32, circ_cnt(&d->b, d->size_bytes), count);
|
||||
copy_size -= copy_size % ctx->stm.burst_size;
|
||||
size_to_end = circ_cnt_to_end(&d->b, d->size_bytes);
|
||||
tail = d->b.tail;
|
||||
pr_debug("copy_size=%u, size_to_end=%u, head=%u, tail=%u\n",
|
||||
|
|
@ -759,7 +766,7 @@ static int wigig_sensing_release(struct inode *inode, struct file *filp)
|
|||
}
|
||||
|
||||
static long wigig_sensing_ioctl(struct file *file, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
__user unsigned long arg)
|
||||
{
|
||||
int rc;
|
||||
struct wigig_sensing_ctx *ctx = file->private_data;
|
||||
|
|
@ -812,7 +819,12 @@ static long wigig_sensing_ioctl(struct file *file, unsigned int cmd,
|
|||
break;
|
||||
case WIGIG_SENSING_IOCTL_GET_EVENT:
|
||||
pr_info("Received WIGIG_SENSING_IOCTL_GET_EVENT command\n");
|
||||
rc = wigig_sensing_ioc_get_event(ctx);
|
||||
rc = wigig_sensing_ioc_get_event(ctx,
|
||||
(enum wigig_sensing_event *)arg);
|
||||
break;
|
||||
case WIGIG_SENSING_IOCTL_GET_NUM_AVAIL_BURSTS:
|
||||
pr_info("Received WIGIG_SENSING_IOCTL_GET_NUM_AVAIL_BURSTS command\n");
|
||||
rc = wigig_sensing_ioc_get_num_avail_bursts(ctx);
|
||||
break;
|
||||
default:
|
||||
rc = -EINVAL;
|
||||
|
|
@ -908,17 +920,11 @@ static int wigig_sensing_handle_fifo_ready_dri(struct wigig_sensing_ctx *ctx)
|
|||
goto End;
|
||||
}
|
||||
|
||||
if (!ctx->stm.enabled && burst_size != 0) {
|
||||
pr_info("Invalid burst size while disabled %d\n", burst_size);
|
||||
rc = -EFAULT;
|
||||
goto End;
|
||||
}
|
||||
|
||||
ctx->stm.burst_size = burst_size;
|
||||
if (!ctx->stm.enabled ||
|
||||
ctx->stm.state >= WIGIG_SENSING_STATE_SYS_ASSERT ||
|
||||
ctx->stm.state < WIGIG_SENSING_STATE_SPI_READY) {
|
||||
pr_err("Received burst_size in an unexpected state\n");
|
||||
if (ctx->stm.state >= WIGIG_SENSING_STATE_SYS_ASSERT ||
|
||||
ctx->stm.state < WIGIG_SENSING_STATE_READY_STOPPED) {
|
||||
pr_err("Received burst_size in an unexpected state (%d)\n",
|
||||
ctx->stm.state);
|
||||
rc = -EFAULT;
|
||||
goto End;
|
||||
}
|
||||
|
|
@ -951,9 +957,24 @@ static int wigig_sensing_handle_fifo_ready_dri(struct wigig_sensing_ctx *ctx)
|
|||
ctx->temp_buffer = 0;
|
||||
}
|
||||
|
||||
wake_up_interruptible(&ctx->cmd_wait_q);
|
||||
/* Change internal state */
|
||||
rc = wigig_sensing_change_state(ctx, &ctx->stm, ctx->stm.state_request);
|
||||
if (rc) {
|
||||
pr_err("wigig_sensing_change_state() failed\n");
|
||||
goto End;
|
||||
}
|
||||
|
||||
/* Initialize head and tail pointers to 0 */
|
||||
wigig_sensing_ioc_clear_data(ctx);
|
||||
|
||||
ctx->dropped_bursts = 0;
|
||||
ctx->stm.channel = ctx->stm.channel_request;
|
||||
ctx->stm.mode = ctx->stm.mode_request;
|
||||
|
||||
End:
|
||||
ctx->stm.change_mode_in_progress = false;
|
||||
mutex_unlock(&ctx->spi_lock);
|
||||
wake_up_interruptible(&ctx->cmd_wait_q);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
@ -969,9 +990,9 @@ static int wigig_sensing_chip_data_ready(struct wigig_sensing_ctx *ctx,
|
|||
u32 idx = 0;
|
||||
u32 spi_transaction_size;
|
||||
u32 available_space_to_end;
|
||||
u32 orig_head;
|
||||
|
||||
if (stm_state == WIGIG_SENSING_STATE_INITIALIZED ||
|
||||
stm_state == WIGIG_SENSING_STATE_SPI_READY ||
|
||||
stm_state == WIGIG_SENSING_STATE_READY_STOPPED ||
|
||||
stm_state == WIGIG_SENSING_STATE_SYS_ASSERT) {
|
||||
pr_err("Received data ready interrupt in an unexpected stm_state, disregarding\n");
|
||||
|
|
@ -1017,8 +1038,14 @@ static int wigig_sensing_chip_data_ready(struct wigig_sensing_ctx *ctx,
|
|||
spi_transaction_size =
|
||||
calc_spi_transaction_size(fill_level, SPI_MAX_TRANSACTION_SIZE);
|
||||
local = d->b;
|
||||
orig_head = local.head;
|
||||
mutex_lock(&ctx->spi_lock);
|
||||
while (fill_level > 0) {
|
||||
if (ctx->stm.change_mode_in_progress) {
|
||||
local.head = orig_head;
|
||||
break;
|
||||
}
|
||||
|
||||
bytes_to_read = (fill_level < spi_transaction_size) ?
|
||||
fill_level : spi_transaction_size;
|
||||
available_space_to_end =
|
||||
|
|
@ -1131,6 +1158,22 @@ cmd_reply_buf_alloc_failed:
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int wigig_sensing_send_event(struct wigig_sensing_ctx *ctx,
|
||||
enum wigig_sensing_event event)
|
||||
{
|
||||
if (kfifo_is_full(&ctx->events_fifo)) {
|
||||
pr_err("events fifo is full, unable to send event\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
kfifo_in(&ctx->events_fifo, &event, 1);
|
||||
ctx->event_pending = true;
|
||||
|
||||
wake_up_interruptible(&ctx->cmd_wait_q);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t wigig_sensing_dri_isr_thread(int irq, void *cookie)
|
||||
{
|
||||
struct wigig_sensing_ctx *ctx = cookie;
|
||||
|
|
@ -1170,7 +1213,7 @@ static irqreturn_t wigig_sensing_dri_isr_thread(int irq, void *cookie)
|
|||
ctx->stm.spi_malfunction = false;
|
||||
if (ctx->stm.state == WIGIG_SENSING_STATE_INITIALIZED)
|
||||
wigig_sensing_change_state(ctx, &ctx->stm,
|
||||
WIGIG_SENSING_STATE_SPI_READY);
|
||||
WIGIG_SENSING_STATE_READY_STOPPED);
|
||||
}
|
||||
|
||||
pr_debug("Reading SANITY register\n");
|
||||
|
|
@ -1207,17 +1250,37 @@ static irqreturn_t wigig_sensing_dri_isr_thread(int irq, void *cookie)
|
|||
goto bail_out;
|
||||
}
|
||||
|
||||
if (spi_status.b.int_sysassert) {
|
||||
enum wigig_sensing_stm_e old_state = ctx->stm.state;
|
||||
|
||||
pr_info_ratelimited("SYSASSERT INTERRUPT\n");
|
||||
ctx->stm.fw_is_ready = false;
|
||||
|
||||
wigig_sensing_change_state(ctx, &ctx->stm,
|
||||
WIGIG_SENSING_STATE_SYS_ASSERT);
|
||||
|
||||
/* Send asynchronous RESET event to application */
|
||||
if (old_state != WIGIG_SENSING_STATE_READY_STOPPED)
|
||||
wigig_sensing_send_event(ctx,
|
||||
WIGIG_SENSING_EVENT_RESET);
|
||||
|
||||
ctx->stm.spi_malfunction = true;
|
||||
memset(&ctx->inb_cmd, 0, sizeof(ctx->inb_cmd));
|
||||
spi_status.v &= ~INT_SYSASSERT;
|
||||
goto deassert_and_bail_out;
|
||||
}
|
||||
if (spi_status.b.int_fw_ready) {
|
||||
pr_debug("FW READY INTERRUPT\n");
|
||||
pr_info_ratelimited("FW READY INTERRUPT\n");
|
||||
ctx->stm.fw_is_ready = true;
|
||||
ctx->stm.channel_request = 0;
|
||||
ctx->stm.burst_size = 0;
|
||||
ctx->stm.mode = WIGIG_SENSING_MODE_STOP;
|
||||
ctx->stm.enabled = true;
|
||||
|
||||
wigig_sensing_change_state(ctx, &ctx->stm,
|
||||
WIGIG_SENSING_STATE_READY_STOPPED);
|
||||
|
||||
/* Send asynchronous FW_READY event to application */
|
||||
wigig_sensing_send_event(ctx, WIGIG_SENSING_EVENT_FW_READY);
|
||||
|
||||
spi_status.v &= ~INT_FW_READY;
|
||||
}
|
||||
if (spi_status.b.int_data_ready) {
|
||||
|
|
@ -1230,24 +1293,11 @@ static irqreturn_t wigig_sensing_dri_isr_thread(int irq, void *cookie)
|
|||
pr_debug("Change mode in progress, aborting data processing\n");
|
||||
spi_status.v &= ~INT_DATA_READY;
|
||||
}
|
||||
if (spi_status.b.int_sysassert) {
|
||||
pr_debug("SYSASSERT INTERRUPT\n");
|
||||
ctx->stm.fw_is_ready = false;
|
||||
|
||||
rc = wigig_sensing_change_state(ctx, &ctx->stm,
|
||||
WIGIG_SENSING_STATE_SYS_ASSERT);
|
||||
if (rc != 0 ||
|
||||
ctx->stm.state != WIGIG_SENSING_STATE_SYS_ASSERT)
|
||||
pr_err("State change to WIGIG_SENSING_SYS_ASSERT failed\n");
|
||||
|
||||
ctx->stm.spi_malfunction = true;
|
||||
spi_status.v &= ~INT_SYSASSERT;
|
||||
}
|
||||
if (spi_status.b.int_deep_sleep_exit ||
|
||||
(ctx->stm.waiting_for_deep_sleep_exit &&
|
||||
ctx->stm.waiting_for_deep_sleep_exit_first_pass)) {
|
||||
if (spi_status.b.int_deep_sleep_exit)
|
||||
pr_debug("DEEP SLEEP EXIT INTERRUPT\n");
|
||||
pr_info_ratelimited("DEEP SLEEP EXIT INTERRUPT\n");
|
||||
|
||||
if (ctx->stm.waiting_for_deep_sleep_exit) {
|
||||
additional_inb_command = ctx->inb_cmd;
|
||||
|
|
@ -1260,7 +1310,7 @@ static irqreturn_t wigig_sensing_dri_isr_thread(int irq, void *cookie)
|
|||
spi_status.v &= ~INT_DEEP_SLEEP_EXIT;
|
||||
}
|
||||
if (spi_status.b.int_fifo_ready) {
|
||||
pr_debug("FIFO READY INTERRUPT\n");
|
||||
pr_info_ratelimited("FIFO READY INTERRUPT\n");
|
||||
wigig_sensing_handle_fifo_ready_dri(ctx);
|
||||
|
||||
spi_status.v &= ~INT_FIFO_READY;
|
||||
|
|
@ -1274,6 +1324,7 @@ static irqreturn_t wigig_sensing_dri_isr_thread(int irq, void *cookie)
|
|||
pr_err("Unexpected interrupt received, spi_status=0x%X\n",
|
||||
spi_status.v & CLEAR_LOW_23_BITS);
|
||||
|
||||
deassert_and_bail_out:
|
||||
/* Notify FW we are done with interrupt handling */
|
||||
rc = wigig_sensing_deassert_dri(ctx, additional_inb_command);
|
||||
if (rc)
|
||||
|
|
@ -1312,6 +1363,7 @@ static int wigig_sensing_probe(struct spi_device *spi)
|
|||
init_waitqueue_head(&ctx->cmd_wait_q);
|
||||
init_waitqueue_head(&ctx->data_wait_q);
|
||||
ctx->stm.state = WIGIG_SENSING_STATE_INITIALIZED;
|
||||
INIT_KFIFO(ctx->events_fifo);
|
||||
|
||||
/* Allocate memory for the CIRs */
|
||||
/* Allocate a 2MB == 2^21 buffer for CIR data */
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#define __WIGIG_SENSING_H__
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/circ_buf.h>
|
||||
#include <linux/kfifo.h>
|
||||
#include <linux/slab.h>
|
||||
#include <uapi/misc/wigig_sensing_uapi.h>
|
||||
|
||||
|
|
@ -130,7 +131,6 @@ struct spi_fifo {
|
|||
enum wigig_sensing_stm_e {
|
||||
WIGIG_SENSING_STATE_MIN = 0,
|
||||
WIGIG_SENSING_STATE_INITIALIZED,
|
||||
WIGIG_SENSING_STATE_SPI_READY,
|
||||
WIGIG_SENSING_STATE_READY_STOPPED,
|
||||
WIGIG_SENSING_STATE_SEARCH,
|
||||
WIGIG_SENSING_STATE_FACIAL,
|
||||
|
|
@ -143,10 +143,8 @@ enum wigig_sensing_stm_e {
|
|||
|
||||
struct wigig_sensing_stm {
|
||||
bool auto_recovery;
|
||||
bool enabled;
|
||||
bool fw_is_ready;
|
||||
bool spi_malfunction;
|
||||
bool sys_assert;
|
||||
bool waiting_for_deep_sleep_exit;
|
||||
bool waiting_for_deep_sleep_exit_first_pass;
|
||||
bool burst_size_ready;
|
||||
|
|
@ -154,7 +152,10 @@ struct wigig_sensing_stm {
|
|||
enum wigig_sensing_stm_e state;
|
||||
enum wigig_sensing_mode mode;
|
||||
u32 burst_size;
|
||||
u32 channel;
|
||||
u32 channel_request;
|
||||
enum wigig_sensing_stm_e state_request;
|
||||
enum wigig_sensing_mode mode_request;
|
||||
};
|
||||
|
||||
struct wigig_sensing_ctx {
|
||||
|
|
@ -193,6 +194,7 @@ struct wigig_sensing_ctx {
|
|||
struct cir_data cir_data;
|
||||
u8 *temp_buffer;
|
||||
bool event_pending;
|
||||
DECLARE_KFIFO(events_fifo, enum wigig_sensing_event, 8);
|
||||
u32 dropped_bursts;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -27,8 +27,10 @@ struct wigig_sensing_change_mode {
|
|||
};
|
||||
|
||||
enum wigig_sensing_event {
|
||||
WIGIG_SENSING_EVENT_MIN,
|
||||
WIGIG_SENSING_EVENT_FW_READY,
|
||||
WIGIG_SENSING_EVENT_RESET,
|
||||
WIGIG_SENSING_EVENT_MAX,
|
||||
};
|
||||
|
||||
#define WIGIG_SENSING_IOC_MAGIC 'r'
|
||||
|
|
@ -39,6 +41,7 @@ enum wigig_sensing_event {
|
|||
#define WIGIG_SENSING_IOCTL_CLEAR_DATA (3)
|
||||
#define WIGIG_SENSING_IOCTL_GET_NUM_DROPPED_BURSTS (4)
|
||||
#define WIGIG_SENSING_IOCTL_GET_EVENT (5)
|
||||
#define WIGIG_SENSING_IOCTL_GET_NUM_AVAIL_BURSTS (6)
|
||||
|
||||
/**
|
||||
* Set auto recovery, which means that the system will go back to search mode
|
||||
|
|
@ -83,10 +86,17 @@ enum wigig_sensing_event {
|
|||
WIGIG_SENSING_IOCTL_GET_NUM_DROPPED_BURSTS, uint32_t)
|
||||
|
||||
/**
|
||||
* Get number of bursts that where dropped due to data buffer overflow
|
||||
* Get asynchronous event (FW_READY, RESET)
|
||||
*/
|
||||
#define WIGIG_SENSING_IOC_GET_EVENT \
|
||||
_IOR(WIGIG_SENSING_IOC_MAGIC, WIGIG_SENSING_IOCTL_GET_EVENT, \
|
||||
sizeof(enum wigig_sensing_event))
|
||||
|
||||
#endif /* ____WIGIG_SENSING_UAPI_H__ */
|
||||
/**
|
||||
* Get number of available bursts in the data buffer
|
||||
*/
|
||||
#define WIGIG_SENSING_IOC_GET_NUM_AVAIL_BURSTS \
|
||||
_IOR(WIGIG_SENSING_IOC_MAGIC, WIGIG_SENSING_IOCTL_GET_NUM_AVAIL_BURSTS,\
|
||||
sizeof(uint32_t))
|
||||
|
||||
#endif /* __WIGIG_SENSING_UAPI_H__ */
|
||||
|
|
|
|||
Loading…
Reference in a new issue