Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a1401113 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "diag: Free global buffer properly after receiving write done"

parents 0af2ccf0 b62b1338
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -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 */
@@ -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);
+83 −31
Original line number Diff line number Diff line
@@ -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
@@ -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)
{
@@ -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)
@@ -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;
@@ -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 +
@@ -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;
@@ -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;
@@ -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;
@@ -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);
+16 −3
Original line number Diff line number Diff line
@@ -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;
@@ -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",