/********************************************************************** * Author: Cavium, Inc. * * Contact: support@cavium.com * Please include "LiquidIO" in the subject. * * Copyright (c) 2003-2016 Cavium, Inc. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, as * published by the Free Software Foundation. * * This file is distributed in the hope that it will be useful, but * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or * NONINFRINGEMENT. See the GNU General Public License for more * details.
**********************************************************************/ #include <linux/pci.h> #include <linux/netdevice.h> #include <linux/vmalloc.h> #include"liquidio_common.h" #include"octeon_droq.h" #include"octeon_iq.h" #include"response_manager.h" #include"octeon_device.h" #include"octeon_main.h" #include"octeon_network.h" #include"cn66xx_device.h" #include"cn23xx_pf_device.h" #include"cn23xx_vf_device.h"
iq->base_addr = lio_dma_alloc(oct, q_size, &iq->base_addr_dma); if (!iq->base_addr) {
dev_err(&oct->pci_dev->dev, "Cannot allocate memory for instr queue %d\n",
iq_no); return 1;
}
iq->max_count = num_descs;
/* Initialize a list to holds requests that have been posted to Octeon * but has yet to be fetched by octeon
*/
iq->request_list = vzalloc_node(array_size(num_descs, sizeof(*iq->request_list)),
numa_node); if (!iq->request_list)
iq->request_list = vzalloc(array_size(num_descs, sizeof(*iq->request_list))); if (!iq->request_list) {
lio_dma_free(oct, q_size, iq->base_addr, iq->base_addr_dma);
dev_err(&oct->pci_dev->dev, "Alloc failed for IQ[%d] nr free list\n",
iq_no); return 1;
}
/* Return 0 on success, 1 on failure */ int octeon_setup_iq(struct octeon_device *oct, int ifidx, int q_index, union oct_txpciq txpciq,
u32 num_descs, void *app_ctx)
{
u32 iq_no = (u32)txpciq.s.q_no; int numa_node = dev_to_node(&oct->pci_dev->dev);
if (oct->instr_queue[iq_no]) {
dev_dbg(&oct->pci_dev->dev, "IQ is in use. Cannot create the IQ: %d again\n",
iq_no);
oct->instr_queue[iq_no]->txpciq.u64 = txpciq.u64;
oct->instr_queue[iq_no]->app_ctx = app_ctx; return 0;
}
oct->instr_queue[iq_no] =
vzalloc_node(sizeof(struct octeon_instr_queue), numa_node); if (!oct->instr_queue[iq_no])
oct->instr_queue[iq_no] =
vzalloc(sizeof(struct octeon_instr_queue)); if (!oct->instr_queue[iq_no]) return 1;
oct->num_iqs++; if (oct->fn_list.enable_io_queues(oct)) {
octeon_delete_instr_queue(oct, iq_no); return 1;
}
return 0;
}
int lio_wait_for_instr_fetch(struct octeon_device *oct)
{ int i, retry = 1000, pending, instr_cnt = 0;
do {
instr_cnt = 0;
for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct); i++) { if (!(oct->io_qmask.iq & BIT_ULL(i))) continue;
pending =
atomic_read(&oct->instr_queue[i]->instr_pending); if (pending)
__check_db_timeout(oct, i);
instr_cnt += pending;
}
/* This ensures that the read index does not wrap around to the same * position if queue gets full before Octeon could fetch any instr.
*/ if (atomic_read(&iq->instr_pending) >= (s32)(iq->max_count - 1)) {
st.status = IQ_SEND_FAILED;
st.index = -1; return st;
}
if (atomic_read(&iq->instr_pending) >= (s32)(iq->max_count - 2))
st.status = IQ_SEND_STOP;
__copy_cmd_into_iq(iq, cmd);
/* "index" is returned, host_write_index is modified. */
st.index = iq->host_write_index;
iq->host_write_index = incr_index(iq->host_write_index, 1,
iq->max_count);
iq->fill_cnt++;
/* Flush the command into memory. We need to be sure the data is in * memory before indicating that the instruction is pending.
*/
wmb();
atomic_inc(&iq->instr_pending);
return st;
}
int
octeon_register_reqtype_free_fn(struct octeon_device *oct, int reqtype, void (*fn)(void *))
{ if (reqtype > REQTYPE_LAST) {
dev_err(&oct->pci_dev->dev, "%s: Invalid reqtype: %d\n",
__func__, reqtype); return -EINVAL;
}
switch (reqtype) { case REQTYPE_NORESP_NET: case REQTYPE_NORESP_NET_SG: case REQTYPE_RESP_NET_SG:
reqtype_free_fn[oct->octeon_id][reqtype](buf); break; case REQTYPE_RESP_NET: case REQTYPE_SOFT_COMMAND:
sc = buf; /* We're expecting a response from Octeon. * It's up to lio_process_ordered_list() to * process sc. Add sc to the ordered soft * command response list because we expect * a response from Octeon.
*/
spin_lock_irqsave(&oct->response_list
[OCTEON_ORDERED_SC_LIST].lock, flags);
atomic_inc(&oct->response_list
[OCTEON_ORDERED_SC_LIST].pending_req_count);
list_add_tail(&sc->node, &oct->response_list
[OCTEON_ORDERED_SC_LIST].head);
spin_unlock_irqrestore(&oct->response_list
[OCTEON_ORDERED_SC_LIST].lock,
flags); break; default:
dev_err(&oct->pci_dev->dev, "%s Unknown reqtype: %d buf: %p at idx %d\n",
__func__, reqtype, buf, old);
}
/* Can only be called from process context */ int
octeon_flush_iq(struct octeon_device *oct, struct octeon_instr_queue *iq,
u32 napi_budget)
{
u32 inst_processed = 0;
u32 tot_inst_processed = 0; int tx_done = 1;
if (!spin_trylock(&iq->iq_flush_running_lock)) return tx_done;
tot_inst_processed += inst_processed;
} while (tot_inst_processed < napi_budget);
if (napi_budget && (tot_inst_processed >= napi_budget))
tx_done = 0;
iq->last_db_time = jiffies;
spin_unlock_bh(&iq->lock);
spin_unlock(&iq->iq_flush_running_lock);
return tx_done;
}
/* Process instruction queue after timeout. * This routine gets called from a workqueue or when removing the module.
*/ staticvoid __check_db_timeout(struct octeon_device *oct, u64 iq_no)
{ struct octeon_instr_queue *iq;
u64 next_time;
if (!oct) return;
iq = oct->instr_queue[iq_no]; if (!iq) return;
/* return immediately, if no work pending */ if (!atomic_read(&iq->instr_pending)) return; /* If jiffies - last_db_time < db_timeout do nothing */
next_time = iq->last_db_time + iq->db_timeout; if (!time_after(jiffies, (unsignedlong)next_time)) return;
iq->last_db_time = jiffies;
/* Flush the instruction queue */
octeon_flush_iq(oct, iq, 0);
lio_enable_irq(NULL, iq);
}
/* Called by the Poll thread at regular intervals to check the instruction * queue for commands to be posted and for commands that were fetched by Octeon.
*/ staticvoid check_db_timeout(struct work_struct *work)
{ struct cavium_wk *wk = (struct cavium_wk *)work; struct octeon_device *oct = (struct octeon_device *)wk->ctxptr;
u64 iq_no = wk->ctxul; struct cavium_wq *db_wq = &oct->check_db_wq[iq_no];
u32 delay = 10;
iq = oct->instr_queue[sc->iq_no]; if (!iq->allow_soft_cmds) {
dev_err(&oct->pci_dev->dev, "Soft commands are not allowed on Queue %d\n",
sc->iq_no);
INCR_INSTRQUEUE_PKT_COUNT(oct, sc->iq_no, instr_dropped, 1); return IQ_SEND_FAILED;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.