static void ibmveth_rxq_recycle_buffer(struct ibmveth_adapter *adapter) { u32 q_index = adapter->rx_queue.index; u64 correlator = adapter->rx_queue.queue_addr[q_index].correlator; unsigned int pool = correlator >> 32; unsigned int index = correlator & 0xffffffffUL; union ibmveth_buf_desc desc; unsigned long lpar_rc; ibmveth_assert(pool < IbmVethNumBufferPools); ibmveth_assert(index < adapter->rx_buff_pool[pool].size); if(!adapter->rx_buff_pool[pool].active) { ibmveth_rxq_harvest_buffer(adapter); ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[pool]); return; } desc.fields.flags_len = IBMVETH_BUF_VALID | adapter->rx_buff_pool[pool].buff_size; desc.fields.address = adapter->rx_buff_pool[pool].dma_addr[index]; lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc); if(lpar_rc != H_SUCCESS) { ibmveth_debug_printk("h_add_logical_lan_buffer failed during recycle rc=%ld", lpar_rc); ibmveth_remove_buffer_from_pool(adapter, adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator); } if(++adapter->rx_queue.index == adapter->rx_queue.num_slots) { adapter->rx_queue.index = 0; adapter->rx_queue.toggle = !adapter->rx_queue.toggle; } }
static void ibmveth_cleanup(struct ibmveth_adapter *adapter) { int i; struct device *dev = &adapter->vdev->dev; if(adapter->buffer_list_addr != NULL) { if (!dma_mapping_error(dev, adapter->buffer_list_dma)) { dma_unmap_single(dev, adapter->buffer_list_dma, 4096, DMA_BIDIRECTIONAL); adapter->buffer_list_dma = DMA_ERROR_CODE; } free_page((unsigned long)adapter->buffer_list_addr); adapter->buffer_list_addr = NULL; } if(adapter->filter_list_addr != NULL) { if (!dma_mapping_error(dev, adapter->filter_list_dma)) { dma_unmap_single(dev, adapter->filter_list_dma, 4096, DMA_BIDIRECTIONAL); adapter->filter_list_dma = DMA_ERROR_CODE; } free_page((unsigned long)adapter->filter_list_addr); adapter->filter_list_addr = NULL; } if(adapter->rx_queue.queue_addr != NULL) { if (!dma_mapping_error(dev, adapter->rx_queue.queue_dma)) { dma_unmap_single(dev, adapter->rx_queue.queue_dma, adapter->rx_queue.queue_len, DMA_BIDIRECTIONAL); adapter->rx_queue.queue_dma = DMA_ERROR_CODE; } kfree(adapter->rx_queue.queue_addr); adapter->rx_queue.queue_addr = NULL; } for(i = 0; i<IbmVethNumBufferPools; i++) if (adapter->rx_buff_pool[i].active) ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[i]); if (adapter->bounce_buffer != NULL) { if (!dma_mapping_error(dev, adapter->bounce_buffer_dma)) { dma_unmap_single(&adapter->vdev->dev, adapter->bounce_buffer_dma, adapter->netdev->mtu + IBMVETH_BUFF_OH, DMA_BIDIRECTIONAL); adapter->bounce_buffer_dma = DMA_ERROR_CODE; } kfree(adapter->bounce_buffer); adapter->bounce_buffer = NULL; } }
static int ibmveth_change_mtu(struct net_device *dev, int new_mtu) { struct ibmveth_adapter *adapter = netdev_priv(dev); struct vio_dev *viodev = adapter->vdev; int new_mtu_oh = new_mtu + IBMVETH_BUFF_OH; int i; if (new_mtu < IBMVETH_MAX_MTU) return -EINVAL; for (i = 0; i < IbmVethNumBufferPools; i++) if (new_mtu_oh < adapter->rx_buff_pool[i].buff_size) break; if (i == IbmVethNumBufferPools) return -EINVAL; for (i = 0; i < IbmVethNumBufferPools; i++) if (adapter->rx_buff_pool[i].active) { ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[i]); adapter->rx_buff_pool[i].active = 0; } for(i = 0; i<IbmVethNumBufferPools; i++) { adapter->rx_buff_pool[i].active = 1; if (new_mtu_oh < adapter->rx_buff_pool[i].buff_size) { if (netif_running(adapter->netdev)) { adapter->pool_config = 1; ibmveth_close(adapter->netdev); adapter->pool_config = 0; dev->mtu = new_mtu; vio_cmo_set_dev_desired(viodev, ibmveth_get_desired_dma (viodev)); return ibmveth_open(adapter->netdev); } dev->mtu = new_mtu; vio_cmo_set_dev_desired(viodev, ibmveth_get_desired_dma (viodev)); return 0; } } return -EINVAL; }
/* recycle the current buffer on the rx queue */ static int ibmveth_rxq_recycle_buffer(struct ibmveth_adapter *adapter) { u32 q_index = adapter->rx_queue.index; u64 correlator = adapter->rx_queue.queue_addr[q_index].correlator; unsigned int pool = correlator >> 32; unsigned int index = correlator & 0xffffffffUL; union ibmveth_buf_desc desc; unsigned long lpar_rc; int ret = 1; BUG_ON(pool >= IBMVETH_NUM_BUFF_POOLS); BUG_ON(index >= adapter->rx_buff_pool[pool].size); if (!adapter->rx_buff_pool[pool].active) { ibmveth_rxq_harvest_buffer(adapter); ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[pool]); goto out; } desc.fields.flags_len = IBMVETH_BUF_VALID | adapter->rx_buff_pool[pool].buff_size; desc.fields.address = adapter->rx_buff_pool[pool].dma_addr[index]; lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc); if (lpar_rc != H_SUCCESS) { netdev_dbg(adapter->netdev, "h_add_logical_lan_buffer failed " "during recycle rc=%ld", lpar_rc); ibmveth_remove_buffer_from_pool(adapter, adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator); ret = 0; } if (++adapter->rx_queue.index == adapter->rx_queue.num_slots) { adapter->rx_queue.index = 0; adapter->rx_queue.toggle = !adapter->rx_queue.toggle; } out: return ret; }