summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorJonathan Matthew <jmatthew@cvs.openbsd.org>2019-05-17 07:12:33 +0000
committerJonathan Matthew <jmatthew@cvs.openbsd.org>2019-05-17 07:12:33 +0000
commit33b7fa39407b32922a6f42ec971b9db2d920c5bc (patch)
tree595e1da16b4fece262cfbde6e461e6c899594788 /sys/dev
parentc6084d174b32091125e72a1cbb2dcfbe564c04d7 (diff)
Implement mcx_down() and use it to unwind unsuccessful mcx_up() attempts.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/pci/if_mcx.c640
1 files changed, 599 insertions, 41 deletions
diff --git a/sys/dev/pci/if_mcx.c b/sys/dev/pci/if_mcx.c
index a6b5d92445c..d910638f312 100644
--- a/sys/dev/pci/if_mcx.c
+++ b/sys/dev/pci/if_mcx.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_mcx.c,v 1.7 2019/05/15 06:56:36 jmatthew Exp $ */
+/* $OpenBSD: if_mcx.c,v 1.8 2019/05/17 07:12:32 jmatthew Exp $ */
/*
* Copyright (c) 2017 David Gwynne <dlg@openbsd.org>
@@ -187,27 +187,37 @@
#define MCX_CMD_ALLOC_TRANSPORT_DOMAIN \
0x816
#define MCX_CMD_CREATE_TIR 0x900
+#define MCX_CMD_DESTROY_TIR 0x902
#define MCX_CMD_CREATE_SQ 0x904
#define MCX_CMD_MODIFY_SQ 0x905
+#define MCX_CMD_DESTROY_SQ 0x906
#define MCX_CMD_QUERY_SQ 0x907
#define MCX_CMD_CREATE_RQ 0x908
#define MCX_CMD_MODIFY_RQ 0x909
+#define MCX_CMD_DESTROY_RQ 0x90a
#define MCX_CMD_QUERY_RQ 0x90b
#define MCX_CMD_CREATE_TIS 0x912
+#define MCX_CMD_DESTROY_TIS 0x914
#define MCX_CMD_SET_FLOW_TABLE_ROOT \
0x92f
#define MCX_CMD_CREATE_FLOW_TABLE \
0x930
+#define MCX_CMD_DESTROY_FLOW_TABLE \
+ 0x931
#define MCX_CMD_QUERY_FLOW_TABLE \
0x932
#define MCX_CMD_CREATE_FLOW_GROUP \
0x933
+#define MCX_CMD_DESTROY_FLOW_GROUP \
+ 0x934
#define MCX_CMD_QUERY_FLOW_GROUP \
0x935
#define MCX_CMD_SET_FLOW_TABLE_ENTRY \
0x936
#define MCX_CMD_QUERY_FLOW_TABLE_ENTRY \
0x937
+#define MCX_CMD_DELETE_FLOW_TABLE_ENTRY \
+ 0x938
#define MCX_CMD_ALLOC_FLOW_COUNTER \
0x939
#define MCX_CMD_QUERY_FLOW_COUNTER \
@@ -1075,6 +1085,21 @@ struct mcx_cmd_create_tir_out {
uint8_t cmd_reserved1[4];
} __packed __aligned(4);
+struct mcx_cmd_destroy_tir_in {
+ uint16_t cmd_opcode;
+ uint8_t cmd_reserved0[4];
+ uint16_t cmd_op_mod;
+ uint32_t cmd_tirn;
+ uint8_t cmd_reserved1[4];
+} __packed __aligned(4);
+
+struct mcx_cmd_destroy_tir_out {
+ uint8_t cmd_status;
+ uint8_t cmd_reserved0[3];
+ uint32_t cmd_syndrome;
+ uint8_t cmd_reserved1[8];
+} __packed __aligned(4);
+
struct mcx_cmd_create_tis_in {
uint16_t cmd_opcode;
uint8_t cmd_reserved0[4];
@@ -1098,6 +1123,21 @@ struct mcx_cmd_create_tis_out {
uint8_t cmd_reserved1[4];
} __packed __aligned(4);
+struct mcx_cmd_destroy_tis_in {
+ uint16_t cmd_opcode;
+ uint8_t cmd_reserved0[4];
+ uint16_t cmd_op_mod;
+ uint32_t cmd_tisn;
+ uint8_t cmd_reserved1[4];
+} __packed __aligned(4);
+
+struct mcx_cmd_destroy_tis_out {
+ uint8_t cmd_status;
+ uint8_t cmd_reserved0[3];
+ uint32_t cmd_syndrome;
+ uint8_t cmd_reserved1[8];
+} __packed __aligned(4);
+
struct mcx_cq_ctx {
uint32_t cq_status;
uint32_t cq_reserved1;
@@ -1141,6 +1181,21 @@ struct mcx_cmd_create_cq_out {
uint8_t cmd_reserved1[4];
} __packed __aligned(4);
+struct mcx_cmd_destroy_cq_in {
+ uint16_t cmd_opcode;
+ uint8_t cmd_reserved0[4];
+ uint16_t cmd_op_mod;
+ uint32_t cmd_cqn;
+ uint8_t cmd_reserved1[4];
+} __packed __aligned(4);
+
+struct mcx_cmd_destroy_cq_out {
+ uint8_t cmd_status;
+ uint8_t cmd_reserved0[3];
+ uint32_t cmd_syndrome;
+ uint8_t cmd_reserved1[8];
+} __packed __aligned(4);
+
struct mcx_cq_entry {
uint32_t cq_reserved1;
uint32_t cq_lro;
@@ -1300,6 +1355,22 @@ struct mcx_cmd_modify_sq_out {
uint8_t cmd_reserved1[8];
} __packed __aligned(4);
+struct mcx_cmd_destroy_sq_in {
+ uint16_t cmd_opcode;
+ uint8_t cmd_reserved0[4];
+ uint16_t cmd_op_mod;
+ uint32_t cmd_sqn;
+ uint8_t cmd_reserved1[4];
+} __packed __aligned(4);
+
+struct mcx_cmd_destroy_sq_out {
+ uint8_t cmd_status;
+ uint8_t cmd_reserved0[3];
+ uint32_t cmd_syndrome;
+ uint8_t cmd_reserved1[8];
+} __packed __aligned(4);
+
+
struct mcx_rq_ctx {
uint32_t rq_flags;
#define MCX_RQ_CTX_RLKEY (1 << 31)
@@ -1358,6 +1429,21 @@ struct mcx_cmd_modify_rq_out {
uint8_t cmd_reserved1[8];
} __packed __aligned(4);
+struct mcx_cmd_destroy_rq_in {
+ uint16_t cmd_opcode;
+ uint8_t cmd_reserved0[4];
+ uint16_t cmd_op_mod;
+ uint32_t cmd_rqn;
+ uint8_t cmd_reserved1[4];
+} __packed __aligned(4);
+
+struct mcx_cmd_destroy_rq_out {
+ uint8_t cmd_status;
+ uint8_t cmd_reserved0[3];
+ uint32_t cmd_syndrome;
+ uint8_t cmd_reserved1[8];
+} __packed __aligned(4);
+
struct mcx_cmd_create_flow_table_in {
uint16_t cmd_opcode;
uint8_t cmd_reserved0[4];
@@ -1388,6 +1474,27 @@ struct mcx_cmd_create_flow_table_out {
uint8_t cmd_reserved1[4];
} __packed __aligned(4);
+struct mcx_cmd_destroy_flow_table_in {
+ uint16_t cmd_opcode;
+ uint8_t cmd_reserved0[4];
+ uint16_t cmd_op_mod;
+ uint8_t cmd_reserved1[8];
+} __packed __aligned(4);
+
+struct mcx_cmd_destroy_flow_table_mb_in {
+ uint8_t cmd_table_type;
+ uint8_t cmd_reserved0[3];
+ uint32_t cmd_table_id;
+ uint8_t cmd_reserved1[40];
+} __packed __aligned(4);
+
+struct mcx_cmd_destroy_flow_table_out {
+ uint8_t cmd_status;
+ uint8_t cmd_reserved0[3];
+ uint32_t cmd_syndrome;
+ uint8_t cmd_reserved1[8];
+} __packed __aligned(4);
+
struct mcx_cmd_set_flow_table_root_in {
uint16_t cmd_opcode;
uint8_t cmd_reserved0[4];
@@ -1460,6 +1567,28 @@ struct mcx_flow_ctx {
#define MCX_FLOW_CONTEXT_DEST_TYPE_TABLE (1 << 24)
#define MCX_FLOW_CONTEXT_DEST_TYPE_TIR (2 << 24)
+struct mcx_cmd_destroy_flow_group_in {
+ uint16_t cmd_opcode;
+ uint8_t cmd_reserved0[4];
+ uint16_t cmd_op_mod;
+ uint8_t cmd_reserved1[8];
+} __packed __aligned(4);
+
+struct mcx_cmd_destroy_flow_group_mb_in {
+ uint8_t cmd_table_type;
+ uint8_t cmd_reserved0[3];
+ uint32_t cmd_table_id;
+ uint32_t cmd_group_id;
+ uint8_t cmd_reserved1[36];
+} __packed __aligned(4);
+
+struct mcx_cmd_destroy_flow_group_out {
+ uint8_t cmd_status;
+ uint8_t cmd_reserved0[3];
+ uint32_t cmd_syndrome;
+ uint8_t cmd_reserved1[8];
+} __packed __aligned(4);
+
struct mcx_cmd_set_flow_table_entry_in {
uint16_t cmd_opcode;
uint8_t cmd_reserved0[4];
@@ -1513,6 +1642,29 @@ struct mcx_cmd_query_flow_table_entry_mb_out {
struct mcx_flow_ctx cmd_flow_ctx;
} __packed __aligned(4);
+struct mcx_cmd_delete_flow_table_entry_in {
+ uint16_t cmd_opcode;
+ uint8_t cmd_reserved0[4];
+ uint16_t cmd_op_mod;
+ uint8_t cmd_reserved1[8];
+} __packed __aligned(4);
+
+struct mcx_cmd_delete_flow_table_entry_mb_in {
+ uint8_t cmd_table_type;
+ uint8_t cmd_reserved0[3];
+ uint32_t cmd_table_id;
+ uint8_t cmd_reserved1[8];
+ uint32_t cmd_flow_index;
+ uint8_t cmd_reserved2[28];
+} __packed __aligned(4);
+
+struct mcx_cmd_delete_flow_table_entry_out {
+ uint8_t cmd_status;
+ uint8_t cmd_reserved0[3];
+ uint32_t cmd_syndrome;
+ uint8_t cmd_reserved1[8];
+} __packed __aligned(4);
+
struct mcx_cmd_query_flow_group_in {
uint16_t cmd_opcode;
uint8_t cmd_reserved0[4];
@@ -1764,16 +1916,24 @@ static int mcx_create_eq(struct mcx_softc *);
static int mcx_query_nic_vport_context(struct mcx_softc *);
static int mcx_query_special_contexts(struct mcx_softc *);
static int mcx_create_cq(struct mcx_softc *, int);
+static int mcx_destroy_cq(struct mcx_softc *, int);
static int mcx_create_sq(struct mcx_softc *, int);
+static int mcx_destroy_sq(struct mcx_softc *);
static int mcx_ready_sq(struct mcx_softc *);
static int mcx_create_rq(struct mcx_softc *, int);
+static int mcx_destroy_rq(struct mcx_softc *);
static int mcx_ready_rq(struct mcx_softc *);
static int mcx_create_tir(struct mcx_softc *);
+static int mcx_destroy_tir(struct mcx_softc *);
static int mcx_create_tis(struct mcx_softc *);
+static int mcx_destroy_tis(struct mcx_softc *);
static int mcx_create_flow_table(struct mcx_softc *);
static int mcx_set_flow_table_root(struct mcx_softc *);
+static int mcx_destroy_flow_table(struct mcx_softc *);
static int mcx_create_flow_group(struct mcx_softc *);
+static int mcx_destroy_flow_group(struct mcx_softc *);
static int mcx_set_flow_table_entry(struct mcx_softc *, int);
+static int mcx_delete_flow_table_entry(struct mcx_softc *, int);
#if 0
static int mcx_dump_flow_table(struct mcx_softc *);
@@ -2041,6 +2201,9 @@ mcx_attach(struct device *parent, struct device *self, void *aux)
timeout_set(&sc->sc_rx_refill, mcx_refill, sc);
+ sc->sc_flow_table_id = -1;
+ sc->sc_flow_group_id = -1;
+
/* set interface admin down, so bringing it up will start autoneg */
return;
@@ -3530,6 +3693,49 @@ free:
}
static int
+mcx_destroy_cq(struct mcx_softc *sc, int index)
+{
+ struct mcx_cmdq_entry *cqe;
+ struct mcx_cmd_destroy_cq_in *in;
+ struct mcx_cmd_destroy_cq_out *out;
+ int error;
+ int token;
+
+ cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
+ token = mcx_cmdq_token(sc);
+ mcx_cmdq_init(sc, cqe, sizeof(*in), sizeof(*out), token);
+
+ in = mcx_cmdq_in(cqe);
+ in->cmd_opcode = htobe16(MCX_CMD_DESTROY_CQ);
+ in->cmd_op_mod = htobe16(0);
+ in->cmd_cqn = htobe32(sc->sc_cq[index].cq_n);
+
+ mcx_cmdq_post(sc, cqe, 0);
+ error = mcx_cmdq_poll(sc, cqe, 1000);
+ if (error != 0) {
+ printf("%s: destroy cq timeout\n", DEVNAME(sc));
+ return error;
+ }
+ if (mcx_cmdq_verify(cqe) != 0) {
+ printf("%s: destroy cq command corrupt\n", DEVNAME(sc));
+ return error;
+ }
+
+ out = mcx_cmdq_out(cqe);
+ if (out->cmd_status != MCX_CQ_STATUS_OK) {
+ printf("%s: destroy cq failed (%x, %x)\n", DEVNAME(sc),
+ out->cmd_status, betoh32(out->cmd_syndrome));
+ return -1;
+ }
+
+ sc->sc_cq[index].cq_n = 0;
+ mcx_dmamem_free(sc, &sc->sc_cq[index].cq_mem);
+ sc->sc_cq[index].cq_cons = 0;
+ sc->sc_cq[index].cq_count = 0;
+ return 0;
+}
+
+static int
mcx_create_rq(struct mcx_softc *sc, int cqn)
{
struct mcx_cmdq_entry *cqe;
@@ -3663,6 +3869,46 @@ free:
}
static int
+mcx_destroy_rq(struct mcx_softc *sc)
+{
+ struct mcx_cmdq_entry *cqe;
+ struct mcx_cmd_destroy_rq_in *in;
+ struct mcx_cmd_destroy_rq_out *out;
+ int error;
+ int token;
+
+ cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
+ token = mcx_cmdq_token(sc);
+ mcx_cmdq_init(sc, cqe, sizeof(*in), sizeof(*out), token);
+
+ in = mcx_cmdq_in(cqe);
+ in->cmd_opcode = htobe16(MCX_CMD_DESTROY_RQ);
+ in->cmd_op_mod = htobe16(0);
+ in->cmd_rqn = htobe32(sc->sc_rqn);
+
+ mcx_cmdq_post(sc, cqe, 0);
+ error = mcx_cmdq_poll(sc, cqe, 1000);
+ if (error != 0) {
+ printf("%s: destroy rq timeout\n", DEVNAME(sc));
+ return error;
+ }
+ if (mcx_cmdq_verify(cqe) != 0) {
+ printf("%s: destroy rq command corrupt\n", DEVNAME(sc));
+ return error;
+ }
+
+ out = mcx_cmdq_out(cqe);
+ if (out->cmd_status != MCX_CQ_STATUS_OK) {
+ printf("%s: destroy rq failed (%x, %x)\n", DEVNAME(sc),
+ out->cmd_status, betoh32(out->cmd_syndrome));
+ return -1;
+ }
+
+ sc->sc_rqn = 0;
+ return 0;
+}
+
+static int
mcx_create_tir(struct mcx_softc *sc)
{
struct mcx_cmdq_entry *cqe;
@@ -3715,6 +3961,46 @@ free:
}
static int
+mcx_destroy_tir(struct mcx_softc *sc)
+{
+ struct mcx_cmdq_entry *cqe;
+ struct mcx_cmd_destroy_tir_in *in;
+ struct mcx_cmd_destroy_tir_out *out;
+ int error;
+ int token;
+
+ cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
+ token = mcx_cmdq_token(sc);
+ mcx_cmdq_init(sc, cqe, sizeof(*in), sizeof(*out), token);
+
+ in = mcx_cmdq_in(cqe);
+ in->cmd_opcode = htobe16(MCX_CMD_DESTROY_TIR);
+ in->cmd_op_mod = htobe16(0);
+ in->cmd_tirn = htobe32(sc->sc_tirn);
+
+ mcx_cmdq_post(sc, cqe, 0);
+ error = mcx_cmdq_poll(sc, cqe, 1000);
+ if (error != 0) {
+ printf("%s: destroy tir timeout\n", DEVNAME(sc));
+ return error;
+ }
+ if (mcx_cmdq_verify(cqe) != 0) {
+ printf("%s: destroy tir command corrupt\n", DEVNAME(sc));
+ return error;
+ }
+
+ out = mcx_cmdq_out(cqe);
+ if (out->cmd_status != MCX_CQ_STATUS_OK) {
+ printf("%s: destroy tir failed (%x, %x)\n", DEVNAME(sc),
+ out->cmd_status, betoh32(out->cmd_syndrome));
+ return -1;
+ }
+
+ sc->sc_tirn = 0;
+ return 0;
+}
+
+static int
mcx_create_sq(struct mcx_softc *sc, int cqn)
{
struct mcx_cmdq_entry *cqe;
@@ -3800,6 +4086,46 @@ free:
}
static int
+mcx_destroy_sq(struct mcx_softc *sc)
+{
+ struct mcx_cmdq_entry *cqe;
+ struct mcx_cmd_destroy_sq_in *in;
+ struct mcx_cmd_destroy_sq_out *out;
+ int error;
+ int token;
+
+ cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
+ token = mcx_cmdq_token(sc);
+ mcx_cmdq_init(sc, cqe, sizeof(*in), sizeof(*out), token);
+
+ in = mcx_cmdq_in(cqe);
+ in->cmd_opcode = htobe16(MCX_CMD_DESTROY_SQ);
+ in->cmd_op_mod = htobe16(0);
+ in->cmd_sqn = htobe32(sc->sc_sqn);
+
+ mcx_cmdq_post(sc, cqe, 0);
+ error = mcx_cmdq_poll(sc, cqe, 1000);
+ if (error != 0) {
+ printf("%s: destroy sq timeout\n", DEVNAME(sc));
+ return error;
+ }
+ if (mcx_cmdq_verify(cqe) != 0) {
+ printf("%s: destroy sq command corrupt\n", DEVNAME(sc));
+ return error;
+ }
+
+ out = mcx_cmdq_out(cqe);
+ if (out->cmd_status != MCX_CQ_STATUS_OK) {
+ printf("%s: destroy sq failed (%x, %x)\n", DEVNAME(sc),
+ out->cmd_status, betoh32(out->cmd_syndrome));
+ return -1;
+ }
+
+ sc->sc_sqn = 0;
+ return 0;
+}
+
+static int
mcx_ready_sq(struct mcx_softc *sc)
{
struct mcx_cmdq_entry *cqe;
@@ -3902,6 +4228,47 @@ free:
}
static int
+mcx_destroy_tis(struct mcx_softc *sc)
+{
+ struct mcx_cmdq_entry *cqe;
+ struct mcx_cmd_destroy_tis_in *in;
+ struct mcx_cmd_destroy_tis_out *out;
+ int error;
+ int token;
+
+ cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
+ token = mcx_cmdq_token(sc);
+ mcx_cmdq_init(sc, cqe, sizeof(*in), sizeof(*out), token);
+
+ in = mcx_cmdq_in(cqe);
+ in->cmd_opcode = htobe16(MCX_CMD_DESTROY_TIS);
+ in->cmd_op_mod = htobe16(0);
+ in->cmd_tisn = htobe32(sc->sc_tisn);
+
+ mcx_cmdq_post(sc, cqe, 0);
+ error = mcx_cmdq_poll(sc, cqe, 1000);
+ if (error != 0) {
+ printf("%s: destroy tis timeout\n", DEVNAME(sc));
+ return error;
+ }
+ if (mcx_cmdq_verify(cqe) != 0) {
+ printf("%s: destroy tis command corrupt\n", DEVNAME(sc));
+ return error;
+ }
+
+ out = mcx_cmdq_out(cqe);
+ if (out->cmd_status != MCX_CQ_STATUS_OK) {
+ printf("%s: destroy tis failed (%x, %x)\n", DEVNAME(sc),
+ out->cmd_status, betoh32(out->cmd_syndrome));
+ return -1;
+ }
+
+ sc->sc_tirn = 0;
+ return 0;
+}
+
+#if 0
+static int
mcx_alloc_flow_counter(struct mcx_softc *sc, int i)
{
struct mcx_cmdq_entry *cqe;
@@ -3939,6 +4306,7 @@ mcx_alloc_flow_counter(struct mcx_softc *sc, int i)
return (0);
}
+#endif
static int
mcx_create_flow_table(struct mcx_softc *sc)
@@ -4044,6 +4412,61 @@ free:
}
static int
+mcx_destroy_flow_table(struct mcx_softc *sc)
+{
+ struct mcx_cmdq_entry *cqe;
+ struct mcx_dmamem mxm;
+ struct mcx_cmd_destroy_flow_table_in *in;
+ struct mcx_cmd_destroy_flow_table_mb_in *mb;
+ struct mcx_cmd_destroy_flow_table_out *out;
+ int error;
+ int token;
+
+ cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
+ token = mcx_cmdq_token(sc);
+ mcx_cmdq_init(sc, cqe, sizeof(*in) + sizeof(*mb), sizeof(*out), token);
+
+ in = mcx_cmdq_in(cqe);
+ in->cmd_opcode = htobe16(MCX_CMD_DESTROY_FLOW_TABLE);
+ in->cmd_op_mod = htobe16(0);
+
+ if (mcx_cmdq_mboxes_alloc(sc, &mxm, 1, &cqe->cq_input_ptr, token) != 0) {
+ printf("%s: unable to allocate destroy flow table mailbox\n",
+ DEVNAME(sc));
+ return (-1);
+ }
+ mb = mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0));
+ mb->cmd_table_type = MCX_FLOW_TABLE_TYPE_RX;
+ mb->cmd_table_id = htobe32(sc->sc_flow_table_id);
+
+ mcx_cmdq_mboxes_sign(&mxm, 1);
+ mcx_cmdq_post(sc, cqe, 0);
+ error = mcx_cmdq_poll(sc, cqe, 1000);
+ if (error != 0) {
+ printf("%s: destroy flow table timeout\n", DEVNAME(sc));
+ goto free;
+ }
+ if (mcx_cmdq_verify(cqe) != 0) {
+ printf("%s: destroy flow table command corrupt\n", DEVNAME(sc));
+ goto free;
+ }
+
+ out = mcx_cmdq_out(cqe);
+ if (out->cmd_status != MCX_CQ_STATUS_OK) {
+ printf("%s: destroy flow table failed (%x, %x)\n", DEVNAME(sc),
+ out->cmd_status, betoh32(out->cmd_syndrome));
+ error = -1;
+ goto free;
+ }
+
+ sc->sc_flow_table_id = -1;
+free:
+ mcx_dmamem_free(sc, &mxm);
+ return (error);
+}
+
+
+static int
mcx_create_flow_group(struct mcx_softc *sc)
{
struct mcx_cmdq_entry *cqe;
@@ -4101,6 +4524,61 @@ free:
}
static int
+mcx_destroy_flow_group(struct mcx_softc *sc)
+{
+ struct mcx_cmdq_entry *cqe;
+ struct mcx_dmamem mxm;
+ struct mcx_cmd_destroy_flow_group_in *in;
+ struct mcx_cmd_destroy_flow_group_mb_in *mb;
+ struct mcx_cmd_destroy_flow_group_out *out;
+ int error;
+ int token;
+
+ cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
+ token = mcx_cmdq_token(sc);
+ mcx_cmdq_init(sc, cqe, sizeof(*in) + sizeof(*mb), sizeof(*out), token);
+
+ in = mcx_cmdq_in(cqe);
+ in->cmd_opcode = htobe16(MCX_CMD_DESTROY_FLOW_GROUP);
+ in->cmd_op_mod = htobe16(0);
+
+ if (mcx_cmdq_mboxes_alloc(sc, &mxm, 2, &cqe->cq_input_ptr, token) != 0) {
+ printf("%s: unable to allocate destroy flow group mailbox\n",
+ DEVNAME(sc));
+ return (-1);
+ }
+ mb = mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0));
+ mb->cmd_table_type = MCX_FLOW_TABLE_TYPE_RX;
+ mb->cmd_table_id = htobe32(sc->sc_flow_table_id);
+ mb->cmd_group_id = htobe32(sc->sc_flow_group_id);
+
+ mcx_cmdq_mboxes_sign(&mxm, 2);
+ mcx_cmdq_post(sc, cqe, 0);
+ error = mcx_cmdq_poll(sc, cqe, 1000);
+ if (error != 0) {
+ printf("%s: destroy flow group timeout\n", DEVNAME(sc));
+ goto free;
+ }
+ if (mcx_cmdq_verify(cqe) != 0) {
+ printf("%s: destroy flow group command corrupt\n", DEVNAME(sc));
+ goto free;
+ }
+
+ out = mcx_cmdq_out(cqe);
+ if (out->cmd_status != MCX_CQ_STATUS_OK) {
+ printf("%s: destroy flow group failed (%x, %x)\n", DEVNAME(sc),
+ out->cmd_status, betoh32(out->cmd_syndrome));
+ error = -1;
+ goto free;
+ }
+
+ sc->sc_flow_group_id = -1;
+free:
+ mcx_dmamem_free(sc, &mxm);
+ return (error);
+}
+
+static int
mcx_set_flow_table_entry(struct mcx_softc *sc, int counter)
{
struct mcx_cmdq_entry *cqe;
@@ -4178,6 +4656,63 @@ free:
return (error);
}
+static int
+mcx_delete_flow_table_entry(struct mcx_softc *sc, int index)
+{
+ struct mcx_cmdq_entry *cqe;
+ struct mcx_dmamem mxm;
+ struct mcx_cmd_delete_flow_table_entry_in *in;
+ struct mcx_cmd_delete_flow_table_entry_mb_in *mbin;
+ struct mcx_cmd_delete_flow_table_entry_out *out;
+ int error;
+ int token;
+
+ cqe = MCX_DMA_KVA(&sc->sc_cmdq_mem);
+ token = mcx_cmdq_token(sc);
+ mcx_cmdq_init(sc, cqe, sizeof(*in) + sizeof(*mbin), sizeof(*out),
+ token);
+
+ in = mcx_cmdq_in(cqe);
+ in->cmd_opcode = htobe16(MCX_CMD_DELETE_FLOW_TABLE_ENTRY);
+ in->cmd_op_mod = htobe16(0);
+
+ if (mcx_cmdq_mboxes_alloc(sc, &mxm, 2, &cqe->cq_input_ptr, token) != 0) {
+ printf("%s: unable to allocate delete flow table entry mailbox\n",
+ DEVNAME(sc));
+ return (-1);
+ }
+ mbin = mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0));
+ mbin->cmd_table_type = MCX_FLOW_TABLE_TYPE_RX;
+ mbin->cmd_table_id = htobe32(sc->sc_flow_table_id);
+ mbin->cmd_flow_index = htobe32(index);
+
+ mcx_cmdq_mboxes_sign(&mxm, 2);
+ mcx_cmdq_post(sc, cqe, 0);
+ error = mcx_cmdq_poll(sc, cqe, 1000);
+ if (error != 0) {
+ printf("%s: delete flow table entry timeout\n", DEVNAME(sc));
+ goto free;
+ }
+ if (mcx_cmdq_verify(cqe) != 0) {
+ printf("%s: delete flow table entry command corrupt\n",
+ DEVNAME(sc));
+ goto free;
+ }
+
+ out = mcx_cmdq_out(cqe);
+ if (out->cmd_status != MCX_CQ_STATUS_OK) {
+ printf("%s: delete flow table entry %d failed (%x, %x)\n",
+ DEVNAME(sc), index, out->cmd_status,
+ betoh32(out->cmd_syndrome));
+ error = -1;
+ goto free;
+ }
+
+free:
+ mcx_dmamem_free(sc, &mxm);
+ return (error);
+}
+
#if 0
int
mcx_dump_flow_table(struct mcx_softc *sc)
@@ -4939,7 +5474,8 @@ mcx_intr(void *xsc)
}
static void
-mcx_free_slots(struct mcx_softc *sc, struct mcx_slot *slots, int allocated, int total)
+mcx_free_slots(struct mcx_softc *sc, struct mcx_slot *slots, int allocated,
+ int total)
{
struct mcx_slot *ms;
@@ -4947,6 +5483,8 @@ mcx_free_slots(struct mcx_softc *sc, struct mcx_slot *slots, int allocated, int
while (i-- > 0) {
ms = &slots[i];
bus_dmamap_destroy(sc->sc_dmat, ms->ms_map);
+ if (ms->ms_m != NULL)
+ m_freem(ms->ms_m);
}
free(slots, M_DEVBUF, total * sizeof(*ms));
}
@@ -4994,52 +5532,41 @@ mcx_up(struct mcx_softc *sc)
}
if (mcx_create_cq(sc, sc->sc_eqn) != 0)
- goto destroy_tx_slots;
- if (mcx_create_cq(sc, sc->sc_eqn) != 0)
- goto destroy_tx_slots;
+ goto down;
/* send queue */
if (mcx_create_tis(sc) != 0)
- goto destroy_sq;
+ goto down;
if (mcx_create_sq(sc, sc->sc_cq[0].cq_n) != 0)
- goto destroy_rq;
+ goto down;
/* receive queue */
if (mcx_create_rq(sc, sc->sc_cq[0].cq_n) != 0)
- goto destroy_cq;
+ goto down;
if (mcx_create_tir(sc) != 0)
- goto destroy_tis;
-
- if (0) {
- if (mcx_alloc_flow_counter(sc, 0) != 0)
- goto destroy_tir;
- if (mcx_alloc_flow_counter(sc, 1) != 0)
- goto destroy_tir;
- if (mcx_alloc_flow_counter(sc, 2) != 0)
- goto destroy_tir;
- }
+ goto down;
/* receive flow table mapping everything to the rq */
if (mcx_create_flow_table(sc) != 0)
- goto destroy_tir;
+ goto down;
if (mcx_create_flow_group(sc) != 0)
- goto destroy_flow_table; /* probably don't have to unset the root table? */
+ goto down;
if (mcx_set_flow_table_entry(sc, -1) != 0)
- goto destroy_flow_group;
+ goto down;
if (mcx_set_flow_table_root(sc) != 0)
- goto destroy_flow_table;
+ goto down;
/* start the queues */
if (mcx_ready_sq(sc) != 0)
- goto destroy_flow_table_entry;
+ goto down;
if (mcx_ready_rq(sc) != 0)
- goto destroy_flow_table_entry;
+ goto down;
if_rxr_init(&sc->sc_rxr, 1, (1 << MCX_LOG_RQ_SIZE));
sc->sc_rx_cons = 0;
@@ -5054,22 +5581,6 @@ mcx_up(struct mcx_softc *sc)
ifq_restart(&ifp->if_snd);
return;
-destroy_flow_table_entry:
- /* mcx_destroy_flow_table_entry(sc); */
-destroy_flow_group:
- /* mcx_destroy_flow_group(sc); */
-destroy_flow_table:
- /* mcx_destroy_flow_table(sc); */
-destroy_tir:
- /* mcx_destroy_tir(sc); */
-destroy_tis:
- /* mcx_destroy_tis(sc); */
-destroy_sq:
- /* mcx_destroy_sq(sc); */
-destroy_rq:
- /* mcx_destroy_rq(sc); */
-destroy_cq:
- /* mcx_destroy_cq(sc); */
destroy_tx_slots:
mcx_free_slots(sc, sc->sc_tx_slots, i, (1 << MCX_LOG_SQ_SIZE));
sc->sc_rx_slots = NULL;
@@ -5078,12 +5589,59 @@ destroy_tx_slots:
destroy_rx_slots:
mcx_free_slots(sc, sc->sc_rx_slots, i, (1 << MCX_LOG_RQ_SIZE));
sc->sc_rx_slots = NULL;
+down:
+ mcx_down(sc);
}
static void
mcx_down(struct mcx_softc *sc)
{
- /* destroy all the rings and stuff? */
+ struct ifnet *ifp = &sc->sc_ac.ac_if;
+ int i;
+
+ CLR(ifp->if_flags, IFF_RUNNING);
+
+ /*
+ * delete flow table entries first, so no packets can arrive
+ * after the barriers
+ */
+ for (i = 0; i < sc->sc_flow_table_entry; i++)
+ mcx_delete_flow_table_entry(sc, i);
+ sc->sc_flow_table_entry = 0;
+
+ intr_barrier(&sc->sc_ih);
+ ifq_barrier(&ifp->if_snd);
+
+ if (sc->sc_flow_group_id != -1)
+ mcx_destroy_flow_group(sc);
+
+ if (sc->sc_flow_table_id != -1)
+ mcx_destroy_flow_table(sc);
+
+ if (sc->sc_tirn != 0)
+ mcx_destroy_tir(sc);
+ if (sc->sc_rqn != 0)
+ mcx_destroy_rq(sc);
+
+ if (sc->sc_sqn != 0)
+ mcx_destroy_sq(sc);
+ if (sc->sc_tisn != 0)
+ mcx_destroy_tis(sc);
+
+ for (i = 0; i < sc->sc_num_cq; i++)
+ mcx_destroy_cq(sc, i);
+ sc->sc_num_cq = 0;
+
+ if (sc->sc_tx_slots != NULL) {
+ mcx_free_slots(sc, sc->sc_tx_slots, (1 << MCX_LOG_SQ_SIZE),
+ (1 << MCX_LOG_SQ_SIZE));
+ sc->sc_tx_slots = NULL;
+ }
+ if (sc->sc_rx_slots != NULL) {
+ mcx_free_slots(sc, sc->sc_rx_slots, (1 << MCX_LOG_RQ_SIZE),
+ (1 << MCX_LOG_RQ_SIZE));
+ sc->sc_rx_slots = NULL;
+ }
}
static int