[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1450335186-3062-3-git-send-email-kan.liang@intel.com>
Date: Thu, 17 Dec 2015 06:53:04 +0000
From: kan.liang@...el.com
To: netdev@...r.kernel.org, davem@...emloft.net, bwh@...nel.org
Cc: jesse.brandeburg@...el.com, andi@...stfloor.org,
f.fainelli@...il.com, alexander.duyck@...il.com,
jeffrey.t.kirsher@...el.com, shannon.nelson@...el.com,
carolyn.wyborny@...el.com, donald.c.skidmore@...el.com,
mitch.a.williams@...el.com, ogerlitz@...lanox.com,
edumazet@...gle.com, jiri@...lanox.com, sfeldma@...il.com,
gospo@...ulusnetworks.com, sasha.levin@...cle.com,
dsahern@...il.com, tj@...nel.org, cascardo@...hat.com,
corbet@....net, ben@...adent.org.uk,
Kan Liang <kan.liang@...el.com>
Subject: [RFC 3/5] ethtool: introduce new ioctl for per queue setting
From: Kan Liang <kan.liang@...el.com>
Introduce a new ioctl for per queue parameters setting.
Users can apply commands to specific queues by setting SUB_COMMAND and
queue_mask as following command.
ethtool --set-perqueue-command DEVNAME [queue_mask %x] SUB_COMMAND
If queue_mask is not set, the SUB_COMMAND will be applied to all queues.
The following patches will enable SUB_COMMANDs for per queue setting.
Signed-off-by: Kan Liang <kan.liang@...el.com>
---
ethtool-copy.h | 18 +++++++++++
ethtool.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
internal.h | 2 ++
3 files changed, 114 insertions(+)
diff --git a/ethtool-copy.h b/ethtool-copy.h
index d23ffc4..a76c1dc 100644
--- a/ethtool-copy.h
+++ b/ethtool-copy.h
@@ -1108,6 +1108,22 @@ enum ethtool_sfeatures_retval_bits {
#define ETHTOOL_F_WISH (1 << ETHTOOL_F_WISH__BIT)
#define ETHTOOL_F_COMPAT (1 << ETHTOOL_F_COMPAT__BIT)
+#define MAX_QUEUE 4096
+#define MAX_QUEUE_MASK (MAX_QUEUE / 64)
+
+/**
+ * struct ethtool_per_queue_op - apply sub command to the queues in mask.
+ * @cmd: ETHTOOL_PERQUEUE
+ * @queue_mask: Mask the queues which sub command apply to
+ * @sub_command: the sub command
+ * @data: parameters of the command
+ */
+struct ethtool_per_queue_op {
+ __u32 cmd;
+ __u64 queue_mask[MAX_QUEUE_MASK];
+ __u32 sub_command;
+ char data[];
+};
/* CMDs currently supported */
#define ETHTOOL_GSET 0x00000001 /* Get settings. */
@@ -1190,6 +1206,8 @@ enum ethtool_sfeatures_retval_bits {
#define ETHTOOL_GTUNABLE 0x00000048 /* Get tunable configuration */
#define ETHTOOL_STUNABLE 0x00000049 /* Set tunable configuration */
+#define ETHTOOL_PERQUEUE 0x0000004a /* Set per queue options */
+
/* compatibility with older code */
#define SPARC_ETH_GSET ETHTOOL_GSET
#define SPARC_ETH_SSET ETHTOOL_SSET
diff --git a/ethtool.c b/ethtool.c
index cb9e630..ea88c85 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -3989,6 +3989,8 @@ static int do_seee(struct cmd_context *ctx)
return 0;
}
+static int do_perqueue(struct cmd_context *ctx);
+
#ifndef TEST_ETHTOOL
int send_ioctl(struct cmd_context *ctx, void *cmd)
{
@@ -4146,6 +4148,8 @@ static const struct option {
" [ advertise %x ]\n"
" [ tx-lpi on|off ]\n"
" [ tx-timer %d ]\n"},
+ { "--set-perqueue-command", 1, do_perqueue, "Set per queue command",
+ " [queue_mask %x] SUB_COMMAND\n"},
{ "-h|--help", 0, show_usage, "Show this help" },
{ "--version", 0, do_version, "Show version number" },
{}
@@ -4197,6 +4201,96 @@ static int find_option(int argc, char **argp)
return -1;
}
+static int set_queue_mask(u64 *queue_mask, char *str)
+{
+ int len = strlen(str);
+ int index = BITS_TO_U64((len * 4));
+ char tmp[17];
+ char *end = str + len;
+ int i, num;
+
+ if (len > MAX_QUEUE)
+ return -EINVAL;
+
+ for (i = 0; i < index; i++) {
+ num = end - str;
+ if (num >= 16) {
+ end -= 16;
+ num = 16;
+ } else {
+ end = str;
+ }
+ strncpy(tmp, end, num);
+ tmp[num] = '\0';
+
+ queue_mask[i] = strtoull(tmp, NULL, 16);
+ }
+
+ return 0;
+}
+
+#define MAX(x, y) (x > y ? x : y)
+
+static int find_max_queue_num(struct cmd_context *ctx)
+{
+ struct ethtool_channels echannels;
+
+ echannels.cmd = ETHTOOL_GCHANNELS;
+ if (send_ioctl(ctx, &echannels))
+ return -1;
+
+ return MAX(MAX(echannels.rx_count, echannels.tx_count), echannels.combined_count);
+}
+
+static int do_perqueue(struct cmd_context *ctx)
+{
+ __u64 queue_mask[MAX_QUEUE_MASK] = {0};
+ __u64 mask;
+ int i, queue_num = 0;
+
+ if (ctx->argc == 0)
+ exit_bad_args();
+
+ /* All queues will be applied if no queue_mask set */
+ if (strncmp(*ctx->argp, "queue_mask", 10)) {
+ queue_num = find_max_queue_num(ctx);
+ if (queue_num < 0) {
+ perror("Cannot get queue number");
+ return -EFAULT;
+ }
+ for (i = 0; i < queue_num / 64; i++)
+ queue_mask[i] = ~0;
+ queue_mask[i] = (1ULL << (queue_num - i * 64)) - 1;
+ } else {
+ ctx->argc--;
+ ctx->argp++;
+ if (set_queue_mask(queue_mask, *ctx->argp)) {
+ perror("Invalid queue mask");
+ return -EINVAL;
+ }
+ ctx->argc--;
+ ctx->argp++;
+
+ /* Get the masked queue number */
+ for (i = 0; i < MAX_QUEUE_MASK; i++) {
+ mask = queue_mask[i];
+ while (mask > 0) {
+ if (mask & 0x1)
+ queue_num++;
+ mask = mask >> 1;
+ }
+ }
+ }
+
+ i = find_option(ctx->argc, ctx->argp);
+ if (i < 0)
+ exit_bad_args();
+
+ /* no sub_command support yet */
+
+ return 0;
+}
+
int main(int argc, char **argp)
{
int (*func)(struct cmd_context *);
diff --git a/internal.h b/internal.h
index b5ef646..6690d40 100644
--- a/internal.h
+++ b/internal.h
@@ -65,8 +65,10 @@ static inline u64 cpu_to_be64(u64 value)
#define BITS_PER_BYTE 8
#define BITS_PER_LONG (BITS_PER_BYTE * sizeof(long))
+#define BITS_PER_LONG_LONG (BITS_PER_BYTE * sizeof(unsigned long long))
#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_LONG)
+#define BITS_TO_U64(nr) DIV_ROUND_UP(nr, BITS_PER_LONG_LONG)
static inline void set_bit(unsigned int nr, unsigned long *addr)
{
--
1.7.11.7
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists