tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: ixg(4) performances



   Date: Tue, 26 Aug 2014 10:25:52 -0400
   From: christos%zoulas.com@localhost (Christos Zoulas)

   On Aug 26,  2:23pm, manu%netbsd.org@localhost (Emmanuel Dreyfus) wrote:
   -- Subject: Re: ixg(4) performances

   | I see <dev/pci/pciio.h>  has a PCI_IOC_CFGREAD / PCI_IOC_CFGWRITE ioctl,
   | does that means Linux's setpci can be easily reproduced?

   I would probably extend pcictl with cfgread and cfgwrite commands.

How about the attached patch?  I've been sitting on this for months.
Index: usr.sbin/pcictl/pcictl.8
===================================================================
RCS file: /cvsroot/src/usr.sbin/pcictl/pcictl.8,v
retrieving revision 1.10
diff -p -u -r1.10 pcictl.8
--- usr.sbin/pcictl/pcictl.8    25 Feb 2011 21:40:48 -0000      1.10
+++ usr.sbin/pcictl/pcictl.8    26 Aug 2014 15:38:55 -0000
@@ -33,7 +33,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd February 25, 2011
+.Dd June 12, 2014
 .Dt PCICTL 8
 .Os
 .Sh NAME
@@ -79,6 +79,31 @@ at the specified bus, device, and functi
 If the bus is not specified, it defaults to the bus number of the
 PCI bus specified on the command line.
 If the function is not specified, it defaults to 0.
+.Pp
+.Nm read
+.Op Fl b Ar bus
+.Fl d Ar device
+.Op Fl f Ar function
+.Ar reg
+.Pp
+Read the specified 32-bit aligned PCI configuration register and print
+it in hexadecimal to standard output.
+If the bus is not specified, it defaults to the bus number of the
+PCI bus specified on the command line.
+If the function is not specified, it defaults to 0.
+.Pp
+.Nm write
+.Op Fl b Ar bus
+.Fl d Ar device
+.Op Fl f Ar function
+.Ar reg
+.Ar value
+.Pp
+Write the specified value to the specified 32-bit aligned PCI
+configuration register.
+If the bus is not specified, it defaults to the bus number of the
+PCI bus specified on the command line.
+If the function is not specified, it defaults to 0.
 .Sh FILES
 .Pa /dev/pci*
 - PCI bus device nodes
Index: usr.sbin/pcictl/pcictl.c
===================================================================
RCS file: /cvsroot/src/usr.sbin/pcictl/pcictl.c,v
retrieving revision 1.18
diff -p -u -r1.18 pcictl.c
--- usr.sbin/pcictl/pcictl.c    30 Aug 2011 20:08:38 -0000      1.18
+++ usr.sbin/pcictl/pcictl.c    26 Aug 2014 15:38:55 -0000
@@ -76,6 +76,8 @@ static int    print_numbers = 0;
 
 static void    cmd_list(int, char *[]);
 static void    cmd_dump(int, char *[]);
+static void    cmd_read(int, char *[]);
+static void    cmd_write(int, char *[]);
 
 static const struct command commands[] = {
        { "list",
@@ -88,10 +90,21 @@ static const struct command commands[] =
          cmd_dump,
          O_RDONLY },
 
+       { "read",
+         "[-b bus] -d device [-f function] reg",
+         cmd_read,
+         O_RDONLY },
+
+       { "write",
+         "[-b bus] -d device [-f function] reg value",
+         cmd_write,
+         O_WRONLY },
+
        { 0, 0, 0, 0 },
 };
 
 static int     parse_bdf(const char *);
+static u_int   parse_reg(const char *);
 
 static void    scan_pci(int, int, int, void (*)(u_int, u_int, u_int));
 
@@ -230,6 +243,87 @@ cmd_dump(int argc, char *argv[])
        scan_pci(bus, dev, func, scan_pci_dump);
 }
 
+static void
+cmd_read(int argc, char *argv[])
+{
+       int bus, dev, func;
+       u_int reg;
+       pcireg_t value;
+       int ch;
+
+       bus = pci_businfo.busno;
+       func = 0;
+       dev = -1;
+
+       while ((ch = getopt(argc, argv, "b:d:f:")) != -1) {
+               switch (ch) {
+               case 'b':
+                       bus = parse_bdf(optarg);
+                       break;
+               case 'd':
+                       dev = parse_bdf(optarg);
+                       break;
+               case 'f':
+                       func = parse_bdf(optarg);
+                       break;
+               default:
+                       usage();
+               }
+       }
+       argv += optind;
+       argc -= optind;
+
+       if (argc != 1)
+               usage();
+       reg = parse_reg(argv[0]);
+       if (pcibus_conf_read(pcifd, bus, dev, func, reg, &value) == -1)
+               err(EXIT_FAILURE, "pcibus_conf_read"
+                   "(bus %d dev %d func %d reg %u)", bus, dev, func, reg);
+       if (printf("%08x\n", value) < 0)
+               err(EXIT_FAILURE, "printf");
+}
+
+static void
+cmd_write(int argc, char *argv[])
+{
+       int bus, dev, func;
+       u_int reg;
+       pcireg_t value;
+       int ch;
+
+       bus = pci_businfo.busno;
+       func = 0;
+       dev = -1;
+
+       while ((ch = getopt(argc, argv, "b:d:f:")) != -1) {
+               switch (ch) {
+               case 'b':
+                       bus = parse_bdf(optarg);
+                       break;
+               case 'd':
+                       dev = parse_bdf(optarg);
+                       break;
+               case 'f':
+                       func = parse_bdf(optarg);
+                       break;
+               default:
+                       usage();
+               }
+       }
+       argv += optind;
+       argc -= optind;
+
+       if (argc != 2)
+               usage();
+       reg = parse_reg(argv[0]);
+       __CTASSERT(sizeof(value) == sizeof(u_int));
+       value = parse_reg(argv[1]);
+       if (pcibus_conf_write(pcifd, bus, dev, func, reg, value) == -1)
+               err(EXIT_FAILURE, "pcibus_conf_write"
+                   "(bus %d dev %d func %d reg %u value 0x%x)",
+                   bus, dev, func, reg, value);
+}
+
 static int
 parse_bdf(const char *str)
 {
@@ -240,9 +334,32 @@ parse_bdf(const char *str)
            strcmp(str, "any") == 0)
                return (-1);
 
+       errno = 0;
        value = strtol(str, &end, 0);
-       if (*end != '\0') 
+       if ((str[0] == '\0') || (*end != '\0'))
+               errx(EXIT_FAILURE, "\"%s\" is not a number", str);
+       if ((errno == ERANGE) && ((value == LONG_MIN) || (value == LONG_MAX)))
+               errx(EXIT_FAILURE, "out of range: %s", str);
+       if ((value < INT_MIN) || (INT_MAX < value))
+               errx(EXIT_FAILURE, "out of range: %lu", value);
+
+       return value;
+}
+
+static u_int
+parse_reg(const char *str)
+{
+       unsigned long value;
+       char *end;
+
+       errno = 0;
+       value = strtoul(str, &end, 0);
+       if (*end != '\0')
                errx(EXIT_FAILURE, "\"%s\" is not a number", str);
+       if ((errno == ERANGE) && (value == ULONG_MAX))
+               errx(EXIT_FAILURE, "out of range: %s", str);
+       if (UINT_MAX < value)
+               errx(EXIT_FAILURE, "out of range: %lu", value);
 
        return value;
 }


Home | Main Index | Thread Index | Old Index