-/* Falcon hardware control.
- * Falcon is the internal codename for the SFC4000 controller that is
- * present in SFE400X evaluation boards
- */
-
-/**
- * struct falcon_nic_data - Falcon NIC state
- * @next_buffer_table: First available buffer table id
- * @pci_dev2: The secondary PCI device if present
- * @i2c_data: Operations and state for I2C bit-bashing algorithm
- * @int_error_count: Number of internal errors seen recently
- * @int_error_expire: Time at which error count will be expired
- */
-struct falcon_nic_data {
- unsigned next_buffer_table;
- struct pci_dev *pci_dev2;
- struct i2c_algo_bit_data i2c_data;
-
- unsigned int_error_count;
- unsigned long int_error_expire;
-};
-
-/**************************************************************************
- *
- * Configurable values
- *
- **************************************************************************
- */
-
-static int disable_dma_stats;
-
-/* This is set to 16 for a good reason. In summary, if larger than
- * 16, the descriptor cache holds more than a default socket
- * buffer's worth of packets (for UDP we can only have at most one
- * socket buffer's worth outstanding). This combined with the fact
- * that we only get 1 TX event per descriptor cache means the NIC
- * goes idle.
- */
-#define TX_DC_ENTRIES 16
-#define TX_DC_ENTRIES_ORDER 0
-#define TX_DC_BASE 0x130000
-
-#define RX_DC_ENTRIES 64
-#define RX_DC_ENTRIES_ORDER 2
-#define RX_DC_BASE 0x100000
-
-static const unsigned int
-/* "Large" EEPROM device: Atmel AT25640 or similar
- * 8 KB, 16-bit address, 32 B write block */
-large_eeprom_type = ((13 << SPI_DEV_TYPE_SIZE_LBN)
- | (2 << SPI_DEV_TYPE_ADDR_LEN_LBN)
- | (5 << SPI_DEV_TYPE_BLOCK_SIZE_LBN)),
-/* Default flash device: Atmel AT25F1024
- * 128 KB, 24-bit address, 32 KB erase block, 256 B write block */
-default_flash_type = ((17 << SPI_DEV_TYPE_SIZE_LBN)
- | (3 << SPI_DEV_TYPE_ADDR_LEN_LBN)
- | (0x52 << SPI_DEV_TYPE_ERASE_CMD_LBN)
- | (15 << SPI_DEV_TYPE_ERASE_SIZE_LBN)
- | (8 << SPI_DEV_TYPE_BLOCK_SIZE_LBN));
-
-/* RX FIFO XOFF watermark
- *
- * When the amount of the RX FIFO increases used increases past this
- * watermark send XOFF. Only used if RX flow control is enabled (ethtool -A)
- * This also has an effect on RX/TX arbitration
- */
-static int rx_xoff_thresh_bytes = -1;
-module_param(rx_xoff_thresh_bytes, int, 0644);
-MODULE_PARM_DESC(rx_xoff_thresh_bytes, "RX fifo XOFF threshold");
-
-/* RX FIFO XON watermark
- *
- * When the amount of the RX FIFO used decreases below this
- * watermark send XON. Only used if TX flow control is enabled (ethtool -A)
- * This also has an effect on RX/TX arbitration
- */
-static int rx_xon_thresh_bytes = -1;
-module_param(rx_xon_thresh_bytes, int, 0644);
-MODULE_PARM_DESC(rx_xon_thresh_bytes, "RX fifo XON threshold");
-
-/* TX descriptor ring size - min 512 max 4k */
-#define FALCON_TXD_RING_ORDER TX_DESCQ_SIZE_1K
-#define FALCON_TXD_RING_SIZE 1024
-#define FALCON_TXD_RING_MASK (FALCON_TXD_RING_SIZE - 1)
-
-/* RX descriptor ring size - min 512 max 4k */
-#define FALCON_RXD_RING_ORDER RX_DESCQ_SIZE_1K
-#define FALCON_RXD_RING_SIZE 1024
-#define FALCON_RXD_RING_MASK (FALCON_RXD_RING_SIZE - 1)
-
-/* Event queue size - max 32k */
-#define FALCON_EVQ_ORDER EVQ_SIZE_4K
-#define FALCON_EVQ_SIZE 4096
-#define FALCON_EVQ_MASK (FALCON_EVQ_SIZE - 1)
-
-/* If FALCON_MAX_INT_ERRORS internal errors occur within
- * FALCON_INT_ERROR_EXPIRE seconds, we consider the NIC broken and
- * disable it.
- */
-#define FALCON_INT_ERROR_EXPIRE 3600
-#define FALCON_MAX_INT_ERRORS 5
-
-/* We poll for events every FLUSH_INTERVAL ms, and check FLUSH_POLL_COUNT times
- */
-#define FALCON_FLUSH_INTERVAL 10
-#define FALCON_FLUSH_POLL_COUNT 100
-
-/**************************************************************************
- *
- * Falcon constants
- *
- **************************************************************************
- */
-
-/* DMA address mask */
-#define FALCON_DMA_MASK DMA_BIT_MASK(46)
-
-/* TX DMA length mask (13-bit) */
-#define FALCON_TX_DMA_MASK (4096 - 1)
-
-/* Size and alignment of special buffers (4KB) */
-#define FALCON_BUF_SIZE 4096
-
-/* Dummy SRAM size code */
-#define SRM_NB_BSZ_ONCHIP_ONLY (-1)
-
-#define FALCON_IS_DUAL_FUNC(efx) \
- (falcon_rev(efx) < FALCON_REV_B0)
-
-/**************************************************************************
- *
- * Falcon hardware access
- *
- **************************************************************************/
-
-/* Read the current event from the event queue */
-static inline efx_qword_t *falcon_event(struct efx_channel *channel,
- unsigned int index)
-{
- return (((efx_qword_t *) (channel->eventq.addr)) + index);
-}
-
-/* See if an event is present
- *
- * We check both the high and low dword of the event for all ones. We
- * wrote all ones when we cleared the event, and no valid event can
- * have all ones in either its high or low dwords. This approach is
- * robust against reordering.
- *
- * Note that using a single 64-bit comparison is incorrect; even
- * though the CPU read will be atomic, the DMA write may not be.
- */
-static inline int falcon_event_present(efx_qword_t *event)
-{
- return (!(EFX_DWORD_IS_ALL_ONES(event->dword[0]) |
- EFX_DWORD_IS_ALL_ONES(event->dword[1])));
-}
-
-/**************************************************************************
- *
- * I2C bus - this is a bit-bashing interface using GPIO pins
- * Note that it uses the output enables to tristate the outputs
- * SDA is the data pin and SCL is the clock
- *
- **************************************************************************
- */
-static void falcon_setsda(void *data, int state)
-{
- struct efx_nic *efx = (struct efx_nic *)data;
- efx_oword_t reg;
-
- falcon_read(efx, ®, GPIO_CTL_REG_KER);
- EFX_SET_OWORD_FIELD(reg, GPIO3_OEN, !state);
- falcon_write(efx, ®, GPIO_CTL_REG_KER);
-}
-
-static void falcon_setscl(void *data, int state)
-{
- struct efx_nic *efx = (struct efx_nic *)data;
- efx_oword_t reg;
-
- falcon_read(efx, ®, GPIO_CTL_REG_KER);
- EFX_SET_OWORD_FIELD(reg, GPIO0_OEN, !state);
- falcon_write(efx, ®, GPIO_CTL_REG_KER);
-}
-
-static int falcon_getsda(void *data)
-{
- struct efx_nic *efx = (struct efx_nic *)data;
- efx_oword_t reg;
-
- falcon_read(efx, ®, GPIO_CTL_REG_KER);
- return EFX_OWORD_FIELD(reg, GPIO3_IN);
-}
-
-static int falcon_getscl(void *data)
-{
- struct efx_nic *efx = (struct efx_nic *)data;
- efx_oword_t reg;
-
- falcon_read(efx, ®, GPIO_CTL_REG_KER);
- return EFX_OWORD_FIELD(reg, GPIO0_IN);
-}
-
-static struct i2c_algo_bit_data falcon_i2c_bit_operations = {
- .setsda = falcon_setsda,
- .setscl = falcon_setscl,
- .getsda = falcon_getsda,
- .getscl = falcon_getscl,
- .udelay = 5,
- /* Wait up to 50 ms for slave to let us pull SCL high */
- .timeout = DIV_ROUND_UP(HZ, 20),
-};
-
-/**************************************************************************
- *
- * Falcon special buffer handling
- * Special buffers are used for event queues and the TX and RX
- * descriptor rings.
- *
- *************************************************************************/
-
-/*
- * Initialise a Falcon special buffer
- *
- * This will define a buffer (previously allocated via
- * falcon_alloc_special_buffer()) in Falcon's buffer table, allowing
- * it to be used for event queues, descriptor rings etc.
- */
-static void
-falcon_init_special_buffer(struct efx_nic *efx,
- struct efx_special_buffer *buffer)
-{
- efx_qword_t buf_desc;
- int index;
- dma_addr_t dma_addr;
- int i;
-
- EFX_BUG_ON_PARANOID(!buffer->addr);
-
- /* Write buffer descriptors to NIC */
- for (i = 0; i < buffer->entries; i++) {
- index = buffer->index + i;
- dma_addr = buffer->dma_addr + (i * 4096);
- EFX_LOG(efx, "mapping special buffer %d at %llx\n",
- index, (unsigned long long)dma_addr);
- EFX_POPULATE_QWORD_4(buf_desc,
- IP_DAT_BUF_SIZE, IP_DAT_BUF_SIZE_4K,
- BUF_ADR_REGION, 0,
- BUF_ADR_FBUF, (dma_addr >> 12),
- BUF_OWNER_ID_FBUF, 0);
- falcon_write_sram(efx, &buf_desc, index);
- }
-}
-
-/* Unmaps a buffer from Falcon and clears the buffer table entries */
-static void
-falcon_fini_special_buffer(struct efx_nic *efx,
- struct efx_special_buffer *buffer)
-{
- efx_oword_t buf_tbl_upd;
- unsigned int start = buffer->index;
- unsigned int end = (buffer->index + buffer->entries - 1);
-
- if (!buffer->entries)
- return;
-
- EFX_LOG(efx, "unmapping special buffers %d-%d\n",
- buffer->index, buffer->index + buffer->entries - 1);
-
- EFX_POPULATE_OWORD_4(buf_tbl_upd,
- BUF_UPD_CMD, 0,
- BUF_CLR_CMD, 1,
- BUF_CLR_END_ID, end,
- BUF_CLR_START_ID, start);
- falcon_write(efx, &buf_tbl_upd, BUF_TBL_UPD_REG_KER);
-}
-
-/*
- * Allocate a new Falcon special buffer
- *
- * This allocates memory for a new buffer, clears it and allocates a
- * new buffer ID range. It does not write into Falcon's buffer table.
- *
- * This call will allocate 4KB buffers, since Falcon can't use 8KB
- * buffers for event queues and descriptor rings.
- */
-static int falcon_alloc_special_buffer(struct efx_nic *efx,
- struct efx_special_buffer *buffer,
- unsigned int len)
-{
- struct falcon_nic_data *nic_data = efx->nic_data;
-
- len = ALIGN(len, FALCON_BUF_SIZE);
-
- buffer->addr = pci_alloc_consistent(efx->pci_dev, len,
- &buffer->dma_addr);
- if (!buffer->addr)
- return -ENOMEM;
- buffer->len = len;
- buffer->entries = len / FALCON_BUF_SIZE;
- BUG_ON(buffer->dma_addr & (FALCON_BUF_SIZE - 1));
-
- /* All zeros is a potentially valid event so memset to 0xff */
- memset(buffer->addr, 0xff, len);
-
- /* Select new buffer ID */
- buffer->index = nic_data->next_buffer_table;
- nic_data->next_buffer_table += buffer->entries;
-
- EFX_LOG(efx, "allocating special buffers %d-%d at %llx+%x "
- "(virt %p phys %llx)\n", buffer->index,
- buffer->index + buffer->entries - 1,
- (u64)buffer->dma_addr, len,
- buffer->addr, (u64)virt_to_phys(buffer->addr));
-
- return 0;
-}
-
-static void falcon_free_special_buffer(struct efx_nic *efx,
- struct efx_special_buffer *buffer)
-{
- if (!buffer->addr)
- return;
-
- EFX_LOG(efx, "deallocating special buffers %d-%d at %llx+%x "
- "(virt %p phys %llx)\n", buffer->index,
- buffer->index + buffer->entries - 1,
- (u64)buffer->dma_addr, buffer->len,
- buffer->addr, (u64)virt_to_phys(buffer->addr));
-
- pci_free_consistent(efx->pci_dev, buffer->len, buffer->addr,
- buffer->dma_addr);
- buffer->addr = NULL;
- buffer->entries = 0;
-}
-
-/**************************************************************************
- *
- * Falcon generic buffer handling
- * These buffers are used for interrupt status and MAC stats
- *
- **************************************************************************/
-
-static int falcon_alloc_buffer(struct efx_nic *efx,
- struct efx_buffer *buffer, unsigned int len)
-{
- buffer->addr = pci_alloc_consistent(efx->pci_dev, len,
- &buffer->dma_addr);
- if (!buffer->addr)
- return -ENOMEM;
- buffer->len = len;
- memset(buffer->addr, 0, len);
- return 0;
-}
-
-static void falcon_free_buffer(struct efx_nic *efx, struct efx_buffer *buffer)
-{
- if (buffer->addr) {
- pci_free_consistent(efx->pci_dev, buffer->len,
- buffer->addr, buffer->dma_addr);
- buffer->addr = NULL;
- }
-}
-
-/**************************************************************************
- *
- * Falcon TX path
- *
- **************************************************************************/
-
-/* Returns a pointer to the specified transmit descriptor in the TX
- * descriptor queue belonging to the specified channel.
- */
-static inline efx_qword_t *falcon_tx_desc(struct efx_tx_queue *tx_queue,
- unsigned int index)
-{
- return (((efx_qword_t *) (tx_queue->txd.addr)) + index);
-}
-
-/* This writes to the TX_DESC_WPTR; write pointer for TX descriptor ring */
-static inline void falcon_notify_tx_desc(struct efx_tx_queue *tx_queue)
-{
- unsigned write_ptr;
- efx_dword_t reg;
-
- write_ptr = tx_queue->write_count & FALCON_TXD_RING_MASK;
- EFX_POPULATE_DWORD_1(reg, TX_DESC_WPTR_DWORD, write_ptr);
- falcon_writel_page(tx_queue->efx, ®,
- TX_DESC_UPD_REG_KER_DWORD, tx_queue->queue);
-}
-
-
-/* For each entry inserted into the software descriptor ring, create a
- * descriptor in the hardware TX descriptor ring (in host memory), and
- * write a doorbell.
- */
-void falcon_push_buffers(struct efx_tx_queue *tx_queue)
-{
-
- struct efx_tx_buffer *buffer;
- efx_qword_t *txd;
- unsigned write_ptr;
-
- BUG_ON(tx_queue->write_count == tx_queue->insert_count);
-
- do {
- write_ptr = tx_queue->write_count & FALCON_TXD_RING_MASK;
- buffer = &tx_queue->buffer[write_ptr];
- txd = falcon_tx_desc(tx_queue, write_ptr);
- ++tx_queue->write_count;
-
- /* Create TX descriptor ring entry */
- EFX_POPULATE_QWORD_5(*txd,
- TX_KER_PORT, 0,
- TX_KER_CONT, buffer->continuation,
- TX_KER_BYTE_CNT, buffer->len,
- TX_KER_BUF_REGION, 0,
- TX_KER_BUF_ADR, buffer->dma_addr);
- } while (tx_queue->write_count != tx_queue->insert_count);
-
- wmb(); /* Ensure descriptors are written before they are fetched */
- falcon_notify_tx_desc(tx_queue);
-}
-
-/* Allocate hardware resources for a TX queue */
-int falcon_probe_tx(struct efx_tx_queue *tx_queue)
-{
- struct efx_nic *efx = tx_queue->efx;
- return falcon_alloc_special_buffer(efx, &tx_queue->txd,
- FALCON_TXD_RING_SIZE *
- sizeof(efx_qword_t));
-}
-
-void falcon_init_tx(struct efx_tx_queue *tx_queue)
-{
- efx_oword_t tx_desc_ptr;
- struct efx_nic *efx = tx_queue->efx;
-
- tx_queue->flushed = false;
-
- /* Pin TX descriptor ring */
- falcon_init_special_buffer(efx, &tx_queue->txd);
-
- /* Push TX descriptor ring to card */
- EFX_POPULATE_OWORD_10(tx_desc_ptr,
- TX_DESCQ_EN, 1,
- TX_ISCSI_DDIG_EN, 0,
- TX_ISCSI_HDIG_EN, 0,
- TX_DESCQ_BUF_BASE_ID, tx_queue->txd.index,
- TX_DESCQ_EVQ_ID, tx_queue->channel->channel,
- TX_DESCQ_OWNER_ID, 0,
- TX_DESCQ_LABEL, tx_queue->queue,
- TX_DESCQ_SIZE, FALCON_TXD_RING_ORDER,
- TX_DESCQ_TYPE, 0,
- TX_NON_IP_DROP_DIS_B0, 1);
-
- if (falcon_rev(efx) >= FALCON_REV_B0) {
- int csum = tx_queue->queue == EFX_TX_QUEUE_OFFLOAD_CSUM;
- EFX_SET_OWORD_FIELD(tx_desc_ptr, TX_IP_CHKSM_DIS_B0, !csum);
- EFX_SET_OWORD_FIELD(tx_desc_ptr, TX_TCP_CHKSM_DIS_B0, !csum);
- }
-
- falcon_write_table(efx, &tx_desc_ptr, efx->type->txd_ptr_tbl_base,
- tx_queue->queue);
-
- if (falcon_rev(efx) < FALCON_REV_B0) {
- efx_oword_t reg;
-
- /* Only 128 bits in this register */
- BUILD_BUG_ON(EFX_TX_QUEUE_COUNT >= 128);
-
- falcon_read(efx, ®, TX_CHKSM_CFG_REG_KER_A1);
- if (tx_queue->queue == EFX_TX_QUEUE_OFFLOAD_CSUM)
- clear_bit_le(tx_queue->queue, (void *)®);
- else
- set_bit_le(tx_queue->queue, (void *)®);
- falcon_write(efx, ®, TX_CHKSM_CFG_REG_KER_A1);
- }
-}
-
-static void falcon_flush_tx_queue(struct efx_tx_queue *tx_queue)
-{
- struct efx_nic *efx = tx_queue->efx;
- efx_oword_t tx_flush_descq;
-
- /* Post a flush command */
- EFX_POPULATE_OWORD_2(tx_flush_descq,
- TX_FLUSH_DESCQ_CMD, 1,
- TX_FLUSH_DESCQ, tx_queue->queue);
- falcon_write(efx, &tx_flush_descq, TX_FLUSH_DESCQ_REG_KER);
-}
-
-void falcon_fini_tx(struct efx_tx_queue *tx_queue)
-{
- struct efx_nic *efx = tx_queue->efx;
- efx_oword_t tx_desc_ptr;
-
- /* The queue should have been flushed */
- WARN_ON(!tx_queue->flushed);
-
- /* Remove TX descriptor ring from card */
- EFX_ZERO_OWORD(tx_desc_ptr);
- falcon_write_table(efx, &tx_desc_ptr, efx->type->txd_ptr_tbl_base,
- tx_queue->queue);
-
- /* Unpin TX descriptor ring */
- falcon_fini_special_buffer(efx, &tx_queue->txd);
-}
-
-/* Free buffers backing TX queue */
-void falcon_remove_tx(struct efx_tx_queue *tx_queue)
-{
- falcon_free_special_buffer(tx_queue->efx, &tx_queue->txd);
-}
-
-/**************************************************************************
- *
- * Falcon RX path
- *
- **************************************************************************/
-
-/* Returns a pointer to the specified descriptor in the RX descriptor queue */
-static inline efx_qword_t *falcon_rx_desc(struct efx_rx_queue *rx_queue,
- unsigned int index)
-{
- return (((efx_qword_t *) (rx_queue->rxd.addr)) + index);
-}
-
-/* This creates an entry in the RX descriptor queue */
-static inline void falcon_build_rx_desc(struct efx_rx_queue *rx_queue,
- unsigned index)
-{
- struct efx_rx_buffer *rx_buf;
- efx_qword_t *rxd;
-
- rxd = falcon_rx_desc(rx_queue, index);
- rx_buf = efx_rx_buffer(rx_queue, index);
- EFX_POPULATE_QWORD_3(*rxd,
- RX_KER_BUF_SIZE,
- rx_buf->len -
- rx_queue->efx->type->rx_buffer_padding,
- RX_KER_BUF_REGION, 0,
- RX_KER_BUF_ADR, rx_buf->dma_addr);
-}
-
-/* This writes to the RX_DESC_WPTR register for the specified receive
- * descriptor ring.
- */
-void falcon_notify_rx_desc(struct efx_rx_queue *rx_queue)
-{
- efx_dword_t reg;
- unsigned write_ptr;
-
- while (rx_queue->notified_count != rx_queue->added_count) {
- falcon_build_rx_desc(rx_queue,
- rx_queue->notified_count &
- FALCON_RXD_RING_MASK);
- ++rx_queue->notified_count;
- }
-
- wmb();
- write_ptr = rx_queue->added_count & FALCON_RXD_RING_MASK;
- EFX_POPULATE_DWORD_1(reg, RX_DESC_WPTR_DWORD, write_ptr);
- falcon_writel_page(rx_queue->efx, ®,
- RX_DESC_UPD_REG_KER_DWORD, rx_queue->queue);
-}
-
-int falcon_probe_rx(struct efx_rx_queue *rx_queue)
-{
- struct efx_nic *efx = rx_queue->efx;
- return falcon_alloc_special_buffer(efx, &rx_queue->rxd,
- FALCON_RXD_RING_SIZE *
- sizeof(efx_qword_t));
-}
-
-void falcon_init_rx(struct efx_rx_queue *rx_queue)
-{
- efx_oword_t rx_desc_ptr;
- struct efx_nic *efx = rx_queue->efx;
- bool is_b0 = falcon_rev(efx) >= FALCON_REV_B0;
- bool iscsi_digest_en = is_b0;
-
- EFX_LOG(efx, "RX queue %d ring in special buffers %d-%d\n",
- rx_queue->queue, rx_queue->rxd.index,
- rx_queue->rxd.index + rx_queue->rxd.entries - 1);
-
- rx_queue->flushed = false;
-
- /* Pin RX descriptor ring */
- falcon_init_special_buffer(efx, &rx_queue->rxd);
-
- /* Push RX descriptor ring to card */
- EFX_POPULATE_OWORD_10(rx_desc_ptr,
- RX_ISCSI_DDIG_EN, iscsi_digest_en,
- RX_ISCSI_HDIG_EN, iscsi_digest_en,
- RX_DESCQ_BUF_BASE_ID, rx_queue->rxd.index,
- RX_DESCQ_EVQ_ID, rx_queue->channel->channel,
- RX_DESCQ_OWNER_ID, 0,
- RX_DESCQ_LABEL, rx_queue->queue,
- RX_DESCQ_SIZE, FALCON_RXD_RING_ORDER,
- RX_DESCQ_TYPE, 0 /* kernel queue */ ,
- /* For >=B0 this is scatter so disable */
- RX_DESCQ_JUMBO, !is_b0,
- RX_DESCQ_EN, 1);
- falcon_write_table(efx, &rx_desc_ptr, efx->type->rxd_ptr_tbl_base,
- rx_queue->queue);
-}
-
-static void falcon_flush_rx_queue(struct efx_rx_queue *rx_queue)
-{
- struct efx_nic *efx = rx_queue->efx;
- efx_oword_t rx_flush_descq;
-
- /* Post a flush command */
- EFX_POPULATE_OWORD_2(rx_flush_descq,
- RX_FLUSH_DESCQ_CMD, 1,
- RX_FLUSH_DESCQ, rx_queue->queue);
- falcon_write(efx, &rx_flush_descq, RX_FLUSH_DESCQ_REG_KER);
-}
-
-void falcon_fini_rx(struct efx_rx_queue *rx_queue)
-{
- efx_oword_t rx_desc_ptr;
- struct efx_nic *efx = rx_queue->efx;
-
- /* The queue should already have been flushed */
- WARN_ON(!rx_queue->flushed);
-
- /* Remove RX descriptor ring from card */
- EFX_ZERO_OWORD(rx_desc_ptr);
- falcon_write_table(efx, &rx_desc_ptr, efx->type->rxd_ptr_tbl_base,
- rx_queue->queue);
-
- /* Unpin RX descriptor ring */
- falcon_fini_special_buffer(efx, &rx_queue->rxd);
-}
-
-/* Free buffers backing RX queue */
-void falcon_remove_rx(struct efx_rx_queue *rx_queue)
-{
- falcon_free_special_buffer(rx_queue->efx, &rx_queue->rxd);
-}
-
-/**************************************************************************
- *
- * Falcon event queue processing
- * Event queues are processed by per-channel tasklets.
- *
- **************************************************************************/
-
-/* Update a channel's event queue's read pointer (RPTR) register
- *
- * This writes the EVQ_RPTR_REG register for the specified channel's
- * event queue.
- *
- * Note that EVQ_RPTR_REG contains the index of the "last read" event,
- * whereas channel->eventq_read_ptr contains the index of the "next to
- * read" event.
- */
-void falcon_eventq_read_ack(struct efx_channel *channel)
-{
- efx_dword_t reg;
- struct efx_nic *efx = channel->efx;
-
- EFX_POPULATE_DWORD_1(reg, EVQ_RPTR_DWORD, channel->eventq_read_ptr);
- falcon_writel_table(efx, ®, efx->type->evq_rptr_tbl_base,
- channel->channel);
-}
-
-/* Use HW to insert a SW defined event */
-void falcon_generate_event(struct efx_channel *channel, efx_qword_t *event)
-{
- efx_oword_t drv_ev_reg;
-
- EFX_POPULATE_OWORD_2(drv_ev_reg,
- DRV_EV_QID, channel->channel,
- DRV_EV_DATA,
- EFX_QWORD_FIELD64(*event, WHOLE_EVENT));
- falcon_write(channel->efx, &drv_ev_reg, DRV_EV_REG_KER);
-}
-
-/* Handle a transmit completion event
- *
- * Falcon batches TX completion events; the message we receive is of
- * the form "complete all TX events up to this index".
- */
-static void falcon_handle_tx_event(struct efx_channel *channel,
- efx_qword_t *event)
-{
- unsigned int tx_ev_desc_ptr;
- unsigned int tx_ev_q_label;
- struct efx_tx_queue *tx_queue;
- struct efx_nic *efx = channel->efx;
-
- if (likely(EFX_QWORD_FIELD(*event, TX_EV_COMP))) {
- /* Transmit completion */
- tx_ev_desc_ptr = EFX_QWORD_FIELD(*event, TX_EV_DESC_PTR);
- tx_ev_q_label = EFX_QWORD_FIELD(*event, TX_EV_Q_LABEL);
- tx_queue = &efx->tx_queue[tx_ev_q_label];
- channel->irq_mod_score +=
- (tx_ev_desc_ptr - tx_queue->read_count) &
- efx->type->txd_ring_mask;
- efx_xmit_done(tx_queue, tx_ev_desc_ptr);
- } else if (EFX_QWORD_FIELD(*event, TX_EV_WQ_FF_FULL)) {
- /* Rewrite the FIFO write pointer */
- tx_ev_q_label = EFX_QWORD_FIELD(*event, TX_EV_Q_LABEL);
- tx_queue = &efx->tx_queue[tx_ev_q_label];
-
- if (efx_dev_registered(efx))
- netif_tx_lock(efx->net_dev);
- falcon_notify_tx_desc(tx_queue);
- if (efx_dev_registered(efx))
- netif_tx_unlock(efx->net_dev);
- } else if (EFX_QWORD_FIELD(*event, TX_EV_PKT_ERR) &&
- EFX_WORKAROUND_10727(efx)) {
- efx_schedule_reset(efx, RESET_TYPE_TX_DESC_FETCH);
- } else {
- EFX_ERR(efx, "channel %d unexpected TX event "
- EFX_QWORD_FMT"\n", channel->channel,
- EFX_QWORD_VAL(*event));
- }
-}
-
-/* Detect errors included in the rx_evt_pkt_ok bit. */
-static void falcon_handle_rx_not_ok(struct efx_rx_queue *rx_queue,
- const efx_qword_t *event,
- bool *rx_ev_pkt_ok,
- bool *discard)
-{
- struct efx_nic *efx = rx_queue->efx;
- bool rx_ev_buf_owner_id_err, rx_ev_ip_hdr_chksum_err;
- bool rx_ev_tcp_udp_chksum_err, rx_ev_eth_crc_err;
- bool rx_ev_frm_trunc, rx_ev_drib_nib, rx_ev_tobe_disc;
- bool rx_ev_other_err, rx_ev_pause_frm;
- bool rx_ev_ip_frag_err, rx_ev_hdr_type, rx_ev_mcast_pkt;
- unsigned rx_ev_pkt_type;
-
- rx_ev_hdr_type = EFX_QWORD_FIELD(*event, RX_EV_HDR_TYPE);
- rx_ev_mcast_pkt = EFX_QWORD_FIELD(*event, RX_EV_MCAST_PKT);
- rx_ev_tobe_disc = EFX_QWORD_FIELD(*event, RX_EV_TOBE_DISC);
- rx_ev_pkt_type = EFX_QWORD_FIELD(*event, RX_EV_PKT_TYPE);
- rx_ev_buf_owner_id_err = EFX_QWORD_FIELD(*event,
- RX_EV_BUF_OWNER_ID_ERR);
- rx_ev_ip_frag_err = EFX_QWORD_FIELD(*event, RX_EV_IF_FRAG_ERR);
- rx_ev_ip_hdr_chksum_err = EFX_QWORD_FIELD(*event,
- RX_EV_IP_HDR_CHKSUM_ERR);
- rx_ev_tcp_udp_chksum_err = EFX_QWORD_FIELD(*event,
- RX_EV_TCP_UDP_CHKSUM_ERR);
- rx_ev_eth_crc_err = EFX_QWORD_FIELD(*event, RX_EV_ETH_CRC_ERR);
- rx_ev_frm_trunc = EFX_QWORD_FIELD(*event, RX_EV_FRM_TRUNC);
- rx_ev_drib_nib = ((falcon_rev(efx) >= FALCON_REV_B0) ?
- 0 : EFX_QWORD_FIELD(*event, RX_EV_DRIB_NIB));
- rx_ev_pause_frm = EFX_QWORD_FIELD(*event, RX_EV_PAUSE_FRM_ERR);
-
- /* Every error apart from tobe_disc and pause_frm */
- rx_ev_other_err = (rx_ev_drib_nib | rx_ev_tcp_udp_chksum_err |
- rx_ev_buf_owner_id_err | rx_ev_eth_crc_err |
- rx_ev_frm_trunc | rx_ev_ip_hdr_chksum_err);
-
- /* Count errors that are not in MAC stats. Ignore expected
- * checksum errors during self-test. */
- if (rx_ev_frm_trunc)
- ++rx_queue->channel->n_rx_frm_trunc;
- else if (rx_ev_tobe_disc)
- ++rx_queue->channel->n_rx_tobe_disc;
- else if (!efx->loopback_selftest) {
- if (rx_ev_ip_hdr_chksum_err)
- ++rx_queue->channel->n_rx_ip_hdr_chksum_err;
- else if (rx_ev_tcp_udp_chksum_err)
- ++rx_queue->channel->n_rx_tcp_udp_chksum_err;
- }
- if (rx_ev_ip_frag_err)
- ++rx_queue->channel->n_rx_ip_frag_err;
-
- /* The frame must be discarded if any of these are true. */
- *discard = (rx_ev_eth_crc_err | rx_ev_frm_trunc | rx_ev_drib_nib |
- rx_ev_tobe_disc | rx_ev_pause_frm);
-
- /* TOBE_DISC is expected on unicast mismatches; don't print out an
- * error message. FRM_TRUNC indicates RXDP dropped the packet due
- * to a FIFO overflow.
- */
-#ifdef EFX_ENABLE_DEBUG
- if (rx_ev_other_err) {
- EFX_INFO_RL(efx, " RX queue %d unexpected RX event "
- EFX_QWORD_FMT "%s%s%s%s%s%s%s%s\n",
- rx_queue->queue, EFX_QWORD_VAL(*event),
- rx_ev_buf_owner_id_err ? " [OWNER_ID_ERR]" : "",
- rx_ev_ip_hdr_chksum_err ?
- " [IP_HDR_CHKSUM_ERR]" : "",
- rx_ev_tcp_udp_chksum_err ?
- " [TCP_UDP_CHKSUM_ERR]" : "",
- rx_ev_eth_crc_err ? " [ETH_CRC_ERR]" : "",
- rx_ev_frm_trunc ? " [FRM_TRUNC]" : "",
- rx_ev_drib_nib ? " [DRIB_NIB]" : "",
- rx_ev_tobe_disc ? " [TOBE_DISC]" : "",
- rx_ev_pause_frm ? " [PAUSE]" : "");
- }
-#endif
-}
-
-/* Handle receive events that are not in-order. */
-static void falcon_handle_rx_bad_index(struct efx_rx_queue *rx_queue,
- unsigned index)
-{
- struct efx_nic *efx = rx_queue->efx;
- unsigned expected, dropped;
-
- expected = rx_queue->removed_count & FALCON_RXD_RING_MASK;
- dropped = ((index + FALCON_RXD_RING_SIZE - expected) &
- FALCON_RXD_RING_MASK);
- EFX_INFO(efx, "dropped %d events (index=%d expected=%d)\n",
- dropped, index, expected);
-
- efx_schedule_reset(efx, EFX_WORKAROUND_5676(efx) ?
- RESET_TYPE_RX_RECOVERY : RESET_TYPE_DISABLE);
-}
-
-/* Handle a packet received event
- *
- * Falcon silicon gives a "discard" flag if it's a unicast packet with the
- * wrong destination address
- * Also "is multicast" and "matches multicast filter" flags can be used to
- * discard non-matching multicast packets.
- */
-static void falcon_handle_rx_event(struct efx_channel *channel,
- const efx_qword_t *event)
-{
- unsigned int rx_ev_desc_ptr, rx_ev_byte_cnt;
- unsigned int rx_ev_hdr_type, rx_ev_mcast_pkt;
- unsigned expected_ptr;
- bool rx_ev_pkt_ok, discard = false, checksummed;
- struct efx_rx_queue *rx_queue;
- struct efx_nic *efx = channel->efx;
-
- /* Basic packet information */
- rx_ev_byte_cnt = EFX_QWORD_FIELD(*event, RX_EV_BYTE_CNT);
- rx_ev_pkt_ok = EFX_QWORD_FIELD(*event, RX_EV_PKT_OK);
- rx_ev_hdr_type = EFX_QWORD_FIELD(*event, RX_EV_HDR_TYPE);
- WARN_ON(EFX_QWORD_FIELD(*event, RX_EV_JUMBO_CONT));
- WARN_ON(EFX_QWORD_FIELD(*event, RX_EV_SOP) != 1);
- WARN_ON(EFX_QWORD_FIELD(*event, RX_EV_Q_LABEL) != channel->channel);
-
- rx_queue = &efx->rx_queue[channel->channel];
-
- rx_ev_desc_ptr = EFX_QWORD_FIELD(*event, RX_EV_DESC_PTR);
- expected_ptr = rx_queue->removed_count & FALCON_RXD_RING_MASK;
- if (unlikely(rx_ev_desc_ptr != expected_ptr))
- falcon_handle_rx_bad_index(rx_queue, rx_ev_desc_ptr);
-
- if (likely(rx_ev_pkt_ok)) {
- /* If packet is marked as OK and packet type is TCP/IPv4 or
- * UDP/IPv4, then we can rely on the hardware checksum.
- */
- checksummed = RX_EV_HDR_TYPE_HAS_CHECKSUMS(rx_ev_hdr_type);
- } else {
- falcon_handle_rx_not_ok(rx_queue, event, &rx_ev_pkt_ok,
- &discard);
- checksummed = false;
- }
-
- /* Detect multicast packets that didn't match the filter */
- rx_ev_mcast_pkt = EFX_QWORD_FIELD(*event, RX_EV_MCAST_PKT);
- if (rx_ev_mcast_pkt) {
- unsigned int rx_ev_mcast_hash_match =
- EFX_QWORD_FIELD(*event, RX_EV_MCAST_HASH_MATCH);
-
- if (unlikely(!rx_ev_mcast_hash_match))
- discard = true;
- }
-
- channel->irq_mod_score += 2;
-
- /* Handle received packet */
- efx_rx_packet(rx_queue, rx_ev_desc_ptr, rx_ev_byte_cnt,
- checksummed, discard);
-}
-
-/* Global events are basically PHY events */
-static void falcon_handle_global_event(struct efx_channel *channel,
- efx_qword_t *event)
-{
- struct efx_nic *efx = channel->efx;
- bool handled = false;
-
- if (EFX_QWORD_FIELD(*event, G_PHY0_INTR) ||
- EFX_QWORD_FIELD(*event, G_PHY1_INTR) ||
- EFX_QWORD_FIELD(*event, XG_PHY_INTR) ||
- EFX_QWORD_FIELD(*event, XFP_PHY_INTR)) {
- efx->phy_op->clear_interrupt(efx);
- queue_work(efx->workqueue, &efx->phy_work);
- handled = true;
- }
-
- if ((falcon_rev(efx) >= FALCON_REV_B0) &&
- EFX_QWORD_FIELD(*event, XG_MNT_INTR_B0)) {
- queue_work(efx->workqueue, &efx->mac_work);
- handled = true;
- }
-
- if (EFX_QWORD_FIELD_VER(efx, *event, RX_RECOVERY)) {
- EFX_ERR(efx, "channel %d seen global RX_RESET "
- "event. Resetting.\n", channel->channel);
-
- atomic_inc(&efx->rx_reset);
- efx_schedule_reset(efx, EFX_WORKAROUND_6555(efx) ?
- RESET_TYPE_RX_RECOVERY : RESET_TYPE_DISABLE);
- handled = true;
- }
-
- if (!handled)
- EFX_ERR(efx, "channel %d unknown global event "
- EFX_QWORD_FMT "\n", channel->channel,
- EFX_QWORD_VAL(*event));
-}
-
-static void falcon_handle_driver_event(struct efx_channel *channel,
- efx_qword_t *event)
-{
- struct efx_nic *efx = channel->efx;
- unsigned int ev_sub_code;
- unsigned int ev_sub_data;
-
- ev_sub_code = EFX_QWORD_FIELD(*event, DRIVER_EV_SUB_CODE);
- ev_sub_data = EFX_QWORD_FIELD(*event, DRIVER_EV_SUB_DATA);
-
- switch (ev_sub_code) {
- case TX_DESCQ_FLS_DONE_EV_DECODE:
- EFX_TRACE(efx, "channel %d TXQ %d flushed\n",
- channel->channel, ev_sub_data);
- break;
- case RX_DESCQ_FLS_DONE_EV_DECODE:
- EFX_TRACE(efx, "channel %d RXQ %d flushed\n",
- channel->channel, ev_sub_data);
- break;
- case EVQ_INIT_DONE_EV_DECODE:
- EFX_LOG(efx, "channel %d EVQ %d initialised\n",
- channel->channel, ev_sub_data);
- break;
- case SRM_UPD_DONE_EV_DECODE:
- EFX_TRACE(efx, "channel %d SRAM update done\n",
- channel->channel);
- break;
- case WAKE_UP_EV_DECODE:
- EFX_TRACE(efx, "channel %d RXQ %d wakeup event\n",
- channel->channel, ev_sub_data);
- break;
- case TIMER_EV_DECODE:
- EFX_TRACE(efx, "channel %d RX queue %d timer expired\n",
- channel->channel, ev_sub_data);
- break;
- case RX_RECOVERY_EV_DECODE:
- EFX_ERR(efx, "channel %d seen DRIVER RX_RESET event. "
- "Resetting.\n", channel->channel);
- atomic_inc(&efx->rx_reset);
- efx_schedule_reset(efx,
- EFX_WORKAROUND_6555(efx) ?
- RESET_TYPE_RX_RECOVERY :
- RESET_TYPE_DISABLE);
- break;
- case RX_DSC_ERROR_EV_DECODE:
- EFX_ERR(efx, "RX DMA Q %d reports descriptor fetch error."
- " RX Q %d is disabled.\n", ev_sub_data, ev_sub_data);
- efx_schedule_reset(efx, RESET_TYPE_RX_DESC_FETCH);
- break;
- case TX_DSC_ERROR_EV_DECODE:
- EFX_ERR(efx, "TX DMA Q %d reports descriptor fetch error."
- " TX Q %d is disabled.\n", ev_sub_data, ev_sub_data);
- efx_schedule_reset(efx, RESET_TYPE_TX_DESC_FETCH);
- break;
- default:
- EFX_TRACE(efx, "channel %d unknown driver event code %d "
- "data %04x\n", channel->channel, ev_sub_code,
- ev_sub_data);
- break;
- }
-}
-
-int falcon_process_eventq(struct efx_channel *channel, int rx_quota)
-{
- unsigned int read_ptr;
- efx_qword_t event, *p_event;
- int ev_code;
- int rx_packets = 0;
-
- read_ptr = channel->eventq_read_ptr;
-
- do {
- p_event = falcon_event(channel, read_ptr);
- event = *p_event;
-
- if (!falcon_event_present(&event))
- /* End of events */
- break;
-
- EFX_TRACE(channel->efx, "channel %d event is "EFX_QWORD_FMT"\n",
- channel->channel, EFX_QWORD_VAL(event));
-
- /* Clear this event by marking it all ones */
- EFX_SET_QWORD(*p_event);
-
- ev_code = EFX_QWORD_FIELD(event, EV_CODE);
-
- switch (ev_code) {
- case RX_IP_EV_DECODE:
- falcon_handle_rx_event(channel, &event);
- ++rx_packets;
- break;
- case TX_IP_EV_DECODE:
- falcon_handle_tx_event(channel, &event);
- break;
- case DRV_GEN_EV_DECODE:
- channel->eventq_magic
- = EFX_QWORD_FIELD(event, EVQ_MAGIC);
- EFX_LOG(channel->efx, "channel %d received generated "
- "event "EFX_QWORD_FMT"\n", channel->channel,
- EFX_QWORD_VAL(event));
- break;
- case GLOBAL_EV_DECODE:
- falcon_handle_global_event(channel, &event);
- break;
- case DRIVER_EV_DECODE:
- falcon_handle_driver_event(channel, &event);
- break;
- default:
- EFX_ERR(channel->efx, "channel %d unknown event type %d"
- " (data " EFX_QWORD_FMT ")\n", channel->channel,
- ev_code, EFX_QWORD_VAL(event));
- }
-
- /* Increment read pointer */
- read_ptr = (read_ptr + 1) & FALCON_EVQ_MASK;
-
- } while (rx_packets < rx_quota);
-
- channel->eventq_read_ptr = read_ptr;
- return rx_packets;
-}
-
-void falcon_set_int_moderation(struct efx_channel *channel)
-{
- efx_dword_t timer_cmd;
- struct efx_nic *efx = channel->efx;
-
- /* Set timer register */
- if (channel->irq_moderation) {
- /* Round to resolution supported by hardware. The value we
- * program is based at 0. So actual interrupt moderation
- * achieved is ((x + 1) * res).
- */
- channel->irq_moderation -= (channel->irq_moderation %
- FALCON_IRQ_MOD_RESOLUTION);
- if (channel->irq_moderation < FALCON_IRQ_MOD_RESOLUTION)
- channel->irq_moderation = FALCON_IRQ_MOD_RESOLUTION;
- EFX_POPULATE_DWORD_2(timer_cmd,
- TIMER_MODE, TIMER_MODE_INT_HLDOFF,
- TIMER_VAL,
- channel->irq_moderation /
- FALCON_IRQ_MOD_RESOLUTION - 1);
- } else {
- EFX_POPULATE_DWORD_2(timer_cmd,
- TIMER_MODE, TIMER_MODE_DIS,
- TIMER_VAL, 0);
- }
- falcon_writel_page_locked(efx, &timer_cmd, TIMER_CMD_REG_KER,
- channel->channel);
-
-}
-
-/* Allocate buffer table entries for event queue */
-int falcon_probe_eventq(struct efx_channel *channel)
-{
- struct efx_nic *efx = channel->efx;
- unsigned int evq_size;
-
- evq_size = FALCON_EVQ_SIZE * sizeof(efx_qword_t);
- return falcon_alloc_special_buffer(efx, &channel->eventq, evq_size);
-}
-
-void falcon_init_eventq(struct efx_channel *channel)
-{
- efx_oword_t evq_ptr;
- struct efx_nic *efx = channel->efx;
-
- EFX_LOG(efx, "channel %d event queue in special buffers %d-%d\n",
- channel->channel, channel->eventq.index,
- channel->eventq.index + channel->eventq.entries - 1);
-
- /* Pin event queue buffer */
- falcon_init_special_buffer(efx, &channel->eventq);
-
- /* Fill event queue with all ones (i.e. empty events) */
- memset(channel->eventq.addr, 0xff, channel->eventq.len);
-
- /* Push event queue to card */
- EFX_POPULATE_OWORD_3(evq_ptr,
- EVQ_EN, 1,
- EVQ_SIZE, FALCON_EVQ_ORDER,
- EVQ_BUF_BASE_ID, channel->eventq.index);
- falcon_write_table(efx, &evq_ptr, efx->type->evq_ptr_tbl_base,
- channel->channel);
-
- falcon_set_int_moderation(channel);
-}
-
-void falcon_fini_eventq(struct efx_channel *channel)
-{
- efx_oword_t eventq_ptr;
- struct efx_nic *efx = channel->efx;
-
- /* Remove event queue from card */
- EFX_ZERO_OWORD(eventq_ptr);
- falcon_write_table(efx, &eventq_ptr, efx->type->evq_ptr_tbl_base,
- channel->channel);
-
- /* Unpin event queue */
- falcon_fini_special_buffer(efx, &channel->eventq);
-}
-
-/* Free buffers backing event queue */
-void falcon_remove_eventq(struct efx_channel *channel)
-{
- falcon_free_special_buffer(channel->efx, &channel->eventq);
-}