aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/sfc
diff options
context:
space:
mode:
authorStuart Hodgson <smhodgson@solarflare.com>2012-07-18 04:52:11 -0400
committerBen Hutchings <bhutchings@solarflare.com>2012-09-07 16:13:39 -0400
commitc31e5f9f97fba32103c8bdd286eee8e3aefbee31 (patch)
tree33fd1ed248a3f4812686af9a2b749c6e6f4b4090 /drivers/net/ethernet/sfc
parent79d68b370074044d7a9dd789ee103ffe5ef00bda (diff)
sfc: Add channel specific receive_skb handler and post_remove callback
Allows an extra channel to override the standard receive_skb handler and also for extra non generic operations to be performed on remove. Also set default rx strategy so only skbs can be delivered to the PTP receive function. Signed-off-by: Stuart Hodgson <smhodgson@solarflare.com> Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Diffstat (limited to 'drivers/net/ethernet/sfc')
-rw-r--r--drivers/net/ethernet/sfc/efx.c6
-rw-r--r--drivers/net/ethernet/sfc/efx.h1
-rw-r--r--drivers/net/ethernet/sfc/net_driver.h3
-rw-r--r--drivers/net/ethernet/sfc/rx.c13
4 files changed, 21 insertions, 2 deletions
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 342a1f31e5b8..8b79a6413fe4 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -734,6 +734,7 @@ static void efx_remove_channel(struct efx_channel *channel)
734 efx_for_each_possible_channel_tx_queue(tx_queue, channel) 734 efx_for_each_possible_channel_tx_queue(tx_queue, channel)
735 efx_remove_tx_queue(tx_queue); 735 efx_remove_tx_queue(tx_queue);
736 efx_remove_eventq(channel); 736 efx_remove_eventq(channel);
737 channel->type->post_remove(channel);
737} 738}
738 739
739static void efx_remove_channels(struct efx_nic *efx) 740static void efx_remove_channels(struct efx_nic *efx)
@@ -852,6 +853,7 @@ void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue)
852 853
853static const struct efx_channel_type efx_default_channel_type = { 854static const struct efx_channel_type efx_default_channel_type = {
854 .pre_probe = efx_channel_dummy_op_int, 855 .pre_probe = efx_channel_dummy_op_int,
856 .post_remove = efx_channel_dummy_op_void,
855 .get_name = efx_get_channel_name, 857 .get_name = efx_get_channel_name,
856 .copy = efx_copy_channel, 858 .copy = efx_copy_channel,
857 .keep_eventq = false, 859 .keep_eventq = false,
@@ -862,6 +864,10 @@ int efx_channel_dummy_op_int(struct efx_channel *channel)
862 return 0; 864 return 0;
863} 865}
864 866
867void efx_channel_dummy_op_void(struct efx_channel *channel)
868{
869}
870
865/************************************************************************** 871/**************************************************************************
866 * 872 *
867 * Port handling 873 * Port handling
diff --git a/drivers/net/ethernet/sfc/efx.h b/drivers/net/ethernet/sfc/efx.h
index 70755c97251a..f11170bc48bf 100644
--- a/drivers/net/ethernet/sfc/efx.h
+++ b/drivers/net/ethernet/sfc/efx.h
@@ -102,6 +102,7 @@ static inline void efx_filter_rfs_expire(struct efx_channel *channel) {}
102 102
103/* Channels */ 103/* Channels */
104extern int efx_channel_dummy_op_int(struct efx_channel *channel); 104extern int efx_channel_dummy_op_int(struct efx_channel *channel);
105extern void efx_channel_dummy_op_void(struct efx_channel *channel);
105extern void efx_process_channel_now(struct efx_channel *channel); 106extern void efx_process_channel_now(struct efx_channel *channel);
106extern int 107extern int
107efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries); 108efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries);
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index 24a78a35bddb..0f0926e68963 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -393,14 +393,17 @@ struct efx_channel {
393 * @get_name: Generate the channel's name (used for its IRQ handler) 393 * @get_name: Generate the channel's name (used for its IRQ handler)
394 * @copy: Copy the channel state prior to reallocation. May be %NULL if 394 * @copy: Copy the channel state prior to reallocation. May be %NULL if
395 * reallocation is not supported. 395 * reallocation is not supported.
396 * @receive_skb: Handle an skb ready to be passed to netif_receive_skb()
396 * @keep_eventq: Flag for whether event queue should be kept initialised 397 * @keep_eventq: Flag for whether event queue should be kept initialised
397 * while the device is stopped 398 * while the device is stopped
398 */ 399 */
399struct efx_channel_type { 400struct efx_channel_type {
400 void (*handle_no_channel)(struct efx_nic *); 401 void (*handle_no_channel)(struct efx_nic *);
401 int (*pre_probe)(struct efx_channel *); 402 int (*pre_probe)(struct efx_channel *);
403 void (*post_remove)(struct efx_channel *);
402 void (*get_name)(struct efx_channel *, char *buf, size_t len); 404 void (*get_name)(struct efx_channel *, char *buf, size_t len);
403 struct efx_channel *(*copy)(const struct efx_channel *); 405 struct efx_channel *(*copy)(const struct efx_channel *);
406 void (*receive_skb)(struct efx_channel *, struct sk_buff *);
404 bool keep_eventq; 407 bool keep_eventq;
405}; 408};
406 409
diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c
index e997f83f14f5..9e0ad1b75c33 100644
--- a/drivers/net/ethernet/sfc/rx.c
+++ b/drivers/net/ethernet/sfc/rx.c
@@ -575,7 +575,10 @@ static void efx_rx_deliver(struct efx_channel *channel,
575 skb_record_rx_queue(skb, channel->rx_queue.core_index); 575 skb_record_rx_queue(skb, channel->rx_queue.core_index);
576 576
577 /* Pass the packet up */ 577 /* Pass the packet up */
578 netif_receive_skb(skb); 578 if (channel->type->receive_skb)
579 channel->type->receive_skb(channel, skb);
580 else
581 netif_receive_skb(skb);
579 582
580 /* Update allocation strategy method */ 583 /* Update allocation strategy method */
581 channel->rx_alloc_level += RX_ALLOC_FACTOR_SKB; 584 channel->rx_alloc_level += RX_ALLOC_FACTOR_SKB;
@@ -617,7 +620,8 @@ void __efx_rx_packet(struct efx_channel *channel, struct efx_rx_buffer *rx_buf)
617 if (unlikely(!(efx->net_dev->features & NETIF_F_RXCSUM))) 620 if (unlikely(!(efx->net_dev->features & NETIF_F_RXCSUM)))
618 rx_buf->flags &= ~EFX_RX_PKT_CSUMMED; 621 rx_buf->flags &= ~EFX_RX_PKT_CSUMMED;
619 622
620 if (likely(rx_buf->flags & (EFX_RX_BUF_PAGE | EFX_RX_PKT_CSUMMED))) 623 if (likely(rx_buf->flags & (EFX_RX_BUF_PAGE | EFX_RX_PKT_CSUMMED)) &&
624 !channel->type->receive_skb)
621 efx_rx_packet_gro(channel, rx_buf, eh); 625 efx_rx_packet_gro(channel, rx_buf, eh);
622 else 626 else
623 efx_rx_deliver(channel, rx_buf); 627 efx_rx_deliver(channel, rx_buf);
@@ -627,6 +631,11 @@ void efx_rx_strategy(struct efx_channel *channel)
627{ 631{
628 enum efx_rx_alloc_method method = rx_alloc_method; 632 enum efx_rx_alloc_method method = rx_alloc_method;
629 633
634 if (channel->type->receive_skb) {
635 channel->rx_alloc_push_pages = false;
636 return;
637 }
638
630 /* Only makes sense to use page based allocation if GRO is enabled */ 639 /* Only makes sense to use page based allocation if GRO is enabled */
631 if (!(channel->efx->net_dev->features & NETIF_F_GRO)) { 640 if (!(channel->efx->net_dev->features & NETIF_F_GRO)) {
632 method = RX_ALLOC_METHOD_SKB; 641 method = RX_ALLOC_METHOD_SKB;