aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/cxgbe/adapter.h1
-rw-r--r--sys/dev/cxgbe/t4_filter.c42
-rw-r--r--sys/dev/cxgbe/t4_ioctl.h2
-rw-r--r--sys/dev/cxgbe/t4_main.c3
4 files changed, 48 insertions, 0 deletions
diff --git a/sys/dev/cxgbe/adapter.h b/sys/dev/cxgbe/adapter.h
index 8b8e6bf339e8..5fe7b76ccb0d 100644
--- a/sys/dev/cxgbe/adapter.h
+++ b/sys/dev/cxgbe/adapter.h
@@ -1337,6 +1337,7 @@ void cxgbe_ratelimit_query(struct ifnet *, struct if_ratelimit_query_results *);
/* t4_filter.c */
int get_filter_mode(struct adapter *, uint32_t *);
int set_filter_mode(struct adapter *, uint32_t);
+int set_filter_mask(struct adapter *, uint32_t);
int get_filter(struct adapter *, struct t4_filter *);
int set_filter(struct adapter *, struct t4_filter *);
int del_filter(struct adapter *, struct t4_filter *);
diff --git a/sys/dev/cxgbe/t4_filter.c b/sys/dev/cxgbe/t4_filter.c
index 1e0269fcd5c0..3afab0d1d6b9 100644
--- a/sys/dev/cxgbe/t4_filter.c
+++ b/sys/dev/cxgbe/t4_filter.c
@@ -543,6 +543,48 @@ done:
return (rc);
}
+int
+set_filter_mask(struct adapter *sc, uint32_t mode)
+{
+ struct tp_params *tp = &sc->params.tp;
+ int rc, iconf;
+ uint16_t fmask;
+
+ iconf = mode_to_iconf(mode);
+ fmask = mode_to_fconf(mode);
+ if ((iconf == -1 || iconf == tp->vnic_mode) && fmask == tp->filter_mask)
+ return (0); /* Nothing to do */
+
+ /*
+ * We aren't going to change the global filter mode or VNIC mode here.
+ * The given filter mask must conform to them.
+ */
+ if ((fmask | tp->filter_mode) != tp->filter_mode)
+ return (EINVAL);
+ if (iconf != -1 && iconf != tp->vnic_mode)
+ return (EINVAL);
+
+ rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4sethfm");
+ if (rc)
+ return (rc);
+
+ if (sc->tids.tids_in_use > 0) { /* TOE or hashfilters active */
+ rc = EBUSY;
+ goto done;
+ }
+
+#ifdef TCP_OFFLOAD
+ if (uld_active(sc, ULD_TOM)) {
+ rc = EBUSY;
+ goto done;
+ }
+#endif
+ rc = -t4_set_filter_cfg(sc, -1, fmask, -1);
+done:
+ end_synchronized_op(sc, 0);
+ return (rc);
+}
+
static inline uint64_t
get_filter_hits(struct adapter *sc, uint32_t tid)
{
diff --git a/sys/dev/cxgbe/t4_ioctl.h b/sys/dev/cxgbe/t4_ioctl.h
index 4f0a71683ef0..ff2c5ef80a14 100644
--- a/sys/dev/cxgbe/t4_ioctl.h
+++ b/sys/dev/cxgbe/t4_ioctl.h
@@ -63,6 +63,7 @@ enum {
T4_LOAD_BOOT, /* flash boot rom */
T4_LOAD_BOOTCFG, /* flash bootcfg */
T4_CUDBG_DUMP, /* debug dump of chip state */
+ T4_SET_FILTER_MASK, /* set filter mask (hashfilter mode) */
};
struct t4_reg {
@@ -429,4 +430,5 @@ struct t4_offload_policy {
#define CHELSIO_T4_LOAD_BOOTCFG _IOW('f', T4_LOAD_BOOTCFG, struct t4_data)
#define CHELSIO_T4_CUDBG_DUMP _IOWR('f', T4_CUDBG_DUMP, struct t4_cudbg_dump)
#define CHELSIO_T4_SET_OFLD_POLICY _IOW('f', T4_SET_OFLD_POLICY, struct t4_offload_policy)
+#define CHELSIO_T4_SET_FILTER_MASK _IOW('f', T4_SET_FILTER_MASK, uint32_t)
#endif
diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c
index f64d349b46ae..3594db2ea136 100644
--- a/sys/dev/cxgbe/t4_main.c
+++ b/sys/dev/cxgbe/t4_main.c
@@ -10970,6 +10970,9 @@ t4_ioctl(struct cdev *dev, unsigned long cmd, caddr_t data, int fflag,
case CHELSIO_T4_SET_FILTER_MODE:
rc = set_filter_mode(sc, *(uint32_t *)data);
break;
+ case CHELSIO_T4_SET_FILTER_MASK:
+ rc = set_filter_mask(sc, *(uint32_t *)data);
+ break;
case CHELSIO_T4_GET_FILTER:
rc = get_filter(sc, (struct t4_filter *)data);
break;