diff options
Diffstat (limited to 'drivers/net/ibmveth.c')
-rw-r--r-- | drivers/net/ibmveth.c | 58 |
1 files changed, 50 insertions, 8 deletions
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 4bac3cd8f235..2802db23d3cb 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c | |||
@@ -213,6 +213,7 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc | |||
213 | } | 213 | } |
214 | 214 | ||
215 | free_index = pool->consumer_index++ % pool->size; | 215 | free_index = pool->consumer_index++ % pool->size; |
216 | pool->consumer_index = free_index; | ||
216 | index = pool->free_map[free_index]; | 217 | index = pool->free_map[free_index]; |
217 | 218 | ||
218 | ibmveth_assert(index != IBM_VETH_INVALID_MAP); | 219 | ibmveth_assert(index != IBM_VETH_INVALID_MAP); |
@@ -238,7 +239,10 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc | |||
238 | if(lpar_rc != H_SUCCESS) { | 239 | if(lpar_rc != H_SUCCESS) { |
239 | pool->free_map[free_index] = index; | 240 | pool->free_map[free_index] = index; |
240 | pool->skbuff[index] = NULL; | 241 | pool->skbuff[index] = NULL; |
241 | pool->consumer_index--; | 242 | if (pool->consumer_index == 0) |
243 | pool->consumer_index = pool->size - 1; | ||
244 | else | ||
245 | pool->consumer_index--; | ||
242 | dma_unmap_single(&adapter->vdev->dev, | 246 | dma_unmap_single(&adapter->vdev->dev, |
243 | pool->dma_addr[index], pool->buff_size, | 247 | pool->dma_addr[index], pool->buff_size, |
244 | DMA_FROM_DEVICE); | 248 | DMA_FROM_DEVICE); |
@@ -326,6 +330,7 @@ static void ibmveth_remove_buffer_from_pool(struct ibmveth_adapter *adapter, u64 | |||
326 | DMA_FROM_DEVICE); | 330 | DMA_FROM_DEVICE); |
327 | 331 | ||
328 | free_index = adapter->rx_buff_pool[pool].producer_index++ % adapter->rx_buff_pool[pool].size; | 332 | free_index = adapter->rx_buff_pool[pool].producer_index++ % adapter->rx_buff_pool[pool].size; |
333 | adapter->rx_buff_pool[pool].producer_index = free_index; | ||
329 | adapter->rx_buff_pool[pool].free_map[free_index] = index; | 334 | adapter->rx_buff_pool[pool].free_map[free_index] = index; |
330 | 335 | ||
331 | mb(); | 336 | mb(); |
@@ -437,6 +442,31 @@ static void ibmveth_cleanup(struct ibmveth_adapter *adapter) | |||
437 | &adapter->rx_buff_pool[i]); | 442 | &adapter->rx_buff_pool[i]); |
438 | } | 443 | } |
439 | 444 | ||
445 | static int ibmveth_register_logical_lan(struct ibmveth_adapter *adapter, | ||
446 | union ibmveth_buf_desc rxq_desc, u64 mac_address) | ||
447 | { | ||
448 | int rc, try_again = 1; | ||
449 | |||
450 | /* After a kexec the adapter will still be open, so our attempt to | ||
451 | * open it will fail. So if we get a failure we free the adapter and | ||
452 | * try again, but only once. */ | ||
453 | retry: | ||
454 | rc = h_register_logical_lan(adapter->vdev->unit_address, | ||
455 | adapter->buffer_list_dma, rxq_desc.desc, | ||
456 | adapter->filter_list_dma, mac_address); | ||
457 | |||
458 | if (rc != H_SUCCESS && try_again) { | ||
459 | do { | ||
460 | rc = h_free_logical_lan(adapter->vdev->unit_address); | ||
461 | } while (H_IS_LONG_BUSY(rc) || (rc == H_BUSY)); | ||
462 | |||
463 | try_again = 0; | ||
464 | goto retry; | ||
465 | } | ||
466 | |||
467 | return rc; | ||
468 | } | ||
469 | |||
440 | static int ibmveth_open(struct net_device *netdev) | 470 | static int ibmveth_open(struct net_device *netdev) |
441 | { | 471 | { |
442 | struct ibmveth_adapter *adapter = netdev->priv; | 472 | struct ibmveth_adapter *adapter = netdev->priv; |
@@ -502,12 +532,9 @@ static int ibmveth_open(struct net_device *netdev) | |||
502 | ibmveth_debug_printk("filter list @ 0x%p\n", adapter->filter_list_addr); | 532 | ibmveth_debug_printk("filter list @ 0x%p\n", adapter->filter_list_addr); |
503 | ibmveth_debug_printk("receive q @ 0x%p\n", adapter->rx_queue.queue_addr); | 533 | ibmveth_debug_printk("receive q @ 0x%p\n", adapter->rx_queue.queue_addr); |
504 | 534 | ||
535 | h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_DISABLE); | ||
505 | 536 | ||
506 | lpar_rc = h_register_logical_lan(adapter->vdev->unit_address, | 537 | lpar_rc = ibmveth_register_logical_lan(adapter, rxq_desc, mac_address); |
507 | adapter->buffer_list_dma, | ||
508 | rxq_desc.desc, | ||
509 | adapter->filter_list_dma, | ||
510 | mac_address); | ||
511 | 538 | ||
512 | if(lpar_rc != H_SUCCESS) { | 539 | if(lpar_rc != H_SUCCESS) { |
513 | ibmveth_error_printk("h_register_logical_lan failed with %ld\n", lpar_rc); | 540 | ibmveth_error_printk("h_register_logical_lan failed with %ld\n", lpar_rc); |
@@ -905,6 +932,14 @@ static int ibmveth_change_mtu(struct net_device *dev, int new_mtu) | |||
905 | return -EINVAL; | 932 | return -EINVAL; |
906 | } | 933 | } |
907 | 934 | ||
935 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
936 | static void ibmveth_poll_controller(struct net_device *dev) | ||
937 | { | ||
938 | ibmveth_replenish_task(dev->priv); | ||
939 | ibmveth_interrupt(dev->irq, dev); | ||
940 | } | ||
941 | #endif | ||
942 | |||
908 | static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id) | 943 | static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id) |
909 | { | 944 | { |
910 | int rc, i; | 945 | int rc, i; |
@@ -977,6 +1012,9 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_ | |||
977 | netdev->ethtool_ops = &netdev_ethtool_ops; | 1012 | netdev->ethtool_ops = &netdev_ethtool_ops; |
978 | netdev->change_mtu = ibmveth_change_mtu; | 1013 | netdev->change_mtu = ibmveth_change_mtu; |
979 | SET_NETDEV_DEV(netdev, &dev->dev); | 1014 | SET_NETDEV_DEV(netdev, &dev->dev); |
1015 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
1016 | netdev->poll_controller = ibmveth_poll_controller; | ||
1017 | #endif | ||
980 | netdev->features |= NETIF_F_LLTX; | 1018 | netdev->features |= NETIF_F_LLTX; |
981 | spin_lock_init(&adapter->stats_lock); | 1019 | spin_lock_init(&adapter->stats_lock); |
982 | 1020 | ||
@@ -1132,7 +1170,9 @@ static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter) | |||
1132 | { | 1170 | { |
1133 | struct proc_dir_entry *entry; | 1171 | struct proc_dir_entry *entry; |
1134 | if (ibmveth_proc_dir) { | 1172 | if (ibmveth_proc_dir) { |
1135 | entry = create_proc_entry(adapter->netdev->name, S_IFREG, ibmveth_proc_dir); | 1173 | char u_addr[10]; |
1174 | sprintf(u_addr, "%x", adapter->vdev->unit_address); | ||
1175 | entry = create_proc_entry(u_addr, S_IFREG, ibmveth_proc_dir); | ||
1136 | if (!entry) { | 1176 | if (!entry) { |
1137 | ibmveth_error_printk("Cannot create adapter proc entry"); | 1177 | ibmveth_error_printk("Cannot create adapter proc entry"); |
1138 | } else { | 1178 | } else { |
@@ -1147,7 +1187,9 @@ static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter) | |||
1147 | static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter) | 1187 | static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter) |
1148 | { | 1188 | { |
1149 | if (ibmveth_proc_dir) { | 1189 | if (ibmveth_proc_dir) { |
1150 | remove_proc_entry(adapter->netdev->name, ibmveth_proc_dir); | 1190 | char u_addr[10]; |
1191 | sprintf(u_addr, "%x", adapter->vdev->unit_address); | ||
1192 | remove_proc_entry(u_addr, ibmveth_proc_dir); | ||
1151 | } | 1193 | } |
1152 | } | 1194 | } |
1153 | 1195 | ||