Exemplo n.º 1
0
static int ibmveth_set_csum_offload(struct net_device *dev, u32 data,
				    void (*done) (struct net_device *, u32))
{
	struct ibmveth_adapter *adapter = netdev_priv(dev);
	unsigned long set_attr, clr_attr, ret_attr;
	long ret;
	int rc1 = 0, rc2 = 0;
	int restart = 0;

	if (netif_running(dev)) {
		restart = 1;
		adapter->pool_config = 1;
		ibmveth_close(dev);
		adapter->pool_config = 0;
	}

	set_attr = 0;
	clr_attr = 0;

	if (data)
		set_attr = IBMVETH_ILLAN_IPV4_TCP_CSUM;
	else
		clr_attr = IBMVETH_ILLAN_IPV4_TCP_CSUM;

	ret = h_illan_attributes(adapter->vdev->unit_address, 0, 0, &ret_attr);

	if (ret == H_SUCCESS && !(ret_attr & IBMVETH_ILLAN_ACTIVE_TRUNK) &&
	    !(ret_attr & IBMVETH_ILLAN_TRUNK_PRI_MASK) &&
	    (ret_attr & IBMVETH_ILLAN_PADDED_PKT_CSUM)) {
		ret = h_illan_attributes(adapter->vdev->unit_address, clr_attr,
					 set_attr, &ret_attr);

		if (ret != H_SUCCESS) {
			rc1 = -EIO;
			ibmveth_error_printk("unable to change checksum offload settings."
					     " %d rc=%ld\n", data, ret);

			ret = h_illan_attributes(adapter->vdev->unit_address,
						 set_attr, clr_attr, &ret_attr);
		} else
			done(dev, data);
	} else {
		rc1 = -EIO;
		ibmveth_error_printk("unable to change checksum offload settings."
				     " %d rc=%ld ret_attr=%lx\n", data, ret, ret_attr);
	}

	if (restart)
		rc2 = ibmveth_open(dev);

	return rc1 ? rc1 : rc2;
}
Exemplo n.º 2
0
static int ibmveth_close(struct net_device *netdev)
{
	struct ibmveth_adapter *adapter = netdev_priv(netdev);
	long lpar_rc;

	ibmveth_debug_printk("close starting\n");

	napi_disable(&adapter->napi);

	if (!adapter->pool_config)
		netif_stop_queue(netdev);

	free_irq(netdev->irq, netdev);

	do {
		lpar_rc = h_free_logical_lan(adapter->vdev->unit_address);
	} while (H_IS_LONG_BUSY(lpar_rc) || (lpar_rc == H_BUSY));

	if(lpar_rc != H_SUCCESS)
	{
		ibmveth_error_printk("h_free_logical_lan failed with %lx, continuing with close\n",
				     lpar_rc);
	}

	adapter->rx_no_buffer = *(u64*)(((char*)adapter->buffer_list_addr) + 4096 - 8);

	ibmveth_cleanup(adapter);

	ibmveth_debug_printk("close complete\n");

	return 0;
}
Exemplo n.º 3
0
static void ibmveth_set_multicast_list(struct net_device *netdev)
{
	struct ibmveth_adapter *adapter = netdev_priv(netdev);
	unsigned long lpar_rc;

	if((netdev->flags & IFF_PROMISC) || (netdev->mc_count > adapter->mcastFilterSize)) {
		lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address,
					   IbmVethMcastEnableRecv |
					   IbmVethMcastDisableFiltering,
					   0);
		if(lpar_rc != H_SUCCESS) {
			ibmveth_error_printk("h_multicast_ctrl rc=%ld when entering promisc mode\n", lpar_rc);
		}
	} else {
		struct dev_mc_list *mclist = netdev->mc_list;
		int i;
		
		lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address,
					   IbmVethMcastEnableRecv |
					   IbmVethMcastDisableFiltering |
					   IbmVethMcastClearFilterTable,
					   0);
		if(lpar_rc != H_SUCCESS) {
			ibmveth_error_printk("h_multicast_ctrl rc=%ld when attempting to clear filter table\n", lpar_rc);
		}
		
		for(i = 0; i < netdev->mc_count; ++i, mclist = mclist->next) {
			
			unsigned long mcast_addr = 0;
			memcpy(((char *)&mcast_addr)+2, mclist->dmi_addr, 6);
			lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address,
						   IbmVethMcastAddFilter,
						   mcast_addr);
			if(lpar_rc != H_SUCCESS) {
				ibmveth_error_printk("h_multicast_ctrl rc=%ld when adding an entry to the filter table\n", lpar_rc);
			}
		}

		
		lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address,
					   IbmVethMcastEnableFiltering,
					   0);
		if(lpar_rc != H_SUCCESS) {
			ibmveth_error_printk("h_multicast_ctrl rc=%ld when enabling filtering\n", lpar_rc);
		}
	}
}
Exemplo n.º 4
0
static void ibmveth_set_multicast_list(struct net_device *netdev)
{
	struct ibmveth_adapter *adapter = netdev_priv(netdev);
	unsigned long lpar_rc;

	if ((netdev->flags & IFF_PROMISC) ||
	    (netdev_mc_count(netdev) > adapter->mcastFilterSize)) {
		lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address,
					   IbmVethMcastEnableRecv |
					   IbmVethMcastDisableFiltering,
					   0);
		if(lpar_rc != H_SUCCESS) {
			ibmveth_error_printk("h_multicast_ctrl rc=%ld when entering promisc mode\n", lpar_rc);
		}
	} else {
		struct netdev_hw_addr *ha;
		/* clear the filter table & disable filtering */
		lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address,
					   IbmVethMcastEnableRecv |
					   IbmVethMcastDisableFiltering |
					   IbmVethMcastClearFilterTable,
					   0);
		if(lpar_rc != H_SUCCESS) {
			ibmveth_error_printk("h_multicast_ctrl rc=%ld when attempting to clear filter table\n", lpar_rc);
		}
		/* add the addresses to the filter table */
		netdev_for_each_mc_addr(ha, netdev) {
			// add the multicast address to the filter table
			unsigned long mcast_addr = 0;
			memcpy(((char *)&mcast_addr)+2, ha->addr, 6);
			lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address,
						   IbmVethMcastAddFilter,
						   mcast_addr);
			if(lpar_rc != H_SUCCESS) {
				ibmveth_error_printk("h_multicast_ctrl rc=%ld when adding an entry to the filter table\n", lpar_rc);
			}
		}

		/* re-enable filtering */
		lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address,
					   IbmVethMcastEnableFiltering,
					   0);
		if(lpar_rc != H_SUCCESS) {
			ibmveth_error_printk("h_multicast_ctrl rc=%ld when enabling filtering\n", lpar_rc);
		}
	}
Exemplo n.º 5
0
static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter)
{
	struct proc_dir_entry *entry;
	if (ibmveth_proc_dir) {
		char u_addr[10];
		sprintf(u_addr, "%x", adapter->vdev->unit_address);
		entry = proc_create_data(u_addr, S_IFREG, ibmveth_proc_dir,
					 &ibmveth_proc_fops, adapter);
		if (!entry)
			ibmveth_error_printk("Cannot create adapter proc entry");
	}
	return;
}
Exemplo n.º 6
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;
}
Exemplo n.º 7
0
static int ibmveth_open(struct net_device *netdev)
{
	struct ibmveth_adapter *adapter = netdev_priv(netdev);
	u64 mac_address = 0;
	int rxq_entries = 1;
	unsigned long lpar_rc;
	int rc;
	union ibmveth_buf_desc rxq_desc;
	int i;
	struct device *dev;

	ibmveth_debug_printk("open starting\n");

	napi_enable(&adapter->napi);

	for(i = 0; i<IbmVethNumBufferPools; i++)
		rxq_entries += adapter->rx_buff_pool[i].size;

	adapter->buffer_list_addr = (void*) get_zeroed_page(GFP_KERNEL);
	adapter->filter_list_addr = (void*) get_zeroed_page(GFP_KERNEL);

	if(!adapter->buffer_list_addr || !adapter->filter_list_addr) {
		ibmveth_error_printk("unable to allocate filter or buffer list pages\n");
		ibmveth_cleanup(adapter);
		napi_disable(&adapter->napi);
		return -ENOMEM;
	}

	adapter->rx_queue.queue_len = sizeof(struct ibmveth_rx_q_entry) * rxq_entries;
	adapter->rx_queue.queue_addr = kmalloc(adapter->rx_queue.queue_len, GFP_KERNEL);

	if(!adapter->rx_queue.queue_addr) {
		ibmveth_error_printk("unable to allocate rx queue pages\n");
		ibmveth_cleanup(adapter);
		napi_disable(&adapter->napi);
		return -ENOMEM;
	}

	dev = &adapter->vdev->dev;

	adapter->buffer_list_dma = dma_map_single(dev,
			adapter->buffer_list_addr, 4096, DMA_BIDIRECTIONAL);
	adapter->filter_list_dma = dma_map_single(dev,
			adapter->filter_list_addr, 4096, DMA_BIDIRECTIONAL);
	adapter->rx_queue.queue_dma = dma_map_single(dev,
			adapter->rx_queue.queue_addr,
			adapter->rx_queue.queue_len, DMA_BIDIRECTIONAL);

	if ((dma_mapping_error(dev, adapter->buffer_list_dma)) ||
	    (dma_mapping_error(dev, adapter->filter_list_dma)) ||
	    (dma_mapping_error(dev, adapter->rx_queue.queue_dma))) {
		ibmveth_error_printk("unable to map filter or buffer list pages\n");
		ibmveth_cleanup(adapter);
		napi_disable(&adapter->napi);
		return -ENOMEM;
	}

	adapter->rx_queue.index = 0;
	adapter->rx_queue.num_slots = rxq_entries;
	adapter->rx_queue.toggle = 1;

	memcpy(&mac_address, netdev->dev_addr, netdev->addr_len);
	mac_address = mac_address >> 16;

	rxq_desc.fields.flags_len = IBMVETH_BUF_VALID | adapter->rx_queue.queue_len;
	rxq_desc.fields.address = adapter->rx_queue.queue_dma;

	ibmveth_debug_printk("buffer list @ 0x%p\n", adapter->buffer_list_addr);
	ibmveth_debug_printk("filter list @ 0x%p\n", adapter->filter_list_addr);
	ibmveth_debug_printk("receive q   @ 0x%p\n", adapter->rx_queue.queue_addr);

	h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_DISABLE);

	lpar_rc = ibmveth_register_logical_lan(adapter, rxq_desc, mac_address);

	if(lpar_rc != H_SUCCESS) {
		ibmveth_error_printk("h_register_logical_lan failed with %ld\n", lpar_rc);
		ibmveth_error_printk("buffer TCE:0x%llx filter TCE:0x%llx rxq desc:0x%llx MAC:0x%llx\n",
				     adapter->buffer_list_dma,
				     adapter->filter_list_dma,
				     rxq_desc.desc,
				     mac_address);
		ibmveth_cleanup(adapter);
		napi_disable(&adapter->napi);
		return -ENONET;
	}

	for(i = 0; i<IbmVethNumBufferPools; i++) {
		if(!adapter->rx_buff_pool[i].active)
			continue;
		if (ibmveth_alloc_buffer_pool(&adapter->rx_buff_pool[i])) {
			ibmveth_error_printk("unable to alloc pool\n");
			adapter->rx_buff_pool[i].active = 0;
			ibmveth_cleanup(adapter);
			napi_disable(&adapter->napi);
			return -ENOMEM ;
		}
	}

	ibmveth_debug_printk("registering irq 0x%x\n", netdev->irq);
	if((rc = request_irq(netdev->irq, &ibmveth_interrupt, 0, netdev->name, netdev)) != 0) {
		ibmveth_error_printk("unable to request irq 0x%x, rc %d\n", netdev->irq, rc);
		do {
			rc = h_free_logical_lan(adapter->vdev->unit_address);
		} while (H_IS_LONG_BUSY(rc) || (rc == H_BUSY));

		ibmveth_cleanup(adapter);
		napi_disable(&adapter->napi);
		return rc;
	}

	adapter->bounce_buffer =
	    kmalloc(netdev->mtu + IBMVETH_BUFF_OH, GFP_KERNEL);
	if (!adapter->bounce_buffer) {
		ibmveth_error_printk("unable to allocate bounce buffer\n");
		ibmveth_cleanup(adapter);
		napi_disable(&adapter->napi);
		return -ENOMEM;
	}
	adapter->bounce_buffer_dma =
	    dma_map_single(&adapter->vdev->dev, adapter->bounce_buffer,
			   netdev->mtu + IBMVETH_BUFF_OH, DMA_BIDIRECTIONAL);
	if (dma_mapping_error(dev, adapter->bounce_buffer_dma)) {
		ibmveth_error_printk("unable to map bounce buffer\n");
		ibmveth_cleanup(adapter);
		napi_disable(&adapter->napi);
		return -ENOMEM;
	}

	ibmveth_debug_printk("initial replenish cycle\n");
	ibmveth_interrupt(netdev->irq, netdev);

	netif_start_queue(netdev);

	ibmveth_debug_printk("open complete\n");

	return 0;
}
Exemplo n.º 8
0
static ssize_t veth_pool_store(struct kobject * kobj, struct attribute * attr,
const char * buf, size_t count)
{
	struct ibmveth_buff_pool *pool = container_of(kobj,
						      struct ibmveth_buff_pool,
						      kobj);
	struct net_device *netdev = dev_get_drvdata(
	    container_of(kobj->parent, struct device, kobj));
	struct ibmveth_adapter *adapter = netdev_priv(netdev);
	long value = simple_strtol(buf, NULL, 10);
	long rc;

	if (attr == &veth_active_attr) {
		if (value && !pool->active) {
			if (netif_running(netdev)) {
				if(ibmveth_alloc_buffer_pool(pool)) {
					ibmveth_error_printk("unable to alloc pool\n");
					return -ENOMEM;
				}
				pool->active = 1;
				adapter->pool_config = 1;
				ibmveth_close(netdev);
				adapter->pool_config = 0;
				if ((rc = ibmveth_open(netdev)))
					return rc;
			} else
				pool->active = 1;
		} else if (!value && pool->active) {
			int mtu = netdev->mtu + IBMVETH_BUFF_OH;
			int i;
			
			for (i = 0; i < IbmVethNumBufferPools; i++) {
				if (pool == &adapter->rx_buff_pool[i])
					continue;
				if (!adapter->rx_buff_pool[i].active)
					continue;
				if (mtu <= adapter->rx_buff_pool[i].buff_size)
					break;
			}

			if (i == IbmVethNumBufferPools) {
				ibmveth_error_printk("no active pool >= MTU\n");
				return -EPERM;
			}

			if (netif_running(netdev)) {
				adapter->pool_config = 1;
				ibmveth_close(netdev);
				pool->active = 0;
				adapter->pool_config = 0;
				if ((rc = ibmveth_open(netdev)))
					return rc;
			}
			pool->active = 0;
		}
	} else if (attr == &veth_num_attr) {
		if (value <= 0 || value > IBMVETH_MAX_POOL_COUNT)
			return -EINVAL;
		else {
			if (netif_running(netdev)) {
				adapter->pool_config = 1;
				ibmveth_close(netdev);
				adapter->pool_config = 0;
				pool->size = value;
				if ((rc = ibmveth_open(netdev)))
					return rc;
			} else
				pool->size = value;
		}
	} else if (attr == &veth_size_attr) {
		if (value <= IBMVETH_BUFF_OH || value > IBMVETH_MAX_BUF_SIZE)
			return -EINVAL;
		else {
			if (netif_running(netdev)) {
				adapter->pool_config = 1;
				ibmveth_close(netdev);
				adapter->pool_config = 0;
				pool->buff_size = value;
				if ((rc = ibmveth_open(netdev)))
					return rc;
			} else
				pool->buff_size = value;
		}
	}

	
	ibmveth_interrupt(netdev->irq, netdev);
	return count;
}
Exemplo n.º 9
0
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;
}