diff options
Diffstat (limited to 'drivers/net/ethernet/sfc/ef100_rx.c')
-rw-r--r-- | drivers/net/ethernet/sfc/ef100_rx.c | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/drivers/net/ethernet/sfc/ef100_rx.c b/drivers/net/ethernet/sfc/ef100_rx.c index 65bbe37753e6..83d9db71d7d7 100644 --- a/drivers/net/ethernet/sfc/ef100_rx.c +++ b/drivers/net/ethernet/sfc/ef100_rx.c @@ -21,7 +21,7 @@ /* Get the value of a field in the RX prefix */ #define PREFIX_OFFSET_W(_f) (ESF_GZ_RX_PREFIX_ ## _f ## _LBN / 32) #define PREFIX_OFFSET_B(_f) (ESF_GZ_RX_PREFIX_ ## _f ## _LBN % 32) -#define PREFIX_WIDTH_MASK(_f) ((1UL << ESF_GZ_RX_PREFIX_ ## _f ## _WIDTH) - 1) +#define PREFIX_WIDTH_MASK(_f) ((1ULL << ESF_GZ_RX_PREFIX_ ## _f ## _WIDTH) - 1) #define PREFIX_WORD(_p, _f) le32_to_cpu((__force __le32)(_p)[PREFIX_OFFSET_W(_f)]) #define PREFIX_FIELD(_p, _f) ((PREFIX_WORD(_p, _f) >> PREFIX_OFFSET_B(_f)) & \ PREFIX_WIDTH_MASK(_f)) @@ -67,6 +67,13 @@ void __ef100_rx_packet(struct efx_channel *channel) prefix = (u32 *)(eh - ESE_GZ_RX_PKT_PREFIX_LEN); + if (channel->type->receive_raw) { + u32 mark = PREFIX_FIELD(prefix, USER_MARK); + + if (channel->type->receive_raw(rx_queue, mark)) + return; /* packet was consumed */ + } + if (ef100_has_fcs_error(channel, prefix) && unlikely(!(efx->net_dev->features & NETIF_F_RXALL))) goto out; @@ -183,24 +190,32 @@ void efx_ef100_ev_rx(struct efx_channel *channel, const efx_qword_t *p_event) void ef100_rx_write(struct efx_rx_queue *rx_queue) { + unsigned int notified_count = rx_queue->notified_count; struct efx_rx_buffer *rx_buf; unsigned int idx; efx_qword_t *rxd; efx_dword_t rxdb; - while (rx_queue->notified_count != rx_queue->added_count) { - idx = rx_queue->notified_count & rx_queue->ptr_mask; + while (notified_count != rx_queue->added_count) { + idx = notified_count & rx_queue->ptr_mask; rx_buf = efx_rx_buffer(rx_queue, idx); rxd = efx_rx_desc(rx_queue, idx); EFX_POPULATE_QWORD_1(*rxd, ESF_GZ_RX_BUF_ADDR, rx_buf->dma_addr); - ++rx_queue->notified_count; + ++notified_count; } + if (notified_count == rx_queue->notified_count) + return; wmb(); EFX_POPULATE_DWORD_1(rxdb, ERF_GZ_RX_RING_PIDX, rx_queue->added_count & rx_queue->ptr_mask); efx_writed_page(rx_queue->efx, &rxdb, ER_GZ_RX_RING_DOORBELL, efx_rx_queue_index(rx_queue)); + if (rx_queue->grant_credits) + wmb(); + rx_queue->notified_count = notified_count; + if (rx_queue->grant_credits) + schedule_work(&rx_queue->grant_work); } |