yuezonghe | 824eb0c | 2024-06-27 02:32:26 -0700 | [diff] [blame] | 1 | #include <linux/module.h> |
| 2 | #include <linux/etherdevice.h> |
| 3 | |
| 4 | #include <net/SI/ext_mem.h> |
| 5 | |
| 6 | #include "ddrnet.h" |
| 7 | |
| 8 | #define DDRNET_DEBUG 1 |
| 9 | #ifdef USE_DDRNET_PACKET |
| 10 | #define TAG_SIZE 4 |
| 11 | |
| 12 | static unsigned char B_TAG[TAG_SIZE] = {0xaa, 0xaa, 0x55, 0x55}; |
| 13 | static unsigned char E_TAG[TAG_SIZE] = {0x55, 0x55, 0xaa, 0xaa}; |
| 14 | #endif |
| 15 | |
| 16 | #define pswan1 ICP_CHANNEL_WAN1 |
| 17 | #define pswan2 ICP_CHANNEL_WAN2 |
| 18 | #define pswan3 ICP_CHANNEL_WAN3 |
| 19 | #define pswan4 ICP_CHANNEL_WAN4 |
| 20 | |
| 21 | |
| 22 | #ifdef dbg |
| 23 | #undef dbg |
| 24 | #endif |
| 25 | #if DDRNET_DEBUG |
| 26 | #define dbg(format, arg...) printk(KERN_DEBUG " ddrnet.c<%s>: " format "\n" , \ |
| 27 | __func__ , ## arg) |
| 28 | #else |
| 29 | #define dbg(format, arg...) do {} while (0) |
| 30 | #endif |
| 31 | |
| 32 | #ifdef err |
| 33 | #undef err |
| 34 | #endif |
| 35 | #define err(format, arg...) printk(KERN_ERR " ddrnet.c<%s>: " format "\n" , \ |
| 36 | __func__ , ## arg) |
| 37 | |
| 38 | #ifdef warn |
| 39 | #undef warn |
| 40 | #endif |
| 41 | #define warn(format, arg...) printk(KERN_WARNING " ddrnet.c<%s>: " format "\n" , \ |
| 42 | __func__ , ## arg) |
| 43 | |
| 44 | #ifdef info |
| 45 | #undef info |
| 46 | #endif |
| 47 | #define info(format, arg...) printk(KERN_ERR " ddrnet.c<%s>: " format "\n" , \ |
| 48 | __func__ , ## arg) |
| 49 | |
| 50 | |
| 51 | |
| 52 | |
| 53 | enum{ |
| 54 | //DDR_DEV_LAN = 0, |
| 55 | //DDR_DEV_WAN, |
| 56 | DDR_DEV_WAN1 = 0, |
| 57 | DDR_DEV_WAN2, |
| 58 | DDR_DEV_WAN3, |
| 59 | DDR_DEV_WAN4, |
| 60 | DDR_DEV_MAX, |
| 61 | |
| 62 | }; |
| 63 | |
| 64 | #define NET_LAN 0x10 |
| 65 | #define NET_WAN 0x11 |
| 66 | /* NET NUMBER; channel id; lan/wan*/ |
| 67 | |
| 68 | static unsigned int ddr_net_collect[DDR_DEV_MAX][3]= { |
| 69 | //{DDR_DEV_LAN, LAN1, NET_LAN}, |
| 70 | //{DDR_DEV_WAN, WAN, NET_WAN}, |
| 71 | {DDR_DEV_WAN1, pswan1, NET_WAN}, |
| 72 | {DDR_DEV_WAN2, pswan2, NET_WAN}, |
| 73 | {DDR_DEV_WAN3, pswan3, NET_WAN}, |
| 74 | {DDR_DEV_WAN4, pswan4, NET_WAN}, |
| 75 | |
| 76 | }; |
| 77 | |
| 78 | |
| 79 | |
| 80 | #define WATCHDOG_TIMEO (5*HZ) |
| 81 | #define ICP_CHANNEL_SIZE (8 * 1024 *2) |
| 82 | |
| 83 | #define ICP_PSBUFF_LEN 8 |
| 84 | |
| 85 | #define SKB_DATA_PTR_LEN 4 |
| 86 | |
| 87 | |
| 88 | //ps_buff lenth |
| 89 | #define SKB_DATA_LEN 1860 |
| 90 | #define SKB_DATA_DLPSBUFF_OFFSET (0x23100000 + 0x476018 + 0x400) |
| 91 | |
| 92 | #ifdef USE_DDRNET_PACKET |
| 93 | u32 g_ddrnet_rx = 0; |
| 94 | u32 g_ddrnet_rx_drop = 0; |
| 95 | |
| 96 | u32 g_ddrnet_rx_free = 0; |
| 97 | u32 g_ddrnet_rx_free_drop = 0; |
| 98 | |
| 99 | extern u32 g_ddrnet_wrap_num; |
| 100 | #endif |
| 101 | static struct net_device *ddrnet_dev[DDR_DEV_MAX]; |
| 102 | |
| 103 | static struct ddrnet *debug_ddrnet[DDR_DEV_MAX]; |
| 104 | |
| 105 | #ifdef USE_DDRNET_PACKET |
| 106 | struct ddrnet_queue free_psb_que; |
| 107 | struct ddrnet_queue free_psb_que_free; |
| 108 | |
| 109 | struct semaphore freepsb_que_sem; |
| 110 | struct task_struct* freepsb_wrap_thread = NULL; |
| 111 | struct timer_list freepsb_wrap_timer; |
| 112 | |
| 113 | u32 g_ddrnet_psbuf_nr = 0; |
| 114 | module_param(g_ddrnet_psbuf_nr, int, 0444); |
| 115 | struct spinlock g_psbuf_nr_lock; |
| 116 | #endif |
| 117 | |
| 118 | extern int (*fast_from_driver)(struct sk_buff *skb, struct net_device* dev); |
| 119 | |
| 120 | static void channelResult(int result) |
| 121 | { |
| 122 | if (result == 0) { |
| 123 | dbg("channel: success, len = %d", result); |
| 124 | return; |
| 125 | } |
| 126 | |
| 127 | switch (result) { |
| 128 | case RPMSG_INT_NOCLEAR: |
| 129 | dbg("channel: int not clear"); |
| 130 | break; |
| 131 | case RPMSG_ERROR: |
| 132 | err("channel: error"); |
| 133 | break; |
| 134 | case RPMSG_INVALID_PARAMETER: |
| 135 | err("channel: Invalid Parameter"); |
| 136 | break; |
| 137 | case RPMSG_SPACE_NOT_ENOUGH: |
| 138 | err("channel: space not enough"); |
| 139 | break; |
| 140 | case RPMSG_CHANNEL_ALREADY_EXIST: |
| 141 | err("channel: channel already existed"); |
| 142 | break; |
| 143 | case RPMSG_CHANNEL_INEXISTANCE: |
| 144 | err("channel: channel is not existed"); |
| 145 | break; |
| 146 | case RPMSG_CHANNEL_MSG_ERR: |
| 147 | err("channel: channel msg error"); |
| 148 | break; |
| 149 | case RPMSG_CHANNEL_ERROR: |
| 150 | err("channel: channel error"); |
| 151 | break; |
| 152 | case RPMSG_NO_MSG: |
| 153 | err("channel: no msg"); |
| 154 | break; |
| 155 | default: |
| 156 | err("channel: unknown error, result = %d",result); |
| 157 | } |
| 158 | } |
| 159 | |
| 160 | int g_zpr_ddrnet_flag1 = 0; |
| 161 | module_param(g_zpr_ddrnet_flag1, int, 0644); |
| 162 | static int ddrnet_icp_receive_thread(void * __dev) |
| 163 | { |
| 164 | struct ddrnet *dev = (struct ddrnet *)__dev; |
| 165 | int retval; |
| 166 | T_ZDrvRpMsg_Msg msg = { 0 }; |
| 167 | #ifdef USE_DDRNET_PACKET |
| 168 | struct ddrnet_package pkg = {0}; |
| 169 | int loop = 0; |
| 170 | int pkg_len = 0; |
| 171 | u8* cursor = NULL; |
| 172 | u32 spin_flag = 0; |
| 173 | u32 drop_nr = 0; |
| 174 | #endif |
| 175 | struct T_FromExt_mem psData = { 0 }; |
| 176 | |
| 177 | volatile int i = 0xFFFFFFFF; |
| 178 | unsigned long flags; |
| 179 | info("ddrnet_icp_receive_thread, lan = %d, actor_id = %d, channel_id = %d", dev->lan, dev->actor_id, dev->channel_id); |
| 180 | |
| 181 | //struct sched_param param = { .sched_priority = 1 }; |
| 182 | //param.sched_priority = 40; |
| 183 | //sched_setscheduler(current, SCHED_FIFO, ¶m); |
| 184 | |
| 185 | |
| 186 | while(1) { |
| 187 | #ifdef USE_DDRNET_PACKET |
| 188 | struct sk_buff *skb; |
| 189 | msg.actorID = dev->actor_id; |
| 190 | msg.chID = dev->channel_id; |
| 191 | msg.buf = &pkg; |
| 192 | msg.len = sizeof(struct ddrnet_package); |
| 193 | if(g_zpr_ddrnet_flag1 == 0 && dev->lan) |
| 194 | { |
| 195 | msleep(5); |
| 196 | continue; |
| 197 | } |
| 198 | spin_lock_irqsave(&g_psbuf_nr_lock, spin_flag); |
| 199 | if(g_ddrnet_psbuf_nr >= DDRNET_PACKET_QUEUE_COUNT - DDRNET_TRANS_THREDHOLD) |
| 200 | { |
| 201 | spin_unlock_irqrestore(&g_psbuf_nr_lock, spin_flag); |
| 202 | printk("g_ddrnet_psbuf_nr >= DDRNET_PACKET_QUEUE_COUNT - g_ddrnet_wrap_num"); |
| 203 | msleep(100); |
| 204 | continue; |
| 205 | } |
| 206 | spin_unlock_irqrestore(&g_psbuf_nr_lock, spin_flag); |
| 207 | retval = zDrvRpMsg_Read(&msg); |
| 208 | if (retval <= 0) { |
| 209 | err("no msg or thread exited"); |
| 210 | msleep(100); |
| 211 | continue; |
| 212 | } |
| 213 | pkg_len = pkg.pkg_length; |
| 214 | cursor = pkg.contents; |
| 215 | retval = memcmp(cursor, B_TAG, TAG_SIZE); |
| 216 | cursor += TAG_SIZE; |
| 217 | if (retval == 0) |
| 218 | retval = memcmp(cursor + pkg_len * DDRNET_PSB_PACKET_UNIT_SIZE, E_TAG, TAG_SIZE); |
| 219 | if(retval == 0) |
| 220 | { |
| 221 | //g_ddrnet_rx++; |
| 222 | //drop_nr = 0; |
| 223 | //printk("g_ddrnet_rx %d\n", g_ddrnet_rx); |
| 224 | for(loop = 0; loop < pkg_len; loop++) |
| 225 | { |
| 226 | memcpy(&psData, cursor, DDRNET_PSB_PACKET_UNIT_SIZE); |
| 227 | cursor += DDRNET_PSB_PACKET_UNIT_SIZE; |
| 228 | //printk("psbuf data:head %x:%x\n", psData.pbuf_data, psData.pbuf_head); |
| 229 | skb = skb_build_psbuf(&psData); //DL DATA, NO FREE |
| 230 | |
| 231 | if (!skb) { |
| 232 | err("ddrnet_icp_receive_thread can not allocate skb. drop the package"); |
| 233 | dev->net->stats.rx_dropped++; |
| 234 | //drop_nr++; |
| 235 | } else { |
| 236 | skb_push(skb, ETH_HLEN); |
| 237 | |
| 238 | if(loop == pkg_len - 1) |
| 239 | { |
| 240 | skb_set_last_pkg(skb); |
| 241 | } |
| 242 | if (set_protocol_by_version(skb) < 0) |
| 243 | continue; |
| 244 | if (fast_from_driver && fast_from_driver(skb, dev->net)) |
| 245 | { |
| 246 | continue; |
| 247 | } |
| 248 | memcpy(skb->data, dev->net->dev_addr, ETH_ALEN); |
| 249 | memcpy(skb->data + ETH_ALEN, dev->net->dev_addr, ETH_ALEN); |
| 250 | spin_lock_irqsave(&dev->rxq.lock, flags); |
| 251 | __skb_queue_tail (&dev->rxq, skb); |
| 252 | spin_unlock_irqrestore(&dev->rxq.lock, flags); |
| 253 | tasklet_schedule (&dev->bh); |
| 254 | } |
| 255 | |
| 256 | } |
| 257 | |
| 258 | spin_lock_irqsave(&g_psbuf_nr_lock, spin_flag); |
| 259 | g_ddrnet_psbuf_nr = g_ddrnet_psbuf_nr + pkg_len;// - drop_nr; |
| 260 | spin_unlock_irqrestore(&g_psbuf_nr_lock, spin_flag); |
| 261 | |
| 262 | g_ddrnet_rx = g_ddrnet_rx + pkg_len;// - drop_nr; |
| 263 | |
| 264 | } |
| 265 | else |
| 266 | { |
| 267 | g_ddrnet_rx_drop++; |
| 268 | printk(KERN_WARNING " ICP data recived ERR, g_ddrnet_rx_drop %d\n", g_ddrnet_rx_drop); |
| 269 | } |
| 270 | #else |
| 271 | //while(!kthread_should_stop()) { |
| 272 | struct sk_buff *skb; |
| 273 | |
| 274 | msg.actorID = dev->actor_id; |
| 275 | msg.chID = dev->channel_id; |
| 276 | msg.buf = &psData; |
| 277 | msg.len = sizeof(struct T_FromExt_mem); |
| 278 | // msg.flag |= RPMSG_READ_POLL; |
| 279 | |
| 280 | //TODO Èç¹û½ø³ÌÍ˳öÇÒÒ»Ö±¶ÁÈ¡²»µ½Êý¾Ý£¬Õâ¸öµØ·½»á·ñÒ»Ö±¿¨×¡? |
| 281 | //while(i--); |
| 282 | if(g_zpr_ddrnet_flag1 == 0 && dev->lan) |
| 283 | { |
| 284 | msleep(5); |
| 285 | continue; |
| 286 | } |
| 287 | retval = zDrvRpMsg_Read(&msg); |
| 288 | //dbg("zDrvRpMsg_Read retval = %d, len = %d", retval, msg.len); |
| 289 | if (retval <= 0) { |
| 290 | err("no msg or threand exited"); |
| 291 | msleep(1000); |
| 292 | continue; |
| 293 | } |
| 294 | |
| 295 | skb = skb_build_psbuf(&psData); |
| 296 | |
| 297 | |
| 298 | //only test --- need check how to adjust len with peirong |
| 299 | //dbg("skb original len = %d", skb->len); |
| 300 | //skb_put(skb, psData.len); |
| 301 | //dbg("skb_put len = %d", skb->len); |
| 302 | //end |
| 303 | |
| 304 | if (!skb) { |
| 305 | err("ddrnet_icp_receive_thread can not allocate skb. drop the package"); |
| 306 | dev->net->stats.rx_dropped++; |
| 307 | } else { |
| 308 | //PSBUF_OUT( skb->head, PSBUF_MDL_AP_DDRNET_BASE, PSBUF_MDL_AP_NET_BASE ); |
| 309 | //spin_lock(&dev->rxq.lock); |
| 310 | skb_push(skb, ETH_HLEN); |
| 311 | |
| 312 | if (set_protocol_by_version(skb) < 0) |
| 313 | continue; |
| 314 | |
| 315 | if (fast_from_driver && fast_from_driver(skb, dev->net)) |
| 316 | { |
| 317 | continue; |
| 318 | } |
| 319 | |
| 320 | memcpy(skb->data, dev->net->dev_addr, ETH_ALEN); |
| 321 | memcpy(skb->data + ETH_ALEN, dev->net->dev_addr, ETH_ALEN); |
| 322 | |
| 323 | spin_lock_irqsave(&dev->rxq.lock, flags); |
| 324 | __skb_queue_tail (&dev->rxq, skb); |
| 325 | spin_unlock_irqrestore(&dev->rxq.lock, flags); |
| 326 | //spin_unlock(&dev->rxq.lock); |
| 327 | tasklet_schedule (&dev->bh); |
| 328 | } |
| 329 | #endif |
| 330 | } |
| 331 | return 0; |
| 332 | } |
| 333 | |
| 334 | static int ddrnet_icp_release_thread(void * __dev) |
| 335 | { |
| 336 | struct ddrnet *dev = (struct ddrnet *)__dev; |
| 337 | int retval; |
| 338 | #ifdef USE_DDRNET_PACKET |
| 339 | |
| 340 | struct ddrnet_package pkg = {0}; |
| 341 | int loop = 0; |
| 342 | int pkg_len = 0; |
| 343 | u8* cursor = NULL; |
| 344 | |
| 345 | #endif |
| 346 | struct sched_param param = { .sched_priority = 1 }; |
| 347 | param.sched_priority = 40; |
| 348 | //sched_setscheduler(current, SCHED_FIFO, ¶m); |
| 349 | |
| 350 | T_ZDrvRpMsg_Msg msg = { 0 }; |
| 351 | void *skb; |
| 352 | |
| 353 | //dev->channel_id = channel_8; // »ñȡͨµÀºÅ |
| 354 | |
| 355 | while(1) { |
| 356 | //while(!kthread_should_stop()) { |
| 357 | #ifdef USE_DDRNET_PACKET |
| 358 | struct sk_buff *skb; |
| 359 | msg.actorID = dev->actor_id; |
| 360 | msg.chID = channel_8; |
| 361 | msg.buf = &pkg; |
| 362 | msg.len = sizeof(struct ddrnet_package); |
| 363 | //msg.flag |= RPMSG_READ_POLL; |
| 364 | |
| 365 | retval = zDrvRpMsg_Read(&msg); |
| 366 | if (retval <= 0) { |
| 367 | err("no msg or threand exited"); |
| 368 | msleep(1000); |
| 369 | continue; |
| 370 | } |
| 371 | pkg_len = pkg.pkg_length; |
| 372 | cursor = pkg.contents; |
| 373 | //printk("release thread, pkg_len %d\n", pkg_len); |
| 374 | retval = memcmp(cursor, B_TAG, TAG_SIZE); |
| 375 | cursor += TAG_SIZE; |
| 376 | if (retval == 0) |
| 377 | retval = memcmp(cursor + pkg_len * SKB_DATA_PTR_LEN, E_TAG, TAG_SIZE); |
| 378 | if(retval == 0) |
| 379 | { |
| 380 | g_ddrnet_rx_free += pkg_len; |
| 381 | //printk("g_ddrnet_rx_free %d\n", g_ddrnet_rx_free); |
| 382 | for(loop = 0; loop < pkg_len; loop++) |
| 383 | { |
| 384 | memcpy(&skb, cursor, SKB_DATA_PTR_LEN); |
| 385 | //printk("release thread, free skb addr %#x\n", skb); |
| 386 | free_toext_mem(skb); |
| 387 | cursor += SKB_DATA_PTR_LEN; |
| 388 | } |
| 389 | } |
| 390 | else |
| 391 | { |
| 392 | g_ddrnet_rx_free_drop++; |
| 393 | printk(KERN_WARNING "ICP READ FREEBUF DATA ERR, g_ddrnet_rx_free_drop %d\n", g_ddrnet_rx_free_drop); |
| 394 | } |
| 395 | #else |
| 396 | struct sk_buff *skb; |
| 397 | msg.actorID = dev->actor_id; |
| 398 | msg.chID = channel_8; |
| 399 | msg.buf = (unsigned char *)(&skb); // Êý¾Ý |
| 400 | msg.len = SKB_DATA_PTR_LEN; // ¶ÁÈ¡µÄ³¤¶È |
| 401 | //msg.flag |= RPMSG_READ_POLL; |
| 402 | |
| 403 | retval = zDrvRpMsg_Read(&msg); // ¶ÁÈ¡»·ÐζÓÁÐÖÐÒ»¸ö½Úµã£¬ |
| 404 | if (retval <= 0) { |
| 405 | err("no msg or threand exited"); |
| 406 | msleep(1000); |
| 407 | continue; |
| 408 | } |
| 409 | //ÈôºóÐøÎ´·¢ÏÖ´æÔں˼äskbй©£¬¿ÉÒÔÖ±½ÓʹÓÃkfree_skb(skb);½Ó¿Ú½øÐÐÕý³£µÄskbÊÍ·Å,µ«ÐèÒªÓëinsert_toext_memÒ»ÆðÈ¥³ý |
| 410 | free_toext_mem(skb); |
| 411 | |
| 412 | #endif |
| 413 | } |
| 414 | } |
| 415 | static int ddrnet_start(struct net_device *net) |
| 416 | { |
| 417 | struct ddrnet *dev = netdev_priv(net); |
| 418 | int retval; |
| 419 | struct task_struct *th; |
| 420 | struct task_struct *re; |
| 421 | info("ddrnet_open %s", dev->net->name); |
| 422 | |
| 423 | if(net->flags & IFF_UP) { |
| 424 | dbg("the %s has been opened!", dev->net->name); |
| 425 | return -EBUSY; |
| 426 | } |
| 427 | netif_start_queue (net); |
| 428 | |
| 429 | //read msg from icp |
| 430 | //th = kthread_run(ddrnet_icp_receive_thread, dev, "receive-thread"); |
| 431 | if (dev->rcv_thread == NULL) { |
| 432 | th = kthread_run(ddrnet_icp_receive_thread, dev, "receive-thread"); |
| 433 | if (IS_ERR(th)) { |
| 434 | err("Unable to start receive thread."); |
| 435 | return PTR_ERR(th); |
| 436 | } |
| 437 | dev->rcv_thread = th; |
| 438 | } |
| 439 | if(dev->rel_thread == NULL) { |
| 440 | re = kthread_run(ddrnet_icp_release_thread, dev, "release-thread"); |
| 441 | if (IS_ERR(re)) { |
| 442 | err("Unable to start release thread."); |
| 443 | return PTR_ERR(re); |
| 444 | } |
| 445 | dev->rel_thread = re; |
| 446 | } |
| 447 | #ifdef USE_DDRNET_PACKET |
| 448 | if(dev->skb_wrap_thread == NULL) { |
| 449 | re = kthread_run(ddrnet_skb_wrap_thread, dev, "skb-wrap-thread"); |
| 450 | if (IS_ERR(re)) { |
| 451 | err("Unable to start packet wrap thread."); |
| 452 | return PTR_ERR(re); |
| 453 | } |
| 454 | dev->skb_wrap_thread = re; |
| 455 | } |
| 456 | |
| 457 | #endif |
| 458 | return 0; |
| 459 | } |
| 460 | |
| 461 | static int ddrnet_open(struct net_device *net) |
| 462 | { |
| 463 | info("ddrnet_open"); |
| 464 | ddrnet_start(net); |
| 465 | /* |
| 466 | struct ddrnet *dev = netdev_priv(net); |
| 467 | int retval; |
| 468 | struct task_struct *th; |
| 469 | |
| 470 | if(net->flags & IFF_UP) { |
| 471 | dbg("the %s has been opened!", dev->net->name); |
| 472 | return -EBUSY; |
| 473 | } |
| 474 | netif_start_queue (net); |
| 475 | |
| 476 | //read msg from icp |
| 477 | th = kthread_run(ddrnet_icp_receive_thread, dev, "receive-thread"); |
| 478 | |
| 479 | if (IS_ERR(th)) { |
| 480 | err("Unable to start receive thread."); |
| 481 | return PTR_ERR(th); |
| 482 | } |
| 483 | dev->rcv_thread = th; |
| 484 | */ |
| 485 | return 0; |
| 486 | } |
| 487 | |
| 488 | static int ddrnet_close(struct net_device *net) |
| 489 | { |
| 490 | struct ddrnet *dev = netdev_priv(net); |
| 491 | |
| 492 | info("ddrnet_close"); |
| 493 | |
| 494 | netif_stop_queue(net); |
| 495 | #if 0 |
| 496 | if(dev->rcv_thread) |
| 497 | kthread_stop(dev->rcv_thread); |
| 498 | dev->rcv_thread = NULL; |
| 499 | if(dev->rel_thread) |
| 500 | kthread_stop(dev->rel_thread); |
| 501 | dev->rel_thread = NULL; |
| 502 | #endif |
| 503 | tasklet_kill (&dev->bh); |
| 504 | } |
| 505 | |
| 506 | static int ddrnet_write_icp_message(struct ddrnet *dev,struct T_ToExt_info *psData) |
| 507 | { |
| 508 | T_ZDrvRpMsg_Msg msg; |
| 509 | |
| 510 | memset(&msg, 0, sizeof(T_ZDrvRpMsg_Msg)); |
| 511 | msg.actorID = dev->actor_id; |
| 512 | msg.chID = dev->channel_id; |
| 513 | msg.flag |= RPMSG_WRITE_INT; |
| 514 | |
| 515 | msg.buf = psData; |
| 516 | msg.len = sizeof(struct T_ToExt_info); |
| 517 | |
| 518 | return zDrvRpMsg_WriteLockIrq(&msg); |
| 519 | } |
| 520 | |
| 521 | //½«CP²à´«µÝÀ´µÄpsbufÖ¸ÕëдÈëDDR£¬ÒÔICP·½Ê½Í¨ÖªCP²à |
| 522 | void write_freepsbuf(void *head) |
| 523 | { |
| 524 | int ret = 0; |
| 525 | |
| 526 | #ifdef USE_DDRNET_PACKET |
| 527 | Try_enqueue: |
| 528 | ret = ddrnet_freepsb_packet_enqueue(head); |
| 529 | if(ret < 0) |
| 530 | { |
| 531 | printk(KERN_WARNING "ddrnet_freepsb_packet_enqueue fail, try again...ret : %d!!!!!!", ret); |
| 532 | goto Try_enqueue; |
| 533 | } |
| 534 | |
| 535 | #else |
| 536 | T_ZDrvRpMsg_Msg msg = { .actorID = PS_ID, |
| 537 | .chID = ICP_CHANNEL_DEV_BUFFREE, |
| 538 | .flag = RPMSG_WRITE_INT, |
| 539 | .buf = NULL, |
| 540 | .len = 4 }; |
| 541 | |
| 542 | msg.buf = head; |
| 543 | |
| 544 | ret = zDrvRpMsg_WriteLockIrq(&msg); |
| 545 | #endif |
| 546 | if(ret <= 0) |
| 547 | panic("write ddr err, ret : %d!!!!!!", ret); |
| 548 | |
| 549 | } |
| 550 | |
| 551 | /* Called by the kernel in order to transmit a packet. */ |
| 552 | unsigned long g_ddrnet_cpnum = 0; |
| 553 | unsigned long g_ddrnet_othernum = 0; |
| 554 | unsigned long g_ddrnet_failnum1 = 0; |
| 555 | unsigned long g_ddrnet_failnum = 0; |
| 556 | int test_retval=11; |
| 557 | static netdev_tx_t ddrnet_tx_packet(struct sk_buff *skb, struct net_device *net) |
| 558 | { |
| 559 | int length; |
| 560 | unsigned char *psbuff; |
| 561 | struct ddrnet *dev = netdev_priv(net); |
| 562 | int retval = RPMSG_ERROR; |
| 563 | unsigned long phy; |
| 564 | int needFreePsbuff = 0; |
| 565 | struct T_ToExt_info skb_info={0}; |
| 566 | struct sk_buff *skb_new; |
| 567 | |
| 568 | if (!skb) { |
| 569 | panic("skb err!!!!"); |
| 570 | } |
| 571 | //Æ«ÒÆÖÁipÍ· |
| 572 | skb_pull(skb, ETH_HLEN); |
| 573 | |
| 574 | //Ë¢ÐÂcache |
| 575 | skb = flush_skbuf(skb); |
| 576 | |
| 577 | skb_info.skb_data = virtaddr_to_phys(skb->data); |
| 578 | skb_info.skb_head = virtaddr_to_phys(skb->head); |
| 579 | skb_info.skb = skb; |
| 580 | skb_info.datalen = skb->len; |
| 581 | |
| 582 | //ÈôºóÐøÎ޺˼äskbÄÚ´æÐ¹Â©£¬¿ÉÈ¥³ý¸Ã½Ó¿Ú£¬µ«ÐèÓëfree_toext_mem½Ó¿ÚÒ»ÆðÈ¥³ý |
| 583 | insert_toext_mem(skb); |
| 584 | #ifdef USE_DDRNET_PACKET |
| 585 | retval = ddrnet_skb_packet_enqueue(dev, &skb_info); |
| 586 | #else |
| 587 | retval = ddrnet_write_icp_message(dev, &skb_info); |
| 588 | #endif |
| 589 | test_retval = retval; |
| 590 | if (retval > 0) { |
| 591 | net->trans_start = jiffies; |
| 592 | net->stats.tx_packets++; |
| 593 | net->stats.tx_bytes += skb->len; |
| 594 | return NET_XMIT_SUCCESS; |
| 595 | } else { |
| 596 | //panic("write err, ret : %d!!!!", retval); |
| 597 | printk("write err, ret : %d!!!!", retval); |
| 598 | free_toext_mem(skb); |
| 599 | //return NET_XMIT_DROP; |
| 600 | return NET_XMIT_SUCCESS; |
| 601 | } |
| 602 | |
| 603 | } |
| 604 | |
| 605 | #if 0 |
| 606 | { |
| 607 | int length; |
| 608 | unsigned char *psbuff; |
| 609 | struct ddrnet *dev = netdev_priv(net); |
| 610 | int retval = RPMSG_ERROR; |
| 611 | unsigned long phy; |
| 612 | int needFreePsbuff = 0; |
| 613 | |
| 614 | //dbg("in ddr_ap_tx_packet, location = %d, data = 0x%X, len = %d\n", skb->location, skb->data, skb->len); |
| 615 | |
| 616 | if (!skb) { |
| 617 | err("ddrnet_tx_packet psbuff null"); |
| 618 | return NET_XMIT_DROP; |
| 619 | } |
| 620 | |
| 621 | length = skb->len; |
| 622 | |
| 623 | if (SKB_LOCATION_AP == skb->location || skb->cloned == 1) { |
| 624 | psbuff = alloc_psbuff(); |
| 625 | if (!psbuff) { |
| 626 | //err("ddrnet_tx_packet can not alloc_psbuff"); |
| 627 | net->stats.tx_dropped++; |
| 628 | g_ddrnet_failnum1++; |
| 629 | goto out; |
| 630 | //return NET_XMIT_DROP; |
| 631 | } |
| 632 | memcpy(psbuff, skb->data, length); |
| 633 | PSBUF_IN( psbuff, PSBUF_MDL_AP_DDRNET_BASE+1 ); |
| 634 | } else { |
| 635 | //err("ddrnet_tx_packet location is not AP"); |
| 636 | |
| 637 | if(SKB_LOCATION_CP == skb->location) |
| 638 | { |
| 639 | g_ddrnet_cpnum++; |
| 640 | psbuff = skb->data; |
| 641 | } |
| 642 | else |
| 643 | { |
| 644 | err("@!@ddrnet_tx_packet location is not AP %d",skb->location); |
| 645 | g_ddrnet_othernum++; |
| 646 | } |
| 647 | PSBUF_IN( skb->head, PSBUF_MDL_AP_DDRNET_BASE+2 ); |
| 648 | } |
| 649 | |
| 650 | /* if(dev->channel_id == LAN1) |
| 651 | { |
| 652 | memmove(psbuff - 2, psbuff, length); |
| 653 | psbuff = psbuff - 2; |
| 654 | } |
| 655 | |
| 656 | */ |
| 657 | if (psbuff_virt_to_phys(psbuff, &phy) != 1) { |
| 658 | //free_psbuff(psbuff); |
| 659 | |
| 660 | err("ddrnet_tx_packet psbuff_virt_to_phys error psbuff: 0x%x", psbuff); |
| 661 | net->stats.tx_dropped++; |
| 662 | g_ddrnet_failnum++; |
| 663 | goto out; |
| 664 | //return NET_XMIT_DROP; |
| 665 | } |
| 666 | #if 0 |
| 667 | if((dev->channel_id == channel_4) ||(dev->channel_id == channel_5) |
| 668 | ||(dev->channel_id == channel_6) ||(dev->channel_id == channel_10)) |
| 669 | { |
| 670 | #endif |
| 671 | if(phy > SKB_DATA_DLPSBUFF_OFFSET) |
| 672 | { |
| 673 | needFreePsbuff = 1; |
| 674 | goto out; |
| 675 | } |
| 676 | //} |
| 677 | |
| 678 | //dbg("ddr_ap_tx_packet virtual = 0x%X, phy = 0x%X", psbuff, phy); |
| 679 | |
| 680 | PSBUF_OUT( psbuff, PSBUF_MDL_AP_DDRNET_BASE, PSBUF_MDL_CP_CTRM_BASE ); |
| 681 | retval = ddrnet_write_icp_message(dev, phy, length); |
| 682 | //retval = ddrnet_write_icp_message(dev, psbuff, length); |
| 683 | if (retval > 0) { |
| 684 | net->trans_start = jiffies; |
| 685 | net->stats.tx_packets++; |
| 686 | net->stats.tx_bytes += length; |
| 687 | //dbg("> tx, len %d, type 0x%x", length, skb->protocol); |
| 688 | } else { |
| 689 | net->stats.tx_dropped++; |
| 690 | channelResult(retval); |
| 691 | needFreePsbuff = 1; |
| 692 | } |
| 693 | |
| 694 | out: |
| 695 | if (SKB_LOCATION_CP != skb->location || skb->cloned == 1 || needFreePsbuff) { |
| 696 | dev_kfree_skb_any (skb); |
| 697 | } else { |
| 698 | kfree_7510_skb(skb); |
| 699 | } |
| 700 | |
| 701 | //dbg("transmit result = %d\n", retval); |
| 702 | |
| 703 | if (retval > 0) |
| 704 | return NET_XMIT_SUCCESS; |
| 705 | else |
| 706 | return NET_XMIT_DROP; |
| 707 | } |
| 708 | #endif |
| 709 | |
| 710 | /* Called by the kernel when transmit times out */ |
| 711 | static void ddrnet_tx_timeout(struct net_device *net) |
| 712 | { |
| 713 | err("sent timeout!"); |
| 714 | net->stats.tx_errors++; |
| 715 | netif_wake_queue(net); |
| 716 | } |
| 717 | |
| 718 | static struct net_device_stats *ddrnet_get_stats(struct net_device *net) |
| 719 | { |
| 720 | // dbg("%s: request for stats\n", net->name); |
| 721 | return &net->stats; |
| 722 | } |
| 723 | |
| 724 | static const struct net_device_ops ddr_netdev_ops = { |
| 725 | .ndo_open = ddrnet_open, |
| 726 | .ndo_stop = ddrnet_close, |
| 727 | .ndo_start_xmit = ddrnet_tx_packet, |
| 728 | .ndo_tx_timeout = ddrnet_tx_timeout, |
| 729 | .ndo_get_stats = ddrnet_get_stats, |
| 730 | }; |
| 731 | |
| 732 | static inline void ddrnet_init_netdev(struct net_device *net) |
| 733 | { |
| 734 | //memset(net->dev_addr, 0xfe, ETH_ALEN); |
| 735 | #if 0 |
| 736 | u8 mac[ETH_ALEN] = {0x0, 0xa0, 0xc6, 0x11, 0x22, 0x33}; |
| 737 | memcpy(net->dev_addr, mac, ETH_ALEN); |
| 738 | #else |
| 739 | // randomly generated ethernet address |
| 740 | static u8 node_id [ETH_ALEN]; |
| 741 | random_ether_addr(node_id); |
| 742 | memcpy (net->dev_addr, node_id, sizeof node_id); |
| 743 | #endif |
| 744 | net->netdev_ops = &ddr_netdev_ops; |
| 745 | net->watchdog_timeo = WATCHDOG_TIMEO; |
| 746 | net->flags |= IFF_NOARP; |
| 747 | } |
| 748 | |
| 749 | static inline int ddrnet_createIcpChannel(struct ddrnet *dev) |
| 750 | { |
| 751 | int retval; |
| 752 | |
| 753 | //creata channel --- send/receive use the same channel |
| 754 | retval = zDrvRpMsg_CreateChannel (dev->actor_id, dev->channel_id, dev->channel_size); |
| 755 | channelResult(retval); |
| 756 | if(retval != RPMSG_SUCCESS && retval != RPMSG_CHANNEL_ALREADY_EXIST) |
| 757 | goto out; |
| 758 | |
| 759 | return retval; |
| 760 | |
| 761 | out: |
| 762 | err("could not create channel."); |
| 763 | return retval; |
| 764 | } |
| 765 | |
| 766 | #ifdef USE_DDRNET_PACKET |
| 767 | static inline void ddrnet_init_wraper(struct ddrnet* dev) |
| 768 | { |
| 769 | u32 spin_flag = 0; |
| 770 | struct ddrnet_skb_packet* packet = NULL; |
| 771 | u32 loop = 0; |
| 772 | |
| 773 | ddrnet_init_queue(&dev->skb_que); |
| 774 | ddrnet_init_queue(&dev->skb_que_free); |
| 775 | packet = (struct ddrnet_skb_packet*)kmalloc(DDRNET_SKB_PACKET_SIZE * DDRNET_PACKET_QUEUE_COUNT, GFP_ATOMIC); |
| 776 | |
| 777 | spin_lock_irqsave(&dev->skb_que_free.lock, spin_flag); |
| 778 | |
| 779 | for (loop = 0; loop < DDRNET_PACKET_QUEUE_COUNT; loop++) |
| 780 | { |
| 781 | ddrnet_list_insert_tail(&packet->list, &dev->skb_que_free.queue); |
| 782 | packet++; |
| 783 | } |
| 784 | dev->skb_que_free.qlen = DDRNET_PACKET_QUEUE_COUNT; |
| 785 | |
| 786 | spin_unlock_irqrestore(&dev->skb_que_free.lock, spin_flag); |
| 787 | sema_init(&dev->skb_que_sem,1); |
| 788 | |
| 789 | init_timer(&dev->wrap_timer); |
| 790 | dev->wrap_timer.data = (u32) dev; |
| 791 | dev->wrap_timer.function = ddrnet_skb_Wrap_TimerCallBack; |
| 792 | add_timer(&dev->wrap_timer); |
| 793 | |
| 794 | } |
| 795 | #endif |
| 796 | static inline void ddrnet_init_lan(struct net_device *net, unsigned int index) |
| 797 | { |
| 798 | struct ddrnet *dev; |
| 799 | dev = netdev_priv(net); |
| 800 | dev->net = net; |
| 801 | strcpy(net->name, "lan%d"); |
| 802 | dev->lan = 1; |
| 803 | dev->actor_id = PS_ID; |
| 804 | // dev->channel_id = LAN1; |
| 805 | dev->channel_id = ddr_net_collect[index][1]; |
| 806 | dev->channel_size = ICP_CHANNEL_SIZE; |
| 807 | skb_queue_head_init (&dev->rxq); |
| 808 | } |
| 809 | |
| 810 | static inline void ddrnet_init_wan(struct net_device *net, unsigned int index) |
| 811 | { |
| 812 | struct ddrnet *dev; |
| 813 | unsigned wan_index; |
| 814 | dev = netdev_priv(net); |
| 815 | dev->net = net; |
| 816 | //strcpy(net->name, "wan%d"); |
| 817 | wan_index = index + 1; // WAN1, WAN2,.... |
| 818 | sprintf(net->name, "wan%d", wan_index); |
| 819 | dev->lan = 0; |
| 820 | dev->actor_id = PS_ID; |
| 821 | //dev->channel_id = WAN; |
| 822 | dev->channel_id = ddr_net_collect[index][1]; |
| 823 | dev->channel_size = ICP_CHANNEL_SIZE; |
| 824 | skb_queue_head_init (&dev->rxq); |
| 825 | } |
| 826 | |
| 827 | static void ddrnet_skb_return (struct ddrnet *dev, struct sk_buff *skb) |
| 828 | { |
| 829 | int status; |
| 830 | |
| 831 | skb->protocol = eth_type_trans (skb, dev->net); |
| 832 | |
| 833 | status = netif_rx (skb); |
| 834 | if (status == NET_RX_SUCCESS) { |
| 835 | dev->net->stats.rx_packets++; |
| 836 | dev->net->stats.rx_bytes += skb->len; |
| 837 | } else { |
| 838 | dev->net->stats.rx_errors++; |
| 839 | err("netif_rx status %d.", status); |
| 840 | } |
| 841 | } |
| 842 | |
| 843 | static void ddrnet_bh (unsigned long param) |
| 844 | { |
| 845 | struct ddrnet *dev = (struct ddrnet *)param; |
| 846 | struct sk_buff *skb; |
| 847 | |
| 848 | while(skb = skb_dequeue(&dev->rxq)) { |
| 849 | if (skb->len) |
| 850 | ddrnet_skb_return(dev, skb); |
| 851 | else { |
| 852 | dev->net->stats.rx_errors++; |
| 853 | |
| 854 | dev_kfree_skb (skb); |
| 855 | err("drop!!!ddrnet_bh skb len == 0."); |
| 856 | } |
| 857 | } |
| 858 | } |
| 859 | int flag_zDrvRpMsg=0x5a; |
| 860 | int *vir_addr_ddrnet = NULL; |
| 861 | EXPORT_SYMBOL(vir_addr_ddrnet); |
| 862 | |
| 863 | static int __init ddrnet_init(void) |
| 864 | { |
| 865 | int i; |
| 866 | int err; |
| 867 | struct ddrnet *dev; |
| 868 | struct net_device *net; |
| 869 | |
| 870 | #ifdef USE_DDRNET_PACKET |
| 871 | u32 loop = 0; |
| 872 | u32 spin_flag = 0; |
| 873 | struct ddrnet_psbuf_packet* packet = NULL; |
| 874 | #endif |
| 875 | dbg("ddr_ap_net_lan_init.\n"); |
| 876 | |
| 877 | err = -ENOMEM; |
| 878 | for (i = 0; i < DDR_DEV_MAX; i++){ |
| 879 | //for (i = 0; i < 1; i++) { |
| 880 | net = alloc_etherdev(sizeof(struct ddrnet)); |
| 881 | if (!net) { |
| 882 | printk(KERN_ERR "could not allocate device.\n"); |
| 883 | return err; |
| 884 | } |
| 885 | |
| 886 | //È·±£ËùÓз¢Íùcp²àµÄÊý¾ÝÍ·²¿Ô¤Áô×ã¹»£¬±ÜÃâË¢cacheµÄʱºòÖØÐÂÉêÇëskb |
| 887 | net->needed_headroom += NET_SKB_PAD - ETH_HLEN; |
| 888 | |
| 889 | dev = netdev_priv(net); |
| 890 | debug_ddrnet[i] = dev; |
| 891 | |
| 892 | if(ddr_net_collect[i][2] == NET_LAN) |
| 893 | ddrnet_init_lan(net, i); |
| 894 | else if (ddr_net_collect[i][2] == NET_WAN) |
| 895 | ddrnet_init_wan(net, i); |
| 896 | else |
| 897 | goto out_free_netdev; |
| 898 | |
| 899 | dev->net = net; |
| 900 | dev->bh.func = ddrnet_bh; |
| 901 | dev->bh.data = (unsigned long) dev; |
| 902 | dev->rcv_thread = NULL; |
| 903 | dev->rel_thread = NULL; |
| 904 | #ifdef USE_DDRNET_PACKET |
| 905 | dev->skb_wrap_thread == NULL; |
| 906 | #endif |
| 907 | ddrnet_init_netdev(net); |
| 908 | ddrnet_createIcpChannel(dev); |
| 909 | #ifdef USE_DDRNET_PACKET |
| 910 | ddrnet_init_wraper(dev); |
| 911 | #endif |
| 912 | err = register_netdev(net); |
| 913 | if (err) |
| 914 | goto out_free_netdev; |
| 915 | ddrnet_dev[i] = net; |
| 916 | |
| 917 | // ddrnet_start(net); |
| 918 | } |
| 919 | |
| 920 | { |
| 921 | flag_zDrvRpMsg=zDrvRpMsg_CreateChannel (PS_ID, ICP_CHANNEL_DEV_BUFFREE, 16*1024); |
| 922 | #ifdef USE_DDRNET_PACKET |
| 923 | spin_lock_init(&g_psbuf_nr_lock); |
| 924 | ddrnet_init_queue(&free_psb_que); |
| 925 | ddrnet_init_queue(&free_psb_que_free); |
| 926 | sema_init(&freepsb_que_sem, 1); |
| 927 | packet = (struct ddrnet_psbuf_packet*)kmalloc(DDRNET_PSB_PACKET_SIZE * DDRNET_PACKET_QUEUE_COUNT, GFP_ATOMIC); |
| 928 | |
| 929 | spin_lock_irqsave(&free_psb_que_free.lock, spin_flag); |
| 930 | for (loop = 0; loop < DDRNET_PACKET_QUEUE_COUNT; loop++) |
| 931 | { |
| 932 | ddrnet_list_insert_tail(&packet->list, &free_psb_que_free.queue); |
| 933 | packet++; |
| 934 | } |
| 935 | free_psb_que_free.qlen = DDRNET_PACKET_QUEUE_COUNT; |
| 936 | spin_unlock_irqrestore(&free_psb_que_free.lock, spin_flag); |
| 937 | |
| 938 | if(freepsb_wrap_thread == NULL) { |
| 939 | freepsb_wrap_thread = kthread_run(ddrnet_freepsb_wrap_thread, 0, "freepsb-wrap-thread"); |
| 940 | if (IS_ERR(freepsb_wrap_thread)) { |
| 941 | err("Unable to start packet wrap thread."); |
| 942 | return PTR_ERR(freepsb_wrap_thread); |
| 943 | } |
| 944 | } |
| 945 | init_timer(&freepsb_wrap_timer); |
| 946 | freepsb_wrap_timer.data = NULL; |
| 947 | freepsb_wrap_timer.function = ddrnet_freepsb_Wrap_TimerCallBack; |
| 948 | add_timer(&freepsb_wrap_timer); |
| 949 | #endif |
| 950 | } |
| 951 | |
| 952 | |
| 953 | vir_addr_ddrnet = ioremap_cached(PSBUFFER_MEM_BASE, PSBUFFER_MEM_SIZE); |
| 954 | if(vir_addr_ddrnet == NULL) |
| 955 | { |
| 956 | printk(KERN_WARNING "Warning: [zx297510] cp ps_buf mmap failed.\n"); |
| 957 | panic("Warning: [zx297510] cp ps_buf mmap failed.\n"); |
| 958 | } |
| 959 | |
| 960 | return 0; |
| 961 | |
| 962 | out_free_netdev: |
| 963 | free_netdev(net); |
| 964 | return err; |
| 965 | } |
| 966 | late_initcall(ddrnet_init); |
| 967 | |
| 968 | static void __exit ddrnet_exit(void) |
| 969 | { |
| 970 | int i; |
| 971 | struct net_device *net; |
| 972 | |
| 973 | for (i = 0; i < DDR_DEV_MAX; i++) { |
| 974 | if ((net = ddrnet_dev[i])) { |
| 975 | unregister_netdev(net); |
| 976 | free_netdev(net); |
| 977 | ddrnet_dev[i] = NULL; |
| 978 | } |
| 979 | } |
| 980 | } |
| 981 | module_exit(ddrnet_exit); |
| 982 | |
| 983 | MODULE_AUTHOR("P96G"); |
| 984 | MODULE_DESCRIPTION("7510 AP Lan Net Device"); |
| 985 | MODULE_LICENSE("GPL"); |