Signed-off-by: Ben Widawsky <ben at bwidawsk.net> --- tests/dpf_test | 8 +++ tools/Makefile.am | 3 +- tools/intel_l3_parity.c | 159 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 169 insertions(+), 1 deletion(-) create mode 100755 tests/dpf_test create mode 100644 tools/intel_l3_parity.c diff --git a/tests/dpf_test b/tests/dpf_test new file mode 100755 index 0000000..7d431ac --- /dev/null +++ b/tests/dpf_test @@ -0,0 +1,8 @@ +#!/bin/bash + +SOURCE_DIR="$( dirname "${BASH_SOURCE[0]}" )" +. $SOURCE_DIR/drm_lib.sh + +$SOURCE_DIR/../tools/intel_l3_parity -c 2>&1 +$SOURCE_DIR/../tools/intel_l3_parity 0,0,0 2>&1 +$SOURCE_DIR/../tools/intel_l3_parity 2>&1 diff --git a/tools/Makefile.am b/tools/Makefile.am index 2e4128b..d461f38 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -14,7 +14,8 @@ bin_PROGRAMS = \ intel_reg_snapshot \ intel_reg_write \ intel_reg_read \ - intel_forcewaked + intel_forcewaked \ + intel_l3_parity noinst_PROGRAMS = \ intel_dump_decode \ diff --git a/tools/intel_l3_parity.c b/tools/intel_l3_parity.c new file mode 100644 index 0000000..260c3d0 --- /dev/null +++ b/tools/intel_l3_parity.c @@ -0,0 +1,159 @@ +/* + * Copyright ? 2012 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Ben Widawsky <ben at bwidawsk.net> + * + */ + +#define _GNU_SOURCE +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include "intel_chipset.h" +#include "intel_gpu_tools.h" +#include "drmtest.h" + +#define NUM_BANKS 4 +#define NUM_SUBBANKS 8 +#define NUM_REGS (NUM_BANKS * NUM_SUBBANKS) + +struct __attribute__ ((__packed__)) l3_log_register { + uint32_t row0_enable : 1; + uint32_t rsvd2 : 4; + uint32_t row0 : 11; + uint32_t row1_enable : 1; + uint32_t rsvd1 : 4; + uint32_t row1 : 11; +} l3log[NUM_BANKS][NUM_SUBBANKS]; + +static void dumpit(void) +{ + int i, j; + + for (i = 0; i < NUM_BANKS; i++) { + for (j = 0; j < NUM_SUBBANKS; j++) { + struct l3_log_register *reg = &l3log[i][j]; + + if (reg->row0_enable) + printf("Row %d, Bank %d, Subbank %d is disabled\n", + reg->row0, i, j); + if (reg->row1_enable) + printf("Row %d, Bank %d, Subbank %d is disabled\n", + reg->row1, i, j); + } + } +} + +static int disable_rbs(int row, int bank, int sbank) +{ + struct l3_log_register *reg = &l3log[bank][sbank]; + + // can't map more than 2 rows + if (reg->row0_enable && reg->row1_enable) + return -1; + + // can't remap the same row twice + if ((reg->row0_enable && reg->row0 == row) || + (reg->row1_enable && reg->row1 == row)) { + return -1; + } + + if (reg->row0_enable) { + reg->row1 = row; + reg->row1_enable = 1; + } else { + reg->row0 = row; + reg->row0_enable = 1; + } + + return 0; +} + +static int do_parse(int argc, char *argv[]) +{ + int row, bank, sbank, i, ret; + + for (i = 1; i < argc; i++) { + ret = sscanf(argv[i], "%d,%d,%d", &row, &bank, &sbank); + if (ret != 3) + return i; + assert(disable_rbs(row, bank, sbank) == 0); + } + return 0; +} + +int main(int argc, char *argv[]) +{ + const int device = drm_get_card(0); + char *path; + unsigned int devid; + int drm_fd, fd, ret; + + drm_fd = drm_open_any(); + devid = intel_get_drm_devid(drm_fd); + + ret = asprintf(&path, "/sys/class/drm/card%d/l3_parity", device); + assert(ret != -1); + + fd = open(path, O_RDWR); + if (fd == -1 && IS_IVYBRIDGE(devid)) { + perror("Opening sysfs"); + exit(EXIT_FAILURE); + } else if (fd == -1) + exit(EXIT_SUCCESS); + + ret = read(fd, l3log, NUM_REGS * sizeof(uint32_t)); + if (ret == -1) { + perror("Reading sysfs"); + exit(EXIT_FAILURE); + } + + assert(lseek(fd, 0, SEEK_SET) == 0); + + if (argc == 1) { + dumpit(); + exit(EXIT_SUCCESS); + } else if (!strncmp("-c", argv[1], 2)) { + memset(l3log, 0, sizeof(l3log)); + } else { + ret = do_parse(argc, argv); + if (ret != 0) { + fprintf(stderr, "Malformed command line at %s\n", argv[ret]); + exit(EXIT_FAILURE); + } + } + + ret = write(fd, l3log, NUM_REGS * sizeof(uint32_t)); + if (ret == -1) { + perror("Writing sysfs"); + exit(EXIT_FAILURE); + } + + close(fd); + + exit(EXIT_SUCCESS); +} -- 1.7.10.2