[qca-nss-drv] Dump logbuffer during the coredump

Change-Id: Icacb3056cb4baac1c18d0d3a802cadf2d94d1914
Signed-off-by: Cemil Coskun <ccoskun@codeaurora.org>
diff --git a/nss_log.c b/nss_log.c
index 4cf0795..7a0fdd5 100644
--- a/nss_log.c
+++ b/nss_log.c
@@ -46,17 +46,7 @@
 	int nss_id;		/* NSS Core id being used */
 };
 
-/*
- * Saves the ring buffer address for logging per NSS core
- */
-struct nss_ring_buffer_addr {
-	void *addr;		/* Pointer to struct nss_log_descriptor */
-	dma_addr_t dma_addr;	/* DMA Handle */
-	uint32_t nentries;	/* Number of entries in the ring buffer */
-	int refcnt;		/* Reference count */
-};
-
-static struct nss_ring_buffer_addr nss_rbe[NSS_MAX_CORES];
+struct nss_log_ring_buffer_addr nss_rbe[NSS_MAX_CORES];
 
 static DEFINE_MUTEX(nss_log_mutex);
 static wait_queue_head_t nss_log_wq;
@@ -140,7 +130,7 @@
 	 * Increment the reference count so that we don't free
 	 * the memory
 	 */
-	nss_rbe[nss_id].refcnt++;
+	nss_rbe[nss_id].ref_cnt++;
 	data->nss_id = nss_id;
 	filp->private_data = data;
 	mutex_unlock(&nss_log_mutex);
@@ -162,9 +152,9 @@
 	}
 
 	mutex_lock(&nss_log_mutex);
-	nss_rbe[data->nss_id].refcnt--;
-	BUG_ON(nss_rbe[data->nss_id].refcnt < 0);
-	if (nss_rbe[data->nss_id].refcnt == 0) {
+	nss_rbe[data->nss_id].ref_cnt--;
+	BUG_ON(nss_rbe[data->nss_id].ref_cnt < 0);
+	if (!nss_rbe[data->nss_id].ref_cnt) {
 		wake_up(&nss_log_wq);
 	}
 	mutex_unlock(&nss_log_mutex);
@@ -217,7 +207,7 @@
 	/*
 	 * Get the current index
 	 */
-	dma_sync_single_for_cpu(NULL, data->dma_addr, sizeof (struct nss_log_descriptor), DMA_FROM_DEVICE);
+	dma_sync_single_for_cpu(NULL, data->dma_addr, sizeof(struct nss_log_descriptor), DMA_FROM_DEVICE);
 	entry = nss_log_current_entry(desc);
 
 	/*
@@ -230,7 +220,7 @@
 	/*
 	 * If this is the first read (after open) on our device file.
 	 */
-	if (unlikely(*ppos == 0)) {
+	if (unlikely(!(*ppos))) {
 		/*
 		 * If log buffer has rolled over. Almost all the time
 		 * it will be true.
@@ -258,7 +248,7 @@
 	 */
 	while (entry > data->last_entry) {
 		index = offset = (data->last_entry % data->nentries);
-		offset = (offset * sizeof (struct nss_log_entry))
+		offset = (offset * sizeof(struct nss_log_entry))
 			 + offsetof(struct nss_log_descriptor, log_ring_buffer);
 
 		dma_sync_single_for_cpu(NULL, data->dma_addr + offset,
@@ -274,13 +264,12 @@
 		 * Copy to user buffer and if we fail then we return
 		 * failure.
 		 */
-	        if (copy_to_user(buf + bytes, msg, b) == 0) {
-			bytes += b;
-		} else {
-			bytes = -EFAULT;
-			break;
+		if (copy_to_user(buf + bytes, msg, b)) {
+			return -EFAULT;
 		}
 
+		bytes += b;
+
 		/*
 		 * If we ran out of space in the buffer.
 		 */
@@ -316,7 +305,7 @@
  * nss_debug_interface_event()
  *	Received an event from NSS FW
  */
-static void nss_debug_interface_event(void *app_data, struct nss_debug_interface_msg *nim)
+static void nss_debug_interface_event(void *app_data, struct nss_log_debug_interface_msg *nim)
 {
 	struct nss_cmn_msg *ncm = (struct nss_cmn_msg *)nim;
 
@@ -327,11 +316,11 @@
 
 /*
  * nss_debug_interface_handler()
- * 	handle NSS -> HLOS messages for debug interfaces
+ *	handle NSS -> HLOS messages for debug interfaces
  */
 static void nss_debug_interface_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, __attribute__((unused))void *app_data)
 {
-	struct nss_debug_interface_msg *ntm = (struct nss_debug_interface_msg *)ncm;
+	struct nss_log_debug_interface_msg *ntm = (struct nss_log_debug_interface_msg *)ncm;
 	nss_log_msg_callback_t cb;
 
 	BUG_ON(ncm->interface != NSS_DEBUG_INTERFACE);
@@ -344,7 +333,7 @@
 		return;
 	}
 
-	if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_debug_interface_msg)) {
+	if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_log_debug_interface_msg)) {
 		nss_warning("%p: Length of message is greater than required: %d", nss_ctx, nss_cmn_get_msg_len(ncm));
 		return;
 	}
@@ -373,9 +362,9 @@
 
 /*
  * nss_debug_interface_tx()
- * 	Transmit a debug interface message to NSS FW
+ *	Transmit a debug interface message to NSS FW
  */
-static nss_tx_status_t nss_debug_interface_tx(struct nss_ctx_instance *nss_ctx, struct nss_debug_interface_msg *msg)
+static nss_tx_status_t nss_debug_interface_tx(struct nss_ctx_instance *nss_ctx, struct nss_log_debug_interface_msg *msg)
 {
 	struct nss_cmn_msg *ncm = &msg->cm;
 
@@ -401,17 +390,14 @@
  */
 bool nss_debug_log_buffer_alloc(uint8_t nss_id, uint32_t nentry)
 {
-	struct nss_ring_buffer_addr old_rbe;
-	struct nss_debug_interface_msg msg;
-	struct nss_debug_log_memory_msg *dbg;
+	struct nss_log_debug_interface_msg msg;
+	struct nss_log_debug_memory_msg *dbg;
 	struct nss_top_instance *nss_top;
 	struct nss_ctx_instance *nss_ctx;
 	dma_addr_t dma_addr;
 	uint32_t size;
 	void *addr = NULL;
 	nss_tx_status_t status;
-	bool err = false;
-	bool old_state = false;
 
 	if (nss_id >= NSS_MAX_CORES) {
 		return false;
@@ -425,9 +411,7 @@
 		return false;
 	}
 
-	memset(&msg, 0, sizeof(struct nss_debug_interface_msg));
-
-	size = sizeof (struct nss_log_descriptor) + (sizeof (struct nss_log_entry) * nentry);
+	size = sizeof(struct nss_log_descriptor) + (sizeof(struct nss_log_entry) * nentry);
 	addr = kmalloc(size, GFP_ATOMIC);
 	if (!addr) {
 		nss_warning("%p: Failed to allocate memory for logging (size:%d)\n", nss_ctx, size);
@@ -438,7 +422,8 @@
 	dma_addr = (uint32_t)dma_map_single(nss_ctx->dev, addr, size, DMA_FROM_DEVICE);
 	if (unlikely(dma_mapping_error(nss_ctx->dev, dma_addr))) {
 		nss_warning("%p: Failed to map address in DMA", nss_ctx);
-		goto fail2;
+		kfree(addr);
+		return false;
 	}
 
 	/*
@@ -448,40 +433,32 @@
 	mutex_lock(&nss_log_mutex);
 	if (nss_rbe[nss_id].addr) {
 		mutex_unlock(&nss_log_mutex);
-		if (!wait_event_timeout(nss_log_wq, nss_rbe[nss_id].refcnt == 0, 5 * HZ)) {
+
+		/*
+		 * Someone is using the current logbuffer. Wait until ref count become 0.
+		 * We have to return mutex here, because the current user requires it to
+		 * release the reference.
+		 */
+		if (!wait_event_timeout(nss_log_wq, !nss_rbe[nss_id].ref_cnt, 5 * HZ)) {
 			nss_warning("%p: Timeout waiting for refcnt to become 0\n", nss_ctx);
-			goto fail1;
+			goto fail;
 		}
 
 		mutex_lock(&nss_log_mutex);
 		if (!nss_rbe[nss_id].addr) {
 			mutex_unlock(&nss_log_mutex);
-			goto fail1;
+			goto fail;
 		}
-		if (nss_rbe[nss_id].refcnt > 0) {
+		if (nss_rbe[nss_id].ref_cnt > 0) {
 			mutex_unlock(&nss_log_mutex);
-			nss_warning("%p: Some other thread is condenting..opting out\n", nss_ctx);
-			goto fail1;
+			nss_warning("%p: Some other thread is contending..opting out\n", nss_ctx);
+			goto fail;
 		}
-
-		/*
-		 * Save the original dma buffer. In case we fail down the line, we will
-		 * restore the state. Otherwise, old_state will be freed once we get
-		 * ACK from NSS FW.
-		 */
-		old_state = true;
-		memcpy(&old_rbe, &nss_rbe[nss_id], sizeof (struct nss_ring_buffer_addr));
 	}
 
-	nss_rbe[nss_id].addr = addr;
-	nss_rbe[nss_id].nentries = nentry;
-	nss_rbe[nss_id].refcnt = 1;	/* Block other threads till we are done */
-	nss_rbe[nss_id].dma_addr = dma_addr;
-	mutex_unlock(&nss_log_mutex);
-
-	memset(&msg, 0, sizeof (struct nss_debug_interface_msg));
+	memset(&msg, 0, sizeof(struct nss_log_debug_interface_msg));
 	nss_cmn_msg_init(&msg.cm, NSS_DEBUG_INTERFACE, NSS_DEBUG_INTERFACE_TYPE_LOG_BUF_INIT,
-		sizeof(struct nss_debug_log_memory_msg), nss_debug_interface_event, NULL);
+		sizeof(struct nss_log_debug_memory_msg), nss_debug_interface_event, NULL);
 
 	dbg = &msg.msg.addr;
 	dbg->nentry = nentry;
@@ -491,80 +468,49 @@
 	msg_event = false;
 	status = nss_debug_interface_tx(nss_ctx, &msg);
 	if (status != NSS_TX_SUCCESS) {
+		mutex_unlock(&nss_log_mutex);
 		nss_warning("%p: Failed to send message to debug interface:%d\n", nss_ctx, status);
-		err = true;
-	} else {
-		int r;
+		goto fail;
+	}
 
-		/*
-		 * Wait for 5 seconds since this is a critical operation.
-		 */
-		r = wait_event_timeout(msg_wq, msg_event == true, 5 * HZ);
-		if (r == 0) {
-			nss_warning("%p: Timeout send message to debug interface\n", nss_ctx);
-			err = true;
-		} else if (msg_response != NSS_CMN_RESPONSE_ACK) {
-			nss_warning("%p: Response error for send message to debug interface:%d\n", nss_ctx, msg_response);
-			err = true;
-		}
+	/*
+	 * Wait for 5 seconds since this is a critical operation.
+	 * Mutex is not unlocked here because we do not want someone to acquire the mutex and use the logbuffer
+	 * while we are waiting message from NSS.
+	 */
+	if (!wait_event_timeout(msg_wq, msg_event, 5 * HZ)) {
+		mutex_unlock(&nss_log_mutex);
+		nss_warning("%p: Timeout send message to debug interface\n", nss_ctx);
+		goto fail;
+	}
+
+	if (msg_response != NSS_CMN_RESPONSE_ACK) {
+		mutex_unlock(&nss_log_mutex);
+		nss_warning("%p: Response error for send message to debug interface:%d\n", nss_ctx, msg_response);
+		goto fail;
 	}
 
 	/*
 	 * If we had to free the previous allocation for ring buffer.
 	 */
-	if (old_state == true) {
-		/*
-		 * If we didn't fail, then we must unmap and free previous dma buffer
-		 */
-		if (err == false) {
-			uint32_t old_size;
-
-			old_size = sizeof (struct nss_log_descriptor) +
-				(sizeof (struct nss_log_entry) * old_rbe.nentries);
-			dma_unmap_single(nss_ctx->dev, old_rbe.dma_addr, old_size, DMA_FROM_DEVICE);
-			kfree(old_rbe.addr);
-		} else {
-			/*
-			 * Restore the original dma buffer since we failed somewhere.
-			 */
-			mutex_lock(&nss_log_mutex);
-			memcpy(&nss_rbe[nss_id], &old_rbe, sizeof (struct nss_ring_buffer_addr));
-			mutex_unlock(&nss_log_mutex);
-			wake_up(&nss_log_wq);
-		}
-	} else {
-		/*
-		 * There was no logbuffer allocated from host side.
-		 */
-
-		/*
-		 * If there was error, then we need to reset back. Note that we are
-		 * still holding refcnt.
-		 */
-		if (err == true) {
-			mutex_lock(&nss_log_mutex);
-			nss_rbe[nss_id].addr = NULL;
-			nss_rbe[nss_id].nentries = 0;
-			nss_rbe[nss_id].refcnt = 0;
-			nss_rbe[nss_id].dma_addr = 0;
-			mutex_unlock(&nss_log_mutex);
-			wake_up(&nss_log_wq);
-		}
+	if (nss_rbe[nss_id].addr) {
+		uint32_t old_size;
+		old_size = sizeof(struct nss_log_descriptor) +
+			(sizeof(struct nss_log_entry) * nss_rbe[nss_id].nentries);
+		dma_unmap_single(nss_ctx->dev, nss_rbe[nss_id].dma_addr, old_size, DMA_FROM_DEVICE);
+		kfree(nss_rbe[nss_id].addr);
 	}
 
-	if (err == false) {
-		mutex_lock(&nss_log_mutex);
-		nss_rbe[nss_id].refcnt--;	/* we are done */
-		mutex_unlock(&nss_log_mutex);
-		wake_up(&nss_log_wq);
-		return true;
-	}
+	nss_rbe[nss_id].addr = addr;
+	nss_rbe[nss_id].nentries = nentry;
+	nss_rbe[nss_id].ref_cnt = 0;
+	nss_rbe[nss_id].dma_addr = dma_addr;
+	mutex_unlock(&nss_log_mutex);
+	wake_up(&nss_log_wq);
+	return true;
 
-fail1:
-	if (addr) {
-		dma_unmap_single(NULL, dma_addr, size, DMA_FROM_DEVICE);
-	}
-fail2:
+fail:
+	dma_unmap_single(NULL, dma_addr, size, DMA_FROM_DEVICE);
 	kfree(addr);
 	wake_up(&nss_log_wq);
 	return false;
@@ -590,7 +536,7 @@
 	}
 
 	if (nss_ctl_logbuf < 32) {
-		printk("Invalid NSS FW logbuffer size:%d (must be > 32)\n", nss_ctl_logbuf);
+		nss_warning("Invalid NSS FW logbuffer size:%d (must be > 32)\n", nss_ctl_logbuf);
 		nss_ctl_logbuf = 0;
 		return ret;
 	}
@@ -604,7 +550,7 @@
 			nss_warning("NSS logbuffer init failed with register handler:%d\n", core_status);
 		}
 
-		if (nss_debug_log_buffer_alloc(i, nss_ctl_logbuf) == false) {
+		if (!nss_debug_log_buffer_alloc(i, nss_ctl_logbuf)) {
 			nss_warning("%d: Failed to set debug log buffer on NSS core", i);
 		}
 	}