Signed-off-by: Auke Kok <[EMAIL PROTECTED]>
---

 ethtool-copy.h |   23 +++++++++++++
 ethtool.8      |   23 +++++++++++++
 ethtool.c      |  103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 149 insertions(+), 0 deletions(-)

diff --git a/ethtool-copy.h b/ethtool-copy.h
index ab9d688..aefd580 100644
--- a/ethtool-copy.h
+++ b/ethtool-copy.h
@@ -196,6 +196,23 @@ struct ethtool_ringparam {
        __u32   tx_pending;
 };
 
+/* for configuring RX/TX queue count */
+struct ethtool_queueparam {
+       __u32   cmd;    /* ETHTOOL_{G,S}QUEUEPARAM */
+
+       /* Read only attributes.  These indicate the maximum number
+        * of RX/TX queues the driver will allow the user to set.
+        */
+       __u32   rx_max;
+       __u32   tx_max;
+
+       /* Values changeable by the user.  The valid values are
+        * in the range 1 to the "*_max" counterpart above.
+        */
+       __u32   rx;
+       __u32   tx;
+};
+
 /* for configuring link flow control parameters */
 struct ethtool_pauseparam {
        __u32   cmd;    /* ETHTOOL_{G,S}PAUSEPARAM */
@@ -295,6 +312,8 @@ int ethtool_op_set_lro(struct net_device *dev, u32 data);
  * set_coalesce: Set interrupt coalescing parameters
  * get_ringparam: Report ring sizes
  * set_ringparam: Set ring sizes
+ * get_queueparam: Report ring sizes
+ * set_queueparam: Set ring sizes
  * get_pauseparam: Report pause parameters
  * set_pauseparam: Set pause paramters
  * get_rx_csum: Report whether receive checksums are turned on or off
@@ -356,6 +375,8 @@ struct ethtool_ops {
        int     (*set_coalesce)(struct net_device *, struct ethtool_coalesce *);
        void    (*get_ringparam)(struct net_device *, struct ethtool_ringparam 
*);
        int     (*set_ringparam)(struct net_device *, struct ethtool_ringparam 
*);
+       void    (*get_queueparam)(struct net_device *, struct 
ethtool_queueparam *);
+       int     (*set_queueparam)(struct net_device *, struct 
ethtool_queueparam *);
        void    (*get_pauseparam)(struct net_device *, struct 
ethtool_pauseparam*);
        int     (*set_pauseparam)(struct net_device *, struct 
ethtool_pauseparam*);
        u32     (*get_rx_csum)(struct net_device *);
@@ -422,6 +443,8 @@ struct ethtool_ops {
 #define ETHTOOL_SGSO           0x00000024 /* Set GSO enable (ethtool_value) */
 #define ETHTOOL_GLRO           0x00000025 /* Get LRO enable (ethtool_value) */
 #define ETHTOOL_SLRO           0x00000026 /* Set LRO enable (ethtool_value) */
+#define ETHTOOL_GQUEUEPARAM    0x00000027 /* Get queue parameters */
+#define ETHTOOL_SQUEUEPARAM    0x00000028 /* Set queue parameters. */
 
 /* compatibility with older code */
 #define SPARC_ETH_GSET         ETHTOOL_GSET
diff --git a/ethtool.8 b/ethtool.8
index 89abf08..3f2e0c0 100644
--- a/ethtool.8
+++ b/ethtool.8
@@ -120,6 +120,17 @@ ethtool \- Display or change ethernet card settings
 .RB [ tx
 .IR N ]
 
+
+.B ethtool \-q|\-\-show\-queue
+.I ethX
+
+.B ethtool \-Q|\-\-set\-queue
+.I ethX
+.RB [ rx
+.IR N ]
+.RB [ tx
+.IR N ]
+
 .B ethtool \-i|\-\-driver
 .I ethX
 
@@ -243,6 +254,18 @@ Changes the number of ring entries for the Rx Jumbo ring.
 .BI tx \ N
 Changes the number of ring entries for the Tx ring.
 .TP
+.B \-q \-\-show\-queue
+Queries the specified ethernet device for rx/tx queue parameter information.
+.TP
+.B \-Q \-\-set\-queue
+Changes the rx/tx queue parameters of the specified ethernet device.
+.TP
+.BI rx \ N
+Changes the number of Rx queues.
+.TP
+.BI tx \ N
+Changes the number of Tx queues.
+.TP
 .B \-i \-\-driver
 Queries the specified ethernet device for associated driver information.
 .TP
diff --git a/ethtool.c b/ethtool.c
index 4c9844a..227349f 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -64,6 +64,8 @@ static int do_gpause(int fd, struct ifreq *ifr);
 static int do_spause(int fd, struct ifreq *ifr);
 static int do_gring(int fd, struct ifreq *ifr);
 static int do_sring(int fd, struct ifreq *ifr);
+static int do_gqueue(int fd, struct ifreq *ifr);
+static int do_squeue(int fd, struct ifreq *ifr);
 static int do_gcoalesce(int fd, struct ifreq *ifr);
 static int do_scoalesce(int fd, struct ifreq *ifr);
 static int do_goffload(int fd, struct ifreq *ifr);
@@ -87,6 +89,8 @@ static enum {
        MODE_SCOALESCE,
        MODE_GRING,
        MODE_SRING,
+       MODE_GQUEUE,
+       MODE_SQUEUE,
        MODE_GOFFLOAD,
        MODE_SOFFLOAD,
        MODE_GSTATS,
@@ -144,6 +148,10 @@ static struct option {
                "               [ rx-mini N ]\n"
                "               [ rx-jumbo N ]\n"
                "               [ tx N ]\n" },
+    { "-q", "--show-queue", MODE_GQUEUE, "Query RX/TX queue parameters" },
+    { "-Q", "--set-queue", MODE_SQUEUE, "Set RX/TX queue parameters",
+               "               [ rx N ]\n"
+               "               [ tx N ]\n" },
     { "-k", "--show-offload", MODE_GOFFLOAD, "Get protocol offload 
information" },
     { "-K", "--offload", MODE_SOFFLOAD, "Set protocol offload",
                "               [ rx on|off ]\n"
@@ -216,6 +224,11 @@ static int ring_rx_mini_wanted = -1;
 static int ring_rx_jumbo_wanted = -1;
 static int ring_tx_wanted = -1;
 
+static struct ethtool_queueparam equeue;
+static int gqueue_changed = 0;
+static int queue_rx = -1;
+static int queue_tx = -1;
+
 static struct ethtool_coalesce ecoal;
 static int gcoalesce_changed = 0;
 static int coal_stats_wanted = -1;
@@ -328,6 +341,11 @@ static struct cmdline_info cmdline_ring[] = {
        { "tx", CMDL_INT, &ring_tx_wanted, &ering.tx_pending },
 };
 
+static struct cmdline_info cmdline_queue[] = {
+       { "rx", CMDL_INT, &queue_rx, &equeue.rx},
+       { "tx", CMDL_INT, &queue_tx, &equeue.tx},
+};
+
 static struct cmdline_info cmdline_coalesce[] = {
        { "adaptive-rx", CMDL_BOOL, &coal_adaptive_rx_wanted, 
&ecoal.use_adaptive_rx_coalesce },
        { "adaptive-tx", CMDL_BOOL, &coal_adaptive_tx_wanted, 
&ecoal.use_adaptive_tx_coalesce },
@@ -430,6 +448,8 @@ static void parse_cmdline(int argc, char **argp)
                            (mode == MODE_SCOALESCE) ||
                            (mode == MODE_GRING) ||
                            (mode == MODE_SRING) ||
+                           (mode == MODE_GQUEUE) ||
+                           (mode == MODE_SQUEUE) ||
                            (mode == MODE_GOFFLOAD) ||
                            (mode == MODE_SOFFLOAD) ||
                            (mode == MODE_GSTATS) ||
@@ -496,6 +516,14 @@ static void parse_cmdline(int argc, char **argp)
                                i = argc;
                                break;
                        }
+                       if (mode == MODE_SQUEUE) {
+                               parse_generic_cmdline(argc, argp, i,
+                                       &gqueue_changed,
+                                       cmdline_ring,
+                                       ARRAY_SIZE(cmdline_queue));
+                               i = argc;
+                               break;
+                       }
                        if (mode == MODE_SCOALESCE) {
                                parse_generic_cmdline(argc, argp, i,
                                        &gcoalesce_changed,
@@ -1150,6 +1178,26 @@ static int dump_ring(void)
        return 0;
 }
 
+static int dump_queue(void)
+{
+       fprintf(stdout,
+               "Pre-set maximums:\n"
+               "RX:            %u\n"
+               "TX:            %u\n",
+               equeue.rx_max,
+               equeue.tx_max);
+
+       fprintf(stdout,
+               "Current hardware settings:\n"
+               "RX:            %u\n"
+               "TX:            %u\n",
+               equeue.rx,
+               equeue.tx);
+
+       fprintf(stdout, "\n");
+       return 0;
+}
+
 static int dump_coalesce(void)
 {
        fprintf(stdout, "Adaptive RX: %s  TX: %s\n",
@@ -1278,6 +1326,10 @@ static int doit(void)
                return do_gring(fd, &ifr);
        } else if (mode == MODE_SRING) {
                return do_sring(fd, &ifr);
+       } else if (mode == MODE_GQUEUE) {
+               return do_gqueue(fd, &ifr);
+       } else if (mode == MODE_SQUEUE) {
+               return do_squeue(fd, &ifr);
        } else if (mode == MODE_GOFFLOAD) {
                return do_goffload(fd, &ifr);
        } else if (mode == MODE_SOFFLOAD) {
@@ -1435,6 +1487,57 @@ static int do_gring(int fd, struct ifreq *ifr)
        return 0;
 }
 
+static int do_squeue(int fd, struct ifreq *ifr)
+{
+       int err, changed = 0;
+
+       equeue.cmd = ETHTOOL_GQUEUEPARAM;
+       ifr->ifr_data = (caddr_t)&equeue;
+       err = ioctl(fd, SIOCETHTOOL, ifr);
+       if (err) {
+               perror("Cannot get device queue settings");
+               return 76;
+       }
+
+       do_generic_set(cmdline_queue, ARRAY_SIZE(cmdline_queue), &changed);
+
+       if (!changed) {
+               fprintf(stderr, "no queue parameters changed, aborting\n");
+               return 80;
+       }
+
+       equeue.cmd = ETHTOOL_SQUEUEPARAM;
+       ifr->ifr_data = (caddr_t)&equeue;
+       err = ioctl(fd, SIOCETHTOOL, ifr);
+       if (err) {
+               perror("Cannot set device queue parameters");
+               return 81;
+       }
+
+       return 0;
+}
+
+static int do_gqueue(int fd, struct ifreq *ifr)
+{
+       int err;
+
+       fprintf(stdout, "Queue parameters for %s:\n", devname);
+
+       equeue.cmd = ETHTOOL_GQUEUEPARAM;
+       ifr->ifr_data = (caddr_t)&equeue;
+       err = ioctl(fd, SIOCETHTOOL, ifr);
+       if (err == 0) {
+               err = dump_queue();
+               if (err)
+                       return err;
+       } else {
+               perror("Cannot get device queue settings");
+               return 76;
+       }
+
+       return 0;
+}
+
 static int do_gcoalesce(int fd, struct ifreq *ifr)
 {
        int err;
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to