static int ibmveth_set_features(struct net_device *dev, netdev_features_t features) { struct ibmveth_adapter *adapter = netdev_priv(dev); int rx_csum = !!(features & NETIF_F_RXCSUM); int large_send = !!(features & (NETIF_F_TSO | NETIF_F_TSO6)); int rc1 = 0, rc2 = 0; if (rx_csum != adapter->rx_csum) { rc1 = ibmveth_set_csum_offload(dev, rx_csum); if (rc1 && !adapter->rx_csum) dev->features = features & ~(NETIF_F_CSUM_MASK | NETIF_F_RXCSUM); } if (large_send != adapter->large_send) { rc2 = ibmveth_set_tso(dev, large_send); if (rc2 && !adapter->large_send) dev->features = features & ~(NETIF_F_TSO | NETIF_F_TSO6); } return rc1 ? rc1 : rc2; }
static int ibmveth_set_rx_csum(struct net_device *dev, u32 data) { struct ibmveth_adapter *adapter = netdev_priv(dev); if ((data && adapter->rx_csum) || (!data && !adapter->rx_csum)) return 0; return ibmveth_set_csum_offload(dev, data, ibmveth_set_rx_csum_flags); }
static int ibmveth_set_features(struct net_device *dev, u32 features) { struct ibmveth_adapter *adapter = netdev_priv(dev); int rx_csum = !!(features & NETIF_F_RXCSUM); int rc; if (rx_csum == adapter->rx_csum) return 0; rc = ibmveth_set_csum_offload(dev, rx_csum); if (rc && !adapter->rx_csum) dev->features = features & ~(NETIF_F_ALL_CSUM | NETIF_F_RXCSUM); return rc; }
static int ibmveth_set_tx_csum(struct net_device *dev, u32 data) { struct ibmveth_adapter *adapter = netdev_priv(dev); int rc = 0; if (data && (dev->features & NETIF_F_IP_CSUM)) return 0; if (!data && !(dev->features & NETIF_F_IP_CSUM)) return 0; if (data && !adapter->rx_csum) rc = ibmveth_set_csum_offload(dev, data, ibmveth_set_tx_csum_flags); else ibmveth_set_tx_csum_flags(dev, data); return rc; }
static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id) { int rc, i; struct net_device *netdev; struct ibmveth_adapter *adapter; unsigned char *mac_addr_p; unsigned int *mcastFilterSize_p; dev_dbg(&dev->dev, "entering ibmveth_probe for UA 0x%x\n", dev->unit_address); mac_addr_p = (unsigned char *)vio_get_attribute(dev, VETH_MAC_ADDR, NULL); if (!mac_addr_p) { dev_err(&dev->dev, "Can't find VETH_MAC_ADDR attribute\n"); return -EINVAL; } mcastFilterSize_p = (unsigned int *)vio_get_attribute(dev, VETH_MCAST_FILTER_SIZE, NULL); if (!mcastFilterSize_p) { dev_err(&dev->dev, "Can't find VETH_MCAST_FILTER_SIZE " "attribute\n"); return -EINVAL; } netdev = alloc_etherdev(sizeof(struct ibmveth_adapter)); if (!netdev) return -ENOMEM; adapter = netdev_priv(netdev); dev_set_drvdata(&dev->dev, netdev); adapter->vdev = dev; adapter->netdev = netdev; adapter->mcastFilterSize = *mcastFilterSize_p; adapter->pool_config = 0; netif_napi_add(netdev, &adapter->napi, ibmveth_poll, 16); /* * Some older boxes running PHYP non-natively have an OF that returns * a 8-byte local-mac-address field (and the first 2 bytes have to be * ignored) while newer boxes' OF return a 6-byte field. Note that * IEEE 1275 specifies that local-mac-address must be a 6-byte field. * The RPA doc specifies that the first byte must be 10b, so we'll * just look for it to solve this 8 vs. 6 byte field issue */ if ((*mac_addr_p & 0x3) != 0x02) mac_addr_p += 2; adapter->mac_addr = 0; memcpy(&adapter->mac_addr, mac_addr_p, 6); netdev->irq = dev->irq; netdev->netdev_ops = &ibmveth_netdev_ops; netdev->ethtool_ops = &netdev_ethtool_ops; SET_NETDEV_DEV(netdev, &dev->dev); netdev->features |= NETIF_F_SG; memcpy(netdev->dev_addr, &adapter->mac_addr, netdev->addr_len); for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) { struct kobject *kobj = &adapter->rx_buff_pool[i].kobj; int error; ibmveth_init_buffer_pool(&adapter->rx_buff_pool[i], i, pool_count[i], pool_size[i], pool_active[i]); error = kobject_init_and_add(kobj, &ktype_veth_pool, &dev->dev.kobj, "pool%d", i); if (!error) kobject_uevent(kobj, KOBJ_ADD); } netdev_dbg(netdev, "adapter @ 0x%p\n", adapter); adapter->buffer_list_dma = DMA_ERROR_CODE; adapter->filter_list_dma = DMA_ERROR_CODE; adapter->rx_queue.queue_dma = DMA_ERROR_CODE; netdev_dbg(netdev, "registering netdev...\n"); ibmveth_set_csum_offload(netdev, 1, ibmveth_set_tx_csum_flags); rc = register_netdev(netdev); if (rc) { netdev_dbg(netdev, "failed to register netdev rc=%d\n", rc); free_netdev(netdev); return rc; } netdev_dbg(netdev, "registered\n"); return 0; }