static int _ns_send()

in nicstar.c [1627:1721]


static int _ns_send(struct atm_vcc *vcc, struct sk_buff *skb, bool may_sleep)
{
	ns_dev *card;
	vc_map *vc;
	scq_info *scq;
	unsigned long buflen;
	ns_scqe scqe;
	u32 flags;		/* TBD flags, not CPU flags */

	card = vcc->dev->dev_data;
	TXPRINTK("nicstar%d: ns_send() called.\n", card->index);
	if ((vc = (vc_map *) vcc->dev_data) == NULL) {
		printk("nicstar%d: vcc->dev_data == NULL on ns_send().\n",
		       card->index);
		atomic_inc(&vcc->stats->tx_err);
		dev_kfree_skb_any(skb);
		return -EINVAL;
	}

	if (!vc->tx) {
		printk("nicstar%d: Trying to transmit on a non-tx VC.\n",
		       card->index);
		atomic_inc(&vcc->stats->tx_err);
		dev_kfree_skb_any(skb);
		return -EINVAL;
	}

	if (vcc->qos.aal != ATM_AAL5 && vcc->qos.aal != ATM_AAL0) {
		printk("nicstar%d: Only AAL0 and AAL5 are supported.\n",
		       card->index);
		atomic_inc(&vcc->stats->tx_err);
		dev_kfree_skb_any(skb);
		return -EINVAL;
	}

	if (skb_shinfo(skb)->nr_frags != 0) {
		printk("nicstar%d: No scatter-gather yet.\n", card->index);
		atomic_inc(&vcc->stats->tx_err);
		dev_kfree_skb_any(skb);
		return -EINVAL;
	}

	ATM_SKB(skb)->vcc = vcc;

	NS_PRV_DMA(skb) = dma_map_single(&card->pcidev->dev, skb->data,
					 skb->len, DMA_TO_DEVICE);

	if (vcc->qos.aal == ATM_AAL5) {
		buflen = (skb->len + 47 + 8) / 48 * 48;	/* Multiple of 48 */
		flags = NS_TBD_AAL5;
		scqe.word_2 = cpu_to_le32(NS_PRV_DMA(skb));
		scqe.word_3 = cpu_to_le32(skb->len);
		scqe.word_4 =
		    ns_tbd_mkword_4(0, (u32) vcc->vpi, (u32) vcc->vci, 0,
				    ATM_SKB(skb)->
				    atm_options & ATM_ATMOPT_CLP ? 1 : 0);
		flags |= NS_TBD_EOPDU;
	} else {		/* (vcc->qos.aal == ATM_AAL0) */

		buflen = ATM_CELL_PAYLOAD;	/* i.e., 48 bytes */
		flags = NS_TBD_AAL0;
		scqe.word_2 = cpu_to_le32(NS_PRV_DMA(skb) + NS_AAL0_HEADER);
		scqe.word_3 = cpu_to_le32(0x00000000);
		if (*skb->data & 0x02)	/* Payload type 1 - end of pdu */
			flags |= NS_TBD_EOPDU;
		scqe.word_4 =
		    cpu_to_le32(*((u32 *) skb->data) & ~NS_TBD_VC_MASK);
		/* Force the VPI/VCI to be the same as in VCC struct */
		scqe.word_4 |=
		    cpu_to_le32((((u32) vcc->
				  vpi) << NS_TBD_VPI_SHIFT | ((u32) vcc->
							      vci) <<
				 NS_TBD_VCI_SHIFT) & NS_TBD_VC_MASK);
	}

	if (vcc->qos.txtp.traffic_class == ATM_CBR) {
		scqe.word_1 = ns_tbd_mkword_1_novbr(flags, (u32) buflen);
		scq = ((vc_map *) vcc->dev_data)->scq;
	} else {
		scqe.word_1 =
		    ns_tbd_mkword_1(flags, (u32) 1, (u32) 1, (u32) buflen);
		scq = card->scq0;
	}

	if (push_scqe(card, vc, scq, &scqe, skb, may_sleep) != 0) {
		atomic_inc(&vcc->stats->tx_err);
		dma_unmap_single(&card->pcidev->dev, NS_PRV_DMA(skb), skb->len,
				 DMA_TO_DEVICE);
		dev_kfree_skb_any(skb);
		return -EIO;
	}
	atomic_inc(&vcc->stats->tx);

	return 0;
}