示例#1
0
/*
 * Poll a virtual cards message queue.
 * If there are new status-replies from the card, copy them to
 * ringbuffer for reading on /dev/isdnctrl and call
 * isdnloop_parse_status() for processing them. Watch for special
 * Firmware bootmessage and parse it, to get the D-Channel protocol.
 * If there are B-Channels open, initiate a timer-callback to
 * isdnloop_pollbchan().
 * This routine is called periodically via timer interrupt.
 *
 * Parameter:
 *   data = pointer to card struct
 */
static void
isdnloop_polldchan(unsigned long data)
{
	isdnloop_card *card = (isdnloop_card *) data;
	struct sk_buff *skb;
	int avail;
	int left;
	u_char c;
	int ch;
	unsigned long flags;
	u_char *p;
	isdn_ctrl cmd;

	if ((skb = skb_dequeue(&card->dqueue)))
		avail = skb->len;
	else
		avail = 0;
	for (left = avail; left > 0; left--) {
		c = *skb->data;
		skb_pull(skb, 1);
		isdnloop_putmsg(card, c);
		card->imsg[card->iptr] = c;
		if (card->iptr < 59)
			card->iptr++;
		if (!skb->len) {
			avail++;
			isdnloop_putmsg(card, '\n');
			card->imsg[card->iptr] = 0;
			card->iptr = 0;
			if (card->imsg[0] == '0' && card->imsg[1] >= '0' &&
			  card->imsg[1] <= '2' && card->imsg[2] == ';') {
				ch = (card->imsg[1] - '0') - 1;
				p = &card->imsg[3];
				isdnloop_parse_status(p, ch, card);
			} else {
				p = card->imsg;
				if (!strncmp(p, "DRV1.", 5)) {
					printk(KERN_INFO "isdnloop: (%s) %s\n", CID, p);
					if (!strncmp(p + 7, "TC", 2)) {
						card->ptype = ISDN_PTYPE_1TR6;
						card->interface.features |= ISDN_FEATURE_P_1TR6;
						printk(KERN_INFO
						       "isdnloop: (%s) 1TR6-Protocol loaded and running\n", CID);
					}
					if (!strncmp(p + 7, "EC", 2)) {
						card->ptype = ISDN_PTYPE_EURO;
						card->interface.features |= ISDN_FEATURE_P_EURO;
						printk(KERN_INFO
						       "isdnloop: (%s) Euro-Protocol loaded and running\n", CID);
					}
					continue;

				}
			}
		}
	}
	if (avail) {
		cmd.command = ISDN_STAT_STAVAIL;
		cmd.driver = card->myid;
		cmd.arg = avail;
		card->interface.statcallb(&cmd);
	}
	if (card->flags & (ISDNLOOP_FLAGS_B1ACTIVE | ISDNLOOP_FLAGS_B2ACTIVE))
		if (!(card->flags & ISDNLOOP_FLAGS_RBTIMER)) {
			/* schedule b-channel polling */
			card->flags |= ISDNLOOP_FLAGS_RBTIMER;
			spin_lock_irqsave(&card->isdnloop_lock, flags);
			del_timer(&card->rb_timer);
			card->rb_timer.function = isdnloop_pollbchan;
			card->rb_timer.data = (unsigned long) card;
			card->rb_timer.expires = jiffies + ISDNLOOP_TIMER_BCREAD;
			add_timer(&card->rb_timer);
			spin_unlock_irqrestore(&card->isdnloop_lock, flags);
		}
	/* schedule again */
	spin_lock_irqsave(&card->isdnloop_lock, flags);
	card->st_timer.expires = jiffies + ISDNLOOP_TIMER_DCREAD;
	add_timer(&card->st_timer);
	spin_unlock_irqrestore(&card->isdnloop_lock, flags);
}
示例#2
0
static void rx_complete(struct usb_ep *ep, struct usb_request *req)
{
	struct sk_buff	*skb = req->context, *skb2;
	struct eth_dev	*dev = ep->driver_data;
	int		status = req->status;

	switch (status) {

	/* normal completion */
	case 0:
		skb_put(skb, req->actual);

		if (dev->unwrap) {
			unsigned long	flags;

			spin_lock_irqsave(&dev->lock, flags);
			if (dev->port_usb) {
				status = dev->unwrap(dev->port_usb,
							skb,
							&dev->rx_frames);
			} else {
				dev_kfree_skb_any(skb);
				status = -ENOTCONN;
			}
			spin_unlock_irqrestore(&dev->lock, flags);
		} else {
			skb_queue_tail(&dev->rx_frames, skb);
		}
		skb = NULL;

		skb2 = skb_dequeue(&dev->rx_frames);
		while (skb2) {
			if (status < 0
					|| ETH_HLEN > skb2->len
					|| skb2->len > ETH_FRAME_LEN) {
				dev->net->stats.rx_errors++;
				dev->net->stats.rx_length_errors++;
				DBG(dev, "rx length %d\n", skb2->len);
				dev_kfree_skb_any(skb2);
				goto next_frame;
			}
			skb2->protocol = eth_type_trans(skb2, dev->net);
			dev->net->stats.rx_packets++;
			dev->net->stats.rx_bytes += skb2->len;

			/* no buffer copies needed, unless hardware can't
			 * use skb buffers.
			 */
			status = netif_rx(skb2);
next_frame:
			skb2 = skb_dequeue(&dev->rx_frames);
		}
		break;

	/* software-driven interface shutdown */
	case -ECONNRESET:		/* unlink */
	case -ESHUTDOWN:		/* disconnect etc */
		VDBG(dev, "rx shutdown, code %d\n", status);
		goto quiesce;

	/* for hardware automagic (such as pxa) */
	case -ECONNABORTED:		/* endpoint reset */
		DBG(dev, "rx %s reset\n", ep->name);
		defer_kevent(dev, WORK_RX_MEMORY);
quiesce:
		dev_kfree_skb_any(skb);
		goto clean;

	/* data overrun */
	case -EOVERFLOW:
		dev->net->stats.rx_over_errors++;
		/* FALLTHROUGH */

	default:
		dev->net->stats.rx_errors++;
		DBG(dev, "rx status %d\n", status);
		break;
	}

	if (skb)
		dev_kfree_skb_any(skb);
	if (!netif_running(dev->net)) {
clean:
		spin_lock(&dev->req_lock);
		list_add(&req->list, &dev->rx_reqs);
		spin_unlock(&dev->req_lock);
		req = NULL;
	}
	if (req)
		rx_submit(dev, req, GFP_ATOMIC);
}
示例#3
0
static int shaper_qframe(struct shaper *shaper, struct sk_buff *skb)
{
 	struct sk_buff *ptr;
 	
 	/*
 	 *	Get ready to work on this shaper. Lock may fail if its
 	 *	an interrupt and locked.
 	 */
 	 
 	if(!shaper_lock(shaper))
 		return -1;
 	ptr=shaper->sendq.prev;
 	
 	/*
 	 *	Set up our packet details
 	 */
 	 
 	skb->shapelatency=0;
 	skb->shapeclock=shaper->recovery;
 	if(time_before(skb->shapeclock, jiffies))
 		skb->shapeclock=jiffies;
 	skb->priority=0;	/* short term bug fix */
 	skb->shapestamp=jiffies;
 	
 	/*
 	 *	Time slots for this packet.
 	 */
 	 
 	skb->shapelen= shaper_clocks(shaper,skb);
 	
#ifdef SHAPER_COMPLEX /* and broken.. */

 	while(ptr && ptr!=(struct sk_buff *)&shaper->sendq)
 	{
 		if(ptr->pri<skb->pri 
 			&& jiffies - ptr->shapeclock < SHAPER_MAXSLIP)
 		{
 			struct sk_buff *tmp=ptr->prev;

 			/*
 			 *	It goes before us therefore we slip the length
 			 *	of the new frame.
 			 */

 			ptr->shapeclock+=skb->shapelen;
 			ptr->shapelatency+=skb->shapelen;

 			/*
 			 *	The packet may have slipped so far back it
 			 *	fell off.
 			 */
 			if(ptr->shapelatency > SHAPER_LATENCY)
 			{
 				skb_unlink(ptr);
 				dev_kfree_skb(ptr);
 			}
 			ptr=tmp;
 		}
 		else
 			break;
 	}
 	if(ptr==NULL || ptr==(struct sk_buff *)&shaper->sendq)
 		skb_queue_head(&shaper->sendq,skb);
 	else
 	{
 		struct sk_buff *tmp;
 		/*
 		 *	Set the packet clock out time according to the
 		 *	frames ahead. Im sure a bit of thought could drop
 		 *	this loop.
 		 */
 		for(tmp=skb_peek(&shaper->sendq); tmp!=NULL && tmp!=ptr; tmp=tmp->next)
 			skb->shapeclock+=tmp->shapelen;
 		skb_append(ptr,skb);
 	}
#else
	{
		struct sk_buff *tmp;
		/*
		 *	Up our shape clock by the time pending on the queue
		 *	(Should keep this in the shaper as a variable..)
		 */
		for(tmp=skb_peek(&shaper->sendq); tmp!=NULL && 
			tmp!=(struct sk_buff *)&shaper->sendq; tmp=tmp->next)
			skb->shapeclock+=tmp->shapelen;
		/*
		 *	Queue over time. Spill packet.
		 */
		if(skb->shapeclock-jiffies > SHAPER_LATENCY)
			dev_kfree_skb(skb);
		else
			skb_queue_tail(&shaper->sendq, skb);
	}
#endif 	
 	if(sh_debug)
 		printk("Frame queued.\n");
 	if(skb_queue_len(&shaper->sendq)>SHAPER_QLEN)
 	{
 		ptr=skb_dequeue(&shaper->sendq);
 		dev_kfree_skb(ptr);
 	}
 	shaper_unlock(shaper);
 	shaper_kick(shaper);
 	return 0;
}
static void
jade_interrupt(struct IsdnCardState *cs, u_char val, u_char jade)
{
	u_char r;
	struct BCState *bcs = cs->bcs + jade;
	struct sk_buff *skb;
	int fifo_size = 32;
	int count;
	int i_jade = (int) jade; /* To satisfy the compiler */
	
	if (!test_bit(BC_FLG_INIT, &bcs->Flag))
		return;

	if (val & 0x80) {	/* RME */
		r = READJADE(cs, i_jade, jade_HDLC_RSTA);
		if ((r & 0xf0) != 0xa0) {
			if (!(r & 0x80))
				if (cs->debug & L1_DEB_WARN)
					debugl1(cs, "JADE %s invalid frame", (jade ? "B":"A"));
			if ((r & 0x40) && bcs->mode)
				if (cs->debug & L1_DEB_WARN)
					debugl1(cs, "JADE %c RDO mode=%d", 'A'+jade, bcs->mode);
			if (!(r & 0x20))
				if (cs->debug & L1_DEB_WARN)
					debugl1(cs, "JADE %c CRC error", 'A'+jade);
			WriteJADECMDR(cs, jade, jade_HDLC_RCMD, jadeRCMD_RMC);
		} else {
			count = READJADE(cs, i_jade, jade_HDLC_RBCL) & 0x1F;
			if (count == 0)
				count = fifo_size;
			jade_empty_fifo(bcs, count);
			if ((count = bcs->hw.hscx.rcvidx - 1) > 0) {
				if (cs->debug & L1_DEB_HSCX_FIFO)
					debugl1(cs, "HX Frame %d", count);
				if (!(skb = dev_alloc_skb(count)))
					printk(KERN_WARNING "JADE %s receive out of memory\n", (jade ? "B":"A"));
				else {
					memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count);
					skb_queue_tail(&bcs->rqueue, skb);
				}
			}
		}
		bcs->hw.hscx.rcvidx = 0;
		schedule_event(bcs, B_RCVBUFREADY);
	}
	if (val & 0x40) {	/* RPF */
		jade_empty_fifo(bcs, fifo_size);
		if (bcs->mode == L1_MODE_TRANS) {
			/* receive audio data */
			if (!(skb = dev_alloc_skb(fifo_size)))
				printk(KERN_WARNING "HiSax: receive out of memory\n");
			else {
				memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size);
				skb_queue_tail(&bcs->rqueue, skb);
			}
			bcs->hw.hscx.rcvidx = 0;
			schedule_event(bcs, B_RCVBUFREADY);
		}
	}
	if (val & 0x10) {	/* XPR */
		if (bcs->tx_skb) {
			if (bcs->tx_skb->len) {
				jade_fill_fifo(bcs);
				return;
			} else {
				if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) &&
					(PACKET_NOACK != bcs->tx_skb->pkt_type)) {
					u_long	flags;
					spin_lock_irqsave(&bcs->aclock, flags);
					bcs->ackcnt += bcs->hw.hscx.count;
					spin_unlock_irqrestore(&bcs->aclock, flags);
					schedule_event(bcs, B_ACKPENDING);
				}
				dev_kfree_skb_irq(bcs->tx_skb);
				bcs->hw.hscx.count = 0;
				bcs->tx_skb = NULL;
			}
		}
		if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
			bcs->hw.hscx.count = 0;
			test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
			jade_fill_fifo(bcs);
		} else {
			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
			schedule_event(bcs, B_XMTBUFREADY);
		}
	}
}
/*
 * @brief Flush all packets in exception instance to files for debugging
 * @param
 *     None
 * @return
 *     This function returns KAL_SUCCESS always.
 */
KAL_INT32 eemcs_expt_flush()
{
    KAL_UINT32 pkts = 0;
    KAL_UINT32 i = 0;
//    struct sk_buff *skb = NULL;

	/* Flush all port skb from expt skb list  */
	for (i = 0; i < CCCI_PORT_NUM; i++) {
		pkts = atomic_read(&g_except_inst.port[i].pkt_cnt);

		/* No data in port */
		if (pkts == 0)
			continue;

		DBGLOG(EXPT, DBG, "free %d skb in port%d expt list", pkts, i);
		skb_queue_purge(&g_except_inst.port[i].skb_list);
		atomic_set(&g_except_inst.port[i].pkt_cnt, 0);
	}

	/* Flush all rx skb from expt skb list  */
	for (i = 0; i < SDIO_RX_Q_NUM; i++) {
		pkts = atomic_read(&g_except_inst.rxq[i].pkt_cnt);

		/* No data in port */
		if (pkts == 0)
			continue;

		DBGLOG(EXPT, DBG, "free %d skb in rxq%d expt list", pkts, i);
		skb_queue_purge(&g_except_inst.rxq[i].skb_list);
		atomic_set(&g_except_inst.rxq[i].pkt_cnt, 0);
	}

	/* Flush all tx skb from expt skb list  */
	for (i = 0; i < SDIO_TX_Q_NUM; i++) {
		pkts = atomic_read(&g_except_inst.txq[i].pkt_cnt);

		/* No data in port */
		if (pkts == 0)
			continue;

		DBGLOG(EXPT, DBG, "free %d skb in txq%d expt list", pkts, i);
		skb_queue_purge(&g_except_inst.txq[i].skb_list);
		atomic_set(&g_except_inst.txq[i].pkt_cnt, 0);
	}

#if 0    
    char log_file[NAME_MAX] = {0};
    struct file *fp = NULL;
    KAL_UINT32 pkts = 0;
    KAL_UINT32 i = 0, j = 0;
    struct sk_buff *skb = NULL;

    DEBUG_LOG_FUNCTION_ENTRY;
    /* Flush all DL packets to a file */
    for (i = 0; i < SDIO_RX_Q_NUM; i++) {
        pkts = atomic_read(&g_except_inst.rxq[i].pkt_cnt);
        DBGLOG(EXPT, DBG, "[EXPT] %d packets in DL SWQ %d", pkts, i);
        /* No data in Rx Q */
        if (pkts == 0)
            continue;

        sprintf(log_file, "%s/eemcs_expt_rx-%02d_%d.bak", EEMCS_EXCEPTION_LOG_PATH, g_except_inst.rxq[i].id, pkts);
        fp = file_open(log_file, O_RDWR | O_CREAT | O_TRUNC, 0777);
        if (fp == NULL) {
            DBGLOG(EXPT, ERR, "[EXPT] Failed to open file %s", log_file);
            continue;
        }
        // Write packets number
        file_write(fp, (char*)&pkts, sizeof(KAL_UINT32));
        /* Write each skb in list */
        for (j = 0; j < pkts; j++) {
            skb = skb_dequeue(&g_except_inst.rxq[i].skb_list);
            if (skb == NULL) {
                DBGLOG(EXPT, WAR, "[EXPT] Failed to read skb from RX list %d", i);
            } else {
                hif_dl_pkt_handle_complete(i);
                // Write skb data length
                file_write(fp, (char*)&skb->len, sizeof(unsigned int));
                // Write skb data
                file_write(fp, skb->data, skb->len);
                atomic_dec(&g_except_inst.rxq[i].pkt_cnt);
            }
        }
        file_close(fp);
        DBGLOG(EXPT, TRA, "[EXPT] All unhandled DL packets in Q are saved to %s", log_file);
    }
    /* Flush all UL packets to a file */
    for (i = 0; i < SDIO_TX_Q_NUM; i++) {
        pkts = atomic_read(&g_except_inst.txq[i].pkt_cnt);
        DBGLOG(EXPT, DBG, "[EXPT] %d packets in UL SWQ %d", pkts, i);
        /* No data in Tx Q */
        if (pkts == 0)
            continue;

        sprintf(log_file, "%s/eemcs_expt_tx-%02d_%d.bak", EEMCS_EXCEPTION_LOG_PATH, g_except_inst.txq[i].id, pkts);
        fp = file_open(log_file, O_RDWR | O_CREAT | O_TRUNC, 0777);
        if (fp == NULL) {
            DBGLOG(EXPT, ERR, "[EXPT] Failed to open file %s", log_file);
            continue;
        }
        // Write packets number
        file_write(fp, (char*)&pkts, sizeof(KAL_UINT32));
        /* Write each skb in list */
        for (j = 0; j < pkts; j++) {
            skb = skb_dequeue(&g_except_inst.txq[i].skb_list);
            if (skb == NULL) {
                DBGLOG(EXPT, WAR, "[EXPT] Failed to read skb from TX list %d", i);
            } else {
                // Write skb data length
                file_write(fp, (char*)&skb->len, sizeof(unsigned int));
                // Write skb data
                file_write(fp, skb->data, skb->len);
                atomic_dec(&g_except_inst.txq[i].pkt_cnt);
            }
        }
        file_close(fp);
        DBGLOG(EXPT, TRA, "[EXPT] All unhandled UL packets in Q are saved to %s", log_file);
    }
    /* Flush all port packets to a file */
    for (i = 0; i < CCCI_CDEV_NUM; i++) {
        pkts = atomic_read(&g_except_inst.port[i].pkt_cnt);
        DBGLOG(EXPT, DBG, "[EXPT] %d packets in port %d", pkts, i);
        /* No data in port */
        if (pkts == 0)
            continue;

        sprintf(log_file, "%s/eemcs_expt_port-%02d_%d.bak", EEMCS_EXCEPTION_LOG_PATH, i, pkts);
        fp = file_open(log_file, O_RDWR | O_CREAT, 0777);
        if (fp == NULL) {
            DBGLOG(EXPT, ERR, "[EXPT] Failed to open file %s", log_file);
            continue;
        }
        // Write packets number
        file_write(fp, (char*)&pkts, sizeof(KAL_UINT32));
        /* Write each skb in list */
        for (j = 0; j < pkts; j++) {
            skb = skb_dequeue(&g_except_inst.port[i].skb_list);
            if (skb == NULL) {
                DBGLOG(EXPT, WAR, "[EXPT] Failed to read skb from port list %d", i);
            } else {
                // Write skb data length
                file_write(fp, (char*)&skb->len, sizeof(unsigned int));
                // Write skb data
                file_write(fp, skb->data, skb->len);
                atomic_dec(&g_except_inst.port[i].pkt_cnt);
            }
        }
        file_close(fp);
        DBGLOG(EXPT, TRA, "[EXPT] All unhandled UL packets in port are saved to %s", log_file);
    }
    DBGLOG(EXPT, TRA, "[EXPT] eemcs_expt_flush() Finished !!");

    DEBUG_LOG_FUNCTION_LEAVE;
#else
    DEBUG_LOG_FUNCTION_ENTRY;
    DEBUG_LOG_FUNCTION_LEAVE;
#endif
    return KAL_SUCCESS;
}
示例#6
0
static void rx_complete(struct usb_ep *ep, struct usb_request *req)
{
	struct sk_buff	*skb = req->context, *skb2;
	struct eth_dev	*dev = ep->driver_data;
	int		status = req->status;

	switch (status) {

	
	case 0:
		skb_put(skb, req->actual);

		if (dev->unwrap) {
			unsigned long	flags;

			spin_lock_irqsave(&dev->lock, flags);
			if (dev->port_usb) {
				status = dev->unwrap(dev->port_usb,
							skb,
							&dev->rx_frames);
			} else {
				dev_kfree_skb_any(skb);
				status = -ENOTCONN;
			}
			spin_unlock_irqrestore(&dev->lock, flags);
		} else {
			skb_queue_tail(&dev->rx_frames, skb);
		}
		skb = NULL;

		skb2 = skb_dequeue(&dev->rx_frames);
		while (skb2) {
			if (status < 0
					|| ETH_HLEN > skb2->len
					|| skb2->len > ETH_FRAME_LEN) {
				dev->net->stats.rx_errors++;
				dev->net->stats.rx_length_errors++;
				DBG(dev, "rx length %d\n", skb2->len);
				dev_kfree_skb_any(skb2);
				goto next_frame;
			}
			skb2->protocol = eth_type_trans(skb2, dev->net);
			dev->net->stats.rx_packets++;
			dev->net->stats.rx_bytes += skb2->len;

			
			status = netif_rx(skb2);
next_frame:
			skb2 = skb_dequeue(&dev->rx_frames);
		}
		break;

	
	case -ECONNRESET:		
	case -ESHUTDOWN:		
		VDBG(dev, "rx shutdown, code %d\n", status);
		goto quiesce;

	
	case -ECONNABORTED:		
		DBG(dev, "rx %s reset\n", ep->name);
		defer_kevent(dev, WORK_RX_MEMORY);
quiesce:
		dev_kfree_skb_any(skb);
		goto clean;

	
	case -EOVERFLOW:
		dev->net->stats.rx_over_errors++;
		

	default:
		dev->net->stats.rx_errors++;
		DBG(dev, "rx status %d\n", status);
		break;
	}

	if (skb)
		dev_kfree_skb_any(skb);
	if (!netif_running(dev->net)) {
clean:
		spin_lock(&dev->req_lock);
		list_add(&req->list, &dev->rx_reqs);
		spin_unlock(&dev->req_lock);
		req = NULL;
	}
	if (req)
		rx_submit(dev, req, GFP_ATOMIC);
}
static void ntl_receive(struct sock *sk, int len)
{
    int err;
    struct sk_buff *skb;
    pid_t pid;
    struct nlmsghdr *nl_header;
    __u32 seq;
    struct pimfor_hdr *header;
    char *data;
    int version;
    int operation;
    unsigned long oid;
    int dev_id;
    int flags;
    unsigned long length;
  	struct net_device *dev;

#ifdef DRIVER_DEBUG
    printk(KERN_INFO "ntl_receive: sock %p, len %d \n", sk, len);
#endif

    do
    {
        if (rtnl_shlock_nowait())
                return;

        while ( (skb = skb_dequeue(&sk->receive_queue)) != NULL )
        {
            pid = NETLINK_CB(skb).pid;
            nl_header = (struct nlmsghdr*) skb->data;
            seq = nl_header->nlmsg_seq;
            header = (struct pimfor_hdr*)(skb->data+(sizeof(struct nlmsghdr)));
            data = PIMFOR_DATA(header);

            if ( nl_header->nlmsg_type == NETLINK_TYPE_PIMFOR )
            {
                pimfor_decode_header(header, &version, &operation, &oid, &dev_id, &flags, &length);

                if (version == PIMFOR_VERSION_1) {

                    err = mgt_request( DEV_NETWORK, dev_id, pid, seq, operation, oid, data, length );

                    if ( err < 0 ) {
                        printk(KERN_INFO "ntl_receive: mgt_request(%d, %d, %d, %x, %d, %x, %d) returned %d\n",
                               DEV_NETWORK, dev_id, pid, seq, operation, oid, length, err );
                        netlink_ack(skb, nl_header, -EOPNOTSUPP );
                    }

                } else {
                    printk(KERN_ERR "ntl_receive: version (%d) != PIMFOR_VERSION_1\n", version );
                    netlink_ack(skb, nl_header, -EOPNOTSUPP );
                }
            } else {
                printk(KERN_ERR "nl_header->nlmsg_type (%d) != NETLINK_TYPE_PIMFOR\n", nl_header->nlmsg_type );
                netlink_ack(skb, nl_header, -EOPNOTSUPP );
            }

            kfree_skb(skb);
        }
        up(&rtnl_sem);

    } while (nl_sock && nl_sock->receive_queue.qlen);
}
示例#8
0
文件: hfc_2bs0.c 项目: 03199618/linux
void
main_irq_hfc(struct BCState *bcs)
{
	struct IsdnCardState *cs = bcs->cs;
	int z1, z2, rcnt;
	u_char f1, f2, cip;
	int receive, transmit, count = 5;
	struct sk_buff *skb;

Begin:
	count--;
	cip = HFC_CIP | HFC_F1 | HFC_REC | HFC_CHANNEL(bcs->channel);
	if ((cip & 0xc3) != (cs->hw.hfc.cip & 0xc3)) {
		cs->BC_Write_Reg(cs, HFC_STATUS, cip, cip);
		WaitForBusy(cs);
	}
	WaitNoBusy(cs);
	receive = 0;
	if (bcs->mode == L1_MODE_HDLC) {
		f1 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
		cip = HFC_CIP | HFC_F2 | HFC_REC | HFC_CHANNEL(bcs->channel);
		WaitNoBusy(cs);
		f2 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
		if (f1 != f2) {
			if (cs->debug & L1_DEB_HSCX)
				debugl1(cs, "hfc rec %d f1(%d) f2(%d)",
					bcs->channel, f1, f2);
			receive = 1;
		}
	}
	if (receive || (bcs->mode == L1_MODE_TRANS)) {
		WaitForBusy(cs);
		z1 = ReadZReg(bcs, HFC_Z1 | HFC_REC | HFC_CHANNEL(bcs->channel));
		z2 = ReadZReg(bcs, HFC_Z2 | HFC_REC | HFC_CHANNEL(bcs->channel));
		rcnt = z1 - z2;
		if (rcnt < 0)
			rcnt += cs->hw.hfc.fifosize;
		if ((bcs->mode == L1_MODE_HDLC) || (rcnt)) {
			rcnt++;
			if (cs->debug & L1_DEB_HSCX)
				debugl1(cs, "hfc rec %d z1(%x) z2(%x) cnt(%d)",
					bcs->channel, z1, z2, rcnt);
			/*              sti(); */
			if ((skb = hfc_empty_fifo(bcs, rcnt))) {
				skb_queue_tail(&bcs->rqueue, skb);
				schedule_event(bcs, B_RCVBUFREADY);
			}
		}
		receive = 1;
	}
	if (bcs->tx_skb) {
		transmit = 1;
		test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
		hfc_fill_fifo(bcs);
		if (test_bit(BC_FLG_BUSY, &bcs->Flag))
			transmit = 0;
	} else {
		if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
			transmit = 1;
			test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
			hfc_fill_fifo(bcs);
			if (test_bit(BC_FLG_BUSY, &bcs->Flag))
				transmit = 0;
		} else {
			transmit = 0;
			schedule_event(bcs, B_XMTBUFREADY);
		}
	}
	if ((receive || transmit) && count)
		goto Begin;
	return;
}
示例#9
0
void iwm_tx_worker(struct work_struct *work)
{
	struct iwm_priv *iwm;
	struct iwm_tx_info *tx_info = NULL;
	struct sk_buff *skb;
	struct iwm_tx_queue *txq;
	struct iwm_sta_info *sta_info;
	struct iwm_tid_info *tid_info;
	int cmdlen, ret, pool_id;

	txq = container_of(work, struct iwm_tx_queue, worker);
	iwm = container_of(txq, struct iwm_priv, txq[txq->id]);

	pool_id = queue_to_pool_id(txq->id);

	while (!test_bit(pool_id, &iwm->tx_credit.full_pools_map) &&
	       !skb_queue_empty(&txq->queue)) {

		spin_lock_bh(&txq->lock);
		skb = skb_dequeue(&txq->queue);
		spin_unlock_bh(&txq->lock);

		tx_info = skb_to_tx_info(skb);
		sta_info = &iwm->sta_table[tx_info->sta];
		if (!sta_info->valid) {
			IWM_ERR(iwm, "Trying to send a frame to unknown STA\n");
			kfree_skb(skb);
			continue;
		}

		tid_info = &sta_info->tid_info[tx_info->tid];

		mutex_lock(&tid_info->mutex);

		/*
		 * If the RAxTID is stopped, we queue the skb to the stopped
		 * queue.
		 * Whenever we'll get a UMAC notification to resume the tx flow
		 * for this RAxTID, we'll merge back the stopped queue into the
		 * regular queue. See iwm_ntf_stop_resume_tx() from rx.c.
		 */
		if (tid_info->stopped) {
			IWM_DBG_TX(iwm, DBG, "%dx%d stopped\n",
				   tx_info->sta, tx_info->tid);
			spin_lock_bh(&txq->lock);
			skb_queue_tail(&txq->stopped_queue, skb);
			spin_unlock_bh(&txq->lock);

			mutex_unlock(&tid_info->mutex);
			continue;
		}

		cmdlen = IWM_UDMA_HDR_LEN + skb->len;

		IWM_DBG_TX(iwm, DBG, "Tx frame on queue %d: skb: 0x%p, sta: "
			   "%d, color: %d\n", txq->id, skb, tx_info->sta,
			   tx_info->color);

		if (txq->concat_count + cmdlen > IWM_HAL_CONCATENATE_BUF_SIZE)
			iwm_tx_send_concat_packets(iwm, txq);

		ret = iwm_tx_credit_alloc(iwm, pool_id, cmdlen);
		if (ret) {
			IWM_DBG_TX(iwm, DBG, "not enough tx_credit for queue "
				   "%d, Tx worker stopped\n", txq->id);
			spin_lock_bh(&txq->lock);
			skb_queue_head(&txq->queue, skb);
			spin_unlock_bh(&txq->lock);

			mutex_unlock(&tid_info->mutex);
			break;
		}

		txq->concat_ptr = txq->concat_buf + txq->concat_count;
		tid_info->last_seq_num =
			iwm_tx_build_packet(iwm, skb, pool_id, txq->concat_ptr);
		txq->concat_count += ALIGN(cmdlen, 16);

		mutex_unlock(&tid_info->mutex);

		kfree_skb(skb);
	}

	iwm_tx_send_concat_packets(iwm, txq);

	if (__netif_subqueue_stopped(iwm_to_ndev(iwm), txq->id) &&
	    !test_bit(pool_id, &iwm->tx_credit.full_pools_map) &&
	    (skb_queue_len(&txq->queue) < IWM_TX_LIST_SIZE / 2)) {
		IWM_DBG_TX(iwm, DBG, "LINK: start netif_subqueue[%d]", txq->id);
		netif_wake_subqueue(iwm_to_ndev(iwm), txq->id);
	}
}
示例#10
0
void
isac_interrupt(struct IsdnCardState *cs, u_char val)
{
	u_char exval, v1;
	struct sk_buff *skb;
	unsigned int count;

	if (cs->debug & L1_DEB_ISAC)
		debugl1(cs, "ISAC interrupt %x", val);
	if (val & 0x80) {	/* RME */
		exval = cs->readisac(cs, ISAC_RSTA);
		if ((exval & 0x70) != 0x20) {
			if (exval & 0x40) {
				if (cs->debug & L1_DEB_WARN)
					debugl1(cs, "ISAC RDO");
#ifdef ERROR_STATISTIC
				cs->err_rx++;
#endif
			}
			if (!(exval & 0x20)) {
				if (cs->debug & L1_DEB_WARN)
					debugl1(cs, "ISAC CRC error");
#ifdef ERROR_STATISTIC
				cs->err_crc++;
#endif
			}
			cs->writeisac(cs, ISAC_CMDR, 0x80);
		} else {
			count = cs->readisac(cs, ISAC_RBCL) & 0x1f;
			if (count == 0)
				count = 32;
			isac_empty_fifo(cs, count);
			if ((count = cs->rcvidx) > 0) {
				cs->rcvidx = 0;
				if (!(skb = alloc_skb(count, GFP_ATOMIC)))
					printk(KERN_WARNING "HiSax: D receive out of memory\n");
				else {
					memcpy(skb_put(skb, count), cs->rcvbuf, count);
					skb_queue_tail(&cs->rq, skb);
				}
			}
		}
		cs->rcvidx = 0;
		schedule_event(cs, D_RCVBUFREADY);
	}
	if (val & 0x40) {	/* RPF */
		isac_empty_fifo(cs, 32);
	}
	if (val & 0x20) {	/* RSC */
		/* never */
		if (cs->debug & L1_DEB_WARN)
			debugl1(cs, "ISAC RSC interrupt");
	}
	if (val & 0x10) {	/* XPR */
		if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
			del_timer(&cs->dbusytimer);
		if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
			schedule_event(cs, D_CLEARBUSY);
		if (cs->tx_skb) {
			if (cs->tx_skb->len) {
				isac_fill_fifo(cs);
				goto afterXPR;
			} else {
				dev_kfree_skb_irq(cs->tx_skb);
				cs->tx_cnt = 0;
				cs->tx_skb = NULL;
			}
		}
		if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
			cs->tx_cnt = 0;
			isac_fill_fifo(cs);
		} else
			schedule_event(cs, D_XMTBUFREADY);
	}
      afterXPR:
	if (val & 0x04) {	/* CISQ */
		exval = cs->readisac(cs, ISAC_CIR0);
		if (cs->debug & L1_DEB_ISAC)
			debugl1(cs, "ISAC CIR0 %02X", exval );
		if (exval & 2) {
			cs->dc.isac.ph_state = (exval >> 2) & 0xf;
			if (cs->debug & L1_DEB_ISAC)
				debugl1(cs, "ph_state change %x", cs->dc.isac.ph_state);
			schedule_event(cs, D_L1STATECHANGE);
		}
示例#11
0
/*
 * State machine for state 3, Connected State.
 * The handling of the timer(s) is in file nr_timer.c
 * Handling of state 0 and connection release is in netrom.c.
 */
static int nr_state3_machine(struct sock *sk, struct sk_buff *skb, int frametype)
{
	struct sk_buff_head temp_queue;
	struct sk_buff *skbn;
	unsigned short save_vr;
	unsigned short nr, ns;
	int queued = 0;

	nr = skb->data[18];
	ns = skb->data[17];

	switch (frametype) {

		case NR_CONNREQ:
			nr_write_internal(sk, NR_CONNACK);
			break;

		case NR_DISCREQ:
			nr_write_internal(sk, NR_DISCACK);
			nr_disconnect(sk, 0);
			break;

		case NR_CONNACK | NR_CHOKE_FLAG:
		case NR_DISCACK:
			nr_disconnect(sk, ECONNRESET);
			break;

		case NR_INFOACK:
		case NR_INFOACK | NR_CHOKE_FLAG:
		case NR_INFOACK | NR_NAK_FLAG:
		case NR_INFOACK | NR_NAK_FLAG | NR_CHOKE_FLAG:
			if (frametype & NR_CHOKE_FLAG) {
				sk->protinfo.nr->condition |= NR_COND_PEER_RX_BUSY;
				nr_start_t4timer(sk);
			} else {
				sk->protinfo.nr->condition &= ~NR_COND_PEER_RX_BUSY;
				nr_stop_t4timer(sk);
			}
			if (!nr_validate_nr(sk, nr)) {
				break;
			}
			if (frametype & NR_NAK_FLAG) {
				nr_frames_acked(sk, nr);
				nr_send_nak_frame(sk);
			} else {
				if (sk->protinfo.nr->condition & NR_COND_PEER_RX_BUSY) {
					nr_frames_acked(sk, nr);
				} else {
					nr_check_iframes_acked(sk, nr);
				}
			}
			break;

		case NR_INFO:
		case NR_INFO | NR_NAK_FLAG:
		case NR_INFO | NR_CHOKE_FLAG:
		case NR_INFO | NR_MORE_FLAG:
		case NR_INFO | NR_NAK_FLAG | NR_CHOKE_FLAG:
		case NR_INFO | NR_CHOKE_FLAG | NR_MORE_FLAG:
		case NR_INFO | NR_NAK_FLAG | NR_MORE_FLAG:
		case NR_INFO | NR_NAK_FLAG | NR_CHOKE_FLAG | NR_MORE_FLAG:
			if (frametype & NR_CHOKE_FLAG) {
				sk->protinfo.nr->condition |= NR_COND_PEER_RX_BUSY;
				nr_start_t4timer(sk);
			} else {
				sk->protinfo.nr->condition &= ~NR_COND_PEER_RX_BUSY;
				nr_stop_t4timer(sk);
			}
			if (nr_validate_nr(sk, nr)) {
				if (frametype & NR_NAK_FLAG) {
					nr_frames_acked(sk, nr);
					nr_send_nak_frame(sk);
				} else {
					if (sk->protinfo.nr->condition & NR_COND_PEER_RX_BUSY) {
						nr_frames_acked(sk, nr);
					} else {
						nr_check_iframes_acked(sk, nr);
					}
				}
			}
			queued = 1;
			skb_queue_head(&sk->protinfo.nr->reseq_queue, skb);
			if (sk->protinfo.nr->condition & NR_COND_OWN_RX_BUSY)
				break;
			skb_queue_head_init(&temp_queue);
			do {
				save_vr = sk->protinfo.nr->vr;
				while ((skbn = skb_dequeue(&sk->protinfo.nr->reseq_queue)) != NULL) {
					ns = skbn->data[17];
					if (ns == sk->protinfo.nr->vr) {
						if (nr_queue_rx_frame(sk, skbn, frametype & NR_MORE_FLAG) == 0) {
							sk->protinfo.nr->vr = (sk->protinfo.nr->vr + 1) % NR_MODULUS;
						} else {
							sk->protinfo.nr->condition |= NR_COND_OWN_RX_BUSY;
							skb_queue_tail(&temp_queue, skbn);
						}
					} else if (nr_in_rx_window(sk, ns)) {
						skb_queue_tail(&temp_queue, skbn);
					} else {
						kfree_skb(skbn);
					}
				}
				while ((skbn = skb_dequeue(&temp_queue)) != NULL) {
					skb_queue_tail(&sk->protinfo.nr->reseq_queue, skbn);
				}
			} while (save_vr != sk->protinfo.nr->vr);
			/*
			 * Window is full, ack it immediately.
			 */
			if (((sk->protinfo.nr->vl + sk->protinfo.nr->window) % NR_MODULUS) == sk->protinfo.nr->vr) {
				nr_enquiry_response(sk);
			} else {
				if (!(sk->protinfo.nr->condition & NR_COND_ACK_PENDING)) {
					sk->protinfo.nr->condition |= NR_COND_ACK_PENDING;
					nr_start_t2timer(sk);
				}
			}
			break;

		default:
			break;
	}

	return queued;
}
示例#12
0
static void usbnet_bh (unsigned long param)
{
	struct usbnet		*dev = (struct usbnet *) param;
	struct sk_buff		*skb;
	struct skb_data		*entry;

	while ((skb = skb_dequeue (&dev->done))) {
		entry = (struct skb_data *) skb->cb;
		switch (entry->state) {
		case rx_done:
			entry->state = rx_cleanup;
			rx_process (dev, skb);
			continue;
		case tx_done:
		case rx_cleanup:
			usb_free_urb (entry->urb);
			dev_kfree_skb (skb);
			continue;
		default:
			netdev_dbg(dev->net, "bogus skb state %d\n", entry->state);
		}
	}

	// waiting for all pending urbs to complete?
	if (dev->wait) {
		if ((dev->txq.qlen + dev->rxq.qlen + dev->done.qlen) == 0) {
			wake_up (dev->wait);
		}

	// or are we maybe short a few urbs?
	} else if (netif_running (dev->net) &&
		   netif_device_present (dev->net) &&
		   !timer_pending (&dev->delay) &&
		   !test_bit (EVENT_RX_HALT, &dev->flags)) {
		int	temp = dev->rxq.qlen;
		int	qlen = RX_QLEN (dev);

		if (temp < qlen) {
			struct urb	*urb;
			int		i;

			// don't refill the queue all at once
			for (i = 0; i < 10 && dev->rxq.qlen < qlen; i++) {
				urb = usb_alloc_urb (0, GFP_ATOMIC);
				if (urb != NULL) {
					if (rx_submit (dev, urb, GFP_ATOMIC) ==
					    -ENOLINK)
						return;
				}
			}
			if (temp != dev->rxq.qlen)
				netif_dbg(dev, link, dev->net,
					  "rxqlen %d --> %d\n",
					  temp, dev->rxq.qlen);
			if (dev->rxq.qlen < qlen)
				tasklet_schedule (&dev->bh);
		}
		if (dev->txq.qlen < TX_QLEN (dev))
			netif_wake_queue (dev->net);
	}
}
示例#13
0
static struct sk_buff_head *msm_ipc_router_build_msg(unsigned int num_sect,
					  struct iovec const *msg_sect,
					  size_t total_len)
{
	struct sk_buff_head *msg_head;
	struct sk_buff *msg;
	int i, copied, first = 1;
	int data_size = 0, request_size, offset;
	void *data;

	for (i = 0; i < num_sect; i++)
		data_size += msg_sect[i].iov_len;

	if (!data_size)
		return NULL;

	msg_head = kmalloc(sizeof(struct sk_buff_head), GFP_KERNEL);
	if (!msg_head) {
		pr_err("%s: cannot allocate skb_head\n", __func__);
		return NULL;
	}
	skb_queue_head_init(msg_head);

	for (copied = 1, i = 0; copied && (i < num_sect); i++) {
		data_size = msg_sect[i].iov_len;
		offset = 0;
		while (offset != msg_sect[i].iov_len) {
			request_size = data_size;
			if (first)
				request_size += IPC_ROUTER_HDR_SIZE;

			msg = alloc_skb(request_size, GFP_KERNEL);
			if (!msg) {
				if (request_size <= (PAGE_SIZE/2)) {
					pr_err("%s: cannot allocated skb\n",
						__func__);
					goto msg_build_failure;
				}
				data_size = data_size / 2;
				continue;
			}

			if (first) {
				skb_reserve(msg, IPC_ROUTER_HDR_SIZE);
				first = 0;
			}

			data = skb_put(msg, data_size);
			copied = !copy_from_user(msg->data,
					msg_sect[i].iov_base + offset,
					data_size);
			if (!copied) {
				pr_err("%s: copy_from_user failed\n",
					__func__);
				kfree_skb(msg);
				goto msg_build_failure;
			}
			skb_queue_tail(msg_head, msg);
			offset += data_size;
			data_size = msg_sect[i].iov_len - offset;
		}
	}
	return msg_head;

msg_build_failure:
	while (!skb_queue_empty(msg_head)) {
		msg = skb_dequeue(msg_head);
		kfree_skb(msg);
	}
	kfree(msg_head);
	return NULL;
}
示例#14
0
void rtl_btcoex_recvmsg_int(struct sock *sk_in, s32 bytes) {
#else
void rtl_btcoex_recvmsg_int(struct sock *sk_in) {
#endif

	struct rtl_priv *rtlpriv = pbtcoexadapter;	
	struct bt_coex_info *pcoex_info = &rtlpriv->coex_info;

	pcoex_info->sk_store = sk_in;
	queue_delayed_work(pbtcoexadapter->works.rtl_wq,
		&rtlpriv->works.socket_wq, 0);

}




void rtl_btcoex_recvmsgbysocket(void* data) {

	u8 recv_data[RECV_DATA_MAX_LEN];
	u32 len = 0;
	u16 recv_length = 0;
	u16 parse_res = 0;

	struct rtl_priv *rtlpriv = pbtcoexadapter;
	struct bt_coex_info *pcoex_info = &rtlpriv->coex_info;
	struct sock *sk = pcoex_info->sk_store;
	struct sk_buff * skb = NULL;

	if(sk == NULL)
		BTC_PRINT(BTC_MSG_SOCKET, SOCKET_CRITICAL,"critical error when receive socket data!\n");


	len = skb_queue_len(&sk->sk_receive_queue);
	while(len > 0){
			skb = skb_dequeue(&sk->sk_receive_queue);

			/*important: cut the udp header from skb->data!
			  header length is 8 byte*/
			recv_length = skb->len-8;
			memset(recv_data,0,sizeof(recv_data));
			safe_memcpy(recv_data, skb->data+8, recv_length, RECV_DATA_MAX_LEN);

			/*DBG_871X("received data: %s :with len %u\n",recv_data, skb->len);*/
			parse_res = rtl_btcoex_parse_recv_data(recv_data,recv_length);
			/*DBG_871X("parse_res; %d\n",parse_res);*/
			if(RX_ATTEND_ACK == parse_res) //attend ack
			{
				pcoex_info ->BT_attend = true;
				BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,"RX_ATTEND_ACK!,sock_open:%d, BT_attend:%d\n",pcoex_info ->sock_open,pcoex_info ->BT_attend);
			}
			if(RX_ATTEND_REQ == parse_res) //attend req from BT
			{
				pcoex_info ->BT_attend = true;
				BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,"RX_BT_ATTEND_REQ!,sock_open:%d, BT_attend:%d\n",pcoex_info ->sock_open,pcoex_info ->BT_attend);
				rtl_btcoex_sendmsgbysocket(pbtcoexadapter,attend_ack,sizeof(attend_ack),false);
			}		
			if(RX_INVITE_REQ == parse_res) //attend req from BT
			{
				pcoex_info ->BT_attend = true;
				BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,"RX_INVITE_REQ!,sock_open:%d, BT_attend:%d\n",pcoex_info ->sock_open,pcoex_info ->BT_attend);
				rtl_btcoex_sendmsgbysocket(pbtcoexadapter,invite_rsp,sizeof(invite_rsp),false);
			}	
			if(RX_INVITE_RSP == parse_res) //attend req from BT
			{
				pcoex_info ->BT_attend = true;
				BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,"RX_INVITE_RSP!,sock_open:%d, BT_attend:%d\n",pcoex_info ->sock_open,pcoex_info ->BT_attend);
			}	
			else if (RX_LEAVE_ACK == parse_res) //mean BT know wifi  will leave
			{
				pcoex_info ->BT_attend = false;
				BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,"RX_LEAVE_ACK!,sock_open:%d, BT_attend:%d\n",pcoex_info ->sock_open,pcoex_info ->BT_attend);			
			}
			else if(RX_BT_LEAVE == parse_res) //BT leave
			{
				rtl_btcoex_sendmsgbysocket(pbtcoexadapter, leave_ack,sizeof(leave_ack),false); // no ack
				pcoex_info ->BT_attend = false;
				BTC_PRINT(BTC_MSG_SOCKET, SOCKET_NORMAL,"RX_BT_LEAVE!sock_open:%d, BT_attend:%d\n",pcoex_info ->sock_open,pcoex_info ->BT_attend);			
			}
			else/*todo: check if recv data are really hci cmds*/
			{
				if(true == pcoex_info->BT_attend)
					rtl_btcoex_parse_hci_cmd(pbtcoexadapter,recv_data,recv_length);
			}
			len--;
			kfree_skb(skb);
			/*never do a sleep in this context!*/
	}

	
}
示例#15
0
文件: yam.c 项目: ANFS/ANFS-kernel
static void yam_tx_byte(struct net_device *dev, struct yam_port *yp)
{
	struct sk_buff *skb;
	unsigned char b, temp;

	switch (yp->tx_state) {
	case TX_OFF:
		break;
	case TX_HEAD:
		if (--yp->tx_count <= 0) {
			if (!(skb = skb_dequeue(&yp->send_queue))) {
				ptt_off(dev);
				yp->tx_state = TX_OFF;
				break;
			}
			yp->tx_state = TX_DATA;
			if (skb->data[0] != 0) {
/*                              do_kiss_params(s, skb->data, skb->len); */
				dev_kfree_skb_any(skb);
				break;
			}
			yp->tx_len = skb->len - 1;	/* strip KISS byte */
			if (yp->tx_len >= YAM_MAX_FRAME || yp->tx_len < 2) {
        			dev_kfree_skb_any(skb);
				break;
			}
			skb_copy_from_linear_data_offset(skb, 1,
							 yp->tx_buf,
							 yp->tx_len);
			dev_kfree_skb_any(skb);
			yp->tx_count = 0;
			yp->tx_crcl = 0x21;
			yp->tx_crch = 0xf3;
			yp->tx_state = TX_DATA;
		}
		break;
	case TX_DATA:
		b = yp->tx_buf[yp->tx_count++];
		outb(b, THR(dev->base_addr));
		temp = yp->tx_crcl;
		yp->tx_crcl = chktabl[temp] ^ yp->tx_crch;
		yp->tx_crch = chktabh[temp] ^ b;
		if (yp->tx_count >= yp->tx_len) {
			yp->tx_state = TX_CRC1;
		}
		break;
	case TX_CRC1:
		yp->tx_crch = chktabl[yp->tx_crcl] ^ yp->tx_crch;
		yp->tx_crcl = chktabh[yp->tx_crcl] ^ chktabl[yp->tx_crch] ^ 0xff;
		outb(yp->tx_crcl, THR(dev->base_addr));
		yp->tx_state = TX_CRC2;
		break;
	case TX_CRC2:
		outb(chktabh[yp->tx_crch] ^ 0xFF, THR(dev->base_addr));
		if (skb_queue_empty(&yp->send_queue)) {
			yp->tx_count = (yp->bitrate * yp->txtail) / 8000;
			if (yp->dupmode == 2)
				yp->tx_count += (yp->bitrate * yp->holdd) / 8;
			if (yp->tx_count == 0)
				yp->tx_count = 1;
			yp->tx_state = TX_TAIL;
		} else {
			yp->tx_count = 1;
			yp->tx_state = TX_HEAD;
		}
		++dev->stats.tx_packets;
		break;
	case TX_TAIL:
		if (--yp->tx_count <= 0) {
			yp->tx_state = TX_OFF;
			ptt_off(dev);
		}
		break;
	}
}
示例#16
0
/*
 * receive a message from an RxRPC socket
 * - we need to be careful about two or more threads calling recvmsg
 *   simultaneously
 */
int rxrpc_recvmsg(struct kiocb *iocb, struct socket *sock,
		  struct msghdr *msg, size_t len, int flags)
{
	struct rxrpc_skb_priv *sp;
	struct rxrpc_call *call = NULL, *continue_call = NULL;
	struct rxrpc_sock *rx = rxrpc_sk(sock->sk);
	struct sk_buff *skb;
	long timeo;
	int copy, ret, ullen, offset, copied = 0;
	u32 abort_code;

	DEFINE_WAIT(wait);

	_enter(",,,%zu,%d", len, flags);

	if (flags & (MSG_OOB | MSG_TRUNC))
		return -EOPNOTSUPP;

	ullen = msg->msg_flags & MSG_CMSG_COMPAT ? 4 : sizeof(unsigned long);

	timeo = sock_rcvtimeo(&rx->sk, flags & MSG_DONTWAIT);
	msg->msg_flags |= MSG_MORE;

	lock_sock(&rx->sk);

	for (;;) {
		/* return immediately if a client socket has no outstanding
		 * calls */
		if (RB_EMPTY_ROOT(&rx->calls)) {
			if (copied)
				goto out;
			if (rx->sk.sk_state != RXRPC_SERVER_LISTENING) {
				release_sock(&rx->sk);
				if (continue_call)
					rxrpc_put_call(continue_call);
				return -ENODATA;
			}
		}

		/* get the next message on the Rx queue */
		skb = skb_peek(&rx->sk.sk_receive_queue);
		if (!skb) {
			/* nothing remains on the queue */
			if (copied &&
			    (flags & MSG_PEEK || timeo == 0))
				goto out;

			/* wait for a message to turn up */
			release_sock(&rx->sk);
			prepare_to_wait_exclusive(sk_sleep(&rx->sk), &wait,
						  TASK_INTERRUPTIBLE);
			ret = sock_error(&rx->sk);
			if (ret)
				goto wait_error;

			if (skb_queue_empty(&rx->sk.sk_receive_queue)) {
				if (signal_pending(current))
					goto wait_interrupted;
				timeo = schedule_timeout(timeo);
			}
			finish_wait(sk_sleep(&rx->sk), &wait);
			lock_sock(&rx->sk);
			continue;
		}

	peek_next_packet:
		sp = rxrpc_skb(skb);
		call = sp->call;
		ASSERT(call != NULL);

		_debug("next pkt %s", rxrpc_pkts[sp->hdr.type]);

		/* make sure we wait for the state to be updated in this call */
		spin_lock_bh(&call->lock);
		spin_unlock_bh(&call->lock);

		if (test_bit(RXRPC_CALL_RELEASED, &call->flags)) {
			_debug("packet from released call");
			if (skb_dequeue(&rx->sk.sk_receive_queue) != skb)
				BUG();
			rxrpc_free_skb(skb);
			continue;
		}

		/* determine whether to continue last data receive */
		if (continue_call) {
			_debug("maybe cont");
			if (call != continue_call ||
			    skb->mark != RXRPC_SKB_MARK_DATA) {
				release_sock(&rx->sk);
				rxrpc_put_call(continue_call);
				_leave(" = %d [noncont]", copied);
				return copied;
			}
		}

		rxrpc_get_call(call);

		/* copy the peer address and timestamp */
		if (!continue_call) {
			if (msg->msg_name) {
				size_t len =
					sizeof(call->conn->trans->peer->srx);
				memcpy(msg->msg_name,
				       &call->conn->trans->peer->srx, len);
				msg->msg_namelen = len;
			}
			sock_recv_ts_and_drops(msg, &rx->sk, skb);
		}

		/* receive the message */
		if (skb->mark != RXRPC_SKB_MARK_DATA)
			goto receive_non_data_message;

		_debug("recvmsg DATA #%u { %d, %d }",
		       ntohl(sp->hdr.seq), skb->len, sp->offset);

		if (!continue_call) {
			/* only set the control data once per recvmsg() */
			ret = put_cmsg(msg, SOL_RXRPC, RXRPC_USER_CALL_ID,
				       ullen, &call->user_call_ID);
			if (ret < 0)
				goto copy_error;
			ASSERT(test_bit(RXRPC_CALL_HAS_USERID, &call->flags));
		}

		ASSERTCMP(ntohl(sp->hdr.seq), >=, call->rx_data_recv);
		ASSERTCMP(ntohl(sp->hdr.seq), <=, call->rx_data_recv + 1);
		call->rx_data_recv = ntohl(sp->hdr.seq);

		ASSERTCMP(ntohl(sp->hdr.seq), >, call->rx_data_eaten);

		offset = sp->offset;
		copy = skb->len - offset;
		if (copy > len - copied)
			copy = len - copied;

		if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
			ret = skb_copy_datagram_iovec(skb, offset,
						      msg->msg_iov, copy);
		} else {
			ret = skb_copy_and_csum_datagram_iovec(skb, offset,
							       msg->msg_iov);
			if (ret == -EINVAL)
				goto csum_copy_error;
		}

		if (ret < 0)
			goto copy_error;

		/* handle piecemeal consumption of data packets */
		_debug("copied %d+%d", copy, copied);

		offset += copy;
		copied += copy;

		if (!(flags & MSG_PEEK))
			sp->offset = offset;

		if (sp->offset < skb->len) {
			_debug("buffer full");
			ASSERTCMP(copied, ==, len);
			break;
		}

		/* we transferred the whole data packet */
		if (sp->hdr.flags & RXRPC_LAST_PACKET) {
			_debug("last");
			if (call->conn->out_clientflag) {
				 /* last byte of reply received */
				ret = copied;
				goto terminal_message;
			}

			/* last bit of request received */
			if (!(flags & MSG_PEEK)) {
				_debug("eat packet");
				if (skb_dequeue(&rx->sk.sk_receive_queue) !=
				    skb)
					BUG();
				rxrpc_free_skb(skb);
			}
			msg->msg_flags &= ~MSG_MORE;
			break;
		}

		/* move on to the next data message */
		_debug("next");
		if (!continue_call)
			continue_call = sp->call;
		else
			rxrpc_put_call(call);
		call = NULL;

		if (flags & MSG_PEEK) {
			_debug("peek next");
			skb = skb->next;
			if (skb == (struct sk_buff *) &rx->sk.sk_receive_queue)
				break;
			goto peek_next_packet;
		}

		_debug("eat packet");
		if (skb_dequeue(&rx->sk.sk_receive_queue) != skb)
			BUG();
		rxrpc_free_skb(skb);
	}
示例#17
0
static struct sk_buff *ath_dequeue(struct hci_uart *hu)
{
	struct ath_struct *ath = hu->priv;

	return skb_dequeue(&ath->txq);
}
示例#18
0
文件: datagram.c 项目: GNUHurdTR/hurd
struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, int noblock, int *err)
{
	int error;
	struct sk_buff *skb;

	/* Caller is allowed not to check sk->err before skb_recv_datagram() */
	error = sock_error(sk);
	if (error)
		goto no_packet;

restart:
	while(skb_queue_empty(&sk->receive_queue))	/* No data */
	{
		/* Socket errors? */
		error = sock_error(sk);
		if (error)
			goto no_packet;

		/* Socket shut down? */
		if (sk->shutdown & RCV_SHUTDOWN)
			goto no_packet;

		/* Sequenced packets can come disconnected. If so we report the problem */
		error = -ENOTCONN;
		if(connection_based(sk) && sk->state!=TCP_ESTABLISHED)
			goto no_packet;

		/* handle signals */
		error = -ERESTARTSYS;
		if (signal_pending(current))
			goto no_packet;

		/* User doesn't want to wait */
		error = -EAGAIN;
		if (noblock)
			goto no_packet;

		wait_for_packet(sk);
	}

	/* Again only user level code calls this function, so nothing interrupt level
	   will suddenly eat the receive_queue */
	if (flags & MSG_PEEK)
	{
		unsigned long cpu_flags;

		/* It is the only POTENTIAL race condition
		   in this function. skb may be stolen by
		   another receiver after peek, but before
		   incrementing use count, provided kernel
		   is reentearble (it is not) or this function
		   is called by interrupts.

		   Protect it with global skb spinlock,
		   though for now even this is overkill.
		                                --ANK (980728)
		 */
		spin_lock_irqsave(&skb_queue_lock, cpu_flags);
		skb = skb_peek(&sk->receive_queue);
		if(skb!=NULL)
			atomic_inc(&skb->users);
		spin_unlock_irqrestore(&skb_queue_lock, cpu_flags);
	} else
		skb = skb_dequeue(&sk->receive_queue);

	if (!skb)	/* Avoid race if someone beats us to the data */
		goto restart;
	return skb;

no_packet:
	*err = error;
	return NULL;
}
示例#19
0
/*
 * handle an error received on the local endpoint
 */
void rxrpc_UDP_error_report(struct sock *sk)
{
	struct sock_exterr_skb *serr;
	struct rxrpc_transport *trans;
	struct rxrpc_local *local = sk->sk_user_data;
	struct rxrpc_peer *peer;
	struct sk_buff *skb;
	__be32 addr;
	__be16 port;

	_enter("%p{%d}", sk, local->debug_id);

	skb = skb_dequeue(&sk->sk_error_queue);
	if (!skb) {
		_leave("UDP socket errqueue empty");
		return;
	}

	rxrpc_new_skb(skb);

	serr = SKB_EXT_ERR(skb);
	addr = *(__be32 *)(skb_network_header(skb) + serr->addr_offset);
	port = serr->port;

	_net("Rx UDP Error from %pI4:%hu", &addr, ntohs(port));
	_debug("Msg l:%d d:%d", skb->len, skb->data_len);

	peer = rxrpc_find_peer(local, addr, port);
	if (IS_ERR(peer)) {
		rxrpc_free_skb(skb);
		_leave(" [no peer]");
		return;
	}

	trans = rxrpc_find_transport(local, peer);
	if (!trans) {
		rxrpc_put_peer(peer);
		rxrpc_free_skb(skb);
		_leave(" [no trans]");
		return;
	}

	if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP &&
	    serr->ee.ee_type == ICMP_DEST_UNREACH &&
	    serr->ee.ee_code == ICMP_FRAG_NEEDED
	    ) {
		u32 mtu = serr->ee.ee_info;

		_net("Rx Received ICMP Fragmentation Needed (%d)", mtu);

		/* wind down the local interface MTU */
		if (mtu > 0 && peer->if_mtu == 65535 && mtu < peer->if_mtu) {
			peer->if_mtu = mtu;
			_net("I/F MTU %u", mtu);
		}

		/* ip_rt_frag_needed() may have eaten the info */
		if (mtu == 0)
			mtu = ntohs(icmp_hdr(skb)->un.frag.mtu);

		if (mtu == 0) {
			/* they didn't give us a size, estimate one */
			if (mtu > 1500) {
				mtu >>= 1;
				if (mtu < 1500)
					mtu = 1500;
			} else {
示例#20
0
static int handle_minor_send(struct capiminor *mp)
{
	struct sk_buff *skb;
	u16 len;
	int count = 0;
	u16 errcode;
	u16 datahandle;

	if (mp->tty && mp->ttyoutstop) {
#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
		printk(KERN_DEBUG "capi: send: tty stopped\n");
#endif
		return 0;
	}

	while ((skb = skb_dequeue(&mp->outqueue)) != 0) {
		datahandle = mp->datahandle;
		len = (u16)skb->len;
		skb_push(skb, CAPI_DATA_B3_REQ_LEN);
		memset(skb->data, 0, CAPI_DATA_B3_REQ_LEN);
		capimsg_setu16(skb->data, 0, CAPI_DATA_B3_REQ_LEN);
		capimsg_setu16(skb->data, 2, mp->applid);
		capimsg_setu8 (skb->data, 4, CAPI_DATA_B3);
		capimsg_setu8 (skb->data, 5, CAPI_REQ);
		capimsg_setu16(skb->data, 6, mp->msgid++);
		capimsg_setu32(skb->data, 8, mp->ncci);	/* NCCI */
		capimsg_setu32(skb->data, 12, (u32) skb->data); /* Data32 */
		capimsg_setu16(skb->data, 16, len);	/* Data length */
		capimsg_setu16(skb->data, 18, datahandle);
		capimsg_setu16(skb->data, 20, 0);	/* Flags */

		if (capincci_add_ack(mp, datahandle) < 0) {
			skb_pull(skb, CAPI_DATA_B3_REQ_LEN);
			skb_queue_head(&mp->outqueue, skb);
			return count;
		}
		errcode = (*capifuncs->capi_put_message) (mp->applid, skb);
		if (errcode == CAPI_NOERROR) {
			mp->datahandle++;
			count++;
			mp->outbytes -= len;
#ifdef _DEBUG_DATAFLOW
			printk(KERN_DEBUG "capi: DATA_B3_REQ %u len=%u\n",
							datahandle, len);
#endif
			continue;
		}
		capiminor_del_ack(mp, datahandle);

		if (errcode == CAPI_SENDQUEUEFULL) {
			skb_pull(skb, CAPI_DATA_B3_REQ_LEN);
			skb_queue_head(&mp->outqueue, skb);
			break;
		}

		/* ups, drop packet */
		printk(KERN_ERR "capi: put_message = %x\n", errcode);
		mp->outbytes -= len;
		kfree_skb(skb);
	}
	if (count)
		wake_up_interruptible(&mp->sendwait);
	return count;
}
示例#21
0
static void
hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx)
{
	u_char r;
	struct BCState *bcs = cs->bcs + hscx;
	struct sk_buff *skb;
	int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32;
	int count;

	if (!test_bit(BC_FLG_INIT, &bcs->Flag))
		return;

	if (val & 0x80) {	/* RME */
		r = READHSCX(cs, hscx, HSCX_RSTA);
		if ((r & 0xf0) != 0xa0) {
			if (!(r & 0x80)) {
				if (cs->debug & L1_DEB_WARN)
					debugl1(cs, "HSCX invalid frame");
#ifdef ERROR_STATISTIC
				bcs->err_inv++;
#endif
			}
			if ((r & 0x40) && bcs->mode) {
				if (cs->debug & L1_DEB_WARN)
					debugl1(cs, "HSCX RDO mode=%d",
						bcs->mode);
#ifdef ERROR_STATISTIC
				bcs->err_rdo++;
#endif
			}
			if (!(r & 0x20)) {
				if (cs->debug & L1_DEB_WARN)
					debugl1(cs, "HSCX CRC error");
#ifdef ERROR_STATISTIC
				bcs->err_crc++;
#endif
			}
			WriteHSCXCMDR(cs, hscx, 0x80);
		} else {
			count = READHSCX(cs, hscx, HSCX_RBCL) & (
				test_bit(HW_IPAC, &cs->HW_Flags)? 0x3f: 0x1f);
			if (count == 0)
				count = fifo_size;
			hscx_empty_fifo(bcs, count);
			if ((count = bcs->hw.hscx.rcvidx - 1) > 0) {
				if (cs->debug & L1_DEB_HSCX_FIFO)
					debugl1(cs, "HX Frame %d", count);
				if (!(skb = dev_alloc_skb(count)))
					printk(KERN_WARNING "HSCX: receive out of memory\n");
				else {
					memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count);
					skb_queue_tail(&bcs->rqueue, skb);
				}
			}
		}
		bcs->hw.hscx.rcvidx = 0;
		schedule_event(bcs, B_RCVBUFREADY);
	}
	if (val & 0x40) {	/* RPF */
		hscx_empty_fifo(bcs, fifo_size);
		if (bcs->mode == L1_MODE_TRANS) {
			/* receive audio data */
			if (!(skb = dev_alloc_skb(fifo_size)))
				printk(KERN_WARNING "HiSax: receive out of memory\n");
			else {
				memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size);
				skb_queue_tail(&bcs->rqueue, skb);
			}
			bcs->hw.hscx.rcvidx = 0;
			schedule_event(bcs, B_RCVBUFREADY);
		}
	}
	if (val & 0x10) {	/* XPR */
		if (bcs->tx_skb) {
			if (bcs->tx_skb->len) {
				hscx_fill_fifo(bcs);
				return;
			} else {
				if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) &&
					(PACKET_NOACK != bcs->tx_skb->pkt_type)) {
					u_long	flags;
					spin_lock_irqsave(&bcs->aclock, flags);
					bcs->ackcnt += bcs->hw.hscx.count;
					spin_unlock_irqrestore(&bcs->aclock, flags);
					schedule_event(bcs, B_ACKPENDING);
				}
				dev_kfree_skb_irq(bcs->tx_skb);
				bcs->hw.hscx.count = 0; 
				bcs->tx_skb = NULL;
			}
		}
		if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
			bcs->hw.hscx.count = 0;
			test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
			hscx_fill_fifo(bcs);
		} else {
			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
			schedule_event(bcs, B_XMTBUFREADY);
		}
	}
}
示例#22
0
static void
W6692B_interrupt(struct IsdnCardState *cs, u_char bchan)
{
	u_char val;
	u_char r;
	struct BCState *bcs;
	struct sk_buff *skb;
	int count;

	bcs = (cs->bcs->channel == bchan) ? cs->bcs : (cs->bcs+1);
	val = cs->BC_Read_Reg(cs, bchan, W_B_EXIR);
	debugl1(cs, "W6692B chan %d B_EXIR 0x%02X", bchan, val);

	if (!test_bit(BC_FLG_INIT, &bcs->Flag)) {
		debugl1(cs, "W6692B not INIT yet");
		return;
	}
	if (val & W_B_EXI_RME) {	/* RME */
		r = cs->BC_Read_Reg(cs, bchan, W_B_STAR);
		if (r & (W_B_STAR_RDOV | W_B_STAR_CRCE | W_B_STAR_RMB)) {
			if (cs->debug & L1_DEB_WARN)
				debugl1(cs, "W6692 B STAR %x", r);
			if ((r & W_B_STAR_RDOV) && bcs->mode)
				if (cs->debug & L1_DEB_WARN)
					debugl1(cs, "W6692 B RDOV mode=%d",
						bcs->mode);
			if (r & W_B_STAR_CRCE)
				if (cs->debug & L1_DEB_WARN)
					debugl1(cs, "W6692 B CRC error");
			cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RRST | W_B_CMDR_RACT);
		} else {
			count = cs->BC_Read_Reg(cs, bchan, W_B_RBCL) & (W_B_FIFO_THRESH - 1);
			if (count == 0)
				count = W_B_FIFO_THRESH;
			W6692B_empty_fifo(bcs, count);
			if ((count = bcs->hw.w6692.rcvidx) > 0) {
				if (cs->debug & L1_DEB_HSCX_FIFO)
					debugl1(cs, "W6692 Bchan Frame %d", count);
				if (!(skb = dev_alloc_skb(count)))
					printk(KERN_WARNING "W6692: Bchan receive out of memory\n");
				else {
					memcpy(skb_put(skb, count), bcs->hw.w6692.rcvbuf, count);
					skb_queue_tail(&bcs->rqueue, skb);
				}
			}
		}
		bcs->hw.w6692.rcvidx = 0;
		schedule_event(bcs, B_RCVBUFREADY);
	}
	if (val & W_B_EXI_RMR) {	/* RMR */
		W6692B_empty_fifo(bcs, W_B_FIFO_THRESH);
		r = cs->BC_Read_Reg(cs, bchan, W_B_STAR);
		if (r & W_B_STAR_RDOV) {
			if (cs->debug & L1_DEB_WARN)
				debugl1(cs, "W6692 B RDOV(RMR) mode=%d",bcs->mode);
			cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RRST | W_B_CMDR_RACT);
			if (bcs->mode != L1_MODE_TRANS)
				bcs->hw.w6692.rcvidx = 0;
		}
		if (bcs->mode == L1_MODE_TRANS) {
			/* receive audio data */
			if (!(skb = dev_alloc_skb(W_B_FIFO_THRESH)))
				printk(KERN_WARNING "HiSax: receive out of memory\n");
			else {
				memcpy(skb_put(skb, W_B_FIFO_THRESH), bcs->hw.w6692.rcvbuf, W_B_FIFO_THRESH);
				skb_queue_tail(&bcs->rqueue, skb);
			}
			bcs->hw.w6692.rcvidx = 0;
			schedule_event(bcs, B_RCVBUFREADY);
		}
	}
	if (val & W_B_EXI_XDUN) {	/* XDUN */
		cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_XRST | W_B_CMDR_RACT);
		if (cs->debug & L1_DEB_WARN)
			debugl1(cs, "W6692 B EXIR %x Lost TX", val);
		if (bcs->mode == 1)
			W6692B_fill_fifo(bcs);
		else {
			/* Here we lost an TX interrupt, so
			   * restart transmitting the whole frame.
			 */
			if (bcs->tx_skb) {
				skb_push(bcs->tx_skb, bcs->hw.w6692.count);
				bcs->tx_cnt += bcs->hw.w6692.count;
				bcs->hw.w6692.count = 0;
			}
		}
		return;
	}
	if (val & W_B_EXI_XFR) {	/* XFR */
		r = cs->BC_Read_Reg(cs, bchan, W_B_STAR);
		if (r & W_B_STAR_XDOW) {
			if (cs->debug & L1_DEB_WARN)
				debugl1(cs, "W6692 B STAR %x XDOW", r);
			cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_XRST | W_B_CMDR_RACT);
			if (bcs->tx_skb && (bcs->mode != 1)) {
				skb_push(bcs->tx_skb, bcs->hw.w6692.count);
				bcs->tx_cnt += bcs->hw.w6692.count;
				bcs->hw.w6692.count = 0;
			}
		}
		if (bcs->tx_skb) {
			if (bcs->tx_skb->len) {
				W6692B_fill_fifo(bcs);
				return;
			} else {
				if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) &&
					(PACKET_NOACK != bcs->tx_skb->pkt_type)) {
					u_long	flags;
					spin_lock_irqsave(&bcs->aclock, flags);
					bcs->ackcnt += bcs->hw.w6692.count;
					spin_unlock_irqrestore(&bcs->aclock, flags);
					schedule_event(bcs, B_ACKPENDING);
				}
				dev_kfree_skb_irq(bcs->tx_skb);
				bcs->hw.w6692.count = 0;
				bcs->tx_skb = NULL;
			}
		}
		if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
			bcs->hw.w6692.count = 0;
			test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
			W6692B_fill_fifo(bcs);
		} else {
			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
			schedule_event(bcs, B_XMTBUFREADY);
		}
	}
}
示例#23
0
static int mwifiex_usb_prepare_tx_aggr_skb(struct mwifiex_adapter *adapter,
					   struct usb_tx_data_port *port,
					   struct sk_buff **skb_send)
{
	struct sk_buff *skb_aggr, *skb_tmp;
	u8 *payload, pad;
	u16 align = adapter->bus_aggr.tx_aggr_align;
	struct mwifiex_txinfo *tx_info = NULL;
	bool is_txinfo_set = false;

	/* Packets in aggr_list will be send in either skb_aggr or
	 * write complete, delete the tx_aggr timer
	 */
	if (port->tx_aggr.timer_cnxt.is_hold_timer_set) {
		del_timer(&port->tx_aggr.timer_cnxt.hold_timer);
		port->tx_aggr.timer_cnxt.is_hold_timer_set = false;
		port->tx_aggr.timer_cnxt.hold_tmo_msecs = 0;
	}

	skb_aggr = mwifiex_alloc_dma_align_buf(port->tx_aggr.aggr_len,
					       GFP_ATOMIC);
	if (!skb_aggr) {
		mwifiex_dbg(adapter, ERROR,
			    "%s: alloc skb_aggr failed\n", __func__);

		while ((skb_tmp = skb_dequeue(&port->tx_aggr.aggr_list)))
			mwifiex_write_data_complete(adapter, skb_tmp, 0, -1);

		port->tx_aggr.aggr_num = 0;
		port->tx_aggr.aggr_len = 0;
		return -EBUSY;
	}

	tx_info = MWIFIEX_SKB_TXCB(skb_aggr);
	memset(tx_info, 0, sizeof(*tx_info));

	while ((skb_tmp = skb_dequeue(&port->tx_aggr.aggr_list))) {
		/* padding for aligning next packet header*/
		pad = (align - (skb_tmp->len & (align - 1))) % align;
		payload = skb_put(skb_aggr, skb_tmp->len + pad);
		memcpy(payload, skb_tmp->data, skb_tmp->len);
		if (skb_queue_empty(&port->tx_aggr.aggr_list)) {
			/* do not padding for last packet*/
			*(u16 *)payload = cpu_to_le16(skb_tmp->len);
			*(u16 *)&payload[2] =
				cpu_to_le16(MWIFIEX_TYPE_AGGR_DATA_V2 | 0x80);
			skb_trim(skb_aggr, skb_aggr->len - pad);
		} else {
			/* add aggregation interface header */
			*(u16 *)payload = cpu_to_le16(skb_tmp->len + pad);
			*(u16 *)&payload[2] =
				cpu_to_le16(MWIFIEX_TYPE_AGGR_DATA_V2);
		}

		if (!is_txinfo_set) {
			tx_info->bss_num = MWIFIEX_SKB_TXCB(skb_tmp)->bss_num;
			tx_info->bss_type = MWIFIEX_SKB_TXCB(skb_tmp)->bss_type;
			is_txinfo_set = true;
		}

		port->tx_aggr.aggr_num--;
		port->tx_aggr.aggr_len -= (skb_tmp->len + pad);
		mwifiex_write_data_complete(adapter, skb_tmp, 0, 0);
	}

	tx_info->pkt_len = skb_aggr->len -
			(sizeof(struct txpd) + adapter->intf_hdr_len);
	tx_info->flags |= MWIFIEX_BUF_FLAG_AGGR_PKT;

	port->tx_aggr.aggr_num = 0;
	port->tx_aggr.aggr_len = 0;
	*skb_send = skb_aggr;

	return 0;
}
示例#24
0
static irqreturn_t
W6692_interrupt(int intno, void *dev_id)
{
	struct IsdnCardState	*cs = dev_id;
	u_char			val, exval, v1;
	struct sk_buff		*skb;
	u_int			count;
	u_long			flags;
	int			icnt = 5;

	spin_lock_irqsave(&cs->lock, flags);
	val = cs->readW6692(cs, W_ISTA);
	if (!val) {
		spin_unlock_irqrestore(&cs->lock, flags);
		return IRQ_NONE;
	}
      StartW6692:
	if (cs->debug & L1_DEB_ISAC)
		debugl1(cs, "W6692 ISTA %x", val);

	if (val & W_INT_D_RME) {	/* RME */
		exval = cs->readW6692(cs, W_D_RSTA);
		if (exval & (W_D_RSTA_RDOV | W_D_RSTA_CRCE | W_D_RSTA_RMB)) {
			if (exval & W_D_RSTA_RDOV)
				if (cs->debug & L1_DEB_WARN)
					debugl1(cs, "W6692 RDOV");
			if (exval & W_D_RSTA_CRCE)
				if (cs->debug & L1_DEB_WARN)
					debugl1(cs, "W6692 D-channel CRC error");
			if (exval & W_D_RSTA_RMB)
				if (cs->debug & L1_DEB_WARN)
					debugl1(cs, "W6692 D-channel ABORT");
			cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RACK | W_D_CMDR_RRST);
		} else {
			count = cs->readW6692(cs, W_D_RBCL) & (W_D_FIFO_THRESH - 1);
			if (count == 0)
				count = W_D_FIFO_THRESH;
			W6692_empty_fifo(cs, count);
			if ((count = cs->rcvidx) > 0) {
				cs->rcvidx = 0;
				if (!(skb = alloc_skb(count, GFP_ATOMIC)))
					printk(KERN_WARNING "HiSax: D receive out of memory\n");
				else {
					memcpy(skb_put(skb, count), cs->rcvbuf, count);
					skb_queue_tail(&cs->rq, skb);
				}
			}
		}
		cs->rcvidx = 0;
		schedule_event(cs, D_RCVBUFREADY);
	}
	if (val & W_INT_D_RMR) {	/* RMR */
		W6692_empty_fifo(cs, W_D_FIFO_THRESH);
	}
	if (val & W_INT_D_XFR) {	/* XFR */
		if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
			del_timer(&cs->dbusytimer);
		if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
			schedule_event(cs, D_CLEARBUSY);
		if (cs->tx_skb) {
			if (cs->tx_skb->len) {
				W6692_fill_fifo(cs);
				goto afterXFR;
			} else {
				dev_kfree_skb_irq(cs->tx_skb);
				cs->tx_cnt = 0;
				cs->tx_skb = NULL;
			}
		}
		if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
			cs->tx_cnt = 0;
			W6692_fill_fifo(cs);
		} else
			schedule_event(cs, D_XMTBUFREADY);
	}
      afterXFR:
	if (val & (W_INT_XINT0 | W_INT_XINT1)) {	/* XINT0/1 - never */
		if (cs->debug & L1_DEB_ISAC)
			debugl1(cs, "W6692 spurious XINT!");
	}
	if (val & W_INT_D_EXI) {	/* EXI */
		exval = cs->readW6692(cs, W_D_EXIR);
		if (cs->debug & L1_DEB_WARN)
			debugl1(cs, "W6692 D_EXIR %02x", exval);
		if (exval & (W_D_EXI_XDUN | W_D_EXI_XCOL)) {	/* Transmit underrun/collision */
			debugl1(cs, "W6692 D-chan underrun/collision");
			printk(KERN_WARNING "HiSax: W6692 XDUN/XCOL\n");
			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
				del_timer(&cs->dbusytimer);
			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
				schedule_event(cs, D_CLEARBUSY);
			if (cs->tx_skb) {	/* Restart frame */
				skb_push(cs->tx_skb, cs->tx_cnt);
				cs->tx_cnt = 0;
				W6692_fill_fifo(cs);
			} else {
				printk(KERN_WARNING "HiSax: W6692 XDUN/XCOL no skb\n");
				debugl1(cs, "W6692 XDUN/XCOL no skb");
				cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_XRST);
			}
		}
		if (exval & W_D_EXI_RDOV) {	/* RDOV */
			debugl1(cs, "W6692 D-channel RDOV");
			printk(KERN_WARNING "HiSax: W6692 D-RDOV\n");
			cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RRST);
		}
		if (exval & W_D_EXI_TIN2) {	/* TIN2 - never */
			debugl1(cs, "W6692 spurious TIN2 interrupt");
		}
		if (exval & W_D_EXI_MOC) {	/* MOC - not supported */
			debugl1(cs, "W6692 spurious MOC interrupt");
			v1 = cs->readW6692(cs, W_MOSR);
			debugl1(cs, "W6692 MOSR %02x", v1);
		}
		if (exval & W_D_EXI_ISC) {	/* ISC - Level1 change */
			v1 = cs->readW6692(cs, W_CIR);
			if (cs->debug & L1_DEB_ISAC)
				debugl1(cs, "W6692 ISC CIR=0x%02X", v1);
			if (v1 & W_CIR_ICC) {
				cs->dc.w6692.ph_state = v1 & W_CIR_COD_MASK;
				if (cs->debug & L1_DEB_ISAC)
					debugl1(cs, "ph_state_change %x", cs->dc.w6692.ph_state);
				schedule_event(cs, D_L1STATECHANGE);
			}
			if (v1 & W_CIR_SCC) {
				v1 = cs->readW6692(cs, W_SQR);
				debugl1(cs, "W6692 SCC SQR=0x%02X", v1);
			}
		}
		if (exval & W_D_EXI_WEXP) {
			debugl1(cs, "W6692 spurious WEXP interrupt!");
		}
		if (exval & W_D_EXI_TEXP) {
			debugl1(cs, "W6692 spurious TEXP interrupt!");
		}
	}
	if (val & W_INT_B1_EXI) {
		debugl1(cs, "W6692 B channel 1 interrupt");
		W6692B_interrupt(cs, 0);
	}
	if (val & W_INT_B2_EXI) {
		debugl1(cs, "W6692 B channel 2 interrupt");
		W6692B_interrupt(cs, 1);
	}
	val = cs->readW6692(cs, W_ISTA);
	if (val && icnt) {
		icnt--;
		goto StartW6692;
	}
	if (!icnt) {
		printk(KERN_WARNING "W6692 IRQ LOOP\n");
		cs->writeW6692(cs, W_IMASK, 0xff);
	}
	spin_unlock_irqrestore(&cs->lock, flags);
	return IRQ_HANDLED;
}
示例#25
0
/**
 *	@brief read handler for BT char dev
 *
 *	@param filp	pointer to structure file
 *	@param buf		pointer to char buffer
 *	@param count	size of receive buffer
 *	@param f_pos	pointer to loff_t type data
 *	@return			number of bytes read
 */
ssize_t
chardev_read(struct file * filp, char *buf, size_t count, loff_t * f_pos)
{
	struct char_dev *dev = (struct char_dev *)filp->private_data;
	struct m_dev *m_dev = dev->m_dev;
	DECLARE_WAITQUEUE(wait, current);
	ssize_t ret = 0;
	struct sk_buff *skb = NULL;

	ENTER();
	if (!dev || !dev->m_dev) {
		LEAVE();
		return -ENXIO;
	}
	/* Wait for rx data */
	add_wait_queue(&m_dev->req_wait_q, &wait);
	while (1) {
		set_current_state(TASK_INTERRUPTIBLE);
		skb = skb_dequeue(&m_dev->rx_q);
		if (skb)
			break;
		if (!test_bit(HCI_UP, &m_dev->flags)) {
			ret = -EBUSY;
			break;
		}

		if (filp->f_flags & O_NONBLOCK) {
			ret = -EAGAIN;
			break;
		}
		if (signal_pending(current)) {
			ret = -EINTR;
			break;
		}
		schedule();
	}
	set_current_state(TASK_RUNNING);
	remove_wait_queue(&m_dev->req_wait_q, &wait);

	if (!skb)
		goto out;

	if (m_dev->read_continue_flag == 0) {
		/* Put type byte before the data */
		memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
		PRINTM(DATA, "Read: pkt_type: 0x%x, len=%d @%lu\n",
		       bt_cb(skb)->pkt_type, skb->len, jiffies);
	}
	DBG_HEXDUMP(DAT_D, "chardev_read", skb->data, skb->len);
	if (skb->len > count) {
		/* user data length is smaller than the skb length */
		if (copy_to_user(buf, skb->data, count)) {
			ret = -EFAULT;
			goto outf;
		}
		skb_pull(skb, count);
		skb_queue_head(&m_dev->rx_q, skb);
		m_dev->read_continue_flag = 1;
		wake_up_interruptible(&m_dev->req_wait_q);
		ret = count;
		goto out;
	} else {
		if (copy_to_user(buf, skb->data, skb->len)) {
			ret = -EFAULT;
			goto outf;
		}
		m_dev->read_continue_flag = 0;
		ret = skb->len;
	}
outf:
	kfree_skb(skb);
out:
	LEAVE();
	return ret;
}
示例#26
0
/*
 * reject packets through the local endpoint
 */
void rxrpc_reject_packets(struct work_struct *work)
{
	union {
		struct sockaddr sa;
		struct sockaddr_in sin;
	} sa;
	struct rxrpc_skb_priv *sp;
	struct rxrpc_header hdr;
	struct rxrpc_local *local;
	struct sk_buff *skb;
	struct msghdr msg;
	struct kvec iov[2];
	size_t size;
	__be32 code;

	local = container_of(work, struct rxrpc_local, rejecter);
	rxrpc_get_local(local);

	_enter("%d", local->debug_id);

	iov[0].iov_base = &hdr;
	iov[0].iov_len = sizeof(hdr);
	iov[1].iov_base = &code;
	iov[1].iov_len = sizeof(code);
	size = sizeof(hdr) + sizeof(code);

	msg.msg_name = &sa;
	msg.msg_control = NULL;
	msg.msg_controllen = 0;
	msg.msg_flags = 0;

	memset(&sa, 0, sizeof(sa));
	sa.sa.sa_family = local->srx.transport.family;
	switch (sa.sa.sa_family) {
	case AF_INET:
		msg.msg_namelen = sizeof(sa.sin);
		break;
	default:
		msg.msg_namelen = 0;
		break;
	}

	memset(&hdr, 0, sizeof(hdr));
	hdr.type = RXRPC_PACKET_TYPE_ABORT;

	while ((skb = skb_dequeue(&local->reject_queue))) {
		sp = rxrpc_skb(skb);
		switch (sa.sa.sa_family) {
		case AF_INET:
			sa.sin.sin_port = udp_hdr(skb)->source;
			sa.sin.sin_addr.s_addr = ip_hdr(skb)->saddr;
			code = htonl(skb->priority);

			hdr.epoch = sp->hdr.epoch;
			hdr.cid = sp->hdr.cid;
			hdr.callNumber = sp->hdr.callNumber;
			hdr.serviceId = sp->hdr.serviceId;
			hdr.flags = sp->hdr.flags;
			hdr.flags ^= RXRPC_CLIENT_INITIATED;
			hdr.flags &= RXRPC_CLIENT_INITIATED;

			kernel_sendmsg(local->socket, &msg, iov, 2, size);
			break;

		default:
			break;
		}

		rxrpc_free_skb(skb);
		rxrpc_put_local(local);
	}

	rxrpc_put_local(local);
	_leave("");
}
示例#27
0
static void c4_dispatch_tx(avmcard *card)
{
	avmcard_dmainfo *dma = card->dma;
	struct sk_buff *skb;
	u8 cmd, subcmd;
	u16 len;
	u32 txlen;
	void *p;


	if (card->csr & DBELL_DOWN_ARM) { /* tx busy */
		return;
	}

	skb = skb_dequeue(&dma->send_queue);
	if (!skb) {
#ifdef CONFIG_C4_DEBUG
		printk(KERN_DEBUG "%s: tx underrun\n", card->name);
#endif
		return;
	}

	len = CAPIMSG_LEN(skb->data);

	if (len) {
		cmd = CAPIMSG_COMMAND(skb->data);
		subcmd = CAPIMSG_SUBCOMMAND(skb->data);

		p = dma->sendbuf.dmabuf;

		if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
			u16 dlen = CAPIMSG_DATALEN(skb->data);
			_put_byte(&p, SEND_DATA_B3_REQ);
			_put_slice(&p, skb->data, len);
			_put_slice(&p, skb->data + len, dlen);
		} else {
			_put_byte(&p, SEND_MESSAGE);
			_put_slice(&p, skb->data, len);
		}
		txlen = (u8 *)p - (u8 *)dma->sendbuf.dmabuf;
#ifdef CONFIG_C4_DEBUG
		printk(KERN_DEBUG "%s: tx put msg len=%d\n", card->name, txlen);
#endif
	} else {
		txlen = skb->len-2;
#ifdef CONFIG_C4_POLLDEBUG
		if (skb->data[2] == SEND_POLLACK)
			printk(KERN_INFO "%s: ack to c4\n", card->name);
#endif
#ifdef CONFIG_C4_DEBUG
		printk(KERN_DEBUG "%s: tx put 0x%x len=%d\n",
				card->name, skb->data[2], txlen);
#endif
		memcpy(dma->sendbuf.dmabuf, skb->data+2, skb->len-2);
	}
	txlen = (txlen + 3) & ~3;

	c4outmeml(card->mbase+MBOX_DOWN_ADDR, dma->sendbuf.dmaaddr);
	c4outmeml(card->mbase+MBOX_DOWN_LEN, txlen);

	card->csr |= DBELL_DOWN_ARM;

	c4outmeml(card->mbase+DOORBELL, DBELL_DOWN_ARM);

	dev_kfree_skb_any(skb);
}
示例#28
0
/*
 * deliver messages to a call
 */
static void afs_deliver_to_call(struct afs_call *call)
{
	struct sk_buff *skb;
	bool last;
	u32 abort_code;
	int ret;

	_enter("");

	while ((call->state == AFS_CALL_AWAIT_REPLY ||
		call->state == AFS_CALL_AWAIT_OP_ID ||
		call->state == AFS_CALL_AWAIT_REQUEST ||
		call->state == AFS_CALL_AWAIT_ACK) &&
	       (skb = skb_dequeue(&call->rx_queue))) {
		switch (skb->mark) {
		case RXRPC_SKB_MARK_DATA:
			_debug("Rcv DATA");
			last = rxrpc_kernel_is_data_last(skb);
			ret = call->type->deliver(call, skb, last);
			switch (ret) {
			case 0:
				if (last &&
				    call->state == AFS_CALL_AWAIT_REPLY)
					call->state = AFS_CALL_COMPLETE;
				break;
			case -ENOTCONN:
				abort_code = RX_CALL_DEAD;
				goto do_abort;
			case -ENOTSUPP:
				abort_code = RX_INVALID_OPERATION;
				goto do_abort;
			default:
				abort_code = RXGEN_CC_UNMARSHAL;
				if (call->state != AFS_CALL_AWAIT_REPLY)
					abort_code = RXGEN_SS_UNMARSHAL;
			do_abort:
				rxrpc_kernel_abort_call(call->rxcall,
							abort_code);
				call->error = ret;
				call->state = AFS_CALL_ERROR;
				break;
			}
			afs_data_delivered(skb);
			skb = NULL;
			continue;
		case RXRPC_SKB_MARK_FINAL_ACK:
			_debug("Rcv ACK");
			call->state = AFS_CALL_COMPLETE;
			break;
		case RXRPC_SKB_MARK_BUSY:
			_debug("Rcv BUSY");
			call->error = -EBUSY;
			call->state = AFS_CALL_BUSY;
			break;
		case RXRPC_SKB_MARK_REMOTE_ABORT:
			abort_code = rxrpc_kernel_get_abort_code(skb);
			call->error = call->type->abort_to_error(abort_code);
			call->state = AFS_CALL_ABORTED;
			_debug("Rcv ABORT %u -> %d", abort_code, call->error);
			break;
		case RXRPC_SKB_MARK_NET_ERROR:
			call->error = -rxrpc_kernel_get_error_number(skb);
			call->state = AFS_CALL_ERROR;
			_debug("Rcv NET ERROR %d", call->error);
			break;
		case RXRPC_SKB_MARK_LOCAL_ERROR:
			call->error = -rxrpc_kernel_get_error_number(skb);
			call->state = AFS_CALL_ERROR;
			_debug("Rcv LOCAL ERROR %d", call->error);
			break;
		default:
			BUG();
			break;
		}

		afs_free_skb(skb);
	}

	/* make sure the queue is empty if the call is done with (we might have
	 * aborted the call early because of an unmarshalling error) */
	if (call->state >= AFS_CALL_COMPLETE) {
		while ((skb = skb_dequeue(&call->rx_queue)))
			afs_free_skb(skb);
		if (call->incoming) {
			rxrpc_kernel_end_call(call->rxcall);
			call->rxcall = NULL;
			call->type->destructor(call);
			afs_free_call(call);
		}
	}

	_leave("");
}
示例#29
0
static void shaper_flush(struct shaper *shaper)
{
	struct sk_buff *skb;
	while((skb=skb_dequeue(&shaper->sendq))!=NULL)
		dev_kfree_skb(skb);
}
示例#30
0
u32 usb_read_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)
{
	int err;
	unsigned int pipe;
	u32 ret = _FAIL;
	PURB purb = NULL;
	struct recv_buf	*precvbuf = (struct recv_buf *)rmem;
	_adapter		*adapter = pintfhdl->padapter;
	struct dvobj_priv	*pdvobj = adapter_to_dvobj(adapter);
	struct pwrctrl_priv *pwrctl = dvobj_to_pwrctl(pdvobj);
	struct recv_priv	*precvpriv = &adapter->recvpriv;
	struct usb_device	*pusbd = pdvobj->pusbdev;

_func_enter_;

	if (RTW_CANNOT_RX(adapter) || (precvbuf == NULL)) {
		RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_read_port:( RTW_CANNOT_RX ) || precvbuf == NULL!!!\n"));
		goto exit;
	}

	usb_init_recvbuf(adapter, precvbuf);

	if (precvbuf->pskb == NULL) {
		SIZE_PTR tmpaddr = 0;
		SIZE_PTR alignment = 0;

		if (NULL != (precvbuf->pskb = skb_dequeue(&precvpriv->free_recv_skb_queue)))
			goto recv_buf_hook;

		#ifndef CONFIG_FIX_NR_BULKIN_BUFFER
		precvbuf->pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
		#endif

		if (precvbuf->pskb == NULL) {
			if (0)
				DBG_871X("usb_read_port() enqueue precvbuf=%p \n", precvbuf);
			/* enqueue precvbuf and wait for free skb */
			rtw_enqueue_recvbuf(precvbuf, &precvpriv->recv_buf_pending_queue);
			goto exit;
		}

		tmpaddr = (SIZE_PTR)precvbuf->pskb->data;
		alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
		skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
	}

recv_buf_hook:
	precvbuf->phead = precvbuf->pskb->head;
	precvbuf->pdata = precvbuf->pskb->data;
	precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
	precvbuf->pend = skb_end_pointer(precvbuf->pskb);
	precvbuf->pbuf = precvbuf->pskb->data;

	purb = precvbuf->purb;

	/* translate DMA FIFO addr to pipehandle */
	pipe = ffaddr2pipehdl(pdvobj, addr);

	usb_fill_bulk_urb(purb, pusbd, pipe,
		precvbuf->pbuf,
		MAX_RECVBUF_SZ,
		usb_read_port_complete,
		precvbuf);

	err = usb_submit_urb(purb, GFP_ATOMIC);
	if (err && err != (-EPERM)) {
		DBG_871X("cannot submit rx in-token(err = 0x%08x),urb_status = %d\n"
			, err, purb->status);
		goto exit;
	}

	ATOMIC_INC(&(precvpriv->rx_pending_cnt));
	ret = _SUCCESS;

exit:

_func_exit_;

	return ret;
}