zte's code,first commit
Change-Id: I9a04da59e459a9bc0d67f101f700d9d7dc8d681b
diff --git a/ap/os/linux/linux-3.4.x/drivers/net/ddr/ddrnet.c b/ap/os/linux/linux-3.4.x/drivers/net/ddr/ddrnet.c
new file mode 100644
index 0000000..9f1422f
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/drivers/net/ddr/ddrnet.c
@@ -0,0 +1,985 @@
+#include <linux/module.h>
+#include <linux/etherdevice.h>
+
+#include <net/SI/ext_mem.h>
+
+#include "ddrnet.h"
+
+#define DDRNET_DEBUG 1
+#ifdef USE_DDRNET_PACKET
+#define TAG_SIZE 4
+
+static unsigned char B_TAG[TAG_SIZE] = {0xaa, 0xaa, 0x55, 0x55};
+static unsigned char E_TAG[TAG_SIZE] = {0x55, 0x55, 0xaa, 0xaa};
+#endif
+
+#define pswan1 ICP_CHANNEL_WAN1
+#define pswan2 ICP_CHANNEL_WAN2
+#define pswan3 ICP_CHANNEL_WAN3
+#define pswan4 ICP_CHANNEL_WAN4
+
+
+#ifdef dbg
+#undef dbg
+#endif
+#if DDRNET_DEBUG
+#define dbg(format, arg...) printk(KERN_DEBUG " ddrnet.c<%s>: " format "\n" , \
+ __func__ , ## arg)
+#else
+#define dbg(format, arg...) do {} while (0)
+#endif
+
+#ifdef err
+#undef err
+#endif
+#define err(format, arg...) printk(KERN_ERR " ddrnet.c<%s>: " format "\n" , \
+ __func__ , ## arg)
+
+#ifdef warn
+#undef warn
+#endif
+#define warn(format, arg...) printk(KERN_WARNING " ddrnet.c<%s>: " format "\n" , \
+ __func__ , ## arg)
+
+#ifdef info
+#undef info
+#endif
+#define info(format, arg...) printk(KERN_ERR " ddrnet.c<%s>: " format "\n" , \
+ __func__ , ## arg)
+
+
+
+
+enum{
+ //DDR_DEV_LAN = 0,
+ //DDR_DEV_WAN,
+ DDR_DEV_WAN1 = 0,
+ DDR_DEV_WAN2,
+ DDR_DEV_WAN3,
+ DDR_DEV_WAN4,
+ DDR_DEV_MAX,
+
+};
+
+#define NET_LAN 0x10
+#define NET_WAN 0x11
+/* NET NUMBER; channel id; lan/wan*/
+
+static unsigned int ddr_net_collect[DDR_DEV_MAX][3]= {
+ //{DDR_DEV_LAN, LAN1, NET_LAN},
+ //{DDR_DEV_WAN, WAN, NET_WAN},
+ {DDR_DEV_WAN1, pswan1, NET_WAN},
+ {DDR_DEV_WAN2, pswan2, NET_WAN},
+ {DDR_DEV_WAN3, pswan3, NET_WAN},
+ {DDR_DEV_WAN4, pswan4, NET_WAN},
+
+};
+
+
+
+#define WATCHDOG_TIMEO (5*HZ)
+#define ICP_CHANNEL_SIZE (8 * 1024 *2)
+
+#define ICP_PSBUFF_LEN 8
+
+#define SKB_DATA_PTR_LEN 4
+
+
+//ps_buff lenth
+#define SKB_DATA_LEN 1860
+#define SKB_DATA_DLPSBUFF_OFFSET (0x23100000 + 0x476018 + 0x400)
+
+#ifdef USE_DDRNET_PACKET
+u32 g_ddrnet_rx = 0;
+u32 g_ddrnet_rx_drop = 0;
+
+u32 g_ddrnet_rx_free = 0;
+u32 g_ddrnet_rx_free_drop = 0;
+
+extern u32 g_ddrnet_wrap_num;
+#endif
+static struct net_device *ddrnet_dev[DDR_DEV_MAX];
+
+static struct ddrnet *debug_ddrnet[DDR_DEV_MAX];
+
+#ifdef USE_DDRNET_PACKET
+struct ddrnet_queue free_psb_que;
+struct ddrnet_queue free_psb_que_free;
+
+struct semaphore freepsb_que_sem;
+struct task_struct* freepsb_wrap_thread = NULL;
+struct timer_list freepsb_wrap_timer;
+
+u32 g_ddrnet_psbuf_nr = 0;
+module_param(g_ddrnet_psbuf_nr, int, 0444);
+struct spinlock g_psbuf_nr_lock;
+#endif
+
+extern int (*fast_from_driver)(struct sk_buff *skb, struct net_device* dev);
+
+static void channelResult(int result)
+{
+ if (result == 0) {
+ dbg("channel: success, len = %d", result);
+ return;
+ }
+
+ switch (result) {
+ case RPMSG_INT_NOCLEAR:
+ dbg("channel: int not clear");
+ break;
+ case RPMSG_ERROR:
+ err("channel: error");
+ break;
+ case RPMSG_INVALID_PARAMETER:
+ err("channel: Invalid Parameter");
+ break;
+ case RPMSG_SPACE_NOT_ENOUGH:
+ err("channel: space not enough");
+ break;
+ case RPMSG_CHANNEL_ALREADY_EXIST:
+ err("channel: channel already existed");
+ break;
+ case RPMSG_CHANNEL_INEXISTANCE:
+ err("channel: channel is not existed");
+ break;
+ case RPMSG_CHANNEL_MSG_ERR:
+ err("channel: channel msg error");
+ break;
+ case RPMSG_CHANNEL_ERROR:
+ err("channel: channel error");
+ break;
+ case RPMSG_NO_MSG:
+ err("channel: no msg");
+ break;
+ default:
+ err("channel: unknown error, result = %d",result);
+ }
+}
+
+int g_zpr_ddrnet_flag1 = 0;
+module_param(g_zpr_ddrnet_flag1, int, 0644);
+static int ddrnet_icp_receive_thread(void * __dev)
+{
+ struct ddrnet *dev = (struct ddrnet *)__dev;
+ int retval;
+ T_ZDrvRpMsg_Msg msg = { 0 };
+#ifdef USE_DDRNET_PACKET
+ struct ddrnet_package pkg = {0};
+ int loop = 0;
+ int pkg_len = 0;
+ u8* cursor = NULL;
+ u32 spin_flag = 0;
+ u32 drop_nr = 0;
+#endif
+ struct T_FromExt_mem psData = { 0 };
+
+ volatile int i = 0xFFFFFFFF;
+ unsigned long flags;
+ info("ddrnet_icp_receive_thread, lan = %d, actor_id = %d, channel_id = %d", dev->lan, dev->actor_id, dev->channel_id);
+
+ //struct sched_param param = { .sched_priority = 1 };
+ //param.sched_priority = 40;
+ //sched_setscheduler(current, SCHED_FIFO, ¶m);
+
+
+ while(1) {
+#ifdef USE_DDRNET_PACKET
+ struct sk_buff *skb;
+ msg.actorID = dev->actor_id;
+ msg.chID = dev->channel_id;
+ msg.buf = &pkg;
+ msg.len = sizeof(struct ddrnet_package);
+ if(g_zpr_ddrnet_flag1 == 0 && dev->lan)
+ {
+ msleep(5);
+ continue;
+ }
+ spin_lock_irqsave(&g_psbuf_nr_lock, spin_flag);
+ if(g_ddrnet_psbuf_nr >= DDRNET_PACKET_QUEUE_COUNT - DDRNET_TRANS_THREDHOLD)
+ {
+ spin_unlock_irqrestore(&g_psbuf_nr_lock, spin_flag);
+ printk("g_ddrnet_psbuf_nr >= DDRNET_PACKET_QUEUE_COUNT - g_ddrnet_wrap_num");
+ msleep(100);
+ continue;
+ }
+ spin_unlock_irqrestore(&g_psbuf_nr_lock, spin_flag);
+ retval = zDrvRpMsg_Read(&msg);
+ if (retval <= 0) {
+ err("no msg or thread exited");
+ msleep(100);
+ continue;
+ }
+ pkg_len = pkg.pkg_length;
+ cursor = pkg.contents;
+ retval = memcmp(cursor, B_TAG, TAG_SIZE);
+ cursor += TAG_SIZE;
+ if (retval == 0)
+ retval = memcmp(cursor + pkg_len * DDRNET_PSB_PACKET_UNIT_SIZE, E_TAG, TAG_SIZE);
+ if(retval == 0)
+ {
+ //g_ddrnet_rx++;
+ //drop_nr = 0;
+ //printk("g_ddrnet_rx %d\n", g_ddrnet_rx);
+ for(loop = 0; loop < pkg_len; loop++)
+ {
+ memcpy(&psData, cursor, DDRNET_PSB_PACKET_UNIT_SIZE);
+ cursor += DDRNET_PSB_PACKET_UNIT_SIZE;
+ //printk("psbuf data:head %x:%x\n", psData.pbuf_data, psData.pbuf_head);
+ skb = skb_build_psbuf(&psData); //DL DATA, NO FREE
+
+ if (!skb) {
+ err("ddrnet_icp_receive_thread can not allocate skb. drop the package");
+ dev->net->stats.rx_dropped++;
+ //drop_nr++;
+ } else {
+ skb_push(skb, ETH_HLEN);
+
+ if(loop == pkg_len - 1)
+ {
+ skb_set_last_pkg(skb);
+ }
+ if (set_protocol_by_version(skb) < 0)
+ continue;
+ if (fast_from_driver && fast_from_driver(skb, dev->net))
+ {
+ continue;
+ }
+ memcpy(skb->data, dev->net->dev_addr, ETH_ALEN);
+ memcpy(skb->data + ETH_ALEN, dev->net->dev_addr, ETH_ALEN);
+ spin_lock_irqsave(&dev->rxq.lock, flags);
+ __skb_queue_tail (&dev->rxq, skb);
+ spin_unlock_irqrestore(&dev->rxq.lock, flags);
+ tasklet_schedule (&dev->bh);
+ }
+
+ }
+
+ spin_lock_irqsave(&g_psbuf_nr_lock, spin_flag);
+ g_ddrnet_psbuf_nr = g_ddrnet_psbuf_nr + pkg_len;// - drop_nr;
+ spin_unlock_irqrestore(&g_psbuf_nr_lock, spin_flag);
+
+ g_ddrnet_rx = g_ddrnet_rx + pkg_len;// - drop_nr;
+
+ }
+ else
+ {
+ g_ddrnet_rx_drop++;
+ printk(KERN_WARNING " ICP data recived ERR, g_ddrnet_rx_drop %d\n", g_ddrnet_rx_drop);
+ }
+#else
+ //while(!kthread_should_stop()) {
+ struct sk_buff *skb;
+
+ msg.actorID = dev->actor_id;
+ msg.chID = dev->channel_id;
+ msg.buf = &psData;
+ msg.len = sizeof(struct T_FromExt_mem);
+ // msg.flag |= RPMSG_READ_POLL;
+
+ //TODO Èç¹û½ø³ÌÍ˳öÇÒÒ»Ö±¶ÁÈ¡²»µ½Êý¾Ý£¬Õâ¸öµØ·½»á·ñÒ»Ö±¿¨×¡?
+ //while(i--);
+ if(g_zpr_ddrnet_flag1 == 0 && dev->lan)
+ {
+ msleep(5);
+ continue;
+ }
+ retval = zDrvRpMsg_Read(&msg);
+ //dbg("zDrvRpMsg_Read retval = %d, len = %d", retval, msg.len);
+ if (retval <= 0) {
+ err("no msg or threand exited");
+ msleep(1000);
+ continue;
+ }
+
+ skb = skb_build_psbuf(&psData);
+
+
+ //only test --- need check how to adjust len with peirong
+ //dbg("skb original len = %d", skb->len);
+ //skb_put(skb, psData.len);
+ //dbg("skb_put len = %d", skb->len);
+ //end
+
+ if (!skb) {
+ err("ddrnet_icp_receive_thread can not allocate skb. drop the package");
+ dev->net->stats.rx_dropped++;
+ } else {
+ //PSBUF_OUT( skb->head, PSBUF_MDL_AP_DDRNET_BASE, PSBUF_MDL_AP_NET_BASE );
+ //spin_lock(&dev->rxq.lock);
+ skb_push(skb, ETH_HLEN);
+
+ if (set_protocol_by_version(skb) < 0)
+ continue;
+
+ if (fast_from_driver && fast_from_driver(skb, dev->net))
+ {
+ continue;
+ }
+
+ memcpy(skb->data, dev->net->dev_addr, ETH_ALEN);
+ memcpy(skb->data + ETH_ALEN, dev->net->dev_addr, ETH_ALEN);
+
+ spin_lock_irqsave(&dev->rxq.lock, flags);
+ __skb_queue_tail (&dev->rxq, skb);
+ spin_unlock_irqrestore(&dev->rxq.lock, flags);
+ //spin_unlock(&dev->rxq.lock);
+ tasklet_schedule (&dev->bh);
+ }
+#endif
+ }
+ return 0;
+}
+
+static int ddrnet_icp_release_thread(void * __dev)
+{
+ struct ddrnet *dev = (struct ddrnet *)__dev;
+ int retval;
+#ifdef USE_DDRNET_PACKET
+
+ struct ddrnet_package pkg = {0};
+ int loop = 0;
+ int pkg_len = 0;
+ u8* cursor = NULL;
+
+#endif
+ struct sched_param param = { .sched_priority = 1 };
+ param.sched_priority = 40;
+ //sched_setscheduler(current, SCHED_FIFO, ¶m);
+
+ T_ZDrvRpMsg_Msg msg = { 0 };
+ void *skb;
+
+ //dev->channel_id = channel_8; // »ñȡͨµÀºÅ
+
+ while(1) {
+ //while(!kthread_should_stop()) {
+#ifdef USE_DDRNET_PACKET
+ struct sk_buff *skb;
+ msg.actorID = dev->actor_id;
+ msg.chID = channel_8;
+ msg.buf = &pkg;
+ msg.len = sizeof(struct ddrnet_package);
+ //msg.flag |= RPMSG_READ_POLL;
+
+ retval = zDrvRpMsg_Read(&msg);
+ if (retval <= 0) {
+ err("no msg or threand exited");
+ msleep(1000);
+ continue;
+ }
+ pkg_len = pkg.pkg_length;
+ cursor = pkg.contents;
+ //printk("release thread, pkg_len %d\n", pkg_len);
+ retval = memcmp(cursor, B_TAG, TAG_SIZE);
+ cursor += TAG_SIZE;
+ if (retval == 0)
+ retval = memcmp(cursor + pkg_len * SKB_DATA_PTR_LEN, E_TAG, TAG_SIZE);
+ if(retval == 0)
+ {
+ g_ddrnet_rx_free += pkg_len;
+ //printk("g_ddrnet_rx_free %d\n", g_ddrnet_rx_free);
+ for(loop = 0; loop < pkg_len; loop++)
+ {
+ memcpy(&skb, cursor, SKB_DATA_PTR_LEN);
+ //printk("release thread, free skb addr %#x\n", skb);
+ free_toext_mem(skb);
+ cursor += SKB_DATA_PTR_LEN;
+ }
+ }
+ else
+ {
+ g_ddrnet_rx_free_drop++;
+ printk(KERN_WARNING "ICP READ FREEBUF DATA ERR, g_ddrnet_rx_free_drop %d\n", g_ddrnet_rx_free_drop);
+ }
+#else
+ struct sk_buff *skb;
+ msg.actorID = dev->actor_id;
+ msg.chID = channel_8;
+ msg.buf = (unsigned char *)(&skb); // Êý¾Ý
+ msg.len = SKB_DATA_PTR_LEN; // ¶ÁÈ¡µÄ³¤¶È
+ //msg.flag |= RPMSG_READ_POLL;
+
+ retval = zDrvRpMsg_Read(&msg); // ¶ÁÈ¡»·ÐζÓÁÐÖÐÒ»¸ö½Úµã£¬
+ if (retval <= 0) {
+ err("no msg or threand exited");
+ msleep(1000);
+ continue;
+ }
+ //ÈôºóÐøÎ´·¢ÏÖ´æÔں˼äskbй©£¬¿ÉÒÔÖ±½ÓʹÓÃkfree_skb(skb);½Ó¿Ú½øÐÐÕý³£µÄskbÊÍ·Å,µ«ÐèÒªÓëinsert_toext_memÒ»ÆðÈ¥³ý
+ free_toext_mem(skb);
+
+#endif
+ }
+}
+static int ddrnet_start(struct net_device *net)
+{
+ struct ddrnet *dev = netdev_priv(net);
+ int retval;
+ struct task_struct *th;
+ struct task_struct *re;
+ info("ddrnet_open %s", dev->net->name);
+
+ if(net->flags & IFF_UP) {
+ dbg("the %s has been opened!", dev->net->name);
+ return -EBUSY;
+ }
+ netif_start_queue (net);
+
+ //read msg from icp
+ //th = kthread_run(ddrnet_icp_receive_thread, dev, "receive-thread");
+ if (dev->rcv_thread == NULL) {
+ th = kthread_run(ddrnet_icp_receive_thread, dev, "receive-thread");
+ if (IS_ERR(th)) {
+ err("Unable to start receive thread.");
+ return PTR_ERR(th);
+ }
+ dev->rcv_thread = th;
+ }
+ if(dev->rel_thread == NULL) {
+ re = kthread_run(ddrnet_icp_release_thread, dev, "release-thread");
+ if (IS_ERR(re)) {
+ err("Unable to start release thread.");
+ return PTR_ERR(re);
+ }
+ dev->rel_thread = re;
+ }
+#ifdef USE_DDRNET_PACKET
+ if(dev->skb_wrap_thread == NULL) {
+ re = kthread_run(ddrnet_skb_wrap_thread, dev, "skb-wrap-thread");
+ if (IS_ERR(re)) {
+ err("Unable to start packet wrap thread.");
+ return PTR_ERR(re);
+ }
+ dev->skb_wrap_thread = re;
+ }
+
+#endif
+ return 0;
+}
+
+static int ddrnet_open(struct net_device *net)
+{
+ info("ddrnet_open");
+ ddrnet_start(net);
+/*
+ struct ddrnet *dev = netdev_priv(net);
+ int retval;
+ struct task_struct *th;
+
+ if(net->flags & IFF_UP) {
+ dbg("the %s has been opened!", dev->net->name);
+ return -EBUSY;
+ }
+ netif_start_queue (net);
+
+ //read msg from icp
+ th = kthread_run(ddrnet_icp_receive_thread, dev, "receive-thread");
+
+ if (IS_ERR(th)) {
+ err("Unable to start receive thread.");
+ return PTR_ERR(th);
+ }
+ dev->rcv_thread = th;
+*/
+ return 0;
+}
+
+static int ddrnet_close(struct net_device *net)
+{
+ struct ddrnet *dev = netdev_priv(net);
+
+ info("ddrnet_close");
+
+ netif_stop_queue(net);
+#if 0
+ if(dev->rcv_thread)
+ kthread_stop(dev->rcv_thread);
+ dev->rcv_thread = NULL;
+ if(dev->rel_thread)
+ kthread_stop(dev->rel_thread);
+ dev->rel_thread = NULL;
+#endif
+ tasklet_kill (&dev->bh);
+}
+
+static int ddrnet_write_icp_message(struct ddrnet *dev,struct T_ToExt_info *psData)
+{
+ T_ZDrvRpMsg_Msg msg;
+
+ memset(&msg, 0, sizeof(T_ZDrvRpMsg_Msg));
+ msg.actorID = dev->actor_id;
+ msg.chID = dev->channel_id;
+ msg.flag |= RPMSG_WRITE_INT;
+
+ msg.buf = psData;
+ msg.len = sizeof(struct T_ToExt_info);
+
+ return zDrvRpMsg_WriteLockIrq(&msg);
+}
+
+//½«CP²à´«µÝÀ´µÄpsbufÖ¸ÕëдÈëDDR£¬ÒÔICP·½Ê½Í¨ÖªCP²à
+void write_freepsbuf(void *head)
+{
+ int ret = 0;
+
+#ifdef USE_DDRNET_PACKET
+Try_enqueue:
+ ret = ddrnet_freepsb_packet_enqueue(head);
+ if(ret < 0)
+ {
+ printk(KERN_WARNING "ddrnet_freepsb_packet_enqueue fail, try again...ret : %d!!!!!!", ret);
+ goto Try_enqueue;
+ }
+
+#else
+ T_ZDrvRpMsg_Msg msg = { .actorID = PS_ID,
+ .chID = ICP_CHANNEL_DEV_BUFFREE,
+ .flag = RPMSG_WRITE_INT,
+ .buf = NULL,
+ .len = 4 };
+
+ msg.buf = head;
+
+ ret = zDrvRpMsg_WriteLockIrq(&msg);
+#endif
+ if(ret <= 0)
+ panic("write ddr err, ret : %d!!!!!!", ret);
+
+}
+
+/* Called by the kernel in order to transmit a packet. */
+unsigned long g_ddrnet_cpnum = 0;
+unsigned long g_ddrnet_othernum = 0;
+unsigned long g_ddrnet_failnum1 = 0;
+unsigned long g_ddrnet_failnum = 0;
+int test_retval=11;
+static netdev_tx_t ddrnet_tx_packet(struct sk_buff *skb, struct net_device *net)
+{
+ int length;
+ unsigned char *psbuff;
+ struct ddrnet *dev = netdev_priv(net);
+ int retval = RPMSG_ERROR;
+ unsigned long phy;
+ int needFreePsbuff = 0;
+ struct T_ToExt_info skb_info={0};
+ struct sk_buff *skb_new;
+
+ if (!skb) {
+ panic("skb err!!!!");
+ }
+ //Æ«ÒÆÖÁipÍ·
+ skb_pull(skb, ETH_HLEN);
+
+ //Ë¢ÐÂcache
+ skb = flush_skbuf(skb);
+
+ skb_info.skb_data = virtaddr_to_phys(skb->data);
+ skb_info.skb_head = virtaddr_to_phys(skb->head);
+ skb_info.skb = skb;
+ skb_info.datalen = skb->len;
+
+ //ÈôºóÐøÎ޺˼äskbÄÚ´æÐ¹Â©£¬¿ÉÈ¥³ý¸Ã½Ó¿Ú£¬µ«ÐèÓëfree_toext_mem½Ó¿ÚÒ»ÆðÈ¥³ý
+ insert_toext_mem(skb);
+#ifdef USE_DDRNET_PACKET
+ retval = ddrnet_skb_packet_enqueue(dev, &skb_info);
+#else
+ retval = ddrnet_write_icp_message(dev, &skb_info);
+#endif
+ test_retval = retval;
+ if (retval > 0) {
+ net->trans_start = jiffies;
+ net->stats.tx_packets++;
+ net->stats.tx_bytes += skb->len;
+ return NET_XMIT_SUCCESS;
+ } else {
+ //panic("write err, ret : %d!!!!", retval);
+ printk("write err, ret : %d!!!!", retval);
+ free_toext_mem(skb);
+ //return NET_XMIT_DROP;
+ return NET_XMIT_SUCCESS;
+ }
+
+}
+
+#if 0
+{
+ int length;
+ unsigned char *psbuff;
+ struct ddrnet *dev = netdev_priv(net);
+ int retval = RPMSG_ERROR;
+ unsigned long phy;
+ int needFreePsbuff = 0;
+
+ //dbg("in ddr_ap_tx_packet, location = %d, data = 0x%X, len = %d\n", skb->location, skb->data, skb->len);
+
+ if (!skb) {
+ err("ddrnet_tx_packet psbuff null");
+ return NET_XMIT_DROP;
+ }
+
+ length = skb->len;
+
+ if (SKB_LOCATION_AP == skb->location || skb->cloned == 1) {
+ psbuff = alloc_psbuff();
+ if (!psbuff) {
+ //err("ddrnet_tx_packet can not alloc_psbuff");
+ net->stats.tx_dropped++;
+ g_ddrnet_failnum1++;
+ goto out;
+ //return NET_XMIT_DROP;
+ }
+ memcpy(psbuff, skb->data, length);
+ PSBUF_IN( psbuff, PSBUF_MDL_AP_DDRNET_BASE+1 );
+ } else {
+ //err("ddrnet_tx_packet location is not AP");
+
+ if(SKB_LOCATION_CP == skb->location)
+ {
+ g_ddrnet_cpnum++;
+ psbuff = skb->data;
+ }
+ else
+ {
+ err("@!@ddrnet_tx_packet location is not AP %d",skb->location);
+ g_ddrnet_othernum++;
+ }
+ PSBUF_IN( skb->head, PSBUF_MDL_AP_DDRNET_BASE+2 );
+ }
+
+/* if(dev->channel_id == LAN1)
+ {
+ memmove(psbuff - 2, psbuff, length);
+ psbuff = psbuff - 2;
+ }
+
+ */
+ if (psbuff_virt_to_phys(psbuff, &phy) != 1) {
+ //free_psbuff(psbuff);
+
+ err("ddrnet_tx_packet psbuff_virt_to_phys error psbuff: 0x%x", psbuff);
+ net->stats.tx_dropped++;
+ g_ddrnet_failnum++;
+ goto out;
+ //return NET_XMIT_DROP;
+ }
+ #if 0
+ if((dev->channel_id == channel_4) ||(dev->channel_id == channel_5)
+ ||(dev->channel_id == channel_6) ||(dev->channel_id == channel_10))
+ {
+ #endif
+ if(phy > SKB_DATA_DLPSBUFF_OFFSET)
+ {
+ needFreePsbuff = 1;
+ goto out;
+ }
+ //}
+
+ //dbg("ddr_ap_tx_packet virtual = 0x%X, phy = 0x%X", psbuff, phy);
+
+ PSBUF_OUT( psbuff, PSBUF_MDL_AP_DDRNET_BASE, PSBUF_MDL_CP_CTRM_BASE );
+ retval = ddrnet_write_icp_message(dev, phy, length);
+ //retval = ddrnet_write_icp_message(dev, psbuff, length);
+ if (retval > 0) {
+ net->trans_start = jiffies;
+ net->stats.tx_packets++;
+ net->stats.tx_bytes += length;
+ //dbg("> tx, len %d, type 0x%x", length, skb->protocol);
+ } else {
+ net->stats.tx_dropped++;
+ channelResult(retval);
+ needFreePsbuff = 1;
+ }
+
+out:
+ if (SKB_LOCATION_CP != skb->location || skb->cloned == 1 || needFreePsbuff) {
+ dev_kfree_skb_any (skb);
+ } else {
+ kfree_7510_skb(skb);
+ }
+
+ //dbg("transmit result = %d\n", retval);
+
+ if (retval > 0)
+ return NET_XMIT_SUCCESS;
+ else
+ return NET_XMIT_DROP;
+}
+#endif
+
+/* Called by the kernel when transmit times out */
+static void ddrnet_tx_timeout(struct net_device *net)
+{
+ err("sent timeout!");
+ net->stats.tx_errors++;
+ netif_wake_queue(net);
+}
+
+static struct net_device_stats *ddrnet_get_stats(struct net_device *net)
+{
+// dbg("%s: request for stats\n", net->name);
+ return &net->stats;
+}
+
+static const struct net_device_ops ddr_netdev_ops = {
+ .ndo_open = ddrnet_open,
+ .ndo_stop = ddrnet_close,
+ .ndo_start_xmit = ddrnet_tx_packet,
+ .ndo_tx_timeout = ddrnet_tx_timeout,
+ .ndo_get_stats = ddrnet_get_stats,
+};
+
+static inline void ddrnet_init_netdev(struct net_device *net)
+{
+ //memset(net->dev_addr, 0xfe, ETH_ALEN);
+#if 0
+ u8 mac[ETH_ALEN] = {0x0, 0xa0, 0xc6, 0x11, 0x22, 0x33};
+ memcpy(net->dev_addr, mac, ETH_ALEN);
+#else
+ // randomly generated ethernet address
+ static u8 node_id [ETH_ALEN];
+ random_ether_addr(node_id);
+ memcpy (net->dev_addr, node_id, sizeof node_id);
+#endif
+ net->netdev_ops = &ddr_netdev_ops;
+ net->watchdog_timeo = WATCHDOG_TIMEO;
+ net->flags |= IFF_NOARP;
+}
+
+static inline int ddrnet_createIcpChannel(struct ddrnet *dev)
+{
+ int retval;
+
+ //creata channel --- send/receive use the same channel
+ retval = zDrvRpMsg_CreateChannel (dev->actor_id, dev->channel_id, dev->channel_size);
+ channelResult(retval);
+ if(retval != RPMSG_SUCCESS && retval != RPMSG_CHANNEL_ALREADY_EXIST)
+ goto out;
+
+ return retval;
+
+out:
+ err("could not create channel.");
+ return retval;
+}
+
+#ifdef USE_DDRNET_PACKET
+static inline void ddrnet_init_wraper(struct ddrnet* dev)
+{
+ u32 spin_flag = 0;
+ struct ddrnet_skb_packet* packet = NULL;
+ u32 loop = 0;
+
+ ddrnet_init_queue(&dev->skb_que);
+ ddrnet_init_queue(&dev->skb_que_free);
+ packet = (struct ddrnet_skb_packet*)kmalloc(DDRNET_SKB_PACKET_SIZE * DDRNET_PACKET_QUEUE_COUNT, GFP_ATOMIC);
+
+ spin_lock_irqsave(&dev->skb_que_free.lock, spin_flag);
+
+ for (loop = 0; loop < DDRNET_PACKET_QUEUE_COUNT; loop++)
+ {
+ ddrnet_list_insert_tail(&packet->list, &dev->skb_que_free.queue);
+ packet++;
+ }
+ dev->skb_que_free.qlen = DDRNET_PACKET_QUEUE_COUNT;
+
+ spin_unlock_irqrestore(&dev->skb_que_free.lock, spin_flag);
+ sema_init(&dev->skb_que_sem,1);
+
+ init_timer(&dev->wrap_timer);
+ dev->wrap_timer.data = (u32) dev;
+ dev->wrap_timer.function = ddrnet_skb_Wrap_TimerCallBack;
+ add_timer(&dev->wrap_timer);
+
+}
+#endif
+static inline void ddrnet_init_lan(struct net_device *net, unsigned int index)
+{
+ struct ddrnet *dev;
+ dev = netdev_priv(net);
+ dev->net = net;
+ strcpy(net->name, "lan%d");
+ dev->lan = 1;
+ dev->actor_id = PS_ID;
+ // dev->channel_id = LAN1;
+ dev->channel_id = ddr_net_collect[index][1];
+ dev->channel_size = ICP_CHANNEL_SIZE;
+ skb_queue_head_init (&dev->rxq);
+}
+
+static inline void ddrnet_init_wan(struct net_device *net, unsigned int index)
+{
+ struct ddrnet *dev;
+ unsigned wan_index;
+ dev = netdev_priv(net);
+ dev->net = net;
+ //strcpy(net->name, "wan%d");
+ wan_index = index + 1; // WAN1, WAN2,....
+ sprintf(net->name, "wan%d", wan_index);
+ dev->lan = 0;
+ dev->actor_id = PS_ID;
+ //dev->channel_id = WAN;
+ dev->channel_id = ddr_net_collect[index][1];
+ dev->channel_size = ICP_CHANNEL_SIZE;
+ skb_queue_head_init (&dev->rxq);
+}
+
+static void ddrnet_skb_return (struct ddrnet *dev, struct sk_buff *skb)
+{
+ int status;
+
+ skb->protocol = eth_type_trans (skb, dev->net);
+
+ status = netif_rx (skb);
+ if (status == NET_RX_SUCCESS) {
+ dev->net->stats.rx_packets++;
+ dev->net->stats.rx_bytes += skb->len;
+ } else {
+ dev->net->stats.rx_errors++;
+ err("netif_rx status %d.", status);
+ }
+}
+
+static void ddrnet_bh (unsigned long param)
+{
+ struct ddrnet *dev = (struct ddrnet *)param;
+ struct sk_buff *skb;
+
+ while(skb = skb_dequeue(&dev->rxq)) {
+ if (skb->len)
+ ddrnet_skb_return(dev, skb);
+ else {
+ dev->net->stats.rx_errors++;
+
+ dev_kfree_skb (skb);
+ err("drop!!!ddrnet_bh skb len == 0.");
+ }
+ }
+}
+int flag_zDrvRpMsg=0x5a;
+int *vir_addr_ddrnet = NULL;
+EXPORT_SYMBOL(vir_addr_ddrnet);
+
+static int __init ddrnet_init(void)
+{
+ int i;
+ int err;
+ struct ddrnet *dev;
+ struct net_device *net;
+
+#ifdef USE_DDRNET_PACKET
+ u32 loop = 0;
+ u32 spin_flag = 0;
+ struct ddrnet_psbuf_packet* packet = NULL;
+#endif
+ dbg("ddr_ap_net_lan_init.\n");
+
+ err = -ENOMEM;
+ for (i = 0; i < DDR_DEV_MAX; i++){
+ //for (i = 0; i < 1; i++) {
+ net = alloc_etherdev(sizeof(struct ddrnet));
+ if (!net) {
+ printk(KERN_ERR "could not allocate device.\n");
+ return err;
+ }
+
+ //È·±£ËùÓз¢Íùcp²àµÄÊý¾ÝÍ·²¿Ô¤Áô×ã¹»£¬±ÜÃâË¢cacheµÄʱºòÖØÐÂÉêÇëskb
+ net->needed_headroom += NET_SKB_PAD - ETH_HLEN;
+
+ dev = netdev_priv(net);
+ debug_ddrnet[i] = dev;
+
+ if(ddr_net_collect[i][2] == NET_LAN)
+ ddrnet_init_lan(net, i);
+ else if (ddr_net_collect[i][2] == NET_WAN)
+ ddrnet_init_wan(net, i);
+ else
+ goto out_free_netdev;
+
+ dev->net = net;
+ dev->bh.func = ddrnet_bh;
+ dev->bh.data = (unsigned long) dev;
+ dev->rcv_thread = NULL;
+ dev->rel_thread = NULL;
+#ifdef USE_DDRNET_PACKET
+ dev->skb_wrap_thread == NULL;
+#endif
+ ddrnet_init_netdev(net);
+ ddrnet_createIcpChannel(dev);
+#ifdef USE_DDRNET_PACKET
+ ddrnet_init_wraper(dev);
+#endif
+ err = register_netdev(net);
+ if (err)
+ goto out_free_netdev;
+ ddrnet_dev[i] = net;
+
+ // ddrnet_start(net);
+ }
+
+ {
+ flag_zDrvRpMsg=zDrvRpMsg_CreateChannel (PS_ID, ICP_CHANNEL_DEV_BUFFREE, 16*1024);
+#ifdef USE_DDRNET_PACKET
+ spin_lock_init(&g_psbuf_nr_lock);
+ ddrnet_init_queue(&free_psb_que);
+ ddrnet_init_queue(&free_psb_que_free);
+ sema_init(&freepsb_que_sem, 1);
+ packet = (struct ddrnet_psbuf_packet*)kmalloc(DDRNET_PSB_PACKET_SIZE * DDRNET_PACKET_QUEUE_COUNT, GFP_ATOMIC);
+
+ spin_lock_irqsave(&free_psb_que_free.lock, spin_flag);
+ for (loop = 0; loop < DDRNET_PACKET_QUEUE_COUNT; loop++)
+ {
+ ddrnet_list_insert_tail(&packet->list, &free_psb_que_free.queue);
+ packet++;
+ }
+ free_psb_que_free.qlen = DDRNET_PACKET_QUEUE_COUNT;
+ spin_unlock_irqrestore(&free_psb_que_free.lock, spin_flag);
+
+ if(freepsb_wrap_thread == NULL) {
+ freepsb_wrap_thread = kthread_run(ddrnet_freepsb_wrap_thread, 0, "freepsb-wrap-thread");
+ if (IS_ERR(freepsb_wrap_thread)) {
+ err("Unable to start packet wrap thread.");
+ return PTR_ERR(freepsb_wrap_thread);
+ }
+ }
+ init_timer(&freepsb_wrap_timer);
+ freepsb_wrap_timer.data = NULL;
+ freepsb_wrap_timer.function = ddrnet_freepsb_Wrap_TimerCallBack;
+ add_timer(&freepsb_wrap_timer);
+#endif
+ }
+
+
+ vir_addr_ddrnet = ioremap_cached(PSBUFFER_MEM_BASE, PSBUFFER_MEM_SIZE);
+ if(vir_addr_ddrnet == NULL)
+ {
+ printk(KERN_WARNING "Warning: [zx297510] cp ps_buf mmap failed.\n");
+ panic("Warning: [zx297510] cp ps_buf mmap failed.\n");
+ }
+
+ return 0;
+
+out_free_netdev:
+ free_netdev(net);
+ return err;
+}
+late_initcall(ddrnet_init);
+
+static void __exit ddrnet_exit(void)
+{
+ int i;
+ struct net_device *net;
+
+ for (i = 0; i < DDR_DEV_MAX; i++) {
+ if ((net = ddrnet_dev[i])) {
+ unregister_netdev(net);
+ free_netdev(net);
+ ddrnet_dev[i] = NULL;
+ }
+ }
+}
+module_exit(ddrnet_exit);
+
+MODULE_AUTHOR("P96G");
+MODULE_DESCRIPTION("7510 AP Lan Net Device");
+MODULE_LICENSE("GPL");