From: Kan Liang <kan.li...@intel.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.li...@intel.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 majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html