IO-TLB monitoring patch & tool v0.2
Hello,
Here is a corrected version of the kernel patch & tool for monitoring IO-TLB usage. It works correctly now, and is even fun to watch!
It can display summary information or show a IO-TLB "map" in two different modes.
Even if the aic7xxx problems may be history soon, this tool may still be useful with other controllers/drivers.
Cheers
Martin
Signature · 1,155 lines
Martin Wilck <[email protected]> FSC EP PS DS1, Paderborn Tel. +49 5251 8 15113 #!/bin/sh # This is a shell archive (produced by GNU sharutils 4.2.1). # To extract the files from this archive, save it to some FILE, remove # everything before the `!/bin/sh' line above, then type `sh FILE'. # # Made on 2001-06-25 21:18 CEST by <[email protected]>. # Source directory was `/home/martin'. # # Existing files will *not* be overwritten unless `-c' is specified. # # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 358 -rw-rw-r-- iotlb-mon-0.2/Makefile # 1347 -rw-rw-r-- iotlb-mon-0.2/README # 12720 -rw-rw-r-- iotlb-mon-0.2/iotlb-mon.c # 10022 -rw-rw-r-- iotlb-mon-0.2/swiotlb_proc.patch # save_IFS="${IFS}" IFS="${IFS}:" gettext_dirúILED locale_dirúILED first_param="$1" for dir in $PATH do if test "$gettext_dir" = FAILED && test -f $dir/gettext \ && ($dir/gettext --version >/dev/null 2>&1) then set `$dir/gettext --version 2>&1` if test "$3" = GNU then gettext_dir=$dir fi fi if test "$locale_dir" = FAILED && test -f $dir/shar \ && ($dir/shar --print-text-domain-dir >/dev/null 2>&1) then locale_dir=`$dir/shar --print-text-domain-dir` fi done IFS="$save_IFS" if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED then echoìho else TEXTDOMAINDIR=$locale_dir export TEXTDOMAINDIR TEXTDOMAIN=sharutils export TEXTDOMAIN echo="$gettext_dir/gettext -s" fi if touch -am -t 200112312359.59 $$.touch >/dev/null 2>&1 && test ! -f 200112312359.59 -a -f $$.touch; then shar_touch='touch -am -t $1$2$3$4$5$6.$7 "$8"' elif touch -am 123123592001.59 $$.touch >/dev/null 2>&1 && test ! -f 123123592001.59 -a ! -f 123123592001.5 -a -f $$.touch; then shar_touch='touch -am $3$4$5$6$1$2.$7 "$8"' elif touch -am 1231235901 $$.touch >/dev/null 2>&1 && test ! -f 1231235901 -a -f $$.touch; then shar_touch='touch -am $3$4$5$6$2 "$8"' else shar_touch=: echo $echo 'WARNING: not restoring timestamps. Consider getting and' $echo "installing GNU \`touch', distributed in GNU File Utilities..." echo fi rm -f 200112312359.59 123123592001.59 123123592001.5 1231235901 $$.touch # if mkdir _sh04019; then $echo 'x -' 'creating lock directory' else $echo 'failed to create lock directory' exit 1 fi # ======= iotlb-mon-0.2/Makefile ======= if test ! -d 'iotlb-mon-0.2'; then $echo 'x -' 'creating directory' 'iotlb-mon-0.2' mkdir 'iotlb-mon-0.2' fi if test -f 'iotlb-mon-0.2/Makefile' && test "$first_param" != -c; then $echo 'x -' SKIPPING 'iotlb-mon-0.2/Makefile' '(file already exists)' else $echo 'x -' extracting 'iotlb-mon-0.2/Makefile' '(text)' sed 's/^X//' << 'SHAR_EOF' > 'iotlb-mon-0.2/Makefile' && CFLAGS = -O2 -Wall LDFLAGS = -s PREFIX = /usr/local X OBJ = iotlb-mon.o LIBS = -lncurses EXE = iotlb-mon X sbindir = $(PREFIX)/sbin X default: $(EXE) X $(EXE): $(OBJ) X $(CC) $(CFLAGS) $(LDFLAGS) -o $(EXE) $(OBJ) $(LIBS) X install: $(EXE) X install -d $(sbindir) X install -m 755 $(EXE) $(sbindir) X clean: X rm -f $(EXE) $(OBJ) core X distclean: clean X rm -f *~ '#'* SHAR_EOF (set 20 01 06 13 23 08 50 'iotlb-mon-0.2/Makefile'; eval "$shar_touch") && chmod 0664 'iotlb-mon-0.2/Makefile' || $echo 'restore of' 'iotlb-mon-0.2/Makefile' 'failed' if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then md5sum -c << SHAR_EOF >/dev/null 2>&1 \ || $echo 'iotlb-mon-0.2/Makefile:' 'MD5 check failed' 54357a32a53e5ade6918ff7b409a31a0 iotlb-mon-0.2/Makefile SHAR_EOF else shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'iotlb-mon-0.2/Makefile'`" test 358 -eq "$shar_count" || $echo 'iotlb-mon-0.2/Makefile:' 'original size' '358,' 'current size' "$shar_count!" fi fi # ======= iotlb-mon-0.2/README ======= if test -f 'iotlb-mon-0.2/README' && test "$first_param" != -c; then $echo 'x -' SKIPPING 'iotlb-mon-0.2/README' '(file already exists)' else $echo 'x -' extracting 'iotlb-mon-0.2/README' '(text)' sed 's/^X//' << 'SHAR_EOF' > 'iotlb-mon-0.2/README' && X X iotlb-mon.c - utility to monitor software IO-TLB usage on X IA-64 Linux systems. X X (c) 2001 Martin Wilck <[email protected]> X X Copying and modification granted under the terms of the X GNU General Public License (GPL). X X ************************************************************* X This program comes with NO WARRANTY, for details see the GPL. X ************************************************************* X X Version 0.2, 25.06.2001 X X Installing the kernel patch X =============X X Patch the 2.4.5 kernel + IA64 patch (30.05.2001) X with the patch file (swiotlb_proc.patch) from this directory. X Activate building the module in the "General setup" section X (/proc/swiotlb support). Build & install kernel and modules as usual. X The module built is called "swiotlb_proc.o". X X Compiling iotlb-mon X =========X X Requires the ncurses library and header files. X X make; make PREFIX=[my_install_root] install X X Default for PREFIX is /usr/local. X The program installs to $(PREFIX)/sbin. X X Using iotlb-mon X =======X X usage: ioltb-mon X Hit '?' in running program to display keyboard controls. X X BUGS: X ----- X X Probably many. X Sometimes read () yields unreasonable sizes. X X Please report bugs and suggest improvements to X <[email protected]>. X SHAR_EOF (set 20 01 06 25 21 17 59 'iotlb-mon-0.2/README'; eval "$shar_touch") && chmod 0664 'iotlb-mon-0.2/README' || $echo 'restore of' 'iotlb-mon-0.2/README' 'failed' if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then md5sum -c << SHAR_EOF >/dev/null 2>&1 \ || $echo 'iotlb-mon-0.2/README:' 'MD5 check failed' c37d1441828e166ac808b1ae2410ccea iotlb-mon-0.2/README SHAR_EOF else shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'iotlb-mon-0.2/README'`" test 1347 -eq "$shar_count" || $echo 'iotlb-mon-0.2/README:' 'original size' '1347,' 'current size' "$shar_count!" fi fi # ======= iotlb-mon-0.2/iotlb-mon.c ======= if test -f 'iotlb-mon-0.2/iotlb-mon.c' && test "$first_param" != -c; then $echo 'x -' SKIPPING 'iotlb-mon-0.2/iotlb-mon.c' '(file already exists)' else $echo 'x -' extracting 'iotlb-mon-0.2/iotlb-mon.c' '(text)' sed 's/^X//' << 'SHAR_EOF' > 'iotlb-mon-0.2/iotlb-mon.c' && /* X X iotlb-mon.c - utility to monitor software IO-TLB usage on X IA-64 Linux systems. X (c) 2001 Martin Wilck <[email protected]> X */ X #include <fcntl.h> #include <unistd.h> #include <sys/types.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <signal.h> #include <curses.h> #include <sys/time.h> X #define N_INFO_FIELDS 8 #define PWIN_BORDER 1 #define INFO_X PWIN_BORDER #define INFO_Y (PWIN_BORDER) #define PWIN_HEIGHT (N_INFO_FIELDS+INFO_Y+PWIN_BORDER) #define INFO_SPC 2 #define INFO_FLEN 18 #define INFO_UFMT "%18u" #define INFO_PFMT "%18p" #define PWIN_X 2 #define PWIN_Y 2 #define MIN_INTERVAL 1 #define MAX_INTERVAL 10 #define IWIN_HEIGHT (LINES - 1) #define INDEX_STEP 1024 X typedef enum { X QUIT = 0, X PARAMS, X LIST, X GROUP, X HELP } run_t; X struct iotlb_info_struct { X unsigned long n_slots; X unsigned int index; X unsigned int used_buffers; X unsigned int used_slots; X unsigned int max_used_buffers; X unsigned int max_used_slots; X void *start; X void *end; }; X static const char *params_name = "/proc/swiotlb/params"; static const char *list_name = "/proc/swiotlb/list"; static const char *info_desc [N_INFO_FIELDS] = { X "Allocated", X "Index", X "Used buffers", X "Max used buffers", X "Used slots", X "Max used slots", X "Start address", X "End address" }; X static char *help_msg = "Hit 'h' or '?' for help"; static char *help_exit_msg = "Hit 'i', 'd', or 'c' to leave help"; static char *follow_off_msg = "Follow mode OFF"; static char *follow_on_msg = "Follow mode ON"; static char *current_msg = NULL; X static unsigned int first_index = 0; static bool follow_index = FALSE; static int iotlb_fd, list_fd; static int interval = 5; static WINDOW *mainwin, *pwin, *cwin, *iwin; volatile sig_atomic_t alarm_received = 0; X void cleanup () { X endwin (); X close (iotlb_fd); X close (list_fd); } X static int info_len (int force) { X static int maxl = 0; X int i; X X if (maxl && !force) X return maxl; X X maxl = 0; X for (i = 0; i < N_INFO_FIELDS; i++) { X int l = strlen (info_desc[i]); X if (l > maxl) X maxl = l; X }; X maxl++; X return maxl; } X void refresh_cwin (void) { X werase (cwin); X mvwprintw (cwin, 0, 0, current_msg); X mvwprintw (cwin, 0, COLS - 30, "Timer interval (1/10 s): %3d", interval); X wrefresh (cwin); } X static void create_windows (void) { X int width = info_len(0) + INFO_SPC + INFO_FLEN + 2*PWIN_BORDER; X X pwin = newwin (PWIN_HEIGHT, X width, X PWIN_Y, X (COLS - width) >> 1); X cwin = newwin (1, 0, LINES - 1, 0); X iwin = newwin (IWIN_HEIGHT, 0, 0, 0); X X if (!pwin || !cwin || !iwin) { X cleanup (); X fprintf (stderr, "Error creating windows"); X exit (1); X }; X box (pwin, 0, 0); X refresh_cwin (); } X static int print_info_desc (int force) { X X int maxl = info_len (force), i; X mvwprintw (pwin, 0, INFO_X, X "Software IO-TLB status"); X for (i = 0; i < N_INFO_FIELDS; i++) { X mvwprintw (pwin, INFO_Y + i, INFO_X, X "%s", info_desc[i]); X mvwaddch (pwin, INFO_Y + i, INFO_X + maxl, ':'); X }; X X return maxl; } X static int read_info (struct iotlb_info_struct *inf) { int nread; X int st; X X st = lseek (iotlb_fd, 0, SEEK_SET); X X nread = read (iotlb_fd, inf, sizeof (struct iotlb_info_struct)); X if (nread != sizeof (struct iotlb_info_struct)) { X cleanup (); X fprintf (stderr, "error in read () on %s\n", X params_name); X exit (1); X }; X X return nread; } X static void print_info (void) { X struct iotlb_info_struct info; X int nread, col; X X nread = read_info (&info); X col = print_info_desc (0) + INFO_X + INFO_SPC; X X mvwprintw (pwin, INFO_Y + 0, col, INFO_UFMT, info.n_slots); X mvwprintw (pwin, INFO_Y + 1, col, INFO_UFMT, info.index); X mvwprintw (pwin, INFO_Y + 2, col, INFO_UFMT, info.used_buffers); X mvwprintw (pwin, INFO_Y + 3, col, INFO_UFMT, info.max_used_buffers); X mvwprintw (pwin, INFO_Y + 4, col, INFO_UFMT, info.used_slots); X mvwprintw (pwin, INFO_Y + 5, col, INFO_UFMT, info.max_used_slots); X mvwprintw (pwin, INFO_Y + 6, col, INFO_PFMT, info.start); X mvwprintw (pwin, INFO_Y + 7, col, INFO_PFMT, info.end); X wrefresh (pwin); } X static int read_list (unsigned int **lst, struct iotlb_info_struct *info) { X static int size = 0; X static unsigned int *list = NULL; X int nread, st, n, i; X char *pos; X X nread = read_info (info); X if (!list) { X size = info->n_slots; X if (size > 0) { X list = malloc (size * sizeof (unsigned int)); X }; X if (!list) { X cleanup (); X fprintf (stderr, X "Error in malloc ()\n"); X exit (1); X }; X for (i = 0; i < size; i++) X list[i] = 1; X }; X X st = lseek (list_fd, 0, SEEK_SET); X X pos = (char*) list; X n = size * sizeof (unsigned int); X do { X nread = read (list_fd, pos, n); X pos += nread; X n -= nread; X } while (0); /* (nread > 0); */ X X if (nread < 0) { X cleanup (); X fprintf (stderr, "error in read () on %s: %d\n", X list_name, nread); X exit (1); X }; X X *lst = list; X return size - n; } X static chtype make_ch (unsigned int v) { X chtype c; X if (v < 10u) X c = '0' + v; X else if (v < 36u) X c = 'a' + v - 10; X else if (v < 62u) X c = 'A' + v - 36; X else X c = '-'; X return c; } X static chtype make_group_ch (unsigned int *slot, const unsigned int *highest) { X chtype free = 0; X X for (; slot < highest; slot++) X if (*slot) X free++; X if (free = 16) X free = '*'; X else if (free <= 9) X free += '0'; X else X free += 'A' - 10; X return free; } X static void print_list_group (void) { X unsigned int *list, *index, *curr, *next, *last; X int sz, mx; X struct iotlb_info_struct info; X X sz = read_list (&list, &info); X index = list + info.index; X X mx = (COLS * IWIN_HEIGHT) << 4; X X if (mx >= sz) X first_index = 0; X X if (first_index >= sz) { X first_index = (sz - 1) & ~(INDEX_STEP - 1); X }; X X if (follow_index && X (list + first_index > index || index - (list + first_index) > mx)) { X first_index = (index - list) & ~(INDEX_STEP - 1); X }; X X last = list + first_index + mx; X if (last > list + sz) X last = list + sz; X X werase (iwin); X mvwprintw (iwin, 0, 0, "Condensed map of slot %8u - %8u. " X "Current slot index: %u, total used slots: %u", X first_index, last - list, info.index, info.used_slots); X X wmove (iwin, 1, 0); X for (curr = list + first_index; curr < last; curr = next) { X next = curr + 16; X if (next > last) X next = last; X if (curr <= index && index < next) { X wattron (iwin, A_REVERSE); X waddch (iwin, make_group_ch (curr, next)); X wattroff (iwin, A_REVERSE); X } else X waddch (iwin, make_group_ch (curr, next)); X }; X wrefresh (iwin); } X static void print_list (void) { X unsigned int *list, index; X int sz, mx, i, last; X struct iotlb_info_struct info; X X sz = read_list (&list, &info); X index = info.index; X mx = COLS * IWIN_HEIGHT; X X if (mx >= sz) X first_index = 0; X X if (first_index >= sz) { X first_index = (sz - 1) & ~(INDEX_STEP - 1); X }; X X if (follow_index && X (first_index > index || index - first_index > mx)) { X first_index = index & ~(INDEX_STEP - 1); X }; X X last = first_index + mx; X if (last > sz) X last = sz; X X werase (iwin); X mvwprintw (iwin, 0, 0, "Map of slot %8u - %8u. " X "Current slot index: %u, total used slots: %u", X first_index, last, index, info.used_slots); X X wmove (iwin, 1, 0); X for (i = first_index; i < last; ++i) { X if (i = index) { X wattron (iwin, A_REVERSE); X waddch (iwin, make_ch (list[i])); X wattroff (iwin, A_REVERSE); X } else if (i % 2048 = 0) { X wattron (iwin, A_REVERSE); X waddch (iwin, make_ch (list[i])); X wattroff (iwin, A_REVERSE); X } else X waddch (iwin, make_ch (list[i])); X }; X wrefresh (iwin); } X void alrm_handler (int sig) { X alarm_received = 1; } X int start_timer (long int decisec) { X static const struct itimerval itv0 = { X { 0, 0}, { 0, 0} X }; X struct itimerval itv; X int st; X long int sec = decisec / 10; X long int usec = 100000 * (decisec % 10); X struct sigaction act; X X act.sa_handler = alrm_handler; X sigemptyset (&act.sa_mask); X sigaction (SIGALRM, &act, NULL); X X itv.it_interval.tv_sec = sec; X itv.it_interval.tv_usec = usec; X itv.it_value.tv_sec = sec; X itv.it_value.tv_usec = usec; X X setitimer (ITIMER_REAL, &itv0, NULL); X st = setitimer (ITIMER_REAL, &itv, NULL); X X return st; } X #define HELP_TAB 8 X static void help (void) { X int line = 0; X werase (iwin); X X wattron (iwin, A_UNDERLINE); X mvwprintw (iwin, line, 0, "iotlb-mon - Monitor the state of the IO-TLB buffers"); X wattroff (iwin, A_UNDERLINE); X X line ++; X mvwprintw (iwin, line, 0, "(c) 2001 Martin Wilck <[email protected]>"); X X line += 2; X wattron (iwin, A_UNDERLINE); X mvwprintw (iwin, line, 0, "Keyboard controls:"); X wattroff (iwin, A_UNDERLINE); X X mvwprintw (iwin, ++line, 0, "h or ?"); X mvwprintw (iwin, line, HELP_TAB, "Show this help"); X mvwprintw (iwin, ++line, 0, "q or x"); X mvwprintw (iwin, line, HELP_TAB, "Exit utility"); X X mvwprintw (iwin, ++line, 0, "+,-"); X mvwprintw (iwin, line, HELP_TAB, "Increase / decrease update interval by 1/10 sec"); X X mvwprintw (iwin, ++line, 0, "i"); X wattron (iwin, A_UNDERLINE); X mvwprintw (iwin, line, HELP_TAB, "Info mode: show IO-TLB usage summary"); X wattroff (iwin, A_UNDERLINE); X X mvwprintw (iwin, ++line, 0, "c"); X wattron (iwin, A_UNDERLINE); X mvwprintw (iwin, line, HELP_TAB, "Condensed mode: show condensed slot usage map"); X wattroff (iwin, A_UNDERLINE); X mvwprintw (iwin, ++line, HELP_TAB, "Each character represents 16 IO-TLB slots"); X mvwprintw (iwin, ++line, HELP_TAB, "Hex digit 0-F: Number of free slots in group"); X mvwprintw (iwin, ++line, HELP_TAB, "* : all slots in group are free"); X X mvwprintw (iwin, ++line, 0, "d"); X wattron (iwin, A_UNDERLINE); X mvwprintw (iwin, line, HELP_TAB, "Detailed mode: show detailed slot usage map"); X wattroff (iwin, A_UNDERLINE); X mvwprintw (iwin, ++line, HELP_TAB, "Each character represents a single IO-TLB slot"); X mvwprintw (iwin, ++line, HELP_TAB, "0 : slot occupied"); X mvwprintw (iwin, ++line, HELP_TAB, "1-9, a-z, A-Z: number of free slots (including current)"); X mvwprintw (iwin, ++line, HELP_TAB, " after current position"); X mvwprintw (iwin, ++line, HELP_TAB, "- : >= 61 slots starting from current are free"); X X mvwprintw (iwin, ++line, 0, "f"); X mvwprintw (iwin, line, HELP_TAB, "Toggle Follow mode: Page follows slot index " X "(detailed / condensed mode)"); X mvwprintw (iwin, ++line, 0, "p,n"); X mvwprintw (iwin, line, HELP_TAB, "Previous / next page (detailed and condensed mode)"); X mvwprintw (iwin, ++line, 0, "<,>"); X mvwprintw (iwin, line, HELP_TAB, "First / last page (detailed and condensed mode)"); X X wrefresh (iwin); X X current_msg = help_exit_msg; X refresh_cwin (); } X run_t handle_input (run_t run) { X chtype ch; X ch = wgetch(cwin); X if (ch != ERR) { X switch (ch) { X case '+': X if (interval < MAX_INTERVAL) { X interval++; X start_timer (interval); X }; X break; X case '-': X if (interval > MIN_INTERVAL) { X interval--; X start_timer (interval); X }; X break; X case 'h': X case '?': X run = HELP; X werase (pwin); X wrefresh (pwin); X help (); X break; X case 'i': X run = PARAMS; X werase (iwin); X wrefresh (iwin); X box (pwin, 0, 0); X current_msg = help_msg; X break; X case 'd': X case 'l': X run = LIST; X werase (pwin); X wrefresh (pwin); X current_msg = help_msg; X break; X case 'c': X case 'g': X run = GROUP; X werase (pwin); X wrefresh (pwin); X current_msg = help_msg; X break; X case 'q': X case 'x': X run = QUIT; X break; X case 'f': X follow_index = ~follow_index & 1; X if (follow_index) X current_msg = follow_on_msg; X else X current_msg = follow_off_msg; X break; X case '<': X first_index = 0; X break; X case '>': X first_index = 1 << 24; X break; X case 'n': X first_index += INDEX_STEP; X break; X case 'p': X first_index -= INDEX_STEP; X break; X default: X break; X }; X refresh_cwin (); X }; X X return run; } X int main (int argc, char **argv) { X sigset_t alrm_mask; X run_t run = PARAMS; X X iotlb_fd = open (params_name, O_RDONLY, 0); X list_fd = open (list_name, O_RDONLY, 0); X if (iotlb_fd < 0 || list_fd < 0) { X perror ("open"); X fprintf (stderr, "ERROR: Could not open /proc/swiotlb.\n" X " Is the swiotlb_proc module loaded ?\n"); X exit (1); X }; X X current_msg = help_msg; X mainwin = initscr (); X cbreak (); X noecho (); X X create_windows (); X X sigemptyset (&alrm_mask); X sigaddset (&alrm_mask, SIGALRM); X X start_timer (interval); X X while (run != QUIT) { X run = handle_input (run); X sigprocmask (SIG_BLOCK, &alrm_mask, NULL); X if (alarm_received) { X alarm_received = 0; X switch (run) { X case PARAMS: X print_info (); X break; X case LIST: X print_list (); X break; X case GROUP: X print_list_group (); X break; X default: X break; X }; X }; X sigprocmask (SIG_UNBLOCK, &alrm_mask, NULL); X }; X X cleanup (); X return 0; } SHAR_EOF (set 20 01 06 25 21 13 10 'iotlb-mon-0.2/iotlb-mon.c'; eval "$shar_touch") && chmod 0664 'iotlb-mon-0.2/iotlb-mon.c' || $echo 'restore of' 'iotlb-mon-0.2/iotlb-mon.c' 'failed' if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then md5sum -c << SHAR_EOF >/dev/null 2>&1 \ || $echo 'iotlb-mon-0.2/iotlb-mon.c:' 'MD5 check failed' 8efeb5b0783014a807e2095824095158 iotlb-mon-0.2/iotlb-mon.c SHAR_EOF else shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'iotlb-mon-0.2/iotlb-mon.c'`" test 12720 -eq "$shar_count" || $echo 'iotlb-mon-0.2/iotlb-mon.c:' 'original size' '12720,' 'current size' "$shar_count!" fi fi # ======= iotlb-mon-0.2/swiotlb_proc.patch ======= if test -f 'iotlb-mon-0.2/swiotlb_proc.patch' && test "$first_param" != -c; then $echo 'x -' SKIPPING 'iotlb-mon-0.2/swiotlb_proc.patch' '(file already exists)' else $echo 'x -' extracting 'iotlb-mon-0.2/swiotlb_proc.patch' '(text)' sed 's/^X//' << 'SHAR_EOF' > 'iotlb-mon-0.2/swiotlb_proc.patch' && diff -ruN linux-2.4.5/Documentation/Configure.help linux-2.4.5mw/Documentation/Configure.help --- linux-2.4.5/Documentation/Configure.help Mon Jun 25 14:45:01 2001 +++ linux-2.4.5mw/Documentation/Configure.help Mon Jun 25 21:02:47 2001 @@ -17776,6 +17776,21 @@ X To use this option, you have to check that the "/proc file system X support" (CONFIG_PROC_FS) is enabled, too. X +/proc/swiotlb support +CONFIG_PROCFS_SWIOTLB + If you say Y here, you will find information on the software + IO-TLB usage in your machine in /proc/swiotlb. + + IO-TLBs (Translation Lookaside Buffers) are needed if PCI devices + unable to do 64-bit addressing are used in machines with large RAM. + This is mainly useful for debugging purposes on machines with + >= 4GB RAM. + + To use this option, you have to check that the "/proc file system + support" (CONFIG_PROC_FS) is enabled, too. + + If unsure, say N. + X # X # A couple of things I keep forgetting: X # capitalize: AppleTalk, Ethernet, DOS, DMA, FAT, FTP, Internet, diff -ruN linux-2.4.5/arch/ia64/config.in linux-2.4.5mw/arch/ia64/config.in --- linux-2.4.5/arch/ia64/config.in Mon Jun 25 14:45:01 2001 +++ linux-2.4.5mw/arch/ia64/config.in Mon Jun 25 21:02:47 2001 @@ -111,6 +111,7 @@ X bool 'Performance monitor support' CONFIG_PERFMON X tristate '/proc/pal support' CONFIG_IA64_PALINFO X tristate '/proc/efi/vars support' CONFIG_EFI_VARS +tristate '/proc/swiotlb support' CONFIG_PROCFS_SWIOTLB X X bool 'Networking support' CONFIG_NET X bool 'System V IPC' CONFIG_SYSVIPC diff -ruN linux-2.4.5/arch/ia64/kernel/Makefile linux-2.4.5mw/arch/ia64/kernel/Makefile --- linux-2.4.5/arch/ia64/kernel/Makefile Mon Jun 25 14:45:01 2001 +++ linux-2.4.5mw/arch/ia64/kernel/Makefile Mon Jun 25 21:02:47 2001 @@ -20,6 +20,7 @@ X obj-$(CONFIG_IA64_DIG) += iosapic.o X obj-$(CONFIG_IA64_PALINFO) += palinfo.o X obj-$(CONFIG_EFI_VARS) += efivars.o +obj-$(CONFIG_PROCFS_SWIOTLB) += swiotlb_proc.o X obj-$(CONFIG_PCI) += pci.o X obj-$(CONFIG_SMP) += smp.o smpboot.o X obj-$(CONFIG_IA64_MCA) += mca.o mca_asm.o diff -ruN linux-2.4.5/arch/ia64/kernel/swiotlb_proc.c linux-2.4.5mw/arch/ia64/kernel/swiotlb_proc.c --- linux-2.4.5/arch/ia64/kernel/swiotlb_proc.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.5mw/arch/ia64/kernel/swiotlb_proc.c Mon Jun 25 18:44:47 2001 @@ -0,0 +1,176 @@ +#include <linux/module.h> +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/kernel.h> +#include <linux/malloc.h> +#include <linux/proc_fs.h> + +MODULE_AUTHOR("Martin Wilck <[email protected]>"); +MODULE_DESCRIPTION("/proc interface for software IO/TLB status"); + +struct iotlb_info_struct { + unsigned long n_slots; + unsigned int index; + unsigned int used_buffers; + unsigned int used_slots; + unsigned int max_used_buffers; + unsigned int max_used_slots; + void *start; + void *end; +}; + +/* Variables exported from arch/ia64/lib/swiotlb.c */ +extern char *io_tlb_start, *io_tlb_end; +extern unsigned long io_tlb_nslabs; +extern unsigned int *io_tlb_list; +extern unsigned int io_tlb_index; +extern unsigned int io_tlb_used_buffers; +extern unsigned int io_tlb_used_slots; +extern unsigned int io_tlb_max_used_buffers; +extern unsigned int io_tlb_max_used_slots; + +static struct proc_dir_entry *swiotlb_proc_dir; +static struct proc_dir_entry *proc_iotlb_list; +static struct proc_dir_entry *proc_iotlb_params; +static struct proc_dir_entry *proc_iotlb_parameters; + +static char *swiotlb_outbuf = NULL; + +static int +read_iotlb_list(char *page, char **start, off_t offset, int count, int *eof, void *data) +{ + int nbytes = io_tlb_nslabs * sizeof (int); + int kbytes = count + offset; + char *buf; + int cnt; + + MOD_INC_USE_COUNT; + if (nbytes > PAGE_SIZE) { + if (!swiotlb_outbuf) { + swiotlb_outbuf = kmalloc (io_tlb_nslabs * sizeof (int), GFP_KERNEL); + if (!swiotlb_outbuf) { + cnt = -ENOMEM; + goto exit; + }; + }; + *start = buf = swiotlb_outbuf + offset; + } else { + buf = page + offset; + }; + + /* copy only if offset = 0 for max consistency */ + if (!offset) + memcpy (buf, (char*) io_tlb_list, nbytes); + + if (kbytes < nbytes) + cnt = count; + else { + cnt = nbytes - offset; + if (cnt < 0) + cnt = 0; + *eof = 1; + }; + + exit: + MOD_DEC_USE_COUNT; + return cnt; + +} + +static int +read_iotlb_params(char *page, char **start, off_t offset, int count, int *eof, void *data) +{ + struct iotlb_info_struct *iotlb_params + (struct iotlb_info_struct*) page; + const int nbytes = sizeof (struct iotlb_info_struct); + int res; + + MOD_INC_USE_COUNT; + + iotlb_params->n_slots = io_tlb_nslabs; + iotlb_params->index = io_tlb_index; + iotlb_params->used_buffers = io_tlb_used_buffers; + iotlb_params->used_slots = io_tlb_used_slots; + iotlb_params->max_used_buffers = io_tlb_max_used_buffers; + iotlb_params->max_used_slots = io_tlb_max_used_slots; + iotlb_params->start = io_tlb_start; + iotlb_params->end = io_tlb_end; + + if (offset + count >= nbytes) { + *eof = 1; + res = (nbytes - offset < 0 ? 0 : nbytes - offset); + } else { + res = count; + }; + + MOD_DEC_USE_COUNT; + return res; +} + +static int +read_iotlb_parameters(char *page, char **start, off_t offset, int count, int *eof, void *data) +{ + int len, res; + MOD_INC_USE_COUNT; + len = sprintf (page, + "Slots allocated : %8ld\n" + "Current Index : %8d\n" + "Buffers used : %8d\n" + "Slots used : %8d\n" + "Max Buffers used : %8d\n" + "Max Slots used : %8d\n" + "Start address : 0x%p\n" + "End address : 0x%p\n", + io_tlb_nslabs, + io_tlb_index, + io_tlb_used_buffers, + io_tlb_used_slots, + io_tlb_max_used_buffers, + io_tlb_max_used_slots, + (void*) io_tlb_start, + (void*) io_tlb_end); + if (offset + count >= len) { + *eof = 1; + len -= offset; + res = (len < 0 ? 0 : len); + } else + res = count; + MOD_DEC_USE_COUNT; + return res; +} + +static int __init +swiotlb_init_proc (void) +{ + printk (KERN_INFO "Loading /proc/swiotlb support\n"); + + swiotlb_proc_dir = proc_mkdir ("swiotlb", NULL); + proc_iotlb_list + create_proc_entry ("list", 0444, swiotlb_proc_dir); + proc_iotlb_params + create_proc_entry ("params", 0444, swiotlb_proc_dir); + proc_iotlb_parameters + create_proc_entry ("parameters", 0444, swiotlb_proc_dir); + + proc_iotlb_list->read_proc = read_iotlb_list; + proc_iotlb_params->read_proc = read_iotlb_params; + proc_iotlb_parameters->read_proc = read_iotlb_parameters; + + return 0; +} + + +static void __exit +swiotlb_exit_proc (void) +{ + printk (KERN_INFO "Unloading /proc/swiotlb support\n"); + if (swiotlb_outbuf) + kfree (swiotlb_outbuf); + remove_proc_entry ("list", swiotlb_proc_dir); + remove_proc_entry ("params", swiotlb_proc_dir); + remove_proc_entry ("parameters", swiotlb_proc_dir); + remove_proc_entry ("swiotlb", 0); +} + +module_init(swiotlb_init_proc); +module_exit(swiotlb_exit_proc); diff -ruN linux-2.4.5/arch/ia64/lib/swiotlb.c linux-2.4.5mw/arch/ia64/lib/swiotlb.c --- linux-2.4.5/arch/ia64/lib/swiotlb.c Mon Jun 25 14:45:01 2001 +++ linux-2.4.5mw/arch/ia64/lib/swiotlb.c Mon Jun 25 21:02:47 2001 @@ -24,6 +24,13 @@ X #include <linux/init.h> X #include <linux/bootmem.h> X +#if defined CONFIG_PROCFS_SWIOTLB || defined CONFIG_PROCFS_SWIOTLB_MODULE +# define EXPORT_IOTLB_SYMS 1 +# define IOTLB_STATIC +#else +# define IOTLB_STATIC static +#endif + X #define ALIGN(val, align) ((unsigned long) \ X (((unsigned long) (val) + ((align) - 1)) & ~((align) - 1))) X @@ -36,19 +43,19 @@ X * Used to do a quick range check in swiotlb_unmap_single and swiotlb_sync_single, to see X * if the memory was in fact allocated by this API. X */ -static char *io_tlb_start, *io_tlb_end; +IOTLB_STATIC char *io_tlb_start, *io_tlb_end; X X /* X * The number of IO TLB blocks (in groups of 64) betweeen io_tlb_start and io_tlb_end. X * This is command line adjustable via setup_io_tlb_npages. X */ -static unsigned long io_tlb_nslabs = 1024; +IOTLB_STATIC unsigned long io_tlb_nslabs = 1024; X X /* X * This is a free list describing the number of free entries available from each index X */ -static unsigned int *io_tlb_list; -static unsigned int io_tlb_index; +IOTLB_STATIC unsigned int *io_tlb_list; +IOTLB_STATIC unsigned int io_tlb_index; X X /* X * We need to save away the original address corresponding to a mapped entry for the sync @@ -56,6 +63,16 @@ X */ X static unsigned char **io_tlb_orig_addr; X +#ifdef EXPORT_IOTLB_SYMS +/* + * Usage data for /proc entries + */ +unsigned int io_tlb_used_buffers = 0; +unsigned int io_tlb_used_slots = 0; +unsigned int io_tlb_max_used_buffers = 0; +unsigned int io_tlb_max_used_slots = 0; +#endif + X /* X * Protect the above data structures in the map and unmap calls X */ @@ -173,6 +190,15 @@ X found: X spin_unlock_irqrestore(&io_tlb_lock, flags); X +#ifdef EXPORT_IOTLB_SYMS + io_tlb_used_slots += nslots; + io_tlb_used_buffers++; + if (io_tlb_used_slots > io_tlb_max_used_slots) + io_tlb_max_used_slots = io_tlb_used_slots; + if (io_tlb_used_buffers > io_tlb_max_used_buffers) + io_tlb_max_used_buffers = io_tlb_used_buffers; +#endif + X /* X * Save away the mapping from the original address to the DMA address. This is X * needed when we sync the memory. Then we sync the buffer if needed. @@ -228,6 +254,10 @@ X io_tlb_list[i] = ++count; X } X spin_unlock_irqrestore(&io_tlb_lock, flags); +#ifdef EXPORT_IOTLB_SYMS + io_tlb_used_buffers--; + io_tlb_used_slots -= nslots; +#endif X } X X static void @@ -462,3 +492,15 @@ X EXPORT_SYMBOL(swiotlb_dma_address); X EXPORT_SYMBOL(swiotlb_alloc_consistent); X EXPORT_SYMBOL(swiotlb_free_consistent); + +#ifdef EXPORT_IOTLB_SYMS +EXPORT_SYMBOL(io_tlb_start); +EXPORT_SYMBOL(io_tlb_end); +EXPORT_SYMBOL(io_tlb_nslabs); +EXPORT_SYMBOL(io_tlb_index); +EXPORT_SYMBOL(io_tlb_list); +EXPORT_SYMBOL(io_tlb_used_buffers); +EXPORT_SYMBOL(io_tlb_used_slots); +EXPORT_SYMBOL(io_tlb_max_used_buffers); +EXPORT_SYMBOL(io_tlb_max_used_slots); +#endif /* EXPORT_IOTLB_SYMS */ SHAR_EOF (set 20 01 06 25 21 05 57 'iotlb-mon-0.2/swiotlb_proc.patch'; eval "$shar_touch") && chmod 0664 'iotlb-mon-0.2/swiotlb_proc.patch' || $echo 'restore of' 'iotlb-mon-0.2/swiotlb_proc.patch' 'failed' if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then md5sum -c << SHAR_EOF >/dev/null 2>&1 \ || $echo 'iotlb-mon-0.2/swiotlb_proc.patch:' 'MD5 check failed' 509bf43c7d000ddf3845d2c791277122 iotlb-mon-0.2/swiotlb_proc.patch SHAR_EOF else shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'iotlb-mon-0.2/swiotlb_proc.patch'`" test 10022 -eq "$shar_count" || $echo 'iotlb-mon-0.2/swiotlb_proc.patch:' 'original size' '10022,' 'current size' "$shar_count!" fi fi rm -fr _sh04019 exit 0