static int efx_begin_loopback(struct efx_tx_queue *tx_queue) { struct efx_nic *efx = tx_queue->efx; struct efx_loopback_state *state = efx->loopback_selftest; struct efx_loopback_payload *payload; struct sk_buff *skb; int i; netdev_tx_t rc; /* Transmit N copies of buffer */ for (i = 0; i < state->packet_count; i++) { /* Allocate an skb, holding an extra reference for * transmit completion counting */ skb = alloc_skb(sizeof(state->payload), GFP_KERNEL); if (!skb) return -ENOMEM; state->skbs[i] = skb; skb_get(skb); /* Copy the payload in, incrementing the source address to * exercise the rss vectors */ payload = ((struct efx_loopback_payload *) skb_put(skb, sizeof(state->payload))); memcpy(payload, &state->payload, sizeof(state->payload)); payload->ip.saddr = htonl(INADDR_LOOPBACK | (i << 2)); /* Ensure everything we've written is visible to the * interrupt handler. */ smp_wmb(); if (efx_dev_registered(efx)) netif_tx_lock_bh(efx->net_dev); rc = efx_enqueue_skb(tx_queue, skb); if (efx_dev_registered(efx)) netif_tx_unlock_bh(efx->net_dev); if (rc != NETDEV_TX_OK) { EFX_ERR(efx, "TX queue %d could not transmit packet %d " "of %d in %s loopback test\n", tx_queue->queue, i + 1, state->packet_count, LOOPBACK_MODE(efx)); /* Defer cleaning up the other skbs for the caller */ kfree_skb(skb); return -EPIPE; } } return 0; }
/* Initiate a packet transmission. We use one channel per CPU * (sharing when we have more CPUs than channels). On Falcon, the TX * completion events will be directed back to the CPU that transmitted * the packet, which should be cache-efficient. * * Context: non-blocking. * Note that returning anything other than NETDEV_TX_OK will cause the * OS to free the skb. */ netdev_tx_t efx_hard_start_xmit(struct sk_buff *skb, struct net_device *net_dev) { struct efx_nic *efx = netdev_priv(net_dev); struct efx_tx_queue *tx_queue; if (unlikely(efx->port_inhibited)) return NETDEV_TX_BUSY; tx_queue = efx_get_tx_queue(efx, skb_get_queue_mapping(skb), skb->ip_summed == CHECKSUM_PARTIAL ? EFX_TXQ_TYPE_OFFLOAD : 0); return efx_enqueue_skb(tx_queue, skb); }
/* Initiate a packet transmission on the specified TX queue. * Note that returning anything other than NETDEV_TX_OK will cause the * OS to free the skb. * * This function is split out from efx_hard_start_xmit to allow the * loopback test to direct packets via specific TX queues. It is * therefore a non-static inline, so as not to penalise performance * for non-loopback transmissions. * * Context: netif_tx_lock held */ inline netdev_tx_t efx_xmit(struct efx_nic *efx, struct efx_tx_queue *tx_queue, struct sk_buff *skb) { netdev_tx_t rc; /* Map fragments for DMA and add to TX queue */ rc = efx_enqueue_skb(tx_queue, skb); if (unlikely(rc != NETDEV_TX_OK)) goto out; /* Update last TX timer */ efx->net_dev->trans_start = jiffies; out: return rc; }
/* Initiate a packet transmission. We use one channel per CPU * (sharing when we have more CPUs than channels). On Falcon, the TX * completion events will be directed back to the CPU that transmitted * the packet, which should be cache-efficient. * * Context: non-blocking. * Note that returning anything other than NETDEV_TX_OK will cause the * OS to free the skb. */ netdev_tx_t efx_hard_start_xmit(struct sk_buff *skb, struct net_device *net_dev) { struct efx_nic *efx = netdev_priv(net_dev); struct efx_tx_queue *tx_queue; unsigned index, type; EFX_WARN_ON_PARANOID(!netif_device_present(net_dev)); index = skb_get_queue_mapping(skb); type = skb->ip_summed == CHECKSUM_PARTIAL ? EFX_TXQ_TYPE_OFFLOAD : 0; if (index >= efx->n_tx_channels) { index -= efx->n_tx_channels; type |= EFX_TXQ_TYPE_HIGHPRI; } tx_queue = efx_get_tx_queue(efx, index, type); return efx_enqueue_skb(tx_queue, skb); }