diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 208e0048709b82723d839f98a560936a921bd00c..f6e29a975e4e844db85b1ad052ef37b8fada02c4 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -2358,7 +2358,11 @@ static void efx_ef10_tx_write(struct efx_tx_queue *tx_queue) /* Create TX descriptor ring entry */ if (buffer->flags & EFX_TX_BUF_OPTION) { *txd = buffer->option; + if (EFX_QWORD_FIELD(*txd, ESF_DZ_TX_OPTION_TYPE) == 1) + /* PIO descriptor */ + tx_queue->packet_write_count = tx_queue->write_count; } else { + tx_queue->packet_write_count = tx_queue->write_count; BUILD_BUG_ON(EFX_TX_BUF_CONT != 1); EFX_POPULATE_QWORD_3( *txd, @@ -5796,6 +5800,7 @@ const struct efx_nic_type efx_hunt_a0_nic_type = { .rx_ts_offset = ES_DZ_RX_PREFIX_TSTAMP_OFST, .can_rx_scatter = true, .always_rx_scatter = true, + .option_descriptors = true, .max_interrupt_mode = EFX_INT_MODE_MSIX, .timer_period_max = 1 << ERF_DD_EVQ_IND_TIMER_VAL_WIDTH, .offload_features = EF10_OFFLOAD_FEATURES, diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index 49db9e833c961862c8833dc1590a1f9574040b76..b20fe437265f38495fba26ae602c274817ebe671 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -208,6 +208,12 @@ struct efx_tx_buffer { * @write_count: Current write pointer * This is the number of buffers that have been added to the * hardware ring. + * @packet_write_count: Completable write pointer + * This is the write pointer of the last packet written. + * Normally this will equal @write_count, but as option descriptors + * don't produce completion events, they won't update this. + * Filled in iff @efx->type->option_descriptors; only used for PIO. + * Thus, this is written and used on EF10, and neither on farch. * @old_read_count: The value of read_count when last checked. * This is here for performance reasons. The xmit path will * only get the up-to-date value of read_count if this @@ -255,6 +261,7 @@ struct efx_tx_queue { /* Members used only on the xmit path */ unsigned int insert_count ____cacheline_aligned_in_smp; unsigned int write_count; + unsigned int packet_write_count; unsigned int old_read_count; unsigned int tso_bursts; unsigned int tso_long_headers; @@ -1237,6 +1244,7 @@ struct efx_mtd_partition { * @rx_buffer_padding: Size of padding at end of RX packet * @can_rx_scatter: NIC is able to scatter packets to multiple buffers * @always_rx_scatter: NIC will always scatter packets to multiple buffers + * @option_descriptors: NIC supports TX option descriptors * @max_interrupt_mode: Highest capability interrupt mode supported * from &enum efx_init_mode. * @timer_period_max: Maximum period of interrupt timer (in ticks) @@ -1395,6 +1403,7 @@ struct efx_nic_type { unsigned int rx_buffer_padding; bool can_rx_scatter; bool always_rx_scatter; + bool option_descriptors; unsigned int max_interrupt_mode; unsigned int timer_period_max; netdev_features_t offload_features; diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h index 223774635cbabf23a439cb90a983427b0f0fef38..6a69aa3b01291ee97c99dc78dd3c05d33e6d0127 100644 --- a/drivers/net/ethernet/sfc/nic.h +++ b/drivers/net/ethernet/sfc/nic.h @@ -85,6 +85,17 @@ static inline bool __efx_nic_tx_is_empty(struct efx_tx_queue *tx_queue, return ((empty_read_count ^ write_count) & ~EFX_EMPTY_COUNT_VALID) == 0; } +/* Report whether the NIC considers this TX queue empty, using + * packet_write_count (the write count recorded for the last completable + * doorbell push). May return false negative. EF10 only, which is OK + * because only EF10 supports PIO. + */ +static inline bool efx_nic_tx_is_empty(struct efx_tx_queue *tx_queue) +{ + EFX_WARN_ON_ONCE_PARANOID(!tx_queue->efx->type->option_descriptors); + return __efx_nic_tx_is_empty(tx_queue, tx_queue->packet_write_count); +} + /* Decide whether we can use TX PIO, ie. write packet data directly into * a buffer on the device. This can reduce latency at the expense of * throughput, so we only do this if both hardware and software TX rings @@ -94,9 +105,9 @@ static inline bool __efx_nic_tx_is_empty(struct efx_tx_queue *tx_queue, static inline bool efx_nic_may_tx_pio(struct efx_tx_queue *tx_queue) { struct efx_tx_queue *partner = efx_tx_queue_partner(tx_queue); - return tx_queue->piobuf && - __efx_nic_tx_is_empty(tx_queue, tx_queue->insert_count) && - __efx_nic_tx_is_empty(partner, partner->insert_count); + + return tx_queue->piobuf && efx_nic_tx_is_empty(tx_queue) && + efx_nic_tx_is_empty(partner); } /* Decide whether to push a TX descriptor to the NIC vs merely writing diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c index 4e54e5dc9fcb49bf03667843d47a4a2cf1aa978b..118ff56017562edc7400a06e341b71b30aed84b7 100644 --- a/drivers/net/ethernet/sfc/siena.c +++ b/drivers/net/ethernet/sfc/siena.c @@ -1044,6 +1044,7 @@ const struct efx_nic_type siena_a0_nic_type = { .rx_hash_offset = FS_BZ_RX_PREFIX_HASH_OFST, .rx_buffer_padding = 0, .can_rx_scatter = true, + .option_descriptors = false, .max_interrupt_mode = EFX_INT_MODE_MSIX, .timer_period_max = 1 << FRF_CZ_TC_TIMER_VAL_WIDTH, .offload_features = (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c index 3c0151424d125d611d7d6f09b604bb5cfbb33519..beaf98080a0b6d3d1b0ce216b70376bdb7b912cc 100644 --- a/drivers/net/ethernet/sfc/tx.c +++ b/drivers/net/ethernet/sfc/tx.c @@ -817,6 +817,7 @@ void efx_init_tx_queue(struct efx_tx_queue *tx_queue) tx_queue->insert_count = 0; tx_queue->write_count = 0; + tx_queue->packet_write_count = 0; tx_queue->old_write_count = 0; tx_queue->read_count = 0; tx_queue->old_read_count = 0;