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