19aa32835SJeff Kirsher /* 29aa32835SJeff Kirsher * IBM Power Virtual Ethernet Device Driver 39aa32835SJeff Kirsher * 49aa32835SJeff Kirsher * This program is free software; you can redistribute it and/or modify 59aa32835SJeff Kirsher * it under the terms of the GNU General Public License as published by 69aa32835SJeff Kirsher * the Free Software Foundation; either version 2 of the License, or 79aa32835SJeff Kirsher * (at your option) any later version. 89aa32835SJeff Kirsher * 99aa32835SJeff Kirsher * This program is distributed in the hope that it will be useful, 109aa32835SJeff Kirsher * but WITHOUT ANY WARRANTY; without even the implied warranty of 119aa32835SJeff Kirsher * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 129aa32835SJeff Kirsher * GNU General Public License for more details. 139aa32835SJeff Kirsher * 149aa32835SJeff Kirsher * You should have received a copy of the GNU General Public License 150ab75ae8SJeff Kirsher * along with this program; if not, see <http://www.gnu.org/licenses/>. 169aa32835SJeff Kirsher * 179aa32835SJeff Kirsher * Copyright (C) IBM Corporation, 2003, 2010 189aa32835SJeff Kirsher * 199aa32835SJeff Kirsher * Authors: Dave Larson <larson1@us.ibm.com> 209aa32835SJeff Kirsher * Santiago Leon <santil@linux.vnet.ibm.com> 219aa32835SJeff Kirsher * Brian King <brking@linux.vnet.ibm.com> 229aa32835SJeff Kirsher * Robert Jennings <rcj@linux.vnet.ibm.com> 239aa32835SJeff Kirsher * Anton Blanchard <anton@au.ibm.com> 249aa32835SJeff Kirsher */ 259aa32835SJeff Kirsher 269aa32835SJeff Kirsher #include <linux/module.h> 279aa32835SJeff Kirsher #include <linux/moduleparam.h> 289aa32835SJeff Kirsher #include <linux/types.h> 299aa32835SJeff Kirsher #include <linux/errno.h> 309aa32835SJeff Kirsher #include <linux/dma-mapping.h> 319aa32835SJeff Kirsher #include <linux/kernel.h> 329aa32835SJeff Kirsher #include <linux/netdevice.h> 339aa32835SJeff Kirsher #include <linux/etherdevice.h> 349aa32835SJeff Kirsher #include <linux/skbuff.h> 359aa32835SJeff Kirsher #include <linux/init.h> 369aa32835SJeff Kirsher #include <linux/interrupt.h> 379aa32835SJeff Kirsher #include <linux/mm.h> 389aa32835SJeff Kirsher #include <linux/pm.h> 399aa32835SJeff Kirsher #include <linux/ethtool.h> 409aa32835SJeff Kirsher #include <linux/in.h> 419aa32835SJeff Kirsher #include <linux/ip.h> 429aa32835SJeff Kirsher #include <linux/ipv6.h> 439aa32835SJeff Kirsher #include <linux/slab.h> 449aa32835SJeff Kirsher #include <asm/hvcall.h> 459aa32835SJeff Kirsher #include <linux/atomic.h> 469aa32835SJeff Kirsher #include <asm/vio.h> 479aa32835SJeff Kirsher #include <asm/iommu.h> 489aa32835SJeff Kirsher #include <asm/firmware.h> 499aa32835SJeff Kirsher 509aa32835SJeff Kirsher #include "ibmveth.h" 519aa32835SJeff Kirsher 529aa32835SJeff Kirsher static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance); 539aa32835SJeff Kirsher static void ibmveth_rxq_harvest_buffer(struct ibmveth_adapter *adapter); 549aa32835SJeff Kirsher static unsigned long ibmveth_get_desired_dma(struct vio_dev *vdev); 559aa32835SJeff Kirsher 569aa32835SJeff Kirsher static struct kobj_type ktype_veth_pool; 579aa32835SJeff Kirsher 589aa32835SJeff Kirsher 599aa32835SJeff Kirsher static const char ibmveth_driver_name[] = "ibmveth"; 609aa32835SJeff Kirsher static const char ibmveth_driver_string[] = "IBM Power Virtual Ethernet Driver"; 618641dd85SThomas Falcon #define ibmveth_driver_version "1.05" 629aa32835SJeff Kirsher 639aa32835SJeff Kirsher MODULE_AUTHOR("Santiago Leon <santil@linux.vnet.ibm.com>"); 649aa32835SJeff Kirsher MODULE_DESCRIPTION("IBM Power Virtual Ethernet Driver"); 659aa32835SJeff Kirsher MODULE_LICENSE("GPL"); 669aa32835SJeff Kirsher MODULE_VERSION(ibmveth_driver_version); 679aa32835SJeff Kirsher 689aa32835SJeff Kirsher static unsigned int tx_copybreak __read_mostly = 128; 699aa32835SJeff Kirsher module_param(tx_copybreak, uint, 0644); 709aa32835SJeff Kirsher MODULE_PARM_DESC(tx_copybreak, 719aa32835SJeff Kirsher "Maximum size of packet that is copied to a new buffer on transmit"); 729aa32835SJeff Kirsher 739aa32835SJeff Kirsher static unsigned int rx_copybreak __read_mostly = 128; 749aa32835SJeff Kirsher module_param(rx_copybreak, uint, 0644); 759aa32835SJeff Kirsher MODULE_PARM_DESC(rx_copybreak, 769aa32835SJeff Kirsher "Maximum size of packet that is copied to a new buffer on receive"); 779aa32835SJeff Kirsher 789aa32835SJeff Kirsher static unsigned int rx_flush __read_mostly = 0; 799aa32835SJeff Kirsher module_param(rx_flush, uint, 0644); 809aa32835SJeff Kirsher MODULE_PARM_DESC(rx_flush, "Flush receive buffers before use"); 819aa32835SJeff Kirsher 82*07e6a97dSThomas Falcon static bool old_large_send __read_mostly; 83*07e6a97dSThomas Falcon module_param(old_large_send, bool, S_IRUGO); 84*07e6a97dSThomas Falcon MODULE_PARM_DESC(old_large_send, 85*07e6a97dSThomas Falcon "Use old large send method on firmware that supports the new method"); 86*07e6a97dSThomas Falcon 879aa32835SJeff Kirsher struct ibmveth_stat { 889aa32835SJeff Kirsher char name[ETH_GSTRING_LEN]; 899aa32835SJeff Kirsher int offset; 909aa32835SJeff Kirsher }; 919aa32835SJeff Kirsher 929aa32835SJeff Kirsher #define IBMVETH_STAT_OFF(stat) offsetof(struct ibmveth_adapter, stat) 939aa32835SJeff Kirsher #define IBMVETH_GET_STAT(a, off) *((u64 *)(((unsigned long)(a)) + off)) 949aa32835SJeff Kirsher 959aa32835SJeff Kirsher struct ibmveth_stat ibmveth_stats[] = { 969aa32835SJeff Kirsher { "replenish_task_cycles", IBMVETH_STAT_OFF(replenish_task_cycles) }, 979aa32835SJeff Kirsher { "replenish_no_mem", IBMVETH_STAT_OFF(replenish_no_mem) }, 989aa32835SJeff Kirsher { "replenish_add_buff_failure", 999aa32835SJeff Kirsher IBMVETH_STAT_OFF(replenish_add_buff_failure) }, 1009aa32835SJeff Kirsher { "replenish_add_buff_success", 1019aa32835SJeff Kirsher IBMVETH_STAT_OFF(replenish_add_buff_success) }, 1029aa32835SJeff Kirsher { "rx_invalid_buffer", IBMVETH_STAT_OFF(rx_invalid_buffer) }, 1039aa32835SJeff Kirsher { "rx_no_buffer", IBMVETH_STAT_OFF(rx_no_buffer) }, 1049aa32835SJeff Kirsher { "tx_map_failed", IBMVETH_STAT_OFF(tx_map_failed) }, 1059aa32835SJeff Kirsher { "tx_send_failed", IBMVETH_STAT_OFF(tx_send_failed) }, 1069aa32835SJeff Kirsher { "fw_enabled_ipv4_csum", IBMVETH_STAT_OFF(fw_ipv4_csum_support) }, 1079aa32835SJeff Kirsher { "fw_enabled_ipv6_csum", IBMVETH_STAT_OFF(fw_ipv6_csum_support) }, 1088641dd85SThomas Falcon { "tx_large_packets", IBMVETH_STAT_OFF(tx_large_packets) }, 109*07e6a97dSThomas Falcon { "rx_large_packets", IBMVETH_STAT_OFF(rx_large_packets) }, 110*07e6a97dSThomas Falcon { "fw_enabled_large_send", IBMVETH_STAT_OFF(fw_large_send_support) } 1119aa32835SJeff Kirsher }; 1129aa32835SJeff Kirsher 1139aa32835SJeff Kirsher /* simple methods of getting data from the current rxq entry */ 1149aa32835SJeff Kirsher static inline u32 ibmveth_rxq_flags(struct ibmveth_adapter *adapter) 1159aa32835SJeff Kirsher { 1160b536be7SAnton Blanchard return be32_to_cpu(adapter->rx_queue.queue_addr[adapter->rx_queue.index].flags_off); 1179aa32835SJeff Kirsher } 1189aa32835SJeff Kirsher 1199aa32835SJeff Kirsher static inline int ibmveth_rxq_toggle(struct ibmveth_adapter *adapter) 1209aa32835SJeff Kirsher { 1219aa32835SJeff Kirsher return (ibmveth_rxq_flags(adapter) & IBMVETH_RXQ_TOGGLE) >> 1229aa32835SJeff Kirsher IBMVETH_RXQ_TOGGLE_SHIFT; 1239aa32835SJeff Kirsher } 1249aa32835SJeff Kirsher 1259aa32835SJeff Kirsher static inline int ibmveth_rxq_pending_buffer(struct ibmveth_adapter *adapter) 1269aa32835SJeff Kirsher { 1279aa32835SJeff Kirsher return ibmveth_rxq_toggle(adapter) == adapter->rx_queue.toggle; 1289aa32835SJeff Kirsher } 1299aa32835SJeff Kirsher 1309aa32835SJeff Kirsher static inline int ibmveth_rxq_buffer_valid(struct ibmveth_adapter *adapter) 1319aa32835SJeff Kirsher { 1329aa32835SJeff Kirsher return ibmveth_rxq_flags(adapter) & IBMVETH_RXQ_VALID; 1339aa32835SJeff Kirsher } 1349aa32835SJeff Kirsher 1359aa32835SJeff Kirsher static inline int ibmveth_rxq_frame_offset(struct ibmveth_adapter *adapter) 1369aa32835SJeff Kirsher { 1379aa32835SJeff Kirsher return ibmveth_rxq_flags(adapter) & IBMVETH_RXQ_OFF_MASK; 1389aa32835SJeff Kirsher } 1399aa32835SJeff Kirsher 1409aa32835SJeff Kirsher static inline int ibmveth_rxq_frame_length(struct ibmveth_adapter *adapter) 1419aa32835SJeff Kirsher { 1420b536be7SAnton Blanchard return be32_to_cpu(adapter->rx_queue.queue_addr[adapter->rx_queue.index].length); 1439aa32835SJeff Kirsher } 1449aa32835SJeff Kirsher 1459aa32835SJeff Kirsher static inline int ibmveth_rxq_csum_good(struct ibmveth_adapter *adapter) 1469aa32835SJeff Kirsher { 1479aa32835SJeff Kirsher return ibmveth_rxq_flags(adapter) & IBMVETH_RXQ_CSUM_GOOD; 1489aa32835SJeff Kirsher } 1499aa32835SJeff Kirsher 1509aa32835SJeff Kirsher /* setup the initial settings for a buffer pool */ 1519aa32835SJeff Kirsher static void ibmveth_init_buffer_pool(struct ibmveth_buff_pool *pool, 1529aa32835SJeff Kirsher u32 pool_index, u32 pool_size, 1539aa32835SJeff Kirsher u32 buff_size, u32 pool_active) 1549aa32835SJeff Kirsher { 1559aa32835SJeff Kirsher pool->size = pool_size; 1569aa32835SJeff Kirsher pool->index = pool_index; 1579aa32835SJeff Kirsher pool->buff_size = buff_size; 1589aa32835SJeff Kirsher pool->threshold = pool_size * 7 / 8; 1599aa32835SJeff Kirsher pool->active = pool_active; 1609aa32835SJeff Kirsher } 1619aa32835SJeff Kirsher 1629aa32835SJeff Kirsher /* allocate and setup an buffer pool - called during open */ 1639aa32835SJeff Kirsher static int ibmveth_alloc_buffer_pool(struct ibmveth_buff_pool *pool) 1649aa32835SJeff Kirsher { 1659aa32835SJeff Kirsher int i; 1669aa32835SJeff Kirsher 1679aa32835SJeff Kirsher pool->free_map = kmalloc(sizeof(u16) * pool->size, GFP_KERNEL); 1689aa32835SJeff Kirsher 1699aa32835SJeff Kirsher if (!pool->free_map) 1709aa32835SJeff Kirsher return -1; 1719aa32835SJeff Kirsher 1729aa32835SJeff Kirsher pool->dma_addr = kmalloc(sizeof(dma_addr_t) * pool->size, GFP_KERNEL); 1739aa32835SJeff Kirsher if (!pool->dma_addr) { 1749aa32835SJeff Kirsher kfree(pool->free_map); 1759aa32835SJeff Kirsher pool->free_map = NULL; 1769aa32835SJeff Kirsher return -1; 1779aa32835SJeff Kirsher } 1789aa32835SJeff Kirsher 1799aa32835SJeff Kirsher pool->skbuff = kcalloc(pool->size, sizeof(void *), GFP_KERNEL); 1809aa32835SJeff Kirsher 1819aa32835SJeff Kirsher if (!pool->skbuff) { 1829aa32835SJeff Kirsher kfree(pool->dma_addr); 1839aa32835SJeff Kirsher pool->dma_addr = NULL; 1849aa32835SJeff Kirsher 1859aa32835SJeff Kirsher kfree(pool->free_map); 1869aa32835SJeff Kirsher pool->free_map = NULL; 1879aa32835SJeff Kirsher return -1; 1889aa32835SJeff Kirsher } 1899aa32835SJeff Kirsher 1909aa32835SJeff Kirsher memset(pool->dma_addr, 0, sizeof(dma_addr_t) * pool->size); 1919aa32835SJeff Kirsher 1929aa32835SJeff Kirsher for (i = 0; i < pool->size; ++i) 1939aa32835SJeff Kirsher pool->free_map[i] = i; 1949aa32835SJeff Kirsher 1959aa32835SJeff Kirsher atomic_set(&pool->available, 0); 1969aa32835SJeff Kirsher pool->producer_index = 0; 1979aa32835SJeff Kirsher pool->consumer_index = 0; 1989aa32835SJeff Kirsher 1999aa32835SJeff Kirsher return 0; 2009aa32835SJeff Kirsher } 2019aa32835SJeff Kirsher 2029aa32835SJeff Kirsher static inline void ibmveth_flush_buffer(void *addr, unsigned long length) 2039aa32835SJeff Kirsher { 2049aa32835SJeff Kirsher unsigned long offset; 2059aa32835SJeff Kirsher 2069aa32835SJeff Kirsher for (offset = 0; offset < length; offset += SMP_CACHE_BYTES) 2079aa32835SJeff Kirsher asm("dcbfl %0,%1" :: "b" (addr), "r" (offset)); 2089aa32835SJeff Kirsher } 2099aa32835SJeff Kirsher 2109aa32835SJeff Kirsher /* replenish the buffers for a pool. note that we don't need to 2119aa32835SJeff Kirsher * skb_reserve these since they are used for incoming... 2129aa32835SJeff Kirsher */ 2139aa32835SJeff Kirsher static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, 2149aa32835SJeff Kirsher struct ibmveth_buff_pool *pool) 2159aa32835SJeff Kirsher { 2169aa32835SJeff Kirsher u32 i; 2179aa32835SJeff Kirsher u32 count = pool->size - atomic_read(&pool->available); 2189aa32835SJeff Kirsher u32 buffers_added = 0; 2199aa32835SJeff Kirsher struct sk_buff *skb; 2209aa32835SJeff Kirsher unsigned int free_index, index; 2219aa32835SJeff Kirsher u64 correlator; 2229aa32835SJeff Kirsher unsigned long lpar_rc; 2239aa32835SJeff Kirsher dma_addr_t dma_addr; 2249aa32835SJeff Kirsher 2259aa32835SJeff Kirsher mb(); 2269aa32835SJeff Kirsher 2279aa32835SJeff Kirsher for (i = 0; i < count; ++i) { 2289aa32835SJeff Kirsher union ibmveth_buf_desc desc; 2299aa32835SJeff Kirsher 2309aa32835SJeff Kirsher skb = netdev_alloc_skb(adapter->netdev, pool->buff_size); 2319aa32835SJeff Kirsher 2329aa32835SJeff Kirsher if (!skb) { 2339aa32835SJeff Kirsher netdev_dbg(adapter->netdev, 2349aa32835SJeff Kirsher "replenish: unable to allocate skb\n"); 2359aa32835SJeff Kirsher adapter->replenish_no_mem++; 2369aa32835SJeff Kirsher break; 2379aa32835SJeff Kirsher } 2389aa32835SJeff Kirsher 2399aa32835SJeff Kirsher free_index = pool->consumer_index; 2409aa32835SJeff Kirsher pool->consumer_index++; 2419aa32835SJeff Kirsher if (pool->consumer_index >= pool->size) 2429aa32835SJeff Kirsher pool->consumer_index = 0; 2439aa32835SJeff Kirsher index = pool->free_map[free_index]; 2449aa32835SJeff Kirsher 2459aa32835SJeff Kirsher BUG_ON(index == IBM_VETH_INVALID_MAP); 2469aa32835SJeff Kirsher BUG_ON(pool->skbuff[index] != NULL); 2479aa32835SJeff Kirsher 2489aa32835SJeff Kirsher dma_addr = dma_map_single(&adapter->vdev->dev, skb->data, 2499aa32835SJeff Kirsher pool->buff_size, DMA_FROM_DEVICE); 2509aa32835SJeff Kirsher 2519aa32835SJeff Kirsher if (dma_mapping_error(&adapter->vdev->dev, dma_addr)) 2529aa32835SJeff Kirsher goto failure; 2539aa32835SJeff Kirsher 2549aa32835SJeff Kirsher pool->free_map[free_index] = IBM_VETH_INVALID_MAP; 2559aa32835SJeff Kirsher pool->dma_addr[index] = dma_addr; 2569aa32835SJeff Kirsher pool->skbuff[index] = skb; 2579aa32835SJeff Kirsher 2589aa32835SJeff Kirsher correlator = ((u64)pool->index << 32) | index; 2599aa32835SJeff Kirsher *(u64 *)skb->data = correlator; 2609aa32835SJeff Kirsher 2619aa32835SJeff Kirsher desc.fields.flags_len = IBMVETH_BUF_VALID | pool->buff_size; 2629aa32835SJeff Kirsher desc.fields.address = dma_addr; 2639aa32835SJeff Kirsher 2649aa32835SJeff Kirsher if (rx_flush) { 2659aa32835SJeff Kirsher unsigned int len = min(pool->buff_size, 2669aa32835SJeff Kirsher adapter->netdev->mtu + 2679aa32835SJeff Kirsher IBMVETH_BUFF_OH); 2689aa32835SJeff Kirsher ibmveth_flush_buffer(skb->data, len); 2699aa32835SJeff Kirsher } 2709aa32835SJeff Kirsher lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, 2719aa32835SJeff Kirsher desc.desc); 2729aa32835SJeff Kirsher 2739aa32835SJeff Kirsher if (lpar_rc != H_SUCCESS) { 2749aa32835SJeff Kirsher goto failure; 2759aa32835SJeff Kirsher } else { 2769aa32835SJeff Kirsher buffers_added++; 2779aa32835SJeff Kirsher adapter->replenish_add_buff_success++; 2789aa32835SJeff Kirsher } 2799aa32835SJeff Kirsher } 2809aa32835SJeff Kirsher 2819aa32835SJeff Kirsher mb(); 2829aa32835SJeff Kirsher atomic_add(buffers_added, &(pool->available)); 2839aa32835SJeff Kirsher return; 2849aa32835SJeff Kirsher 2859aa32835SJeff Kirsher failure: 2869aa32835SJeff Kirsher pool->free_map[free_index] = index; 2879aa32835SJeff Kirsher pool->skbuff[index] = NULL; 2889aa32835SJeff Kirsher if (pool->consumer_index == 0) 2899aa32835SJeff Kirsher pool->consumer_index = pool->size - 1; 2909aa32835SJeff Kirsher else 2919aa32835SJeff Kirsher pool->consumer_index--; 2929aa32835SJeff Kirsher if (!dma_mapping_error(&adapter->vdev->dev, dma_addr)) 2939aa32835SJeff Kirsher dma_unmap_single(&adapter->vdev->dev, 2949aa32835SJeff Kirsher pool->dma_addr[index], pool->buff_size, 2959aa32835SJeff Kirsher DMA_FROM_DEVICE); 2969aa32835SJeff Kirsher dev_kfree_skb_any(skb); 2979aa32835SJeff Kirsher adapter->replenish_add_buff_failure++; 2989aa32835SJeff Kirsher 2999aa32835SJeff Kirsher mb(); 3009aa32835SJeff Kirsher atomic_add(buffers_added, &(pool->available)); 3019aa32835SJeff Kirsher } 3029aa32835SJeff Kirsher 303cbd52281SAnton Blanchard /* 304cbd52281SAnton Blanchard * The final 8 bytes of the buffer list is a counter of frames dropped 305cbd52281SAnton Blanchard * because there was not a buffer in the buffer list capable of holding 306cbd52281SAnton Blanchard * the frame. 307cbd52281SAnton Blanchard */ 308cbd52281SAnton Blanchard static void ibmveth_update_rx_no_buffer(struct ibmveth_adapter *adapter) 309cbd52281SAnton Blanchard { 310cbd52281SAnton Blanchard __be64 *p = adapter->buffer_list_addr + 4096 - 8; 311cbd52281SAnton Blanchard 312cbd52281SAnton Blanchard adapter->rx_no_buffer = be64_to_cpup(p); 313cbd52281SAnton Blanchard } 314cbd52281SAnton Blanchard 3159aa32835SJeff Kirsher /* replenish routine */ 3169aa32835SJeff Kirsher static void ibmveth_replenish_task(struct ibmveth_adapter *adapter) 3179aa32835SJeff Kirsher { 3189aa32835SJeff Kirsher int i; 3199aa32835SJeff Kirsher 3209aa32835SJeff Kirsher adapter->replenish_task_cycles++; 3219aa32835SJeff Kirsher 3229aa32835SJeff Kirsher for (i = (IBMVETH_NUM_BUFF_POOLS - 1); i >= 0; i--) { 3239aa32835SJeff Kirsher struct ibmveth_buff_pool *pool = &adapter->rx_buff_pool[i]; 3249aa32835SJeff Kirsher 3259aa32835SJeff Kirsher if (pool->active && 3269aa32835SJeff Kirsher (atomic_read(&pool->available) < pool->threshold)) 3279aa32835SJeff Kirsher ibmveth_replenish_buffer_pool(adapter, pool); 3289aa32835SJeff Kirsher } 3299aa32835SJeff Kirsher 330cbd52281SAnton Blanchard ibmveth_update_rx_no_buffer(adapter); 3319aa32835SJeff Kirsher } 3329aa32835SJeff Kirsher 3339aa32835SJeff Kirsher /* empty and free ana buffer pool - also used to do cleanup in error paths */ 3349aa32835SJeff Kirsher static void ibmveth_free_buffer_pool(struct ibmveth_adapter *adapter, 3359aa32835SJeff Kirsher struct ibmveth_buff_pool *pool) 3369aa32835SJeff Kirsher { 3379aa32835SJeff Kirsher int i; 3389aa32835SJeff Kirsher 3399aa32835SJeff Kirsher kfree(pool->free_map); 3409aa32835SJeff Kirsher pool->free_map = NULL; 3419aa32835SJeff Kirsher 3429aa32835SJeff Kirsher if (pool->skbuff && pool->dma_addr) { 3439aa32835SJeff Kirsher for (i = 0; i < pool->size; ++i) { 3449aa32835SJeff Kirsher struct sk_buff *skb = pool->skbuff[i]; 3459aa32835SJeff Kirsher if (skb) { 3469aa32835SJeff Kirsher dma_unmap_single(&adapter->vdev->dev, 3479aa32835SJeff Kirsher pool->dma_addr[i], 3489aa32835SJeff Kirsher pool->buff_size, 3499aa32835SJeff Kirsher DMA_FROM_DEVICE); 3509aa32835SJeff Kirsher dev_kfree_skb_any(skb); 3519aa32835SJeff Kirsher pool->skbuff[i] = NULL; 3529aa32835SJeff Kirsher } 3539aa32835SJeff Kirsher } 3549aa32835SJeff Kirsher } 3559aa32835SJeff Kirsher 3569aa32835SJeff Kirsher if (pool->dma_addr) { 3579aa32835SJeff Kirsher kfree(pool->dma_addr); 3589aa32835SJeff Kirsher pool->dma_addr = NULL; 3599aa32835SJeff Kirsher } 3609aa32835SJeff Kirsher 3619aa32835SJeff Kirsher if (pool->skbuff) { 3629aa32835SJeff Kirsher kfree(pool->skbuff); 3639aa32835SJeff Kirsher pool->skbuff = NULL; 3649aa32835SJeff Kirsher } 3659aa32835SJeff Kirsher } 3669aa32835SJeff Kirsher 3679aa32835SJeff Kirsher /* remove a buffer from a pool */ 3689aa32835SJeff Kirsher static void ibmveth_remove_buffer_from_pool(struct ibmveth_adapter *adapter, 3699aa32835SJeff Kirsher u64 correlator) 3709aa32835SJeff Kirsher { 3719aa32835SJeff Kirsher unsigned int pool = correlator >> 32; 3729aa32835SJeff Kirsher unsigned int index = correlator & 0xffffffffUL; 3739aa32835SJeff Kirsher unsigned int free_index; 3749aa32835SJeff Kirsher struct sk_buff *skb; 3759aa32835SJeff Kirsher 3769aa32835SJeff Kirsher BUG_ON(pool >= IBMVETH_NUM_BUFF_POOLS); 3779aa32835SJeff Kirsher BUG_ON(index >= adapter->rx_buff_pool[pool].size); 3789aa32835SJeff Kirsher 3799aa32835SJeff Kirsher skb = adapter->rx_buff_pool[pool].skbuff[index]; 3809aa32835SJeff Kirsher 3819aa32835SJeff Kirsher BUG_ON(skb == NULL); 3829aa32835SJeff Kirsher 3839aa32835SJeff Kirsher adapter->rx_buff_pool[pool].skbuff[index] = NULL; 3849aa32835SJeff Kirsher 3859aa32835SJeff Kirsher dma_unmap_single(&adapter->vdev->dev, 3869aa32835SJeff Kirsher adapter->rx_buff_pool[pool].dma_addr[index], 3879aa32835SJeff Kirsher adapter->rx_buff_pool[pool].buff_size, 3889aa32835SJeff Kirsher DMA_FROM_DEVICE); 3899aa32835SJeff Kirsher 3909aa32835SJeff Kirsher free_index = adapter->rx_buff_pool[pool].producer_index; 3919aa32835SJeff Kirsher adapter->rx_buff_pool[pool].producer_index++; 3929aa32835SJeff Kirsher if (adapter->rx_buff_pool[pool].producer_index >= 3939aa32835SJeff Kirsher adapter->rx_buff_pool[pool].size) 3949aa32835SJeff Kirsher adapter->rx_buff_pool[pool].producer_index = 0; 3959aa32835SJeff Kirsher adapter->rx_buff_pool[pool].free_map[free_index] = index; 3969aa32835SJeff Kirsher 3979aa32835SJeff Kirsher mb(); 3989aa32835SJeff Kirsher 3999aa32835SJeff Kirsher atomic_dec(&(adapter->rx_buff_pool[pool].available)); 4009aa32835SJeff Kirsher } 4019aa32835SJeff Kirsher 4029aa32835SJeff Kirsher /* get the current buffer on the rx queue */ 4039aa32835SJeff Kirsher static inline struct sk_buff *ibmveth_rxq_get_buffer(struct ibmveth_adapter *adapter) 4049aa32835SJeff Kirsher { 4059aa32835SJeff Kirsher u64 correlator = adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator; 4069aa32835SJeff Kirsher unsigned int pool = correlator >> 32; 4079aa32835SJeff Kirsher unsigned int index = correlator & 0xffffffffUL; 4089aa32835SJeff Kirsher 4099aa32835SJeff Kirsher BUG_ON(pool >= IBMVETH_NUM_BUFF_POOLS); 4109aa32835SJeff Kirsher BUG_ON(index >= adapter->rx_buff_pool[pool].size); 4119aa32835SJeff Kirsher 4129aa32835SJeff Kirsher return adapter->rx_buff_pool[pool].skbuff[index]; 4139aa32835SJeff Kirsher } 4149aa32835SJeff Kirsher 4159aa32835SJeff Kirsher /* recycle the current buffer on the rx queue */ 4168decf868SDavid S. Miller static int ibmveth_rxq_recycle_buffer(struct ibmveth_adapter *adapter) 4179aa32835SJeff Kirsher { 4189aa32835SJeff Kirsher u32 q_index = adapter->rx_queue.index; 4199aa32835SJeff Kirsher u64 correlator = adapter->rx_queue.queue_addr[q_index].correlator; 4209aa32835SJeff Kirsher unsigned int pool = correlator >> 32; 4219aa32835SJeff Kirsher unsigned int index = correlator & 0xffffffffUL; 4229aa32835SJeff Kirsher union ibmveth_buf_desc desc; 4239aa32835SJeff Kirsher unsigned long lpar_rc; 4248decf868SDavid S. Miller int ret = 1; 4259aa32835SJeff Kirsher 4269aa32835SJeff Kirsher BUG_ON(pool >= IBMVETH_NUM_BUFF_POOLS); 4279aa32835SJeff Kirsher BUG_ON(index >= adapter->rx_buff_pool[pool].size); 4289aa32835SJeff Kirsher 4299aa32835SJeff Kirsher if (!adapter->rx_buff_pool[pool].active) { 4309aa32835SJeff Kirsher ibmveth_rxq_harvest_buffer(adapter); 4319aa32835SJeff Kirsher ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[pool]); 4328decf868SDavid S. Miller goto out; 4339aa32835SJeff Kirsher } 4349aa32835SJeff Kirsher 4359aa32835SJeff Kirsher desc.fields.flags_len = IBMVETH_BUF_VALID | 4369aa32835SJeff Kirsher adapter->rx_buff_pool[pool].buff_size; 4379aa32835SJeff Kirsher desc.fields.address = adapter->rx_buff_pool[pool].dma_addr[index]; 4389aa32835SJeff Kirsher 4399aa32835SJeff Kirsher lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc); 4409aa32835SJeff Kirsher 4419aa32835SJeff Kirsher if (lpar_rc != H_SUCCESS) { 4429aa32835SJeff Kirsher netdev_dbg(adapter->netdev, "h_add_logical_lan_buffer failed " 4439aa32835SJeff Kirsher "during recycle rc=%ld", lpar_rc); 4449aa32835SJeff Kirsher ibmveth_remove_buffer_from_pool(adapter, adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator); 4458decf868SDavid S. Miller ret = 0; 4469aa32835SJeff Kirsher } 4479aa32835SJeff Kirsher 4489aa32835SJeff Kirsher if (++adapter->rx_queue.index == adapter->rx_queue.num_slots) { 4499aa32835SJeff Kirsher adapter->rx_queue.index = 0; 4509aa32835SJeff Kirsher adapter->rx_queue.toggle = !adapter->rx_queue.toggle; 4519aa32835SJeff Kirsher } 4528decf868SDavid S. Miller 4538decf868SDavid S. Miller out: 4548decf868SDavid S. Miller return ret; 4559aa32835SJeff Kirsher } 4569aa32835SJeff Kirsher 4579aa32835SJeff Kirsher static void ibmveth_rxq_harvest_buffer(struct ibmveth_adapter *adapter) 4589aa32835SJeff Kirsher { 4599aa32835SJeff Kirsher ibmveth_remove_buffer_from_pool(adapter, adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator); 4609aa32835SJeff Kirsher 4619aa32835SJeff Kirsher if (++adapter->rx_queue.index == adapter->rx_queue.num_slots) { 4629aa32835SJeff Kirsher adapter->rx_queue.index = 0; 4639aa32835SJeff Kirsher adapter->rx_queue.toggle = !adapter->rx_queue.toggle; 4649aa32835SJeff Kirsher } 4659aa32835SJeff Kirsher } 4669aa32835SJeff Kirsher 4679aa32835SJeff Kirsher static void ibmveth_cleanup(struct ibmveth_adapter *adapter) 4689aa32835SJeff Kirsher { 4699aa32835SJeff Kirsher int i; 4709aa32835SJeff Kirsher struct device *dev = &adapter->vdev->dev; 4719aa32835SJeff Kirsher 4729aa32835SJeff Kirsher if (adapter->buffer_list_addr != NULL) { 4739aa32835SJeff Kirsher if (!dma_mapping_error(dev, adapter->buffer_list_dma)) { 4749aa32835SJeff Kirsher dma_unmap_single(dev, adapter->buffer_list_dma, 4096, 4759aa32835SJeff Kirsher DMA_BIDIRECTIONAL); 4769aa32835SJeff Kirsher adapter->buffer_list_dma = DMA_ERROR_CODE; 4779aa32835SJeff Kirsher } 4789aa32835SJeff Kirsher free_page((unsigned long)adapter->buffer_list_addr); 4799aa32835SJeff Kirsher adapter->buffer_list_addr = NULL; 4809aa32835SJeff Kirsher } 4819aa32835SJeff Kirsher 4829aa32835SJeff Kirsher if (adapter->filter_list_addr != NULL) { 4839aa32835SJeff Kirsher if (!dma_mapping_error(dev, adapter->filter_list_dma)) { 4849aa32835SJeff Kirsher dma_unmap_single(dev, adapter->filter_list_dma, 4096, 4859aa32835SJeff Kirsher DMA_BIDIRECTIONAL); 4869aa32835SJeff Kirsher adapter->filter_list_dma = DMA_ERROR_CODE; 4879aa32835SJeff Kirsher } 4889aa32835SJeff Kirsher free_page((unsigned long)adapter->filter_list_addr); 4899aa32835SJeff Kirsher adapter->filter_list_addr = NULL; 4909aa32835SJeff Kirsher } 4919aa32835SJeff Kirsher 4929aa32835SJeff Kirsher if (adapter->rx_queue.queue_addr != NULL) { 493d90c92feSSantiago Leon dma_free_coherent(dev, adapter->rx_queue.queue_len, 494d90c92feSSantiago Leon adapter->rx_queue.queue_addr, 495d90c92feSSantiago Leon adapter->rx_queue.queue_dma); 4969aa32835SJeff Kirsher adapter->rx_queue.queue_addr = NULL; 4979aa32835SJeff Kirsher } 4989aa32835SJeff Kirsher 4999aa32835SJeff Kirsher for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) 5009aa32835SJeff Kirsher if (adapter->rx_buff_pool[i].active) 5019aa32835SJeff Kirsher ibmveth_free_buffer_pool(adapter, 5029aa32835SJeff Kirsher &adapter->rx_buff_pool[i]); 5039aa32835SJeff Kirsher 5049aa32835SJeff Kirsher if (adapter->bounce_buffer != NULL) { 5059aa32835SJeff Kirsher if (!dma_mapping_error(dev, adapter->bounce_buffer_dma)) { 5069aa32835SJeff Kirsher dma_unmap_single(&adapter->vdev->dev, 5079aa32835SJeff Kirsher adapter->bounce_buffer_dma, 5089aa32835SJeff Kirsher adapter->netdev->mtu + IBMVETH_BUFF_OH, 5099aa32835SJeff Kirsher DMA_BIDIRECTIONAL); 5109aa32835SJeff Kirsher adapter->bounce_buffer_dma = DMA_ERROR_CODE; 5119aa32835SJeff Kirsher } 5129aa32835SJeff Kirsher kfree(adapter->bounce_buffer); 5139aa32835SJeff Kirsher adapter->bounce_buffer = NULL; 5149aa32835SJeff Kirsher } 5159aa32835SJeff Kirsher } 5169aa32835SJeff Kirsher 5179aa32835SJeff Kirsher static int ibmveth_register_logical_lan(struct ibmveth_adapter *adapter, 5189aa32835SJeff Kirsher union ibmveth_buf_desc rxq_desc, u64 mac_address) 5199aa32835SJeff Kirsher { 5209aa32835SJeff Kirsher int rc, try_again = 1; 5219aa32835SJeff Kirsher 5229aa32835SJeff Kirsher /* 5239aa32835SJeff Kirsher * After a kexec the adapter will still be open, so our attempt to 5249aa32835SJeff Kirsher * open it will fail. So if we get a failure we free the adapter and 5259aa32835SJeff Kirsher * try again, but only once. 5269aa32835SJeff Kirsher */ 5279aa32835SJeff Kirsher retry: 5289aa32835SJeff Kirsher rc = h_register_logical_lan(adapter->vdev->unit_address, 5299aa32835SJeff Kirsher adapter->buffer_list_dma, rxq_desc.desc, 5309aa32835SJeff Kirsher adapter->filter_list_dma, mac_address); 5319aa32835SJeff Kirsher 5329aa32835SJeff Kirsher if (rc != H_SUCCESS && try_again) { 5339aa32835SJeff Kirsher do { 5349aa32835SJeff Kirsher rc = h_free_logical_lan(adapter->vdev->unit_address); 5359aa32835SJeff Kirsher } while (H_IS_LONG_BUSY(rc) || (rc == H_BUSY)); 5369aa32835SJeff Kirsher 5379aa32835SJeff Kirsher try_again = 0; 5389aa32835SJeff Kirsher goto retry; 5399aa32835SJeff Kirsher } 5409aa32835SJeff Kirsher 5419aa32835SJeff Kirsher return rc; 5429aa32835SJeff Kirsher } 5439aa32835SJeff Kirsher 544d746ca95SAnton Blanchard static u64 ibmveth_encode_mac_addr(u8 *mac) 545d746ca95SAnton Blanchard { 546d746ca95SAnton Blanchard int i; 547d746ca95SAnton Blanchard u64 encoded = 0; 548d746ca95SAnton Blanchard 549d746ca95SAnton Blanchard for (i = 0; i < ETH_ALEN; i++) 550d746ca95SAnton Blanchard encoded = (encoded << 8) | mac[i]; 551d746ca95SAnton Blanchard 552d746ca95SAnton Blanchard return encoded; 553d746ca95SAnton Blanchard } 554d746ca95SAnton Blanchard 5559aa32835SJeff Kirsher static int ibmveth_open(struct net_device *netdev) 5569aa32835SJeff Kirsher { 5579aa32835SJeff Kirsher struct ibmveth_adapter *adapter = netdev_priv(netdev); 558d746ca95SAnton Blanchard u64 mac_address; 5599aa32835SJeff Kirsher int rxq_entries = 1; 5609aa32835SJeff Kirsher unsigned long lpar_rc; 5619aa32835SJeff Kirsher int rc; 5629aa32835SJeff Kirsher union ibmveth_buf_desc rxq_desc; 5639aa32835SJeff Kirsher int i; 5649aa32835SJeff Kirsher struct device *dev; 5659aa32835SJeff Kirsher 5669aa32835SJeff Kirsher netdev_dbg(netdev, "open starting\n"); 5679aa32835SJeff Kirsher 5689aa32835SJeff Kirsher napi_enable(&adapter->napi); 5699aa32835SJeff Kirsher 5709aa32835SJeff Kirsher for(i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) 5719aa32835SJeff Kirsher rxq_entries += adapter->rx_buff_pool[i].size; 5729aa32835SJeff Kirsher 5739aa32835SJeff Kirsher adapter->buffer_list_addr = (void*) get_zeroed_page(GFP_KERNEL); 5749aa32835SJeff Kirsher adapter->filter_list_addr = (void*) get_zeroed_page(GFP_KERNEL); 5759aa32835SJeff Kirsher 5769aa32835SJeff Kirsher if (!adapter->buffer_list_addr || !adapter->filter_list_addr) { 5779aa32835SJeff Kirsher netdev_err(netdev, "unable to allocate filter or buffer list " 5789aa32835SJeff Kirsher "pages\n"); 5799aa32835SJeff Kirsher rc = -ENOMEM; 5809aa32835SJeff Kirsher goto err_out; 5819aa32835SJeff Kirsher } 5829aa32835SJeff Kirsher 583d90c92feSSantiago Leon dev = &adapter->vdev->dev; 584d90c92feSSantiago Leon 5859aa32835SJeff Kirsher adapter->rx_queue.queue_len = sizeof(struct ibmveth_rx_q_entry) * 5869aa32835SJeff Kirsher rxq_entries; 587d90c92feSSantiago Leon adapter->rx_queue.queue_addr = 588d90c92feSSantiago Leon dma_alloc_coherent(dev, adapter->rx_queue.queue_len, 589d90c92feSSantiago Leon &adapter->rx_queue.queue_dma, GFP_KERNEL); 5909aa32835SJeff Kirsher if (!adapter->rx_queue.queue_addr) { 5919aa32835SJeff Kirsher rc = -ENOMEM; 5929aa32835SJeff Kirsher goto err_out; 5939aa32835SJeff Kirsher } 5949aa32835SJeff Kirsher 5959aa32835SJeff Kirsher adapter->buffer_list_dma = dma_map_single(dev, 5969aa32835SJeff Kirsher adapter->buffer_list_addr, 4096, DMA_BIDIRECTIONAL); 5979aa32835SJeff Kirsher adapter->filter_list_dma = dma_map_single(dev, 5989aa32835SJeff Kirsher adapter->filter_list_addr, 4096, DMA_BIDIRECTIONAL); 5999aa32835SJeff Kirsher 6009aa32835SJeff Kirsher if ((dma_mapping_error(dev, adapter->buffer_list_dma)) || 601d90c92feSSantiago Leon (dma_mapping_error(dev, adapter->filter_list_dma))) { 6029aa32835SJeff Kirsher netdev_err(netdev, "unable to map filter or buffer list " 6039aa32835SJeff Kirsher "pages\n"); 6049aa32835SJeff Kirsher rc = -ENOMEM; 6059aa32835SJeff Kirsher goto err_out; 6069aa32835SJeff Kirsher } 6079aa32835SJeff Kirsher 6089aa32835SJeff Kirsher adapter->rx_queue.index = 0; 6099aa32835SJeff Kirsher adapter->rx_queue.num_slots = rxq_entries; 6109aa32835SJeff Kirsher adapter->rx_queue.toggle = 1; 6119aa32835SJeff Kirsher 612d746ca95SAnton Blanchard mac_address = ibmveth_encode_mac_addr(netdev->dev_addr); 6139aa32835SJeff Kirsher 6149aa32835SJeff Kirsher rxq_desc.fields.flags_len = IBMVETH_BUF_VALID | 6159aa32835SJeff Kirsher adapter->rx_queue.queue_len; 6169aa32835SJeff Kirsher rxq_desc.fields.address = adapter->rx_queue.queue_dma; 6179aa32835SJeff Kirsher 6189aa32835SJeff Kirsher netdev_dbg(netdev, "buffer list @ 0x%p\n", adapter->buffer_list_addr); 6199aa32835SJeff Kirsher netdev_dbg(netdev, "filter list @ 0x%p\n", adapter->filter_list_addr); 6209aa32835SJeff Kirsher netdev_dbg(netdev, "receive q @ 0x%p\n", adapter->rx_queue.queue_addr); 6219aa32835SJeff Kirsher 6229aa32835SJeff Kirsher h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_DISABLE); 6239aa32835SJeff Kirsher 6249aa32835SJeff Kirsher lpar_rc = ibmveth_register_logical_lan(adapter, rxq_desc, mac_address); 6259aa32835SJeff Kirsher 6269aa32835SJeff Kirsher if (lpar_rc != H_SUCCESS) { 6279aa32835SJeff Kirsher netdev_err(netdev, "h_register_logical_lan failed with %ld\n", 6289aa32835SJeff Kirsher lpar_rc); 6299aa32835SJeff Kirsher netdev_err(netdev, "buffer TCE:0x%llx filter TCE:0x%llx rxq " 6309aa32835SJeff Kirsher "desc:0x%llx MAC:0x%llx\n", 6319aa32835SJeff Kirsher adapter->buffer_list_dma, 6329aa32835SJeff Kirsher adapter->filter_list_dma, 6339aa32835SJeff Kirsher rxq_desc.desc, 6349aa32835SJeff Kirsher mac_address); 6359aa32835SJeff Kirsher rc = -ENONET; 6369aa32835SJeff Kirsher goto err_out; 6379aa32835SJeff Kirsher } 6389aa32835SJeff Kirsher 6399aa32835SJeff Kirsher for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) { 6409aa32835SJeff Kirsher if (!adapter->rx_buff_pool[i].active) 6419aa32835SJeff Kirsher continue; 6429aa32835SJeff Kirsher if (ibmveth_alloc_buffer_pool(&adapter->rx_buff_pool[i])) { 6439aa32835SJeff Kirsher netdev_err(netdev, "unable to alloc pool\n"); 6449aa32835SJeff Kirsher adapter->rx_buff_pool[i].active = 0; 6459aa32835SJeff Kirsher rc = -ENOMEM; 6469aa32835SJeff Kirsher goto err_out; 6479aa32835SJeff Kirsher } 6489aa32835SJeff Kirsher } 6499aa32835SJeff Kirsher 6509aa32835SJeff Kirsher netdev_dbg(netdev, "registering irq 0x%x\n", netdev->irq); 6519aa32835SJeff Kirsher rc = request_irq(netdev->irq, ibmveth_interrupt, 0, netdev->name, 6529aa32835SJeff Kirsher netdev); 6539aa32835SJeff Kirsher if (rc != 0) { 6549aa32835SJeff Kirsher netdev_err(netdev, "unable to request irq 0x%x, rc %d\n", 6559aa32835SJeff Kirsher netdev->irq, rc); 6569aa32835SJeff Kirsher do { 65788c5100cSDavid S. Miller lpar_rc = h_free_logical_lan(adapter->vdev->unit_address); 65888c5100cSDavid S. Miller } while (H_IS_LONG_BUSY(lpar_rc) || (lpar_rc == H_BUSY)); 6599aa32835SJeff Kirsher 6609aa32835SJeff Kirsher goto err_out; 6619aa32835SJeff Kirsher } 6629aa32835SJeff Kirsher 6639aa32835SJeff Kirsher adapter->bounce_buffer = 6649aa32835SJeff Kirsher kmalloc(netdev->mtu + IBMVETH_BUFF_OH, GFP_KERNEL); 6659aa32835SJeff Kirsher if (!adapter->bounce_buffer) { 6669aa32835SJeff Kirsher rc = -ENOMEM; 6679aa32835SJeff Kirsher goto err_out_free_irq; 6689aa32835SJeff Kirsher } 6699aa32835SJeff Kirsher adapter->bounce_buffer_dma = 6709aa32835SJeff Kirsher dma_map_single(&adapter->vdev->dev, adapter->bounce_buffer, 6719aa32835SJeff Kirsher netdev->mtu + IBMVETH_BUFF_OH, DMA_BIDIRECTIONAL); 6729aa32835SJeff Kirsher if (dma_mapping_error(dev, adapter->bounce_buffer_dma)) { 6739aa32835SJeff Kirsher netdev_err(netdev, "unable to map bounce buffer\n"); 6749aa32835SJeff Kirsher rc = -ENOMEM; 6759aa32835SJeff Kirsher goto err_out_free_irq; 6769aa32835SJeff Kirsher } 6779aa32835SJeff Kirsher 6789aa32835SJeff Kirsher netdev_dbg(netdev, "initial replenish cycle\n"); 6799aa32835SJeff Kirsher ibmveth_interrupt(netdev->irq, netdev); 6809aa32835SJeff Kirsher 6819aa32835SJeff Kirsher netif_start_queue(netdev); 6829aa32835SJeff Kirsher 6839aa32835SJeff Kirsher netdev_dbg(netdev, "open complete\n"); 6849aa32835SJeff Kirsher 6859aa32835SJeff Kirsher return 0; 6869aa32835SJeff Kirsher 6879aa32835SJeff Kirsher err_out_free_irq: 6889aa32835SJeff Kirsher free_irq(netdev->irq, netdev); 6899aa32835SJeff Kirsher err_out: 6909aa32835SJeff Kirsher ibmveth_cleanup(adapter); 6919aa32835SJeff Kirsher napi_disable(&adapter->napi); 6929aa32835SJeff Kirsher return rc; 6939aa32835SJeff Kirsher } 6949aa32835SJeff Kirsher 6959aa32835SJeff Kirsher static int ibmveth_close(struct net_device *netdev) 6969aa32835SJeff Kirsher { 6979aa32835SJeff Kirsher struct ibmveth_adapter *adapter = netdev_priv(netdev); 6989aa32835SJeff Kirsher long lpar_rc; 6999aa32835SJeff Kirsher 7009aa32835SJeff Kirsher netdev_dbg(netdev, "close starting\n"); 7019aa32835SJeff Kirsher 7029aa32835SJeff Kirsher napi_disable(&adapter->napi); 7039aa32835SJeff Kirsher 7049aa32835SJeff Kirsher if (!adapter->pool_config) 7059aa32835SJeff Kirsher netif_stop_queue(netdev); 7069aa32835SJeff Kirsher 7079aa32835SJeff Kirsher h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_DISABLE); 7089aa32835SJeff Kirsher 7099aa32835SJeff Kirsher do { 7109aa32835SJeff Kirsher lpar_rc = h_free_logical_lan(adapter->vdev->unit_address); 7119aa32835SJeff Kirsher } while (H_IS_LONG_BUSY(lpar_rc) || (lpar_rc == H_BUSY)); 7129aa32835SJeff Kirsher 7139aa32835SJeff Kirsher if (lpar_rc != H_SUCCESS) { 7149aa32835SJeff Kirsher netdev_err(netdev, "h_free_logical_lan failed with %lx, " 7159aa32835SJeff Kirsher "continuing with close\n", lpar_rc); 7169aa32835SJeff Kirsher } 7179aa32835SJeff Kirsher 7189aa32835SJeff Kirsher free_irq(netdev->irq, netdev); 7199aa32835SJeff Kirsher 720cbd52281SAnton Blanchard ibmveth_update_rx_no_buffer(adapter); 7219aa32835SJeff Kirsher 7229aa32835SJeff Kirsher ibmveth_cleanup(adapter); 7239aa32835SJeff Kirsher 7249aa32835SJeff Kirsher netdev_dbg(netdev, "close complete\n"); 7259aa32835SJeff Kirsher 7269aa32835SJeff Kirsher return 0; 7279aa32835SJeff Kirsher } 7289aa32835SJeff Kirsher 7299aa32835SJeff Kirsher static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) 7309aa32835SJeff Kirsher { 7319aa32835SJeff Kirsher cmd->supported = (SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | 7329aa32835SJeff Kirsher SUPPORTED_FIBRE); 7339aa32835SJeff Kirsher cmd->advertising = (ADVERTISED_1000baseT_Full | ADVERTISED_Autoneg | 7349aa32835SJeff Kirsher ADVERTISED_FIBRE); 7359aa32835SJeff Kirsher ethtool_cmd_speed_set(cmd, SPEED_1000); 7369aa32835SJeff Kirsher cmd->duplex = DUPLEX_FULL; 7379aa32835SJeff Kirsher cmd->port = PORT_FIBRE; 7389aa32835SJeff Kirsher cmd->phy_address = 0; 7399aa32835SJeff Kirsher cmd->transceiver = XCVR_INTERNAL; 7409aa32835SJeff Kirsher cmd->autoneg = AUTONEG_ENABLE; 7419aa32835SJeff Kirsher cmd->maxtxpkt = 0; 7429aa32835SJeff Kirsher cmd->maxrxpkt = 1; 7439aa32835SJeff Kirsher return 0; 7449aa32835SJeff Kirsher } 7459aa32835SJeff Kirsher 7469aa32835SJeff Kirsher static void netdev_get_drvinfo(struct net_device *dev, 7479aa32835SJeff Kirsher struct ethtool_drvinfo *info) 7489aa32835SJeff Kirsher { 7497826d43fSJiri Pirko strlcpy(info->driver, ibmveth_driver_name, sizeof(info->driver)); 7507826d43fSJiri Pirko strlcpy(info->version, ibmveth_driver_version, sizeof(info->version)); 7519aa32835SJeff Kirsher } 7529aa32835SJeff Kirsher 753c8f44affSMichał Mirosław static netdev_features_t ibmveth_fix_features(struct net_device *dev, 754c8f44affSMichał Mirosław netdev_features_t features) 7559aa32835SJeff Kirsher { 7569aa32835SJeff Kirsher /* 7579aa32835SJeff Kirsher * Since the ibmveth firmware interface does not have the 7589aa32835SJeff Kirsher * concept of separate tx/rx checksum offload enable, if rx 7599aa32835SJeff Kirsher * checksum is disabled we also have to disable tx checksum 7609aa32835SJeff Kirsher * offload. Once we disable rx checksum offload, we are no 7619aa32835SJeff Kirsher * longer allowed to send tx buffers that are not properly 7629aa32835SJeff Kirsher * checksummed. 7639aa32835SJeff Kirsher */ 7649aa32835SJeff Kirsher 7659aa32835SJeff Kirsher if (!(features & NETIF_F_RXCSUM)) 7669aa32835SJeff Kirsher features &= ~NETIF_F_ALL_CSUM; 7679aa32835SJeff Kirsher 7689aa32835SJeff Kirsher return features; 7699aa32835SJeff Kirsher } 7709aa32835SJeff Kirsher 7719aa32835SJeff Kirsher static int ibmveth_set_csum_offload(struct net_device *dev, u32 data) 7729aa32835SJeff Kirsher { 7739aa32835SJeff Kirsher struct ibmveth_adapter *adapter = netdev_priv(dev); 7749aa32835SJeff Kirsher unsigned long set_attr, clr_attr, ret_attr; 7759aa32835SJeff Kirsher unsigned long set_attr6, clr_attr6; 7768decf868SDavid S. Miller long ret, ret4, ret6; 7779aa32835SJeff Kirsher int rc1 = 0, rc2 = 0; 7789aa32835SJeff Kirsher int restart = 0; 7799aa32835SJeff Kirsher 7809aa32835SJeff Kirsher if (netif_running(dev)) { 7819aa32835SJeff Kirsher restart = 1; 7829aa32835SJeff Kirsher adapter->pool_config = 1; 7839aa32835SJeff Kirsher ibmveth_close(dev); 7849aa32835SJeff Kirsher adapter->pool_config = 0; 7859aa32835SJeff Kirsher } 7869aa32835SJeff Kirsher 7879aa32835SJeff Kirsher set_attr = 0; 7889aa32835SJeff Kirsher clr_attr = 0; 7898decf868SDavid S. Miller set_attr6 = 0; 7908decf868SDavid S. Miller clr_attr6 = 0; 7919aa32835SJeff Kirsher 7929aa32835SJeff Kirsher if (data) { 7939aa32835SJeff Kirsher set_attr = IBMVETH_ILLAN_IPV4_TCP_CSUM; 7949aa32835SJeff Kirsher set_attr6 = IBMVETH_ILLAN_IPV6_TCP_CSUM; 7959aa32835SJeff Kirsher } else { 7969aa32835SJeff Kirsher clr_attr = IBMVETH_ILLAN_IPV4_TCP_CSUM; 7979aa32835SJeff Kirsher clr_attr6 = IBMVETH_ILLAN_IPV6_TCP_CSUM; 7989aa32835SJeff Kirsher } 7999aa32835SJeff Kirsher 8009aa32835SJeff Kirsher ret = h_illan_attributes(adapter->vdev->unit_address, 0, 0, &ret_attr); 8019aa32835SJeff Kirsher 8029aa32835SJeff Kirsher if (ret == H_SUCCESS && !(ret_attr & IBMVETH_ILLAN_ACTIVE_TRUNK) && 8039aa32835SJeff Kirsher !(ret_attr & IBMVETH_ILLAN_TRUNK_PRI_MASK) && 8049aa32835SJeff Kirsher (ret_attr & IBMVETH_ILLAN_PADDED_PKT_CSUM)) { 8058decf868SDavid S. Miller ret4 = h_illan_attributes(adapter->vdev->unit_address, clr_attr, 8069aa32835SJeff Kirsher set_attr, &ret_attr); 8079aa32835SJeff Kirsher 8088decf868SDavid S. Miller if (ret4 != H_SUCCESS) { 8099aa32835SJeff Kirsher netdev_err(dev, "unable to change IPv4 checksum " 8109aa32835SJeff Kirsher "offload settings. %d rc=%ld\n", 8118decf868SDavid S. Miller data, ret4); 8129aa32835SJeff Kirsher 8138decf868SDavid S. Miller h_illan_attributes(adapter->vdev->unit_address, 8149aa32835SJeff Kirsher set_attr, clr_attr, &ret_attr); 8158decf868SDavid S. Miller 8168decf868SDavid S. Miller if (data == 1) 8178decf868SDavid S. Miller dev->features &= ~NETIF_F_IP_CSUM; 8188decf868SDavid S. Miller 8199aa32835SJeff Kirsher } else { 8209aa32835SJeff Kirsher adapter->fw_ipv4_csum_support = data; 8219aa32835SJeff Kirsher } 8229aa32835SJeff Kirsher 8239aa32835SJeff Kirsher ret6 = h_illan_attributes(adapter->vdev->unit_address, 8249aa32835SJeff Kirsher clr_attr6, set_attr6, &ret_attr); 8259aa32835SJeff Kirsher 8269aa32835SJeff Kirsher if (ret6 != H_SUCCESS) { 8279aa32835SJeff Kirsher netdev_err(dev, "unable to change IPv6 checksum " 8289aa32835SJeff Kirsher "offload settings. %d rc=%ld\n", 8298decf868SDavid S. Miller data, ret6); 8309aa32835SJeff Kirsher 8318decf868SDavid S. Miller h_illan_attributes(adapter->vdev->unit_address, 8328decf868SDavid S. Miller set_attr6, clr_attr6, &ret_attr); 8338decf868SDavid S. Miller 8348decf868SDavid S. Miller if (data == 1) 8358decf868SDavid S. Miller dev->features &= ~NETIF_F_IPV6_CSUM; 8368decf868SDavid S. Miller 8379aa32835SJeff Kirsher } else 8389aa32835SJeff Kirsher adapter->fw_ipv6_csum_support = data; 8399aa32835SJeff Kirsher 8408decf868SDavid S. Miller if (ret4 == H_SUCCESS || ret6 == H_SUCCESS) 8419aa32835SJeff Kirsher adapter->rx_csum = data; 8429aa32835SJeff Kirsher else 8439aa32835SJeff Kirsher rc1 = -EIO; 8449aa32835SJeff Kirsher } else { 8459aa32835SJeff Kirsher rc1 = -EIO; 8469aa32835SJeff Kirsher netdev_err(dev, "unable to change checksum offload settings." 8479aa32835SJeff Kirsher " %d rc=%ld ret_attr=%lx\n", data, ret, 8489aa32835SJeff Kirsher ret_attr); 8499aa32835SJeff Kirsher } 8509aa32835SJeff Kirsher 8519aa32835SJeff Kirsher if (restart) 8529aa32835SJeff Kirsher rc2 = ibmveth_open(dev); 8539aa32835SJeff Kirsher 8549aa32835SJeff Kirsher return rc1 ? rc1 : rc2; 8559aa32835SJeff Kirsher } 8569aa32835SJeff Kirsher 857*07e6a97dSThomas Falcon static int ibmveth_set_tso(struct net_device *dev, u32 data) 858*07e6a97dSThomas Falcon { 859*07e6a97dSThomas Falcon struct ibmveth_adapter *adapter = netdev_priv(dev); 860*07e6a97dSThomas Falcon unsigned long set_attr, clr_attr, ret_attr; 861*07e6a97dSThomas Falcon long ret1, ret2; 862*07e6a97dSThomas Falcon int rc1 = 0, rc2 = 0; 863*07e6a97dSThomas Falcon int restart = 0; 864*07e6a97dSThomas Falcon 865*07e6a97dSThomas Falcon if (netif_running(dev)) { 866*07e6a97dSThomas Falcon restart = 1; 867*07e6a97dSThomas Falcon adapter->pool_config = 1; 868*07e6a97dSThomas Falcon ibmveth_close(dev); 869*07e6a97dSThomas Falcon adapter->pool_config = 0; 870*07e6a97dSThomas Falcon } 871*07e6a97dSThomas Falcon 872*07e6a97dSThomas Falcon set_attr = 0; 873*07e6a97dSThomas Falcon clr_attr = 0; 874*07e6a97dSThomas Falcon 875*07e6a97dSThomas Falcon if (data) 876*07e6a97dSThomas Falcon set_attr = IBMVETH_ILLAN_LRG_SR_ENABLED; 877*07e6a97dSThomas Falcon else 878*07e6a97dSThomas Falcon clr_attr = IBMVETH_ILLAN_LRG_SR_ENABLED; 879*07e6a97dSThomas Falcon 880*07e6a97dSThomas Falcon ret1 = h_illan_attributes(adapter->vdev->unit_address, 0, 0, &ret_attr); 881*07e6a97dSThomas Falcon 882*07e6a97dSThomas Falcon if (ret1 == H_SUCCESS && (ret_attr & IBMVETH_ILLAN_LRG_SND_SUPPORT) && 883*07e6a97dSThomas Falcon !old_large_send) { 884*07e6a97dSThomas Falcon ret2 = h_illan_attributes(adapter->vdev->unit_address, clr_attr, 885*07e6a97dSThomas Falcon set_attr, &ret_attr); 886*07e6a97dSThomas Falcon 887*07e6a97dSThomas Falcon if (ret2 != H_SUCCESS) { 888*07e6a97dSThomas Falcon netdev_err(dev, "unable to change tso settings. %d rc=%ld\n", 889*07e6a97dSThomas Falcon data, ret2); 890*07e6a97dSThomas Falcon 891*07e6a97dSThomas Falcon h_illan_attributes(adapter->vdev->unit_address, 892*07e6a97dSThomas Falcon set_attr, clr_attr, &ret_attr); 893*07e6a97dSThomas Falcon 894*07e6a97dSThomas Falcon if (data == 1) 895*07e6a97dSThomas Falcon dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6); 896*07e6a97dSThomas Falcon rc1 = -EIO; 897*07e6a97dSThomas Falcon 898*07e6a97dSThomas Falcon } else { 899*07e6a97dSThomas Falcon adapter->fw_large_send_support = data; 900*07e6a97dSThomas Falcon adapter->large_send = data; 901*07e6a97dSThomas Falcon } 902*07e6a97dSThomas Falcon } else { 903*07e6a97dSThomas Falcon /* Older firmware version of large send offload does not 904*07e6a97dSThomas Falcon * support tcp6/ipv6 905*07e6a97dSThomas Falcon */ 906*07e6a97dSThomas Falcon if (data == 1) { 907*07e6a97dSThomas Falcon dev->features &= ~NETIF_F_TSO6; 908*07e6a97dSThomas Falcon netdev_info(dev, "TSO feature requires all partitions to have updated driver"); 909*07e6a97dSThomas Falcon } 910*07e6a97dSThomas Falcon adapter->large_send = data; 911*07e6a97dSThomas Falcon } 912*07e6a97dSThomas Falcon 913*07e6a97dSThomas Falcon if (restart) 914*07e6a97dSThomas Falcon rc2 = ibmveth_open(dev); 915*07e6a97dSThomas Falcon 916*07e6a97dSThomas Falcon return rc1 ? rc1 : rc2; 917*07e6a97dSThomas Falcon } 918*07e6a97dSThomas Falcon 919c8f44affSMichał Mirosław static int ibmveth_set_features(struct net_device *dev, 920c8f44affSMichał Mirosław netdev_features_t features) 9219aa32835SJeff Kirsher { 9229aa32835SJeff Kirsher struct ibmveth_adapter *adapter = netdev_priv(dev); 9239aa32835SJeff Kirsher int rx_csum = !!(features & NETIF_F_RXCSUM); 924*07e6a97dSThomas Falcon int large_send = !!(features & (NETIF_F_TSO | NETIF_F_TSO6)); 925*07e6a97dSThomas Falcon int rc1 = 0, rc2 = 0; 9268641dd85SThomas Falcon 927*07e6a97dSThomas Falcon if (rx_csum != adapter->rx_csum) { 928*07e6a97dSThomas Falcon rc1 = ibmveth_set_csum_offload(dev, rx_csum); 929*07e6a97dSThomas Falcon if (rc1 && !adapter->rx_csum) 930*07e6a97dSThomas Falcon dev->features = 931*07e6a97dSThomas Falcon features & ~(NETIF_F_ALL_CSUM | NETIF_F_RXCSUM); 932*07e6a97dSThomas Falcon } 9339aa32835SJeff Kirsher 934*07e6a97dSThomas Falcon if (large_send != adapter->large_send) { 935*07e6a97dSThomas Falcon rc2 = ibmveth_set_tso(dev, large_send); 936*07e6a97dSThomas Falcon if (rc2 && !adapter->large_send) 937*07e6a97dSThomas Falcon dev->features = 938*07e6a97dSThomas Falcon features & ~(NETIF_F_TSO | NETIF_F_TSO6); 939*07e6a97dSThomas Falcon } 9409aa32835SJeff Kirsher 941*07e6a97dSThomas Falcon return rc1 ? rc1 : rc2; 9429aa32835SJeff Kirsher } 9439aa32835SJeff Kirsher 9449aa32835SJeff Kirsher static void ibmveth_get_strings(struct net_device *dev, u32 stringset, u8 *data) 9459aa32835SJeff Kirsher { 9469aa32835SJeff Kirsher int i; 9479aa32835SJeff Kirsher 9489aa32835SJeff Kirsher if (stringset != ETH_SS_STATS) 9499aa32835SJeff Kirsher return; 9509aa32835SJeff Kirsher 9519aa32835SJeff Kirsher for (i = 0; i < ARRAY_SIZE(ibmveth_stats); i++, data += ETH_GSTRING_LEN) 9529aa32835SJeff Kirsher memcpy(data, ibmveth_stats[i].name, ETH_GSTRING_LEN); 9539aa32835SJeff Kirsher } 9549aa32835SJeff Kirsher 9559aa32835SJeff Kirsher static int ibmveth_get_sset_count(struct net_device *dev, int sset) 9569aa32835SJeff Kirsher { 9579aa32835SJeff Kirsher switch (sset) { 9589aa32835SJeff Kirsher case ETH_SS_STATS: 9599aa32835SJeff Kirsher return ARRAY_SIZE(ibmveth_stats); 9609aa32835SJeff Kirsher default: 9619aa32835SJeff Kirsher return -EOPNOTSUPP; 9629aa32835SJeff Kirsher } 9639aa32835SJeff Kirsher } 9649aa32835SJeff Kirsher 9659aa32835SJeff Kirsher static void ibmveth_get_ethtool_stats(struct net_device *dev, 9669aa32835SJeff Kirsher struct ethtool_stats *stats, u64 *data) 9679aa32835SJeff Kirsher { 9689aa32835SJeff Kirsher int i; 9699aa32835SJeff Kirsher struct ibmveth_adapter *adapter = netdev_priv(dev); 9709aa32835SJeff Kirsher 9719aa32835SJeff Kirsher for (i = 0; i < ARRAY_SIZE(ibmveth_stats); i++) 9729aa32835SJeff Kirsher data[i] = IBMVETH_GET_STAT(adapter, ibmveth_stats[i].offset); 9739aa32835SJeff Kirsher } 9749aa32835SJeff Kirsher 9759aa32835SJeff Kirsher static const struct ethtool_ops netdev_ethtool_ops = { 9769aa32835SJeff Kirsher .get_drvinfo = netdev_get_drvinfo, 9779aa32835SJeff Kirsher .get_settings = netdev_get_settings, 9789aa32835SJeff Kirsher .get_link = ethtool_op_get_link, 9799aa32835SJeff Kirsher .get_strings = ibmveth_get_strings, 9809aa32835SJeff Kirsher .get_sset_count = ibmveth_get_sset_count, 9819aa32835SJeff Kirsher .get_ethtool_stats = ibmveth_get_ethtool_stats, 9829aa32835SJeff Kirsher }; 9839aa32835SJeff Kirsher 9849aa32835SJeff Kirsher static int ibmveth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) 9859aa32835SJeff Kirsher { 9869aa32835SJeff Kirsher return -EOPNOTSUPP; 9879aa32835SJeff Kirsher } 9889aa32835SJeff Kirsher 9899aa32835SJeff Kirsher #define page_offset(v) ((unsigned long)(v) & ((1 << 12) - 1)) 9909aa32835SJeff Kirsher 9919aa32835SJeff Kirsher static int ibmveth_send(struct ibmveth_adapter *adapter, 992*07e6a97dSThomas Falcon union ibmveth_buf_desc *descs, unsigned long mss) 9939aa32835SJeff Kirsher { 9949aa32835SJeff Kirsher unsigned long correlator; 9959aa32835SJeff Kirsher unsigned int retry_count; 9969aa32835SJeff Kirsher unsigned long ret; 9979aa32835SJeff Kirsher 9989aa32835SJeff Kirsher /* 9999aa32835SJeff Kirsher * The retry count sets a maximum for the number of broadcast and 10009aa32835SJeff Kirsher * multicast destinations within the system. 10019aa32835SJeff Kirsher */ 10029aa32835SJeff Kirsher retry_count = 1024; 10039aa32835SJeff Kirsher correlator = 0; 10049aa32835SJeff Kirsher do { 10059aa32835SJeff Kirsher ret = h_send_logical_lan(adapter->vdev->unit_address, 10069aa32835SJeff Kirsher descs[0].desc, descs[1].desc, 10079aa32835SJeff Kirsher descs[2].desc, descs[3].desc, 10089aa32835SJeff Kirsher descs[4].desc, descs[5].desc, 1009*07e6a97dSThomas Falcon correlator, &correlator, mss, 1010*07e6a97dSThomas Falcon adapter->fw_large_send_support); 10119aa32835SJeff Kirsher } while ((ret == H_BUSY) && (retry_count--)); 10129aa32835SJeff Kirsher 10139aa32835SJeff Kirsher if (ret != H_SUCCESS && ret != H_DROPPED) { 10149aa32835SJeff Kirsher netdev_err(adapter->netdev, "tx: h_send_logical_lan failed " 10159aa32835SJeff Kirsher "with rc=%ld\n", ret); 10169aa32835SJeff Kirsher return 1; 10179aa32835SJeff Kirsher } 10189aa32835SJeff Kirsher 10199aa32835SJeff Kirsher return 0; 10209aa32835SJeff Kirsher } 10219aa32835SJeff Kirsher 10229aa32835SJeff Kirsher static netdev_tx_t ibmveth_start_xmit(struct sk_buff *skb, 10239aa32835SJeff Kirsher struct net_device *netdev) 10249aa32835SJeff Kirsher { 10259aa32835SJeff Kirsher struct ibmveth_adapter *adapter = netdev_priv(netdev); 10269aa32835SJeff Kirsher unsigned int desc_flags; 10279aa32835SJeff Kirsher union ibmveth_buf_desc descs[6]; 10289aa32835SJeff Kirsher int last, i; 10299aa32835SJeff Kirsher int force_bounce = 0; 10308decf868SDavid S. Miller dma_addr_t dma_addr; 1031*07e6a97dSThomas Falcon unsigned long mss = 0; 10329aa32835SJeff Kirsher 10339aa32835SJeff Kirsher /* 10349aa32835SJeff Kirsher * veth handles a maximum of 6 segments including the header, so 10359aa32835SJeff Kirsher * we have to linearize the skb if there are more than this. 10369aa32835SJeff Kirsher */ 10379aa32835SJeff Kirsher if (skb_shinfo(skb)->nr_frags > 5 && __skb_linearize(skb)) { 10389aa32835SJeff Kirsher netdev->stats.tx_dropped++; 10399aa32835SJeff Kirsher goto out; 10409aa32835SJeff Kirsher } 10419aa32835SJeff Kirsher 10429aa32835SJeff Kirsher /* veth can't checksum offload UDP */ 10439aa32835SJeff Kirsher if (skb->ip_summed == CHECKSUM_PARTIAL && 10449aa32835SJeff Kirsher ((skb->protocol == htons(ETH_P_IP) && 10459aa32835SJeff Kirsher ip_hdr(skb)->protocol != IPPROTO_TCP) || 10469aa32835SJeff Kirsher (skb->protocol == htons(ETH_P_IPV6) && 10479aa32835SJeff Kirsher ipv6_hdr(skb)->nexthdr != IPPROTO_TCP)) && 10489aa32835SJeff Kirsher skb_checksum_help(skb)) { 10499aa32835SJeff Kirsher 10509aa32835SJeff Kirsher netdev_err(netdev, "tx: failed to checksum packet\n"); 10519aa32835SJeff Kirsher netdev->stats.tx_dropped++; 10529aa32835SJeff Kirsher goto out; 10539aa32835SJeff Kirsher } 10549aa32835SJeff Kirsher 10559aa32835SJeff Kirsher desc_flags = IBMVETH_BUF_VALID; 10569aa32835SJeff Kirsher 1057*07e6a97dSThomas Falcon if (skb_is_gso(skb) && adapter->fw_large_send_support) 1058*07e6a97dSThomas Falcon desc_flags |= IBMVETH_BUF_LRG_SND; 1059*07e6a97dSThomas Falcon 10609aa32835SJeff Kirsher if (skb->ip_summed == CHECKSUM_PARTIAL) { 10619aa32835SJeff Kirsher unsigned char *buf = skb_transport_header(skb) + 10629aa32835SJeff Kirsher skb->csum_offset; 10639aa32835SJeff Kirsher 10649aa32835SJeff Kirsher desc_flags |= (IBMVETH_BUF_NO_CSUM | IBMVETH_BUF_CSUM_GOOD); 10659aa32835SJeff Kirsher 10669aa32835SJeff Kirsher /* Need to zero out the checksum */ 10679aa32835SJeff Kirsher buf[0] = 0; 10689aa32835SJeff Kirsher buf[1] = 0; 10699aa32835SJeff Kirsher } 10709aa32835SJeff Kirsher 10719aa32835SJeff Kirsher retry_bounce: 10729aa32835SJeff Kirsher memset(descs, 0, sizeof(descs)); 10739aa32835SJeff Kirsher 10749aa32835SJeff Kirsher /* 10759aa32835SJeff Kirsher * If a linear packet is below the rx threshold then 10769aa32835SJeff Kirsher * copy it into the static bounce buffer. This avoids the 10779aa32835SJeff Kirsher * cost of a TCE insert and remove. 10789aa32835SJeff Kirsher */ 10799aa32835SJeff Kirsher if (force_bounce || (!skb_is_nonlinear(skb) && 10809aa32835SJeff Kirsher (skb->len < tx_copybreak))) { 10819aa32835SJeff Kirsher skb_copy_from_linear_data(skb, adapter->bounce_buffer, 10829aa32835SJeff Kirsher skb->len); 10839aa32835SJeff Kirsher 10849aa32835SJeff Kirsher descs[0].fields.flags_len = desc_flags | skb->len; 10859aa32835SJeff Kirsher descs[0].fields.address = adapter->bounce_buffer_dma; 10869aa32835SJeff Kirsher 1087*07e6a97dSThomas Falcon if (ibmveth_send(adapter, descs, 0)) { 10889aa32835SJeff Kirsher adapter->tx_send_failed++; 10899aa32835SJeff Kirsher netdev->stats.tx_dropped++; 10909aa32835SJeff Kirsher } else { 10919aa32835SJeff Kirsher netdev->stats.tx_packets++; 10929aa32835SJeff Kirsher netdev->stats.tx_bytes += skb->len; 10939aa32835SJeff Kirsher } 10949aa32835SJeff Kirsher 10959aa32835SJeff Kirsher goto out; 10969aa32835SJeff Kirsher } 10979aa32835SJeff Kirsher 10989aa32835SJeff Kirsher /* Map the header */ 10998decf868SDavid S. Miller dma_addr = dma_map_single(&adapter->vdev->dev, skb->data, 11008decf868SDavid S. Miller skb_headlen(skb), DMA_TO_DEVICE); 11018decf868SDavid S. Miller if (dma_mapping_error(&adapter->vdev->dev, dma_addr)) 11029aa32835SJeff Kirsher goto map_failed; 11039aa32835SJeff Kirsher 11049aa32835SJeff Kirsher descs[0].fields.flags_len = desc_flags | skb_headlen(skb); 11058decf868SDavid S. Miller descs[0].fields.address = dma_addr; 11069aa32835SJeff Kirsher 11079aa32835SJeff Kirsher /* Map the frags */ 11089aa32835SJeff Kirsher for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 11099e903e08SEric Dumazet const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 11109aa32835SJeff Kirsher 11118838a538SIan Campbell dma_addr = skb_frag_dma_map(&adapter->vdev->dev, frag, 0, 11129e903e08SEric Dumazet skb_frag_size(frag), DMA_TO_DEVICE); 11139aa32835SJeff Kirsher 11149aa32835SJeff Kirsher if (dma_mapping_error(&adapter->vdev->dev, dma_addr)) 11159aa32835SJeff Kirsher goto map_failed_frags; 11169aa32835SJeff Kirsher 11179e903e08SEric Dumazet descs[i+1].fields.flags_len = desc_flags | skb_frag_size(frag); 11189aa32835SJeff Kirsher descs[i+1].fields.address = dma_addr; 11199aa32835SJeff Kirsher } 11209aa32835SJeff Kirsher 1121*07e6a97dSThomas Falcon if (skb_is_gso(skb)) { 1122*07e6a97dSThomas Falcon if (adapter->fw_large_send_support) { 1123*07e6a97dSThomas Falcon mss = (unsigned long)skb_shinfo(skb)->gso_size; 1124*07e6a97dSThomas Falcon adapter->tx_large_packets++; 1125*07e6a97dSThomas Falcon } else if (!skb_is_gso_v6(skb)) { 11268641dd85SThomas Falcon /* Put -1 in the IP checksum to tell phyp it 1127*07e6a97dSThomas Falcon * is a largesend packet. Put the mss in 1128*07e6a97dSThomas Falcon * the TCP checksum. 11298641dd85SThomas Falcon */ 11308641dd85SThomas Falcon ip_hdr(skb)->check = 0xffff; 1131*07e6a97dSThomas Falcon tcp_hdr(skb)->check = 1132*07e6a97dSThomas Falcon cpu_to_be16(skb_shinfo(skb)->gso_size); 11338641dd85SThomas Falcon adapter->tx_large_packets++; 11348641dd85SThomas Falcon } 1135*07e6a97dSThomas Falcon } 11368641dd85SThomas Falcon 1137*07e6a97dSThomas Falcon if (ibmveth_send(adapter, descs, mss)) { 11389aa32835SJeff Kirsher adapter->tx_send_failed++; 11399aa32835SJeff Kirsher netdev->stats.tx_dropped++; 11409aa32835SJeff Kirsher } else { 11419aa32835SJeff Kirsher netdev->stats.tx_packets++; 11429aa32835SJeff Kirsher netdev->stats.tx_bytes += skb->len; 11439aa32835SJeff Kirsher } 11449aa32835SJeff Kirsher 11458decf868SDavid S. Miller dma_unmap_single(&adapter->vdev->dev, 11468decf868SDavid S. Miller descs[0].fields.address, 11478decf868SDavid S. Miller descs[0].fields.flags_len & IBMVETH_BUF_LEN_MASK, 11488decf868SDavid S. Miller DMA_TO_DEVICE); 11498decf868SDavid S. Miller 11508decf868SDavid S. Miller for (i = 1; i < skb_shinfo(skb)->nr_frags + 1; i++) 11519aa32835SJeff Kirsher dma_unmap_page(&adapter->vdev->dev, descs[i].fields.address, 11529aa32835SJeff Kirsher descs[i].fields.flags_len & IBMVETH_BUF_LEN_MASK, 11539aa32835SJeff Kirsher DMA_TO_DEVICE); 11549aa32835SJeff Kirsher 11559aa32835SJeff Kirsher out: 115626faa9d7SEric W. Biederman dev_consume_skb_any(skb); 11579aa32835SJeff Kirsher return NETDEV_TX_OK; 11589aa32835SJeff Kirsher 11599aa32835SJeff Kirsher map_failed_frags: 11609aa32835SJeff Kirsher last = i+1; 11619aa32835SJeff Kirsher for (i = 0; i < last; i++) 11629aa32835SJeff Kirsher dma_unmap_page(&adapter->vdev->dev, descs[i].fields.address, 11639aa32835SJeff Kirsher descs[i].fields.flags_len & IBMVETH_BUF_LEN_MASK, 11649aa32835SJeff Kirsher DMA_TO_DEVICE); 11659aa32835SJeff Kirsher 11669aa32835SJeff Kirsher map_failed: 11679aa32835SJeff Kirsher if (!firmware_has_feature(FW_FEATURE_CMO)) 11689aa32835SJeff Kirsher netdev_err(netdev, "tx: unable to map xmit buffer\n"); 11699aa32835SJeff Kirsher adapter->tx_map_failed++; 11709aa32835SJeff Kirsher skb_linearize(skb); 11719aa32835SJeff Kirsher force_bounce = 1; 11729aa32835SJeff Kirsher goto retry_bounce; 11739aa32835SJeff Kirsher } 11749aa32835SJeff Kirsher 11759aa32835SJeff Kirsher static int ibmveth_poll(struct napi_struct *napi, int budget) 11769aa32835SJeff Kirsher { 11779aa32835SJeff Kirsher struct ibmveth_adapter *adapter = 11789aa32835SJeff Kirsher container_of(napi, struct ibmveth_adapter, napi); 11799aa32835SJeff Kirsher struct net_device *netdev = adapter->netdev; 11809aa32835SJeff Kirsher int frames_processed = 0; 11819aa32835SJeff Kirsher unsigned long lpar_rc; 11829c7e8bc5SThomas Falcon struct iphdr *iph; 11839aa32835SJeff Kirsher 11849aa32835SJeff Kirsher restart_poll: 1185cb013ea1SEric W. Biederman while (frames_processed < budget) { 11869aa32835SJeff Kirsher if (!ibmveth_rxq_pending_buffer(adapter)) 11879aa32835SJeff Kirsher break; 11889aa32835SJeff Kirsher 11899aa32835SJeff Kirsher smp_rmb(); 11909aa32835SJeff Kirsher if (!ibmveth_rxq_buffer_valid(adapter)) { 11919aa32835SJeff Kirsher wmb(); /* suggested by larson1 */ 11929aa32835SJeff Kirsher adapter->rx_invalid_buffer++; 11939aa32835SJeff Kirsher netdev_dbg(netdev, "recycling invalid buffer\n"); 11949aa32835SJeff Kirsher ibmveth_rxq_recycle_buffer(adapter); 11959aa32835SJeff Kirsher } else { 11969aa32835SJeff Kirsher struct sk_buff *skb, *new_skb; 11979aa32835SJeff Kirsher int length = ibmveth_rxq_frame_length(adapter); 11989aa32835SJeff Kirsher int offset = ibmveth_rxq_frame_offset(adapter); 11999aa32835SJeff Kirsher int csum_good = ibmveth_rxq_csum_good(adapter); 12009aa32835SJeff Kirsher 12019aa32835SJeff Kirsher skb = ibmveth_rxq_get_buffer(adapter); 12029aa32835SJeff Kirsher 12039aa32835SJeff Kirsher new_skb = NULL; 12049aa32835SJeff Kirsher if (length < rx_copybreak) 12059aa32835SJeff Kirsher new_skb = netdev_alloc_skb(netdev, length); 12069aa32835SJeff Kirsher 12079aa32835SJeff Kirsher if (new_skb) { 12089aa32835SJeff Kirsher skb_copy_to_linear_data(new_skb, 12099aa32835SJeff Kirsher skb->data + offset, 12109aa32835SJeff Kirsher length); 12119aa32835SJeff Kirsher if (rx_flush) 12129aa32835SJeff Kirsher ibmveth_flush_buffer(skb->data, 12139aa32835SJeff Kirsher length + offset); 12148decf868SDavid S. Miller if (!ibmveth_rxq_recycle_buffer(adapter)) 12158decf868SDavid S. Miller kfree_skb(skb); 12169aa32835SJeff Kirsher skb = new_skb; 12179aa32835SJeff Kirsher } else { 12189aa32835SJeff Kirsher ibmveth_rxq_harvest_buffer(adapter); 12199aa32835SJeff Kirsher skb_reserve(skb, offset); 12209aa32835SJeff Kirsher } 12219aa32835SJeff Kirsher 12229aa32835SJeff Kirsher skb_put(skb, length); 12239aa32835SJeff Kirsher skb->protocol = eth_type_trans(skb, netdev); 12249aa32835SJeff Kirsher 12259c7e8bc5SThomas Falcon if (csum_good) { 12269aa32835SJeff Kirsher skb->ip_summed = CHECKSUM_UNNECESSARY; 12279c7e8bc5SThomas Falcon if (be16_to_cpu(skb->protocol) == ETH_P_IP) { 12289c7e8bc5SThomas Falcon iph = (struct iphdr *)skb->data; 12299c7e8bc5SThomas Falcon 12309c7e8bc5SThomas Falcon /* If the IP checksum is not offloaded and if the packet 12319c7e8bc5SThomas Falcon * is large send, the checksum must be rebuilt. 12329c7e8bc5SThomas Falcon */ 12339c7e8bc5SThomas Falcon if (iph->check == 0xffff) { 12349c7e8bc5SThomas Falcon iph->check = 0; 12359c7e8bc5SThomas Falcon iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); 12369c7e8bc5SThomas Falcon adapter->rx_large_packets++; 12379c7e8bc5SThomas Falcon } 12389c7e8bc5SThomas Falcon } 12399c7e8bc5SThomas Falcon } 12409aa32835SJeff Kirsher 124192ec8279SThomas Falcon napi_gro_receive(napi, skb); /* send it up */ 12429aa32835SJeff Kirsher 12439aa32835SJeff Kirsher netdev->stats.rx_packets++; 12449aa32835SJeff Kirsher netdev->stats.rx_bytes += length; 12459aa32835SJeff Kirsher frames_processed++; 12469aa32835SJeff Kirsher } 1247cb013ea1SEric W. Biederman } 12489aa32835SJeff Kirsher 12499aa32835SJeff Kirsher ibmveth_replenish_task(adapter); 12509aa32835SJeff Kirsher 12519aa32835SJeff Kirsher if (frames_processed < budget) { 12524736edc7SYongbae Park napi_complete(napi); 12534736edc7SYongbae Park 12549aa32835SJeff Kirsher /* We think we are done - reenable interrupts, 12559aa32835SJeff Kirsher * then check once more to make sure we are done. 12569aa32835SJeff Kirsher */ 12579aa32835SJeff Kirsher lpar_rc = h_vio_signal(adapter->vdev->unit_address, 12589aa32835SJeff Kirsher VIO_IRQ_ENABLE); 12599aa32835SJeff Kirsher 12609aa32835SJeff Kirsher BUG_ON(lpar_rc != H_SUCCESS); 12619aa32835SJeff Kirsher 12629aa32835SJeff Kirsher if (ibmveth_rxq_pending_buffer(adapter) && 12639aa32835SJeff Kirsher napi_reschedule(napi)) { 12649aa32835SJeff Kirsher lpar_rc = h_vio_signal(adapter->vdev->unit_address, 12659aa32835SJeff Kirsher VIO_IRQ_DISABLE); 12669aa32835SJeff Kirsher goto restart_poll; 12679aa32835SJeff Kirsher } 12689aa32835SJeff Kirsher } 12699aa32835SJeff Kirsher 12709aa32835SJeff Kirsher return frames_processed; 12719aa32835SJeff Kirsher } 12729aa32835SJeff Kirsher 12739aa32835SJeff Kirsher static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance) 12749aa32835SJeff Kirsher { 12759aa32835SJeff Kirsher struct net_device *netdev = dev_instance; 12769aa32835SJeff Kirsher struct ibmveth_adapter *adapter = netdev_priv(netdev); 12779aa32835SJeff Kirsher unsigned long lpar_rc; 12789aa32835SJeff Kirsher 12799aa32835SJeff Kirsher if (napi_schedule_prep(&adapter->napi)) { 12809aa32835SJeff Kirsher lpar_rc = h_vio_signal(adapter->vdev->unit_address, 12819aa32835SJeff Kirsher VIO_IRQ_DISABLE); 12829aa32835SJeff Kirsher BUG_ON(lpar_rc != H_SUCCESS); 12839aa32835SJeff Kirsher __napi_schedule(&adapter->napi); 12849aa32835SJeff Kirsher } 12859aa32835SJeff Kirsher return IRQ_HANDLED; 12869aa32835SJeff Kirsher } 12879aa32835SJeff Kirsher 12889aa32835SJeff Kirsher static void ibmveth_set_multicast_list(struct net_device *netdev) 12899aa32835SJeff Kirsher { 12909aa32835SJeff Kirsher struct ibmveth_adapter *adapter = netdev_priv(netdev); 12919aa32835SJeff Kirsher unsigned long lpar_rc; 12929aa32835SJeff Kirsher 12939aa32835SJeff Kirsher if ((netdev->flags & IFF_PROMISC) || 12949aa32835SJeff Kirsher (netdev_mc_count(netdev) > adapter->mcastFilterSize)) { 12959aa32835SJeff Kirsher lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address, 12969aa32835SJeff Kirsher IbmVethMcastEnableRecv | 12979aa32835SJeff Kirsher IbmVethMcastDisableFiltering, 12989aa32835SJeff Kirsher 0); 12999aa32835SJeff Kirsher if (lpar_rc != H_SUCCESS) { 13009aa32835SJeff Kirsher netdev_err(netdev, "h_multicast_ctrl rc=%ld when " 13019aa32835SJeff Kirsher "entering promisc mode\n", lpar_rc); 13029aa32835SJeff Kirsher } 13039aa32835SJeff Kirsher } else { 13049aa32835SJeff Kirsher struct netdev_hw_addr *ha; 13059aa32835SJeff Kirsher /* clear the filter table & disable filtering */ 13069aa32835SJeff Kirsher lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address, 13079aa32835SJeff Kirsher IbmVethMcastEnableRecv | 13089aa32835SJeff Kirsher IbmVethMcastDisableFiltering | 13099aa32835SJeff Kirsher IbmVethMcastClearFilterTable, 13109aa32835SJeff Kirsher 0); 13119aa32835SJeff Kirsher if (lpar_rc != H_SUCCESS) { 13129aa32835SJeff Kirsher netdev_err(netdev, "h_multicast_ctrl rc=%ld when " 13139aa32835SJeff Kirsher "attempting to clear filter table\n", 13149aa32835SJeff Kirsher lpar_rc); 13159aa32835SJeff Kirsher } 13169aa32835SJeff Kirsher /* add the addresses to the filter table */ 13179aa32835SJeff Kirsher netdev_for_each_mc_addr(ha, netdev) { 13189aa32835SJeff Kirsher /* add the multicast address to the filter table */ 1319d746ca95SAnton Blanchard u64 mcast_addr; 1320d746ca95SAnton Blanchard mcast_addr = ibmveth_encode_mac_addr(ha->addr); 13219aa32835SJeff Kirsher lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address, 13229aa32835SJeff Kirsher IbmVethMcastAddFilter, 13239aa32835SJeff Kirsher mcast_addr); 13249aa32835SJeff Kirsher if (lpar_rc != H_SUCCESS) { 13259aa32835SJeff Kirsher netdev_err(netdev, "h_multicast_ctrl rc=%ld " 13269aa32835SJeff Kirsher "when adding an entry to the filter " 13279aa32835SJeff Kirsher "table\n", lpar_rc); 13289aa32835SJeff Kirsher } 13299aa32835SJeff Kirsher } 13309aa32835SJeff Kirsher 13319aa32835SJeff Kirsher /* re-enable filtering */ 13329aa32835SJeff Kirsher lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address, 13339aa32835SJeff Kirsher IbmVethMcastEnableFiltering, 13349aa32835SJeff Kirsher 0); 13359aa32835SJeff Kirsher if (lpar_rc != H_SUCCESS) { 13369aa32835SJeff Kirsher netdev_err(netdev, "h_multicast_ctrl rc=%ld when " 13379aa32835SJeff Kirsher "enabling filtering\n", lpar_rc); 13389aa32835SJeff Kirsher } 13399aa32835SJeff Kirsher } 13409aa32835SJeff Kirsher } 13419aa32835SJeff Kirsher 13429aa32835SJeff Kirsher static int ibmveth_change_mtu(struct net_device *dev, int new_mtu) 13439aa32835SJeff Kirsher { 13449aa32835SJeff Kirsher struct ibmveth_adapter *adapter = netdev_priv(dev); 13459aa32835SJeff Kirsher struct vio_dev *viodev = adapter->vdev; 13469aa32835SJeff Kirsher int new_mtu_oh = new_mtu + IBMVETH_BUFF_OH; 13479aa32835SJeff Kirsher int i, rc; 13489aa32835SJeff Kirsher int need_restart = 0; 13499aa32835SJeff Kirsher 13509aa32835SJeff Kirsher if (new_mtu < IBMVETH_MIN_MTU) 13519aa32835SJeff Kirsher return -EINVAL; 13529aa32835SJeff Kirsher 13539aa32835SJeff Kirsher for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) 13544fce1482SDavid Gibson if (new_mtu_oh <= adapter->rx_buff_pool[i].buff_size) 13559aa32835SJeff Kirsher break; 13569aa32835SJeff Kirsher 13579aa32835SJeff Kirsher if (i == IBMVETH_NUM_BUFF_POOLS) 13589aa32835SJeff Kirsher return -EINVAL; 13599aa32835SJeff Kirsher 13609aa32835SJeff Kirsher /* Deactivate all the buffer pools so that the next loop can activate 13619aa32835SJeff Kirsher only the buffer pools necessary to hold the new MTU */ 13629aa32835SJeff Kirsher if (netif_running(adapter->netdev)) { 13639aa32835SJeff Kirsher need_restart = 1; 13649aa32835SJeff Kirsher adapter->pool_config = 1; 13659aa32835SJeff Kirsher ibmveth_close(adapter->netdev); 13669aa32835SJeff Kirsher adapter->pool_config = 0; 13679aa32835SJeff Kirsher } 13689aa32835SJeff Kirsher 13699aa32835SJeff Kirsher /* Look for an active buffer pool that can hold the new MTU */ 13709aa32835SJeff Kirsher for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) { 13719aa32835SJeff Kirsher adapter->rx_buff_pool[i].active = 1; 13729aa32835SJeff Kirsher 13734fce1482SDavid Gibson if (new_mtu_oh <= adapter->rx_buff_pool[i].buff_size) { 13749aa32835SJeff Kirsher dev->mtu = new_mtu; 13759aa32835SJeff Kirsher vio_cmo_set_dev_desired(viodev, 13769aa32835SJeff Kirsher ibmveth_get_desired_dma 13779aa32835SJeff Kirsher (viodev)); 13789aa32835SJeff Kirsher if (need_restart) { 13799aa32835SJeff Kirsher return ibmveth_open(adapter->netdev); 13809aa32835SJeff Kirsher } 13819aa32835SJeff Kirsher return 0; 13829aa32835SJeff Kirsher } 13839aa32835SJeff Kirsher } 13849aa32835SJeff Kirsher 13859aa32835SJeff Kirsher if (need_restart && (rc = ibmveth_open(adapter->netdev))) 13869aa32835SJeff Kirsher return rc; 13879aa32835SJeff Kirsher 13889aa32835SJeff Kirsher return -EINVAL; 13899aa32835SJeff Kirsher } 13909aa32835SJeff Kirsher 13919aa32835SJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER 13929aa32835SJeff Kirsher static void ibmveth_poll_controller(struct net_device *dev) 13939aa32835SJeff Kirsher { 13949aa32835SJeff Kirsher ibmveth_replenish_task(netdev_priv(dev)); 13959aa32835SJeff Kirsher ibmveth_interrupt(dev->irq, dev); 13969aa32835SJeff Kirsher } 13979aa32835SJeff Kirsher #endif 13989aa32835SJeff Kirsher 13999aa32835SJeff Kirsher /** 14009aa32835SJeff Kirsher * ibmveth_get_desired_dma - Calculate IO memory desired by the driver 14019aa32835SJeff Kirsher * 14029aa32835SJeff Kirsher * @vdev: struct vio_dev for the device whose desired IO mem is to be returned 14039aa32835SJeff Kirsher * 14049aa32835SJeff Kirsher * Return value: 14059aa32835SJeff Kirsher * Number of bytes of IO data the driver will need to perform well. 14069aa32835SJeff Kirsher */ 14079aa32835SJeff Kirsher static unsigned long ibmveth_get_desired_dma(struct vio_dev *vdev) 14089aa32835SJeff Kirsher { 14099aa32835SJeff Kirsher struct net_device *netdev = dev_get_drvdata(&vdev->dev); 14109aa32835SJeff Kirsher struct ibmveth_adapter *adapter; 1411d0847757SAlistair Popple struct iommu_table *tbl; 14129aa32835SJeff Kirsher unsigned long ret; 14139aa32835SJeff Kirsher int i; 14149aa32835SJeff Kirsher int rxqentries = 1; 14159aa32835SJeff Kirsher 1416d0847757SAlistair Popple tbl = get_iommu_table_base(&vdev->dev); 1417d0847757SAlistair Popple 14189aa32835SJeff Kirsher /* netdev inits at probe time along with the structures we need below*/ 14199aa32835SJeff Kirsher if (netdev == NULL) 1420d0847757SAlistair Popple return IOMMU_PAGE_ALIGN(IBMVETH_IO_ENTITLEMENT_DEFAULT, tbl); 14219aa32835SJeff Kirsher 14229aa32835SJeff Kirsher adapter = netdev_priv(netdev); 14239aa32835SJeff Kirsher 14249aa32835SJeff Kirsher ret = IBMVETH_BUFF_LIST_SIZE + IBMVETH_FILT_LIST_SIZE; 1425d0847757SAlistair Popple ret += IOMMU_PAGE_ALIGN(netdev->mtu, tbl); 14269aa32835SJeff Kirsher 14279aa32835SJeff Kirsher for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) { 14289aa32835SJeff Kirsher /* add the size of the active receive buffers */ 14299aa32835SJeff Kirsher if (adapter->rx_buff_pool[i].active) 14309aa32835SJeff Kirsher ret += 14319aa32835SJeff Kirsher adapter->rx_buff_pool[i].size * 14329aa32835SJeff Kirsher IOMMU_PAGE_ALIGN(adapter->rx_buff_pool[i]. 1433d0847757SAlistair Popple buff_size, tbl); 14349aa32835SJeff Kirsher rxqentries += adapter->rx_buff_pool[i].size; 14359aa32835SJeff Kirsher } 14369aa32835SJeff Kirsher /* add the size of the receive queue entries */ 1437d0847757SAlistair Popple ret += IOMMU_PAGE_ALIGN( 1438d0847757SAlistair Popple rxqentries * sizeof(struct ibmveth_rx_q_entry), tbl); 14399aa32835SJeff Kirsher 14409aa32835SJeff Kirsher return ret; 14419aa32835SJeff Kirsher } 14429aa32835SJeff Kirsher 1443c77c761fSThomas Falcon static int ibmveth_set_mac_addr(struct net_device *dev, void *p) 1444c77c761fSThomas Falcon { 1445c77c761fSThomas Falcon struct ibmveth_adapter *adapter = netdev_priv(dev); 1446c77c761fSThomas Falcon struct sockaddr *addr = p; 1447c77c761fSThomas Falcon u64 mac_address; 1448c77c761fSThomas Falcon int rc; 1449c77c761fSThomas Falcon 1450c77c761fSThomas Falcon if (!is_valid_ether_addr(addr->sa_data)) 1451c77c761fSThomas Falcon return -EADDRNOTAVAIL; 1452c77c761fSThomas Falcon 1453c77c761fSThomas Falcon mac_address = ibmveth_encode_mac_addr(addr->sa_data); 1454c77c761fSThomas Falcon rc = h_change_logical_lan_mac(adapter->vdev->unit_address, mac_address); 1455c77c761fSThomas Falcon if (rc) { 1456c77c761fSThomas Falcon netdev_err(adapter->netdev, "h_change_logical_lan_mac failed with rc=%d\n", rc); 1457c77c761fSThomas Falcon return rc; 1458c77c761fSThomas Falcon } 1459c77c761fSThomas Falcon 1460c77c761fSThomas Falcon ether_addr_copy(dev->dev_addr, addr->sa_data); 1461c77c761fSThomas Falcon 1462c77c761fSThomas Falcon return 0; 1463c77c761fSThomas Falcon } 1464c77c761fSThomas Falcon 14659aa32835SJeff Kirsher static const struct net_device_ops ibmveth_netdev_ops = { 14669aa32835SJeff Kirsher .ndo_open = ibmveth_open, 14679aa32835SJeff Kirsher .ndo_stop = ibmveth_close, 14689aa32835SJeff Kirsher .ndo_start_xmit = ibmveth_start_xmit, 1469afc4b13dSJiri Pirko .ndo_set_rx_mode = ibmveth_set_multicast_list, 14709aa32835SJeff Kirsher .ndo_do_ioctl = ibmveth_ioctl, 14719aa32835SJeff Kirsher .ndo_change_mtu = ibmveth_change_mtu, 14729aa32835SJeff Kirsher .ndo_fix_features = ibmveth_fix_features, 14739aa32835SJeff Kirsher .ndo_set_features = ibmveth_set_features, 14749aa32835SJeff Kirsher .ndo_validate_addr = eth_validate_addr, 1475c77c761fSThomas Falcon .ndo_set_mac_address = ibmveth_set_mac_addr, 14769aa32835SJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER 14779aa32835SJeff Kirsher .ndo_poll_controller = ibmveth_poll_controller, 14789aa32835SJeff Kirsher #endif 14799aa32835SJeff Kirsher }; 14809aa32835SJeff Kirsher 14811dd06ae8SGreg Kroah-Hartman static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id) 14829aa32835SJeff Kirsher { 148313f85203SBenjamin Herrenschmidt int rc, i, mac_len; 14849aa32835SJeff Kirsher struct net_device *netdev; 14859aa32835SJeff Kirsher struct ibmveth_adapter *adapter; 14869aa32835SJeff Kirsher unsigned char *mac_addr_p; 14879aa32835SJeff Kirsher unsigned int *mcastFilterSize_p; 1488*07e6a97dSThomas Falcon long ret; 1489*07e6a97dSThomas Falcon unsigned long ret_attr; 14909aa32835SJeff Kirsher 14919aa32835SJeff Kirsher dev_dbg(&dev->dev, "entering ibmveth_probe for UA 0x%x\n", 14929aa32835SJeff Kirsher dev->unit_address); 14939aa32835SJeff Kirsher 14949aa32835SJeff Kirsher mac_addr_p = (unsigned char *)vio_get_attribute(dev, VETH_MAC_ADDR, 149513f85203SBenjamin Herrenschmidt &mac_len); 14969aa32835SJeff Kirsher if (!mac_addr_p) { 14979aa32835SJeff Kirsher dev_err(&dev->dev, "Can't find VETH_MAC_ADDR attribute\n"); 14989aa32835SJeff Kirsher return -EINVAL; 14999aa32835SJeff Kirsher } 150013f85203SBenjamin Herrenschmidt /* Workaround for old/broken pHyp */ 150113f85203SBenjamin Herrenschmidt if (mac_len == 8) 150213f85203SBenjamin Herrenschmidt mac_addr_p += 2; 150313f85203SBenjamin Herrenschmidt else if (mac_len != 6) { 150413f85203SBenjamin Herrenschmidt dev_err(&dev->dev, "VETH_MAC_ADDR attribute wrong len %d\n", 150513f85203SBenjamin Herrenschmidt mac_len); 150613f85203SBenjamin Herrenschmidt return -EINVAL; 150713f85203SBenjamin Herrenschmidt } 15089aa32835SJeff Kirsher 15099aa32835SJeff Kirsher mcastFilterSize_p = (unsigned int *)vio_get_attribute(dev, 15109aa32835SJeff Kirsher VETH_MCAST_FILTER_SIZE, NULL); 15119aa32835SJeff Kirsher if (!mcastFilterSize_p) { 15129aa32835SJeff Kirsher dev_err(&dev->dev, "Can't find VETH_MCAST_FILTER_SIZE " 15139aa32835SJeff Kirsher "attribute\n"); 15149aa32835SJeff Kirsher return -EINVAL; 15159aa32835SJeff Kirsher } 15169aa32835SJeff Kirsher 15179aa32835SJeff Kirsher netdev = alloc_etherdev(sizeof(struct ibmveth_adapter)); 15189aa32835SJeff Kirsher 15199aa32835SJeff Kirsher if (!netdev) 15209aa32835SJeff Kirsher return -ENOMEM; 15219aa32835SJeff Kirsher 15229aa32835SJeff Kirsher adapter = netdev_priv(netdev); 15239aa32835SJeff Kirsher dev_set_drvdata(&dev->dev, netdev); 15249aa32835SJeff Kirsher 15259aa32835SJeff Kirsher adapter->vdev = dev; 15269aa32835SJeff Kirsher adapter->netdev = netdev; 15279aa32835SJeff Kirsher adapter->mcastFilterSize = *mcastFilterSize_p; 15289aa32835SJeff Kirsher adapter->pool_config = 0; 15299aa32835SJeff Kirsher 15309aa32835SJeff Kirsher netif_napi_add(netdev, &adapter->napi, ibmveth_poll, 16); 15319aa32835SJeff Kirsher 15329aa32835SJeff Kirsher netdev->irq = dev->irq; 15339aa32835SJeff Kirsher netdev->netdev_ops = &ibmveth_netdev_ops; 15349aa32835SJeff Kirsher netdev->ethtool_ops = &netdev_ethtool_ops; 15359aa32835SJeff Kirsher SET_NETDEV_DEV(netdev, &dev->dev); 15369aa32835SJeff Kirsher netdev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM | 15379aa32835SJeff Kirsher NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; 1538*07e6a97dSThomas Falcon 15399aa32835SJeff Kirsher netdev->features |= netdev->hw_features; 15409aa32835SJeff Kirsher 1541*07e6a97dSThomas Falcon ret = h_illan_attributes(adapter->vdev->unit_address, 0, 0, &ret_attr); 1542*07e6a97dSThomas Falcon 1543*07e6a97dSThomas Falcon /* If running older firmware, TSO should not be enabled by default */ 1544*07e6a97dSThomas Falcon if (ret == H_SUCCESS && (ret_attr & IBMVETH_ILLAN_LRG_SND_SUPPORT) && 1545*07e6a97dSThomas Falcon !old_large_send) { 1546*07e6a97dSThomas Falcon netdev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6; 1547*07e6a97dSThomas Falcon netdev->features |= netdev->hw_features; 1548*07e6a97dSThomas Falcon } else { 15498641dd85SThomas Falcon netdev->hw_features |= NETIF_F_TSO; 1550*07e6a97dSThomas Falcon } 15518641dd85SThomas Falcon 1552d746ca95SAnton Blanchard memcpy(netdev->dev_addr, mac_addr_p, ETH_ALEN); 15539aa32835SJeff Kirsher 1554cd7c7ec3SThomas Falcon if (firmware_has_feature(FW_FEATURE_CMO)) 1555cd7c7ec3SThomas Falcon memcpy(pool_count, pool_count_cmo, sizeof(pool_count)); 1556cd7c7ec3SThomas Falcon 15579aa32835SJeff Kirsher for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) { 15589aa32835SJeff Kirsher struct kobject *kobj = &adapter->rx_buff_pool[i].kobj; 15599aa32835SJeff Kirsher int error; 15609aa32835SJeff Kirsher 15619aa32835SJeff Kirsher ibmveth_init_buffer_pool(&adapter->rx_buff_pool[i], i, 15629aa32835SJeff Kirsher pool_count[i], pool_size[i], 15639aa32835SJeff Kirsher pool_active[i]); 15649aa32835SJeff Kirsher error = kobject_init_and_add(kobj, &ktype_veth_pool, 15659aa32835SJeff Kirsher &dev->dev.kobj, "pool%d", i); 15669aa32835SJeff Kirsher if (!error) 15679aa32835SJeff Kirsher kobject_uevent(kobj, KOBJ_ADD); 15689aa32835SJeff Kirsher } 15699aa32835SJeff Kirsher 15709aa32835SJeff Kirsher netdev_dbg(netdev, "adapter @ 0x%p\n", adapter); 15719aa32835SJeff Kirsher 15729aa32835SJeff Kirsher adapter->buffer_list_dma = DMA_ERROR_CODE; 15739aa32835SJeff Kirsher adapter->filter_list_dma = DMA_ERROR_CODE; 15749aa32835SJeff Kirsher adapter->rx_queue.queue_dma = DMA_ERROR_CODE; 15759aa32835SJeff Kirsher 15769aa32835SJeff Kirsher netdev_dbg(netdev, "registering netdev...\n"); 15779aa32835SJeff Kirsher 15789aa32835SJeff Kirsher ibmveth_set_features(netdev, netdev->features); 15799aa32835SJeff Kirsher 15809aa32835SJeff Kirsher rc = register_netdev(netdev); 15819aa32835SJeff Kirsher 15829aa32835SJeff Kirsher if (rc) { 15839aa32835SJeff Kirsher netdev_dbg(netdev, "failed to register netdev rc=%d\n", rc); 15849aa32835SJeff Kirsher free_netdev(netdev); 15859aa32835SJeff Kirsher return rc; 15869aa32835SJeff Kirsher } 15879aa32835SJeff Kirsher 15889aa32835SJeff Kirsher netdev_dbg(netdev, "registered\n"); 15899aa32835SJeff Kirsher 15909aa32835SJeff Kirsher return 0; 15919aa32835SJeff Kirsher } 15929aa32835SJeff Kirsher 1593e11787a2SBill Pemberton static int ibmveth_remove(struct vio_dev *dev) 15949aa32835SJeff Kirsher { 15959aa32835SJeff Kirsher struct net_device *netdev = dev_get_drvdata(&dev->dev); 15969aa32835SJeff Kirsher struct ibmveth_adapter *adapter = netdev_priv(netdev); 15979aa32835SJeff Kirsher int i; 15989aa32835SJeff Kirsher 15999aa32835SJeff Kirsher for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) 16009aa32835SJeff Kirsher kobject_put(&adapter->rx_buff_pool[i].kobj); 16019aa32835SJeff Kirsher 16029aa32835SJeff Kirsher unregister_netdev(netdev); 16039aa32835SJeff Kirsher 16049aa32835SJeff Kirsher free_netdev(netdev); 16059aa32835SJeff Kirsher dev_set_drvdata(&dev->dev, NULL); 16069aa32835SJeff Kirsher 16079aa32835SJeff Kirsher return 0; 16089aa32835SJeff Kirsher } 16099aa32835SJeff Kirsher 16109aa32835SJeff Kirsher static struct attribute veth_active_attr; 16119aa32835SJeff Kirsher static struct attribute veth_num_attr; 16129aa32835SJeff Kirsher static struct attribute veth_size_attr; 16139aa32835SJeff Kirsher 16149aa32835SJeff Kirsher static ssize_t veth_pool_show(struct kobject *kobj, 16159aa32835SJeff Kirsher struct attribute *attr, char *buf) 16169aa32835SJeff Kirsher { 16179aa32835SJeff Kirsher struct ibmveth_buff_pool *pool = container_of(kobj, 16189aa32835SJeff Kirsher struct ibmveth_buff_pool, 16199aa32835SJeff Kirsher kobj); 16209aa32835SJeff Kirsher 16219aa32835SJeff Kirsher if (attr == &veth_active_attr) 16229aa32835SJeff Kirsher return sprintf(buf, "%d\n", pool->active); 16239aa32835SJeff Kirsher else if (attr == &veth_num_attr) 16249aa32835SJeff Kirsher return sprintf(buf, "%d\n", pool->size); 16259aa32835SJeff Kirsher else if (attr == &veth_size_attr) 16269aa32835SJeff Kirsher return sprintf(buf, "%d\n", pool->buff_size); 16279aa32835SJeff Kirsher return 0; 16289aa32835SJeff Kirsher } 16299aa32835SJeff Kirsher 16309aa32835SJeff Kirsher static ssize_t veth_pool_store(struct kobject *kobj, struct attribute *attr, 16319aa32835SJeff Kirsher const char *buf, size_t count) 16329aa32835SJeff Kirsher { 16339aa32835SJeff Kirsher struct ibmveth_buff_pool *pool = container_of(kobj, 16349aa32835SJeff Kirsher struct ibmveth_buff_pool, 16359aa32835SJeff Kirsher kobj); 16369aa32835SJeff Kirsher struct net_device *netdev = dev_get_drvdata( 16379aa32835SJeff Kirsher container_of(kobj->parent, struct device, kobj)); 16389aa32835SJeff Kirsher struct ibmveth_adapter *adapter = netdev_priv(netdev); 16399aa32835SJeff Kirsher long value = simple_strtol(buf, NULL, 10); 16409aa32835SJeff Kirsher long rc; 16419aa32835SJeff Kirsher 16429aa32835SJeff Kirsher if (attr == &veth_active_attr) { 16439aa32835SJeff Kirsher if (value && !pool->active) { 16449aa32835SJeff Kirsher if (netif_running(netdev)) { 16459aa32835SJeff Kirsher if (ibmveth_alloc_buffer_pool(pool)) { 16469aa32835SJeff Kirsher netdev_err(netdev, 16479aa32835SJeff Kirsher "unable to alloc pool\n"); 16489aa32835SJeff Kirsher return -ENOMEM; 16499aa32835SJeff Kirsher } 16509aa32835SJeff Kirsher pool->active = 1; 16519aa32835SJeff Kirsher adapter->pool_config = 1; 16529aa32835SJeff Kirsher ibmveth_close(netdev); 16539aa32835SJeff Kirsher adapter->pool_config = 0; 16549aa32835SJeff Kirsher if ((rc = ibmveth_open(netdev))) 16559aa32835SJeff Kirsher return rc; 16569aa32835SJeff Kirsher } else { 16579aa32835SJeff Kirsher pool->active = 1; 16589aa32835SJeff Kirsher } 16599aa32835SJeff Kirsher } else if (!value && pool->active) { 16609aa32835SJeff Kirsher int mtu = netdev->mtu + IBMVETH_BUFF_OH; 16619aa32835SJeff Kirsher int i; 16629aa32835SJeff Kirsher /* Make sure there is a buffer pool with buffers that 16639aa32835SJeff Kirsher can hold a packet of the size of the MTU */ 16649aa32835SJeff Kirsher for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) { 16659aa32835SJeff Kirsher if (pool == &adapter->rx_buff_pool[i]) 16669aa32835SJeff Kirsher continue; 16679aa32835SJeff Kirsher if (!adapter->rx_buff_pool[i].active) 16689aa32835SJeff Kirsher continue; 16699aa32835SJeff Kirsher if (mtu <= adapter->rx_buff_pool[i].buff_size) 16709aa32835SJeff Kirsher break; 16719aa32835SJeff Kirsher } 16729aa32835SJeff Kirsher 16739aa32835SJeff Kirsher if (i == IBMVETH_NUM_BUFF_POOLS) { 16749aa32835SJeff Kirsher netdev_err(netdev, "no active pool >= MTU\n"); 16759aa32835SJeff Kirsher return -EPERM; 16769aa32835SJeff Kirsher } 16779aa32835SJeff Kirsher 16789aa32835SJeff Kirsher if (netif_running(netdev)) { 16799aa32835SJeff Kirsher adapter->pool_config = 1; 16809aa32835SJeff Kirsher ibmveth_close(netdev); 16819aa32835SJeff Kirsher pool->active = 0; 16829aa32835SJeff Kirsher adapter->pool_config = 0; 16839aa32835SJeff Kirsher if ((rc = ibmveth_open(netdev))) 16849aa32835SJeff Kirsher return rc; 16859aa32835SJeff Kirsher } 16869aa32835SJeff Kirsher pool->active = 0; 16879aa32835SJeff Kirsher } 16889aa32835SJeff Kirsher } else if (attr == &veth_num_attr) { 16899aa32835SJeff Kirsher if (value <= 0 || value > IBMVETH_MAX_POOL_COUNT) { 16909aa32835SJeff Kirsher return -EINVAL; 16919aa32835SJeff Kirsher } else { 16929aa32835SJeff Kirsher if (netif_running(netdev)) { 16939aa32835SJeff Kirsher adapter->pool_config = 1; 16949aa32835SJeff Kirsher ibmveth_close(netdev); 16959aa32835SJeff Kirsher adapter->pool_config = 0; 16969aa32835SJeff Kirsher pool->size = value; 16979aa32835SJeff Kirsher if ((rc = ibmveth_open(netdev))) 16989aa32835SJeff Kirsher return rc; 16999aa32835SJeff Kirsher } else { 17009aa32835SJeff Kirsher pool->size = value; 17019aa32835SJeff Kirsher } 17029aa32835SJeff Kirsher } 17039aa32835SJeff Kirsher } else if (attr == &veth_size_attr) { 17049aa32835SJeff Kirsher if (value <= IBMVETH_BUFF_OH || value > IBMVETH_MAX_BUF_SIZE) { 17059aa32835SJeff Kirsher return -EINVAL; 17069aa32835SJeff Kirsher } else { 17079aa32835SJeff Kirsher if (netif_running(netdev)) { 17089aa32835SJeff Kirsher adapter->pool_config = 1; 17099aa32835SJeff Kirsher ibmveth_close(netdev); 17109aa32835SJeff Kirsher adapter->pool_config = 0; 17119aa32835SJeff Kirsher pool->buff_size = value; 17129aa32835SJeff Kirsher if ((rc = ibmveth_open(netdev))) 17139aa32835SJeff Kirsher return rc; 17149aa32835SJeff Kirsher } else { 17159aa32835SJeff Kirsher pool->buff_size = value; 17169aa32835SJeff Kirsher } 17179aa32835SJeff Kirsher } 17189aa32835SJeff Kirsher } 17199aa32835SJeff Kirsher 17209aa32835SJeff Kirsher /* kick the interrupt handler to allocate/deallocate pools */ 17219aa32835SJeff Kirsher ibmveth_interrupt(netdev->irq, netdev); 17229aa32835SJeff Kirsher return count; 17239aa32835SJeff Kirsher } 17249aa32835SJeff Kirsher 17259aa32835SJeff Kirsher 17269aa32835SJeff Kirsher #define ATTR(_name, _mode) \ 17279aa32835SJeff Kirsher struct attribute veth_##_name##_attr = { \ 17289aa32835SJeff Kirsher .name = __stringify(_name), .mode = _mode, \ 17299aa32835SJeff Kirsher }; 17309aa32835SJeff Kirsher 17319aa32835SJeff Kirsher static ATTR(active, 0644); 17329aa32835SJeff Kirsher static ATTR(num, 0644); 17339aa32835SJeff Kirsher static ATTR(size, 0644); 17349aa32835SJeff Kirsher 17359aa32835SJeff Kirsher static struct attribute *veth_pool_attrs[] = { 17369aa32835SJeff Kirsher &veth_active_attr, 17379aa32835SJeff Kirsher &veth_num_attr, 17389aa32835SJeff Kirsher &veth_size_attr, 17399aa32835SJeff Kirsher NULL, 17409aa32835SJeff Kirsher }; 17419aa32835SJeff Kirsher 17429aa32835SJeff Kirsher static const struct sysfs_ops veth_pool_ops = { 17439aa32835SJeff Kirsher .show = veth_pool_show, 17449aa32835SJeff Kirsher .store = veth_pool_store, 17459aa32835SJeff Kirsher }; 17469aa32835SJeff Kirsher 17479aa32835SJeff Kirsher static struct kobj_type ktype_veth_pool = { 17489aa32835SJeff Kirsher .release = NULL, 17499aa32835SJeff Kirsher .sysfs_ops = &veth_pool_ops, 17509aa32835SJeff Kirsher .default_attrs = veth_pool_attrs, 17519aa32835SJeff Kirsher }; 17529aa32835SJeff Kirsher 17539aa32835SJeff Kirsher static int ibmveth_resume(struct device *dev) 17549aa32835SJeff Kirsher { 17559aa32835SJeff Kirsher struct net_device *netdev = dev_get_drvdata(dev); 17569aa32835SJeff Kirsher ibmveth_interrupt(netdev->irq, netdev); 17579aa32835SJeff Kirsher return 0; 17589aa32835SJeff Kirsher } 17599aa32835SJeff Kirsher 1760e11787a2SBill Pemberton static struct vio_device_id ibmveth_device_table[] = { 17619aa32835SJeff Kirsher { "network", "IBM,l-lan"}, 17629aa32835SJeff Kirsher { "", "" } 17639aa32835SJeff Kirsher }; 17649aa32835SJeff Kirsher MODULE_DEVICE_TABLE(vio, ibmveth_device_table); 17659aa32835SJeff Kirsher 17669aa32835SJeff Kirsher static struct dev_pm_ops ibmveth_pm_ops = { 17679aa32835SJeff Kirsher .resume = ibmveth_resume 17689aa32835SJeff Kirsher }; 17699aa32835SJeff Kirsher 17709aa32835SJeff Kirsher static struct vio_driver ibmveth_driver = { 17719aa32835SJeff Kirsher .id_table = ibmveth_device_table, 17729aa32835SJeff Kirsher .probe = ibmveth_probe, 17739aa32835SJeff Kirsher .remove = ibmveth_remove, 17749aa32835SJeff Kirsher .get_desired_dma = ibmveth_get_desired_dma, 17759aa32835SJeff Kirsher .name = ibmveth_driver_name, 17769aa32835SJeff Kirsher .pm = &ibmveth_pm_ops, 17779aa32835SJeff Kirsher }; 17789aa32835SJeff Kirsher 17799aa32835SJeff Kirsher static int __init ibmveth_module_init(void) 17809aa32835SJeff Kirsher { 17819aa32835SJeff Kirsher printk(KERN_DEBUG "%s: %s %s\n", ibmveth_driver_name, 17829aa32835SJeff Kirsher ibmveth_driver_string, ibmveth_driver_version); 17839aa32835SJeff Kirsher 17849aa32835SJeff Kirsher return vio_register_driver(&ibmveth_driver); 17859aa32835SJeff Kirsher } 17869aa32835SJeff Kirsher 17879aa32835SJeff Kirsher static void __exit ibmveth_module_exit(void) 17889aa32835SJeff Kirsher { 17899aa32835SJeff Kirsher vio_unregister_driver(&ibmveth_driver); 17909aa32835SJeff Kirsher } 17919aa32835SJeff Kirsher 17929aa32835SJeff Kirsher module_init(ibmveth_module_init); 17939aa32835SJeff Kirsher module_exit(ibmveth_module_exit); 1794