if (skb->list != &card->sbpool.queue) 
if (NS_SKB_CB(skb)->buf_type != BUF_SM) 
static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe){   u32 vpi, vci;   vc_map *vc;   struct sk_buff *iovb;   struct iovec *iov;   struct atm_vcc *vcc;   struct sk_buff *skb;   unsigned short aal5_len;   int len;   u32 stat;   stat = readl(card->membase + STAT);   card->sbfqc = ns_stat_sfbqc_get(stat);      card->lbfqc = ns_stat_lfbqc_get(stat);   skb = (struct sk_buff *) le32_to_cpu(rsqe->buffer_handle);   vpi = ns_rsqe_vpi(rsqe);   vci = ns_rsqe_vci(rsqe);   if (vpi >= 1UL << card->vpibits || vci >= 1UL << card->vcibits)   {      printk("nicstar%d: SDU received for out-of-range vc %d.%d.\n",             card->index, vpi, vci);      recycle_rx_buf(card, skb);      return;   }      vc = &(card->vcmap[vpi << card->vcibits | vci]);   if (!vc->rx)   {      RXPRINTK("nicstar%d: SDU received on non-rx vc %d.%d.\n",             card->index, vpi, vci);      recycle_rx_buf(card, skb);      return;   }   vcc = vc->rx_vcc;   if (vcc->qos.aal == ATM_AAL0)   {      struct sk_buff *sb;      unsigned char *cell;      int i;      cell = skb->data;      for (i = ns_rsqe_cellcount(rsqe); i; i--)      {         if ((sb = dev_alloc_skb(NS_SMSKBSIZE)) == NULL)         {            printk("nicstar%d: Can't allocate buffers for aal0.\n",                   card->index);            atomic_add(i,&vcc->stats->rx_drop);            break;         }         if (!atm_charge(vcc, sb->truesize))         {            RXPRINTK("nicstar%d: atm_charge() dropped aal0 packets.\n",                     card->index);            atomic_add(i-1,&vcc->stats->rx_drop); /* already increased by 1 */            dev_kfree_skb_any(sb);            break;         }         /* Rebuild the header */         *((u32 *) sb->data) = le32_to_cpu(rsqe->word_1) << 4 |                               (ns_rsqe_clp(rsqe) ? 0x00000001 : 0x00000000);         if (i == 1 && ns_rsqe_eopdu(rsqe))            *((u32 *) sb->data) |= 0x00000002;         skb_put(sb, NS_AAL0_HEADER);         memcpy(sb->tail, cell, ATM_CELL_PAYLOAD);         skb_put(sb, ATM_CELL_PAYLOAD);         ATM_SKB(sb)->vcc = vcc;         do_gettimeofday(&sb->stamp);         vcc->push(vcc, sb);         atomic_inc(&vcc->stats->rx);         cell += ATM_CELL_PAYLOAD;      }      recycle_rx_buf(card, skb);      return;   }   /* To reach this point, the AAL layer can only be AAL5 */   if ((iovb = vc->rx_iov) == NULL)   {      iovb = skb_dequeue(&(card->iovpool.queue));      if (iovb == NULL)		/* No buffers in the queue */      {         iovb = alloc_skb(NS_IOVBUFSIZE, GFP_ATOMIC);	 if (iovb == NULL)	 {	    printk("nicstar%d: Out of iovec buffers.\n", card->index);            atomic_inc(&vcc->stats->rx_drop);            recycle_rx_buf(card, skb);            return;	 }      }      else         if (--card->iovpool.count < card->iovnr.min)	 {	    struct sk_buff *new_iovb;	    if ((new_iovb = alloc_skb(NS_IOVBUFSIZE, GFP_ATOMIC)) != NULL)	    {               skb_queue_tail(&card->iovpool.queue, new_iovb);               card->iovpool.count++;	    }	 }      vc->rx_iov = iovb;      NS_SKB(iovb)->iovcnt = 0;      iovb->len = 0;      iovb->tail = iovb->data = iovb->head;      NS_SKB(iovb)->vcc = vcc;      /* IMPORTANT: a pointer to the sk_buff containing the small or large                    buffer is stored as iovec base, NOT a pointer to the 	            small or large buffer itself. */   }   else if (NS_SKB(iovb)->iovcnt >= NS_MAX_IOVECS)   {      printk("nicstar%d: received too big AAL5 SDU.\n", card->index);      atomic_inc(&vcc->stats->rx_err);      recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data, NS_MAX_IOVECS);      NS_SKB(iovb)->iovcnt = 0;      iovb->len = 0;      iovb->tail = iovb->data = iovb->head;      NS_SKB(iovb)->vcc = vcc;   }   iov = &((struct iovec *) iovb->data)[NS_SKB(iovb)->iovcnt++];   iov->iov_base = (void *) skb;   iov->iov_len = ns_rsqe_cellcount(rsqe) * 48;   iovb->len += iov->iov_len;   if (NS_SKB(iovb)->iovcnt == 1)   {      if (skb->list != &card->sbpool.queue)      {         printk("nicstar%d: Expected a small buffer, and this is not one.\n",	        card->index);         which_list(card, skb);         atomic_inc(&vcc->stats->rx_err);         recycle_rx_buf(card, skb);         vc->rx_iov = NULL;         recycle_iov_buf(card, iovb);         return;      }   }   else /* NS_SKB(iovb)->iovcnt >= 2 */   {      if (skb->list != &card->lbpool.queue)      {         printk("nicstar%d: Expected a large buffer, and this is not one.\n",	        card->index);         which_list(card, skb);         atomic_inc(&vcc->stats->rx_err);         recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data,	                       NS_SKB(iovb)->iovcnt);         vc->rx_iov = NULL;         recycle_iov_buf(card, iovb);	 return;      }   }   if (ns_rsqe_eopdu(rsqe))   {      /* This works correctly regardless of the endianness of the host */      unsigned char *L1L2 = (unsigned char *)((u32)skb->data +                                              iov->iov_len - 6);      aal5_len = L1L2[0] << 8 | L1L2[1];      len = (aal5_len == 0x0000) ? 0x10000 : aal5_len;      if (ns_rsqe_crcerr(rsqe) ||          len + 8 > iovb->len || len + (47 + 8) < iovb->len)      {         printk("nicstar%d: AAL5 CRC error", card->index);         if (len + 8 > iovb->len || len + (47 + 8) < iovb->len)            printk(" - PDU size mismatch.\n");         else            printk(".\n");         atomic_inc(&vcc->stats->rx_err);         recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data,	   NS_SKB(iovb)->iovcnt);	 vc->rx_iov = NULL;         recycle_iov_buf(card, iovb);	 return;      }      /* By this point we (hopefully) have a complete SDU without errors. */      if (NS_SKB(iovb)->iovcnt == 1)	/* Just a small buffer */      {         /* skb points to a small buffer */         if (!atm_charge(vcc, skb->truesize))         {            push_rxbufs(card, BUF_SM, (u32) skb, (u32) virt_to_bus(skb->data),                        0, 0);            atomic_inc(&vcc->stats->rx_drop);         }         else	 {            skb_put(skb, len);            dequeue_sm_buf(card, skb);#ifdef NS_USE_DESTRUCTORS            skb->destructor = ns_sb_destructor;#endif /* NS_USE_DESTRUCTORS */            ATM_SKB(skb)->vcc = vcc;            do_gettimeofday(&skb->stamp);            vcc->push(vcc, skb);            atomic_inc(&vcc->stats->rx);         }      }      else if (NS_SKB(iovb)->iovcnt == 2)	/* One small plus one large buffer */      {         struct sk_buff *sb;         sb = (struct sk_buff *) (iov - 1)->iov_base;         /* skb points to a large buffer */         if (len <= NS_SMBUFSIZE)	 {            if (!atm_charge(vcc, sb->truesize))            {               push_rxbufs(card, BUF_SM, (u32) sb, (u32) virt_to_bus(sb->data),                           0, 0);               atomic_inc(&vcc->stats->rx_drop);            }            else	    {               skb_put(sb, len);               dequeue_sm_buf(card, sb);#ifdef NS_USE_DESTRUCTORS               sb->destructor = ns_sb_destructor;#endif /* NS_USE_DESTRUCTORS */               ATM_SKB(sb)->vcc = vcc;               do_gettimeofday(&sb->stamp);               vcc->push(vcc, sb);               atomic_inc(&vcc->stats->rx);            }            push_rxbufs(card, BUF_LG, (u32) skb,	                   (u32) virt_to_bus(skb->data), 0, 0);	 }	 else			/* len > NS_SMBUFSIZE, the usual case */	 {            if (!atm_charge(vcc, skb->truesize))            {               push_rxbufs(card, BUF_LG, (u32) skb,                           (u32) virt_to_bus(skb->data), 0, 0);               atomic_inc(&vcc->stats->rx_drop);            }            else            {               dequeue_lg_buf(card, skb);#ifdef NS_USE_DESTRUCTORS               skb->destructor = ns_lb_destructor;#endif /* NS_USE_DESTRUCTORS */               skb_push(skb, NS_SMBUFSIZE);               memcpy(skb->data, sb->data, NS_SMBUFSIZE);               skb_put(skb, len - NS_SMBUFSIZE);               ATM_SKB(skb)->vcc = vcc;               do_gettimeofday(&skb->stamp);               vcc->push(vcc, skb);               atomic_inc(&vcc->stats->rx);            }            push_rxbufs(card, BUF_SM, (u32) sb, (u32) virt_to_bus(sb->data),                        0, 0);         }	       }      else				/* Must push a huge buffer */      {         struct sk_buff *hb, *sb, *lb;	 int remaining, tocopy;         int j;         hb = skb_dequeue(&(card->hbpool.queue));         if (hb == NULL)		/* No buffers in the queue */         {            hb = dev_alloc_skb(NS_HBUFSIZE);            if (hb == NULL)            {               printk("nicstar%d: Out of huge buffers.\n", card->index);               atomic_inc(&vcc->stats->rx_drop);               recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data,	                             NS_SKB(iovb)->iovcnt);               vc->rx_iov = NULL;               recycle_iov_buf(card, iovb);               return;            }            else if (card->hbpool.count < card->hbnr.min)	    {               struct sk_buff *new_hb;               if ((new_hb = dev_alloc_skb(NS_HBUFSIZE)) != NULL)               {                  skb_queue_tail(&card->hbpool.queue, new_hb);                  card->hbpool.count++;               }            }	 }	 else         if (--card->hbpool.count < card->hbnr.min)         {            struct sk_buff *new_hb;            if ((new_hb = dev_alloc_skb(NS_HBUFSIZE)) != NULL)            {               skb_queue_tail(&card->hbpool.queue, new_hb);               card->hbpool.count++;            }            if (card->hbpool.count < card->hbnr.min)	    {               if ((new_hb = dev_alloc_skb(NS_HBUFSIZE)) != NULL)               {                  skb_queue_tail(&card->hbpool.queue, new_hb);                  card->hbpool.count++;               }            }         }         iov = (struct iovec *) iovb->data;         if (!atm_charge(vcc, hb->truesize))	 {            recycle_iovec_rx_bufs(card, iov, NS_SKB(iovb)->iovcnt);            if (card->hbpool.count < card->hbnr.max)            {               skb_queue_tail(&card->hbpool.queue, hb);               card->hbpool.count++;            }	    else	       dev_kfree_skb_any(hb);	    atomic_inc(&vcc->stats->rx_drop);         }         else	 {            /* Copy the small buffer to the huge buffer */            sb = (struct sk_buff *) iov->iov_base;            memcpy(hb->data, sb->data, iov->iov_len);            skb_put(hb, iov->iov_len);            remaining = len - iov->iov_len;            iov++;            /* Free the small buffer */            push_rxbufs(card, BUF_SM, (u32) sb, (u32) virt_to_bus(sb->data),                        0, 0);            /* Copy all large buffers to the huge buffer and free them */            for (j = 1; j < NS_SKB(iovb)->iovcnt; j++)            {               lb = (struct sk_buff *) iov->iov_base;               tocopy = min_t(int, remaining, iov->iov_len);               memcpy(hb->tail, lb->data, tocopy);               skb_put(hb, tocopy);               iov++;               remaining -= tocopy;               push_rxbufs(card, BUF_LG, (u32) lb,                           (u32) virt_to_bus(lb->data), 0, 0);            }#ifdef EXTRA_DEBUG            if (remaining != 0 || hb->len != len)               printk("nicstar%d: Huge buffer len mismatch.\n", card->index);#endif /* EXTRA_DEBUG */            ATM_SKB(hb)->vcc = vcc;#ifdef NS_USE_DESTRUCTORS            hb->destructor = ns_hb_destructor;#endif /* NS_USE_DESTRUCTORS */            do_gettimeofday(&hb->stamp);            vcc->push(vcc, hb);            atomic_inc(&vcc->stats->rx);         }      }      vc->rx_iov = NULL;      recycle_iov_buf(card, iovb);   }}
10457	/local/tlutelli/issta_data/temp/c/2005_temp/2005/10457/8728b834b226ffcf2c94a58530090e292af2a7bf/nicstar.c/buggy/drivers/atm/nicstar.c