Re: [PATCH net-next,v2] net: rename ndo_setup_tc to ndo_setup_offload

2018-07-19 Thread Martin Habets
On 19/07/18 01:11, Pablo Neira Ayuso wrote:
> One of the recurring complaints is that we do not have, as a driver
> writer, a central location from which we would be fed offloading rules
> into a NIC. This was brought up again during Netconf'18 in Boston.
> 
> This patch just renames ndo_setup_tc to ndo_setup_offload as a very
> early initial work to prepare for follow up patch that discuss unified
> flow representation for the existing offload programming APIs.
> 
> Signed-off-by: Pablo Neira Ayuso 
> Acked-by: Jiri Pirko 
> Acked-by: Jakub Kicinski 

Acked-by: Martin Habets 

> ---
> v2: Missing function definition update in drivers/net/ethernet/sfc/falcon/tx.c
> apparently I forgot to turn on that driver when doing compile-testing,
> problem spotted by Martin Habets. Keeping Jakub and Jiri Acked-by tags,
> as this is the only change in the v1 patch.
> 



Re: [PATCH net-next] net: rename ndo_setup_tc to ndo_setup_offload

2018-07-18 Thread Martin Habets
On 18/07/18 17:14, Pablo Neira Ayuso wrote:
> One of the recurring complaints is that we do not have, as a driver
> writer, a central location from which we would be fed offloading rules
> into a NIC. This was brought up again during Netconf'18 in Boston.
> 
> This patch just renames ndo_setup_tc to ndo_setup_offload as a very
> early initial work to prepare for follow up patches that discuss/propose
> unified flow representation for the existing offload programming APIs:
> ethtool_rxnfc, cls_flower, cls_u32 and (probably, not yet upstream)
> conntrack.
> 
> Signed-off-by: Pablo Neira Ayuso 
> ---
>  drivers/net/ethernet/amd/xgbe/xgbe-drv.c|  6 +++---
>  drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c |  6 +++---
>  drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h |  4 ++--
>  drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c|  2 +-
>  drivers/net/ethernet/broadcom/bnxt/bnxt.c   |  6 +++---
>  drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c   |  6 +++---
>  drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c |  6 +++---
>  drivers/net/ethernet/freescale/dpaa/dpaa_eth.c  |  6 +++---
>  drivers/net/ethernet/hisilicon/hns3/hns3_enet.c |  6 +++---
>  drivers/net/ethernet/intel/fm10k/fm10k_netdev.c |  6 +++---
>  drivers/net/ethernet/intel/i40e/i40e_main.c |  6 +++---
>  drivers/net/ethernet/intel/i40evf/i40evf_main.c |  8 
>  drivers/net/ethernet/intel/igb/igb_main.c   |  6 +++---
>  drivers/net/ethernet/intel/ixgbe/ixgbe_main.c   |  6 +++---
>  drivers/net/ethernet/mellanox/mlx4/en_netdev.c  |  9 +
>  drivers/net/ethernet/mellanox/mlx5/core/en_main.c   |  6 +++---
>  drivers/net/ethernet/mellanox/mlx5/core/en_rep.c|  6 +++---
>  drivers/net/ethernet/mellanox/mlxsw/spectrum.c  |  6 +++---
>  drivers/net/ethernet/netronome/nfp/nfp_net_common.c |  2 +-
>  drivers/net/ethernet/netronome/nfp/nfp_net_repr.c   |  2 +-
>  drivers/net/ethernet/netronome/nfp/nfp_port.c   |  4 ++--
>  drivers/net/ethernet/netronome/nfp/nfp_port.h   |  4 ++--
>  drivers/net/ethernet/sfc/efx.c  |  2 +-
>  drivers/net/ethernet/sfc/efx.h  |  4 ++--
>  drivers/net/ethernet/sfc/falcon/efx.c   |  2 +-
>  drivers/net/ethernet/sfc/falcon/efx.h   |  4 ++--
>  drivers/net/ethernet/sfc/tx.c   |  4 ++--

You changed the function definition in drivers/net/ethernet/sfc/falcon/efx.h, 
but missed the actual
function implementation in drivers/net/ethernet/sfc/falcon/tx.c.
Other than that it looks good to me.

Best regards,
Martin

>  drivers/net/ethernet/stmicro/stmmac/stmmac_main.c   |  6 +++---
>  drivers/net/ethernet/ti/netcp_core.c|  6 +++---
>  drivers/net/netdevsim/netdev.c  |  5 +++--
>  include/linux/netdevice.h   | 18 +-
>  net/dsa/slave.c |  7 ---
>  net/sched/cls_api.c |  6 +++---
>  net/sched/sch_cbs.c |  8 
>  net/sched/sch_etf.c |  8 
>  net/sched/sch_mq.c  |  8 
>  net/sched/sch_mqprio.c  | 16 
>  net/sched/sch_prio.c| 15 ---
>  net/sched/sch_red.c | 15 ---
>  39 files changed, 129 insertions(+), 124 deletions(-)
> 
> diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c 
> b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
> index 24f1053b8785..766864a35648 100644
> --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
> +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
> @@ -2246,8 +2246,8 @@ static void xgbe_poll_controller(struct net_device 
> *netdev)
>  }
>  #endif /* End CONFIG_NET_POLL_CONTROLLER */
>  
> -static int xgbe_setup_tc(struct net_device *netdev, enum tc_setup_type type,
> -  void *type_data)
> +static int xgbe_setup_offload(struct net_device *netdev,
> +   enum tc_setup_type type, void *type_data)
>  {
>   struct xgbe_prv_data *pdata = netdev_priv(netdev);
>   struct tc_mqprio_qopt *mqprio = type_data;
> @@ -2501,7 +2501,7 @@ static const struct net_device_ops xgbe_netdev_ops = {
>  #ifdef CONFIG_NET_POLL_CONTROLLER
>   .ndo_poll_controller= xgbe_poll_controller,
>  #endif
> - .ndo_setup_tc   = xgbe_setup_tc,
> + .ndo_setup_offload  = xgbe_setup_offload,
>   .ndo_fix_features   = xgbe_fix_features,
>   .ndo_set_features   = xgbe_set_features,
>   .ndo_udp_tunnel_add = xgbe_udp_tunnel_add,
> diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c 
> b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
> index 5a727d4729da..200a5938dfe5 100644
> --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
> +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
> @@ 

[PATCH v2 net-next] sfc: stop the TX queue before pushing new buffers

2018-05-24 Thread Martin Habets
efx_enqueue_skb() can push new buffers for the xmit_more functionality.
We must stops the TX queue before this or else the TX queue does not get
restarted and we get a netdev watchdog.

In the error handling we may now need to unwind more than 1 packet, and
we may need to push the new buffers onto the partner queue.

v2: In the error leg also push this queue if xmit_more is set

Fixes: e9117e5099ea ("sfc: Firmware-Assisted TSO version 2")
Reported-by: Jarod Wilson <ja...@redhat.com>
Tested-by: Jarod Wilson <ja...@redhat.com>
Signed-off-by: Martin Habets <mhab...@solarflare.com>
---

Dave, could you please also queue this patch up for stable?

 drivers/net/ethernet/sfc/tx.c |   33 +
 1 file changed, 25 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c
index cece961f2e82..c3ad564ac4c0 100644
--- a/drivers/net/ethernet/sfc/tx.c
+++ b/drivers/net/ethernet/sfc/tx.c
@@ -435,17 +435,18 @@ static int efx_tx_map_data(struct efx_tx_queue *tx_queue, 
struct sk_buff *skb,
} while (1);
 }
 
-/* Remove buffers put into a tx_queue.  None of the buffers must have
- * an skb attached.
+/* Remove buffers put into a tx_queue for the current packet.
+ * None of the buffers must have an skb attached.
  */
-static void efx_enqueue_unwind(struct efx_tx_queue *tx_queue)
+static void efx_enqueue_unwind(struct efx_tx_queue *tx_queue,
+  unsigned int insert_count)
 {
struct efx_tx_buffer *buffer;
unsigned int bytes_compl = 0;
unsigned int pkts_compl = 0;
 
/* Work backwards until we hit the original insert pointer value */
-   while (tx_queue->insert_count != tx_queue->write_count) {
+   while (tx_queue->insert_count != insert_count) {
--tx_queue->insert_count;
buffer = __efx_tx_queue_get_insert_buffer(tx_queue);
efx_dequeue_buffer(tx_queue, buffer, _compl, _compl);
@@ -504,6 +505,8 @@ static int efx_tx_tso_fallback(struct efx_tx_queue 
*tx_queue,
  */
 netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
 {
+   unsigned int old_insert_count = tx_queue->insert_count;
+   bool xmit_more = skb->xmit_more;
bool data_mapped = false;
unsigned int segments;
unsigned int skb_len;
@@ -553,8 +556,10 @@ netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, 
struct sk_buff *skb)
/* Update BQL */
netdev_tx_sent_queue(tx_queue->core_txq, skb_len);
 
+   efx_tx_maybe_stop_queue(tx_queue);
+
/* Pass off to hardware */
-   if (!skb->xmit_more || netif_xmit_stopped(tx_queue->core_txq)) {
+   if (!xmit_more || netif_xmit_stopped(tx_queue->core_txq)) {
struct efx_tx_queue *txq2 = efx_tx_queue_partner(tx_queue);
 
/* There could be packets left on the partner queue if those
@@ -577,14 +582,26 @@ netdev_tx_t efx_enqueue_skb(struct efx_tx_queue 
*tx_queue, struct sk_buff *skb)
tx_queue->tx_packets++;
}
 
-   efx_tx_maybe_stop_queue(tx_queue);
-
return NETDEV_TX_OK;
 
 
 err:
-   efx_enqueue_unwind(tx_queue);
+   efx_enqueue_unwind(tx_queue, old_insert_count);
dev_kfree_skb_any(skb);
+
+   /* If we're not expecting another transmit and we had something to push
+* on this queue or a partner queue then we need to push here to get the
+* previous packets out.
+*/
+   if (!xmit_more) {
+   struct efx_tx_queue *txq2 = efx_tx_queue_partner(tx_queue);
+
+   if (txq2->xmit_more_available)
+   efx_nic_push_buffers(txq2);
+
+   efx_nic_push_buffers(tx_queue);
+   }
+
return NETDEV_TX_OK;
 }
 


[PATCH net-next] sfc: stop the TX queue before pushing new buffers

2018-05-23 Thread Martin Habets
efx_enqueue_skb() can push new buffers for the xmit_more functionality.
We must stops the TX queue before this or else the TX queue does not get
restarted and we get a netdev watchdog.

In the error handling we may now need to unwind more than 1 packet, and
we may need to push the new buffers onto the partner queue.

Fixes: e9117e5099ea ("sfc: Firmware-Assisted TSO version 2")
Reported-by: Jarod Wilson <ja...@redhat.com>
Signed-off-by: Martin Habets <mhab...@solarflare.com>
---

Dave, could you please also queue up this patch for stable?

 drivers/net/ethernet/sfc/tx.c |   31 +++
 1 file changed, 23 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c
index cece961f2e82..17e0697f42d5 100644
--- a/drivers/net/ethernet/sfc/tx.c
+++ b/drivers/net/ethernet/sfc/tx.c
@@ -435,17 +435,18 @@ static int efx_tx_map_data(struct efx_tx_queue *tx_queue, 
struct sk_buff *skb,
} while (1);
 }
 
-/* Remove buffers put into a tx_queue.  None of the buffers must have
- * an skb attached.
+/* Remove buffers put into a tx_queue for the current packet.
+ * None of the buffers must have an skb attached.
  */
-static void efx_enqueue_unwind(struct efx_tx_queue *tx_queue)
+static void efx_enqueue_unwind(struct efx_tx_queue *tx_queue,
+  unsigned int insert_count)
 {
struct efx_tx_buffer *buffer;
unsigned int bytes_compl = 0;
unsigned int pkts_compl = 0;
 
/* Work backwards until we hit the original insert pointer value */
-   while (tx_queue->insert_count != tx_queue->write_count) {
+   while (tx_queue->insert_count != insert_count) {
--tx_queue->insert_count;
buffer = __efx_tx_queue_get_insert_buffer(tx_queue);
efx_dequeue_buffer(tx_queue, buffer, _compl, _compl);
@@ -504,6 +505,8 @@ static int efx_tx_tso_fallback(struct efx_tx_queue 
*tx_queue,
  */
 netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
 {
+   unsigned int old_insert_count = tx_queue->insert_count;
+   bool xmit_more = skb->xmit_more;
bool data_mapped = false;
unsigned int segments;
unsigned int skb_len;
@@ -553,8 +556,10 @@ netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, 
struct sk_buff *skb)
/* Update BQL */
netdev_tx_sent_queue(tx_queue->core_txq, skb_len);
 
+   efx_tx_maybe_stop_queue(tx_queue);
+
/* Pass off to hardware */
-   if (!skb->xmit_more || netif_xmit_stopped(tx_queue->core_txq)) {
+   if (!xmit_more || netif_xmit_stopped(tx_queue->core_txq)) {
struct efx_tx_queue *txq2 = efx_tx_queue_partner(tx_queue);
 
/* There could be packets left on the partner queue if those
@@ -577,14 +582,24 @@ netdev_tx_t efx_enqueue_skb(struct efx_tx_queue 
*tx_queue, struct sk_buff *skb)
tx_queue->tx_packets++;
}
 
-   efx_tx_maybe_stop_queue(tx_queue);
-
return NETDEV_TX_OK;
 
 
 err:
-   efx_enqueue_unwind(tx_queue);
+   efx_enqueue_unwind(tx_queue, old_insert_count);
dev_kfree_skb_any(skb);
+
+   /* If we're not expecting another transmit and we had something to push
+* on this queue or a partner queue then we need to push here to get the
+* previous packets out.
+*/
+   if (!xmit_more) {
+   struct efx_tx_queue *txq2 = efx_tx_queue_partner(tx_queue);
+
+   if (txq2->xmit_more_available)
+   efx_nic_push_buffers(txq2);
+   }
+
return NETDEV_TX_OK;
 }
 



[PATCH net-next] sfc: Add ethtool -m support for QSFP modules

2017-07-18 Thread Martin Habets
This also adds support for non-QSFP modules attached to QSFP.

Signed-off-by: Martin Habets <mhab...@solarflare.com>
---
 drivers/net/ethernet/sfc/mcdi_port.c |  224 +++---
 1 file changed, 181 insertions(+), 43 deletions(-)

diff --git a/drivers/net/ethernet/sfc/mcdi_port.c 
b/drivers/net/ethernet/sfc/mcdi_port.c
index c905971c5f3a..d3f96a8f743b 100644
--- a/drivers/net/ethernet/sfc/mcdi_port.c
+++ b/drivers/net/ethernet/sfc/mcdi_port.c
@@ -746,59 +746,171 @@ static const char *efx_mcdi_phy_test_name(struct efx_nic 
*efx,
return NULL;
 }
 
-#define SFP_PAGE_SIZE  128
-#define SFP_NUM_PAGES  2
-static int efx_mcdi_phy_get_module_eeprom(struct efx_nic *efx,
- struct ethtool_eeprom *ee, u8 *data)
+#define SFP_PAGE_SIZE  128
+#define SFF_DIAG_TYPE_OFFSET   92
+#define SFF_DIAG_ADDR_CHANGE   BIT(2)
+#define SFF_8079_NUM_PAGES 2
+#define SFF_8472_NUM_PAGES 4
+#define SFF_8436_NUM_PAGES 5
+#define SFF_DMT_LEVEL_OFFSET   94
+
+/** efx_mcdi_phy_get_module_eeprom_page() - Get a single page of module eeprom
+ * @efx:   NIC context
+ * @page:  EEPROM page number
+ * @data:  Destination data pointer
+ * @offset:Offset in page to copy from in to data
+ * @space: Space available in data
+ *
+ * Return:
+ *   >=0 - amount of data copied
+ *   <0  - error
+ */
+static int efx_mcdi_phy_get_module_eeprom_page(struct efx_nic *efx,
+  unsigned int page,
+  u8 *data, ssize_t offset,
+  ssize_t space)
 {
MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_PHY_MEDIA_INFO_OUT_LENMAX);
MCDI_DECLARE_BUF(inbuf, MC_CMD_GET_PHY_MEDIA_INFO_IN_LEN);
size_t outlen;
-   int rc;
unsigned int payload_len;
-   unsigned int space_remaining = ee->len;
-   unsigned int page;
-   unsigned int page_off;
unsigned int to_copy;
-   u8 *user_data = data;
+   int rc;
 
-   BUILD_BUG_ON(SFP_PAGE_SIZE * SFP_NUM_PAGES != ETH_MODULE_SFF_8079_LEN);
+   if (offset > SFP_PAGE_SIZE)
+   return -EINVAL;
 
-   page_off = ee->offset % SFP_PAGE_SIZE;
-   page = ee->offset / SFP_PAGE_SIZE;
+   to_copy = min(space, SFP_PAGE_SIZE - offset);
 
-   while (space_remaining && (page < SFP_NUM_PAGES)) {
-   MCDI_SET_DWORD(inbuf, GET_PHY_MEDIA_INFO_IN_PAGE, page);
+   MCDI_SET_DWORD(inbuf, GET_PHY_MEDIA_INFO_IN_PAGE, page);
+   rc = efx_mcdi_rpc_quiet(efx, MC_CMD_GET_PHY_MEDIA_INFO,
+   inbuf, sizeof(inbuf),
+   outbuf, sizeof(outbuf),
+   );
 
-   rc = efx_mcdi_rpc(efx, MC_CMD_GET_PHY_MEDIA_INFO,
- inbuf, sizeof(inbuf),
- outbuf, sizeof(outbuf),
- );
-   if (rc)
-   return rc;
+   if (rc)
+   return rc;
+
+   if (outlen < (MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_OFST +
+   SFP_PAGE_SIZE))
+   return -EIO;
+
+   payload_len = MCDI_DWORD(outbuf, GET_PHY_MEDIA_INFO_OUT_DATALEN);
+   if (payload_len != SFP_PAGE_SIZE)
+   return -EIO;
 
-   if (outlen < (MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_OFST +
- SFP_PAGE_SIZE))
-   return -EIO;
+   memcpy(data, MCDI_PTR(outbuf, GET_PHY_MEDIA_INFO_OUT_DATA) + offset,
+  to_copy);
 
-   payload_len = MCDI_DWORD(outbuf,
-GET_PHY_MEDIA_INFO_OUT_DATALEN);
-   if (payload_len != SFP_PAGE_SIZE)
-   return -EIO;
+   return to_copy;
+}
 
-   /* Copy as much as we can into data */
-   payload_len -= page_off;
-   to_copy = (space_remaining < payload_len) ?
-   space_remaining : payload_len;
+static int efx_mcdi_phy_get_module_eeprom_byte(struct efx_nic *efx,
+  unsigned int page,
+  u8 byte)
+{
+   int rc;
+   u8 data;
 
-   memcpy(user_data,
-  MCDI_PTR(outbuf, GET_PHY_MEDIA_INFO_OUT_DATA) + page_off,
-  to_copy);
+   rc = efx_mcdi_phy_get_module_eeprom_page(efx, page, , byte, 1);
+   if (rc == 1)
+   return data;
+
+   return rc;
+}
+
+static int efx_mcdi_phy_diag_type(struct efx_nic *efx)
+{
+   /* Page zero of the EEPROM includes the diagnostic type at byte 92. */
+   return efx_mcdi_phy_get_module_eeprom_byte(efx, 0,
+  SFF_DIAG_TYPE_OFFSET);
+}
 
-   space_remaining -= to_copy;
-   user_d

[PATCH net] sfc: Fix MCDI command size for filter operations

2017-06-22 Thread Martin Habets
The 8000 series adapters uses catch-all filters for encapsulated traffic
to support filtering VXLAN, NVGRE and GENEVE traffic.
This new filter functionality requires a longer MCDI command.
This patch increases the size of buffers on stack that were missed, which
fixes a kernel panic from the stack protector.

Fixes: 9b41080125176 ("sfc: insert catch-all filters for encapsulated traffic")
Signed-off-by: Martin Habets <mhab...@solarflare.com>
Acked-by: Edward Cree <ec...@solarflare.com>
Acked-by: Bert Kenward bkenw...@solarflare.com
---
 drivers/net/ethernet/sfc/ef10.c |8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index 78efb2822b86..a8089667fc5b 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -4172,7 +4172,7 @@ static s32 efx_ef10_filter_insert(struct efx_nic *efx,
 * recipients
 */
if (is_mc_recip) {
-   MCDI_DECLARE_BUF(inbuf, MC_CMD_FILTER_OP_IN_LEN);
+   MCDI_DECLARE_BUF(inbuf, MC_CMD_FILTER_OP_EXT_IN_LEN);
unsigned int depth, i;
 
memset(inbuf, 0, sizeof(inbuf));
@@ -4320,7 +4320,7 @@ static int efx_ef10_filter_remove_internal(struct efx_nic 
*efx,
efx_ef10_filter_set_entry(table, filter_idx, NULL, 0);
} else {
efx_mcdi_display_error(efx, MC_CMD_FILTER_OP,
-  MC_CMD_FILTER_OP_IN_LEN,
+  MC_CMD_FILTER_OP_EXT_IN_LEN,
   NULL, 0, rc);
}
}
@@ -4453,7 +4453,7 @@ static s32 efx_ef10_filter_rfs_insert(struct efx_nic *efx,
  struct efx_filter_spec *spec)
 {
struct efx_ef10_filter_table *table = efx->filter_state;
-   MCDI_DECLARE_BUF(inbuf, MC_CMD_FILTER_OP_IN_LEN);
+   MCDI_DECLARE_BUF(inbuf, MC_CMD_FILTER_OP_EXT_IN_LEN);
struct efx_filter_spec *saved_spec;
unsigned int hash, i, depth = 1;
bool replacing = false;
@@ -4940,7 +4940,7 @@ static void efx_ef10_filter_table_restore(struct efx_nic 
*efx)
 static void efx_ef10_filter_table_remove(struct efx_nic *efx)
 {
struct efx_ef10_filter_table *table = efx->filter_state;
-   MCDI_DECLARE_BUF(inbuf, MC_CMD_FILTER_OP_IN_LEN);
+   MCDI_DECLARE_BUF(inbuf, MC_CMD_FILTER_OP_EXT_IN_LEN);
struct efx_filter_spec *spec;
unsigned int filter_idx;
int rc;


Re: Getting a handle on all these new NIC features

2017-01-20 Thread Martin Habets
Hi Tom,

On 17/01/17 22:05, Tom Herbert wrote:
> There was some discussion about the problems of dealing with the
> explosion of NIC features in the mlx directory restructuring proposal,
> but I think the is a deeper issue here that should be discussed.
> 
> It's hard not to notice that there has been quite a proliferation of
> NIC features in several drivers. This trend had resulted in very
> complex driver code that may or may not segment individual features.
> One visible manifestation of this is number of ndo functions which is
> somewhere around seventy-five now.
> 
> I suspect the vast majority of these advances NIC features (e.g.
> bridging, UDP offloads, tc offload, etc.) are only relevant to some of
> the people some of the time. The problem we have, in this case those
> of us that are attempting to deploy and maintain NICs at scale, is
> when we have to deal with the ramifications of these features being
> intertwined with core driver functionality that is relevant to
> everyone. This becomes very obvious when we need to backport drivers
> from later versions of kernel.
> 
> I realize that backports of a driver is not a specific concern of the
> Linux kernel, but nevertheless this is a real problem and a fact of
> life for many users. Rebasing the full kernel is still a major effort
> and it seems the best we could ever do is one rebase per year. In the
> interim we need to occasionally backport drivers. Backporting drivers
> is difficult precisely because of new features or API changes to
> existing ones. These sort of changes tend to have a spiderweb of
> dependencies in other parts of the stack so that the number of patches
> we need to cherry-pick goes way beyond those that touch the driver we
> are interested in.

For the sfc driver (Solarflare Adapters) we currently do backports internally 
for:
 - RedHat Enterprise Linux5.10,  5.11
 - RedHat Enterprise Linux6.5, 6.6, 6.7, 6.8
   - Redhat Messaging Realtime and Grid   2.5
 - RedHat Enterprise Linux7.0, 7.1, 7.2
   - RedHat Enterprise Linux for Realtime 7.1, 7.2
 - SuSE Linux Enterprise Server 11sp3, sp4
   - SuSE Linux Enterprise RealTime Extension 11  
 - SuSE Linux Enterprise Server 12base release, sp1
 - Canonical Ubuntu Server LTS14.04, 16.04
 - Canonical Ubuntu Server-
 - Debian 7 "Wheezy"  7.X
 - Debian 8 "Jessie"  8.X
 - Linux  2.6.18 to 4.9-rc1

We update this list as needed, and always try to support the latest kernel.
I do not know if that would cover the kernel version you are using.

Best regards,
Martin

> Currently we (FB) need to backport two NIC drivers. I've already gave
> details of backporting mlx5 on the thread to restructure the driver
> directories. The other driver being backporting seems to suffer from
> the same type of feature complexity.
> 
> In short, I would like to ask if driver maintainers to start to
> modularize driver features. If something being added is obviously a
> narrow feature that only a subset of users will need can we allow
> config options to #ifdef those out somehow? Furthermore can the file
> and directory structure of drivers reflect that; our lives would be
> _so_ much simpler to maintain drivers in production if we have such
> modularity and the ability to build drivers with the features of our
> choosing.
> 
> Thanks,
> Tom


[PATCH net] sfc: push partner queue for skb->xmit_more

2015-11-02 Thread Martin Habets
When the IP stack passes SKBs the sfc driver puts them in 2 different TX
queues (called partners), one for checksummed and one for not checksummed.
If the SKB has xmit_more set the driver will delay pushing the work to the
NIC.

When later it does decide to push the buffers this patch ensures it also
pushes the partner queue, if that also has any delayed work. Before this
fix the work in the partner queue would be left for a long time and cause
a netdev watchdog.

Fixes: 70b33fb ("sfc: add support for skb->xmit_more")

Reported-by: Jianlin Shi <ji...@redhat.com>
Signed-off-by: Martin Habets <mhab...@solarflare.com>
---
 drivers/net/ethernet/sfc/ef10.c   |  4 +++-
 drivers/net/ethernet/sfc/farch.c  |  4 +++-
 drivers/net/ethernet/sfc/net_driver.h |  2 ++
 drivers/net/ethernet/sfc/tx.c | 30 --
 4 files changed, 36 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index ff649ebef637..286cc6b69d57 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -1849,7 +1849,9 @@ static void efx_ef10_tx_write(struct efx_tx_queue 
*tx_queue)
unsigned int write_ptr;
efx_qword_t *txd;
 
-   BUG_ON(tx_queue->write_count == tx_queue->insert_count);
+   tx_queue->xmit_more_available = false;
+   if (unlikely(tx_queue->write_count == tx_queue->insert_count))
+   return;
 
do {
write_ptr = tx_queue->write_count & tx_queue->ptr_mask;
diff --git a/drivers/net/ethernet/sfc/farch.c b/drivers/net/ethernet/sfc/farch.c
index f08266f0eca2..5a1c5a8f278a 100644
--- a/drivers/net/ethernet/sfc/farch.c
+++ b/drivers/net/ethernet/sfc/farch.c
@@ -321,7 +321,9 @@ void efx_farch_tx_write(struct efx_tx_queue *tx_queue)
unsigned write_ptr;
unsigned old_write_count = tx_queue->write_count;
 
-   BUG_ON(tx_queue->write_count == tx_queue->insert_count);
+   tx_queue->xmit_more_available = false;
+   if (unlikely(tx_queue->write_count == tx_queue->insert_count))
+   return;
 
do {
write_ptr = tx_queue->write_count & tx_queue->ptr_mask;
diff --git a/drivers/net/ethernet/sfc/net_driver.h 
b/drivers/net/ethernet/sfc/net_driver.h
index c530e1c4cb4f..24038ef96d9f 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -219,6 +219,7 @@ struct efx_tx_buffer {
  * @tso_packets: Number of packets via the TSO xmit path
  * @pushes: Number of times the TX push feature has been used
  * @pio_packets: Number of times the TX PIO feature has been used
+ * @xmit_more_available: Are any packets waiting to be pushed to the NIC
  * @empty_read_count: If the completion path has seen the queue as empty
  * and the transmission path has not yet checked this, the value of
  * @read_count bitwise-added to %EFX_EMPTY_COUNT_VALID; otherwise 0.
@@ -253,6 +254,7 @@ struct efx_tx_queue {
unsigned int tso_packets;
unsigned int pushes;
unsigned int pio_packets;
+   bool xmit_more_available;
/* Statistics to supplement MAC stats */
unsigned long tx_packets;
 
diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c
index 1833a0146571..67f6afaa022f 100644
--- a/drivers/net/ethernet/sfc/tx.c
+++ b/drivers/net/ethernet/sfc/tx.c
@@ -431,8 +431,20 @@ finish_packet:
efx_tx_maybe_stop_queue(tx_queue);
 
/* Pass off to hardware */
-   if (!skb->xmit_more || netif_xmit_stopped(tx_queue->core_txq))
+   if (!skb->xmit_more || netif_xmit_stopped(tx_queue->core_txq)) {
+   struct efx_tx_queue *txq2 = efx_tx_queue_partner(tx_queue);
+
+   /* There could be packets left on the partner queue if those
+* SKBs had skb->xmit_more set. If we do not push those they
+* could be left for a long time and cause a netdev watchdog.
+*/
+   if (txq2->xmit_more_available)
+   efx_nic_push_buffers(txq2);
+
efx_nic_push_buffers(tx_queue);
+   } else {
+   tx_queue->xmit_more_available = skb->xmit_more;
+   }
 
tx_queue->tx_packets++;
 
@@ -722,6 +734,7 @@ void efx_init_tx_queue(struct efx_tx_queue *tx_queue)
tx_queue->read_count = 0;
tx_queue->old_read_count = 0;
tx_queue->empty_read_count = 0 | EFX_EMPTY_COUNT_VALID;
+   tx_queue->xmit_more_available = false;
 
/* Set up TX descriptor ring */
efx_nic_init_tx(tx_queue);
@@ -747,6 +760,7 @@ void efx_fini_tx_queue(struct efx_tx_queue *tx_queue)
 
++tx_queue->read_count;
}
+   tx_queue->xmit_more_available = false;
netdev_tx_reset_queue(tx_queue->core_txq);
 }
 
@@ -1302,8 +1316,20 @@ static int efx_enqueue_skb_tso(st