/* only send UIH from APPs */
int ts27010_uart_uih_send(struct ts0710_con *ts0710, u8 *data, u32 len)
{
	int ret = -EIO;
	u8 dlci;
#ifdef TS27010_UART_RETRAN
	u8 index;
#endif
	FUNC_ENTER();

	mux_print(MSG_MSGDUMP, "will send UIH frame %d bytes\n", len);
#ifdef DUMP_FRAME
	if (g_mux_uart_dump_frame)
		mux_uart_hexdump(MSG_ERROR, "send UIH frame",
			__func__, __LINE__, data, len);
	else
		mux_uart_hexdump(MSG_MSGDUMP, "send UIH frame",
			__func__, __LINE__, data, len);
#endif

#ifdef UART_LOOP
	return ts27010_uart_uih_send_loop(ts0710, data, len);
#endif

#ifdef MUX_UART_LOGGER
	ts27010_mux_uart_logger_logdata(g_mux_uart_logger, data, len, 1);
#endif

	/* seems bellow state checking is unneccessary */
	dlci = *(data + ADDRESS_OFFSET) >> 2;
	if (ts0710->dlci[dlci].state == FLOW_STOPPED) {
		mux_print(MSG_WARNING, "Flow stopped on DLCI: %d\n", dlci);
		return -EBUSY;
	} else if (ts0710->dlci[dlci].state != CONNECTED) {
		mux_print(MSG_WARNING, "DLCI %d not connected\n", dlci);
		return -ENODEV;
	}

#ifdef TS27010_UART_RETRAN
	index = ts27010_slidewindo_store(s_slide_window, data, len);
	if (0xFF == index) {/* slide window is full, or get signal */
		/* TODO: trigger a panic or reset BP? */
		mux_print(MSG_ERROR, "slide window is full, block sending... "
			"should I report a panic?\n");
		return -EBUSY;
	}
	ret = ts27010_uart_driver_send(data, len, &s_mux_resend_lock);
	ts27010_slidewindow_lock(s_slide_window);
	ts27010_mod_retran_timer(
		ts27010_slidewindow_peek(s_slide_window, index));
	ts27010_slidewindow_unlock(s_slide_window);
	ts27010_clear_timer_para(s_timer_para, index);
#else
	ret = ts27010_uart_driver_send(data, len, NULL);
#endif

	FUNC_EXIT();
	return ret;
}
Esempio n. 2
0
int ts27010_create_network(struct dlci_struct *dlci, struct ts27010_netconfig *nc)
{
	char *netname;
	int retval = 0;
	struct net_device *net;
	struct ts27010_mux_net *mux_net;

	mux_print(MSG_DEBUG, "create network interface\n");

	netname = "pdp_ip%d";
	if (nc->if_name[0] != '\0')
		netname = nc->if_name;
	net = alloc_netdev(sizeof(struct ts27010_mux_net),
		netname,
		ts27010_mux_net_init);
	if (!net) {
		mux_print(MSG_ERROR, "alloc_netdev failed\n");
		retval = -ENOMEM;
		goto error_ret;
	}
	mux_print(MSG_DEBUG, "register netdev\n");
	mux_print(MSG_MSGDUMP, "net device address %x \n", net);
	mux_print(MSG_DEBUG, "net device mtu %d \n", net->mtu);

	retval = register_netdev(net);
	if (retval) {
		mux_print(MSG_ERROR, "network register fail %d\n", retval);
		free_netdev(net);
		goto error_ret;
	}
	dlci->net = net;
	mux_net = (struct ts27010_mux_net *)netdev_priv(net);
	mux_net->dlci = dlci;
#ifdef ENABLE_MUX_NET_KREF_FEATURE
	kref_init(&mux_net->ref);
#endif
	strncpy(nc->if_name, net->name, IFNAMSIZ); /* return net name */

	skb_queue_head_init(&mux_net->txhead);
	mutex_init(&mux_net->net_wq_lock);
	mux_print(MSG_LIGHT, "[WQ] create_workqueue\n");
	mux_net->net_wq = create_singlethread_workqueue(net->name);
	if (!mux_net->net_wq) {
		mux_print(MSG_ERROR, "[WQ] Fail to open WQ\n");
		unregister_netdev(net);
		free_netdev(net);
		retval = -1;
		goto error_ret;
	}
	mux_print(MSG_LIGHT, "[WQ] INIT_WORK\n");
	INIT_DELAYED_WORK(&mux_net->net_work, ts27010_mux_net_tx_work);

	return net->ifindex;	/* return network index */

error_ret:
	return retval;
}
void ts27010_tty_usb_dump_io(void)
{
	int i;
	for (i = 0; i < TS0710_MAX_MUX; i++) {
		mux_print(MSG_ERROR,
			"(%d) refcount: %d, sent: %d, recv: %d, back: %d\n",
			i, atomic_read(&s_td->chan[i].ref_count),
			s_td->chan[i].sent_size, s_td->chan[i].recv_size,
			s_td->chan[i].back_size);
	}
	mux_print(MSG_ERROR, "Total writen size: %d, prot: %d, "
		"total read size: %d\n",
		s_nWriteTotal, s_nWriteProt, s_nReadTotal);
	mux_print(MSG_ERROR, "Total writen count: %d, recved: %d, back: %d\n",
		s_nWriteCount, s_nRecvCount, s_nBackCount);
}
/*
* This function only be used for sending MUX control frame.
*/
int ts27010_uart_control_send(struct ts0710_con *ts0710, u8 *buf, u32 len)
{
	int ret = -EIO;
	FUNC_ENTER();

#ifdef DUMP_FRAME
	if (g_mux_uart_dump_frame)
		mux_uart_hexdump(MSG_ERROR, "send control frame",
			__func__, __LINE__, buf, len);
	else
		mux_uart_hexdump(MSG_MSGDUMP, "send control frame",
			__func__, __LINE__, buf, len);
#endif

#ifdef UART_LOOP
	return ts27010_uart_control_send_loop(ts0710, buf, len);
#endif

#ifdef MUX_UART_LOGGER
	ts27010_mux_uart_logger_logdata(g_mux_uart_logger, buf, len, 1);
#endif
	ret = ts27010_ldisc_uart_send(ts27010mux_uart_tty, buf, len);
	if (ret != len) {
		mux_print(MSG_ERROR, "ldisc send error %d(%d)\n", ret, len);
		ret = -EIO;
	}

	FUNC_EXIT();
	return ret;
}
Esempio n. 5
0
static void net_free(struct kref *ref)
{
	struct ts27010_mux_net *mux_net;
	struct dlci_struct *dlci;
	mux_print(MSG_ERROR, "net_free+\n", dlci->net);

	mux_net = container_of(ref, struct ts27010_mux_net, ref);
	dlci = mux_net->dlci;

	if (dlci->net) {
		unregister_netdev(dlci->net);
		dlci_net_free(dlci);
		mux_print(MSG_ERROR, "net was freed~\n");
	}
	mux_print(MSG_ERROR, "net_free-\n", dlci->net);
}
static int ts27010_uart_driver_send(
	u8 *data, u32 len, struct wake_lock *mux_resend_lock)
{
	int ret;
	FUNC_ENTER();

	ret = ts27010_ldisc_uart_send(ts27010mux_uart_tty, data, len);
	if (ret < 0) {
		mux_print(MSG_ERROR, "pkt write error %d\n", ret);
		ret = -EIO;
	} else if (ret != len) {
		mux_print(MSG_ERROR, "short write %d < %d\n", ret, len);
		ret = -EIO;
	}
	FUNC_EXIT();
	return ret;
}
static void transfer_timeout(unsigned long para)
{
	FUNC_ENTER();
	mux_print(MSG_INFO,
		"transfer_timeout, para= %ld, slide_window.head=%d, "
		"tail=%d, jiffies: %lu\n",
		para, ts27010_slidewindow_head(s_slide_window),
		ts27010_slidewindow_tail(s_slide_window), jiffies);

	if (para >= SLIDE_WINDOWS_SIZE_AP) {
		mux_print(MSG_ERROR, "illegal para: %ld", para);
		return;
	}
	ts27010_inc_timer_para(s_timer_para, para);
	ts27010_sched_retran(s_timer_para);

	FUNC_EXIT();
}
Esempio n. 8
0
static int ts27010_mux_net_start_xmit(struct sk_buff *skb,
										struct net_device *net)
{
	FUNC_ENTER();

	struct ts27010_mux_net *mux_net = (struct ts27010_mux_net *)netdev_priv(net);
	struct dlci_struct *dlci = mux_net->dlci;
	//struct sk_buff_head skb_list;
#ifdef ENABLE_MUX_NET_KREF_FEATURE
	muxnet_get(mux_net);
#endif

	if (!skb) {
		mux_print(MSG_ERROR, "no skb\n");
		return -EINVAL;
	}

	mux_print(MSG_MSGDUMP, "ttyline = %d \n", dlci->line_no);
	mux_print(MSG_DEBUG, "net name : %s \n", net->name);
	mux_print(MSG_MSGDUMP, "net device address: %x \n", net);
	mux_print(MSG_MSGDUMP, "net->type : %d \n", net->type);
	mux_print(MSG_MSGDUMP, "skb->protocol : %x \n" , skb->protocol);
	mux_print(MSG_DEBUG, "skb data length = %d bytes\n", skb->len);

	int i = 0;
	int j = 15; //195;
	if (skb->len < j)
	j = (skb->len / 16) * 16 - 1;
	for (i = 0; i <= j; i = i + 16) {
		mux_print(MSG_MSGDUMP, "skb data %03d - %03d: %02x %02x %02x %02x %02x %02x %02x %02x  %02x %02x %02x %02x %02x %02x %02x %02x\n",
			i, i + 15, *(skb->data + i + 0), *(skb->data + i + 1), *(skb->data + i + 2), *(skb->data + i + 3),
			*(skb->data + i + 4), *(skb->data + i + 5), *(skb->data + i + 6), *(skb->data + i + 7),
			*(skb->data + i + 8), *(skb->data + i + 9), *(skb->data + i + 10), *(skb->data + i + 11),
			*(skb->data + i + 12), *(skb->data + i +13), *(skb->data + i + 14), *(skb->data + i + 15));
	}

	if ( mux_net->net_wq != NULL ) {
		mux_net->net = net;
		skb_queue_tail(&mux_net->txhead, skb);
		queue_delayed_work(mux_net->net_wq, &mux_net->net_work, 0);
	} else {
		mux_print(MSG_ERROR, "[WQ] mux_net->net_wq = NULL\n");
		mux_net->net = NULL;
		kfree_skb(skb);
		return -1;
	}
	FUNC_EXIT();
	return NETDEV_TX_OK;
}
Esempio n. 9
0
static void dlci_net_free(struct dlci_struct *dlci)
{
	if (!dlci->net) {
		WARN_ON(1);
		return;
	}
	mux_print(MSG_ERROR, "free_netdev(0x%x)\n", dlci->net);
	free_netdev(dlci->net);
	dlci->net = NULL;
}
Esempio n. 10
0
void ts27010_destroy_network(struct dlci_struct *dlci)
{
	struct ts27010_mux_net *mux_net;

	mux_print(MSG_INFO, "destroy network interface[%d]\n", dlci->line_no);
	if (dlci->net) {
		mux_net = (struct ts27010_mux_net *)netdev_priv(dlci->net);
		if ( mux_net->net_wq != NULL ) {
			int retry_count = 0;
			int skb_list_count = 0;
			//wait wq send all of TX
			mux_print(MSG_LIGHT, "[WQ] cancel_work_sync\n");
			cancel_delayed_work_sync(&mux_net->net_work);
			mux_print(MSG_LIGHT, "[WQ] destroy_workqueue, wq=[0x%x]\n", mux_net->net_wq);
			destroy_workqueue(mux_net->net_wq);
			mux_net->net_wq = NULL;
			for ( retry_count = 0; retry_count < 20; retry_count++ )
			{
				mutex_lock(&mux_net->net_wq_lock);
				skb_list_count = skb_queue_len(&mux_net->txhead);
				mutex_unlock(&mux_net->net_wq_lock);
				if (skb_list_count > 0) {
					mux_print(MSG_ERROR, "skb_list_count=[%d]\n", skb_list_count);
					mdelay(100);
				} else {
					break;
				}
			}
			if ( skb_list_count > 0 ) {
				mutex_lock(&mux_net->net_wq_lock);
				mux_print(MSG_ERROR, "clear skb\n");
				while ( skb_queue_len(&mux_net->txhead) > 0 ) {
					struct sk_buff* temp = skb_dequeue(&mux_net->txhead);
					if ( temp != NULL ) {
						consume_skb(temp);
					}
					temp = NULL;
				}
				mutex_unlock(&mux_net->net_wq_lock);
			} else {
				mutex_destroy(&mux_net->net_wq_lock);
			}
		}
		mux_print(MSG_LIGHT, "unregister_netdev\n");
		unregister_netdev(dlci->net);
		mux_print(MSG_LIGHT, "dlci_net_free\n");
		dlci_net_free(dlci);
#ifdef ENABLE_MUX_NET_KREF_FEATURE
		kref_put(&mux_net->ref, net_free);
#endif
	}
}
static int tty_push(struct tty_struct *tty, u8 *buf, int len)
{
	int sent = 0;
	FUNC_ENTER();
	while (sent < len) {
		int count = tty_insert_flip_string(
			tty, buf + sent, len - sent);
		if (count != (len - sent)) {
			mux_print(MSG_WARNING,
				"written size %d is not wanted %d\n",
				count, len - sent);
		}
		sent += count;
		/* tty_flip_buffer_push(tty); */
	}
	tty_flip_buffer_push(tty);
	FUNC_EXIT();
	return sent;
}
Esempio n. 12
0
static __be16 ts27010net_ip_type_trans(struct sk_buff *skb, struct net_device *dev)
{
	__be16 protocol = 0;

	skb->dev = dev;

	/* Determine L3 protocol */
	switch (skb->data[0] & 0xf0) {
	case 0x40:
		protocol = htons(ETH_P_IP);
		break;
	case 0x60:
		protocol = htons(ETH_P_IPV6);
		break;
	default:
		mux_print(MSG_ERROR, "[%s] L3 protocol decode error: 0x%02x \n",
					dev->name, skb->data[0] & 0xf0);
		/* skb will be dropped in uppder layer for unknown protocol */
	}
	return protocol;
}
static void ts27010_uart_retran_worker(struct work_struct *work)
{
	int ret;
	int j;
	u8 para[SLIDE_WINDOWS_SIZE_AP];
	struct ts27010_retran_info_t *retran_info;
	FUNC_ENTER();

	memset(para, 0, sizeof(u8) * SLIDE_WINDOWS_SIZE_AP);
	/* get timeout indexs and clean counter */
	ts27010_get_timer_para(s_timer_para, para);

	ts27010_slidewindow_lock(s_slide_window);

	for (j = 0; j < SLIDE_WINDOWS_SIZE_AP; j++) {
		if (para[j] && ts27010_slidewindow_is_idx_in(
			s_slide_window, j)) {
			/* need retransfer j */
			retran_info = ts27010_slidewindow_peek(
				s_slide_window, j);
			mux_print(MSG_INFO,
				"retransfering... index=%d, "
				"sn = %x, length=%d\n",
				j, ts27010_get_retran_sn(retran_info),
				ts27010_get_retran_len(retran_info));
			ret = ts27010_uart_driver_send(
				ts27010_get_retran_data(retran_info),
				ts27010_get_retran_len(retran_info),
				&s_mux_resend_lock);
			ts27010_mod_retran_timer(retran_info);

			if (!ret) {
				/* this frame retransfered */
				mux_print(MSG_INFO,
					"frame %x retransfered successful, "
					"length=%d\n",
					ts27010_get_retran_sn(retran_info),
					ts27010_get_retran_len(retran_info));
#ifdef CONFIG_WAKELOCK
				/*
				 * Re-transfer happened,
				 * so block system 1s for next re-send.
				 */
				wake_lock_timeout(&s_mux_resend_lock, HZ);
#endif
				if (ts27010_inc_retran_count(retran_info)
					== MAX_RETRAN_TIMES) {
					/* retran 10 times, trigger panic */
					mux_print(MSG_ERROR,
						"retrans frame %x(index %d) "
						"failed more than 10 times!\n",
						ts27010_get_retran_sn(
							retran_info), j);
					mux_uart_hexdump(MSG_ERROR,
						"dump frame",
						__func__, __LINE__,
						ts27010_get_retran_data(
							retran_info),
						ts27010_get_retran_len(
							retran_info));
					/* TODO: trigger panic or reset BP? */
				}
			} else {
				mux_print(MSG_ERROR,
					"retran interrupted because of "
					"ipc driver error\n");
				goto EXIT;
			}
		} else if (para[j]) {
			/*
			 * since j is not in slide window,
			 * should stop this timer
			 */
			mux_print(MSG_INFO,
				"timer index %d is out of slide window "
				"head: %d, tail %d\n",
				j, ts27010_slidewindow_head(s_slide_window),
				ts27010_slidewindow_tail(s_slide_window));
			ts27010_stop_retran_timer(
				ts27010_slidewindow_peek(s_slide_window, j));
			ts27010_clear_timer_para(s_timer_para, j);
		}
	}
EXIT:
	ts27010_slidewindow_unlock(s_slide_window);
	FUNC_EXIT();
}
Esempio n. 14
0
static int ts27010_mux_net_open(struct net_device *net)
{
	mux_print(MSG_MSGDUMP, "%s called\n", __func__);
	netif_start_queue(net);
	return 0;
}
Esempio n. 15
0
void ts27010_mux_rx_netchar(struct dlci_struct *dlci,
							unsigned char *in_buf, int size)
{
	FUNC_ENTER();
	struct sk_buff *skb;
	struct net_device *net = dlci->net;
	struct ts27010_mux_net *mux_net = (struct ts27010_mux_net *)netdev_priv(net);
#ifdef ENABLE_MUX_NET_KREF_FEATURE
	muxnet_get(mux_net);
#endif
	unsigned char *dst;

	mux_print(MSG_DEBUG, "ttyline = %d \n", dlci->line_no);
	mux_print(MSG_DEBUG, "net name : %s \n", net->name);
	mux_print(MSG_MSGDUMP, "net device address: %x \n", net);
	mux_print(MSG_MSGDUMP, "net->type : %d \n", net->type);
	mux_print(MSG_DEBUG, "Data length = %d byte\n", size);

	int i = 0;
	int j = 15;//195;
	if (size < j)
		j = (size / 16) * 16 -1;
	for (i = 0; i <= j; i = i + 16) {
		mux_print(MSG_MSGDUMP, "Data %03d - %03d: %02x %02x %02x %02x %02x %02x %02x %02x  %02x %02x %02x %02x %02x %02x %02x %02x\n",
			i, i + 15, *(in_buf + i + 0), *(in_buf + i + 1), *(in_buf + i + 2), *(in_buf + i + 3),
			*(in_buf + i + 4), *(in_buf + i + 5), *(in_buf + i + 6), *(in_buf + i + 7),
			*(in_buf + i + 8), *(in_buf + i + 9), *(in_buf + i + 10), *(in_buf + i + 11),
			*(in_buf + i + 12), *(in_buf + i +13), *(in_buf + i + 14), *(in_buf + i + 15));
	}

	skb = dev_alloc_skb(size + NET_IP_ALIGN);

	if (skb == NULL) {
		mux_print(MSG_ERROR, "[%s] cannot allocate skb\n", net->name);
		/* We got no receive buffer. */
		STATS(net).rx_dropped++;
	} else {
		skb->dev = net;
		skb_reserve(skb, NET_IP_ALIGN);
		dst  = skb_put(skb, size);
		memcpy(dst, in_buf, size);

		/* Driver in IP mode */
		skb->protocol = ts27010net_ip_type_trans(skb, net);
		mux_print(MSG_MSGDUMP, "skb->protocol : %x \n" , skb->protocol);
		/* Deliver to network stack */
		netif_rx(skb);
	}

	/* Update out statistics */
	STATS(net).rx_packets++;
	STATS(net).rx_bytes += size;
	if ( g_mux_uart_print_level != MSG_LIGHT && g_mux_uart_print_level != MSG_ERROR ) {
		mux_print(MSG_DEBUG, "All rx %d packets %d bytes\n", STATS(net).rx_packets, STATS(net).rx_bytes);
	} else {
		mux_print(MSG_LIGHT, "All rx %d packets %d bytes\n", STATS(net).rx_packets, STATS(net).rx_bytes);
	}
#ifdef ENABLE_MUX_NET_KREF_FEATURE
	muxnet_put(mux_net);
#endif
	FUNC_EXIT();
	return;
}
Esempio n. 16
0
static void ts27010_mux_net_tx_work(struct work_struct * work)
{
	struct sk_buff *skb = NULL;
	struct sk_buff *temp = NULL;
	struct net_device *net = NULL;
	struct ts27010_mux_net *mux_net = NULL;
	struct dlci_struct *dlci = NULL;
	unsigned char *data = NULL;
	int len = 0;
	int ret = 0;
	int err = 0;
	FUNC_ENTER();

	if ( work == NULL ) {
		mux_print(MSG_ERROR, "[WQ] work == NULL\n");
		goto net_tx_work_end2;
	}

	mux_net = container_of(work, struct ts27010_mux_net, net_work.work);
	if ( mux_net == NULL ) {
		mux_print(MSG_ERROR, "[WQ] mux_net == NULL\n");
		goto net_tx_work_end2;
	}

	mutex_lock(&mux_net->net_wq_lock);

	dlci = mux_net->dlci;
	if ( dlci == NULL ) {
		mux_print(MSG_ERROR, "[WQ] dlci == NULL\n");
		goto net_tx_work_end;
	}

	net = mux_net->net;
	if ( net == NULL ) {
		mux_print(MSG_ERROR, "[WQ] net == NULL\n");
		goto net_tx_work_end;
	}

	if ( skb_queue_len(&mux_net->txhead) == 0 ) {
		mux_print(MSG_WARNING, "[WQ2] skb_queue_len=[0]\n");
		goto net_tx_work_end;
	}


	do {
		skb = skb_peek(&mux_net->txhead);

		if ( skb == NULL ) {
			mux_print(MSG_ERROR, "[WQ] skb == NULL\n");
			goto net_tx_work_end;
		}

		data = kzalloc(skb->len, GFP_ATOMIC);
		if (!data) {
			mux_print(MSG_ERROR, "[WQ] buffer kzalloc() failed\n");
			goto net_tx_work_end;
		}

		err = skb_copy_bits(skb, 0, data, skb->len);
		if (err < 0) {
			mux_print(MSG_ERROR, "[WQ] skb_copy_bits() failed - %d\n", err);
			if ( data != NULL ) {
				kfree(data);
				mux_print(MSG_ERROR, "[WQ] free memory addr=[0x%x]\n", data);
				data = NULL;
			}
			goto net_tx_work_end;
		}

		len = skb->len;

		mux_print(MSG_LIGHT, "[WQ] dlci=[%d], data=[%d] \n", dlci->line_no, len);

		if ( data != NULL && len > 0) {
			mux_print(MSG_LIGHT, "[WQ] ts27010_mux_uart_line_write+\n");
			ret = ts27010_mux_uart_line_write(dlci->line_no, data, len);
			mux_print(MSG_LIGHT, "[WQ] ts27010_mux_uart_line_write-, ret=[%d]\n", ret);
		}

		if (ret < 0 ) {
			mux_print(MSG_ERROR, "[WQ] ts27010_mux_uart_line_write, ret=[%d]\n", ret);
			/*try again*/
			if ( data != NULL ) {
				kfree(data);
				mux_print(MSG_ERROR, "[WQ] free memory addr=[0x%x]\n", data);
				data = NULL;
			}
			mux_net->retry_count ++;
			queue_delayed_work(mux_net->net_wq, &mux_net->net_work, msecs_to_jiffies(200));
			goto net_tx_work_end;
		} else {
			mux_net->retry_count = 0;
		}

		STATS(net).tx_packets++;
		STATS(net).tx_bytes += skb->len;
		if ( g_mux_uart_print_level != MSG_LIGHT && g_mux_uart_print_level != MSG_ERROR ) {
			mux_print(MSG_DEBUG, "[WQ] All tx %d packets %d bytes\n",
						STATS(net).tx_packets, STATS(net).tx_bytes);
		} else {
			mux_print(MSG_LIGHT, "[WQ] All tx %d packets %d bytes\n",
						STATS(net).tx_packets, STATS(net).tx_bytes);
		}

		if ( data != NULL ) {
			kfree(data);
			data = NULL;
		}
		temp = skb_dequeue(&mux_net->txhead);
		/* And tell the kernel when the last transmit started. */
		net->trans_start = jiffies;
		consume_skb(skb);
#ifdef ENABLE_MUX_NET_KREF_FEATURE
		muxnet_put(mux_net);
#endif
		mutex_unlock(&mux_net->net_wq_lock);
		mutex_lock(&mux_net->net_wq_lock);
	} while (skb_queue_len(&mux_net->txhead) > 0);

net_tx_work_end:
	if ( mux_net != NULL )
		mutex_unlock(&mux_net->net_wq_lock);
net_tx_work_end2:

	mux_print(MSG_LIGHT, "[WQ] net_tx_work_end\n");
	FUNC_EXIT();
	return;
}