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

Commit 431c2266 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "diag: Create separate module for Diag-USB interaction"

parents 8bfc612c d3d930b1
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -2,4 +2,4 @@ obj-$(CONFIG_DIAG_CHAR) := diagchar.o
obj-$(CONFIG_DIAGFWD_BRIDGE_CODE) += diagfwd_bridge.o
obj-$(CONFIG_DIAGFWD_BRIDGE_CODE) += diagfwd_hsic.o
obj-$(CONFIG_DIAGFWD_BRIDGE_CODE) += diagfwd_smux.o
diagchar-objs := diagchar_core.o diagchar_hdlc.o diagfwd.o diagmem.o diagfwd_cntl.o diag_dci.o diag_masks.o diag_debugfs.o
diagchar-objs := diagchar_core.o diagchar_hdlc.o diagfwd.o diag_usb.o diagmem.o diagfwd_cntl.o diag_dci.o diag_masks.o diag_debugfs.o
+87 −23
Original line number Diff line number Diff line
@@ -21,11 +21,13 @@
#include "diagfwd_smux.h"
#include "diagmem.h"
#include "diag_dci.h"
#include "diag_usb.h"

#define DEBUG_BUF_SIZE	4096
static struct dentry *diag_dbgfs_dent;
static int diag_dbgfs_table_index;
static int diag_dbgfs_mempool_index;
static int diag_dbgfs_usbinfo_index;
static int diag_dbgfs_finished;
static int diag_dbgfs_dci_data_index;
static int diag_dbgfs_dci_finished;
@@ -526,14 +528,6 @@ static ssize_t diag_dbgfs_read_workpending(struct file *file,
						diag_notify_update_smd_work)),
		work_pending(&(driver->smd_dci[SENSORS_DATA].
						diag_notify_update_smd_work)));

#ifdef CONFIG_DIAG_OVER_USB
	ret += scnprintf(buf+ret, buf_size-ret,
		"diag_proc_hdlc_work: %d\n"
		"diag_read_work: %d\n",
		work_pending(&(driver->diag_proc_hdlc_work)),
		work_pending(&(driver->diag_read_work)));
#endif
	ret = simple_read_from_buffer(ubuf, count, ppos, buf, ret);

	kfree(buf);
@@ -675,6 +669,79 @@ static ssize_t diag_dbgfs_read_mempool(struct file *file, char __user *ubuf,
	return ret;
}

static ssize_t diag_dbgfs_read_usbinfo(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_usb_info *usb_info = NULL;

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

	buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
	if (ZERO_OR_NULL_PTR(buf)) {
		pr_err("diag: %s, Error allocating memory\n", __func__);
		return -ENOMEM;
	}

	buf_size = ksize(buf);
	bytes_remaining = buf_size;
	for (i = diag_dbgfs_usbinfo_index; i < NUM_DIAG_USB_DEV; i++) {
		usb_info = &diag_usb[i];
		if (!usb_info->enabled)
			continue;
		bytes_written = scnprintf(buf+bytes_in_buffer, bytes_remaining,
			"id: %d\n"
			"name: %s\n"
			"hdl: %p\n"
			"connected: %d\n"
			"enabled: %d\n"
			"mempool: %s\n"
			"read pending: %d\n"
			"read count: %lu\n"
			"write count: %lu\n"
			"read work pending: %d\n"
			"read done work pending: %d\n"
			"connect work pending: %d\n"
			"disconnect work pending: %d\n\n",
			usb_info->id,
			usb_info->name,
			usb_info->hdl,
			usb_info->connected,
			usb_info->enabled,
			DIAG_MEMPOOL_GET_NAME(usb_info->mempool),
			usb_info->read_pending,
			usb_info->read_cnt,
			usb_info->write_cnt,
			work_pending(&usb_info->read_work),
			work_pending(&usb_info->read_done_work),
			work_pending(&usb_info->connect_work),
			work_pending(&usb_info->disconnect_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_usbinfo_index = i+1;
	*ppos = 0;
	ret = simple_read_from_buffer(ubuf, count, ppos, buf, bytes_in_buffer);

	kfree(buf);
	return ret;
}

#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
static ssize_t diag_dbgfs_read_bridge(struct file *file, char __user *ubuf,
				    size_t count, loff_t *ppos)
@@ -724,13 +791,6 @@ static ssize_t diag_dbgfs_read_bridge(struct file *file, char __user *ubuf,
	bytes_in_buffer += bytes_written;
	bytes_remaining = buf_size - bytes_in_buffer;

	bytes_written = scnprintf(buf+bytes_in_buffer, bytes_remaining,
		"HSIC diag_disconnect_work: %d\n",
		work_pending(&(driver->diag_disconnect_work)));

	bytes_in_buffer += bytes_written;
	bytes_remaining = buf_size - bytes_in_buffer;

	for (i = 0; i < MAX_HSIC_DATA_CH; i++) {
		if (diag_hsic[i].hsic_inited) {
			/* Check if there is room to add another HSIC entry */
@@ -746,12 +806,9 @@ static ssize_t diag_dbgfs_read_bridge(struct file *file, char __user *ubuf,
			"hsic_suspend: %d\n"
			"in_busy_hsic_read_on_device: %d\n"
			"in_busy_hsic_write: %d\n"
			"HSIC write_len: %d\n"
			"num_hsic_buf_tbl_entries: %d\n"
			"HSIC usb_connected: %d\n"
			"HSIC diag_read_work: %d\n"
			"diag_read_hsic_work: %d\n"
			"diag_usb_read_complete_work: %d\n\n",
			"diag_read_hsic_work: %d\n\n",
			i,
			diag_hsic[i].hsic_ch,
			diag_hsic[i].hsic_inited,
@@ -760,12 +817,9 @@ static ssize_t diag_dbgfs_read_bridge(struct file *file, char __user *ubuf,
			diag_hsic[i].hsic_suspend,
			diag_hsic[i].in_busy_hsic_read_on_device,
			diag_hsic[i].in_busy_hsic_write,
			diag_bridge[i].write_len,
			diag_hsic[i].num_hsic_buf_tbl_entries,
			diag_bridge[i].usb_connected,
			work_pending(&(diag_bridge[i].diag_read_work)),
			work_pending(&(diag_hsic[i].diag_read_hsic_work)),
			work_pending(&(diag_bridge[i].usb_read_complete_work)));
			work_pending(&(diag_hsic[i].diag_read_hsic_work)));
			if (bytes_written > bytes_hsic_inited)
				bytes_hsic_inited = bytes_written;
		} else {
@@ -906,6 +960,10 @@ const struct file_operations diag_dbgfs_mempool_ops = {
	.read = diag_dbgfs_read_mempool,
};

const struct file_operations diag_dbgfs_usbinfo_ops = {
	.read = diag_dbgfs_read_usbinfo,
};

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

	entry = debugfs_create_file("usbinfo", 0444, diag_dbgfs_dent, 0,
				    &diag_dbgfs_usbinfo_ops);
	if (!entry)
		goto err;

	entry = debugfs_create_file("dci_stats", 0444, diag_dbgfs_dent, 0,
				    &diag_dbgfs_dcistats_ops);
	if (!entry)
@@ -966,6 +1029,7 @@ int diag_debugfs_init(void)

	diag_dbgfs_table_index = 0;
	diag_dbgfs_mempool_index = 0;
	diag_dbgfs_usbinfo_index = 0;
	diag_dbgfs_finished = 0;
	diag_dbgfs_dci_data_index = 0;
	diag_dbgfs_dci_finished = 0;
+447 −0
Original line number Diff line number Diff line
/* Copyright (c) 2014, 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
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <linux/slab.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/sched.h>
#include <linux/ratelimit.h>
#include <linux/workqueue.h>
#include <linux/diagchar.h>
#include <linux/delay.h>
#include <linux/kmemleak.h>
#ifdef CONFIG_DIAG_OVER_USB
#include <linux/usb/usbdiag.h>
#endif
#include "diag_usb.h"
#include "diagmem.h"

#define DIAG_USB_STRING_SZ	10

struct diag_usb_info diag_usb[NUM_DIAG_USB_DEV] = {
	{
		.id = DIAG_USB_LOCAL,
		.name = DIAG_LEGACY,
		.connected = 0,
		.enabled = 0,
		.mempool = POOL_TYPE_USB_APPS,
		.hdl = NULL,
		.ops = NULL,
		.read_buf = NULL,
		.read_ptr = NULL,
		.usb_wq = NULL,
		.read_cnt = 0,
		.write_cnt = 0,
		.read_pending = 0,
	},
#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
	{
		.id = DIAG_USB_MDM,
		.name = DIAG_MDM,
		.connected = 0,
		.enabled = 0,
		.mempool = POOL_TYPE_MDM_USB,
		.hdl = NULL,
		.ops = NULL,
		.read_buf = NULL,
		.read_ptr = NULL,
		.usb_wq = NULL,
		.read_cnt = 0,
		.write_cnt = 0,
		.read_pending = 0,
	},
	{
		.id = DIAG_USB_MDM2,
		.name = DIAG_MDM2,
		.connected = 0,
		.enabled = 0,
		.mempool = POOL_TYPE_MDM2_USB,
		.hdl = NULL,
		.ops = NULL,
		.read_buf = NULL,
		.read_ptr = NULL,
		.usb_wq = NULL,
		.read_cnt = 0,
		.write_cnt = 0,
		.read_pending = 0,
	},
	{
		.id = DIAG_USB_QSC,
		.name = DIAG_QSC,
		.connected = 0,
		.enabled = 0,
		.mempool = POOL_TYPE_QSC_USB,
		.hdl = NULL,
		.ops = NULL,
		.read_buf = NULL,
		.read_ptr = NULL,
		.usb_wq = NULL,
		.read_cnt = 0,
		.write_cnt = 0,
		.read_pending = 0,
	}
#endif
};

/*
 * This function is called asynchronously when USB is connected and
 * synchronously when Diag wants to connect to USB explicitly.
 */
static void usb_connect(struct diag_usb_info *ch)
{
	int err = 0;
	int num_write = 0;
	int num_read = 1; /* Only one read buffer for any USB channel */

	if (!ch)
		return;

	num_write = diag_mempools[ch->mempool].poolsize;
	err = usb_diag_alloc_req(ch->hdl, num_write, num_read);
	if (err) {
		pr_err("diag: Unable to allocate usb requests for %s, write: %d read: %d, err: %d\n",
		       ch->name, num_write, num_read, err);
		return;
	}

	if (ch->ops && ch->ops->open)
		ch->ops->open(ch->ctxt, DIAG_USB_MODE);
	/* As soon as we open the channel, queue a read */
	queue_work(ch->usb_wq, &(ch->read_work));
}

static void usb_connect_work_fn(struct work_struct *work)
{
	struct diag_usb_info *ch = container_of(work, struct diag_usb_info,
						connect_work);
	usb_connect(ch);
}

/*
 * This function is called asynchronously when USB is disconnected
 * and synchronously when Diag wants to disconnect from USB
 * explicitly.
 */
static void usb_disconnect(struct diag_usb_info *ch)
{
	if (ch && ch->ops && ch->ops->close)
		ch->ops->close(ch->ctxt, DIAG_USB_MODE);
}

static void usb_disconnect_work_fn(struct work_struct *work)
{
	struct diag_usb_info *ch = container_of(work, struct diag_usb_info,
						disconnect_work);
	usb_disconnect(ch);
}

static void usb_read_work_fn(struct work_struct *work)
{
	unsigned long flags;
	struct diag_request *req = NULL;
	struct diag_usb_info *ch = container_of(work, struct diag_usb_info,
						read_work);
	if (!ch)
		return;

	if (!ch->connected || !ch->enabled || ch->read_pending) {
		pr_debug_ratelimited("diag: Discarding USB read, ch: %s connected: %d, enabled: %d, pending: %d\n",
				     ch->name, ch->connected, ch->enabled,
				     ch->read_pending);
		return;
	}

	spin_lock_irqsave(&ch->lock, flags);
	req = ch->read_ptr;
	if (req) {
		ch->read_pending = 1;
		req->buf = ch->read_buf;
		req->length = USB_MAX_OUT_BUF;
		usb_diag_read(ch->hdl, req);
	} else {
		pr_err_ratelimited("diag: In %s invalid read req\n", __func__);
	}
	spin_unlock_irqrestore(&ch->lock, flags);
}

static void usb_read_done_work_fn(struct work_struct *work)
{
	struct diag_request *req = NULL;
	struct diag_usb_info *ch = container_of(work, struct diag_usb_info,
						read_done_work);
	if (!ch)
		return;

	/*
	 * USB is disconnected/Disabled before the previous read completed.
	 * Discard the packet and don't do any further processing.
	 */
	if (!ch->connected || !ch->enabled)
		return;

	req = ch->read_ptr;
	ch->read_cnt++;

	if (ch->ops && ch->ops->read_done && req->status >= 0)
		ch->ops->read_done(req->buf, req->actual, ch->ctxt);
}

static void diag_usb_write_done(struct diag_usb_info *ch,
				struct diag_request *req)
{
	int ctxt = 0;

	if (!ch || !req)
		return;

	ch->write_cnt++;
	ctxt = (int)(uintptr_t)req->context;
	if (ch->ops && ch->ops->write_done)
		ch->ops->write_done(req->buf, req->actual, ctxt, ch->ctxt);
	diagmem_free(driver, req, ch->mempool);
	queue_work(ch->usb_wq, &(ch->read_work));
}

static void diag_usb_notifier(void *priv, unsigned event,
			      struct diag_request *d_req)
{
	int id = 0;
	unsigned long flags;
	struct diag_usb_info *usb_info = NULL;

	id = (int)(uintptr_t)priv;
	if (id < 0 || id >= NUM_DIAG_USB_DEV)
		return;
	usb_info = &diag_usb[id];

	switch (event) {
	case USB_DIAG_CONNECT:
		spin_lock_irqsave(&usb_info->lock, flags);
		usb_info->connected = 1;
		spin_unlock_irqrestore(&usb_info->lock, flags);
		pr_info("diag: USB channel %s connected\n", usb_info->name);
		queue_work(usb_info->usb_wq,
			   &usb_info->connect_work);
		break;
	case USB_DIAG_DISCONNECT:
		spin_lock_irqsave(&usb_info->lock, flags);
		usb_info->connected = 0;
		spin_unlock_irqrestore(&usb_info->lock, flags);
		pr_info("diag: USB channel %s disconnected\n", usb_info->name);
		queue_work(usb_info->usb_wq,
			   &usb_info->disconnect_work);
		break;
	case USB_DIAG_READ_DONE:
		spin_lock_irqsave(&usb_info->lock, flags);
		usb_info->read_ptr = d_req;
		usb_info->read_pending = 0;
		spin_unlock_irqrestore(&usb_info->lock, flags);
		queue_work(usb_info->usb_wq,
			   &usb_info->read_done_work);
		break;
	case USB_DIAG_WRITE_DONE:
		diag_usb_write_done(usb_info, d_req);
		break;
	default:
		pr_err_ratelimited("diag: Unknown event from USB diag\n");
		break;
	}
}

int diag_usb_queue_read(int id)
{
	if (id < 0 || id >= NUM_DIAG_USB_DEV) {
		pr_err_ratelimited("diag: In %s, Incorrect id %d\n",
				   __func__, id);
		return -EINVAL;
	}
	queue_work(diag_usb[id].usb_wq, &(diag_usb[id].read_work));
	return 0;
}

int diag_usb_write(int id, unsigned char *buf, int len, int ctxt)
{
	int err = 0;
	struct diag_request *req = NULL;
	struct diag_usb_info *usb_info = NULL;

	if (id < 0 || id >= NUM_DIAG_USB_DEV) {
		pr_err_ratelimited("diag: In %s, Incorrect id %d\n",
				   __func__, id);
		return -EINVAL;
	}

	usb_info = &diag_usb[id];
	if (!usb_info->hdl || !usb_info->connected) {
		pr_debug_ratelimited("diag: USB ch %s is not connected\n",
				     usb_info->name);
		return -ENODEV;
	}

	req = diagmem_alloc(driver, sizeof(struct diag_request),
			    usb_info->mempool);
	if (!req) {
		/*
		 * This should never happen. It either means that we are
		 * trying to write more buffers than the max supported by
		 * this particualar diag USB channel at any given instance,
		 * or the previous write ptrs are stuck in the USB layer.
		 */
		pr_err_ratelimited("diag: In %s, cannot retrieve USB write ptrs for USB channel %s\n",
				   __func__, usb_info->name);
		return -ENOMEM;
	}

	req->buf = buf;
	req->length = len;
	req->context = (void *)(uintptr_t)ctxt;

	err = usb_diag_write(usb_info->hdl, req);
	if (err) {
		pr_err_ratelimited("diag: In %s, error writing to usb channel %s, err: %d\n",
				   __func__, usb_info->name, err);
		diagmem_free(driver, req, usb_info->mempool);
	}

	return err;
}

/*
 * This functions performs USB connect operations wrt Diag synchronously. It
 * doesn't translate to actual USB connect. This is used when Diag switches
 * logging to USB mode and wants to mimic USB connection.
 */
void diag_usb_connect_all(void)
{
	int i = 0;
	unsigned long flags;
	struct diag_usb_info *usb_info = NULL;

	for (i = 0; i < NUM_DIAG_USB_DEV; i++) {
		usb_info = &diag_usb[i];
		if (!usb_info->enabled)
			continue;
		spin_lock_irqsave(&usb_info->lock, flags);
		usb_info->connected = 1;
		spin_unlock_irqrestore(&usb_info->lock, flags);
		usb_connect(usb_info);
	}
}

/*
 * This functions performs USB disconnect operations wrt Diag synchronously.
 * It doesn't translate to actual USB disconnect. This is used when Diag
 * switches logging from USB mode and want to mimic USB disconnect.
 */
void diag_usb_disconnect_all(void)
{
	int i = 0;
	unsigned long flags;
	struct diag_usb_info *usb_info = NULL;

	for (i = 0; i < NUM_DIAG_USB_DEV; i++) {
		usb_info = &diag_usb[i];
		if (!usb_info->enabled)
			continue;
		spin_lock_irqsave(&usb_info->lock, flags);
		usb_info->connected = 0;
		spin_unlock_irqrestore(&usb_info->lock, flags);
		usb_disconnect(usb_info);
	}
}

int diag_usb_register(int id, int ctxt, struct diag_mux_ops *ops)
{
	struct diag_usb_info *ch = NULL;
	unsigned char wq_name[DIAG_USB_NAME_SZ + DIAG_USB_STRING_SZ];

	if (id < 0 || id >= NUM_DIAG_USB_DEV) {
		pr_err("diag: Unable to register with USB, id: %d\n", id);
		return -EIO;
	}

	if (!ops) {
		pr_err("diag: Invalid operations for USB\n");
		return -EIO;
	}

	ch = &diag_usb[id];
	ch->ops = ops;
	ch->ctxt = ctxt;
	spin_lock_init(&ch->lock);
	ch->read_buf = kzalloc(USB_MAX_OUT_BUF, GFP_KERNEL);
	if (!ch->read_buf)
		goto err;
	ch->read_ptr = kzalloc(sizeof(struct diag_request), GFP_KERNEL);
	if (!ch->read_ptr)
		goto err;
	diagmem_init(driver, ch->mempool);
	INIT_WORK(&(ch->read_work), usb_read_work_fn);
	INIT_WORK(&(ch->read_done_work), usb_read_done_work_fn);
	INIT_WORK(&(ch->connect_work), usb_connect_work_fn);
	INIT_WORK(&(ch->disconnect_work), usb_disconnect_work_fn);
	strlcpy(wq_name, "DIAG_USB_", DIAG_USB_STRING_SZ);
	strlcat(wq_name, ch->name, sizeof(ch->name));
	ch->usb_wq = create_singlethread_workqueue(wq_name);
	if (!ch->usb_wq)
		goto err;
	ch->hdl = usb_diag_open(ch->name, (void *)(uintptr_t)id,
				diag_usb_notifier);
	if (IS_ERR(ch->hdl)) {
		pr_err("diag: Unable to open USB channel %s\n", ch->name);
		goto err;
	}
	ch->enabled = 1;
	pr_debug("diag: Successfully registered USB %s\n", ch->name);
	return 0;

err:
	if (ch->usb_wq)
		destroy_workqueue(ch->usb_wq);
	kfree(ch->read_ptr);
	kfree(ch->read_buf);
	return -ENOMEM;
}

void diag_usb_exit(int id)
{
	struct diag_usb_info *ch = NULL;

	if (id < 0 || id >= NUM_DIAG_USB_DEV) {
		pr_err("diag: In %s, incorrect id %d\n", __func__, id);
		return;
	}

	ch = &diag_usb[id];
	ch->ops = NULL;
	ch->connected = 0;
	ch->enabled = 0;
	ch->ctxt = 0;
	ch->read_cnt = 0;
	ch->write_cnt = 0;
	ch->read_pending = 0;
	diagmem_exit(driver, ch->mempool);
	ch->mempool = 0;
	if (ch->hdl) {
		usb_diag_close(ch->hdl);
		ch->hdl = NULL;
	}
	if (ch->usb_wq)
		destroy_workqueue(ch->usb_wq);
	kfree(ch->read_ptr);
	ch->read_ptr = NULL;
	kfree(ch->read_buf);
	ch->read_buf = NULL;
}
+105 −0
Original line number Diff line number Diff line
/* Copyright (c) 2014, 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
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#ifndef DIAGUSB_H
#define DIAGUSB_H

#ifdef CONFIG_DIAG_OVER_USB
#include <linux/usb/usbdiag.h>
#endif
#include "diagchar.h"

#define DIAG_USB_LOCAL		0
#define DIAG_USB_LOCAL_LAST	1
#define DIAG_USB_BRIDGE_BASE	DIAG_USB_LOCAL_LAST
#define DIAG_USB_MDM		(DIAG_USB_BRIDGE_BASE)
#define DIAG_USB_MDM2		(DIAG_USB_BRIDGE_BASE + 1)
#define DIAG_USB_QSC		(DIAG_USB_BRIDGE_BASE + 2)
#define DIAG_USB_BRIDGE_LAST	(DIAG_USB_BRIDGE_BASE + 3)

#ifndef CONFIG_DIAGFWD_BRIDGE_CODE
#define NUM_DIAG_USB_DEV	DIAG_USB_LOCAL_LAST
#else
#define NUM_DIAG_USB_DEV	DIAG_USB_BRIDGE_LAST
#endif

#define DIAG_USB_NAME_SZ	24
#define DIAG_USB_GET_NAME(x)	(diag_usb[x].name)

#define DIAG_USB_MODE		0

struct diag_mux_ops {
	int (*open)(int id, int mode);
	int (*close)(int id, int mode);
	int (*read_done)(unsigned char *buf, int len, int id);
	int (*write_done)(unsigned char *buf, int len, int buf_ctx,
			  int id);
};

struct diag_usb_info {
	int id;
	int ctxt;
	char name[DIAG_USB_NAME_SZ];
	int connected;
	int enabled;
	int mempool;
	unsigned long read_cnt;
	unsigned long write_cnt;
	spinlock_t lock;
	struct usb_diag_ch *hdl;
	struct diag_mux_ops *ops;
	int read_pending;
	unsigned char *read_buf;
	struct diag_request *read_ptr;
	struct work_struct read_work;
	struct work_struct read_done_work;
	struct work_struct connect_work;
	struct work_struct disconnect_work;
	struct workqueue_struct *usb_wq;
};

#ifdef CONFIG_DIAG_OVER_USB
extern struct diag_usb_info diag_usb[NUM_DIAG_USB_DEV];
int diag_usb_register(int id, int ctxt, struct diag_mux_ops *ops);
int diag_usb_queue_read(int id);
int diag_usb_write(int id, unsigned char *buf, int len, int ctxt);
void diag_usb_connect_all(void);
void diag_usb_disconnect_all(void);
void diag_usb_exit(int id);
#else
int diag_usb_register(int id, int ctxt, struct diag_mux_ops *ops)
{
	return 0;
}
int diag_usb_queue_read(int id)
{
	return 0;
}
int diag_usb_write(int id, unsigned char *buf, int len, int ctxt)
{
	return 0;
}
void diag_usb_connect_all(void)
{
	return;
}
void diag_usb_disconnect_all(void)
{
	return;
}
void diag_usb_exit(int id)
{
	return;
}
#endif

#endif
+0 −14
Original line number Diff line number Diff line
@@ -403,14 +403,12 @@ struct diagchar_dev {
	struct diag_smd_info smd_dci_cmd[NUM_SMD_DCI_CMD_CHANNELS];
	int rcvd_feature_mask[NUM_SMD_CONTROL_CHANNELS];
	int separate_cmdrsp[NUM_SMD_CONTROL_CHANNELS];
	unsigned char *usb_buf_out;
	uint8_t peripheral_feature[NUM_SMD_CONTROL_CHANNELS][FEATURE_MASK_LEN];
	uint8_t mask_centralization[NUM_SMD_CONTROL_CHANNELS];
	unsigned char *apps_rsp_buf;
	unsigned char *user_space_data_buf;
	/* buffer for updating mask to peripherals */
	unsigned char *buf_feature_mask_update;
	int read_len_legacy;
	struct mutex diag_hdlc_mutex;
	unsigned char *hdlc_buf;
	unsigned hdlc_count;
@@ -426,14 +424,8 @@ struct diagchar_dev {
	struct workqueue_struct *diag_real_time_wq;
#ifdef CONFIG_DIAG_OVER_USB
	int usb_connected;
	struct usb_diag_ch *legacy_ch;
	struct work_struct diag_proc_hdlc_work;
	struct work_struct diag_read_work;
	struct work_struct diag_usb_connect_work;
	struct work_struct diag_usb_disconnect_work;
#endif
	struct workqueue_struct *diag_wq;
	struct workqueue_struct *diag_usb_wq;
	struct work_struct diag_drain_work;
	struct workqueue_struct *diag_cntl_wq;
	uint8_t log_on_demand_support;
@@ -443,7 +435,6 @@ struct diagchar_dev {
	uint8_t *dci_pkt_buf; /* For Apps DCI packets */
	uint32_t dci_pkt_length;
	int in_busy_dcipktdata;
	struct diag_request *usb_read_ptr;
	int logging_mode;
	int mask_check;
	int logging_process_id;
@@ -465,11 +456,6 @@ struct diagchar_dev {
	uint16_t num_event_id[NUM_SMD_CONTROL_CHANNELS];
	uint32_t num_equip_id[NUM_SMD_CONTROL_CHANNELS];
	uint32_t max_ssid_count[NUM_SMD_CONTROL_CHANNELS];
#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
	/* common for all bridges */
	struct work_struct diag_connect_work;
	struct work_struct diag_disconnect_work;
#endif
};

extern struct diag_bridge_dev *diag_bridge;
Loading