示例#1
0
static int ibmveth_send(struct ibmveth_adapter *adapter,
			union ibmveth_buf_desc *descs)
{
	unsigned long correlator;
	unsigned int retry_count;
	unsigned long ret;

	/*
	 * The retry count sets a maximum for the number of broadcast and
	 * multicast destinations within the system.
	 */
	retry_count = 1024;
	correlator = 0;
	do {
		ret = h_send_logical_lan(adapter->vdev->unit_address,
					     descs[0].desc, descs[1].desc,
					     descs[2].desc, descs[3].desc,
					     descs[4].desc, descs[5].desc,
					     correlator, &correlator);
	} while ((ret == H_BUSY) && (retry_count--));

	if (ret != H_SUCCESS && ret != H_DROPPED) {
		netdev_err(adapter->netdev, "tx: h_send_logical_lan failed "
			   "with rc=%ld\n", ret);
		return 1;
	}

	return 0;
}
示例#2
0
static netdev_tx_t ibmveth_start_xmit(struct sk_buff *skb,
				      struct net_device *netdev)
{
	struct ibmveth_adapter *adapter = netdev_priv(netdev);
	union ibmveth_buf_desc desc;
	unsigned long lpar_rc;
	unsigned long correlator;
	unsigned long flags;
	unsigned int retry_count;
	unsigned int tx_dropped = 0;
	unsigned int tx_bytes = 0;
	unsigned int tx_packets = 0;
	unsigned int tx_send_failed = 0;
	unsigned int tx_map_failed = 0;
	int used_bounce = 0;
	unsigned long data_dma_addr;

	desc.fields.flags_len = IBMVETH_BUF_VALID | skb->len;

	if (skb->ip_summed == CHECKSUM_PARTIAL &&
	    ip_hdr(skb)->protocol != IPPROTO_TCP && skb_checksum_help(skb)) {
		ibmveth_error_printk("tx: failed to checksum packet\n");
		tx_dropped++;
		goto out;
	}

	if (skb->ip_summed == CHECKSUM_PARTIAL) {
		unsigned char *buf = skb_transport_header(skb) + skb->csum_offset;

		desc.fields.flags_len |= (IBMVETH_BUF_NO_CSUM | IBMVETH_BUF_CSUM_GOOD);

		
		buf[0] = 0;
		buf[1] = 0;
	}

	data_dma_addr = dma_map_single(&adapter->vdev->dev, skb->data,
				       skb->len, DMA_TO_DEVICE);
	if (dma_mapping_error(&adapter->vdev->dev, data_dma_addr)) {
		if (!firmware_has_feature(FW_FEATURE_CMO))
			ibmveth_error_printk("tx: unable to map xmit buffer\n");
		skb_copy_from_linear_data(skb, adapter->bounce_buffer,
					  skb->len);
		desc.fields.address = adapter->bounce_buffer_dma;
		tx_map_failed++;
		used_bounce = 1;
		wmb();
	} else
		desc.fields.address = data_dma_addr;

	
	correlator = 0;
	retry_count = 1024;
	do {
		lpar_rc = h_send_logical_lan(adapter->vdev->unit_address,
					     desc.desc, 0, 0, 0, 0, 0,
					     correlator, &correlator);
	} while ((lpar_rc == H_BUSY) && (retry_count--));

	if(lpar_rc != H_SUCCESS && lpar_rc != H_DROPPED) {
		ibmveth_error_printk("tx: h_send_logical_lan failed with rc=%ld\n", lpar_rc);
		ibmveth_error_printk("tx: valid=%d, len=%d, address=0x%08x\n",
				     (desc.fields.flags_len & IBMVETH_BUF_VALID) ? 1 : 0,
				     skb->len, desc.fields.address);
		tx_send_failed++;
		tx_dropped++;
	} else {
		tx_packets++;
		tx_bytes += skb->len;
		netdev->trans_start = jiffies;
	}

	if (!used_bounce)
		dma_unmap_single(&adapter->vdev->dev, data_dma_addr,
				 skb->len, DMA_TO_DEVICE);

out:	spin_lock_irqsave(&adapter->stats_lock, flags);
	netdev->stats.tx_dropped += tx_dropped;
	netdev->stats.tx_bytes += tx_bytes;
	netdev->stats.tx_packets += tx_packets;
	adapter->tx_send_failed += tx_send_failed;
	adapter->tx_map_failed += tx_map_failed;
	spin_unlock_irqrestore(&adapter->stats_lock, flags);

	dev_kfree_skb(skb);
	return NETDEV_TX_OK;
}
示例#3
0
文件: ibmveth.c 项目: maraz/linux-2.6
static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *netdev)
{
	struct ibmveth_adapter *adapter = netdev->priv;
	union ibmveth_buf_desc desc;
	unsigned long lpar_rc;
	unsigned long correlator;
	unsigned long flags;
	unsigned int retry_count;
	unsigned int tx_dropped = 0;
	unsigned int tx_bytes = 0;
	unsigned int tx_packets = 0;
	unsigned int tx_send_failed = 0;
	unsigned int tx_map_failed = 0;

	desc.fields.flags_len = IBMVETH_BUF_VALID | skb->len;
	desc.fields.address = dma_map_single(&adapter->vdev->dev, skb->data,
					     skb->len, DMA_TO_DEVICE);

	if (skb->ip_summed == CHECKSUM_PARTIAL &&
	    ip_hdr(skb)->protocol != IPPROTO_TCP && skb_checksum_help(skb)) {
		ibmveth_error_printk("tx: failed to checksum packet\n");
		tx_dropped++;
		goto out;
	}

	if (skb->ip_summed == CHECKSUM_PARTIAL) {
		unsigned char *buf = skb_transport_header(skb) + skb->csum_offset;

		desc.fields.flags_len |= (IBMVETH_BUF_NO_CSUM | IBMVETH_BUF_CSUM_GOOD);

		/* Need to zero out the checksum */
		buf[0] = 0;
		buf[1] = 0;
	}

	if (dma_mapping_error(desc.fields.address)) {
		ibmveth_error_printk("tx: unable to map xmit buffer\n");
		tx_map_failed++;
		tx_dropped++;
		goto out;
	}

	/* send the frame. Arbitrarily set retrycount to 1024 */
	correlator = 0;
	retry_count = 1024;
	do {
		lpar_rc = h_send_logical_lan(adapter->vdev->unit_address,
					     desc.desc, 0, 0, 0, 0, 0,
					     correlator, &correlator);
	} while ((lpar_rc == H_BUSY) && (retry_count--));

	if(lpar_rc != H_SUCCESS && lpar_rc != H_DROPPED) {
		ibmveth_error_printk("tx: h_send_logical_lan failed with rc=%ld\n", lpar_rc);
		ibmveth_error_printk("tx: valid=%d, len=%d, address=0x%08x\n",
				     (desc.fields.flags_len & IBMVETH_BUF_VALID) ? 1 : 0,
				     skb->len, desc.fields.address);
		tx_send_failed++;
		tx_dropped++;
	} else {
		tx_packets++;
		tx_bytes += skb->len;
		netdev->trans_start = jiffies;
	}

	dma_unmap_single(&adapter->vdev->dev, desc.fields.address,
			 skb->len, DMA_TO_DEVICE);

out:	spin_lock_irqsave(&adapter->stats_lock, flags);
	netdev->stats.tx_dropped += tx_dropped;
	netdev->stats.tx_bytes += tx_bytes;
	netdev->stats.tx_packets += tx_packets;
	adapter->tx_send_failed += tx_send_failed;
	adapter->tx_map_failed += tx_map_failed;
	spin_unlock_irqrestore(&adapter->stats_lock, flags);

	dev_kfree_skb(skb);
	return 0;
}