diff --git a/lib/mqnic/Makefile b/lib/mqnic/Makefile index 4a18ff499..aba9d40e1 100644 --- a/lib/mqnic/Makefile +++ b/lib/mqnic/Makefile @@ -22,7 +22,7 @@ all: $(LIB) %.o: %.c $(CC) $(ALL_CFLAGS) -c -o $@ $< -libmqnic.a: mqnic.o reg_block.o +libmqnic.a: mqnic.o mqnic_if.o mqnic_sched_block.o mqnic_scheduler.o reg_block.o ar rcs $@ $^ install: diff --git a/lib/mqnic/mqnic.c b/lib/mqnic/mqnic.c index ab125692e..3019da0b5 100644 --- a/lib/mqnic/mqnic.c +++ b/lib/mqnic/mqnic.c @@ -1,6 +1,6 @@ /* -Copyright 2019, The Regents of the University of California. +Copyright 2019-2022, The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without @@ -36,7 +36,6 @@ either expressed or implied, of The Regents of the University of California. #include #include -#include #include #include #include @@ -483,271 +482,3 @@ void mqnic_close(struct mqnic *dev) free(dev); } - - -struct mqnic_if *mqnic_if_open(struct mqnic *dev, int index, volatile uint8_t *regs) -{ - struct mqnic_if *interface = calloc(1, sizeof(struct mqnic_if)); - - if (!interface) - return NULL; - - interface->mqnic = dev; - - interface->index = index; - - interface->regs_size = dev->if_stride; - interface->regs = regs; - interface->csr_regs = interface->regs + dev->if_csr_offset; - - if (interface->regs >= dev->regs+dev->regs_size || interface->csr_regs >= dev->regs+dev->regs_size) - { - fprintf(stderr, "Error: computed pointer out of range\n"); - goto fail; - } - - // Enumerate registers - interface->rb_list = enumerate_reg_block_list(interface->regs, dev->if_csr_offset, interface->regs_size); - - if (!interface->rb_list) - { - fprintf(stderr, "Error: filed to enumerate blocks\n"); - goto fail; - } - - interface->if_ctrl_rb = find_reg_block(interface->rb_list, MQNIC_RB_IF_CTRL_TYPE, MQNIC_RB_IF_CTRL_VER, 0); - - if (!interface->if_ctrl_rb) - { - fprintf(stderr, "Error: Interface control block not found\n"); - goto fail; - } - - interface->if_features = mqnic_reg_read32(interface->if_ctrl_rb->regs, MQNIC_RB_IF_CTRL_REG_FEATURES); - interface->port_count = mqnic_reg_read32(interface->if_ctrl_rb->regs, MQNIC_RB_IF_CTRL_REG_PORT_COUNT); - interface->sched_block_count = mqnic_reg_read32(interface->if_ctrl_rb->regs, MQNIC_RB_IF_CTRL_REG_SCHED_COUNT); - interface->max_tx_mtu = mqnic_reg_read32(interface->if_ctrl_rb->regs, MQNIC_RB_IF_CTRL_REG_MAX_TX_MTU); - interface->max_rx_mtu = mqnic_reg_read32(interface->if_ctrl_rb->regs, MQNIC_RB_IF_CTRL_REG_MAX_RX_MTU); - - interface->event_queue_rb = find_reg_block(interface->rb_list, MQNIC_RB_EVENT_QM_TYPE, MQNIC_RB_EVENT_QM_VER, 0); - - if (!interface->event_queue_rb) - { - fprintf(stderr, "Error: Event queue block not found\n"); - goto fail; - } - - interface->event_queue_offset = mqnic_reg_read32(interface->event_queue_rb->regs, MQNIC_RB_EVENT_QM_REG_OFFSET); - interface->event_queue_count = mqnic_reg_read32(interface->event_queue_rb->regs, MQNIC_RB_EVENT_QM_REG_COUNT); - interface->event_queue_stride = mqnic_reg_read32(interface->event_queue_rb->regs, MQNIC_RB_EVENT_QM_REG_STRIDE); - - if (interface->event_queue_count > MQNIC_MAX_EVENT_RINGS) - interface->event_queue_count = MQNIC_MAX_EVENT_RINGS; - - interface->tx_queue_rb = find_reg_block(interface->rb_list, MQNIC_RB_TX_QM_TYPE, MQNIC_RB_TX_QM_VER, 0); - - if (!interface->tx_queue_rb) - { - fprintf(stderr, "Error: TX queue block not found\n"); - goto fail; - } - - interface->tx_queue_offset = mqnic_reg_read32(interface->tx_queue_rb->regs, MQNIC_RB_TX_QM_REG_OFFSET); - interface->tx_queue_count = mqnic_reg_read32(interface->tx_queue_rb->regs, MQNIC_RB_TX_QM_REG_COUNT); - interface->tx_queue_stride = mqnic_reg_read32(interface->tx_queue_rb->regs, MQNIC_RB_TX_QM_REG_STRIDE); - - if (interface->tx_queue_count > MQNIC_MAX_TX_RINGS) - interface->tx_queue_count = MQNIC_MAX_TX_RINGS; - - interface->tx_cpl_queue_rb = find_reg_block(interface->rb_list, MQNIC_RB_TX_CQM_TYPE, MQNIC_RB_TX_CQM_VER, 0); - - if (!interface->tx_cpl_queue_rb) - { - fprintf(stderr, "Error: TX completion queue block not found\n"); - goto fail; - } - - interface->tx_cpl_queue_offset = mqnic_reg_read32(interface->tx_cpl_queue_rb->regs, MQNIC_RB_TX_CQM_REG_OFFSET); - interface->tx_cpl_queue_count = mqnic_reg_read32(interface->tx_cpl_queue_rb->regs, MQNIC_RB_TX_CQM_REG_COUNT); - interface->tx_cpl_queue_stride = mqnic_reg_read32(interface->tx_cpl_queue_rb->regs, MQNIC_RB_TX_CQM_REG_STRIDE); - - if (interface->tx_cpl_queue_count > MQNIC_MAX_TX_CPL_RINGS) - interface->tx_cpl_queue_count = MQNIC_MAX_TX_CPL_RINGS; - - interface->rx_queue_rb = find_reg_block(interface->rb_list, MQNIC_RB_RX_QM_TYPE, MQNIC_RB_RX_QM_VER, 0); - - if (!interface->rx_queue_rb) - { - fprintf(stderr, "Error: RX queue block not found\n"); - goto fail; - } - - interface->rx_queue_offset = mqnic_reg_read32(interface->rx_queue_rb->regs, MQNIC_RB_RX_QM_REG_OFFSET); - interface->rx_queue_count = mqnic_reg_read32(interface->rx_queue_rb->regs, MQNIC_RB_RX_QM_REG_COUNT); - interface->rx_queue_stride = mqnic_reg_read32(interface->rx_queue_rb->regs, MQNIC_RB_RX_QM_REG_STRIDE); - - if (interface->rx_queue_count > MQNIC_MAX_RX_RINGS) - interface->rx_queue_count = MQNIC_MAX_RX_RINGS; - - interface->rx_cpl_queue_rb = find_reg_block(interface->rb_list, MQNIC_RB_RX_CQM_TYPE, MQNIC_RB_RX_CQM_VER, 0); - - if (!interface->rx_cpl_queue_rb) - { - fprintf(stderr, "Error: RX completion queue block not found\n"); - goto fail; - } - - interface->rx_cpl_queue_offset = mqnic_reg_read32(interface->rx_cpl_queue_rb->regs, MQNIC_RB_RX_CQM_REG_OFFSET); - interface->rx_cpl_queue_count = mqnic_reg_read32(interface->rx_cpl_queue_rb->regs, MQNIC_RB_RX_CQM_REG_COUNT); - interface->rx_cpl_queue_stride = mqnic_reg_read32(interface->rx_cpl_queue_rb->regs, MQNIC_RB_RX_CQM_REG_STRIDE); - - if (interface->rx_cpl_queue_count > MQNIC_MAX_RX_CPL_RINGS) - interface->rx_cpl_queue_count = MQNIC_MAX_RX_CPL_RINGS; - - for (int k = 0; k < interface->sched_block_count; k++) - { - struct reg_block *sched_block_rb = find_reg_block(interface->rb_list, MQNIC_RB_SCHED_BLOCK_TYPE, MQNIC_RB_SCHED_BLOCK_VER, k); - struct mqnic_sched_block *sched_block; - - if (!sched_block_rb) - goto fail; - - sched_block = mqnic_sched_block_open(interface, k, sched_block_rb); - - if (!sched_block) - goto fail; - - interface->sched_blocks[k] = sched_block; - } - - return interface; - -fail: - mqnic_if_close(interface); - return NULL; -} - -void mqnic_if_close(struct mqnic_if *interface) -{ - if (!interface) - return; - - for (int k = 0; k < interface->sched_block_count; k++) - { - if (!interface->sched_blocks[k]) - continue; - - mqnic_sched_block_close(interface->sched_blocks[k]); - interface->sched_blocks[k] = NULL; - } - - if (interface->rb_list) - free_reg_block_list(interface->rb_list); - - free(interface); -} - -struct mqnic_sched_block *mqnic_sched_block_open(struct mqnic_if *interface, int index, struct reg_block *block_rb) -{ - struct mqnic_sched_block *block = calloc(1, sizeof(struct mqnic_sched_block)); - - if (!block) - return NULL; - - int offset = mqnic_reg_read32(block_rb->regs, MQNIC_RB_SCHED_BLOCK_REG_OFFSET); - - block->mqnic = interface->mqnic; - block->interface = interface; - - block->index = index; - - block->rb_list = enumerate_reg_block_list(interface->regs, offset, interface->regs_size); - - if (!block->rb_list) - { - fprintf(stderr, "Error: filed to enumerate blocks\n"); - goto fail; - } - - block->sched_count = 0; - for (struct reg_block *rb = block->rb_list; rb->type && rb->version; rb++) - { - if (rb->type == MQNIC_RB_SCHED_RR_TYPE && rb->version == MQNIC_RB_SCHED_RR_VER) - { - struct mqnic_sched *sched = mqnic_sched_open(block, block->sched_count, rb); - - if (!sched) - goto fail; - - block->sched[block->sched_count++] = sched; - } - } - - return block; - -fail: - mqnic_sched_block_close(block); - return NULL; -} - -void mqnic_sched_block_close(struct mqnic_sched_block *block) -{ - if (!block) - return; - - for (int k = 0; k < block->sched_count; k++) - { - if (!block->sched[k]) - continue; - - mqnic_sched_close(block->sched[k]); - block->sched[k] = NULL; - } - - if (block->rb_list) - free_reg_block_list(block->rb_list); - - free(block); -} - -struct mqnic_sched *mqnic_sched_open(struct mqnic_sched_block *block, int index, struct reg_block *rb) -{ - struct mqnic_sched *sched = calloc(1, sizeof(struct mqnic_sched)); - - if (!sched) - return NULL; - - sched->mqnic = block->mqnic; - sched->interface = block->interface; - sched->sched_block = block; - - sched->index = index; - - sched->rb = rb; - sched->regs = rb->base + mqnic_reg_read32(rb->regs, MQNIC_RB_SCHED_RR_REG_OFFSET); - - if (sched->regs >= block->interface->regs+block->interface->regs_size) - { - fprintf(stderr, "Error: computed pointer out of range\n"); - goto fail; - } - - sched->type = rb->type; - sched->offset = mqnic_reg_read32(rb->regs, MQNIC_RB_SCHED_RR_REG_OFFSET); - sched->channel_count = mqnic_reg_read32(rb->regs, MQNIC_RB_SCHED_RR_REG_CH_COUNT); - sched->channel_stride = mqnic_reg_read32(rb->regs, MQNIC_RB_SCHED_RR_REG_CH_STRIDE); - - return sched; - -fail: - mqnic_sched_close(sched); - return NULL; -} - -void mqnic_sched_close(struct mqnic_sched *sched) -{ - if (!sched) - return; - - free(sched); -} diff --git a/lib/mqnic/mqnic.h b/lib/mqnic/mqnic.h index 5d5cc7911..46692de65 100644 --- a/lib/mqnic/mqnic.h +++ b/lib/mqnic/mqnic.h @@ -1,6 +1,6 @@ /* -Copyright 2019, The Regents of the University of California. +Copyright 2019-2022, The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without @@ -36,7 +36,6 @@ either expressed or implied, of The Regents of the University of California. #include #include -#include #include "mqnic_hw.h" #include "reg_block.h" @@ -164,15 +163,19 @@ struct mqnic { char pci_device_path[PATH_MAX]; }; +// mqnic.c struct mqnic *mqnic_open(const char *dev_name); void mqnic_close(struct mqnic *dev); +// mqnic_if.c struct mqnic_if *mqnic_if_open(struct mqnic *dev, int index, volatile uint8_t *regs); void mqnic_if_close(struct mqnic_if *interface); +// mqnic_sched_block.c struct mqnic_sched_block *mqnic_sched_block_open(struct mqnic_if *interface, int index, struct reg_block *block_rb); void mqnic_sched_block_close(struct mqnic_sched_block *block); +// mqnic_scheduler.c struct mqnic_sched *mqnic_sched_open(struct mqnic_sched_block *block, int index, struct reg_block *rb); void mqnic_sched_close(struct mqnic_sched *sched); diff --git a/lib/mqnic/mqnic_if.c b/lib/mqnic/mqnic_if.c new file mode 100644 index 000000000..76b31d20b --- /dev/null +++ b/lib/mqnic/mqnic_if.c @@ -0,0 +1,199 @@ +/* + +Copyright 2019-2022, The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS OF THE UNIVERSITY OF CALIFORNIA ''AS +IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF CALIFORNIA OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of The Regents of the University of California. + +*/ + +#include "mqnic.h" + +#include +#include + +struct mqnic_if *mqnic_if_open(struct mqnic *dev, int index, volatile uint8_t *regs) +{ + struct mqnic_if *interface = calloc(1, sizeof(struct mqnic_if)); + + if (!interface) + return NULL; + + interface->mqnic = dev; + + interface->index = index; + + interface->regs_size = dev->if_stride; + interface->regs = regs; + interface->csr_regs = interface->regs + dev->if_csr_offset; + + if (interface->regs >= dev->regs+dev->regs_size || interface->csr_regs >= dev->regs+dev->regs_size) + { + fprintf(stderr, "Error: computed pointer out of range\n"); + goto fail; + } + + // Enumerate registers + interface->rb_list = enumerate_reg_block_list(interface->regs, dev->if_csr_offset, interface->regs_size); + + if (!interface->rb_list) + { + fprintf(stderr, "Error: filed to enumerate blocks\n"); + goto fail; + } + + interface->if_ctrl_rb = find_reg_block(interface->rb_list, MQNIC_RB_IF_CTRL_TYPE, MQNIC_RB_IF_CTRL_VER, 0); + + if (!interface->if_ctrl_rb) + { + fprintf(stderr, "Error: Interface control block not found\n"); + goto fail; + } + + interface->if_features = mqnic_reg_read32(interface->if_ctrl_rb->regs, MQNIC_RB_IF_CTRL_REG_FEATURES); + interface->port_count = mqnic_reg_read32(interface->if_ctrl_rb->regs, MQNIC_RB_IF_CTRL_REG_PORT_COUNT); + interface->sched_block_count = mqnic_reg_read32(interface->if_ctrl_rb->regs, MQNIC_RB_IF_CTRL_REG_SCHED_COUNT); + interface->max_tx_mtu = mqnic_reg_read32(interface->if_ctrl_rb->regs, MQNIC_RB_IF_CTRL_REG_MAX_TX_MTU); + interface->max_rx_mtu = mqnic_reg_read32(interface->if_ctrl_rb->regs, MQNIC_RB_IF_CTRL_REG_MAX_RX_MTU); + + interface->event_queue_rb = find_reg_block(interface->rb_list, MQNIC_RB_EVENT_QM_TYPE, MQNIC_RB_EVENT_QM_VER, 0); + + if (!interface->event_queue_rb) + { + fprintf(stderr, "Error: Event queue block not found\n"); + goto fail; + } + + interface->event_queue_offset = mqnic_reg_read32(interface->event_queue_rb->regs, MQNIC_RB_EVENT_QM_REG_OFFSET); + interface->event_queue_count = mqnic_reg_read32(interface->event_queue_rb->regs, MQNIC_RB_EVENT_QM_REG_COUNT); + interface->event_queue_stride = mqnic_reg_read32(interface->event_queue_rb->regs, MQNIC_RB_EVENT_QM_REG_STRIDE); + + if (interface->event_queue_count > MQNIC_MAX_EVENT_RINGS) + interface->event_queue_count = MQNIC_MAX_EVENT_RINGS; + + interface->tx_queue_rb = find_reg_block(interface->rb_list, MQNIC_RB_TX_QM_TYPE, MQNIC_RB_TX_QM_VER, 0); + + if (!interface->tx_queue_rb) + { + fprintf(stderr, "Error: TX queue block not found\n"); + goto fail; + } + + interface->tx_queue_offset = mqnic_reg_read32(interface->tx_queue_rb->regs, MQNIC_RB_TX_QM_REG_OFFSET); + interface->tx_queue_count = mqnic_reg_read32(interface->tx_queue_rb->regs, MQNIC_RB_TX_QM_REG_COUNT); + interface->tx_queue_stride = mqnic_reg_read32(interface->tx_queue_rb->regs, MQNIC_RB_TX_QM_REG_STRIDE); + + if (interface->tx_queue_count > MQNIC_MAX_TX_RINGS) + interface->tx_queue_count = MQNIC_MAX_TX_RINGS; + + interface->tx_cpl_queue_rb = find_reg_block(interface->rb_list, MQNIC_RB_TX_CQM_TYPE, MQNIC_RB_TX_CQM_VER, 0); + + if (!interface->tx_cpl_queue_rb) + { + fprintf(stderr, "Error: TX completion queue block not found\n"); + goto fail; + } + + interface->tx_cpl_queue_offset = mqnic_reg_read32(interface->tx_cpl_queue_rb->regs, MQNIC_RB_TX_CQM_REG_OFFSET); + interface->tx_cpl_queue_count = mqnic_reg_read32(interface->tx_cpl_queue_rb->regs, MQNIC_RB_TX_CQM_REG_COUNT); + interface->tx_cpl_queue_stride = mqnic_reg_read32(interface->tx_cpl_queue_rb->regs, MQNIC_RB_TX_CQM_REG_STRIDE); + + if (interface->tx_cpl_queue_count > MQNIC_MAX_TX_CPL_RINGS) + interface->tx_cpl_queue_count = MQNIC_MAX_TX_CPL_RINGS; + + interface->rx_queue_rb = find_reg_block(interface->rb_list, MQNIC_RB_RX_QM_TYPE, MQNIC_RB_RX_QM_VER, 0); + + if (!interface->rx_queue_rb) + { + fprintf(stderr, "Error: RX queue block not found\n"); + goto fail; + } + + interface->rx_queue_offset = mqnic_reg_read32(interface->rx_queue_rb->regs, MQNIC_RB_RX_QM_REG_OFFSET); + interface->rx_queue_count = mqnic_reg_read32(interface->rx_queue_rb->regs, MQNIC_RB_RX_QM_REG_COUNT); + interface->rx_queue_stride = mqnic_reg_read32(interface->rx_queue_rb->regs, MQNIC_RB_RX_QM_REG_STRIDE); + + if (interface->rx_queue_count > MQNIC_MAX_RX_RINGS) + interface->rx_queue_count = MQNIC_MAX_RX_RINGS; + + interface->rx_cpl_queue_rb = find_reg_block(interface->rb_list, MQNIC_RB_RX_CQM_TYPE, MQNIC_RB_RX_CQM_VER, 0); + + if (!interface->rx_cpl_queue_rb) + { + fprintf(stderr, "Error: RX completion queue block not found\n"); + goto fail; + } + + interface->rx_cpl_queue_offset = mqnic_reg_read32(interface->rx_cpl_queue_rb->regs, MQNIC_RB_RX_CQM_REG_OFFSET); + interface->rx_cpl_queue_count = mqnic_reg_read32(interface->rx_cpl_queue_rb->regs, MQNIC_RB_RX_CQM_REG_COUNT); + interface->rx_cpl_queue_stride = mqnic_reg_read32(interface->rx_cpl_queue_rb->regs, MQNIC_RB_RX_CQM_REG_STRIDE); + + if (interface->rx_cpl_queue_count > MQNIC_MAX_RX_CPL_RINGS) + interface->rx_cpl_queue_count = MQNIC_MAX_RX_CPL_RINGS; + + for (int k = 0; k < interface->sched_block_count; k++) + { + struct reg_block *sched_block_rb = find_reg_block(interface->rb_list, MQNIC_RB_SCHED_BLOCK_TYPE, MQNIC_RB_SCHED_BLOCK_VER, k); + struct mqnic_sched_block *sched_block; + + if (!sched_block_rb) + goto fail; + + sched_block = mqnic_sched_block_open(interface, k, sched_block_rb); + + if (!sched_block) + goto fail; + + interface->sched_blocks[k] = sched_block; + } + + return interface; + +fail: + mqnic_if_close(interface); + return NULL; +} + +void mqnic_if_close(struct mqnic_if *interface) +{ + if (!interface) + return; + + for (int k = 0; k < interface->sched_block_count; k++) + { + if (!interface->sched_blocks[k]) + continue; + + mqnic_sched_block_close(interface->sched_blocks[k]); + interface->sched_blocks[k] = NULL; + } + + if (interface->rb_list) + free_reg_block_list(interface->rb_list); + + free(interface); +} diff --git a/lib/mqnic/mqnic_sched_block.c b/lib/mqnic/mqnic_sched_block.c new file mode 100644 index 000000000..7f500486d --- /dev/null +++ b/lib/mqnic/mqnic_sched_block.c @@ -0,0 +1,100 @@ +/* + +Copyright 2019-2022, The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS OF THE UNIVERSITY OF CALIFORNIA ''AS +IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF CALIFORNIA OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of The Regents of the University of California. + +*/ + +#include "mqnic.h" + +#include +#include + +struct mqnic_sched_block *mqnic_sched_block_open(struct mqnic_if *interface, int index, struct reg_block *block_rb) +{ + struct mqnic_sched_block *block = calloc(1, sizeof(struct mqnic_sched_block)); + + if (!block) + return NULL; + + int offset = mqnic_reg_read32(block_rb->regs, MQNIC_RB_SCHED_BLOCK_REG_OFFSET); + + block->mqnic = interface->mqnic; + block->interface = interface; + + block->index = index; + + block->rb_list = enumerate_reg_block_list(interface->regs, offset, interface->regs_size); + + if (!block->rb_list) + { + fprintf(stderr, "Error: filed to enumerate blocks\n"); + goto fail; + } + + block->sched_count = 0; + for (struct reg_block *rb = block->rb_list; rb->type && rb->version; rb++) + { + if (rb->type == MQNIC_RB_SCHED_RR_TYPE && rb->version == MQNIC_RB_SCHED_RR_VER) + { + struct mqnic_sched *sched = mqnic_sched_open(block, block->sched_count, rb); + + if (!sched) + goto fail; + + block->sched[block->sched_count++] = sched; + } + } + + return block; + +fail: + mqnic_sched_block_close(block); + return NULL; +} + +void mqnic_sched_block_close(struct mqnic_sched_block *block) +{ + if (!block) + return; + + for (int k = 0; k < block->sched_count; k++) + { + if (!block->sched[k]) + continue; + + mqnic_sched_close(block->sched[k]); + block->sched[k] = NULL; + } + + if (block->rb_list) + free_reg_block_list(block->rb_list); + + free(block); +} diff --git a/lib/mqnic/mqnic_scheduler.c b/lib/mqnic/mqnic_scheduler.c new file mode 100644 index 000000000..5b6cba0e2 --- /dev/null +++ b/lib/mqnic/mqnic_scheduler.c @@ -0,0 +1,79 @@ +/* + +Copyright 2019-2022, The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS OF THE UNIVERSITY OF CALIFORNIA ''AS +IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF CALIFORNIA OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of The Regents of the University of California. + +*/ + +#include "mqnic.h" + +#include +#include + +struct mqnic_sched *mqnic_sched_open(struct mqnic_sched_block *block, int index, struct reg_block *rb) +{ + struct mqnic_sched *sched = calloc(1, sizeof(struct mqnic_sched)); + + if (!sched) + return NULL; + + sched->mqnic = block->mqnic; + sched->interface = block->interface; + sched->sched_block = block; + + sched->index = index; + + sched->rb = rb; + sched->regs = rb->base + mqnic_reg_read32(rb->regs, MQNIC_RB_SCHED_RR_REG_OFFSET); + + if (sched->regs >= block->interface->regs+block->interface->regs_size) + { + fprintf(stderr, "Error: computed pointer out of range\n"); + goto fail; + } + + sched->type = rb->type; + sched->offset = mqnic_reg_read32(rb->regs, MQNIC_RB_SCHED_RR_REG_OFFSET); + sched->channel_count = mqnic_reg_read32(rb->regs, MQNIC_RB_SCHED_RR_REG_CH_COUNT); + sched->channel_stride = mqnic_reg_read32(rb->regs, MQNIC_RB_SCHED_RR_REG_CH_STRIDE); + + return sched; + +fail: + mqnic_sched_close(sched); + return NULL; +} + +void mqnic_sched_close(struct mqnic_sched *sched) +{ + if (!sched) + return; + + free(sched); +}