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

Commit 75c91e18 authored by Sreelakshmi Gownipalli's avatar Sreelakshmi Gownipalli Committed by Gerrit - the friendly Code Review server
Browse files

diag: Add diag over pcie support



Add support for diag communication with host over pcie as an option.

Change-Id: I4d7785093344b4670e8a45cc55ab53c8671f0d40
Signed-off-by: default avatarSreelakshmi Gownipalli <sgownipa@codeaurora.org>
parent ec9d62e9
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -34,6 +34,17 @@ config DIAGFWD_BRIDGE_CODE
	  become available, this bridge driver enables DIAG traffic over MHI
	  and SMUX.

config DIAG_OVER_PCIE
	bool "Enable Diag traffic to go over PCIE"
	depends on DIAG_CHAR
	depends on MSM_MHI
	help
	  Diag over PCIE enables sending diag traffic over PCIE endpoint when
	  pcie is available. Diag PCIE channels should be configured
	  and connected to use the transport. If PCIE is not configured
	  diag will switch to usb mode and diag traffic will be routed
	  over USB.

config DIAG_USES_SMD
	bool "Enable diag internal interface over SMD"
	depends on DIAG_CHAR && MSM_SMD
+1 −0
Original line number Diff line number Diff line
@@ -3,5 +3,6 @@ obj-$(CONFIG_DIAGFWD_BRIDGE_CODE) += diagfwd_bridge.o
obj-$(CONFIG_USB_QCOM_DIAG_BRIDGE) += diagfwd_hsic.o
obj-$(CONFIG_USB_QCOM_DIAG_BRIDGE) += diagfwd_smux.o
obj-$(CONFIG_MSM_MHI) += diagfwd_mhi.o
obj-$(CONFIG_DIAG_OVER_PCIE) += diag_pcie.o
obj-$(CONFIG_DIAG_USES_SMD) += diagfwd_smd.o
diagchar-objs := diagchar_core.o diagchar_hdlc.o diagfwd.o diagfwd_glink.o diagfwd_peripheral.o diagfwd_socket.o diag_mux.o diag_memorydevice.o diag_usb.o diagmem.o diagfwd_cntl.o diag_dci.o diag_masks.o diag_debugfs.o
+79 −0
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@
#include "diagfwd_smd.h"
#include "diagfwd_socket.h"
#include "diagfwd_glink.h"
#include "diag_pcie.h"
#include "diag_debugfs.h"
#include "diag_ipc_logging.h"

@@ -43,6 +44,9 @@ static struct dentry *diag_dbgfs_dent;
static int diag_dbgfs_table_index;
static int diag_dbgfs_mempool_index;
static int diag_dbgfs_usbinfo_index;
#ifdef CONFIG_DIAG_OVER_PCIE
static int diag_dbgfs_pcieinfo_index;
#endif
static int diag_dbgfs_smdinfo_index;
static int diag_dbgfs_socketinfo_index;
static int diag_dbgfs_glinkinfo_index;
@@ -481,6 +485,68 @@ static ssize_t diag_dbgfs_read_usbinfo(struct file *file, char __user *ubuf,
	return ret;
}

#ifdef CONFIG_DIAG_OVER_PCIE
static ssize_t diag_dbgfs_read_pcieinfo(struct file *file, char __user *ubuf,
				       size_t count, loff_t *ppos)
{
	char *buf = NULL;
	int ret = 0;
	int i = 0;
	unsigned int buf_size;
	unsigned int bytes_remaining = 0;
	unsigned int bytes_written = 0;
	unsigned int bytes_in_buffer = 0;
	struct diag_pcie_info *pcie_info = NULL;
	unsigned int temp_size = sizeof(char) * DEBUG_BUF_SIZE;

	if (diag_dbgfs_pcieinfo_index >= NUM_DIAG_PCIE_DEV) {
		/* Done. Reset to prepare for future requests */
		diag_dbgfs_pcieinfo_index = 0;
		return 0;
	}

	buf = kzalloc(temp_size, GFP_KERNEL);
	if (ZERO_OR_NULL_PTR(buf))
		return -ENOMEM;

	buf_size = ksize(buf);
	bytes_remaining = buf_size;
	for (i = diag_dbgfs_pcieinfo_index; i < NUM_DIAG_PCIE_DEV; i++) {
		pcie_info = &diag_pcie[i];
		bytes_written = scnprintf(buf+bytes_in_buffer, bytes_remaining,
			"id: %d\n"
			"name: %s\n"
			"in channel hdl: %pK\n"
			"out channel hdl: %pK\n"
			"mempool: %s\n"
			"read count: %lu\n"
			"write count: %lu\n"
			"read work pending: %d\n",
			pcie_info->id,
			pcie_info->name,
			pcie_info->in_handle,
			pcie_info->out_handle,
			DIAG_MEMPOOL_GET_NAME(pcie_info->mempool),
			pcie_info->read_cnt,
			pcie_info->write_cnt,
			work_pending(&pcie_info->read_work));
		bytes_in_buffer += bytes_written;

		/* Check if there is room to add another table entry */
		bytes_remaining = buf_size - bytes_in_buffer;

		if (bytes_remaining < bytes_written)
			break;
	}
	diag_dbgfs_pcieinfo_index = i+1;
	*ppos = 0;
	ret = simple_read_from_buffer(ubuf, count, ppos, buf, bytes_in_buffer);

	kfree(buf);
	return ret;
}
#endif

#ifdef CONFIG_DIAG_USES_SMD
static ssize_t diag_dbgfs_read_smdinfo(struct file *file, char __user *ubuf,
				       size_t count, loff_t *ppos)
@@ -1080,6 +1146,12 @@ const struct file_operations diag_dbgfs_usbinfo_ops = {
	.read = diag_dbgfs_read_usbinfo,
};

#ifdef CONFIG_DIAG_OVER_PCIE
const struct file_operations diag_dbgfs_pcieinfo_ops = {
	.read = diag_dbgfs_read_pcieinfo,
};
#endif

const struct file_operations diag_dbgfs_dcistats_ops = {
	.read = diag_dbgfs_read_dcistats,
};
@@ -1139,6 +1211,13 @@ int diag_debugfs_init(void)
	if (!entry)
		goto err;

#ifdef CONFIG_DIAG_OVER_PCIE
	entry = debugfs_create_file("pcieinfo", 0444, diag_dbgfs_dent, 0,
				    &diag_dbgfs_pcieinfo_ops);
	if (!entry)
		goto err;
#endif

	entry = debugfs_create_file("dci_stats", 0444, diag_dbgfs_dent, 0,
				    &diag_dbgfs_dcistats_ops);
	if (!entry)
+114 −10
Original line number Diff line number Diff line
/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -27,12 +27,20 @@
#include "diag_mux.h"
#include "diag_usb.h"
#include "diag_memorydevice.h"
#include "diag_pcie.h"
#include "diagfwd_peripheral.h"
#include "diag_ipc_logging.h"

#ifdef CONFIG_DIAG_OVER_PCIE
#define diag_mux_register_ops diag_pcie_register_ops
#else
#define diag_mux_register_ops diag_usb_register_ops
#endif

struct diag_mux_state_t *diag_mux;
static struct diag_logger_t usb_logger;
static struct diag_logger_t md_logger;
static struct diag_logger_t pcie_logger;

static struct diag_logger_ops usb_log_ops = {
	.open = diag_usb_connect_all,
@@ -50,6 +58,16 @@ static struct diag_logger_ops md_log_ops = {
	.close_peripheral = diag_md_close_peripheral,
};

#ifdef CONFIG_DIAG_OVER_PCIE
static struct diag_logger_ops pcie_log_ops = {
	.open = diag_pcie_connect_all,
	.close = diag_pcie_disconnect_all,
	.queue_read = NULL,
	.write = diag_pcie_write,
	.close_peripheral = NULL
};
#endif

int diag_mux_init(void)
{
	diag_mux = kzalloc(sizeof(struct diag_mux_state_t),
@@ -64,16 +82,29 @@ int diag_mux_init(void)
	md_logger.mode = DIAG_MEMORY_DEVICE_MODE;
	md_logger.log_ops = &md_log_ops;
	diag_md_init();

#ifdef CONFIG_DIAG_OVER_PCIE
	pcie_logger.mode = DIAG_PCIE_MODE;
	pcie_logger.log_ops = &pcie_log_ops;
	diag_mux->pcie_ptr = &pcie_logger;
#endif
	/*
	 * Set USB logging as the default logger. This is the mode
	 * Diag should be in when it initializes.
	 */
	diag_mux->usb_ptr = &usb_logger;
	diag_mux->md_ptr = &md_logger;
	switch (driver->transport_set) {
	case DIAG_ROUTE_TO_PCIE:
		diag_mux->logger = &pcie_logger;
		diag_mux->mode = DIAG_PCIE_MODE;
		break;
	case DIAG_ROUTE_TO_USB:
	default:
		diag_mux->logger = &usb_logger;
	diag_mux->mux_mask = 0;
		diag_mux->mode = DIAG_USB_MODE;
		break;
	}
	diag_mux->mux_mask = 0;
	return 0;
}

@@ -82,7 +113,8 @@ void diag_mux_exit(void)
	kfree(diag_mux);
}

int diag_mux_register(int proc, int ctx, struct diag_mux_ops *ops)
#ifdef CONFIG_DIAG_OVER_PCIE
int diag_pcie_register_ops(int proc, int ctx, struct diag_mux_ops *ops)
{
	int err = 0;

@@ -92,7 +124,12 @@ int diag_mux_register(int proc, int ctx, struct diag_mux_ops *ops)
	if (proc < 0 || proc >= NUM_MUX_PROC)
		return 0;

	/* Register with USB logger */
	pcie_logger.ops[proc] = ops;
	err = diag_pcie_register(proc, ctx, ops);
	if (err) {
		driver->transport_set == DIAG_ROUTE_TO_USB;
		diag_mux->logger = &usb_logger;
		diag_mux->mode = DIAG_USB_MODE;
		usb_logger.ops[proc] = ops;
		err = diag_usb_register(proc, ctx, ops);
		if (err) {
@@ -100,7 +137,44 @@ int diag_mux_register(int proc, int ctx, struct diag_mux_ops *ops)
					   proc, err);
			return err;
		}
		pr_err("diag: MUX: unable to register pcie operations for proc: %d, err: %d\n",
			proc, err);
	}
	return 0;
}
#else
int diag_usb_register_ops(int proc, int ctx, struct diag_mux_ops *ops)
{
	int err = 0;

	if (!ops)
		return -EINVAL;

	if (proc < 0 || proc >= NUM_MUX_PROC)
		return 0;
	usb_logger.ops[proc] = ops;
	err = diag_usb_register(proc, ctx, ops);
	if (err) {
		pr_err("diag: MUX: unable to register usb operations for proc: %d, err: %d\n",
		       proc, err);
		return err;
	}
	return 0;
}
#endif

int diag_mux_register(int proc, int ctx, struct diag_mux_ops *ops)
{
	int err = 0;

	if (!ops)
		return -EINVAL;

	if (proc < 0 || proc >= NUM_MUX_PROC)
		return 0;
	err = diag_mux_register_ops(proc, ctx, ops);
	if (err)
		return err;
	md_logger.ops[proc] = ops;
	err = diag_md_register(proc, ctx, ops);
	if (err) {
@@ -150,10 +224,19 @@ int diag_mux_write(int proc, unsigned char *buf, int len, int ctx)
		return -EINVAL;
	}

	if (MD_PERIPHERAL_MASK(peripheral) & diag_mux->mux_mask)
	if (MD_PERIPHERAL_MASK(peripheral) & diag_mux->mux_mask) {
		logger = diag_mux->md_ptr;
	else
	} else {
		switch (driver->transport_set) {
		case DIAG_ROUTE_TO_PCIE:
			logger = diag_mux->pcie_ptr;
			break;
		case DIAG_ROUTE_TO_USB:
		default:
			logger = diag_mux->usb_ptr;
			break;
		}
	}

	if (logger && logger->log_ops && logger->log_ops->write)
		return logger->log_ops->write(proc, buf, len, ctx);
@@ -201,6 +284,7 @@ int diag_mux_switch_logging(int *req_mode, int *peripheral_mask)
	}

	switch (*req_mode) {
	case DIAG_PCIE_MODE:
	case DIAG_USB_MODE:
		new_mask = ~(*peripheral_mask) & diag_mux->mux_mask;
		if (new_mask != DIAG_CON_NONE)
@@ -219,6 +303,16 @@ int diag_mux_switch_logging(int *req_mode, int *peripheral_mask)
	}

	switch (diag_mux->mode) {
	case DIAG_PCIE_MODE:
		if (*req_mode == DIAG_MEMORY_DEVICE_MODE) {
			diag_mux->pcie_ptr->log_ops->close();
			diag_mux->logger = diag_mux->md_ptr;
			diag_mux->md_ptr->log_ops->open();
		} else if (*req_mode == DIAG_MULTI_MODE) {
			diag_mux->md_ptr->log_ops->open();
			diag_mux->logger = NULL;
		}
		break;
	case DIAG_USB_MODE:
		if (*req_mode == DIAG_MEMORY_DEVICE_MODE) {
			diag_mux->usb_ptr->log_ops->close();
@@ -234,7 +328,14 @@ int diag_mux_switch_logging(int *req_mode, int *peripheral_mask)
			diag_mux->md_ptr->log_ops->close();
			diag_mux->logger = diag_mux->usb_ptr;
			diag_mux->usb_ptr->log_ops->open();
		} else if (*req_mode == DIAG_PCIE_MODE) {
			diag_mux->md_ptr->log_ops->close();
			diag_mux->logger = diag_mux->pcie_ptr;
			diag_mux->pcie_ptr->log_ops->open();
		} else if (*req_mode == DIAG_MULTI_MODE) {
			if (driver->transport_set == DIAG_ROUTE_TO_PCIE)
				diag_mux->pcie_ptr->log_ops->open();
			else
				diag_mux->usb_ptr->log_ops->open();
			diag_mux->logger = NULL;
		}
@@ -243,6 +344,9 @@ int diag_mux_switch_logging(int *req_mode, int *peripheral_mask)
		if (*req_mode == DIAG_USB_MODE) {
			diag_mux->md_ptr->log_ops->close();
			diag_mux->logger = diag_mux->usb_ptr;
		} else if (*req_mode == DIAG_PCIE_MODE) {
			diag_mux->md_ptr->log_ops->close();
			diag_mux->logger = diag_mux->pcie_ptr;
		} else if (*req_mode == DIAG_MEMORY_DEVICE_MODE) {
			diag_mux->usb_ptr->log_ops->close();
			diag_mux->logger = diag_mux->md_ptr;
+6 −1
Original line number Diff line number Diff line
/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2014-2016, 2018 The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -17,6 +17,7 @@ struct diag_mux_state_t {
	struct diag_logger_t *logger;
	struct diag_logger_t *usb_ptr;
	struct diag_logger_t *md_ptr;
	struct diag_logger_t *pcie_ptr;
	unsigned int mux_mask;
	unsigned int mode;
};
@@ -33,6 +34,7 @@ struct diag_mux_ops {
#define DIAG_MEMORY_DEVICE_MODE		1
#define DIAG_NO_LOGGING_MODE		2
#define DIAG_MULTI_MODE			3
#define DIAG_PCIE_MODE		4

#define DIAG_MUX_LOCAL		0
#define DIAG_MUX_LOCAL_LAST	1
@@ -73,4 +75,7 @@ int diag_mux_close_peripheral(int proc, uint8_t peripheral);
int diag_mux_open_all(struct diag_logger_t *logger);
int diag_mux_close_all(void);
int diag_mux_switch_logging(int *new_mode, int *peripheral_mask);
int diag_pcie_register_ops(int proc, int ctx, struct diag_mux_ops *ops);
int diag_usb_register_ops(int proc, int ctx, struct diag_mux_ops *ops);
int diag_mux_register_ops(int proc, int ctx, struct diag_mux_ops *ops);
#endif
Loading