Loading drivers/char/diag/diagchar.h +12 −0 Original line number Diff line number Diff line Loading @@ -800,6 +800,7 @@ struct diagchar_dev { unsigned int poolsize_dci; unsigned int poolsize_user; spinlock_t diagmem_lock; wait_queue_head_t hdlc_wait_q; /* Buffers for masks */ struct mutex diag_cntl_mutex; /* Members for Sending response */ Loading Loading @@ -907,6 +908,17 @@ extern struct diagchar_dev *driver; extern int wrap_enabled; extern uint16_t wrap_count; struct diag_apps_data_t { void *buf; uint32_t len; int ctxt; uint8_t allocated; uint8_t flushed; }; extern struct diag_apps_data_t hdlc_data; extern struct diag_apps_data_t non_hdlc_data; void diag_get_timestamp(char *time_str); void check_drain_timer(void); int diag_get_remote(int remote_info); Loading drivers/char/diag/diagchar_core.c +83 −31 Original line number Diff line number Diff line Loading @@ -133,14 +133,8 @@ static int timer_in_progress; static int diag_mask_clear_param = 1; module_param(diag_mask_clear_param, int, 0644); struct diag_apps_data_t { void *buf; uint32_t len; int ctxt; }; static struct diag_apps_data_t hdlc_data; static struct diag_apps_data_t non_hdlc_data; struct diag_apps_data_t hdlc_data; struct diag_apps_data_t non_hdlc_data; static struct mutex apps_data_mutex; #define DIAGPKT_MAX_DELAYED_RSP 0xFFFF Loading Loading @@ -202,15 +196,22 @@ static void diag_drain_apps_data(struct diag_apps_data_t *data) if (!data || !data->buf) return; spin_lock_irqsave(&driver->diagmem_lock, flags); data->flushed = 1; spin_unlock_irqrestore(&driver->diagmem_lock, flags); err = diag_mux_write(DIAG_LOCAL_PROC, data->buf, data->len, data->ctxt); if (err) { spin_lock_irqsave(&driver->diagmem_lock, flags); if (err) diagmem_free(driver, data->buf, POOL_TYPE_HDLC); data->buf = NULL; data->len = 0; data->allocated = 0; data->flushed = 0; spin_unlock_irqrestore(&driver->diagmem_lock, flags); } } void diag_update_user_client_work_fn(struct work_struct *work) { Loading Loading @@ -282,6 +283,7 @@ static void diag_mempool_init(void) diagmem_init(driver, POOL_TYPE_DCI); spin_lock_init(&driver->diagmem_lock); init_waitqueue_head(&driver->hdlc_wait_q); } static void diag_mempool_exit(void) Loading Loading @@ -3087,31 +3089,47 @@ static int diag_process_apps_data_hdlc(unsigned char *buf, int len, send.last = (void *)(buf + len - 1); send.terminate = 1; if (!data->buf) wait_event_interruptible(driver->hdlc_wait_q, (data->flushed == 0)); if (!data->buf) { spin_lock_irqsave(&driver->diagmem_lock, flags); data->buf = diagmem_alloc(driver, DIAG_MAX_HDLC_BUF_SIZE + APF_DIAG_PADDING, POOL_TYPE_HDLC); if (!data->buf) { ret = PKT_DROP; spin_unlock_irqrestore(&driver->diagmem_lock, flags); goto fail_ret; } data->allocated = 1; data->flushed = 0; spin_unlock_irqrestore(&driver->diagmem_lock, flags); } if ((DIAG_MAX_HDLC_BUF_SIZE - data->len) <= max_encoded_size) { spin_lock_irqsave(&driver->diagmem_lock, flags); data->flushed = 1; spin_unlock_irqrestore(&driver->diagmem_lock, flags); err = diag_mux_write(DIAG_LOCAL_PROC, data->buf, data->len, data->ctxt); if (err) { ret = -EIO; goto fail_free_buf; } data->buf = NULL; data->len = 0; wait_event_interruptible(driver->hdlc_wait_q, (data->flushed == 0)); spin_lock_irqsave(&driver->diagmem_lock, flags); data->buf = diagmem_alloc(driver, DIAG_MAX_HDLC_BUF_SIZE + APF_DIAG_PADDING, POOL_TYPE_HDLC); if (!data->buf) { ret = PKT_DROP; spin_unlock_irqrestore(&driver->diagmem_lock, flags); goto fail_ret; } data->allocated = 1; data->flushed = 0; spin_unlock_irqrestore(&driver->diagmem_lock, flags); } enc.dest = data->buf + data->len; Loading @@ -3126,21 +3144,29 @@ static int diag_process_apps_data_hdlc(unsigned char *buf, int len, */ if ((uintptr_t)enc.dest >= (uintptr_t)(data->buf + DIAG_MAX_HDLC_BUF_SIZE)) { spin_lock_irqsave(&driver->diagmem_lock, flags); data->flushed = 1; spin_unlock_irqrestore(&driver->diagmem_lock, flags); err = diag_mux_write(DIAG_LOCAL_PROC, data->buf, data->len, data->ctxt); if (err) { ret = -EIO; goto fail_free_buf; } data->buf = NULL; data->len = 0; wait_event_interruptible(driver->hdlc_wait_q, (data->flushed == 0)); spin_lock_irqsave(&driver->diagmem_lock, flags); data->buf = diagmem_alloc(driver, DIAG_MAX_HDLC_BUF_SIZE + APF_DIAG_PADDING, POOL_TYPE_HDLC); if (!data->buf) { ret = PKT_DROP; spin_unlock_irqrestore(&driver->diagmem_lock, flags); goto fail_ret; } data->allocated = 1; data->flushed = 0; spin_unlock_irqrestore(&driver->diagmem_lock, flags); enc.dest = data->buf + data->len; enc.dest_last = (void *)(data->buf + data->len + Loading @@ -3154,23 +3180,27 @@ static int diag_process_apps_data_hdlc(unsigned char *buf, int len, DIAG_MAX_HDLC_BUF_SIZE; if (pkt_type == DATA_TYPE_RESPONSE) { spin_lock_irqsave(&driver->diagmem_lock, flags); data->flushed = 1; spin_unlock_irqrestore(&driver->diagmem_lock, flags); err = diag_mux_write(DIAG_LOCAL_PROC, data->buf, data->len, data->ctxt); if (err) { ret = -EIO; goto fail_free_buf; } data->buf = NULL; data->len = 0; } return PKT_ALLOC; fail_free_buf: spin_lock_irqsave(&driver->diagmem_lock, flags); if (data->allocated) diagmem_free(driver, data->buf, POOL_TYPE_HDLC); data->buf = NULL; data->len = 0; data->allocated = 0; data->flushed = 0; spin_unlock_irqrestore(&driver->diagmem_lock, flags); fail_ret: return ret; Loading @@ -3196,33 +3226,47 @@ static int diag_process_apps_data_non_hdlc(unsigned char *buf, int len, __func__, buf, len); return -EIO; } wait_event_interruptible(driver->hdlc_wait_q, (data->flushed == 0)); if (!data->buf) { spin_lock_irqsave(&driver->diagmem_lock, flags); data->buf = diagmem_alloc(driver, DIAG_MAX_HDLC_BUF_SIZE + APF_DIAG_PADDING, POOL_TYPE_HDLC); if (!data->buf) { ret = PKT_DROP; spin_unlock_irqrestore(&driver->diagmem_lock, flags); goto fail_ret; } data->allocated = 1; data->flushed = 0; spin_unlock_irqrestore(&driver->diagmem_lock, flags); } if ((DIAG_MAX_HDLC_BUF_SIZE - data->len) <= max_pkt_size) { spin_lock_irqsave(&driver->diagmem_lock, flags); data->flushed = 1; spin_unlock_irqrestore(&driver->diagmem_lock, flags); err = diag_mux_write(DIAG_LOCAL_PROC, data->buf, data->len, data->ctxt); if (err) { ret = -EIO; goto fail_free_buf; } data->buf = NULL; data->len = 0; wait_event_interruptible(driver->hdlc_wait_q, (data->flushed == 0)); spin_lock_irqsave(&driver->diagmem_lock, flags); data->buf = diagmem_alloc(driver, DIAG_MAX_HDLC_BUF_SIZE + APF_DIAG_PADDING, POOL_TYPE_HDLC); if (!data->buf) { ret = PKT_DROP; spin_unlock_irqrestore(&driver->diagmem_lock, flags); goto fail_ret; } data->allocated = 1; data->flushed = 0; spin_unlock_irqrestore(&driver->diagmem_lock, flags); } header.start = CONTROL_CHAR; Loading @@ -3235,23 +3279,27 @@ static int diag_process_apps_data_non_hdlc(unsigned char *buf, int len, *(uint8_t *)(data->buf + data->len) = CONTROL_CHAR; data->len += sizeof(uint8_t); if (pkt_type == DATA_TYPE_RESPONSE) { spin_lock_irqsave(&driver->diagmem_lock, flags); data->flushed = 1; spin_unlock_irqrestore(&driver->diagmem_lock, flags); err = diag_mux_write(DIAG_LOCAL_PROC, data->buf, data->len, data->ctxt); if (err) { ret = -EIO; goto fail_free_buf; } data->buf = NULL; data->len = 0; } return PKT_ALLOC; fail_free_buf: spin_lock_irqsave(&driver->diagmem_lock, flags); if (data->allocated) diagmem_free(driver, data->buf, POOL_TYPE_HDLC); data->buf = NULL; data->len = 0; data->allocated = 0; data->flushed = 0; spin_unlock_irqrestore(&driver->diagmem_lock, flags); fail_ret: return ret; Loading Loading @@ -4358,8 +4406,12 @@ static int __init diagchar_init(void) driver->rsp_buf_ctxt = SET_BUF_CTXT(APPS_DATA, TYPE_CMD, TYPE_CMD); hdlc_data.ctxt = SET_BUF_CTXT(APPS_DATA, TYPE_DATA, 1); hdlc_data.len = 0; hdlc_data.allocated = 0; hdlc_data.flushed = 0; non_hdlc_data.ctxt = SET_BUF_CTXT(APPS_DATA, TYPE_DATA, 1); non_hdlc_data.len = 0; non_hdlc_data.allocated = 0; non_hdlc_data.flushed = 0; mutex_init(&driver->hdlc_disable_mutex); mutex_init(&driver->diagchar_mutex); mutex_init(&driver->diag_notifier_mutex); Loading drivers/char/diag/diagfwd.c +16 −3 Original line number Diff line number Diff line Loading @@ -1918,6 +1918,7 @@ static int diagfwd_mux_write_done(unsigned char *buf, int len, int buf_ctxt, int peripheral = -1; int type = -1; int num = -1; struct diag_apps_data_t *temp = NULL; if (!buf || len < 0) return -EINVAL; Loading @@ -1936,9 +1937,21 @@ static int diagfwd_mux_write_done(unsigned char *buf, int len, int buf_ctxt, diag_ws_on_copy(DIAG_WS_MUX); } else if (peripheral == APPS_DATA) { spin_lock_irqsave(&driver->diagmem_lock, flags); diagmem_free(driver, (unsigned char *)buf, POOL_TYPE_HDLC); buf = NULL; if (hdlc_data.allocated) temp = &hdlc_data; else if (non_hdlc_data.allocated) temp = &non_hdlc_data; else DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "No apps data buffer is allocated to be freed\n"); if (temp) { diagmem_free(driver, temp->buf, POOL_TYPE_HDLC); temp->buf = NULL; temp->len = 0; temp->allocated = 0; temp->flushed = 0; wake_up_interruptible(&driver->hdlc_wait_q); } spin_unlock_irqrestore(&driver->diagmem_lock, flags); } else { pr_err_ratelimited("diag: Invalid peripheral %d in %s, type: %d\n", Loading Loading
drivers/char/diag/diagchar.h +12 −0 Original line number Diff line number Diff line Loading @@ -800,6 +800,7 @@ struct diagchar_dev { unsigned int poolsize_dci; unsigned int poolsize_user; spinlock_t diagmem_lock; wait_queue_head_t hdlc_wait_q; /* Buffers for masks */ struct mutex diag_cntl_mutex; /* Members for Sending response */ Loading Loading @@ -907,6 +908,17 @@ extern struct diagchar_dev *driver; extern int wrap_enabled; extern uint16_t wrap_count; struct diag_apps_data_t { void *buf; uint32_t len; int ctxt; uint8_t allocated; uint8_t flushed; }; extern struct diag_apps_data_t hdlc_data; extern struct diag_apps_data_t non_hdlc_data; void diag_get_timestamp(char *time_str); void check_drain_timer(void); int diag_get_remote(int remote_info); Loading
drivers/char/diag/diagchar_core.c +83 −31 Original line number Diff line number Diff line Loading @@ -133,14 +133,8 @@ static int timer_in_progress; static int diag_mask_clear_param = 1; module_param(diag_mask_clear_param, int, 0644); struct diag_apps_data_t { void *buf; uint32_t len; int ctxt; }; static struct diag_apps_data_t hdlc_data; static struct diag_apps_data_t non_hdlc_data; struct diag_apps_data_t hdlc_data; struct diag_apps_data_t non_hdlc_data; static struct mutex apps_data_mutex; #define DIAGPKT_MAX_DELAYED_RSP 0xFFFF Loading Loading @@ -202,15 +196,22 @@ static void diag_drain_apps_data(struct diag_apps_data_t *data) if (!data || !data->buf) return; spin_lock_irqsave(&driver->diagmem_lock, flags); data->flushed = 1; spin_unlock_irqrestore(&driver->diagmem_lock, flags); err = diag_mux_write(DIAG_LOCAL_PROC, data->buf, data->len, data->ctxt); if (err) { spin_lock_irqsave(&driver->diagmem_lock, flags); if (err) diagmem_free(driver, data->buf, POOL_TYPE_HDLC); data->buf = NULL; data->len = 0; data->allocated = 0; data->flushed = 0; spin_unlock_irqrestore(&driver->diagmem_lock, flags); } } void diag_update_user_client_work_fn(struct work_struct *work) { Loading Loading @@ -282,6 +283,7 @@ static void diag_mempool_init(void) diagmem_init(driver, POOL_TYPE_DCI); spin_lock_init(&driver->diagmem_lock); init_waitqueue_head(&driver->hdlc_wait_q); } static void diag_mempool_exit(void) Loading Loading @@ -3087,31 +3089,47 @@ static int diag_process_apps_data_hdlc(unsigned char *buf, int len, send.last = (void *)(buf + len - 1); send.terminate = 1; if (!data->buf) wait_event_interruptible(driver->hdlc_wait_q, (data->flushed == 0)); if (!data->buf) { spin_lock_irqsave(&driver->diagmem_lock, flags); data->buf = diagmem_alloc(driver, DIAG_MAX_HDLC_BUF_SIZE + APF_DIAG_PADDING, POOL_TYPE_HDLC); if (!data->buf) { ret = PKT_DROP; spin_unlock_irqrestore(&driver->diagmem_lock, flags); goto fail_ret; } data->allocated = 1; data->flushed = 0; spin_unlock_irqrestore(&driver->diagmem_lock, flags); } if ((DIAG_MAX_HDLC_BUF_SIZE - data->len) <= max_encoded_size) { spin_lock_irqsave(&driver->diagmem_lock, flags); data->flushed = 1; spin_unlock_irqrestore(&driver->diagmem_lock, flags); err = diag_mux_write(DIAG_LOCAL_PROC, data->buf, data->len, data->ctxt); if (err) { ret = -EIO; goto fail_free_buf; } data->buf = NULL; data->len = 0; wait_event_interruptible(driver->hdlc_wait_q, (data->flushed == 0)); spin_lock_irqsave(&driver->diagmem_lock, flags); data->buf = diagmem_alloc(driver, DIAG_MAX_HDLC_BUF_SIZE + APF_DIAG_PADDING, POOL_TYPE_HDLC); if (!data->buf) { ret = PKT_DROP; spin_unlock_irqrestore(&driver->diagmem_lock, flags); goto fail_ret; } data->allocated = 1; data->flushed = 0; spin_unlock_irqrestore(&driver->diagmem_lock, flags); } enc.dest = data->buf + data->len; Loading @@ -3126,21 +3144,29 @@ static int diag_process_apps_data_hdlc(unsigned char *buf, int len, */ if ((uintptr_t)enc.dest >= (uintptr_t)(data->buf + DIAG_MAX_HDLC_BUF_SIZE)) { spin_lock_irqsave(&driver->diagmem_lock, flags); data->flushed = 1; spin_unlock_irqrestore(&driver->diagmem_lock, flags); err = diag_mux_write(DIAG_LOCAL_PROC, data->buf, data->len, data->ctxt); if (err) { ret = -EIO; goto fail_free_buf; } data->buf = NULL; data->len = 0; wait_event_interruptible(driver->hdlc_wait_q, (data->flushed == 0)); spin_lock_irqsave(&driver->diagmem_lock, flags); data->buf = diagmem_alloc(driver, DIAG_MAX_HDLC_BUF_SIZE + APF_DIAG_PADDING, POOL_TYPE_HDLC); if (!data->buf) { ret = PKT_DROP; spin_unlock_irqrestore(&driver->diagmem_lock, flags); goto fail_ret; } data->allocated = 1; data->flushed = 0; spin_unlock_irqrestore(&driver->diagmem_lock, flags); enc.dest = data->buf + data->len; enc.dest_last = (void *)(data->buf + data->len + Loading @@ -3154,23 +3180,27 @@ static int diag_process_apps_data_hdlc(unsigned char *buf, int len, DIAG_MAX_HDLC_BUF_SIZE; if (pkt_type == DATA_TYPE_RESPONSE) { spin_lock_irqsave(&driver->diagmem_lock, flags); data->flushed = 1; spin_unlock_irqrestore(&driver->diagmem_lock, flags); err = diag_mux_write(DIAG_LOCAL_PROC, data->buf, data->len, data->ctxt); if (err) { ret = -EIO; goto fail_free_buf; } data->buf = NULL; data->len = 0; } return PKT_ALLOC; fail_free_buf: spin_lock_irqsave(&driver->diagmem_lock, flags); if (data->allocated) diagmem_free(driver, data->buf, POOL_TYPE_HDLC); data->buf = NULL; data->len = 0; data->allocated = 0; data->flushed = 0; spin_unlock_irqrestore(&driver->diagmem_lock, flags); fail_ret: return ret; Loading @@ -3196,33 +3226,47 @@ static int diag_process_apps_data_non_hdlc(unsigned char *buf, int len, __func__, buf, len); return -EIO; } wait_event_interruptible(driver->hdlc_wait_q, (data->flushed == 0)); if (!data->buf) { spin_lock_irqsave(&driver->diagmem_lock, flags); data->buf = diagmem_alloc(driver, DIAG_MAX_HDLC_BUF_SIZE + APF_DIAG_PADDING, POOL_TYPE_HDLC); if (!data->buf) { ret = PKT_DROP; spin_unlock_irqrestore(&driver->diagmem_lock, flags); goto fail_ret; } data->allocated = 1; data->flushed = 0; spin_unlock_irqrestore(&driver->diagmem_lock, flags); } if ((DIAG_MAX_HDLC_BUF_SIZE - data->len) <= max_pkt_size) { spin_lock_irqsave(&driver->diagmem_lock, flags); data->flushed = 1; spin_unlock_irqrestore(&driver->diagmem_lock, flags); err = diag_mux_write(DIAG_LOCAL_PROC, data->buf, data->len, data->ctxt); if (err) { ret = -EIO; goto fail_free_buf; } data->buf = NULL; data->len = 0; wait_event_interruptible(driver->hdlc_wait_q, (data->flushed == 0)); spin_lock_irqsave(&driver->diagmem_lock, flags); data->buf = diagmem_alloc(driver, DIAG_MAX_HDLC_BUF_SIZE + APF_DIAG_PADDING, POOL_TYPE_HDLC); if (!data->buf) { ret = PKT_DROP; spin_unlock_irqrestore(&driver->diagmem_lock, flags); goto fail_ret; } data->allocated = 1; data->flushed = 0; spin_unlock_irqrestore(&driver->diagmem_lock, flags); } header.start = CONTROL_CHAR; Loading @@ -3235,23 +3279,27 @@ static int diag_process_apps_data_non_hdlc(unsigned char *buf, int len, *(uint8_t *)(data->buf + data->len) = CONTROL_CHAR; data->len += sizeof(uint8_t); if (pkt_type == DATA_TYPE_RESPONSE) { spin_lock_irqsave(&driver->diagmem_lock, flags); data->flushed = 1; spin_unlock_irqrestore(&driver->diagmem_lock, flags); err = diag_mux_write(DIAG_LOCAL_PROC, data->buf, data->len, data->ctxt); if (err) { ret = -EIO; goto fail_free_buf; } data->buf = NULL; data->len = 0; } return PKT_ALLOC; fail_free_buf: spin_lock_irqsave(&driver->diagmem_lock, flags); if (data->allocated) diagmem_free(driver, data->buf, POOL_TYPE_HDLC); data->buf = NULL; data->len = 0; data->allocated = 0; data->flushed = 0; spin_unlock_irqrestore(&driver->diagmem_lock, flags); fail_ret: return ret; Loading Loading @@ -4358,8 +4406,12 @@ static int __init diagchar_init(void) driver->rsp_buf_ctxt = SET_BUF_CTXT(APPS_DATA, TYPE_CMD, TYPE_CMD); hdlc_data.ctxt = SET_BUF_CTXT(APPS_DATA, TYPE_DATA, 1); hdlc_data.len = 0; hdlc_data.allocated = 0; hdlc_data.flushed = 0; non_hdlc_data.ctxt = SET_BUF_CTXT(APPS_DATA, TYPE_DATA, 1); non_hdlc_data.len = 0; non_hdlc_data.allocated = 0; non_hdlc_data.flushed = 0; mutex_init(&driver->hdlc_disable_mutex); mutex_init(&driver->diagchar_mutex); mutex_init(&driver->diag_notifier_mutex); Loading
drivers/char/diag/diagfwd.c +16 −3 Original line number Diff line number Diff line Loading @@ -1918,6 +1918,7 @@ static int diagfwd_mux_write_done(unsigned char *buf, int len, int buf_ctxt, int peripheral = -1; int type = -1; int num = -1; struct diag_apps_data_t *temp = NULL; if (!buf || len < 0) return -EINVAL; Loading @@ -1936,9 +1937,21 @@ static int diagfwd_mux_write_done(unsigned char *buf, int len, int buf_ctxt, diag_ws_on_copy(DIAG_WS_MUX); } else if (peripheral == APPS_DATA) { spin_lock_irqsave(&driver->diagmem_lock, flags); diagmem_free(driver, (unsigned char *)buf, POOL_TYPE_HDLC); buf = NULL; if (hdlc_data.allocated) temp = &hdlc_data; else if (non_hdlc_data.allocated) temp = &non_hdlc_data; else DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "No apps data buffer is allocated to be freed\n"); if (temp) { diagmem_free(driver, temp->buf, POOL_TYPE_HDLC); temp->buf = NULL; temp->len = 0; temp->allocated = 0; temp->flushed = 0; wake_up_interruptible(&driver->hdlc_wait_q); } spin_unlock_irqrestore(&driver->diagmem_lock, flags); } else { pr_err_ratelimited("diag: Invalid peripheral %d in %s, type: %d\n", Loading