blob: 9f1422f867fcf55db724085da0639c95e5d3b5a8 [file] [log] [blame]
#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, &param);
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, &param);
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");