Example #1
0
/* Called in wq context */
void xmd_net_notify(int chno)
{
	int i;
	struct net_device *dev = NULL;
	void *buf = NULL;
	int tot_sz = 0;
	struct rmnet_private *p = NULL;
	struct xmd_ch_info *info = NULL;

	for (i=0; i<ARRAY_SIZE(rmnet_channels); i++) {
		if (rmnet_channels[i].chno == chno)	{
			dev = (struct net_device *)rmnet_channels[i].priv;
			break;
		}
	}

	if (!dev) {
#if defined (RMNET_ERR)
        dynadbg_module(DYNADBG_WARN|DYNADBG_RX,"xmd_net_notify: No device \n");
		printk("xmd_net_notify: No device \n");
#endif
		return;
	}

	p = netdev_priv(dev);
	if (!p)
		return;

	info = p->ch;
	if (!info)
		return;

	/* contains the full data read from hsi channel.*/
    buf = netdatabuffer;
	tot_sz = data_size;
	if (!buf) {
#if defined (RMNET_ERR)
        dynadbg_module(DYNADBG_WARN|DYNADBG_RX,"xmd_net_notify: No buf recvd from ch:%d \n", info->chno);
		printk("xmd_net_notify: No buf recvd from ch:%d tot_sz :%d\n", info->chno,tot_sz);
#endif
		return;
	}
#if defined (RMNET_DEBUG)
    dynadbg_module(DYNADBG_DEBUG|DYNADBG_RX,"xmd_net_notify: total size read = %d from ch:%d \n", tot_sz, info->chno);
	printk("xmd_net_notify: total size read = %d from ch:%d \n",
			tot_sz, info->chno);
#endif

	switch (past_packet.state)
	{
	case RMNET_FULL_PACKET:
		/* no need to do anything */
	break;

	case RMNET_PARTIAL_PACKET:
	{
		void *ip_hdr = (void *)past_packet.buf;
		int sz;
		int copy_size;

#if defined (RMNET_DEBUG)
        dynadbg_module(DYNADBG_DEBUG|DYNADBG_RX,"xmd_net_notify: past partial packet\n");
		printk("xmd_net_notify: past partial packet\n");
#endif
		if (past_packet.type == RMNET_IPV4_VER) {
			sz = ntohs(((struct iphdr*) ip_hdr)->tot_len);
		} else if (past_packet.type == RMNET_IPV6_VER) {
			sz = ntohs(((struct ipv6hdr*) ip_hdr)->payload_len) + sizeof(struct ipv6hdr);
		} else {
#if defined (RMNET_ERR)
        dynadbg_module(DYNADBG_WARN|DYNADBG_RX,"xmd_net_notify: Invalid past version (data), %d\n",
					past_packet.type);
		printk("xmd_net_notify: Invalid past version (data), %d\n",
					past_packet.type);
#endif
			rmnet_reset_pastpacket_info();
			return;
		}
		if(sz > RMNET_DATAT_SIZE) {
			printk(KERN_INFO"rmnet partial packet size too large, sz=%d,can not handle\n",sz);
			rmnet_reset_pastpacket_info();
			return;
		}

		copy_size = sz - past_packet.size;

		 /* if read size if > then copy size, copy full packet.*/
		if (tot_sz >= copy_size) {
			memcpy(past_packet.buf + past_packet.size,buf,copy_size);
		} else {
			/* copy whatever read if read size < packet size.*/
			memcpy(past_packet.buf + past_packet.size,buf,tot_sz);
#if defined (RMNET_DEBUG)
        dynadbg_module(DYNADBG_DEBUG|DYNADBG_RX,"\nxmd_net_notify: RMNET_PARTIAL_PACKET. past size = %d,"
					" total size = %d\n", past_packet.size, tot_sz);
		printk("\nxmd_net_notify: RMNET_PARTIAL_PACKET. past size = %d,"
					" total size = %d\n", past_packet.size, tot_sz);
#endif
			past_packet.size += tot_sz;
			return;
		}

		xmd_trans_packet(dev,past_packet.type,(void*)past_packet.buf,sz);
#if defined (RMNET_DEBUG)
        dynadbg_module(DYNADBG_DEBUG|DYNADBG_RX,"xmd_net_notify: pushed reassembled data packet to tcpip,"
				" sz = %d\n", sz);
		printk("xmd_net_notify: pushed reassembled data packet to tcpip,"
				" sz = %d\n", sz);
#endif
		buf = buf + copy_size;
		tot_sz = tot_sz - copy_size;
		past_packet.state = RMNET_FULL_PACKET;
	}
	break;

	case RMNET_PARTIAL_HEADER:
	{
		void *ip_hdr = (void *)past_packet.buf;
		int sz;
		int copy_size;
		int hdr_size = 0;

#if defined (RMNET_DEBUG)
        dynadbg_module(DYNADBG_DEBUG|DYNADBG_RX,"xmd_net_notify: past partial header packet\n");
		printk("xmd_net_notify: past partial header packet\n");
#endif
		if (past_packet.type == RMNET_IPV4_VER)
			hdr_size = sizeof(struct iphdr);
		else if (past_packet.type  == RMNET_IPV6_VER)
			hdr_size = sizeof(struct ipv6hdr);
		else
		{
#if defined (RMNET_ERR)
        dynadbg_module(DYNADBG_WARN|DYNADBG_RX,"xmd_net_notify: Invalid past version (hdr), %d\n",
					past_packet.type);
       printk("xmd_net_notify: Invalid past version (hdr), %d\n",
					past_packet.type);
#endif
			past_packet.state = RMNET_FULL_PACKET;
			return;
		}

		copy_size = hdr_size - past_packet.size;

		if(tot_sz >= copy_size) {
			memcpy(past_packet.buf + past_packet.size,buf,copy_size);
		} else {
			/* copy whatever read if read size < packet size. */
			memcpy(past_packet.buf + past_packet.size,buf,tot_sz);
#if defined (RMNET_DEBUG)
            dynadbg_module(DYNADBG_DEBUG|DYNADBG_RX,"xmd_net_notify: Still partial header \n");
			printk("xmd_net_notify: Still partial header \n");
#endif
			past_packet.size += tot_sz;
			return;
		}

		buf = buf + copy_size;
		tot_sz = tot_sz - copy_size;
		past_packet.size = past_packet.size + copy_size;

		if (past_packet.type == RMNET_IPV4_VER) {
			sz = ntohs(((struct iphdr*) ip_hdr)->tot_len);
		} else if (past_packet.type == RMNET_IPV6_VER) {
			sz = ntohs(((struct ipv6hdr*) ip_hdr)->payload_len) + sizeof(struct ipv6hdr);
		} else {
#if defined (RMNET_ERR)
           dynadbg_module(DYNADBG_WARN|DYNADBG_RX,"xmd_net_notify: Invalid past version, %d\n",
						past_packet.type);
			printk("xmd_net_notify: Invalid past version, %d\n",
						past_packet.type);
#endif
			past_packet.state = RMNET_FULL_PACKET;
			return;
		}

		copy_size = sz - past_packet.size;

		 /* if read size if > then copy size, copy full packet. */
		if (tot_sz >= copy_size) {
			memcpy(past_packet.buf + past_packet.size,buf,copy_size);
		} else {
			/* copy whatever read if read size < packet size.*/
			memcpy(past_packet.buf + past_packet.size,buf,tot_sz);
#if defined (RMNET_DEBUG)
         dynadbg_module(DYNADBG_DEBUG|DYNADBG_RX,"\nxmd_net_notify: RMNET_PARTIAL_HEADER. past size = %d,"
					" total size = %d\n", past_packet.size, tot_sz);
         printk("\nxmd_net_notify: RMNET_PARTIAL_HEADER. past size = %d,"
					" total size = %d\n", past_packet.size, tot_sz);
#endif
			past_packet.size += tot_sz;
			past_packet.state = RMNET_PARTIAL_PACKET;
			return;
		}

		xmd_trans_packet(dev,past_packet.type,(void *)past_packet.buf,sz);

		buf = buf + copy_size;
		tot_sz = tot_sz - copy_size;

	}
	break;

	default:
#if defined (RMNET_ERR)
        dynadbg_module(DYNADBG_WARN|DYNADBG_RX,"xmd_net_notify: Invalid past state %d\n",
				(int)past_packet.state);
         printk("xmd_net_notify: Invalid past state %d\n",
				(int)past_packet.state);
#endif
		past_packet.state = RMNET_FULL_PACKET;
		break;
	}

	while (tot_sz) {
		int hdr_size = 0;
		int ver = 0;
		void *ip_hdr = (void *)buf;
		int data_sz = 0;

#if defined(__BIG_ENDIAN_BITFIELD)
		ver = ((char *)buf)[0] & 0x0F;
#elif defined(__LITTLE_ENDIAN_BITFIELD)
		ver = (((char *)buf)[0] & 0xF0) >> 4;
#endif

#if defined (RMNET_DEBUG)
        dynadbg_module(DYNADBG_DEBUG|DYNADBG_RX,"xmd_net_notify: ver = 0x%x, total size : %d \n", ver, tot_sz);
		printk("xmd_net_notify: ver = 0x%x, total size : %d \n", ver, tot_sz);
#endif

		if (ver == RMNET_IPV4_VER) {
			hdr_size = sizeof(struct iphdr);
		} else if (ver == RMNET_IPV6_VER) {
			hdr_size = sizeof(struct ipv6hdr);
		} else {
#if defined (RMNET_ERR)
            if( ( (dynamic_debug_mask)&((DYNADBG_DEBUG)|(DYNADBG_RX)|(DYNADBG_XMD_NET_EN)|(DYNADBG_GLOBAL_EN)) ) == \
                            ((DYNADBG_DEBUG)|(DYNADBG_RX)|(DYNADBG_XMD_NET_EN)|(DYNADBG_GLOBAL_EN)) ){
			void *ip_hdr = (char*)(buf+4);
			int tmp_sz = ntohs(((struct iphdr*) ip_hdr)->tot_len);
            
			printk("xmd_net_notify: Invalid version, 0x%x\n", ver);
			printk("xmd_net_notify: Few bytes of pkt : 0x%x 0x%x 0x%x 0x%x "
					"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",	((char *)buf)[0],
					((char *)buf)[1], ((char *)buf)[2], ((char *)buf)[3],
					((char *)buf)[4], ((char *)buf)[5], ((char *)buf)[6],
					((char *)buf)[7], ((char *)buf)[8], ((char *)buf)[9],
					((char *)buf)[10]);
			printk("xmd_net_notify: Current packet size = %d,"
					"ip packet size = %d\n",tot_sz,tmp_sz);
            }
#endif
			past_packet.state = RMNET_FULL_PACKET;
			break;
		}

		if (tot_sz < 6) {
#if defined (RMNET_ERR)
                   dynadbg_module(DYNADBG_WARN|DYNADBG_RX,"xmd_net_notify:buf size insufficient to decode pkt length\n");
			printk("xmd_net_notify:buf size insufficient to decode pkt length\n");
#endif
			past_packet.state = RMNET_FULL_PACKET;
			return;
		}

		if (tot_sz < hdr_size) {
			past_packet.state = RMNET_PARTIAL_HEADER;
			past_packet.size = tot_sz;
			memcpy(past_packet.buf, buf, tot_sz);
			past_packet.type = ver;
#if defined (RMNET_DEBUG)
          dynadbg_module(DYNADBG_DEBUG|DYNADBG_RX,"xmd_net_notify: partial header packet copied locally,"
					" sz = %d\n", tot_sz);
		printk("xmd_net_notify: partial header packet copied locally,"
					" sz = %d\n", tot_sz);
#endif
			return;
		}

		if (ver == RMNET_IPV4_VER) {
			data_sz = ntohs(((struct iphdr*) ip_hdr)->tot_len);
			if (data_sz < sizeof(struct iphdr)){
				printk(KERN_INFO"rmnet receive ipv4 pkt too small, data_sz=%d,can not handle\n",data_sz);
				rmnet_reset_pastpacket_info();
				return;
			}
		} else if (ver == RMNET_IPV6_VER) {
			data_sz = ntohs(((struct ipv6hdr*) ip_hdr)->payload_len) + sizeof(struct ipv6hdr);
		} else {
#if defined (RMNET_ERR)
         dynadbg_module(DYNADBG_WARN|DYNADBG_RX,"xmd_net_notify: data sz check -- "
					"Invalid version, %d\n",ver);
		printk("xmd_net_notify: data sz check -- "
					"Invalid version, %d\n",ver);
#endif
			past_packet.state = RMNET_FULL_PACKET;
			break;
        }

		if(data_sz > RMNET_DATAT_SIZE) {
			printk(KERN_INFO"rmnet full packet size too large, sz=%d,can not handle\n",data_sz);
			rmnet_reset_pastpacket_info();
			return;
		}

#if defined (RMNET_DEBUG)
        dynadbg_module(DYNADBG_DEBUG|DYNADBG_RX,"xmd_net_notify: data size = %d\n", data_sz);
		printk("xmd_net_notify: data size = %d\n", data_sz);
#endif

		if (tot_sz < data_sz) {
			past_packet.state = RMNET_PARTIAL_PACKET;
			past_packet.size = tot_sz;
			memcpy(past_packet.buf, buf, tot_sz);
			past_packet.type = ver;
#if defined (RMNET_DEBUG)
        dynadbg_module(DYNADBG_DEBUG|DYNADBG_RX,"xmd_net_notify: partial data packet copied locally,"
					" sz = %d\n", tot_sz);
		printk("xmd_net_notify: partial data packet copied locally,"
					" sz = %d\n", tot_sz);
#endif
			return;
		}

		xmd_trans_packet(dev, ver, buf, data_sz);
#if defined (RMNET_DEBUG)
         dynadbg_module(DYNADBG_DEBUG|DYNADBG_RX,"xmd_net_notify: pushed full data packet to tcpip, "
				"sz = %d\n", data_sz);
		printk("xmd_net_notify: pushed full data packet to tcpip, "
				"sz = %d\n", data_sz);
#endif
		tot_sz = tot_sz - data_sz;
		buf = buf + data_sz;
#if defined (RMNET_DEBUG)
     dynadbg_module(DYNADBG_DEBUG|DYNADBG_RX,"xmd_net_notify: looping for another packet"
				" tot_sz = %d\n", tot_sz);
		printk("xmd_net_notify: looping for another packet"
				" tot_sz = %d\n", tot_sz);
#endif
	}

	past_packet.state = RMNET_FULL_PACKET;
}
Example #2
0
static void xmd_net_notify(int chno)
{
	int i, rc = 0;
	struct net_device *dev = NULL;
	void *buf = NULL;
	int tot_sz = 0, realign_count = 0;
	struct rmnet_private *p = NULL;
	struct xmd_ch_info *info = NULL;

	for (i=0; i<ARRAY_SIZE(rmnet_channels); i++) {
		if (rmnet_channels[i].chno == chno)	{
			dev = (struct net_device *)rmnet_channels[i].priv;
			break;
		}
	}

	if (!dev) {
#if defined (RMNET_ERR)
		printk("\n%s (line %d) No device\n", __func__, __LINE__);
#endif
		return;
	}

	p = netdev_priv(dev);
	if (!p) {
#if defined (RMNET_ERR)
		printk("\n%s (line %d) No netdev_priv\n", __func__, __LINE__);
#endif
		return;
	}

	info = p->ch;
	if (!info) {
#if defined (RMNET_ERR)
		printk("\n%s (line %d) No info\n", __func__, __LINE__);
#endif
		return;
	}

	/* contains the full data read from hsi channel.*/
	buf = xmd_ch_read(info->chno, &tot_sz);

	if ((!buf)||(tot_sz == 0)){
#if defined (RMNET_ERR)
		printk("\n%s (line %d) No buf recvd from ch(%d) tot_sz(%d)\n",
			__func__ ,__LINE__, info->chno, tot_sz);
#endif
		return;
	}
	
#if defined (RMNET_DEBUG)
	printk("\nxmd_net_notify: total size read = %d from ch:%d \n",
			tot_sz, info->chno);
#endif

	switch (past_packet[info->id].state)
	{
	case RMNET_FULL_PACKET:
		/* no need to do anything */
	break;

	case RMNET_PARTIAL_PACKET:
	{
		void *ip_hdr = (void *)past_packet[info->id].buf;
		int sz;
		int copy_size;

#if defined (RMNET_DEBUG)
		printk("\nxmd_net_notify: past partial packet\n");
#endif
		if (past_packet[info->id].type == RMNET_IPV4_VER) {
			sz = ntohs(((struct iphdr*) ip_hdr)->tot_len);
		} else if (past_packet[info->id].type == RMNET_IPV6_VER) {
			sz = ntohs(((struct ipv6hdr*) ip_hdr)->payload_len) + sizeof(struct ipv6hdr);
		} else {
#if defined (RMNET_ERR)
			printk("\n%s (line %d) Invalid past version(%d)\n", __func__ ,__LINE__ 
				,past_packet[info->id].type);
#endif
			rmnet_reset_pastpacket_info(info->id);
			p->stats.rx_errors++;
			return;
		}

		if((sz <= 0)||(sz > RMNET_DATAT_SIZE)) {
#if defined (RMNET_ERR)
			printk("\n%s (line %d) Invalid hdr len(%d)\n", __func__, __LINE__, sz);
			xmd_net_dump("xmd_net_notify", past_packet[info->id].buf, past_packet[info->id].size);
#endif
			rmnet_reset_pastpacket_info(info->id);
			return;
		}

		copy_size = sz - past_packet[info->id].size;

		 /* if read size if > then copy size, copy full packet.*/
		if (tot_sz >= copy_size) {
			memcpy(past_packet[info->id].buf + past_packet[info->id].size,buf,copy_size);
		} else {
			/* copy whatever read if read size < packet size.*/
			memcpy(past_packet[info->id].buf + past_packet[info->id].size,buf,tot_sz);
#if defined (RMNET_DEBUG)
			printk("\nxmd_net_notify: RMNET_PARTIAL_PACKET. past size = %d, total size = %d\n",
						past_packet[info->id].size, tot_sz);
#endif
			past_packet[info->id].size += tot_sz;
			return;
		}

		rc = xmd_trans_packet(dev,past_packet[info->id].type,(void*)past_packet[info->id].buf,sz);

		if(rc != 0) {
#if defined (RMNET_ERR)
			printk("\n%s (line %d) xmd_trans_packet fail sz(%d) tot_sz(%d)\n",
				__func__, __LINE__, sz, tot_sz);
			xmd_net_dump("xmd_net_notify", past_packet[info->id].buf, sz);
#endif
			rmnet_reset_pastpacket_info(info->id);
		}
			
#if defined (RMNET_DEBUG)
		printk("xmd_net_notify: pushed reassembled data packet to tcpip, sz = %d\n", sz);
#endif
		buf = buf + copy_size;
		tot_sz = tot_sz - copy_size;
		past_packet[info->id].state = RMNET_FULL_PACKET;
	}
	break;

	case RMNET_PARTIAL_HEADER:
	{
		void *ip_hdr = (void *)past_packet[info->id].buf;
		int sz;
		int copy_size;
		int hdr_size = 0;

#if defined (RMNET_DEBUG)
		printk("xmd_net_notify: past partial header packet\n");
#endif
		if (past_packet[info->id].type == RMNET_IPV4_VER)
			hdr_size = sizeof(struct iphdr);
		else if (past_packet[info->id].type  == RMNET_IPV6_VER)
			hdr_size = sizeof(struct ipv6hdr);
		else
		{
#if defined (RMNET_ERR)
			printk("\n%s (line %d): Invalid past version (%d)\n", __func__, __LINE__,
				past_packet[info->id].type);
#endif
			rmnet_reset_pastpacket_info(info->id);
			p->stats.rx_errors++;
			return;
		}

		copy_size = hdr_size - past_packet[info->id].size;

		if(tot_sz >= copy_size) {
			memcpy(past_packet[info->id].buf + past_packet[info->id].size,buf,copy_size);
		} else {
			/* copy whatever read if read size < packet size. */
			memcpy(past_packet[info->id].buf + past_packet[info->id].size,buf,tot_sz);
#if defined (RMNET_DEBUG)
			printk("\n%s (line %d): Still partial header\n", __func__, __LINE__);
#endif
			past_packet[info->id].size += tot_sz;
			return;
		}

		buf = buf + copy_size;
		tot_sz = tot_sz - copy_size;
		past_packet[info->id].size = past_packet[info->id].size + copy_size;

		if (past_packet[info->id].type == RMNET_IPV4_VER) {
			sz = ntohs(((struct iphdr*) ip_hdr)->tot_len);
		} else if (past_packet[info->id].type == RMNET_IPV6_VER) {
			sz = ntohs(((struct ipv6hdr*) ip_hdr)->payload_len) + sizeof(struct ipv6hdr);
		} else {
#if defined (RMNET_ERR)
			printk("\n%s (line %d): Invalid past version (%d)\n", __func__, __LINE__,
							past_packet[info->id].type);
#endif
			rmnet_reset_pastpacket_info(info->id);
			p->stats.rx_errors++;
			return;
		}

		if((sz <= 0)||(sz > RMNET_DATAT_SIZE)) {
#if defined (RMNET_ERR)
			printk("\n%s (line %d): Invalid hdr len(%d)\n", __func__, __LINE__, sz);
			xmd_net_dump("xmd_net_notify", past_packet[info->id].buf, past_packet[info->id].size);
#endif
			rmnet_reset_pastpacket_info(info->id);
			return;
		}

		copy_size = sz - past_packet[info->id].size;

		 /* if read size if > then copy size, copy full packet. */
		if (tot_sz >= copy_size) {
			memcpy(past_packet[info->id].buf + past_packet[info->id].size,buf,copy_size);
		} else {
			/* copy whatever read if read size < packet size.*/
			memcpy(past_packet[info->id].buf + past_packet[info->id].size,buf,tot_sz);
#if defined (RMNET_DEBUG)
			printk("\n%s (line %d): past size = %d, total size = %d\n",  __func__, __LINE__,
						past_packet[info->id].size, tot_sz);
#endif
			past_packet[info->id].size += tot_sz;
			past_packet[info->id].state = RMNET_PARTIAL_PACKET;
			return;
		}

		rc = xmd_trans_packet(dev,past_packet[info->id].type,(void *)past_packet[info->id].buf,sz);

		if(rc != 0) {
#if defined (RMNET_ERR)
			printk("\n%s (line %d): xmd_trans_packet fail sz(%d) tot_sz(%d)\n",
				__func__, __LINE__, sz, tot_sz);
			xmd_net_dump("xmd_net_notify", past_packet[info->id].buf, sz);
#endif
			rmnet_reset_pastpacket_info(info->id);
		}

		buf = buf + copy_size;
		tot_sz = tot_sz - copy_size;
	}
	break;

	default:
	{
#if defined (RMNET_ERR)
		printk("\n%s (line %d): Invalid past state (%d)\n", __func__, __LINE__, 
				(int)past_packet[info->id].state);
#endif
		rmnet_reset_pastpacket_info(info->id);
		p->stats.rx_errors++;
		return;
	}
	break;
	}

	while (tot_sz > 0) {
		int hdr_size = 0;
		int ver = 0;
		void *ip_hdr = (void *)buf;
		int data_sz = 0;

#if defined(__BIG_ENDIAN_BITFIELD)
		ver = ((char *)buf)[0] & 0x0F;
#elif defined(__LITTLE_ENDIAN_BITFIELD)
		ver = (((char *)buf)[0] & 0xF0) >> 4;
#endif

#if defined (RMNET_DEBUG)
		printk("xmd_net_notify: ver = 0x%x, total size : %d \n", ver, tot_sz);
#endif

		if (ver == RMNET_IPV4_VER) {
			hdr_size = sizeof(struct iphdr);
		} else if (ver == RMNET_IPV6_VER) {
			hdr_size = sizeof(struct ipv6hdr);
		} else if(NULL != strnstr((char*)buf, "+PBREADY", 12)) {
#if defined (RMNET_ERR)
			char buf_str[RMNET_ERROR_STR_SIZE];
			memset(buf_str, 0x00, RMNET_ERROR_STR_SIZE);
			memcpy(buf_str, buf, min(RMNET_ERROR_STR_SIZE, tot_sz));
			
			printk("xmd_net_notify: Converted strings %s\n", buf_str);
			printk("xmd_net_notify: Left packet size = %d, \n", tot_sz);
			printk("xmd_net_notify: Modem slient reset, so down rmnet \n");
#endif
			rmnet_sync_down_for_recovery();
			break;
		}
		else if ((NULL != strnstr((char*)buf, "ERROR", 9))||
				(NULL != strnstr((char*)buf, "NO CARRIER", 14))) {
#if defined (RMNET_ERR)
				char buf_str[RMNET_ERROR_STR_SIZE];
				memset(buf_str, 0x00, RMNET_ERROR_STR_SIZE);
				memcpy(buf_str, buf, min(RMNET_ERROR_STR_SIZE, tot_sz));

				printk("xmd_net_notify: Converted strings %s\n", buf_str);
				printk("xmd_net_notify: Left packet size = %d, \n", tot_sz);
#endif
				break;
		}
		else {
			if((realign_count < MAX_RMNET_REALIGN_COUNT) && (tot_sz > 1)) {
#if defined (RMNET_ERR)
				if(realign_count == 0) {
					printk("\n%s (line %d) ch:%d Invalid version 0x%x\n", __func__, __LINE__, info->chno, ver);
					xmd_net_dump("xmd_net_notify", buf, tot_sz);
				}
#endif

				buf++; tot_sz--;
				realign_count++;

				rmnet_reset_pastpacket_info(info->id);
				continue;
			}
			else {
#if defined (RMNET_ERR)
				printk("\n%s (line %d) ch:%d Invalid ver 0x%x realign_count(%d)\n", 
					__func__, __LINE__, info->chno, ver, realign_count);
#endif
				break;
			}
		}
		
#if 0
		else {

			/***********************************************************************
				1. Case of "+PBREADY" : RIL recovery is needed
					Modem resets because of low battery without any modem's notification 
			***********************************************************************/
			if(NULL != strnstr((char*)buf, "+PBREADY", 12)) {
								
#if defined (RMNET_ERR)
				printk("xmd_net_notify: +PBREADY Left packet size= %d\n", tot_sz);
#endif
				rmnet_reset_pastpacket_info(info->id);

#if 0
				/* Start RIL recovery */
				ifx_schedule_cp_dump_or_reset();
#endif
			}

			/**********************************************************************************
				1. Case of "NO CARRIER"
					PDP is disconnected and modem sends "NO CARRIER"
					
				2. Case of "ERROR"
					Left packet data in XMD DLP queue is transimited after network or PDP is disconnected.
					The data  is sent to CAT (modem) and CAT responds "Error"

				3. TODO: Other cases should be checked
			**********************************************************************************/
			else {				
#if defined (RMNET_ERR)				
				char buf_str[RMNET_ERROR_STR_SIZE];

				memset(buf_str, 0x00, RMNET_ERROR_STR_SIZE);
				memcpy(buf_str, buf, min(RMNET_ERROR_STR_SIZE, tot_sz));

				printk("xmd_net_notify: ch:%d Invalid version, 0x%x\n", info->chno, ver);
				printk("xmd_net_notify: Few bytes of pkt : 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
					((char *)buf)[0], ((char *)buf)[1], ((char *)buf)[2],
					((char *)buf)[3], ((char *)buf)[4], ((char *)buf)[5],
					((char *)buf)[6], ((char *)buf)[7], ((char *)buf)[8],
					((char *)buf)[9], ((char *)buf)[10]);
				printk("xmd_net_notify: Converted strings %s\n", buf_str);
				printk("xmd_net_notify: Left packet size = %d, \n", tot_sz);
#endif
				rmnet_reset_pastpacket_info(info->id);

			}
			return;
		}
#endif


		if (tot_sz < hdr_size) {
			past_packet[info->id].state = RMNET_PARTIAL_HEADER;
			past_packet[info->id].size = tot_sz;
			memcpy(past_packet[info->id].buf, buf, tot_sz);
			past_packet[info->id].type = ver;
#if defined (RMNET_DEBUG)
			printk("\n%s (line %d) partial header packet copied locally, sz = %d\n",
					__func__, __LINE__,	tot_sz);
#endif
			return;
		}

		if (ver == RMNET_IPV4_VER) {
			data_sz = ntohs(((struct iphdr*) ip_hdr)->tot_len);
		} else if (ver == RMNET_IPV6_VER) {
			data_sz = ntohs(((struct ipv6hdr*) ip_hdr)->payload_len) + sizeof(struct ipv6hdr);
		} else {
#if defined (RMNET_ERR)
			printk("\n%s (line %d) data sz check -- Invalid version, %d\n", __func__, __LINE__, ver);
#endif
			rmnet_reset_pastpacket_info(info->id);
			p->stats.rx_errors++;
			break;
		}

		if((data_sz <= 0)||(data_sz > RMNET_DATAT_SIZE)) {
			if((realign_count < MAX_RMNET_REALIGN_COUNT) && (tot_sz > 1)) {
#if defined (RMNET_ERR)
				if(realign_count == 0) {
					printk("\n%s (line %d) Invalid hdr len(%d)\n", __func__, __LINE__, data_sz);
					xmd_net_dump("xmd_net_notify", buf, tot_sz);
				}
#endif

				buf++; tot_sz--;
				realign_count++;

				rmnet_reset_pastpacket_info(info->id);
				continue;
			}
			else {
#if defined (RMNET_ERR)
				printk("\n%s (line %d) Invalid hdr len(%d) realign_count(%d)\n", __func__, __LINE__, data_sz, realign_count);
#endif
				break;
			}
		}

#if defined (RMNET_DEBUG)
		printk("xmd_net_notify: data size = %d\n", data_sz);
#endif

		if (tot_sz < data_sz) {
			past_packet[info->id].state = RMNET_PARTIAL_PACKET;
			past_packet[info->id].size = tot_sz;
			memcpy(past_packet[info->id].buf, buf, tot_sz);
			past_packet[info->id].type = ver;

#if 1 
			if(tot_sz < 10) {
				printk("\n%s (line %d) partial data packet copied locally, sz = %d\n",
					__func__, __LINE__,	tot_sz);
			}
#endif
			return;
		}

		rc = xmd_trans_packet(dev, ver, buf, data_sz);

		if(rc != 0) {
#if defined (RMNET_ERR)
			printk("\n%s (line %d) xmd_trans_packet fail data_sz(%d) tot_sz(%d)\n",
				__func__, __LINE__, data_sz, tot_sz);
			xmd_net_dump("xmd_net_notify", buf, data_sz);
#endif
			rmnet_reset_pastpacket_info(info->id);
		}
		
#if defined (RMNET_DEBUG)
		printk("xmd_net_notify: pushed full data packet to tcpip, sz = %d\n",
				data_sz);
#endif
		tot_sz = tot_sz - data_sz;
		buf = buf + data_sz;

#if defined (RMNET_DEBUG)
		printk("xmd_net_notify: looping for another packet tot_sz = %d\n",
				tot_sz);
#endif
	}