static void rx_dle_intr()

in iphase.c [1274:1374]


static void rx_dle_intr(struct atm_dev *dev)  
{  
  IADEV *iadev;  
  struct atm_vcc *vcc;   
  struct sk_buff *skb;  
  int desc;  
  u_short state;   
  struct dle *dle, *cur_dle;  
  u_int dle_lp;  
  int len;
  iadev = INPH_IA_DEV(dev);  
 
  /* free all the dles done, that is just update our own dle read pointer   
	- do we really need to do this. Think not. */  
  /* DMA is done, just get all the recevie buffers from the rx dma queue  
	and push them up to the higher layer protocol. Also free the desc  
	associated with the buffer. */  
  dle = iadev->rx_dle_q.read;  
  dle_lp = readl(iadev->dma+IPHASE5575_RX_LIST_ADDR) & (sizeof(struct dle)*DLE_ENTRIES - 1);  
  cur_dle = (struct dle*)(iadev->rx_dle_q.start + (dle_lp >> 4));  
  while(dle != cur_dle)  
  {  
      /* free the DMAed skb */  
      skb = skb_dequeue(&iadev->rx_dma_q);  
      if (!skb)  
         goto INCR_DLE;
      desc = ATM_DESC(skb);
      free_desc(dev, desc);  
               
      if (!(len = skb->len))
      {  
          printk("rx_dle_intr: skb len 0\n");  
	  dev_kfree_skb_any(skb);  
      }  
      else  
      {  
          struct cpcs_trailer *trailer;
          u_short length;
          struct ia_vcc *ia_vcc;

	  dma_unmap_single(&iadev->pci->dev, iadev->rx_dle_q.write->sys_pkt_addr,
			   len, DMA_FROM_DEVICE);
          /* no VCC related housekeeping done as yet. lets see */  
          vcc = ATM_SKB(skb)->vcc;
	  if (!vcc) {
	      printk("IA: null vcc\n");  
              dev_kfree_skb_any(skb);
              goto INCR_DLE;
          }
          ia_vcc = INPH_IA_VCC(vcc);
          if (ia_vcc == NULL)
          {
             atomic_inc(&vcc->stats->rx_err);
             atm_return(vcc, skb->truesize);
             dev_kfree_skb_any(skb);
             goto INCR_DLE;
           }
          // get real pkt length  pwang_test
          trailer = (struct cpcs_trailer*)((u_char *)skb->data +
                                 skb->len - sizeof(*trailer));
	  length = swap_byte_order(trailer->length);
          if ((length > iadev->rx_buf_sz) || (length > 
                              (skb->len - sizeof(struct cpcs_trailer))))
          {
             atomic_inc(&vcc->stats->rx_err);
             IF_ERR(printk("rx_dle_intr: Bad  AAL5 trailer %d (skb len %d)", 
                                                            length, skb->len);)
             atm_return(vcc, skb->truesize);
             dev_kfree_skb_any(skb);
             goto INCR_DLE;
          }
          skb_trim(skb, length);
          
	  /* Display the packet */  
	  IF_RXPKT(printk("\nDmad Recvd data: len = %d \n", skb->len);  
          xdump(skb->data, skb->len, "RX: ");
          printk("\n");)

	  IF_RX(printk("rx_dle_intr: skb push");)  
	  vcc->push(vcc,skb);  
	  atomic_inc(&vcc->stats->rx);
          iadev->rx_pkt_cnt++;
      }  
INCR_DLE:
      if (++dle == iadev->rx_dle_q.end)  
    	  dle = iadev->rx_dle_q.start;  
  }  
  iadev->rx_dle_q.read = dle;  
  
  /* if the interrupts are masked because there were no free desc available,  
		unmask them now. */ 
  if (!iadev->rxing) {
     state = readl(iadev->reass_reg + STATE_REG) & 0xffff;
     if (!(state & FREEQ_EMPTY)) {
        state = readl(iadev->reass_reg + REASS_MASK_REG) & 0xffff;
        writel(state & ~(RX_FREEQ_EMPT |/* RX_EXCP_RCVD |*/ RX_PKT_RCVD),
                                      iadev->reass_reg+REASS_MASK_REG);
        iadev->rxing++; 
     }
  }
}