Some out-of-tree ICE kernel driver versions have a known issue where they expect size of IRQ queue vector map command to be bigger than needed, and because the driver rejects the correct size as invalid, a workaround is needed to send down a "wrong" size and configure the IRQ maps.
Signed-off-by: Anatoly Burakov <[email protected]> --- drivers/net/intel/iavf/iavf_vchnl.c | 30 ++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/drivers/net/intel/iavf/iavf_vchnl.c b/drivers/net/intel/iavf/iavf_vchnl.c index 0643a835d5..408ff31aa5 100644 --- a/drivers/net/intel/iavf/iavf_vchnl.c +++ b/drivers/net/intel/iavf/iavf_vchnl.c @@ -1566,7 +1566,8 @@ iavf_config_irq_map(struct iavf_adapter *adapter) static int iavf_config_irq_map_lv_chunk(struct iavf_adapter *adapter, uint16_t chunk_sz, - uint16_t chunk_start) + uint16_t chunk_start, + bool wrong_size) { struct { struct virtchnl_queue_vector_maps map_info; @@ -1593,9 +1594,19 @@ iavf_config_irq_map_lv_chunk(struct iavf_adapter *adapter, qv_maps->vector_id = vf->qv_map[chunk_start + i].vector_id; } - /* for some reason PF side checks for buffer being too big, so adjust it down */ - buf_len = sizeof(struct virtchnl_queue_vector_maps) + - sizeof(struct virtchnl_queue_vector) * (chunk_sz - 1); + /* + * in out-of-tree kernel driver versions 2.6.4 and 2.6.6 there is a + * known issue where the PF side expects the buffer size to be bigger + * than necessary. this is a workaround for that issue. + */ + if (wrong_size) + /* send N+1 instead of N to workaround PF side bug */ + buf_len = sizeof(struct virtchnl_queue_vector_maps) + + sizeof(struct virtchnl_queue_vector) * (chunk_sz); + else + /* virtchnl_queue_vector_maps already contains 1 queue_vector */ + buf_len = sizeof(struct virtchnl_queue_vector_maps) + + sizeof(struct virtchnl_queue_vector) * (chunk_sz - 1); args.ops = VIRTCHNL_OP_MAP_QUEUE_VECTOR; args.in_args = (u8 *)map_info; @@ -1609,12 +1620,21 @@ iavf_config_irq_map_lv_chunk(struct iavf_adapter *adapter, int iavf_config_irq_map_lv(struct iavf_adapter *adapter, uint16_t num) { + static bool wrong_size; uint16_t c; int err; for (c = 0; c < num; c += IAVF_CFG_Q_NUM_PER_BUF) { uint16_t chunk_sz = RTE_MIN(num - c, IAVF_CFG_Q_NUM_PER_BUF); - err = iavf_config_irq_map_lv_chunk(adapter, chunk_sz, c); + err = iavf_config_irq_map_lv_chunk(adapter, chunk_sz, c, wrong_size); + if (err) { + /* try workaround for a known issue */ + err = iavf_config_irq_map_lv_chunk(adapter, chunk_sz, c, true); + if (err == 0) { + PMD_DRV_LOG(DEBUG, "Using workaround for IRQ map"); + wrong_size = true; + } + } if (err) { PMD_DRV_LOG(ERR, "Failed to configure irq map chunk [%u, %u)", c, c + chunk_sz); -- 2.47.3

