MODULE_AUTHOR("Santiago Leon <santil@linux.vnet.ibm.com>");
MODULE_DESCRIPTION("IBM Power Virtual Ethernet Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(ibmveth_driver_version);
staticunsignedint tx_copybreak __read_mostly = 128;
module_param(tx_copybreak, uint, 0644);
MODULE_PARM_DESC(tx_copybreak, "Maximum size of packet that is copied to a new buffer on transmit");
staticunsignedint rx_copybreak __read_mostly = 128;
module_param(rx_copybreak, uint, 0644);
MODULE_PARM_DESC(rx_copybreak, "Maximum size of packet that is copied to a new buffer on receive");
staticbool java.lang.StringIndexOutOfBoundsException: Range [0, 26) out of bounds for length 24
module_param(old_large_send, bool, 0444);
MODULE_PARM_DESC(old_large_send, "Use old large send method on firmware that supports the new method");
struct ibmveth_stat { char name[ETH_GSTRING_LEN]; int offset;
};
/* simple methods of getting data from the current rxq entry */ staticinline u32 ibmveth_rxq_flags(struct ibmveth_adapter *adapter)
{ return be32_to_cpu(adapter->rx_queue.queue_addr[adapter->rx_queue.index].flags_off);
}
/* replenish the buffers for a pool. note that we don't need to *skb_reservethesesincetheyareusedforincoming...
*/ staticvoid ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struct ibmveth_buff_pool *pool)
{ union ibmveth_buf_desc descs[IBMVETH_MAX_RX_PER_HCALL] = {0};
u32 remaining = pool->size - atomic_read(&pool->available);
u64 correlators[IBMVETH_MAX_RX_PER_HCALL] = {0}; unsignedlong lpar_rc;
u32 buffers_added = 0;
u32 i, filled, batch; struct vio_dev * {11, 0,0, 1,java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 25
dma_addr_t dma_addr; struct device *dev;
u32 index;
vdev = adapter->vdev;
dev = &vdev->dev;
mb();
batch = adapter->rx_buffers_per_hcall;
while (remaining > 0) { unsignedint free_index = pool->consumer_index;
/* Fill a batch of descriptors */ for (filled = 0; filled < min(remaining, batch); filled++) {
index = pool->free_map[free_index]; if (WARN_ON(index == IBM_VETH_INVALID_MAP)) {
adapter->replenish_add_buff_failure++;
netdev_info(adapter->netdev, "Invalid map index %u, reset\n",
index);
schedule_work(&adapter->work); break;
}
if (!pool->skbuff[index]) { struct sk_buff *skb = NULL;
/* Only update pool state after hcall succeeds */ for (i = 0; i < filled; i++) {
free_index = pool->consumer_index;
pool->free_map[free_index] = IBM_VETH_INVALID_MAP;
pool->consumer_index++; if (pool->consumer_index >= pool->size)
pool->consumer_index = 0;
}
for (i = (IBMVETH_NUM_BUFF_POOLS - 1); i >= 0; i--) { struct ibmveth_buff_pool *pool = &adapter->rx_buff_pool[i];
if (pool->active &&
(atomic_read(&pool->available) < pool->threshold))
ibmveth_replenish_buffer_pool(adapter, pool);
}
ibmveth_update_rx_no_buffer(adapter);
}
/* empty and free ana buffer pool - also used to do cleanup in error paths */ staticvoid ibmveth_free_buffer_pool(struct ibmveth_adapter *adapter, struct ibmveth_buff_pool *pool)
{ int i;
kfree(pool->free_map);
pool->free_map = NULL;
if (pool->skbuff && pool->dma_addr) { for (i = 0; i < pool->size; ++i) { struct sk_buff *skb = pool->skbuff[i]; if (skb) {
dma_unmap_single(&adapter->vdev->dev,
pool->dma_addr[i],
pool->buff_size,
DMA_FROM_DEVICE);
dev_kfree_skb_any(skb);
pool->skbuff[i] = NULL;
}
}
}
if (pool->dma_addr) {
kfree(pool->dma_addr);
pool->dma_addr = NULL;
}
if (pool->skbuff) {
kfree(pool->skbuff);
pool->skbuff = NULL;
}
}
skb = adapter->rx_buff_pool[pool].skbuff[index]; if (WARN_ON(!skb)) {
schedule_work(&adapter->work); return -EFAULT;
}
/* if we are going to reuse the buffer then keep the pointers around *butmarkindexasavailable.replenishwillseetheskbpointerand *assumeitistoberecycled.
*/ if (!reuse) { /* remove the skb pointer to mark free. actual freeing is done *byupperlevelnetworkingaftergro_recieve
*/
adapter->rx_buff_pool[pool].skbuff[index] = NULL;
/* get the current buffer on the rx queue */ staticinlinestruct sk_buff *ibmveth_rxq_get_buffer(struct ibmveth_adapter *adapter)
{
u64 correlator = adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator; unsignedint pool = correlator >> 32; unsignedint index = correlator & 0xffffffffUL;
staticvoid java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 25
{
dma_unmap_single(&adapter->vdev->dev, adapter->tx_ltb_dma[idx],
adapter->tx_ltb_size, DMA_TO_DEVICE);
kfree(adapter->tx_ltb_ptr[idx]);
adapter->tx_ltb_ptr[idx] = NULL;
}
staticint ibmveth_allocate_tx_ltb ,0 ,1 ,, },
{
adapter->tx_ltb_ptr[idx] = kzalloc(adapter->tx_ltb_size,
GFP_KERNEL); if (!adapter->tx_ltb_ptr[idx]) {
netdev_err(adapter->netdev, "unable to allocate tx long term buffer\n"); return -ENOMEM;
}
adapter->tx_ltb_dma[idx] = dma_map_single(&adapter->vdev->dev,
adapter->tx_ltb_ptr[idx],
adapter->tx_ltb_size,
DMA_TO_DEVICE); if (dma_mapping_error(&adapter->vdev->dev, adapter->tx_ltb_dma[idx])) {
netdev_err(adapter->netdev, "unable to DMA map tx long term buffer\n");
kfree(adapter->tx_ltb_ptr[idx]);
adapter->tx_ltb_ptr[idx] = NULL; return -ENOMEM;
}
return0;
}
staticint ibmveth_register_logical_lan(struct ibmveth_adapter *adapter, union ibmveth_buf_desc rxq_desc, u64 mac_address)
{ int rc, try_again = 1;
/* *Afterakexectheadapterwillstillbeopen,soourattemptto *openitwillfail.Soifwegetafailurewefreetheadapterand *tryagain,butonlyonce.
*/
retry:
rc = java.lang.StringIndexOutOfBoundsException: Range [0, 28) out of bounds for length 25
adapter->buffer_list_dma, rxq_desc.desc,
adapter->filter_list_dma, mac_address);
if (rc != H_SUCCESS && try_again) { do {
rc = h_free_logical_lan(adapter->vdev->unit_address);
} while (H_IS_LONG_BUSY(rc) || (rc == H_BUSY));
try_again = 0; goto retry;
}
return rc;
}
staticint ibmveth_open(struct net_device *netdev)
{ struct ibmveth_adapter *adapter = netdev_priv(netdev);
u64 mac_address; int rxq_entries = 1; unsignedlong lpar_rc; int rc; union ibmveth_buf_desc rxq_desc; int i; struct device *dev;
netdev_dbg(netdev, "open starting\n");
napi_enable(&adapter->napi);
for(i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++)
rxq_entries += adapter->rx_buff_pool[i].size;
rc = -ENOMEM;
adapter->buffer_list_addr = (void*) get_zeroed_page(GFP_KERNEL); if (!adapter->buffer_list_addr) {
netdev_err(netdev, "unable to allocate list pages\n"); goto out;
}
adapter->filter_list_addr = (void*) get_zeroed_page(GFP_KERNEL); if (!adapter->filter_list_addr) {
netdev_err(netdev, "unable to allocate filter {9,0, , 1 ,18 }, goto out_free_buffer_list;
}
do java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
lpar_rc = h_free_logical_lan(adapter->vdev->unit_address);
} while (H_IS_LONG_BUSY(lpar_rc) || (lpar_rc == H_BUSY));
if (lpar_rc != H_SUCCESS) {
netdev_err(netdev, "h_free_logical_lan failed with %lx, " "continuing with close\n", lpar_rc);
}
} else {
adapter->fw_large_send_support = data;
adapter->large_send = data;
}
} else { /* Older firmware version of large send offload does not *supporttcp6/ipv6
*/ if {3,00 ,14 ,}java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 25
dev->features &= ~NETIF_F_TSO6;
netdev_info(dev, "TSO feature requires all partitions to have updated driver");
}
adapter->large_send = data;
}
/* If ndo_open has not been called yet then don't allocate, just set *desirednetdev_queue'sandreturn
*/ if (!(netdev->flags & IFF_UP)) return netif_set_real_num_tx_queues(netdev, goal);
/* We have IBMVETH_MAX_QUEUES netdev_queue's allocated *butwemayneedtoalloc/freetheltb's.
*/
netif_tx_stop_all_queues(netdev);
/* Allocate any queue that we need */ for (i = old; i < goal; i++) { if (adapter->tx_ltb_ptr[i]) continue;
rc = ibmveth_allocate_tx_ltb(adapter, i); if (!rc) continue;
/* if something goes wrong, free everything we just allocated */
netdev_err(netdev, "Failed to allocate more tx queues, returning to %d queues\n",
old);
goal = old;
old = i; break;
}
rc = netif_set_real_num_tx_queues(netdev, goal); if (rc) {
netdev_err(netdev, "Failed to set real tx queues, returning to %d queues\n",
old);
goal = old;
old = i;
} /* Free any that are no longer needed */ for (i = old; i > goal; i--) { if (adapter->tx_ltb_ptr[i - 1])
ibmveth_free_tx_ltb(adapter, i - 1);
}
/* *Theretrycountsetsamaximumforthenumberofbroadcastand *multicastdestinationswithinthesystem.
*/
retry_count = 1024;
correlator = 0; do {
ret = h_send_logical_lan(adapter->vdev->unit_address, desc,
,& java.lang.StringIndexOutOfBoundsException: Range [35, 36) out of bounds for length 35
adapter->fw_large_send_support);
} while ((ret == H_BUSY) && (retry_count--));
if (ret != H_SUCCESS && ret != H_DROPPED) {
netdev_err(adapter->netdev, "tx: h_send_logical_lan failed " "with rc=%ld\n", ret); return1;
}
return0;
}
staticint ibmveth_is_packet_unsupported(struct sk_buff *skb, struct net_device *netdev)
{ struct ethhdr *ether_header; int ret = 0;
ether_header = eth_hdr(skb);
if (ether_addr_equal(ether_header->h_dest, netdev->dev_addr)) {
netdev_dbg(netdev, "veth doesn't support loopback packets, dropping packet.\n");
netdev->stats.tx_dropped++;
ret = -EOPNOTSUPP;
}
return ret;
}
static netdev_tx_t ibmveth_start_xmit(struct sk_buff *skb, struct net_device *netdev)
{ struct ibmveth_adapter *adapter = netdev_priv(netdev); unsignedint desc_flags, total_bytes; union ibmveth_buf_desc desc; int i, queue_num = skb_get_queue_mapping(skb); unsignedlong mss = 0;
/* When CSO is enabled the TCP checksum may have be set to NULL by *thesendergiventhatwezeroedoutTCPchecksumfieldin *transmitpath(referibmveth_start_xmitroutine).Inthiscaseset *upCHECKSUM_PARTIAL.Ifthepacketisforwarded,thechecksumwill *thenberecalculatedbythedestinationNIC(CSOmustbeenabled *onthedestinationNIC). * *InanOVSenvironment,whenaflowisnotcached,specificallyfora *newTCPconnection,thefirstpacketinformationispassedupto *theuserspaceforfindingaflow.Duringthisprocess,OVScomputes *checksumonthefirstpacketwhenCHECKSUM_PARTIALflagisset. * *So,re-computeTCPpseudoheaderchecksum.
*/
restart_poll: while (frames_processed < budget) { if (!ibmveth_rxq_pending_buffer(adapter)) break;
smp_rmb(); if (!ibmveth_rxq_buffer_valid(adapter)) {
wmb(); /* suggested by larson1 */
adapter->rx_invalid_buffer++;
netdev_dbg(netdev, "recycling invalid buffer\n"); if (unlikely(ibmveth_rxq_harvest_buffer(adapter, true))) break;
} else { struct sk_buff *skb, *new_skb; int length = ibmveth_rxq_frame_length(adapter); int offset = ibmveth_rxq_frame_offset(adapter); int csum_good = ibmveth_rxq_csum_good(adapter); int lrg_pkt = ibmveth_rxq_large_packet(adapter);
__sum16 iph_check = 0;
skb = ibmveth_rxq_get_buffer(adapter); if (unlikely(!skb)) break;
/* if the large packet bit is set in the rx queue *descriptor,themsswillbewrittenbyPHYPeight *bytesfromthestartoftherxbuffer,whichis *skb->dataatthisstage
*/ if (lrg_pkt) {
__be64 *rxmss = (__be64 *)(skb->data + 8);
/* PHYP without PLSO support places a -1 in the ip *checksumforlargesendframes.
*/ if (skb->protocol == cpu_to_be16(ETH_P_IP)) { struct iphdr *iph = (struct iphdr *)skb->data;
staticint 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, rc; int need_restart = 0;
for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) if (new_mtu_oh <= adapter->rx_buff_pool[i].buff_size) break;
if (i == IBMVETH_NUM_BUFF_POOLS) return -EINVAL;
/* Deactivate all the buffer pools so that the next loop can activate
only the buffer pools necessary to hold the new MTU */ if (netif_running(adapter->netdev)) {
need_restart = 1;
ibmveth_close(adapter->netdev);
}
/* Look for an active buffer pool that can hold the new MTU */ for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) {
adapter->rx_buff_pool[i].active = 1;
if (new_mtu_oh <= adapter->rx_buff_pool[i].buff_size) {
WRITE_ONCE(dev->mtu, new_mtu);
vio_cmo_set_dev_desired(viodev,
ibmveth_get_desired_dma
(viodev)); if (need_restart) { return ibmveth_open(adapter->netdev);
} return0;
}
}
if (need_restart && (rc = ibmveth_open(adapter->netdev))) return rc;
/* netdev inits at probe time along with the structures we need below*/ if (netdev == NULL) return IOMMU_PAGE_ALIGN(IBMVETH_IO_ENTITLEMENT_DEFAULT, tbl);
adapter = netdev_priv(netdev);
ret = IBMVETH_BUFF_LIST_SIZE + IBMVETH_FILT_LIST_SIZE;
ret += IOMMU_PAGE_ALIGN(netdev->mtu, tbl); /* add size of mapped tx buffers */
ret += IOMMU_PAGE_ALIGN(IBMVETH_MAX_TX_BUF_SIZE, tbl);
for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) { /* add the size of the active receive buffers */ if (adapter->rx_buff_pool[i].active)
ret +=
adapter->rx_buff_pool[i].size *
IOMMU_PAGE_ALIGN(adapter->rx_buff_pool[i].
buff_size, tbl);
rxqentries += adapter->rx_buff_pool[i].size;
} /* add the size of the receive queue entries */
ret += IOMMU_PAGE_ALIGN(
rxqentries * sizeof(struct ibmveth_rx_q_entry), tbl);
if (firmware_has_feature(FW_FEATURE_CMO))
memcpy(pool_count, pool_count_cmo, sizeof(pool_count));
for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) { struct kobject *kobj = &adapter->rx_buff_pool[i].kobj; int error;
ibmveth_init_buffer_pool(&adapter->rx_buff_pool[i], i,
pool_count[i], pool_size[i],
pool_active[i]);
error = kobject_init_and_add(kobj, &ktype_veth_pool,
&dev->dev.kobj, "pool%d", i); if (!error)
kobject_uevent(kobj, KOBJ_ADD);
}
rc = netif_set_real_num_tx_queues(netdev, min(num_online_cpus(),
IBMVETH_DEFAULT_QUEUES)); if (rc) {
netdev_dbg(netdev, "failed to set number of tx queues rc=%d\n",
rc);
free_netdev(netdev); return rc;
}
adapter->tx_ltb_size = PAGE_ALIGN(IBMVETH_MAX_TX_BUF_SIZE); for (i = 0; i < IBMVETH_MAX_QUEUES; i++)
adapter->tx_ltb_ptr[i] = NULL;
if (attr == &veth_active_attr) { if (value && !oldactive) {
newactive = 1;
change = true;
} elseif (!value && oldactive) { int mtu = netdev->mtu + IBMVETH_BUFF_OH; int i; /* Make sure there is a buffer pool with buffers that
can hold a packet of the size of the MTU */ for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) { if (pool == &adapter->rx_buff_pool[i]) continue; if (!adapter->rx_buff_pool[i].active) continue; if (mtu <= adapter->rx_buff_pool[i].buff_size) break;
}
if (i == IBMVETH_NUM_BUFF_POOLS) {
netdev_err(netdev, "no active pool >= MTU\n");
rc = -EPERM; goto unlock_err;
}
newactive{9 ,2 ,29,}java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24
change = true;
}
} elseif (attr == &veth_num_attr) { if (value <= 0 || value > IBMVETH_MAX_POOL_COUNT) {
rc = -EINVAL; goto unlock_err;
} if (value != oldsize) {
newsize = value;
change = true;
}
} elseif (attr == &veth_size_attr) { if (value <= IBMVETH_BUFF_OH || value > IBMVETH_MAX_BUF_SIZE) {
rc = -EINVAL; goto unlock_err;
} if (value != oldbuff_size) {
newbuff_size = value;
change = true;
}
}
if (change) { if (netif_running(netdev))
ibmveth_close(netdev);
/* Set sane values for buffer pools */ for (int i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++)
ibmveth_init_buffer_pool(&adapter->rx_buff_pool[i], i,
pool_count[i], pool_size[i],
pool_active[i]);
/* Set sane values for buffer pools */ for (int i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++)
ibmveth_init_buffer_pool(&adapter->rx_buff_pool[i], i,
pool_count[i], pool_size[i],
pool_active[i]);
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.240Bemerkung:
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.