Commit ea6fd0f9 authored by Antoine Kaufmann's avatar Antoine Kaufmann
Browse files

i40e: more admin queue handling

parent dd28f774
...@@ -48,6 +48,11 @@ GUESTS := \ ...@@ -48,6 +48,11 @@ GUESTS := \
gem5-vr-replica-1-cp \ gem5-vr-replica-1-cp \
gem5-vr-replica-2-cp \ gem5-vr-replica-2-cp \
gem5-vr-client-cp \ gem5-vr-client-cp \
gem5-pair-client-16f-cp \
gem5-pair-client-16f \
gem5-pair-client-largewin-cp \
gem5-pair-server-udp-cp \
gem5-pair-client-udp-cp \
# experiments we want for the paper # experiments we want for the paper
EXPERIMENTS := \ EXPERIMENTS := \
......
...@@ -62,7 +62,7 @@ run_qemu() { ...@@ -62,7 +62,7 @@ run_qemu() {
-drive file=$img_a,if=ide,index=0 \ -drive file=$img_a,if=ide,index=0 \
-drive file=$img_b,if=ide,index=1,driver=raw \ -drive file=$img_b,if=ide,index=1,driver=raw \
-kernel $QEMU_KERNEL \ -kernel $QEMU_KERNEL \
-append "earlyprintk=ttyS0 console=ttyS0 root=/dev/sda1 init=/home/ubuntu/guestinit.sh rw" \ -append "earlyprintk=ttyS0 console=ttyS0 root=/dev/sda1 init=/home/ubuntu/guestinit.sh i40e.debug=0x8fffffff rw" \
-serial mon:stdio -m $((4 * 1024)) -smp 1 -display none -enable-kvm \ -serial mon:stdio -m $((4 * 1024)) -smp 1 -display none -enable-kvm \
-nic none \ -nic none \
-chardev socket,path=$pcisock,id=cosimcd \ -chardev socket,path=$pcisock,id=cosimcd \
......
...@@ -428,6 +428,12 @@ uint16_t shadow_ram::read(uint16_t addr) ...@@ -428,6 +428,12 @@ uint16_t shadow_ram::read(uint16_t addr)
case I40E_SR_BOOT_CONFIG_PTR: case I40E_SR_BOOT_CONFIG_PTR:
return 0; return 0;
case I40E_SR_NVM_CONTROL_WORD:
return (1 << I40E_SR_CONTROL_WORD_1_SHIFT);
case I40E_SR_SW_CHECKSUM_WORD:
return 0xbaba;
default: default:
std::cerr << "TODO shadow memory read addr=" << std::hex << addr std::cerr << "TODO shadow memory read addr=" << std::hex << addr
<< std::endl; << std::endl;
......
...@@ -8,6 +8,8 @@ extern "C" { ...@@ -8,6 +8,8 @@ extern "C" {
} }
#include <nicbm.h> #include <nicbm.h>
struct i40e_aq_desc;
namespace i40e { namespace i40e {
class i40e_bm; class i40e_bm;
...@@ -40,6 +42,17 @@ class queue_base { ...@@ -40,6 +42,17 @@ class queue_base {
virtual void done(); virtual void done();
}; };
class dma_data_wb : public dma_base {
protected:
queue_base &queue;
dma_wb &desc_dma;
public:
uint32_t index;
dma_data_wb(queue_base &queue_, size_t len, dma_wb &desc_dma_);
virtual ~dma_data_wb();
virtual void done();
};
uint64_t base; uint64_t base;
uint32_t len; uint32_t len;
uint32_t fetch_head; uint32_t fetch_head;
...@@ -51,6 +64,8 @@ class queue_base { ...@@ -51,6 +64,8 @@ class queue_base {
void trigger_fetch(); void trigger_fetch();
void desc_writeback(const void *desc, uint32_t idx); void desc_writeback(const void *desc, uint32_t idx);
void desc_writeback_indirect(const void *desc, uint32_t idx,
uint64_t data_addr, const void *data, size_t data_len);
/** called when a descriptor is fetched */ /** called when a descriptor is fetched */
virtual void desc_fetched(void *desc, uint32_t idx) = 0; virtual void desc_fetched(void *desc, uint32_t idx) = 0;
...@@ -66,6 +81,17 @@ class queue_admin_tx : public queue_base { ...@@ -66,6 +81,17 @@ class queue_admin_tx : public queue_base {
protected: protected:
i40e_bm &dev; i40e_bm &dev;
// prepare completion descriptor (fills flags, and return value)
void desc_compl_prepare(struct i40e_aq_desc *d, uint16_t retval,
uint16_t extra_flags);
// complete direct response
void desc_complete(struct i40e_aq_desc *d, uint32_t idx,
uint16_t retval, uint16_t extra_flags = 0);
// complete indirect response
void desc_complete_indir(struct i40e_aq_desc *d, uint32_t idx,
uint16_t retval, const void *data, size_t len,
uint16_t extra_flags = 0);
virtual void desc_fetched(void *desc, uint32_t idx); virtual void desc_fetched(void *desc, uint32_t idx);
uint64_t &reg_base; uint64_t &reg_base;
......
...@@ -55,6 +55,27 @@ void queue_base::desc_writeback(const void *desc, uint32_t idx) ...@@ -55,6 +55,27 @@ void queue_base::desc_writeback(const void *desc, uint32_t idx)
runner->issue_dma(*dma); runner->issue_dma(*dma);
} }
void queue_base::desc_writeback_indirect(const void *desc, uint32_t idx,
uint64_t data_addr, const void *data, size_t data_len)
{
// descriptor dma
dma_wb *desc_dma = new dma_wb(*this, desc_len);
desc_dma->write = true;
desc_dma->dma_addr = base + idx * desc_len;
desc_dma->index = idx;
memcpy(desc_dma->data, desc, desc_len);
// purposefully not issued yet, data dma will issue once ready
// data dma
dma_data_wb *data_dma = new dma_data_wb(*this, data_len, *desc_dma);
data_dma->write = true;
data_dma->dma_addr = data_addr;
data_dma->index = idx;
memcpy(data_dma->data, data, data_len);
runner->issue_dma(*data_dma);
}
void queue_base::desc_written_back(uint32_t idx) void queue_base::desc_written_back(uint32_t idx)
{ {
std::cerr << "descriptor " << idx << " written back" << std::endl; std::cerr << "descriptor " << idx << " written back" << std::endl;
...@@ -100,6 +121,27 @@ void queue_base::dma_wb::done() ...@@ -100,6 +121,27 @@ void queue_base::dma_wb::done()
} }
queue_base::dma_data_wb::dma_data_wb(queue_base &queue_, size_t len_,
dma_wb &desc_dma_)
: queue(queue_), desc_dma(desc_dma_)
{
data = new char[len_];
len = len_;
}
queue_base::dma_data_wb::~dma_data_wb()
{
delete[] ((char *) data);
}
void queue_base::dma_data_wb::done()
{
// now we can issue descriptor dma
runner->issue_dma(desc_dma);
delete this;
}
/******************************************************************************/ /******************************************************************************/
queue_admin_tx::queue_admin_tx(i40e_bm &dev_, uint64_t &reg_base_, queue_admin_tx::queue_admin_tx(i40e_bm &dev_, uint64_t &reg_base_,
...@@ -110,6 +152,41 @@ queue_admin_tx::queue_admin_tx(i40e_bm &dev_, uint64_t &reg_base_, ...@@ -110,6 +152,41 @@ queue_admin_tx::queue_admin_tx(i40e_bm &dev_, uint64_t &reg_base_,
desc_len = 32; desc_len = 32;
} }
void queue_admin_tx::desc_compl_prepare(struct i40e_aq_desc *d, uint16_t retval,
uint16_t extra_flags)
{
d->flags &= ~0x1ff;
d->flags |= I40E_AQ_FLAG_DD | I40E_AQ_FLAG_CMP | extra_flags;
if (retval)
d->flags |= I40E_AQ_FLAG_ERR;
d->retval = retval;
}
void queue_admin_tx::desc_complete(struct i40e_aq_desc *d, uint32_t idx,
uint16_t retval, uint16_t extra_flags)
{
desc_compl_prepare(d, extra_flags, retval);
desc_writeback(d, idx);
}
void queue_admin_tx::desc_complete_indir(struct i40e_aq_desc *d, uint32_t idx,
uint16_t retval, const void *data, size_t len, uint16_t extra_flags)
{
if (len > d->datalen) {
std::cerr << "queue_admin_tx::desc_complete_indir: data too long ("
<< len << ") got buffer for (" << d->datalen << ")" << std::endl;
abort();
}
d->datalen = len;
desc_compl_prepare(d, extra_flags, retval);
uint64_t addr = d->params.external.addr_low |
(((uint64_t) d->params.external.addr_high) << 32);
desc_writeback_indirect(d, idx, addr, data, len);
}
void queue_admin_tx::desc_fetched(void *desc, uint32_t idx) void queue_admin_tx::desc_fetched(void *desc, uint32_t idx)
{ {
struct i40e_aq_desc *d = reinterpret_cast<struct i40e_aq_desc *>(desc); struct i40e_aq_desc *d = reinterpret_cast<struct i40e_aq_desc *>(desc);
...@@ -127,9 +204,7 @@ void queue_admin_tx::desc_fetched(void *desc, uint32_t idx) ...@@ -127,9 +204,7 @@ void queue_admin_tx::desc_fetched(void *desc, uint32_t idx)
gv->api_major = I40E_FW_API_VERSION_MAJOR; gv->api_major = I40E_FW_API_VERSION_MAJOR;
gv->api_minor = I40E_FW_API_VERSION_MINOR_X710; gv->api_minor = I40E_FW_API_VERSION_MINOR_X710;
d->flags |= I40E_AQ_FLAG_DD | I40E_AQ_FLAG_CMP; desc_complete(d, idx, 0);
desc_writeback(d, idx);
} else if (d->opcode == i40e_aqc_opc_request_resource) { } else if (d->opcode == i40e_aqc_opc_request_resource) {
std::cerr << " request resource" << std::endl; std::cerr << " request resource" << std::endl;
struct i40e_aqc_request_resource *rr = struct i40e_aqc_request_resource *rr =
...@@ -138,6 +213,7 @@ void queue_admin_tx::desc_fetched(void *desc, uint32_t idx) ...@@ -138,6 +213,7 @@ void queue_admin_tx::desc_fetched(void *desc, uint32_t idx)
rr->timeout = 180000; rr->timeout = 180000;
std::cerr << " res_id=" << rr->resource_id << std::endl; std::cerr << " res_id=" << rr->resource_id << std::endl;
std::cerr << " res_nu=" << rr->resource_number << std::endl; std::cerr << " res_nu=" << rr->resource_number << std::endl;
desc_complete(d, idx, 0);
} else if (d->opcode == i40e_aqc_opc_release_resource) { } else if (d->opcode == i40e_aqc_opc_release_resource) {
std::cerr << " release resource" << std::endl; std::cerr << " release resource" << std::endl;
struct i40e_aqc_request_resource *rr = struct i40e_aqc_request_resource *rr =
...@@ -145,11 +221,41 @@ void queue_admin_tx::desc_fetched(void *desc, uint32_t idx) ...@@ -145,11 +221,41 @@ void queue_admin_tx::desc_fetched(void *desc, uint32_t idx)
d->params.raw); d->params.raw);
std::cerr << " res_id=" << rr->resource_id << std::endl; std::cerr << " res_id=" << rr->resource_id << std::endl;
std::cerr << " res_nu=" << rr->resource_number << std::endl; std::cerr << " res_nu=" << rr->resource_number << std::endl;
desc_complete(d, idx, 0);
} else if (d->opcode == i40e_aqc_opc_clear_pxe_mode) { } else if (d->opcode == i40e_aqc_opc_clear_pxe_mode) {
std::cerr << " clear PXE mode" << std::endl; std::cerr << " clear PXE mode" << std::endl;
dev.regs.gllan_rctl_0 &= ~I40E_GLLAN_RCTL_0_PXE_MODE_MASK; dev.regs.gllan_rctl_0 &= ~I40E_GLLAN_RCTL_0_PXE_MODE_MASK;
desc_complete(d, idx, 0);
} else if (d->opcode == i40e_aqc_opc_list_func_capabilities ||
d->opcode == i40e_aqc_opc_list_dev_capabilities)
{
std::cerr << " get dev/fun caps" << std::endl;
struct i40e_aqc_list_capabilites *lc =
reinterpret_cast<struct i40e_aqc_list_capabilites *>(
d->params.raw);
struct i40e_aqc_list_capabilities_element_resp caps[] = {
{ I40E_AQ_CAP_ID_RSS, 1, 0, 512, 6, 0, {} },
{ I40E_AQ_CAP_ID_RXQ, 1, 0, dev.NUM_QUEUES, 0, 0, {} },
{ I40E_AQ_CAP_ID_TXQ, 1, 0, dev.NUM_QUEUES, 0, 0, {} },
{ I40E_AQ_CAP_ID_MSIX, 1, 0, dev.NUM_PFINTS, 0, 0, {} },
};
size_t num_caps = sizeof(caps) / sizeof(caps[0]);
if (sizeof(caps) <= d->datalen) {
std::cerr << " data fits" << std::endl;
// data fits within the buffer
lc->count = num_caps;
desc_complete_indir(d, idx, 0, caps, sizeof(caps));
} else {
std::cerr << " data doesn't fit" << std::endl;
// data does not fit
d->datalen = sizeof(caps);
desc_complete(d, idx, I40E_AQ_RC_ENOMEM);
}
} else { } else {
std::cerr << " uknown opcode=" << d->opcode << std::endl; std::cerr << " uknown opcode=" << d->opcode << std::endl;
desc_complete(d, idx, I40E_AQ_RC_ESRCH);
} }
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
#include <nicbm.h> #include <nicbm.h>
//#define DEBUG_NICBM 1 #define DEBUG_NICBM 1
#define SYNC_PERIOD (500 * 1000ULL) // 500ns #define SYNC_PERIOD (500 * 1000ULL) // 500ns
#define PCI_LATENCY (500 * 1000ULL) // 500ns #define PCI_LATENCY (500 * 1000ULL) // 500ns
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment