/* 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; }
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; }
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(); }
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; }
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; }
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; }
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(); }
static int ts27010_mux_net_open(struct net_device *net) { mux_print(MSG_MSGDUMP, "%s called\n", __func__); netif_start_queue(net); return 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; }
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; }