ibmveth: enable driver for CMO

Enable ibmveth for Cooperative Memory Overcommitment (CMO). For this driver
it means calculating a desired amount of IO memory based on the current MTU
and updating this value with the bus when MTU changes occur. Because DMA
mappings can fail, we have added a bounce buffer for temporary cases where
the driver can not map IO memory for the buffer pool.

The following changes are made to enable the driver for CMO:
* DMA mapping errors will not result in error messages if entitlement has
been exceeded and resources were not available.
* DMA mapping errors are handled gracefully, ibmveth_replenish_buffer_pool()
is corrected to check the return from dma_map_single and fail gracefully.
* The driver will have a get_desired_dma function defined to function
in a CMO environment.
* When the MTU is changed, the driver will update the device IO entitlement

Signed-off-by: Robert Jennings <rcj@linux.vnet.ibm.com>
Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
Signed-off-by: Santiago Leon <santil@us.ibm.com>
Acked-by: Paul Mackerras <paulus@samba.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

authored by

Robert Jennings and committed by
Benjamin Herrenschmidt
1096d63d ea866e65

+140 -34
+135 -34
drivers/net/ibmveth.c
··· 33 33 */ 34 34 35 35 #include <linux/module.h> 36 + #include <linux/moduleparam.h> 36 37 #include <linux/types.h> 37 38 #include <linux/errno.h> 38 39 #include <linux/ioport.h> ··· 53 52 #include <asm/hvcall.h> 54 53 #include <asm/atomic.h> 55 54 #include <asm/vio.h> 55 + #include <asm/iommu.h> 56 56 #include <asm/uaccess.h> 57 + #include <asm/firmware.h> 57 58 #include <linux/seq_file.h> 58 59 59 60 #include "ibmveth.h" ··· 97 94 static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter); 98 95 static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance); 99 96 static void ibmveth_rxq_harvest_buffer(struct ibmveth_adapter *adapter); 97 + static unsigned long ibmveth_get_desired_dma(struct vio_dev *vdev); 100 98 static struct kobj_type ktype_veth_pool; 99 + 101 100 102 101 #ifdef CONFIG_PROC_FS 103 102 #define IBMVETH_PROC_DIR "ibmveth" ··· 231 226 u32 i; 232 227 u32 count = pool->size - atomic_read(&pool->available); 233 228 u32 buffers_added = 0; 229 + struct sk_buff *skb; 230 + unsigned int free_index, index; 231 + u64 correlator; 232 + unsigned long lpar_rc; 233 + dma_addr_t dma_addr; 234 234 235 235 mb(); 236 236 237 237 for(i = 0; i < count; ++i) { 238 - struct sk_buff *skb; 239 - unsigned int free_index, index; 240 - u64 correlator; 241 238 union ibmveth_buf_desc desc; 242 - unsigned long lpar_rc; 243 - dma_addr_t dma_addr; 244 239 245 240 skb = alloc_skb(pool->buff_size, GFP_ATOMIC); 246 241 ··· 260 255 dma_addr = dma_map_single(&adapter->vdev->dev, skb->data, 261 256 pool->buff_size, DMA_FROM_DEVICE); 262 257 258 + if (dma_mapping_error(dma_addr)) 259 + goto failure; 260 + 263 261 pool->free_map[free_index] = IBM_VETH_INVALID_MAP; 264 262 pool->dma_addr[index] = dma_addr; 265 263 pool->skbuff[index] = skb; ··· 275 267 276 268 lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc); 277 269 278 - if(lpar_rc != H_SUCCESS) { 279 - pool->free_map[free_index] = index; 280 - pool->skbuff[index] = NULL; 281 - if (pool->consumer_index == 0) 282 - pool->consumer_index = pool->size - 1; 283 - else 284 - pool->consumer_index--; 285 - dma_unmap_single(&adapter->vdev->dev, 286 - pool->dma_addr[index], pool->buff_size, 287 - DMA_FROM_DEVICE); 288 - dev_kfree_skb_any(skb); 289 - adapter->replenish_add_buff_failure++; 290 - break; 291 - } else { 270 + if (lpar_rc != H_SUCCESS) 271 + goto failure; 272 + else { 292 273 buffers_added++; 293 274 adapter->replenish_add_buff_success++; 294 275 } 295 276 } 277 + 278 + mb(); 279 + atomic_add(buffers_added, &(pool->available)); 280 + return; 281 + 282 + failure: 283 + pool->free_map[free_index] = index; 284 + pool->skbuff[index] = NULL; 285 + if (pool->consumer_index == 0) 286 + pool->consumer_index = pool->size - 1; 287 + else 288 + pool->consumer_index--; 289 + if (!dma_mapping_error(dma_addr)) 290 + dma_unmap_single(&adapter->vdev->dev, 291 + pool->dma_addr[index], pool->buff_size, 292 + DMA_FROM_DEVICE); 293 + dev_kfree_skb_any(skb); 294 + adapter->replenish_add_buff_failure++; 296 295 297 296 mb(); 298 297 atomic_add(buffers_added, &(pool->available)); ··· 312 297 313 298 adapter->replenish_task_cycles++; 314 299 315 - for(i = 0; i < IbmVethNumBufferPools; i++) 300 + for (i = (IbmVethNumBufferPools - 1); i >= 0; i--) 316 301 if(adapter->rx_buff_pool[i].active) 317 302 ibmveth_replenish_buffer_pool(adapter, 318 303 &adapter->rx_buff_pool[i]); ··· 487 472 if (adapter->rx_buff_pool[i].active) 488 473 ibmveth_free_buffer_pool(adapter, 489 474 &adapter->rx_buff_pool[i]); 475 + 476 + if (adapter->bounce_buffer != NULL) { 477 + if (!dma_mapping_error(adapter->bounce_buffer_dma)) { 478 + dma_unmap_single(&adapter->vdev->dev, 479 + adapter->bounce_buffer_dma, 480 + adapter->netdev->mtu + IBMVETH_BUFF_OH, 481 + DMA_BIDIRECTIONAL); 482 + adapter->bounce_buffer_dma = DMA_ERROR_CODE; 483 + } 484 + kfree(adapter->bounce_buffer); 485 + adapter->bounce_buffer = NULL; 486 + } 490 487 } 491 488 492 489 static int ibmveth_register_logical_lan(struct ibmveth_adapter *adapter, ··· 632 605 ibmveth_cleanup(adapter); 633 606 napi_disable(&adapter->napi); 634 607 return rc; 608 + } 609 + 610 + adapter->bounce_buffer = 611 + kmalloc(netdev->mtu + IBMVETH_BUFF_OH, GFP_KERNEL); 612 + if (!adapter->bounce_buffer) { 613 + ibmveth_error_printk("unable to allocate bounce buffer\n"); 614 + ibmveth_cleanup(adapter); 615 + napi_disable(&adapter->napi); 616 + return -ENOMEM; 617 + } 618 + adapter->bounce_buffer_dma = 619 + dma_map_single(&adapter->vdev->dev, adapter->bounce_buffer, 620 + netdev->mtu + IBMVETH_BUFF_OH, DMA_BIDIRECTIONAL); 621 + if (dma_mapping_error(adapter->bounce_buffer_dma)) { 622 + ibmveth_error_printk("unable to map bounce buffer\n"); 623 + ibmveth_cleanup(adapter); 624 + napi_disable(&adapter->napi); 625 + return -ENOMEM; 635 626 } 636 627 637 628 ibmveth_debug_printk("initial replenish cycle\n"); ··· 898 853 unsigned int tx_packets = 0; 899 854 unsigned int tx_send_failed = 0; 900 855 unsigned int tx_map_failed = 0; 856 + int used_bounce = 0; 857 + unsigned long data_dma_addr; 901 858 902 859 desc.fields.flags_len = IBMVETH_BUF_VALID | skb->len; 903 - desc.fields.address = dma_map_single(&adapter->vdev->dev, skb->data, 904 - skb->len, DMA_TO_DEVICE); 860 + data_dma_addr = dma_map_single(&adapter->vdev->dev, skb->data, 861 + skb->len, DMA_TO_DEVICE); 905 862 906 863 if (skb->ip_summed == CHECKSUM_PARTIAL && 907 864 ip_hdr(skb)->protocol != IPPROTO_TCP && skb_checksum_help(skb)) { ··· 922 875 buf[1] = 0; 923 876 } 924 877 925 - if (dma_mapping_error(desc.fields.address)) { 926 - ibmveth_error_printk("tx: unable to map xmit buffer\n"); 878 + if (dma_mapping_error(data_dma_addr)) { 879 + if (!firmware_has_feature(FW_FEATURE_CMO)) 880 + ibmveth_error_printk("tx: unable to map xmit buffer\n"); 881 + skb_copy_from_linear_data(skb, adapter->bounce_buffer, 882 + skb->len); 883 + desc.fields.address = adapter->bounce_buffer_dma; 927 884 tx_map_failed++; 928 - tx_dropped++; 929 - goto out; 930 - } 885 + used_bounce = 1; 886 + } else 887 + desc.fields.address = data_dma_addr; 931 888 932 889 /* send the frame. Arbitrarily set retrycount to 1024 */ 933 890 correlator = 0; ··· 955 904 netdev->trans_start = jiffies; 956 905 } 957 906 958 - dma_unmap_single(&adapter->vdev->dev, desc.fields.address, 959 - skb->len, DMA_TO_DEVICE); 907 + if (!used_bounce) 908 + dma_unmap_single(&adapter->vdev->dev, data_dma_addr, 909 + skb->len, DMA_TO_DEVICE); 960 910 961 911 out: spin_lock_irqsave(&adapter->stats_lock, flags); 962 912 netdev->stats.tx_dropped += tx_dropped; ··· 1105 1053 static int ibmveth_change_mtu(struct net_device *dev, int new_mtu) 1106 1054 { 1107 1055 struct ibmveth_adapter *adapter = dev->priv; 1056 + struct vio_dev *viodev = adapter->vdev; 1108 1057 int new_mtu_oh = new_mtu + IBMVETH_BUFF_OH; 1109 - int i, rc; 1058 + int i; 1110 1059 1111 1060 if (new_mtu < IBMVETH_MAX_MTU) 1112 1061 return -EINVAL; ··· 1138 1085 ibmveth_close(adapter->netdev); 1139 1086 adapter->pool_config = 0; 1140 1087 dev->mtu = new_mtu; 1141 - if ((rc = ibmveth_open(adapter->netdev))) 1142 - return rc; 1143 - } else 1144 - dev->mtu = new_mtu; 1088 + vio_cmo_set_dev_desired(viodev, 1089 + ibmveth_get_desired_dma 1090 + (viodev)); 1091 + return ibmveth_open(adapter->netdev); 1092 + } 1093 + dev->mtu = new_mtu; 1094 + vio_cmo_set_dev_desired(viodev, 1095 + ibmveth_get_desired_dma 1096 + (viodev)); 1145 1097 return 0; 1146 1098 } 1147 1099 } ··· 1160 1102 ibmveth_interrupt(dev->irq, dev); 1161 1103 } 1162 1104 #endif 1105 + 1106 + /** 1107 + * ibmveth_get_desired_dma - Calculate IO memory desired by the driver 1108 + * 1109 + * @vdev: struct vio_dev for the device whose desired IO mem is to be returned 1110 + * 1111 + * Return value: 1112 + * Number of bytes of IO data the driver will need to perform well. 1113 + */ 1114 + static unsigned long ibmveth_get_desired_dma(struct vio_dev *vdev) 1115 + { 1116 + struct net_device *netdev = dev_get_drvdata(&vdev->dev); 1117 + struct ibmveth_adapter *adapter; 1118 + unsigned long ret; 1119 + int i; 1120 + int rxqentries = 1; 1121 + 1122 + /* netdev inits at probe time along with the structures we need below*/ 1123 + if (netdev == NULL) 1124 + return IOMMU_PAGE_ALIGN(IBMVETH_IO_ENTITLEMENT_DEFAULT); 1125 + 1126 + adapter = netdev_priv(netdev); 1127 + 1128 + ret = IBMVETH_BUFF_LIST_SIZE + IBMVETH_FILT_LIST_SIZE; 1129 + ret += IOMMU_PAGE_ALIGN(netdev->mtu); 1130 + 1131 + for (i = 0; i < IbmVethNumBufferPools; i++) { 1132 + /* add the size of the active receive buffers */ 1133 + if (adapter->rx_buff_pool[i].active) 1134 + ret += 1135 + adapter->rx_buff_pool[i].size * 1136 + IOMMU_PAGE_ALIGN(adapter->rx_buff_pool[i]. 1137 + buff_size); 1138 + rxqentries += adapter->rx_buff_pool[i].size; 1139 + } 1140 + /* add the size of the receive queue entries */ 1141 + ret += IOMMU_PAGE_ALIGN(rxqentries * sizeof(struct ibmveth_rx_q_entry)); 1142 + 1143 + return ret; 1144 + } 1163 1145 1164 1146 static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id) 1165 1147 { ··· 1345 1247 ibmveth_proc_unregister_adapter(adapter); 1346 1248 1347 1249 free_netdev(netdev); 1250 + dev_set_drvdata(&dev->dev, NULL); 1251 + 1348 1252 return 0; 1349 1253 } 1350 1254 ··· 1591 1491 .id_table = ibmveth_device_table, 1592 1492 .probe = ibmveth_probe, 1593 1493 .remove = ibmveth_remove, 1494 + .get_desired_dma = ibmveth_get_desired_dma, 1594 1495 .driver = { 1595 1496 .name = ibmveth_driver_name, 1596 1497 .owner = THIS_MODULE,
+5
drivers/net/ibmveth.h
··· 93 93 plpar_hcall_norets(H_CHANGE_LOGICAL_LAN_MAC, ua, mac) 94 94 95 95 #define IbmVethNumBufferPools 5 96 + #define IBMVETH_IO_ENTITLEMENT_DEFAULT 4243456 /* MTU of 1500 needs 4.2Mb */ 96 97 #define IBMVETH_BUFF_OH 22 /* Overhead: 14 ethernet header + 8 opaque handle */ 97 98 #define IBMVETH_MAX_MTU 68 98 99 #define IBMVETH_MAX_POOL_COUNT 4096 100 + #define IBMVETH_BUFF_LIST_SIZE 4096 101 + #define IBMVETH_FILT_LIST_SIZE 4096 99 102 #define IBMVETH_MAX_BUF_SIZE (1024 * 128) 100 103 101 104 static int pool_size[] = { 512, 1024 * 2, 1024 * 16, 1024 * 32, 1024 * 64 }; ··· 146 143 struct ibmveth_rx_q rx_queue; 147 144 int pool_config; 148 145 int rx_csum; 146 + void *bounce_buffer; 147 + dma_addr_t bounce_buffer_dma; 149 148 150 149 /* adapter specific stats */ 151 150 u64 replenish_task_cycles;