linux-kselftest-4.9-rc1-update

This update consists of:
 
 - Fixes and improvements to existing tests
 - Moving code from Documentation to selftests, samples, and tools.
 
   Moves dnotify_test, prctl, ptp, vDSO, ia64, watchdog, and networking
   tests from Documentation to selftests.
 
   Moves mic/mpssd, misc-devices/mei, timers, watchdog, auxdisplay, and
   blackfin examples from Documentation to samples.
 
   Moves accounting, laptops/dslm, and pcmcia/crc32hash tools from
   Documentation to tools.
 
   Deletes BUILD_DOCSRC and its dependencies.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJX/6zUAAoJEAsCRMQNDUMczIEP/0kH+yjJ3El4GYIokspR1/UU
 ++sy4XMzrD1UPy90v+ftcg4ss5R80r0v7EZ59k1UjDJSZ6WATHHGoZKCS2Dy3xcq
 i+0vm7Bawh7YWrXD3TunwaL97lwb2DdVTSxRXuU4Hfv+oVynUfh/+ZlCH6RCM2nm
 ZJE5PDYiq4nTVSRqFB2FyRE6yay5dPvpQ2ArwnSEw+ku4C+ZdGTGCWzS+aZBwZM/
 ykePkGLVRXz9FsWTCmipJzYu0Z/M4xEGlfXQZiiLG2HicbJNP6AqJImbQrANm+TW
 RFigYpofdhr9XG5TKTLIudaRt9qB6BE0mYEApZXH8U7NrHElfO9BBMEwzajl0V/2
 q/r5iej/CJult3zsfkhdHo7GLXpOaDLyoXiUI6UTgL0XOdWLAWTqDYx4JJz9sXxp
 B9dwKJeP5HLipk6FMkAHgJM90JKQFd/nLDKxeWexbMu/b/yQ2C9AR7NpdQ+c1X7I
 8W8UNEi/fnK75+r4t3NfeD2/5boq/jwujSKEMDQm/3R8L8EFYYb/TRoujFn89Na3
 wbZLV3hBL+KQ5lRyIx7X8RKyVJv1nlo9Wh57ItJed6zvGp5EmsI8w+DER2RfbO2c
 HR2JPDKSxmU8O2WBfDW5QoiPQH8Lssd147Ir0UFE7mwBXgWWsmxJxDpufizAXwyJ
 qnELJ9X3UFIdydtoObLr
 =60kH
 -----END PGP SIGNATURE-----

Merge tag 'linux-kselftest-4.9-rc1-update' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest

Pull kselftest updates from Shuah Khan:
 "This update consists of:

   - Fixes and improvements to existing tests

   - Moving code from Documentation to selftests, samples, and tools:

     * Moves dnotify_test, prctl, ptp, vDSO, ia64, watchdog, and
       networking tests from Documentation to selftests.

     * Moves mic/mpssd, misc-devices/mei, timers, watchdog, auxdisplay,
       and blackfin examples from Documentation to samples.

     * Moves accounting, laptops/dslm, and pcmcia/crc32hash tools from
       Documentation to tools.

     * Deletes BUILD_DOCSRC and its dependencies"

* tag 'linux-kselftest-4.9-rc1-update' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest: (21 commits)
  selftests/futex: Check ANSI terminal color support
  Doc: update 00-INDEX files to reflect the runnable code move
  samples: move blackfin gptimers-example from Documentation
  tools: move pcmcia crc32hash tool from Documentation
  tools: move laptops dslm tool from Documentation
  tools: move accounting tool from Documentation
  samples: move auxdisplay example code from Documentation
  samples: move watchdog example code from Documentation
  samples: move timers example code from Documentation
  samples: move misc-devices/mei example code from Documentation
  samples: move mic/mpssd example code from Documentation
  selftests: Move networking/timestamping from Documentation
  selftests: move watchdog tests from Documentation/watchdog
  selftests: move ia64 tests from Documentation/ia64
  selftests: move vDSO tests from Documentation/vDSO
  selftests: move ptp tests from Documentation/ptp
  selftests: move prctl tests from Documentation/prctl
  selftests: move dnotify_test from Documentation/filesystems
  selftests/timers: Add missing error code assignment before test
  selftests/zram: replace ZRAM_LZ4_COMPRESS
  ...
This commit is contained in:
Linus Torvalds 2016-10-14 15:17:12 -07:00
commit 5d89d9f502
105 changed files with 202 additions and 186 deletions

View file

@ -46,7 +46,8 @@ IRQ.txt
Intel-IOMMU.txt
- basic info on the Intel IOMMU virtualization support.
Makefile
- some files in Documentation dir are actually sample code to build
- This file does nothing. Removing it breaks make htmldocs and
make distclean.
ManagementStyle
- how to (attempt to) manage kernel hackers.
RCU/

View file

@ -1,3 +1 @@
subdir-y := accounting auxdisplay blackfin \
filesystems filesystems ia64 laptops mic misc-devices \
networking pcmcia prctl ptp timers vDSO watchdog
subdir-y :=

View file

@ -1 +0,0 @@
getdelays

View file

@ -1,7 +0,0 @@
# List of programs to build
hostprogs-y := getdelays
# Tell kbuild to always build the programs
always := $(hostprogs-y)
HOSTCFLAGS_getdelays.o += -I$(objtree)/usr/include

View file

@ -54,9 +54,9 @@ are sent to userspace without requiring a command. If it is the last exiting
task of a thread group, the per-tgid statistics are also sent. More details
are given in the taskstats interface description.
The getdelays.c userspace utility in this directory allows simple commands to
be run and the corresponding delay statistics to be displayed. It also serves
as an example of using the taskstats interface.
The getdelays.c userspace utility in tools/accounting directory allows simple
commands to be run and the corresponding delay statistics to be displayed. It
also serves as an example of using the taskstats interface.
Usage
-----

View file

@ -1,550 +0,0 @@
/* getdelays.c
*
* Utility to get per-pid and per-tgid delay accounting statistics
* Also illustrates usage of the taskstats interface
*
* Copyright (C) Shailabh Nagar, IBM Corp. 2005
* Copyright (C) Balbir Singh, IBM Corp. 2006
* Copyright (c) Jay Lan, SGI. 2006
*
* Compile with
* gcc -I/usr/src/linux/include getdelays.c -o getdelays
*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <poll.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <signal.h>
#include <linux/genetlink.h>
#include <linux/taskstats.h>
#include <linux/cgroupstats.h>
/*
* Generic macros for dealing with netlink sockets. Might be duplicated
* elsewhere. It is recommended that commercial grade applications use
* libnl or libnetlink and use the interfaces provided by the library
*/
#define GENLMSG_DATA(glh) ((void *)(NLMSG_DATA(glh) + GENL_HDRLEN))
#define GENLMSG_PAYLOAD(glh) (NLMSG_PAYLOAD(glh, 0) - GENL_HDRLEN)
#define NLA_DATA(na) ((void *)((char*)(na) + NLA_HDRLEN))
#define NLA_PAYLOAD(len) (len - NLA_HDRLEN)
#define err(code, fmt, arg...) \
do { \
fprintf(stderr, fmt, ##arg); \
exit(code); \
} while (0)
int done;
int rcvbufsz;
char name[100];
int dbg;
int print_delays;
int print_io_accounting;
int print_task_context_switch_counts;
#define PRINTF(fmt, arg...) { \
if (dbg) { \
printf(fmt, ##arg); \
} \
}
/* Maximum size of response requested or message sent */
#define MAX_MSG_SIZE 1024
/* Maximum number of cpus expected to be specified in a cpumask */
#define MAX_CPUS 32
struct msgtemplate {
struct nlmsghdr n;
struct genlmsghdr g;
char buf[MAX_MSG_SIZE];
};
char cpumask[100+6*MAX_CPUS];
static void usage(void)
{
fprintf(stderr, "getdelays [-dilv] [-w logfile] [-r bufsize] "
"[-m cpumask] [-t tgid] [-p pid]\n");
fprintf(stderr, " -d: print delayacct stats\n");
fprintf(stderr, " -i: print IO accounting (works only with -p)\n");
fprintf(stderr, " -l: listen forever\n");
fprintf(stderr, " -v: debug on\n");
fprintf(stderr, " -C: container path\n");
}
/*
* Create a raw netlink socket and bind
*/
static int create_nl_socket(int protocol)
{
int fd;
struct sockaddr_nl local;
fd = socket(AF_NETLINK, SOCK_RAW, protocol);
if (fd < 0)
return -1;
if (rcvbufsz)
if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF,
&rcvbufsz, sizeof(rcvbufsz)) < 0) {
fprintf(stderr, "Unable to set socket rcv buf size to %d\n",
rcvbufsz);
goto error;
}
memset(&local, 0, sizeof(local));
local.nl_family = AF_NETLINK;
if (bind(fd, (struct sockaddr *) &local, sizeof(local)) < 0)
goto error;
return fd;
error:
close(fd);
return -1;
}
static int send_cmd(int sd, __u16 nlmsg_type, __u32 nlmsg_pid,
__u8 genl_cmd, __u16 nla_type,
void *nla_data, int nla_len)
{
struct nlattr *na;
struct sockaddr_nl nladdr;
int r, buflen;
char *buf;
struct msgtemplate msg;
msg.n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
msg.n.nlmsg_type = nlmsg_type;
msg.n.nlmsg_flags = NLM_F_REQUEST;
msg.n.nlmsg_seq = 0;
msg.n.nlmsg_pid = nlmsg_pid;
msg.g.cmd = genl_cmd;
msg.g.version = 0x1;
na = (struct nlattr *) GENLMSG_DATA(&msg);
na->nla_type = nla_type;
na->nla_len = nla_len + 1 + NLA_HDRLEN;
memcpy(NLA_DATA(na), nla_data, nla_len);
msg.n.nlmsg_len += NLMSG_ALIGN(na->nla_len);
buf = (char *) &msg;
buflen = msg.n.nlmsg_len ;
memset(&nladdr, 0, sizeof(nladdr));
nladdr.nl_family = AF_NETLINK;
while ((r = sendto(sd, buf, buflen, 0, (struct sockaddr *) &nladdr,
sizeof(nladdr))) < buflen) {
if (r > 0) {
buf += r;
buflen -= r;
} else if (errno != EAGAIN)
return -1;
}
return 0;
}
/*
* Probe the controller in genetlink to find the family id
* for the TASKSTATS family
*/
static int get_family_id(int sd)
{
struct {
struct nlmsghdr n;
struct genlmsghdr g;
char buf[256];
} ans;
int id = 0, rc;
struct nlattr *na;
int rep_len;
strcpy(name, TASKSTATS_GENL_NAME);
rc = send_cmd(sd, GENL_ID_CTRL, getpid(), CTRL_CMD_GETFAMILY,
CTRL_ATTR_FAMILY_NAME, (void *)name,
strlen(TASKSTATS_GENL_NAME)+1);
if (rc < 0)
return 0; /* sendto() failure? */
rep_len = recv(sd, &ans, sizeof(ans), 0);
if (ans.n.nlmsg_type == NLMSG_ERROR ||
(rep_len < 0) || !NLMSG_OK((&ans.n), rep_len))
return 0;
na = (struct nlattr *) GENLMSG_DATA(&ans);
na = (struct nlattr *) ((char *) na + NLA_ALIGN(na->nla_len));
if (na->nla_type == CTRL_ATTR_FAMILY_ID) {
id = *(__u16 *) NLA_DATA(na);
}
return id;
}
#define average_ms(t, c) (t / 1000000ULL / (c ? c : 1))
static void print_delayacct(struct taskstats *t)
{
printf("\n\nCPU %15s%15s%15s%15s%15s\n"
" %15llu%15llu%15llu%15llu%15.3fms\n"
"IO %15s%15s%15s\n"
" %15llu%15llu%15llums\n"
"SWAP %15s%15s%15s\n"
" %15llu%15llu%15llums\n"
"RECLAIM %12s%15s%15s\n"
" %15llu%15llu%15llums\n",
"count", "real total", "virtual total",
"delay total", "delay average",
(unsigned long long)t->cpu_count,
(unsigned long long)t->cpu_run_real_total,
(unsigned long long)t->cpu_run_virtual_total,
(unsigned long long)t->cpu_delay_total,
average_ms((double)t->cpu_delay_total, t->cpu_count),
"count", "delay total", "delay average",
(unsigned long long)t->blkio_count,
(unsigned long long)t->blkio_delay_total,
average_ms(t->blkio_delay_total, t->blkio_count),
"count", "delay total", "delay average",
(unsigned long long)t->swapin_count,
(unsigned long long)t->swapin_delay_total,
average_ms(t->swapin_delay_total, t->swapin_count),
"count", "delay total", "delay average",
(unsigned long long)t->freepages_count,
(unsigned long long)t->freepages_delay_total,
average_ms(t->freepages_delay_total, t->freepages_count));
}
static void task_context_switch_counts(struct taskstats *t)
{
printf("\n\nTask %15s%15s\n"
" %15llu%15llu\n",
"voluntary", "nonvoluntary",
(unsigned long long)t->nvcsw, (unsigned long long)t->nivcsw);
}
static void print_cgroupstats(struct cgroupstats *c)
{
printf("sleeping %llu, blocked %llu, running %llu, stopped %llu, "
"uninterruptible %llu\n", (unsigned long long)c->nr_sleeping,
(unsigned long long)c->nr_io_wait,
(unsigned long long)c->nr_running,
(unsigned long long)c->nr_stopped,
(unsigned long long)c->nr_uninterruptible);
}
static void print_ioacct(struct taskstats *t)
{
printf("%s: read=%llu, write=%llu, cancelled_write=%llu\n",
t->ac_comm,
(unsigned long long)t->read_bytes,
(unsigned long long)t->write_bytes,
(unsigned long long)t->cancelled_write_bytes);
}
int main(int argc, char *argv[])
{
int c, rc, rep_len, aggr_len, len2;
int cmd_type = TASKSTATS_CMD_ATTR_UNSPEC;
__u16 id;
__u32 mypid;
struct nlattr *na;
int nl_sd = -1;
int len = 0;
pid_t tid = 0;
pid_t rtid = 0;
int fd = 0;
int count = 0;
int write_file = 0;
int maskset = 0;
char *logfile = NULL;
int loop = 0;
int containerset = 0;
char *containerpath = NULL;
int cfd = 0;
int forking = 0;
sigset_t sigset;
struct msgtemplate msg;
while (!forking) {
c = getopt(argc, argv, "qdiw:r:m:t:p:vlC:c:");
if (c < 0)
break;
switch (c) {
case 'd':
printf("print delayacct stats ON\n");
print_delays = 1;
break;
case 'i':
printf("printing IO accounting\n");
print_io_accounting = 1;
break;
case 'q':
printf("printing task/process context switch rates\n");
print_task_context_switch_counts = 1;
break;
case 'C':
containerset = 1;
containerpath = optarg;
break;
case 'w':
logfile = strdup(optarg);
printf("write to file %s\n", logfile);
write_file = 1;
break;
case 'r':
rcvbufsz = atoi(optarg);
printf("receive buf size %d\n", rcvbufsz);
if (rcvbufsz < 0)
err(1, "Invalid rcv buf size\n");
break;
case 'm':
strncpy(cpumask, optarg, sizeof(cpumask));
cpumask[sizeof(cpumask) - 1] = '\0';
maskset = 1;
printf("cpumask %s maskset %d\n", cpumask, maskset);
break;
case 't':
tid = atoi(optarg);
if (!tid)
err(1, "Invalid tgid\n");
cmd_type = TASKSTATS_CMD_ATTR_TGID;
break;
case 'p':
tid = atoi(optarg);
if (!tid)
err(1, "Invalid pid\n");
cmd_type = TASKSTATS_CMD_ATTR_PID;
break;
case 'c':
/* Block SIGCHLD for sigwait() later */
if (sigemptyset(&sigset) == -1)
err(1, "Failed to empty sigset");
if (sigaddset(&sigset, SIGCHLD))
err(1, "Failed to set sigchld in sigset");
sigprocmask(SIG_BLOCK, &sigset, NULL);
/* fork/exec a child */
tid = fork();
if (tid < 0)
err(1, "Fork failed\n");
if (tid == 0)
if (execvp(argv[optind - 1],
&argv[optind - 1]) < 0)
exit(-1);
/* Set the command type and avoid further processing */
cmd_type = TASKSTATS_CMD_ATTR_PID;
forking = 1;
break;
case 'v':
printf("debug on\n");
dbg = 1;
break;
case 'l':
printf("listen forever\n");
loop = 1;
break;
default:
usage();
exit(-1);
}
}
if (write_file) {
fd = open(logfile, O_WRONLY | O_CREAT | O_TRUNC,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (fd == -1) {
perror("Cannot open output file\n");
exit(1);
}
}
nl_sd = create_nl_socket(NETLINK_GENERIC);
if (nl_sd < 0)
err(1, "error creating Netlink socket\n");
mypid = getpid();
id = get_family_id(nl_sd);
if (!id) {
fprintf(stderr, "Error getting family id, errno %d\n", errno);
goto err;
}
PRINTF("family id %d\n", id);
if (maskset) {
rc = send_cmd(nl_sd, id, mypid, TASKSTATS_CMD_GET,
TASKSTATS_CMD_ATTR_REGISTER_CPUMASK,
&cpumask, strlen(cpumask) + 1);
PRINTF("Sent register cpumask, retval %d\n", rc);
if (rc < 0) {
fprintf(stderr, "error sending register cpumask\n");
goto err;
}
}
if (tid && containerset) {
fprintf(stderr, "Select either -t or -C, not both\n");
goto err;
}
/*
* If we forked a child, wait for it to exit. Cannot use waitpid()
* as all the delicious data would be reaped as part of the wait
*/
if (tid && forking) {
int sig_received;
sigwait(&sigset, &sig_received);
}
if (tid) {
rc = send_cmd(nl_sd, id, mypid, TASKSTATS_CMD_GET,
cmd_type, &tid, sizeof(__u32));
PRINTF("Sent pid/tgid, retval %d\n", rc);
if (rc < 0) {
fprintf(stderr, "error sending tid/tgid cmd\n");
goto done;
}
}
if (containerset) {
cfd = open(containerpath, O_RDONLY);
if (cfd < 0) {
perror("error opening container file");
goto err;
}
rc = send_cmd(nl_sd, id, mypid, CGROUPSTATS_CMD_GET,
CGROUPSTATS_CMD_ATTR_FD, &cfd, sizeof(__u32));
if (rc < 0) {
perror("error sending cgroupstats command");
goto err;
}
}
if (!maskset && !tid && !containerset) {
usage();
goto err;
}
do {
rep_len = recv(nl_sd, &msg, sizeof(msg), 0);
PRINTF("received %d bytes\n", rep_len);
if (rep_len < 0) {
fprintf(stderr, "nonfatal reply error: errno %d\n",
errno);
continue;
}
if (msg.n.nlmsg_type == NLMSG_ERROR ||
!NLMSG_OK((&msg.n), rep_len)) {
struct nlmsgerr *err = NLMSG_DATA(&msg);
fprintf(stderr, "fatal reply error, errno %d\n",
err->error);
goto done;
}
PRINTF("nlmsghdr size=%zu, nlmsg_len=%d, rep_len=%d\n",
sizeof(struct nlmsghdr), msg.n.nlmsg_len, rep_len);
rep_len = GENLMSG_PAYLOAD(&msg.n);
na = (struct nlattr *) GENLMSG_DATA(&msg);
len = 0;
while (len < rep_len) {
len += NLA_ALIGN(na->nla_len);
switch (na->nla_type) {
case TASKSTATS_TYPE_AGGR_TGID:
/* Fall through */
case TASKSTATS_TYPE_AGGR_PID:
aggr_len = NLA_PAYLOAD(na->nla_len);
len2 = 0;
/* For nested attributes, na follows */
na = (struct nlattr *) NLA_DATA(na);
done = 0;
while (len2 < aggr_len) {
switch (na->nla_type) {
case TASKSTATS_TYPE_PID:
rtid = *(int *) NLA_DATA(na);
if (print_delays)
printf("PID\t%d\n", rtid);
break;
case TASKSTATS_TYPE_TGID:
rtid = *(int *) NLA_DATA(na);
if (print_delays)
printf("TGID\t%d\n", rtid);
break;
case TASKSTATS_TYPE_STATS:
count++;
if (print_delays)
print_delayacct((struct taskstats *) NLA_DATA(na));
if (print_io_accounting)
print_ioacct((struct taskstats *) NLA_DATA(na));
if (print_task_context_switch_counts)
task_context_switch_counts((struct taskstats *) NLA_DATA(na));
if (fd) {
if (write(fd, NLA_DATA(na), na->nla_len) < 0) {
err(1,"write error\n");
}
}
if (!loop)
goto done;
break;
case TASKSTATS_TYPE_NULL:
break;
default:
fprintf(stderr, "Unknown nested"
" nla_type %d\n",
na->nla_type);
break;
}
len2 += NLA_ALIGN(na->nla_len);
na = (struct nlattr *)((char *)na +
NLA_ALIGN(na->nla_len));
}
break;
case CGROUPSTATS_TYPE_CGROUP_STATS:
print_cgroupstats(NLA_DATA(na));
break;
default:
fprintf(stderr, "Unknown nla_type %d\n",
na->nla_type);
case TASKSTATS_TYPE_NULL:
break;
}
na = (struct nlattr *) (GENLMSG_DATA(&msg) + len);
}
} while (loop);
done:
if (maskset) {
rc = send_cmd(nl_sd, id, mypid, TASKSTATS_CMD_GET,
TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK,
&cpumask, strlen(cpumask) + 1);
printf("Sent deregister mask, retval %d\n", rc);
if (rc < 0)
err(rc, "error sending deregister cpumask\n");
}
err:
close(nl_sd);
if (fd)
close(fd);
if (cfd)
close(cfd);
return 0;
}

View file

@ -8,8 +8,6 @@ Interrupts
- ARM Interrupt subsystem documentation
IXP4xx
- Intel IXP4xx Network processor.
Makefile
- Build sourcefiles as part of the Documentation-build for arm
Netwinder
- Netwinder specific documentation
Porting

View file

@ -1 +0,0 @@
cfag12864b-example

View file

@ -1,7 +0,0 @@
# List of programs to build
hostprogs-y := cfag12864b-example
# Tell kbuild to always build the programs
always := $(hostprogs-y)
HOSTCFLAGS_cfag12864b-example.o += -I$(objtree)/usr/include

View file

@ -101,5 +101,5 @@ Although the LCD won't get updated until the next refresh time arrives.
Also, you can mmap the framebuffer: open & mmap, munmap & close...
which is the best option for most uses.
Check Documentation/auxdisplay/cfag12864b-example.c
Check samples/auxdisplay/cfag12864b-example.c
for a real working userspace complete program with usage examples.

View file

@ -1,281 +0,0 @@
/*
* Filename: cfag12864b-example.c
* Version: 0.1.0
* Description: cfag12864b LCD userspace example program
* License: GPLv2
*
* Author: Copyright (C) Miguel Ojeda Sandonis
* Date: 2006-10-31
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
/*
* ------------------------
* start of cfag12864b code
* ------------------------
*/
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#define CFAG12864B_WIDTH (128)
#define CFAG12864B_HEIGHT (64)
#define CFAG12864B_SIZE (128 * 64 / 8)
#define CFAG12864B_BPB (8)
#define CFAG12864B_ADDRESS(x, y) ((y) * CFAG12864B_WIDTH / \
CFAG12864B_BPB + (x) / CFAG12864B_BPB)
#define CFAG12864B_BIT(n) (((unsigned char) 1) << (n))
#undef CFAG12864B_DOCHECK
#ifdef CFAG12864B_DOCHECK
#define CFAG12864B_CHECK(x, y) ((x) < CFAG12864B_WIDTH && \
(y) < CFAG12864B_HEIGHT)
#else
#define CFAG12864B_CHECK(x, y) (1)
#endif
int cfag12864b_fd;
unsigned char * cfag12864b_mem;
unsigned char cfag12864b_buffer[CFAG12864B_SIZE];
/*
* init a cfag12864b framebuffer device
*
* No error: return = 0
* Unable to open: return = -1
* Unable to mmap: return = -2
*/
static int cfag12864b_init(char *path)
{
cfag12864b_fd = open(path, O_RDWR);
if (cfag12864b_fd == -1)
return -1;
cfag12864b_mem = mmap(0, CFAG12864B_SIZE, PROT_READ | PROT_WRITE,
MAP_SHARED, cfag12864b_fd, 0);
if (cfag12864b_mem == MAP_FAILED) {
close(cfag12864b_fd);
return -2;
}
return 0;
}
/*
* exit a cfag12864b framebuffer device
*/
static void cfag12864b_exit(void)
{
munmap(cfag12864b_mem, CFAG12864B_SIZE);
close(cfag12864b_fd);
}
/*
* set (x, y) pixel
*/
static void cfag12864b_set(unsigned char x, unsigned char y)
{
if (CFAG12864B_CHECK(x, y))
cfag12864b_buffer[CFAG12864B_ADDRESS(x, y)] |=
CFAG12864B_BIT(x % CFAG12864B_BPB);
}
/*
* unset (x, y) pixel
*/
static void cfag12864b_unset(unsigned char x, unsigned char y)
{
if (CFAG12864B_CHECK(x, y))
cfag12864b_buffer[CFAG12864B_ADDRESS(x, y)] &=
~CFAG12864B_BIT(x % CFAG12864B_BPB);
}
/*
* is set (x, y) pixel?
*
* Pixel off: return = 0
* Pixel on: return = 1
*/
static unsigned char cfag12864b_isset(unsigned char x, unsigned char y)
{
if (CFAG12864B_CHECK(x, y))
if (cfag12864b_buffer[CFAG12864B_ADDRESS(x, y)] &
CFAG12864B_BIT(x % CFAG12864B_BPB))
return 1;
return 0;
}
/*
* not (x, y) pixel
*/
static void cfag12864b_not(unsigned char x, unsigned char y)
{
if (cfag12864b_isset(x, y))
cfag12864b_unset(x, y);
else
cfag12864b_set(x, y);
}
/*
* fill (set all pixels)
*/
static void cfag12864b_fill(void)
{
unsigned short i;
for (i = 0; i < CFAG12864B_SIZE; i++)
cfag12864b_buffer[i] = 0xFF;
}
/*
* clear (unset all pixels)
*/
static void cfag12864b_clear(void)
{
unsigned short i;
for (i = 0; i < CFAG12864B_SIZE; i++)
cfag12864b_buffer[i] = 0;
}
/*
* format a [128*64] matrix
*
* Pixel off: src[i] = 0
* Pixel on: src[i] > 0
*/
static void cfag12864b_format(unsigned char * matrix)
{
unsigned char i, j, n;
for (i = 0; i < CFAG12864B_HEIGHT; i++)
for (j = 0; j < CFAG12864B_WIDTH / CFAG12864B_BPB; j++) {
cfag12864b_buffer[i * CFAG12864B_WIDTH / CFAG12864B_BPB +
j] = 0;
for (n = 0; n < CFAG12864B_BPB; n++)
if (matrix[i * CFAG12864B_WIDTH +
j * CFAG12864B_BPB + n])
cfag12864b_buffer[i * CFAG12864B_WIDTH /
CFAG12864B_BPB + j] |=
CFAG12864B_BIT(n);
}
}
/*
* blit buffer to lcd
*/
static void cfag12864b_blit(void)
{
memcpy(cfag12864b_mem, cfag12864b_buffer, CFAG12864B_SIZE);
}
/*
* ----------------------
* end of cfag12864b code
* ----------------------
*/
#include <stdio.h>
#define EXAMPLES 6
static void example(unsigned char n)
{
unsigned short i, j;
unsigned char matrix[CFAG12864B_WIDTH * CFAG12864B_HEIGHT];
if (n > EXAMPLES)
return;
printf("Example %i/%i - ", n, EXAMPLES);
switch (n) {
case 1:
printf("Draw points setting bits");
cfag12864b_clear();
for (i = 0; i < CFAG12864B_WIDTH; i += 2)
for (j = 0; j < CFAG12864B_HEIGHT; j += 2)
cfag12864b_set(i, j);
break;
case 2:
printf("Clear the LCD");
cfag12864b_clear();
break;
case 3:
printf("Draw rows formatting a [128*64] matrix");
memset(matrix, 0, CFAG12864B_WIDTH * CFAG12864B_HEIGHT);
for (i = 0; i < CFAG12864B_WIDTH; i++)
for (j = 0; j < CFAG12864B_HEIGHT; j += 2)
matrix[j * CFAG12864B_WIDTH + i] = 1;
cfag12864b_format(matrix);
break;
case 4:
printf("Fill the lcd");
cfag12864b_fill();
break;
case 5:
printf("Draw columns unsetting bits");
for (i = 0; i < CFAG12864B_WIDTH; i += 2)
for (j = 0; j < CFAG12864B_HEIGHT; j++)
cfag12864b_unset(i, j);
break;
case 6:
printf("Do negative not-ing all bits");
for (i = 0; i < CFAG12864B_WIDTH; i++)
for (j = 0; j < CFAG12864B_HEIGHT; j ++)
cfag12864b_not(i, j);
break;
}
puts(" - [Press Enter]");
}
int main(int argc, char *argv[])
{
unsigned char n;
if (argc != 2) {
printf(
"Sintax: %s fbdev\n"
"Usually: /dev/fb0, /dev/fb1...\n", argv[0]);
return -1;
}
if (cfag12864b_init(argv[1])) {
printf("Can't init %s fbdev\n", argv[1]);
return -2;
}
for (n = 1; n <= EXAMPLES; n++) {
example(n);
cfag12864b_blit();
while (getchar() != '\n');
}
cfag12864b_exit();
return 0;
}

View file

@ -1,10 +1,6 @@
00-INDEX
- This file
Makefile
- Makefile for gptimers example file.
bfin-gpio-notes.txt
- Notes in developing/using bfin-gpio driver.
bfin-spi-notes.txt
- Notes for using bfin spi bus driver.
gptimers-example.c
- gptimers example

View file

@ -1,5 +0,0 @@
ifneq ($(CONFIG_BLACKFIN),)
ifneq ($(CONFIG_BFIN_GPTIMERS),)
obj-m := gptimers-example.o
endif
endif

View file

@ -1,91 +0,0 @@
/*
* Simple gptimers example
* http://docs.blackfin.uclinux.org/doku.php?id=linux-kernel:drivers:gptimers
*
* Copyright 2007-2009 Analog Devices Inc.
*
* Licensed under the GPL-2 or later.
*/
#include <linux/interrupt.h>
#include <linux/module.h>
#include <asm/gptimers.h>
#include <asm/portmux.h>
/* ... random driver includes ... */
#define DRIVER_NAME "gptimer_example"
#ifdef IRQ_TIMER5
#define SAMPLE_IRQ_TIMER IRQ_TIMER5
#else
#define SAMPLE_IRQ_TIMER IRQ_TIMER2
#endif
struct gptimer_data {
uint32_t period, width;
};
static struct gptimer_data data;
/* ... random driver state ... */
static irqreturn_t gptimer_example_irq(int irq, void *dev_id)
{
struct gptimer_data *data = dev_id;
/* make sure it was our timer which caused the interrupt */
if (!get_gptimer_intr(TIMER5_id))
return IRQ_NONE;
/* read the width/period values that were captured for the waveform */
data->width = get_gptimer_pwidth(TIMER5_id);
data->period = get_gptimer_period(TIMER5_id);
/* acknowledge the interrupt */
clear_gptimer_intr(TIMER5_id);
/* tell the upper layers we took care of things */
return IRQ_HANDLED;
}
/* ... random driver code ... */
static int __init gptimer_example_init(void)
{
int ret;
/* grab the peripheral pins */
ret = peripheral_request(P_TMR5, DRIVER_NAME);
if (ret) {
printk(KERN_NOTICE DRIVER_NAME ": peripheral request failed\n");
return ret;
}
/* grab the IRQ for the timer */
ret = request_irq(SAMPLE_IRQ_TIMER, gptimer_example_irq,
IRQF_SHARED, DRIVER_NAME, &data);
if (ret) {
printk(KERN_NOTICE DRIVER_NAME ": IRQ request failed\n");
peripheral_free(P_TMR5);
return ret;
}
/* setup the timer and enable it */
set_gptimer_config(TIMER5_id,
WDTH_CAP | PULSE_HI | PERIOD_CNT | IRQ_ENA);
enable_gptimers(TIMER5bit);
return 0;
}
module_init(gptimer_example_init);
static void __exit gptimer_example_exit(void)
{
disable_gptimers(TIMER5bit);
free_irq(SAMPLE_IRQ_TIMER, &data);
peripheral_free(P_TMR5);
}
module_exit(gptimer_example_exit);
MODULE_LICENSE("BSD");

View file

@ -1 +0,0 @@
dnotify_test

View file

@ -2,8 +2,6 @@
- this file (info on some of the filesystems supported by linux).
Locking
- info on locking rules as they pertain to Linux VFS.
Makefile
- Makefile for building the filsystems-part of DocBook.
9p.txt
- 9p (v9fs) is an implementation of the Plan 9 remote fs protocol.
adfs.txt

View file

@ -1,5 +0,0 @@
# List of programs to build
hostprogs-y := dnotify_test
# Tell kbuild to always build the programs
always := $(hostprogs-y)

View file

@ -1,34 +0,0 @@
#define _GNU_SOURCE /* needed to get the defines */
#include <fcntl.h> /* in glibc 2.2 this has the needed
values defined */
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
static volatile int event_fd;
static void handler(int sig, siginfo_t *si, void *data)
{
event_fd = si->si_fd;
}
int main(void)
{
struct sigaction act;
int fd;
act.sa_sigaction = handler;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_SIGINFO;
sigaction(SIGRTMIN + 1, &act, NULL);
fd = open(".", O_RDONLY);
fcntl(fd, F_SETSIG, SIGRTMIN + 1);
fcntl(fd, F_NOTIFY, DN_MODIFY|DN_CREATE|DN_MULTISHOT);
/* we will now be notified if any of the files
in "." is modified or new files are created */
while (1) {
pause();
printf("Got event on fd=%d\n", event_fd);
}
}

View file

@ -1 +0,0 @@
aliasing-test

View file

@ -1,5 +0,0 @@
# List of programs to build
hostprogs-y := aliasing-test
# Tell kbuild to always build the programs
always := $(hostprogs-y)

View file

@ -1,263 +0,0 @@
/*
* Exercise /dev/mem mmap cases that have been troublesome in the past
*
* (c) Copyright 2007 Hewlett-Packard Development Company, L.P.
* Bjorn Helgaas <bjorn.helgaas@hp.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <fcntl.h>
#include <fnmatch.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/pci.h>
int sum;
static int map_mem(char *path, off_t offset, size_t length, int touch)
{
int fd, rc;
void *addr;
int *c;
fd = open(path, O_RDWR);
if (fd == -1) {
perror(path);
return -1;
}
if (fnmatch("/proc/bus/pci/*", path, 0) == 0) {
rc = ioctl(fd, PCIIOC_MMAP_IS_MEM);
if (rc == -1)
perror("PCIIOC_MMAP_IS_MEM ioctl");
}
addr = mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, offset);
if (addr == MAP_FAILED)
return 1;
if (touch) {
c = (int *) addr;
while (c < (int *) (addr + length))
sum += *c++;
}
rc = munmap(addr, length);
if (rc == -1) {
perror("munmap");
return -1;
}
close(fd);
return 0;
}
static int scan_tree(char *path, char *file, off_t offset, size_t length, int touch)
{
struct dirent **namelist;
char *name, *path2;
int i, n, r, rc = 0, result = 0;
struct stat buf;
n = scandir(path, &namelist, 0, alphasort);
if (n < 0) {
perror("scandir");
return -1;
}
for (i = 0; i < n; i++) {
name = namelist[i]->d_name;
if (fnmatch(".", name, 0) == 0)
goto skip;
if (fnmatch("..", name, 0) == 0)
goto skip;
path2 = malloc(strlen(path) + strlen(name) + 3);
strcpy(path2, path);
strcat(path2, "/");
strcat(path2, name);
if (fnmatch(file, name, 0) == 0) {
rc = map_mem(path2, offset, length, touch);
if (rc == 0)
fprintf(stderr, "PASS: %s 0x%lx-0x%lx is %s\n", path2, offset, offset + length, touch ? "readable" : "mappable");
else if (rc > 0)
fprintf(stderr, "PASS: %s 0x%lx-0x%lx not mappable\n", path2, offset, offset + length);
else {
fprintf(stderr, "FAIL: %s 0x%lx-0x%lx not accessible\n", path2, offset, offset + length);
return rc;
}
} else {
r = lstat(path2, &buf);
if (r == 0 && S_ISDIR(buf.st_mode)) {
rc = scan_tree(path2, file, offset, length, touch);
if (rc < 0)
return rc;
}
}
result |= rc;
free(path2);
skip:
free(namelist[i]);
}
free(namelist);
return result;
}
char buf[1024];
static int read_rom(char *path)
{
int fd, rc;
size_t size = 0;
fd = open(path, O_RDWR);
if (fd == -1) {
perror(path);
return -1;
}
rc = write(fd, "1", 2);
if (rc <= 0) {
close(fd);
perror("write");
return -1;
}
do {
rc = read(fd, buf, sizeof(buf));
if (rc > 0)
size += rc;
} while (rc > 0);
close(fd);
return size;
}
static int scan_rom(char *path, char *file)
{
struct dirent **namelist;
char *name, *path2;
int i, n, r, rc = 0, result = 0;
struct stat buf;
n = scandir(path, &namelist, 0, alphasort);
if (n < 0) {
perror("scandir");
return -1;
}
for (i = 0; i < n; i++) {
name = namelist[i]->d_name;
if (fnmatch(".", name, 0) == 0)
goto skip;
if (fnmatch("..", name, 0) == 0)
goto skip;
path2 = malloc(strlen(path) + strlen(name) + 3);
strcpy(path2, path);
strcat(path2, "/");
strcat(path2, name);
if (fnmatch(file, name, 0) == 0) {
rc = read_rom(path2);
/*
* It's OK if the ROM is unreadable. Maybe there
* is no ROM, or some other error occurred. The
* important thing is that no MCA happened.
*/
if (rc > 0)
fprintf(stderr, "PASS: %s read %d bytes\n", path2, rc);
else {
fprintf(stderr, "PASS: %s not readable\n", path2);
return rc;
}
} else {
r = lstat(path2, &buf);
if (r == 0 && S_ISDIR(buf.st_mode)) {
rc = scan_rom(path2, file);
if (rc < 0)
return rc;
}
}
result |= rc;
free(path2);
skip:
free(namelist[i]);
}
free(namelist);
return result;
}
int main(void)
{
int rc;
if (map_mem("/dev/mem", 0, 0xA0000, 1) == 0)
fprintf(stderr, "PASS: /dev/mem 0x0-0xa0000 is readable\n");
else
fprintf(stderr, "FAIL: /dev/mem 0x0-0xa0000 not accessible\n");
/*
* It's not safe to blindly read the VGA frame buffer. If you know
* how to poke the card the right way, it should respond, but it's
* not safe in general. Many machines, e.g., Intel chipsets, cover
* up a non-responding card by just returning -1, but others will
* report the failure as a machine check.
*/
if (map_mem("/dev/mem", 0xA0000, 0x20000, 0) == 0)
fprintf(stderr, "PASS: /dev/mem 0xa0000-0xc0000 is mappable\n");
else
fprintf(stderr, "FAIL: /dev/mem 0xa0000-0xc0000 not accessible\n");
if (map_mem("/dev/mem", 0xC0000, 0x40000, 1) == 0)
fprintf(stderr, "PASS: /dev/mem 0xc0000-0x100000 is readable\n");
else
fprintf(stderr, "FAIL: /dev/mem 0xc0000-0x100000 not accessible\n");
/*
* Often you can map all the individual pieces above (0-0xA0000,
* 0xA0000-0xC0000, and 0xC0000-0x100000), but can't map the whole
* thing at once. This is because the individual pieces use different
* attributes, and there's no single attribute supported over the
* whole region.
*/
rc = map_mem("/dev/mem", 0, 1024*1024, 0);
if (rc == 0)
fprintf(stderr, "PASS: /dev/mem 0x0-0x100000 is mappable\n");
else if (rc > 0)
fprintf(stderr, "PASS: /dev/mem 0x0-0x100000 not mappable\n");
else
fprintf(stderr, "FAIL: /dev/mem 0x0-0x100000 not accessible\n");
scan_tree("/sys/class/pci_bus", "legacy_mem", 0, 0xA0000, 1);
scan_tree("/sys/class/pci_bus", "legacy_mem", 0xA0000, 0x20000, 0);
scan_tree("/sys/class/pci_bus", "legacy_mem", 0xC0000, 0x40000, 1);
scan_tree("/sys/class/pci_bus", "legacy_mem", 0, 1024*1024, 0);
scan_rom("/sys/devices", "rom");
scan_tree("/proc/bus/pci", "??.?", 0, 0xA0000, 1);
scan_tree("/proc/bus/pci", "??.?", 0xA0000, 0x20000, 0);
scan_tree("/proc/bus/pci", "??.?", 0xC0000, 0x40000, 1);
scan_tree("/proc/bus/pci", "??.?", 0, 1024*1024, 0);
return rc;
}

View file

@ -1,8 +1,9 @@
Linux Kernel Selftests
The kernel contains a set of "self tests" under the tools/testing/selftests/
directory. These are intended to be small unit tests to exercise individual
code paths in the kernel.
directory. These are intended to be small tests to exercise individual code
paths in the kernel. Tests are intended to be run after building, installing
and booting a kernel.
On some systems, hot-plug tests could hang forever waiting for cpu and
memory to be ready to be offlined. A special hot-plug target is created

View file

@ -1 +0,0 @@
dslm

View file

@ -1,13 +1,9 @@
00-INDEX
- This file
Makefile
- Makefile for building dslm example program.
asus-laptop.txt
- information on the Asus Laptop Extras driver.
disk-shock-protection.txt
- information on hard disk shock protection.
dslm.c
- Simple Disk Sleep Monitor program
laptop-mode.txt
- how to conserve battery power using laptop-mode.
sony-laptop.txt

View file

@ -1,5 +0,0 @@
# List of programs to build
hostprogs-y := dslm
# Tell kbuild to always build the programs
always := $(hostprogs-y)

View file

@ -1,166 +0,0 @@
/*
* dslm.c
* Simple Disk Sleep Monitor
* by Bartek Kania
* Licensed under the GPL
*/
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <time.h>
#include <string.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <linux/hdreg.h>
#ifdef DEBUG
#define D(x) x
#else
#define D(x)
#endif
int endit = 0;
/* Check if the disk is in powersave-mode
* Most of the code is stolen from hdparm.
* 1 = active, 0 = standby/sleep, -1 = unknown */
static int check_powermode(int fd)
{
unsigned char args[4] = {WIN_CHECKPOWERMODE1,0,0,0};
int state;
if (ioctl(fd, HDIO_DRIVE_CMD, &args)
&& (args[0] = WIN_CHECKPOWERMODE2) /* try again with 0x98 */
&& ioctl(fd, HDIO_DRIVE_CMD, &args)) {
if (errno != EIO || args[0] != 0 || args[1] != 0) {
state = -1; /* "unknown"; */
} else
state = 0; /* "sleeping"; */
} else {
state = (args[2] == 255) ? 1 : 0;
}
D(printf(" drive state is: %d\n", state));
return state;
}
static char *state_name(int i)
{
if (i == -1) return "unknown";
if (i == 0) return "sleeping";
if (i == 1) return "active";
return "internal error";
}
static char *myctime(time_t time)
{
char *ts = ctime(&time);
ts[strlen(ts) - 1] = 0;
return ts;
}
static void measure(int fd)
{
time_t start_time;
int last_state;
time_t last_time;
int curr_state;
time_t curr_time = 0;
time_t time_diff;
time_t active_time = 0;
time_t sleep_time = 0;
time_t unknown_time = 0;
time_t total_time = 0;
int changes = 0;
float tmp;
printf("Starting measurements\n");
last_state = check_powermode(fd);
start_time = last_time = time(0);
printf(" System is in state %s\n\n", state_name(last_state));
while(!endit) {
sleep(1);
curr_state = check_powermode(fd);
if (curr_state != last_state || endit) {
changes++;
curr_time = time(0);
time_diff = curr_time - last_time;
if (last_state == 1) active_time += time_diff;
else if (last_state == 0) sleep_time += time_diff;
else unknown_time += time_diff;
last_state = curr_state;
last_time = curr_time;
printf("%s: State-change to %s\n", myctime(curr_time),
state_name(curr_state));
}
}
changes--; /* Compensate for SIGINT */
total_time = time(0) - start_time;
printf("\nTotal running time: %lus\n", curr_time - start_time);
printf(" State changed %d times\n", changes);
tmp = (float)sleep_time / (float)total_time * 100;
printf(" Time in sleep state: %lus (%.2f%%)\n", sleep_time, tmp);
tmp = (float)active_time / (float)total_time * 100;
printf(" Time in active state: %lus (%.2f%%)\n", active_time, tmp);
tmp = (float)unknown_time / (float)total_time * 100;
printf(" Time in unknown state: %lus (%.2f%%)\n", unknown_time, tmp);
}
static void ender(int s)
{
endit = 1;
}
static void usage(void)
{
puts("usage: dslm [-w <time>] <disk>");
exit(0);
}
int main(int argc, char **argv)
{
int fd;
char *disk = 0;
int settle_time = 60;
/* Parse the simple command-line */
if (argc == 2)
disk = argv[1];
else if (argc == 4) {
settle_time = atoi(argv[2]);
disk = argv[3];
} else
usage();
if (!(fd = open(disk, O_RDONLY|O_NONBLOCK))) {
printf("Can't open %s, because: %s\n", disk, strerror(errno));
exit(-1);
}
if (settle_time) {
printf("Waiting %d seconds for the system to settle down to "
"'normal'\n", settle_time);
sleep(settle_time);
} else
puts("Not waiting for system to settle down");
signal(SIGINT, ender);
measure(fd);
close(fd);
return 0;
}

View file

@ -779,4 +779,4 @@ Monitoring tool
---------------
Bartek Kania submitted this, it can be used to measure how much time your disk
spends spun up/down. See Documentation/laptops/dslm.c
spends spun up/down. See tools/laptop/dslm/dslm.c

View file

@ -1 +0,0 @@
subdir-y := mpssd

View file

@ -1 +0,0 @@
mpssd

View file

@ -1,21 +0,0 @@
ifndef CROSS_COMPILE
# List of programs to build
hostprogs-$(CONFIG_X86_64) := mpssd
mpssd-objs := mpssd.o sysfs.o
# Tell kbuild to always build the programs
always := $(hostprogs-y)
HOSTCFLAGS += -I$(objtree)/usr/include -I$(srctree)/tools/include
ifdef DEBUG
HOSTCFLAGS += -DDEBUG=$(DEBUG)
endif
HOSTLOADLIBES_mpssd := -lpthread
install:
install mpssd /usr/sbin/mpssd
install micctrl /usr/sbin/micctrl
endif

View file

@ -1,173 +0,0 @@
#!/bin/bash
# Intel MIC Platform Software Stack (MPSS)
#
# Copyright(c) 2013 Intel Corporation.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License, version 2, as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# The full GNU General Public License is included in this distribution in
# the file called "COPYING".
#
# Intel MIC User Space Tools.
#
# micctrl - Controls MIC boot/start/stop.
#
# chkconfig: 2345 95 05
# description: start MPSS stack processing.
#
### BEGIN INIT INFO
# Provides: micctrl
### END INIT INFO
# Source function library.
. /etc/init.d/functions
sysfs="/sys/class/mic"
_status()
{
f=$sysfs/$1
echo -e $1 state: "`cat $f/state`" shutdown_status: "`cat $f/shutdown_status`"
}
status()
{
if [ "`echo $1 | head -c3`" == "mic" ]; then
_status $1
return $?
fi
for f in $sysfs/*
do
_status `basename $f`
RETVAL=$?
[ $RETVAL -ne 0 ] && return $RETVAL
done
return 0
}
_reset()
{
f=$sysfs/$1
echo reset > $f/state
}
reset()
{
if [ "`echo $1 | head -c3`" == "mic" ]; then
_reset $1
return $?
fi
for f in $sysfs/*
do
_reset `basename $f`
RETVAL=$?
[ $RETVAL -ne 0 ] && return $RETVAL
done
return 0
}
_boot()
{
f=$sysfs/$1
echo "linux" > $f/bootmode
echo "mic/uos.img" > $f/firmware
echo "mic/$1.image" > $f/ramdisk
echo "boot" > $f/state
}
boot()
{
if [ "`echo $1 | head -c3`" == "mic" ]; then
_boot $1
return $?
fi
for f in $sysfs/*
do
_boot `basename $f`
RETVAL=$?
[ $RETVAL -ne 0 ] && return $RETVAL
done
return 0
}
_shutdown()
{
f=$sysfs/$1
echo shutdown > $f/state
}
shutdown()
{
if [ "`echo $1 | head -c3`" == "mic" ]; then
_shutdown $1
return $?
fi
for f in $sysfs/*
do
_shutdown `basename $f`
RETVAL=$?
[ $RETVAL -ne 0 ] && return $RETVAL
done
return 0
}
_wait()
{
f=$sysfs/$1
while [ "`cat $f/state`" != "offline" -a "`cat $f/state`" != "online" ]
do
sleep 1
echo -e "Waiting for $1 to go offline"
done
}
wait()
{
if [ "`echo $1 | head -c3`" == "mic" ]; then
_wait $1
return $?
fi
# Wait for the cards to go offline
for f in $sysfs/*
do
_wait `basename $f`
RETVAL=$?
[ $RETVAL -ne 0 ] && return $RETVAL
done
return 0
}
if [ ! -d "$sysfs" ]; then
echo -e $"Module unloaded "
exit 3
fi
case $1 in
-s)
status $2
;;
-r)
reset $2
;;
-b)
boot $2
;;
-S)
shutdown $2
;;
-w)
wait $2
;;
*)
echo $"Usage: $0 {-s (status) |-r (reset) |-b (boot) |-S (shutdown) |-w (wait)}"
exit 2
esac
exit $?

View file

@ -1,200 +0,0 @@
#!/bin/bash
# Intel MIC Platform Software Stack (MPSS)
#
# Copyright(c) 2013 Intel Corporation.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License, version 2, as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# The full GNU General Public License is included in this distribution in
# the file called "COPYING".
#
# Intel MIC User Space Tools.
#
# mpss Start mpssd.
#
# chkconfig: 2345 95 05
# description: start MPSS stack processing.
#
### BEGIN INIT INFO
# Provides: mpss
# Required-Start:
# Required-Stop:
# Short-Description: MPSS stack control
# Description: MPSS stack control
### END INIT INFO
# Source function library.
. /etc/init.d/functions
exec=/usr/sbin/mpssd
sysfs="/sys/class/mic"
mic_modules="mic_host mic_x100_dma scif vop"
start()
{
[ -x $exec ] || exit 5
if [ "`ps -e | awk '{print $4}' | grep mpssd | head -1`" = "mpssd" ]; then
echo -e $"MPSSD already running! "
success
echo
return 0
fi
echo -e $"Starting MPSS Stack"
echo -e $"Loading MIC drivers:" $mic_modules
modprobe -a $mic_modules
RETVAL=$?
if [ $RETVAL -ne 0 ]; then
failure
echo
return $RETVAL
fi
# Start the daemon
echo -n $"Starting MPSSD "
$exec
RETVAL=$?
if [ $RETVAL -ne 0 ]; then
failure
echo
return $RETVAL
fi
success
echo
sleep 5
# Boot the cards
micctrl -b
# Wait till ping works
for f in $sysfs/*
do
count=100
ipaddr=`cat $f/cmdline`
ipaddr=${ipaddr#*address,}
ipaddr=`echo $ipaddr | cut -d, -f1 | cut -d\; -f1`
while [ $count -ge 0 ]
do
echo -e "Pinging "`basename $f`" "
ping -c 1 $ipaddr &> /dev/null
RETVAL=$?
if [ $RETVAL -eq 0 ]; then
success
break
fi
sleep 1
count=`expr $count - 1`
done
[ $RETVAL -ne 0 ] && failure || success
echo
done
return $RETVAL
}
stop()
{
echo -e $"Shutting down MPSS Stack: "
# Bail out if module is unloaded
if [ ! -d "$sysfs" ]; then
echo -n $"Module unloaded "
success
echo
return 0
fi
# Shut down the cards.
micctrl -S
# Wait for the cards to go offline
for f in $sysfs/*
do
while [ "`cat $f/state`" != "ready" ]
do
sleep 1
echo -e "Waiting for "`basename $f`" to become ready"
done
done
# Display the status of the cards
micctrl -s
# Kill MPSSD now
echo -n $"Killing MPSSD"
killall -9 mpssd 2>/dev/null
RETVAL=$?
[ $RETVAL -ne 0 ] && failure || success
echo
return $RETVAL
}
restart()
{
stop
sleep 5
start
}
status()
{
micctrl -s
if [ "`ps -e | awk '{print $4}' | grep mpssd | head -n 1`" = "mpssd" ]; then
echo "mpssd is running"
else
echo "mpssd is stopped"
fi
return 0
}
unload()
{
if [ ! -d "$sysfs" ]; then
echo -n $"No MIC_HOST Module: "
success
echo
return
fi
stop
sleep 5
echo -n $"Removing MIC drivers:" $mic_modules
modprobe -r $mic_modules
RETVAL=$?
[ $RETVAL -ne 0 ] && failure || success
echo
return $RETVAL
}
case $1 in
start)
start
;;
stop)
stop
;;
restart)
restart
;;
status)
status
;;
unload)
unload
;;
*)
echo $"Usage: $0 {start|stop|restart|status|unload}"
exit 2
esac
exit $?

File diff suppressed because it is too large Load diff

View file

@ -1,103 +0,0 @@
/*
* Intel MIC Platform Software Stack (MPSS)
*
* Copyright(c) 2013 Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2, as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* The full GNU General Public License is included in this distribution in
* the file called "COPYING".
*
* Intel MIC User Space Tools.
*/
#ifndef _MPSSD_H_
#define _MPSSD_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
#include <libgen.h>
#include <pthread.h>
#include <stdarg.h>
#include <time.h>
#include <errno.h>
#include <sys/dir.h>
#include <sys/ioctl.h>
#include <sys/poll.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/utsname.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <pthread.h>
#include <signal.h>
#include <limits.h>
#include <syslog.h>
#include <getopt.h>
#include <net/if.h>
#include <linux/if_tun.h>
#include <linux/if_tun.h>
#include <linux/virtio_ids.h>
#define MICSYSFSDIR "/sys/class/mic"
#define LOGFILE_NAME "/var/log/mpssd"
#define PAGE_SIZE 4096
struct mic_console_info {
pthread_t console_thread;
int virtio_console_fd;
void *console_dp;
};
struct mic_net_info {
pthread_t net_thread;
int virtio_net_fd;
int tap_fd;
void *net_dp;
};
struct mic_virtblk_info {
pthread_t block_thread;
int virtio_block_fd;
void *block_dp;
volatile sig_atomic_t signaled;
char *backend_file;
int backend;
void *backend_addr;
long backend_size;
};
struct mic_info {
int id;
char *name;
pthread_t config_thread;
pthread_t init_thread;
pid_t pid;
struct mic_console_info mic_console;
struct mic_net_info mic_net;
struct mic_virtblk_info mic_virtblk;
int restart;
int boot_on_resume;
struct mic_info *next;
};
__attribute__((format(printf, 1, 2)))
void mpsslog(char *format, ...);
char *readsysfs(char *dir, char *entry);
int setsysfs(char *dir, char *entry, char *value);
#endif

View file

@ -1,102 +0,0 @@
/*
* Intel MIC Platform Software Stack (MPSS)
*
* Copyright(c) 2013 Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2, as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* The full GNU General Public License is included in this distribution in
* the file called "COPYING".
*
* Intel MIC User Space Tools.
*/
#include "mpssd.h"
#define PAGE_SIZE 4096
char *
readsysfs(char *dir, char *entry)
{
char filename[PATH_MAX];
char value[PAGE_SIZE];
char *string = NULL;
int fd;
int len;
if (dir == NULL)
snprintf(filename, PATH_MAX, "%s/%s", MICSYSFSDIR, entry);
else
snprintf(filename, PATH_MAX,
"%s/%s/%s", MICSYSFSDIR, dir, entry);
fd = open(filename, O_RDONLY);
if (fd < 0) {
mpsslog("Failed to open sysfs entry '%s': %s\n",
filename, strerror(errno));
return NULL;
}
len = read(fd, value, sizeof(value));
if (len < 0) {
mpsslog("Failed to read sysfs entry '%s': %s\n",
filename, strerror(errno));
goto readsys_ret;
}
if (len == 0)
goto readsys_ret;
value[len - 1] = '\0';
string = malloc(strlen(value) + 1);
if (string)
strcpy(string, value);
readsys_ret:
close(fd);
return string;
}
int
setsysfs(char *dir, char *entry, char *value)
{
char filename[PATH_MAX];
char *oldvalue;
int fd, ret = 0;
if (dir == NULL)
snprintf(filename, PATH_MAX, "%s/%s", MICSYSFSDIR, entry);
else
snprintf(filename, PATH_MAX, "%s/%s/%s",
MICSYSFSDIR, dir, entry);
oldvalue = readsysfs(dir, entry);
fd = open(filename, O_RDWR);
if (fd < 0) {
ret = errno;
mpsslog("Failed to open sysfs entry '%s': %s\n",
filename, strerror(errno));
goto done;
}
if (!oldvalue || strcmp(value, oldvalue)) {
if (write(fd, value, strlen(value)) < 0) {
ret = errno;
mpsslog("Failed to write new sysfs entry '%s': %s\n",
filename, strerror(errno));
}
}
close(fd);
done:
if (oldvalue)
free(oldvalue);
return ret;
}

View file

@ -1 +0,0 @@
subdir-y := mei

View file

@ -1 +0,0 @@
mei-amt-version

View file

@ -1,5 +0,0 @@
# List of programs to build
hostprogs-y := mei-amt-version
HOSTCFLAGS_mei-amt-version.o += -I$(objtree)/usr/include
# Tell kbuild to always build the programs
always := $(hostprogs-y)

View file

@ -1,2 +0,0 @@
TODO:
- Cleanup and split the timer function

View file

@ -1,479 +0,0 @@
/******************************************************************************
* Intel Management Engine Interface (Intel MEI) Linux driver
* Intel MEI Interface Header
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* Contact Information:
* Intel Corporation.
* linux-mei@linux.intel.com
* http://www.intel.com
*
* BSD LICENSE
*
* Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <errno.h>
#include <stdint.h>
#include <stdbool.h>
#include <bits/wordsize.h>
#include <linux/mei.h>
/*****************************************************************************
* Intel Management Engine Interface
*****************************************************************************/
#define mei_msg(_me, fmt, ARGS...) do { \
if (_me->verbose) \
fprintf(stderr, fmt, ##ARGS); \
} while (0)
#define mei_err(_me, fmt, ARGS...) do { \
fprintf(stderr, "Error: " fmt, ##ARGS); \
} while (0)
struct mei {
uuid_le guid;
bool initialized;
bool verbose;
unsigned int buf_size;
unsigned char prot_ver;
int fd;
};
static void mei_deinit(struct mei *cl)
{
if (cl->fd != -1)
close(cl->fd);
cl->fd = -1;
cl->buf_size = 0;
cl->prot_ver = 0;
cl->initialized = false;
}
static bool mei_init(struct mei *me, const uuid_le *guid,
unsigned char req_protocol_version, bool verbose)
{
int result;
struct mei_client *cl;
struct mei_connect_client_data data;
me->verbose = verbose;
me->fd = open("/dev/mei", O_RDWR);
if (me->fd == -1) {
mei_err(me, "Cannot establish a handle to the Intel MEI driver\n");
goto err;
}
memcpy(&me->guid, guid, sizeof(*guid));
memset(&data, 0, sizeof(data));
me->initialized = true;
memcpy(&data.in_client_uuid, &me->guid, sizeof(me->guid));
result = ioctl(me->fd, IOCTL_MEI_CONNECT_CLIENT, &data);
if (result) {
mei_err(me, "IOCTL_MEI_CONNECT_CLIENT receive message. err=%d\n", result);
goto err;
}
cl = &data.out_client_properties;
mei_msg(me, "max_message_length %d\n", cl->max_msg_length);
mei_msg(me, "protocol_version %d\n", cl->protocol_version);
if ((req_protocol_version > 0) &&
(cl->protocol_version != req_protocol_version)) {
mei_err(me, "Intel MEI protocol version not supported\n");
goto err;
}
me->buf_size = cl->max_msg_length;
me->prot_ver = cl->protocol_version;
return true;
err:
mei_deinit(me);
return false;
}
static ssize_t mei_recv_msg(struct mei *me, unsigned char *buffer,
ssize_t len, unsigned long timeout)
{
ssize_t rc;
mei_msg(me, "call read length = %zd\n", len);
rc = read(me->fd, buffer, len);
if (rc < 0) {
mei_err(me, "read failed with status %zd %s\n",
rc, strerror(errno));
mei_deinit(me);
} else {
mei_msg(me, "read succeeded with result %zd\n", rc);
}
return rc;
}
static ssize_t mei_send_msg(struct mei *me, const unsigned char *buffer,
ssize_t len, unsigned long timeout)
{
struct timeval tv;
ssize_t written;
ssize_t rc;
fd_set set;
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000000;
mei_msg(me, "call write length = %zd\n", len);
written = write(me->fd, buffer, len);
if (written < 0) {
rc = -errno;
mei_err(me, "write failed with status %zd %s\n",
written, strerror(errno));
goto out;
}
FD_ZERO(&set);
FD_SET(me->fd, &set);
rc = select(me->fd + 1 , &set, NULL, NULL, &tv);
if (rc > 0 && FD_ISSET(me->fd, &set)) {
mei_msg(me, "write success\n");
} else if (rc == 0) {
mei_err(me, "write failed on timeout with status\n");
goto out;
} else { /* rc < 0 */
mei_err(me, "write failed on select with status %zd\n", rc);
goto out;
}
rc = written;
out:
if (rc < 0)
mei_deinit(me);
return rc;
}
/***************************************************************************
* Intel Advanced Management Technology ME Client
***************************************************************************/
#define AMT_MAJOR_VERSION 1
#define AMT_MINOR_VERSION 1
#define AMT_STATUS_SUCCESS 0x0
#define AMT_STATUS_INTERNAL_ERROR 0x1
#define AMT_STATUS_NOT_READY 0x2
#define AMT_STATUS_INVALID_AMT_MODE 0x3
#define AMT_STATUS_INVALID_MESSAGE_LENGTH 0x4
#define AMT_STATUS_HOST_IF_EMPTY_RESPONSE 0x4000
#define AMT_STATUS_SDK_RESOURCES 0x1004
#define AMT_BIOS_VERSION_LEN 65
#define AMT_VERSIONS_NUMBER 50
#define AMT_UNICODE_STRING_LEN 20
struct amt_unicode_string {
uint16_t length;
char string[AMT_UNICODE_STRING_LEN];
} __attribute__((packed));
struct amt_version_type {
struct amt_unicode_string description;
struct amt_unicode_string version;
} __attribute__((packed));
struct amt_version {
uint8_t major;
uint8_t minor;
} __attribute__((packed));
struct amt_code_versions {
uint8_t bios[AMT_BIOS_VERSION_LEN];
uint32_t count;
struct amt_version_type versions[AMT_VERSIONS_NUMBER];
} __attribute__((packed));
/***************************************************************************
* Intel Advanced Management Technology Host Interface
***************************************************************************/
struct amt_host_if_msg_header {
struct amt_version version;
uint16_t _reserved;
uint32_t command;
uint32_t length;
} __attribute__((packed));
struct amt_host_if_resp_header {
struct amt_host_if_msg_header header;
uint32_t status;
unsigned char data[0];
} __attribute__((packed));
const uuid_le MEI_IAMTHIF = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d, \
0xac, 0xa8, 0x46, 0xe0, 0xff, 0x65, 0x81, 0x4c);
#define AMT_HOST_IF_CODE_VERSIONS_REQUEST 0x0400001A
#define AMT_HOST_IF_CODE_VERSIONS_RESPONSE 0x0480001A
const struct amt_host_if_msg_header CODE_VERSION_REQ = {
.version = {AMT_MAJOR_VERSION, AMT_MINOR_VERSION},
._reserved = 0,
.command = AMT_HOST_IF_CODE_VERSIONS_REQUEST,
.length = 0
};
struct amt_host_if {
struct mei mei_cl;
unsigned long send_timeout;
bool initialized;
};
static bool amt_host_if_init(struct amt_host_if *acmd,
unsigned long send_timeout, bool verbose)
{
acmd->send_timeout = (send_timeout) ? send_timeout : 20000;
acmd->initialized = mei_init(&acmd->mei_cl, &MEI_IAMTHIF, 0, verbose);
return acmd->initialized;
}
static void amt_host_if_deinit(struct amt_host_if *acmd)
{
mei_deinit(&acmd->mei_cl);
acmd->initialized = false;
}
static uint32_t amt_verify_code_versions(const struct amt_host_if_resp_header *resp)
{
uint32_t status = AMT_STATUS_SUCCESS;
struct amt_code_versions *code_ver;
size_t code_ver_len;
uint32_t ver_type_cnt;
uint32_t len;
uint32_t i;
code_ver = (struct amt_code_versions *)resp->data;
/* length - sizeof(status) */
code_ver_len = resp->header.length - sizeof(uint32_t);
ver_type_cnt = code_ver_len -
sizeof(code_ver->bios) -
sizeof(code_ver->count);
if (code_ver->count != ver_type_cnt / sizeof(struct amt_version_type)) {
status = AMT_STATUS_INTERNAL_ERROR;
goto out;
}
for (i = 0; i < code_ver->count; i++) {
len = code_ver->versions[i].description.length;
if (len > AMT_UNICODE_STRING_LEN) {
status = AMT_STATUS_INTERNAL_ERROR;
goto out;
}
len = code_ver->versions[i].version.length;
if (code_ver->versions[i].version.string[len] != '\0' ||
len != strlen(code_ver->versions[i].version.string)) {
status = AMT_STATUS_INTERNAL_ERROR;
goto out;
}
}
out:
return status;
}
static uint32_t amt_verify_response_header(uint32_t command,
const struct amt_host_if_msg_header *resp_hdr,
uint32_t response_size)
{
if (response_size < sizeof(struct amt_host_if_resp_header)) {
return AMT_STATUS_INTERNAL_ERROR;
} else if (response_size != (resp_hdr->length +
sizeof(struct amt_host_if_msg_header))) {
return AMT_STATUS_INTERNAL_ERROR;
} else if (resp_hdr->command != command) {
return AMT_STATUS_INTERNAL_ERROR;
} else if (resp_hdr->_reserved != 0) {
return AMT_STATUS_INTERNAL_ERROR;
} else if (resp_hdr->version.major != AMT_MAJOR_VERSION ||
resp_hdr->version.minor < AMT_MINOR_VERSION) {
return AMT_STATUS_INTERNAL_ERROR;
}
return AMT_STATUS_SUCCESS;
}
static uint32_t amt_host_if_call(struct amt_host_if *acmd,
const unsigned char *command, ssize_t command_sz,
uint8_t **read_buf, uint32_t rcmd,
unsigned int expected_sz)
{
uint32_t in_buf_sz;
uint32_t out_buf_sz;
ssize_t written;
uint32_t status;
struct amt_host_if_resp_header *msg_hdr;
in_buf_sz = acmd->mei_cl.buf_size;
*read_buf = (uint8_t *)malloc(sizeof(uint8_t) * in_buf_sz);
if (*read_buf == NULL)
return AMT_STATUS_SDK_RESOURCES;
memset(*read_buf, 0, in_buf_sz);
msg_hdr = (struct amt_host_if_resp_header *)*read_buf;
written = mei_send_msg(&acmd->mei_cl,
command, command_sz, acmd->send_timeout);
if (written != command_sz)
return AMT_STATUS_INTERNAL_ERROR;
out_buf_sz = mei_recv_msg(&acmd->mei_cl, *read_buf, in_buf_sz, 2000);
if (out_buf_sz <= 0)
return AMT_STATUS_HOST_IF_EMPTY_RESPONSE;
status = msg_hdr->status;
if (status != AMT_STATUS_SUCCESS)
return status;
status = amt_verify_response_header(rcmd,
&msg_hdr->header, out_buf_sz);
if (status != AMT_STATUS_SUCCESS)
return status;
if (expected_sz && expected_sz != out_buf_sz)
return AMT_STATUS_INTERNAL_ERROR;
return AMT_STATUS_SUCCESS;
}
static uint32_t amt_get_code_versions(struct amt_host_if *cmd,
struct amt_code_versions *versions)
{
struct amt_host_if_resp_header *response = NULL;
uint32_t status;
status = amt_host_if_call(cmd,
(const unsigned char *)&CODE_VERSION_REQ,
sizeof(CODE_VERSION_REQ),
(uint8_t **)&response,
AMT_HOST_IF_CODE_VERSIONS_RESPONSE, 0);
if (status != AMT_STATUS_SUCCESS)
goto out;
status = amt_verify_code_versions(response);
if (status != AMT_STATUS_SUCCESS)
goto out;
memcpy(versions, response->data, sizeof(struct amt_code_versions));
out:
if (response != NULL)
free(response);
return status;
}
/************************** end of amt_host_if_command ***********************/
int main(int argc, char **argv)
{
struct amt_code_versions ver;
struct amt_host_if acmd;
unsigned int i;
uint32_t status;
int ret;
bool verbose;
verbose = (argc > 1 && strcmp(argv[1], "-v") == 0);
if (!amt_host_if_init(&acmd, 5000, verbose)) {
ret = 1;
goto out;
}
status = amt_get_code_versions(&acmd, &ver);
amt_host_if_deinit(&acmd);
switch (status) {
case AMT_STATUS_HOST_IF_EMPTY_RESPONSE:
printf("Intel AMT: DISABLED\n");
ret = 0;
break;
case AMT_STATUS_SUCCESS:
printf("Intel AMT: ENABLED\n");
for (i = 0; i < ver.count; i++) {
printf("%s:\t%s\n", ver.versions[i].description.string,
ver.versions[i].version.string);
}
ret = 0;
break;
default:
printf("An error has occurred\n");
ret = 1;
break;
}
out:
return ret;
}

View file

@ -10,8 +10,6 @@ LICENSE.qlge
- GPLv2 for QLogic Linux qlge NIC Driver
LICENSE.qlcnic
- GPLv2 for QLogic Linux qlcnic NIC Driver
Makefile
- Makefile for docsrc.
PLIP.txt
- PLIP: The Parallel Line Internet Protocol device driver
README.ipw2100

View file

@ -1 +0,0 @@
subdir-y := timestamping

View file

@ -1,3 +0,0 @@
timestamping
txtimestamp
hwtstamp_config

View file

@ -1,14 +0,0 @@
# To compile, from the source root
#
# make headers_install
# make M=documentation
# List of programs to build
hostprogs-y := hwtstamp_config timestamping txtimestamp
# Tell kbuild to always build the programs
always := $(hostprogs-y)
HOSTCFLAGS_timestamping.o += -I$(objtree)/usr/include
HOSTCFLAGS_txtimestamp.o += -I$(objtree)/usr/include
HOSTCFLAGS_hwtstamp_config.o += -I$(objtree)/usr/include

View file

@ -1,134 +0,0 @@
/* Test program for SIOC{G,S}HWTSTAMP
* Copyright 2013 Solarflare Communications
* Author: Ben Hutchings
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/if.h>
#include <linux/net_tstamp.h>
#include <linux/sockios.h>
static int
lookup_value(const char **names, int size, const char *name)
{
int value;
for (value = 0; value < size; value++)
if (names[value] && strcasecmp(names[value], name) == 0)
return value;
return -1;
}
static const char *
lookup_name(const char **names, int size, int value)
{
return (value >= 0 && value < size) ? names[value] : NULL;
}
static void list_names(FILE *f, const char **names, int size)
{
int value;
for (value = 0; value < size; value++)
if (names[value])
fprintf(f, " %s\n", names[value]);
}
static const char *tx_types[] = {
#define TX_TYPE(name) [HWTSTAMP_TX_ ## name] = #name
TX_TYPE(OFF),
TX_TYPE(ON),
TX_TYPE(ONESTEP_SYNC)
#undef TX_TYPE
};
#define N_TX_TYPES ((int)(sizeof(tx_types) / sizeof(tx_types[0])))
static const char *rx_filters[] = {
#define RX_FILTER(name) [HWTSTAMP_FILTER_ ## name] = #name
RX_FILTER(NONE),
RX_FILTER(ALL),
RX_FILTER(SOME),
RX_FILTER(PTP_V1_L4_EVENT),
RX_FILTER(PTP_V1_L4_SYNC),
RX_FILTER(PTP_V1_L4_DELAY_REQ),
RX_FILTER(PTP_V2_L4_EVENT),
RX_FILTER(PTP_V2_L4_SYNC),
RX_FILTER(PTP_V2_L4_DELAY_REQ),
RX_FILTER(PTP_V2_L2_EVENT),
RX_FILTER(PTP_V2_L2_SYNC),
RX_FILTER(PTP_V2_L2_DELAY_REQ),
RX_FILTER(PTP_V2_EVENT),
RX_FILTER(PTP_V2_SYNC),
RX_FILTER(PTP_V2_DELAY_REQ),
#undef RX_FILTER
};
#define N_RX_FILTERS ((int)(sizeof(rx_filters) / sizeof(rx_filters[0])))
static void usage(void)
{
fputs("Usage: hwtstamp_config if_name [tx_type rx_filter]\n"
"tx_type is any of (case-insensitive):\n",
stderr);
list_names(stderr, tx_types, N_TX_TYPES);
fputs("rx_filter is any of (case-insensitive):\n", stderr);
list_names(stderr, rx_filters, N_RX_FILTERS);
}
int main(int argc, char **argv)
{
struct ifreq ifr;
struct hwtstamp_config config;
const char *name;
int sock;
if ((argc != 2 && argc != 4) || (strlen(argv[1]) >= IFNAMSIZ)) {
usage();
return 2;
}
if (argc == 4) {
config.flags = 0;
config.tx_type = lookup_value(tx_types, N_TX_TYPES, argv[2]);
config.rx_filter = lookup_value(rx_filters, N_RX_FILTERS, argv[3]);
if (config.tx_type < 0 || config.rx_filter < 0) {
usage();
return 2;
}
}
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
perror("socket");
return 1;
}
strcpy(ifr.ifr_name, argv[1]);
ifr.ifr_data = (caddr_t)&config;
if (ioctl(sock, (argc == 2) ? SIOCGHWTSTAMP : SIOCSHWTSTAMP, &ifr)) {
perror("ioctl");
return 1;
}
printf("flags = %#x\n", config.flags);
name = lookup_name(tx_types, N_TX_TYPES, config.tx_type);
if (name)
printf("tx_type = %s\n", name);
else
printf("tx_type = %d\n", config.tx_type);
name = lookup_name(rx_filters, N_RX_FILTERS, config.rx_filter);
if (name)
printf("rx_filter = %s\n", name);
else
printf("rx_filter = %d\n", config.rx_filter);
return 0;
}

View file

@ -1,528 +0,0 @@
/*
* This program demonstrates how the various time stamping features in
* the Linux kernel work. It emulates the behavior of a PTP
* implementation in stand-alone master mode by sending PTPv1 Sync
* multicasts once every second. It looks for similar packets, but
* beyond that doesn't actually implement PTP.
*
* Outgoing packets are time stamped with SO_TIMESTAMPING with or
* without hardware support.
*
* Incoming packets are time stamped with SO_TIMESTAMPING with or
* without hardware support, SIOCGSTAMP[NS] (per-socket time stamp) and
* SO_TIMESTAMP[NS].
*
* Copyright (C) 2009 Intel Corporation.
* Author: Patrick Ohly <patrick.ohly@intel.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <asm/types.h>
#include <linux/net_tstamp.h>
#include <linux/errqueue.h>
#ifndef SO_TIMESTAMPING
# define SO_TIMESTAMPING 37
# define SCM_TIMESTAMPING SO_TIMESTAMPING
#endif
#ifndef SO_TIMESTAMPNS
# define SO_TIMESTAMPNS 35
#endif
#ifndef SIOCGSTAMPNS
# define SIOCGSTAMPNS 0x8907
#endif
#ifndef SIOCSHWTSTAMP
# define SIOCSHWTSTAMP 0x89b0
#endif
static void usage(const char *error)
{
if (error)
printf("invalid option: %s\n", error);
printf("timestamping interface option*\n\n"
"Options:\n"
" IP_MULTICAST_LOOP - looping outgoing multicasts\n"
" SO_TIMESTAMP - normal software time stamping, ms resolution\n"
" SO_TIMESTAMPNS - more accurate software time stamping\n"
" SOF_TIMESTAMPING_TX_HARDWARE - hardware time stamping of outgoing packets\n"
" SOF_TIMESTAMPING_TX_SOFTWARE - software fallback for outgoing packets\n"
" SOF_TIMESTAMPING_RX_HARDWARE - hardware time stamping of incoming packets\n"
" SOF_TIMESTAMPING_RX_SOFTWARE - software fallback for incoming packets\n"
" SOF_TIMESTAMPING_SOFTWARE - request reporting of software time stamps\n"
" SOF_TIMESTAMPING_RAW_HARDWARE - request reporting of raw HW time stamps\n"
" SIOCGSTAMP - check last socket time stamp\n"
" SIOCGSTAMPNS - more accurate socket time stamp\n");
exit(1);
}
static void bail(const char *error)
{
printf("%s: %s\n", error, strerror(errno));
exit(1);
}
static const unsigned char sync[] = {
0x00, 0x01, 0x00, 0x01,
0x5f, 0x44, 0x46, 0x4c,
0x54, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x01, 0x01,
/* fake uuid */
0x00, 0x01,
0x02, 0x03, 0x04, 0x05,
0x00, 0x01, 0x00, 0x37,
0x00, 0x00, 0x00, 0x08,
0x00, 0x00, 0x00, 0x00,
0x49, 0x05, 0xcd, 0x01,
0x29, 0xb1, 0x8d, 0xb0,
0x00, 0x00, 0x00, 0x00,
0x00, 0x01,
/* fake uuid */
0x00, 0x01,
0x02, 0x03, 0x04, 0x05,
0x00, 0x00, 0x00, 0x37,
0x00, 0x00, 0x00, 0x04,
0x44, 0x46, 0x4c, 0x54,
0x00, 0x00, 0xf0, 0x60,
0x00, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0xf0, 0x60,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x04,
0x44, 0x46, 0x4c, 0x54,
0x00, 0x01,
/* fake uuid */
0x00, 0x01,
0x02, 0x03, 0x04, 0x05,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
};
static void sendpacket(int sock, struct sockaddr *addr, socklen_t addr_len)
{
struct timeval now;
int res;
res = sendto(sock, sync, sizeof(sync), 0,
addr, addr_len);
gettimeofday(&now, 0);
if (res < 0)
printf("%s: %s\n", "send", strerror(errno));
else
printf("%ld.%06ld: sent %d bytes\n",
(long)now.tv_sec, (long)now.tv_usec,
res);
}
static void printpacket(struct msghdr *msg, int res,
char *data,
int sock, int recvmsg_flags,
int siocgstamp, int siocgstampns)
{
struct sockaddr_in *from_addr = (struct sockaddr_in *)msg->msg_name;
struct cmsghdr *cmsg;
struct timeval tv;
struct timespec ts;
struct timeval now;
gettimeofday(&now, 0);
printf("%ld.%06ld: received %s data, %d bytes from %s, %zu bytes control messages\n",
(long)now.tv_sec, (long)now.tv_usec,
(recvmsg_flags & MSG_ERRQUEUE) ? "error" : "regular",
res,
inet_ntoa(from_addr->sin_addr),
msg->msg_controllen);
for (cmsg = CMSG_FIRSTHDR(msg);
cmsg;
cmsg = CMSG_NXTHDR(msg, cmsg)) {
printf(" cmsg len %zu: ", cmsg->cmsg_len);
switch (cmsg->cmsg_level) {
case SOL_SOCKET:
printf("SOL_SOCKET ");
switch (cmsg->cmsg_type) {
case SO_TIMESTAMP: {
struct timeval *stamp =
(struct timeval *)CMSG_DATA(cmsg);
printf("SO_TIMESTAMP %ld.%06ld",
(long)stamp->tv_sec,
(long)stamp->tv_usec);
break;
}
case SO_TIMESTAMPNS: {
struct timespec *stamp =
(struct timespec *)CMSG_DATA(cmsg);
printf("SO_TIMESTAMPNS %ld.%09ld",
(long)stamp->tv_sec,
(long)stamp->tv_nsec);
break;
}
case SO_TIMESTAMPING: {
struct timespec *stamp =
(struct timespec *)CMSG_DATA(cmsg);
printf("SO_TIMESTAMPING ");
printf("SW %ld.%09ld ",
(long)stamp->tv_sec,
(long)stamp->tv_nsec);
stamp++;
/* skip deprecated HW transformed */
stamp++;
printf("HW raw %ld.%09ld",
(long)stamp->tv_sec,
(long)stamp->tv_nsec);
break;
}
default:
printf("type %d", cmsg->cmsg_type);
break;
}
break;
case IPPROTO_IP:
printf("IPPROTO_IP ");
switch (cmsg->cmsg_type) {
case IP_RECVERR: {
struct sock_extended_err *err =
(struct sock_extended_err *)CMSG_DATA(cmsg);
printf("IP_RECVERR ee_errno '%s' ee_origin %d => %s",
strerror(err->ee_errno),
err->ee_origin,
#ifdef SO_EE_ORIGIN_TIMESTAMPING
err->ee_origin == SO_EE_ORIGIN_TIMESTAMPING ?
"bounced packet" : "unexpected origin"
#else
"probably SO_EE_ORIGIN_TIMESTAMPING"
#endif
);
if (res < sizeof(sync))
printf(" => truncated data?!");
else if (!memcmp(sync, data + res - sizeof(sync),
sizeof(sync)))
printf(" => GOT OUR DATA BACK (HURRAY!)");
break;
}
case IP_PKTINFO: {
struct in_pktinfo *pktinfo =
(struct in_pktinfo *)CMSG_DATA(cmsg);
printf("IP_PKTINFO interface index %u",
pktinfo->ipi_ifindex);
break;
}
default:
printf("type %d", cmsg->cmsg_type);
break;
}
break;
default:
printf("level %d type %d",
cmsg->cmsg_level,
cmsg->cmsg_type);
break;
}
printf("\n");
}
if (siocgstamp) {
if (ioctl(sock, SIOCGSTAMP, &tv))
printf(" %s: %s\n", "SIOCGSTAMP", strerror(errno));
else
printf("SIOCGSTAMP %ld.%06ld\n",
(long)tv.tv_sec,
(long)tv.tv_usec);
}
if (siocgstampns) {
if (ioctl(sock, SIOCGSTAMPNS, &ts))
printf(" %s: %s\n", "SIOCGSTAMPNS", strerror(errno));
else
printf("SIOCGSTAMPNS %ld.%09ld\n",
(long)ts.tv_sec,
(long)ts.tv_nsec);
}
}
static void recvpacket(int sock, int recvmsg_flags,
int siocgstamp, int siocgstampns)
{
char data[256];
struct msghdr msg;
struct iovec entry;
struct sockaddr_in from_addr;
struct {
struct cmsghdr cm;
char control[512];
} control;
int res;
memset(&msg, 0, sizeof(msg));
msg.msg_iov = &entry;
msg.msg_iovlen = 1;
entry.iov_base = data;
entry.iov_len = sizeof(data);
msg.msg_name = (caddr_t)&from_addr;
msg.msg_namelen = sizeof(from_addr);
msg.msg_control = &control;
msg.msg_controllen = sizeof(control);
res = recvmsg(sock, &msg, recvmsg_flags|MSG_DONTWAIT);
if (res < 0) {
printf("%s %s: %s\n",
"recvmsg",
(recvmsg_flags & MSG_ERRQUEUE) ? "error" : "regular",
strerror(errno));
} else {
printpacket(&msg, res, data,
sock, recvmsg_flags,
siocgstamp, siocgstampns);
}
}
int main(int argc, char **argv)
{
int so_timestamping_flags = 0;
int so_timestamp = 0;
int so_timestampns = 0;
int siocgstamp = 0;
int siocgstampns = 0;
int ip_multicast_loop = 0;
char *interface;
int i;
int enabled = 1;
int sock;
struct ifreq device;
struct ifreq hwtstamp;
struct hwtstamp_config hwconfig, hwconfig_requested;
struct sockaddr_in addr;
struct ip_mreq imr;
struct in_addr iaddr;
int val;
socklen_t len;
struct timeval next;
if (argc < 2)
usage(0);
interface = argv[1];
for (i = 2; i < argc; i++) {
if (!strcasecmp(argv[i], "SO_TIMESTAMP"))
so_timestamp = 1;
else if (!strcasecmp(argv[i], "SO_TIMESTAMPNS"))
so_timestampns = 1;
else if (!strcasecmp(argv[i], "SIOCGSTAMP"))
siocgstamp = 1;
else if (!strcasecmp(argv[i], "SIOCGSTAMPNS"))
siocgstampns = 1;
else if (!strcasecmp(argv[i], "IP_MULTICAST_LOOP"))
ip_multicast_loop = 1;
else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_TX_HARDWARE"))
so_timestamping_flags |= SOF_TIMESTAMPING_TX_HARDWARE;
else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_TX_SOFTWARE"))
so_timestamping_flags |= SOF_TIMESTAMPING_TX_SOFTWARE;
else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_RX_HARDWARE"))
so_timestamping_flags |= SOF_TIMESTAMPING_RX_HARDWARE;
else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_RX_SOFTWARE"))
so_timestamping_flags |= SOF_TIMESTAMPING_RX_SOFTWARE;
else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_SOFTWARE"))
so_timestamping_flags |= SOF_TIMESTAMPING_SOFTWARE;
else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_RAW_HARDWARE"))
so_timestamping_flags |= SOF_TIMESTAMPING_RAW_HARDWARE;
else
usage(argv[i]);
}
sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock < 0)
bail("socket");
memset(&device, 0, sizeof(device));
strncpy(device.ifr_name, interface, sizeof(device.ifr_name));
if (ioctl(sock, SIOCGIFADDR, &device) < 0)
bail("getting interface IP address");
memset(&hwtstamp, 0, sizeof(hwtstamp));
strncpy(hwtstamp.ifr_name, interface, sizeof(hwtstamp.ifr_name));
hwtstamp.ifr_data = (void *)&hwconfig;
memset(&hwconfig, 0, sizeof(hwconfig));
hwconfig.tx_type =
(so_timestamping_flags & SOF_TIMESTAMPING_TX_HARDWARE) ?
HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF;
hwconfig.rx_filter =
(so_timestamping_flags & SOF_TIMESTAMPING_RX_HARDWARE) ?
HWTSTAMP_FILTER_PTP_V1_L4_SYNC : HWTSTAMP_FILTER_NONE;
hwconfig_requested = hwconfig;
if (ioctl(sock, SIOCSHWTSTAMP, &hwtstamp) < 0) {
if ((errno == EINVAL || errno == ENOTSUP) &&
hwconfig_requested.tx_type == HWTSTAMP_TX_OFF &&
hwconfig_requested.rx_filter == HWTSTAMP_FILTER_NONE)
printf("SIOCSHWTSTAMP: disabling hardware time stamping not possible\n");
else
bail("SIOCSHWTSTAMP");
}
printf("SIOCSHWTSTAMP: tx_type %d requested, got %d; rx_filter %d requested, got %d\n",
hwconfig_requested.tx_type, hwconfig.tx_type,
hwconfig_requested.rx_filter, hwconfig.rx_filter);
/* bind to PTP port */
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(319 /* PTP event port */);
if (bind(sock,
(struct sockaddr *)&addr,
sizeof(struct sockaddr_in)) < 0)
bail("bind");
/* set multicast group for outgoing packets */
inet_aton("224.0.1.130", &iaddr); /* alternate PTP domain 1 */
addr.sin_addr = iaddr;
imr.imr_multiaddr.s_addr = iaddr.s_addr;
imr.imr_interface.s_addr =
((struct sockaddr_in *)&device.ifr_addr)->sin_addr.s_addr;
if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF,
&imr.imr_interface.s_addr, sizeof(struct in_addr)) < 0)
bail("set multicast");
/* join multicast group, loop our own packet */
if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
&imr, sizeof(struct ip_mreq)) < 0)
bail("join multicast group");
if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP,
&ip_multicast_loop, sizeof(enabled)) < 0) {
bail("loop multicast");
}
/* set socket options for time stamping */
if (so_timestamp &&
setsockopt(sock, SOL_SOCKET, SO_TIMESTAMP,
&enabled, sizeof(enabled)) < 0)
bail("setsockopt SO_TIMESTAMP");
if (so_timestampns &&
setsockopt(sock, SOL_SOCKET, SO_TIMESTAMPNS,
&enabled, sizeof(enabled)) < 0)
bail("setsockopt SO_TIMESTAMPNS");
if (so_timestamping_flags &&
setsockopt(sock, SOL_SOCKET, SO_TIMESTAMPING,
&so_timestamping_flags,
sizeof(so_timestamping_flags)) < 0)
bail("setsockopt SO_TIMESTAMPING");
/* request IP_PKTINFO for debugging purposes */
if (setsockopt(sock, SOL_IP, IP_PKTINFO,
&enabled, sizeof(enabled)) < 0)
printf("%s: %s\n", "setsockopt IP_PKTINFO", strerror(errno));
/* verify socket options */
len = sizeof(val);
if (getsockopt(sock, SOL_SOCKET, SO_TIMESTAMP, &val, &len) < 0)
printf("%s: %s\n", "getsockopt SO_TIMESTAMP", strerror(errno));
else
printf("SO_TIMESTAMP %d\n", val);
if (getsockopt(sock, SOL_SOCKET, SO_TIMESTAMPNS, &val, &len) < 0)
printf("%s: %s\n", "getsockopt SO_TIMESTAMPNS",
strerror(errno));
else
printf("SO_TIMESTAMPNS %d\n", val);
if (getsockopt(sock, SOL_SOCKET, SO_TIMESTAMPING, &val, &len) < 0) {
printf("%s: %s\n", "getsockopt SO_TIMESTAMPING",
strerror(errno));
} else {
printf("SO_TIMESTAMPING %d\n", val);
if (val != so_timestamping_flags)
printf(" not the expected value %d\n",
so_timestamping_flags);
}
/* send packets forever every five seconds */
gettimeofday(&next, 0);
next.tv_sec = (next.tv_sec + 1) / 5 * 5;
next.tv_usec = 0;
while (1) {
struct timeval now;
struct timeval delta;
long delta_us;
int res;
fd_set readfs, errorfs;
gettimeofday(&now, 0);
delta_us = (long)(next.tv_sec - now.tv_sec) * 1000000 +
(long)(next.tv_usec - now.tv_usec);
if (delta_us > 0) {
/* continue waiting for timeout or data */
delta.tv_sec = delta_us / 1000000;
delta.tv_usec = delta_us % 1000000;
FD_ZERO(&readfs);
FD_ZERO(&errorfs);
FD_SET(sock, &readfs);
FD_SET(sock, &errorfs);
printf("%ld.%06ld: select %ldus\n",
(long)now.tv_sec, (long)now.tv_usec,
delta_us);
res = select(sock + 1, &readfs, 0, &errorfs, &delta);
gettimeofday(&now, 0);
printf("%ld.%06ld: select returned: %d, %s\n",
(long)now.tv_sec, (long)now.tv_usec,
res,
res < 0 ? strerror(errno) : "success");
if (res > 0) {
if (FD_ISSET(sock, &readfs))
printf("ready for reading\n");
if (FD_ISSET(sock, &errorfs))
printf("has error\n");
recvpacket(sock, 0,
siocgstamp,
siocgstampns);
recvpacket(sock, MSG_ERRQUEUE,
siocgstamp,
siocgstampns);
}
} else {
/* write one packet */
sendpacket(sock,
(struct sockaddr *)&addr,
sizeof(addr));
next.tv_sec += 5;
continue;
}
}
return 0;
}

View file

@ -1,549 +0,0 @@
/*
* Copyright 2014 Google Inc.
* Author: willemb@google.com (Willem de Bruijn)
*
* Test software tx timestamping, including
*
* - SCHED, SND and ACK timestamps
* - RAW, UDP and TCP
* - IPv4 and IPv6
* - various packet sizes (to test GSO and TSO)
*
* Consult the command line arguments for help on running
* the various testcases.
*
* This test requires a dummy TCP server.
* A simple `nc6 [-u] -l -p $DESTPORT` will do
*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*/
#define _GNU_SOURCE
#include <arpa/inet.h>
#include <asm/types.h>
#include <error.h>
#include <errno.h>
#include <inttypes.h>
#include <linux/errqueue.h>
#include <linux/if_ether.h>
#include <linux/net_tstamp.h>
#include <netdb.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <netinet/tcp.h>
#include <netpacket/packet.h>
#include <poll.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
/* command line parameters */
static int cfg_proto = SOCK_STREAM;
static int cfg_ipproto = IPPROTO_TCP;
static int cfg_num_pkts = 4;
static int do_ipv4 = 1;
static int do_ipv6 = 1;
static int cfg_payload_len = 10;
static bool cfg_show_payload;
static bool cfg_do_pktinfo;
static bool cfg_loop_nodata;
static uint16_t dest_port = 9000;
static struct sockaddr_in daddr;
static struct sockaddr_in6 daddr6;
static struct timespec ts_prev;
static void __print_timestamp(const char *name, struct timespec *cur,
uint32_t key, int payload_len)
{
if (!(cur->tv_sec | cur->tv_nsec))
return;
fprintf(stderr, " %s: %lu s %lu us (seq=%u, len=%u)",
name, cur->tv_sec, cur->tv_nsec / 1000,
key, payload_len);
if ((ts_prev.tv_sec | ts_prev.tv_nsec)) {
int64_t cur_ms, prev_ms;
cur_ms = (long) cur->tv_sec * 1000 * 1000;
cur_ms += cur->tv_nsec / 1000;
prev_ms = (long) ts_prev.tv_sec * 1000 * 1000;
prev_ms += ts_prev.tv_nsec / 1000;
fprintf(stderr, " (%+" PRId64 " us)", cur_ms - prev_ms);
}
ts_prev = *cur;
fprintf(stderr, "\n");
}
static void print_timestamp_usr(void)
{
struct timespec ts;
struct timeval tv; /* avoid dependency on -lrt */
gettimeofday(&tv, NULL);
ts.tv_sec = tv.tv_sec;
ts.tv_nsec = tv.tv_usec * 1000;
__print_timestamp(" USR", &ts, 0, 0);
}
static void print_timestamp(struct scm_timestamping *tss, int tstype,
int tskey, int payload_len)
{
const char *tsname;
switch (tstype) {
case SCM_TSTAMP_SCHED:
tsname = " ENQ";
break;
case SCM_TSTAMP_SND:
tsname = " SND";
break;
case SCM_TSTAMP_ACK:
tsname = " ACK";
break;
default:
error(1, 0, "unknown timestamp type: %u",
tstype);
}
__print_timestamp(tsname, &tss->ts[0], tskey, payload_len);
}
/* TODO: convert to check_and_print payload once API is stable */
static void print_payload(char *data, int len)
{
int i;
if (!len)
return;
if (len > 70)
len = 70;
fprintf(stderr, "payload: ");
for (i = 0; i < len; i++)
fprintf(stderr, "%02hhx ", data[i]);
fprintf(stderr, "\n");
}
static void print_pktinfo(int family, int ifindex, void *saddr, void *daddr)
{
char sa[INET6_ADDRSTRLEN], da[INET6_ADDRSTRLEN];
fprintf(stderr, " pktinfo: ifindex=%u src=%s dst=%s\n",
ifindex,
saddr ? inet_ntop(family, saddr, sa, sizeof(sa)) : "unknown",
daddr ? inet_ntop(family, daddr, da, sizeof(da)) : "unknown");
}
static void __poll(int fd)
{
struct pollfd pollfd;
int ret;
memset(&pollfd, 0, sizeof(pollfd));
pollfd.fd = fd;
ret = poll(&pollfd, 1, 100);
if (ret != 1)
error(1, errno, "poll");
}
static void __recv_errmsg_cmsg(struct msghdr *msg, int payload_len)
{
struct sock_extended_err *serr = NULL;
struct scm_timestamping *tss = NULL;
struct cmsghdr *cm;
int batch = 0;
for (cm = CMSG_FIRSTHDR(msg);
cm && cm->cmsg_len;
cm = CMSG_NXTHDR(msg, cm)) {
if (cm->cmsg_level == SOL_SOCKET &&
cm->cmsg_type == SCM_TIMESTAMPING) {
tss = (void *) CMSG_DATA(cm);
} else if ((cm->cmsg_level == SOL_IP &&
cm->cmsg_type == IP_RECVERR) ||
(cm->cmsg_level == SOL_IPV6 &&
cm->cmsg_type == IPV6_RECVERR)) {
serr = (void *) CMSG_DATA(cm);
if (serr->ee_errno != ENOMSG ||
serr->ee_origin != SO_EE_ORIGIN_TIMESTAMPING) {
fprintf(stderr, "unknown ip error %d %d\n",
serr->ee_errno,
serr->ee_origin);
serr = NULL;
}
} else if (cm->cmsg_level == SOL_IP &&
cm->cmsg_type == IP_PKTINFO) {
struct in_pktinfo *info = (void *) CMSG_DATA(cm);
print_pktinfo(AF_INET, info->ipi_ifindex,
&info->ipi_spec_dst, &info->ipi_addr);
} else if (cm->cmsg_level == SOL_IPV6 &&
cm->cmsg_type == IPV6_PKTINFO) {
struct in6_pktinfo *info6 = (void *) CMSG_DATA(cm);
print_pktinfo(AF_INET6, info6->ipi6_ifindex,
NULL, &info6->ipi6_addr);
} else
fprintf(stderr, "unknown cmsg %d,%d\n",
cm->cmsg_level, cm->cmsg_type);
if (serr && tss) {
print_timestamp(tss, serr->ee_info, serr->ee_data,
payload_len);
serr = NULL;
tss = NULL;
batch++;
}
}
if (batch > 1)
fprintf(stderr, "batched %d timestamps\n", batch);
}
static int recv_errmsg(int fd)
{
static char ctrl[1024 /* overprovision*/];
static struct msghdr msg;
struct iovec entry;
static char *data;
int ret = 0;
data = malloc(cfg_payload_len);
if (!data)
error(1, 0, "malloc");
memset(&msg, 0, sizeof(msg));
memset(&entry, 0, sizeof(entry));
memset(ctrl, 0, sizeof(ctrl));
entry.iov_base = data;
entry.iov_len = cfg_payload_len;
msg.msg_iov = &entry;
msg.msg_iovlen = 1;
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_control = ctrl;
msg.msg_controllen = sizeof(ctrl);
ret = recvmsg(fd, &msg, MSG_ERRQUEUE);
if (ret == -1 && errno != EAGAIN)
error(1, errno, "recvmsg");
if (ret >= 0) {
__recv_errmsg_cmsg(&msg, ret);
if (cfg_show_payload)
print_payload(data, cfg_payload_len);
}
free(data);
return ret == -1;
}
static void do_test(int family, unsigned int opt)
{
char *buf;
int fd, i, val = 1, total_len;
if (family == AF_INET6 && cfg_proto != SOCK_STREAM) {
/* due to lack of checksum generation code */
fprintf(stderr, "test: skipping datagram over IPv6\n");
return;
}
total_len = cfg_payload_len;
if (cfg_proto == SOCK_RAW) {
total_len += sizeof(struct udphdr);
if (cfg_ipproto == IPPROTO_RAW)
total_len += sizeof(struct iphdr);
}
buf = malloc(total_len);
if (!buf)
error(1, 0, "malloc");
fd = socket(family, cfg_proto, cfg_ipproto);
if (fd < 0)
error(1, errno, "socket");
if (cfg_proto == SOCK_STREAM) {
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
(char*) &val, sizeof(val)))
error(1, 0, "setsockopt no nagle");
if (family == PF_INET) {
if (connect(fd, (void *) &daddr, sizeof(daddr)))
error(1, errno, "connect ipv4");
} else {
if (connect(fd, (void *) &daddr6, sizeof(daddr6)))
error(1, errno, "connect ipv6");
}
}
if (cfg_do_pktinfo) {
if (family == AF_INET6) {
if (setsockopt(fd, SOL_IPV6, IPV6_RECVPKTINFO,
&val, sizeof(val)))
error(1, errno, "setsockopt pktinfo ipv6");
} else {
if (setsockopt(fd, SOL_IP, IP_PKTINFO,
&val, sizeof(val)))
error(1, errno, "setsockopt pktinfo ipv4");
}
}
opt |= SOF_TIMESTAMPING_SOFTWARE |
SOF_TIMESTAMPING_OPT_CMSG |
SOF_TIMESTAMPING_OPT_ID;
if (cfg_loop_nodata)
opt |= SOF_TIMESTAMPING_OPT_TSONLY;
if (setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING,
(char *) &opt, sizeof(opt)))
error(1, 0, "setsockopt timestamping");
for (i = 0; i < cfg_num_pkts; i++) {
memset(&ts_prev, 0, sizeof(ts_prev));
memset(buf, 'a' + i, total_len);
if (cfg_proto == SOCK_RAW) {
struct udphdr *udph;
int off = 0;
if (cfg_ipproto == IPPROTO_RAW) {
struct iphdr *iph = (void *) buf;
memset(iph, 0, sizeof(*iph));
iph->ihl = 5;
iph->version = 4;
iph->ttl = 2;
iph->daddr = daddr.sin_addr.s_addr;
iph->protocol = IPPROTO_UDP;
/* kernel writes saddr, csum, len */
off = sizeof(*iph);
}
udph = (void *) buf + off;
udph->source = ntohs(9000); /* random spoof */
udph->dest = ntohs(dest_port);
udph->len = ntohs(sizeof(*udph) + cfg_payload_len);
udph->check = 0; /* not allowed for IPv6 */
}
print_timestamp_usr();
if (cfg_proto != SOCK_STREAM) {
if (family == PF_INET)
val = sendto(fd, buf, total_len, 0, (void *) &daddr, sizeof(daddr));
else
val = sendto(fd, buf, total_len, 0, (void *) &daddr6, sizeof(daddr6));
} else {
val = send(fd, buf, cfg_payload_len, 0);
}
if (val != total_len)
error(1, errno, "send");
/* wait for all errors to be queued, else ACKs arrive OOO */
usleep(50 * 1000);
__poll(fd);
while (!recv_errmsg(fd)) {}
}
if (close(fd))
error(1, errno, "close");
free(buf);
usleep(400 * 1000);
}
static void __attribute__((noreturn)) usage(const char *filepath)
{
fprintf(stderr, "\nUsage: %s [options] hostname\n"
"\nwhere options are:\n"
" -4: only IPv4\n"
" -6: only IPv6\n"
" -h: show this message\n"
" -I: request PKTINFO\n"
" -l N: send N bytes at a time\n"
" -n: set no-payload option\n"
" -r: use raw\n"
" -R: use raw (IP_HDRINCL)\n"
" -p N: connect to port N\n"
" -u: use udp\n"
" -x: show payload (up to 70 bytes)\n",
filepath);
exit(1);
}
static void parse_opt(int argc, char **argv)
{
int proto_count = 0;
char c;
while ((c = getopt(argc, argv, "46hIl:np:rRux")) != -1) {
switch (c) {
case '4':
do_ipv6 = 0;
break;
case '6':
do_ipv4 = 0;
break;
case 'I':
cfg_do_pktinfo = true;
break;
case 'n':
cfg_loop_nodata = true;
break;
case 'r':
proto_count++;
cfg_proto = SOCK_RAW;
cfg_ipproto = IPPROTO_UDP;
break;
case 'R':
proto_count++;
cfg_proto = SOCK_RAW;
cfg_ipproto = IPPROTO_RAW;
break;
case 'u':
proto_count++;
cfg_proto = SOCK_DGRAM;
cfg_ipproto = IPPROTO_UDP;
break;
case 'l':
cfg_payload_len = strtoul(optarg, NULL, 10);
break;
case 'p':
dest_port = strtoul(optarg, NULL, 10);
break;
case 'x':
cfg_show_payload = true;
break;
case 'h':
default:
usage(argv[0]);
}
}
if (!cfg_payload_len)
error(1, 0, "payload may not be nonzero");
if (cfg_proto != SOCK_STREAM && cfg_payload_len > 1472)
error(1, 0, "udp packet might exceed expected MTU");
if (!do_ipv4 && !do_ipv6)
error(1, 0, "pass -4 or -6, not both");
if (proto_count > 1)
error(1, 0, "pass -r, -R or -u, not multiple");
if (optind != argc - 1)
error(1, 0, "missing required hostname argument");
}
static void resolve_hostname(const char *hostname)
{
struct addrinfo *addrs, *cur;
int have_ipv4 = 0, have_ipv6 = 0;
if (getaddrinfo(hostname, NULL, NULL, &addrs))
error(1, errno, "getaddrinfo");
cur = addrs;
while (cur && !have_ipv4 && !have_ipv6) {
if (!have_ipv4 && cur->ai_family == AF_INET) {
memcpy(&daddr, cur->ai_addr, sizeof(daddr));
daddr.sin_port = htons(dest_port);
have_ipv4 = 1;
}
else if (!have_ipv6 && cur->ai_family == AF_INET6) {
memcpy(&daddr6, cur->ai_addr, sizeof(daddr6));
daddr6.sin6_port = htons(dest_port);
have_ipv6 = 1;
}
cur = cur->ai_next;
}
if (addrs)
freeaddrinfo(addrs);
do_ipv4 &= have_ipv4;
do_ipv6 &= have_ipv6;
}
static void do_main(int family)
{
fprintf(stderr, "family: %s\n",
family == PF_INET ? "INET" : "INET6");
fprintf(stderr, "test SND\n");
do_test(family, SOF_TIMESTAMPING_TX_SOFTWARE);
fprintf(stderr, "test ENQ\n");
do_test(family, SOF_TIMESTAMPING_TX_SCHED);
fprintf(stderr, "test ENQ + SND\n");
do_test(family, SOF_TIMESTAMPING_TX_SCHED |
SOF_TIMESTAMPING_TX_SOFTWARE);
if (cfg_proto == SOCK_STREAM) {
fprintf(stderr, "\ntest ACK\n");
do_test(family, SOF_TIMESTAMPING_TX_ACK);
fprintf(stderr, "\ntest SND + ACK\n");
do_test(family, SOF_TIMESTAMPING_TX_SOFTWARE |
SOF_TIMESTAMPING_TX_ACK);
fprintf(stderr, "\ntest ENQ + SND + ACK\n");
do_test(family, SOF_TIMESTAMPING_TX_SCHED |
SOF_TIMESTAMPING_TX_SOFTWARE |
SOF_TIMESTAMPING_TX_ACK);
}
}
const char *sock_names[] = { NULL, "TCP", "UDP", "RAW" };
int main(int argc, char **argv)
{
if (argc == 1)
usage(argv[0]);
parse_opt(argc, argv);
resolve_hostname(argv[argc - 1]);
fprintf(stderr, "protocol: %s\n", sock_names[cfg_proto]);
fprintf(stderr, "payload: %u\n", cfg_payload_len);
fprintf(stderr, "server port: %u\n", dest_port);
fprintf(stderr, "\n");
if (do_ipv4)
do_main(PF_INET);
if (do_ipv6)
do_main(PF_INET6);
return 0;
}

View file

@ -1 +0,0 @@
crc32hash

View file

@ -1,7 +0,0 @@
# List of programs to build
hostprogs-y := crc32hash
# Tell kbuild to always build the programs
always := $(hostprogs-y)
HOSTCFLAGS_crc32hash.o += -I$(objtree)/usr/include

View file

@ -1,32 +0,0 @@
/* crc32hash.c - derived from linux/lib/crc32.c, GNU GPL v2 */
/* Usage example:
$ ./crc32hash "Dual Speed"
*/
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
static unsigned int crc32(unsigned char const *p, unsigned int len)
{
int i;
unsigned int crc = 0;
while (len--) {
crc ^= *p++;
for (i = 0; i < 8; i++)
crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0);
}
return crc;
}
int main(int argc, char **argv) {
unsigned int result;
if (argc != 2) {
printf("no string passed as argument\n");
return -1;
}
result = crc32((unsigned char const *)argv[1], strlen(argv[1]));
printf("0x%x\n", result);
return 0;
}

View file

@ -27,7 +27,7 @@ pcmcia:m0149cC1ABf06pfn00fn00pa725B842DpbF1EFEE84pc0877B627pd00000000
The hex value after "pa" is the hash of product ID string 1, after "pb" for
string 2 and so on.
Alternatively, you can use crc32hash (see Documentation/pcmcia/crc32hash.c)
Alternatively, you can use crc32hash (see tools/pcmcia/crc32hash.c)
to determine the crc32 hash. Simply pass the string you want to evaluate
as argument to this program, e.g.:
$ ./crc32hash "Dual Speed"
$ tools/pcmcia/crc32hash "Dual Speed"

View file

@ -1,3 +0,0 @@
disable-tsc-ctxt-sw-stress-test
disable-tsc-on-off-stress-test
disable-tsc-test

View file

@ -1,10 +0,0 @@
ifndef CROSS_COMPILE
# List of programs to build
hostprogs-$(CONFIG_X86) := disable-tsc-ctxt-sw-stress-test disable-tsc-on-off-stress-test disable-tsc-test
# Tell kbuild to always build the programs
always := $(hostprogs-y)
HOSTCFLAGS_disable-tsc-ctxt-sw-stress-test.o += -I$(objtree)/usr/include
HOSTCFLAGS_disable-tsc-on-off-stress-test.o += -I$(objtree)/usr/include
HOSTCFLAGS_disable-tsc-test.o += -I$(objtree)/usr/include
endif

View file

@ -1,97 +0,0 @@
/*
* Tests for prctl(PR_GET_TSC, ...) / prctl(PR_SET_TSC, ...)
*
* Tests if the control register is updated correctly
* at context switches
*
* Warning: this test will cause a very high load for a few seconds
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <inttypes.h>
#include <wait.h>
#include <sys/prctl.h>
#include <linux/prctl.h>
/* Get/set the process' ability to use the timestamp counter instruction */
#ifndef PR_GET_TSC
#define PR_GET_TSC 25
#define PR_SET_TSC 26
# define PR_TSC_ENABLE 1 /* allow the use of the timestamp counter */
# define PR_TSC_SIGSEGV 2 /* throw a SIGSEGV instead of reading the TSC */
#endif
static uint64_t rdtsc(void)
{
uint32_t lo, hi;
/* We cannot use "=A", since this would use %rax on x86_64 */
__asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
return (uint64_t)hi << 32 | lo;
}
static void sigsegv_expect(int sig)
{
/* */
}
static void segvtask(void)
{
if (prctl(PR_SET_TSC, PR_TSC_SIGSEGV) < 0)
{
perror("prctl");
exit(0);
}
signal(SIGSEGV, sigsegv_expect);
alarm(10);
rdtsc();
fprintf(stderr, "FATAL ERROR, rdtsc() succeeded while disabled\n");
exit(0);
}
static void sigsegv_fail(int sig)
{
fprintf(stderr, "FATAL ERROR, rdtsc() failed while enabled\n");
exit(0);
}
static void rdtsctask(void)
{
if (prctl(PR_SET_TSC, PR_TSC_ENABLE) < 0)
{
perror("prctl");
exit(0);
}
signal(SIGSEGV, sigsegv_fail);
alarm(10);
for(;;) rdtsc();
}
int main(void)
{
int n_tasks = 100, i;
fprintf(stderr, "[No further output means we're allright]\n");
for (i=0; i<n_tasks; i++)
if (fork() == 0)
{
if (i & 1)
segvtask();
else
rdtsctask();
}
for (i=0; i<n_tasks; i++)
wait(NULL);
exit(0);
}

View file

@ -1,96 +0,0 @@
/*
* Tests for prctl(PR_GET_TSC, ...) / prctl(PR_SET_TSC, ...)
*
* Tests if the control register is updated correctly
* when set with prctl()
*
* Warning: this test will cause a very high load for a few seconds
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <inttypes.h>
#include <wait.h>
#include <sys/prctl.h>
#include <linux/prctl.h>
/* Get/set the process' ability to use the timestamp counter instruction */
#ifndef PR_GET_TSC
#define PR_GET_TSC 25
#define PR_SET_TSC 26
# define PR_TSC_ENABLE 1 /* allow the use of the timestamp counter */
# define PR_TSC_SIGSEGV 2 /* throw a SIGSEGV instead of reading the TSC */
#endif
/* snippet from wikipedia :-) */
static uint64_t rdtsc(void)
{
uint32_t lo, hi;
/* We cannot use "=A", since this would use %rax on x86_64 */
__asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
return (uint64_t)hi << 32 | lo;
}
int should_segv = 0;
static void sigsegv_cb(int sig)
{
if (!should_segv)
{
fprintf(stderr, "FATAL ERROR, rdtsc() failed while enabled\n");
exit(0);
}
if (prctl(PR_SET_TSC, PR_TSC_ENABLE) < 0)
{
perror("prctl");
exit(0);
}
should_segv = 0;
rdtsc();
}
static void task(void)
{
signal(SIGSEGV, sigsegv_cb);
alarm(10);
for(;;)
{
rdtsc();
if (should_segv)
{
fprintf(stderr, "FATAL ERROR, rdtsc() succeeded while disabled\n");
exit(0);
}
if (prctl(PR_SET_TSC, PR_TSC_SIGSEGV) < 0)
{
perror("prctl");
exit(0);
}
should_segv = 1;
}
}
int main(void)
{
int n_tasks = 100, i;
fprintf(stderr, "[No further output means we're allright]\n");
for (i=0; i<n_tasks; i++)
if (fork() == 0)
task();
for (i=0; i<n_tasks; i++)
wait(NULL);
exit(0);
}

View file

@ -1,95 +0,0 @@
/*
* Tests for prctl(PR_GET_TSC, ...) / prctl(PR_SET_TSC, ...)
*
* Basic test to test behaviour of PR_GET_TSC and PR_SET_TSC
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <inttypes.h>
#include <sys/prctl.h>
#include <linux/prctl.h>
/* Get/set the process' ability to use the timestamp counter instruction */
#ifndef PR_GET_TSC
#define PR_GET_TSC 25
#define PR_SET_TSC 26
# define PR_TSC_ENABLE 1 /* allow the use of the timestamp counter */
# define PR_TSC_SIGSEGV 2 /* throw a SIGSEGV instead of reading the TSC */
#endif
const char *tsc_names[] =
{
[0] = "[not set]",
[PR_TSC_ENABLE] = "PR_TSC_ENABLE",
[PR_TSC_SIGSEGV] = "PR_TSC_SIGSEGV",
};
static uint64_t rdtsc(void)
{
uint32_t lo, hi;
/* We cannot use "=A", since this would use %rax on x86_64 */
__asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
return (uint64_t)hi << 32 | lo;
}
static void sigsegv_cb(int sig)
{
int tsc_val = 0;
printf("[ SIG_SEGV ]\n");
printf("prctl(PR_GET_TSC, &tsc_val); ");
fflush(stdout);
if ( prctl(PR_GET_TSC, &tsc_val) == -1)
perror("prctl");
printf("tsc_val == %s\n", tsc_names[tsc_val]);
printf("prctl(PR_SET_TSC, PR_TSC_ENABLE)\n");
fflush(stdout);
if ( prctl(PR_SET_TSC, PR_TSC_ENABLE) == -1)
perror("prctl");
printf("rdtsc() == ");
}
int main(void)
{
int tsc_val = 0;
signal(SIGSEGV, sigsegv_cb);
printf("rdtsc() == %llu\n", (unsigned long long)rdtsc());
printf("prctl(PR_GET_TSC, &tsc_val); ");
fflush(stdout);
if ( prctl(PR_GET_TSC, &tsc_val) == -1)
perror("prctl");
printf("tsc_val == %s\n", tsc_names[tsc_val]);
printf("rdtsc() == %llu\n", (unsigned long long)rdtsc());
printf("prctl(PR_SET_TSC, PR_TSC_ENABLE)\n");
fflush(stdout);
if ( prctl(PR_SET_TSC, PR_TSC_ENABLE) == -1)
perror("prctl");
printf("rdtsc() == %llu\n", (unsigned long long)rdtsc());
printf("prctl(PR_SET_TSC, PR_TSC_SIGSEGV)\n");
fflush(stdout);
if ( prctl(PR_SET_TSC, PR_TSC_SIGSEGV) == -1)
perror("prctl");
printf("rdtsc() == ");
fflush(stdout);
printf("%llu\n", (unsigned long long)rdtsc());
fflush(stdout);
exit(EXIT_SUCCESS);
}

View file

@ -1 +0,0 @@
testptp

View file

@ -1,8 +0,0 @@
# List of programs to build
hostprogs-y := testptp
# Tell kbuild to always build the programs
always := $(hostprogs-y)
HOSTCFLAGS_testptp.o += -I$(objtree)/usr/include
HOSTLOADLIBES_testptp := -lrt

View file

@ -1,523 +0,0 @@
/*
* PTP 1588 clock support - User space test program
*
* Copyright (C) 2010 OMICRON electronics GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define _GNU_SOURCE
#define __SANE_USERSPACE_TYPES__ /* For PPC64, to get LL64 types */
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <math.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/timex.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include <linux/ptp_clock.h>
#define DEVICE "/dev/ptp0"
#ifndef ADJ_SETOFFSET
#define ADJ_SETOFFSET 0x0100
#endif
#ifndef CLOCK_INVALID
#define CLOCK_INVALID -1
#endif
/* clock_adjtime is not available in GLIBC < 2.14 */
#if !__GLIBC_PREREQ(2, 14)
#include <sys/syscall.h>
static int clock_adjtime(clockid_t id, struct timex *tx)
{
return syscall(__NR_clock_adjtime, id, tx);
}
#endif
static clockid_t get_clockid(int fd)
{
#define CLOCKFD 3
#define FD_TO_CLOCKID(fd) ((~(clockid_t) (fd) << 3) | CLOCKFD)
return FD_TO_CLOCKID(fd);
}
static void handle_alarm(int s)
{
printf("received signal %d\n", s);
}
static int install_handler(int signum, void (*handler)(int))
{
struct sigaction action;
sigset_t mask;
/* Unblock the signal. */
sigemptyset(&mask);
sigaddset(&mask, signum);
sigprocmask(SIG_UNBLOCK, &mask, NULL);
/* Install the signal handler. */
action.sa_handler = handler;
action.sa_flags = 0;
sigemptyset(&action.sa_mask);
sigaction(signum, &action, NULL);
return 0;
}
static long ppb_to_scaled_ppm(int ppb)
{
/*
* The 'freq' field in the 'struct timex' is in parts per
* million, but with a 16 bit binary fractional field.
* Instead of calculating either one of
*
* scaled_ppm = (ppb / 1000) << 16 [1]
* scaled_ppm = (ppb << 16) / 1000 [2]
*
* we simply use double precision math, in order to avoid the
* truncation in [1] and the possible overflow in [2].
*/
return (long) (ppb * 65.536);
}
static int64_t pctns(struct ptp_clock_time *t)
{
return t->sec * 1000000000LL + t->nsec;
}
static void usage(char *progname)
{
fprintf(stderr,
"usage: %s [options]\n"
" -a val request a one-shot alarm after 'val' seconds\n"
" -A val request a periodic alarm every 'val' seconds\n"
" -c query the ptp clock's capabilities\n"
" -d name device to open\n"
" -e val read 'val' external time stamp events\n"
" -f val adjust the ptp clock frequency by 'val' ppb\n"
" -g get the ptp clock time\n"
" -h prints this message\n"
" -i val index for event/trigger\n"
" -k val measure the time offset between system and phc clock\n"
" for 'val' times (Maximum 25)\n"
" -l list the current pin configuration\n"
" -L pin,val configure pin index 'pin' with function 'val'\n"
" the channel index is taken from the '-i' option\n"
" 'val' specifies the auxiliary function:\n"
" 0 - none\n"
" 1 - external time stamp\n"
" 2 - periodic output\n"
" -p val enable output with a period of 'val' nanoseconds\n"
" -P val enable or disable (val=1|0) the system clock PPS\n"
" -s set the ptp clock time from the system time\n"
" -S set the system time from the ptp clock time\n"
" -t val shift the ptp clock time by 'val' seconds\n"
" -T val set the ptp clock time to 'val' seconds\n",
progname);
}
int main(int argc, char *argv[])
{
struct ptp_clock_caps caps;
struct ptp_extts_event event;
struct ptp_extts_request extts_request;
struct ptp_perout_request perout_request;
struct ptp_pin_desc desc;
struct timespec ts;
struct timex tx;
static timer_t timerid;
struct itimerspec timeout;
struct sigevent sigevent;
struct ptp_clock_time *pct;
struct ptp_sys_offset *sysoff;
char *progname;
unsigned int i;
int c, cnt, fd;
char *device = DEVICE;
clockid_t clkid;
int adjfreq = 0x7fffffff;
int adjtime = 0;
int capabilities = 0;
int extts = 0;
int gettime = 0;
int index = 0;
int list_pins = 0;
int oneshot = 0;
int pct_offset = 0;
int n_samples = 0;
int periodic = 0;
int perout = -1;
int pin_index = -1, pin_func;
int pps = -1;
int seconds = 0;
int settime = 0;
int64_t t1, t2, tp;
int64_t interval, offset;
progname = strrchr(argv[0], '/');
progname = progname ? 1+progname : argv[0];
while (EOF != (c = getopt(argc, argv, "a:A:cd:e:f:ghi:k:lL:p:P:sSt:T:v"))) {
switch (c) {
case 'a':
oneshot = atoi(optarg);
break;
case 'A':
periodic = atoi(optarg);
break;
case 'c':
capabilities = 1;
break;
case 'd':
device = optarg;
break;
case 'e':
extts = atoi(optarg);
break;
case 'f':
adjfreq = atoi(optarg);
break;
case 'g':
gettime = 1;
break;
case 'i':
index = atoi(optarg);
break;
case 'k':
pct_offset = 1;
n_samples = atoi(optarg);
break;
case 'l':
list_pins = 1;
break;
case 'L':
cnt = sscanf(optarg, "%d,%d", &pin_index, &pin_func);
if (cnt != 2) {
usage(progname);
return -1;
}
break;
case 'p':
perout = atoi(optarg);
break;
case 'P':
pps = atoi(optarg);
break;
case 's':
settime = 1;
break;
case 'S':
settime = 2;
break;
case 't':
adjtime = atoi(optarg);
break;
case 'T':
settime = 3;
seconds = atoi(optarg);
break;
case 'h':
usage(progname);
return 0;
case '?':
default:
usage(progname);
return -1;
}
}
fd = open(device, O_RDWR);
if (fd < 0) {
fprintf(stderr, "opening %s: %s\n", device, strerror(errno));
return -1;
}
clkid = get_clockid(fd);
if (CLOCK_INVALID == clkid) {
fprintf(stderr, "failed to read clock id\n");
return -1;
}
if (capabilities) {
if (ioctl(fd, PTP_CLOCK_GETCAPS, &caps)) {
perror("PTP_CLOCK_GETCAPS");
} else {
printf("capabilities:\n"
" %d maximum frequency adjustment (ppb)\n"
" %d programmable alarms\n"
" %d external time stamp channels\n"
" %d programmable periodic signals\n"
" %d pulse per second\n"
" %d programmable pins\n"
" %d cross timestamping\n",
caps.max_adj,
caps.n_alarm,
caps.n_ext_ts,
caps.n_per_out,
caps.pps,
caps.n_pins,
caps.cross_timestamping);
}
}
if (0x7fffffff != adjfreq) {
memset(&tx, 0, sizeof(tx));
tx.modes = ADJ_FREQUENCY;
tx.freq = ppb_to_scaled_ppm(adjfreq);
if (clock_adjtime(clkid, &tx)) {
perror("clock_adjtime");
} else {
puts("frequency adjustment okay");
}
}
if (adjtime) {
memset(&tx, 0, sizeof(tx));
tx.modes = ADJ_SETOFFSET;
tx.time.tv_sec = adjtime;
tx.time.tv_usec = 0;
if (clock_adjtime(clkid, &tx) < 0) {
perror("clock_adjtime");
} else {
puts("time shift okay");
}
}
if (gettime) {
if (clock_gettime(clkid, &ts)) {
perror("clock_gettime");
} else {
printf("clock time: %ld.%09ld or %s",
ts.tv_sec, ts.tv_nsec, ctime(&ts.tv_sec));
}
}
if (settime == 1) {
clock_gettime(CLOCK_REALTIME, &ts);
if (clock_settime(clkid, &ts)) {
perror("clock_settime");
} else {
puts("set time okay");
}
}
if (settime == 2) {
clock_gettime(clkid, &ts);
if (clock_settime(CLOCK_REALTIME, &ts)) {
perror("clock_settime");
} else {
puts("set time okay");
}
}
if (settime == 3) {
ts.tv_sec = seconds;
ts.tv_nsec = 0;
if (clock_settime(clkid, &ts)) {
perror("clock_settime");
} else {
puts("set time okay");
}
}
if (extts) {
memset(&extts_request, 0, sizeof(extts_request));
extts_request.index = index;
extts_request.flags = PTP_ENABLE_FEATURE;
if (ioctl(fd, PTP_EXTTS_REQUEST, &extts_request)) {
perror("PTP_EXTTS_REQUEST");
extts = 0;
} else {
puts("external time stamp request okay");
}
for (; extts; extts--) {
cnt = read(fd, &event, sizeof(event));
if (cnt != sizeof(event)) {
perror("read");
break;
}
printf("event index %u at %lld.%09u\n", event.index,
event.t.sec, event.t.nsec);
fflush(stdout);
}
/* Disable the feature again. */
extts_request.flags = 0;
if (ioctl(fd, PTP_EXTTS_REQUEST, &extts_request)) {
perror("PTP_EXTTS_REQUEST");
}
}
if (list_pins) {
int n_pins = 0;
if (ioctl(fd, PTP_CLOCK_GETCAPS, &caps)) {
perror("PTP_CLOCK_GETCAPS");
} else {
n_pins = caps.n_pins;
}
for (i = 0; i < n_pins; i++) {
desc.index = i;
if (ioctl(fd, PTP_PIN_GETFUNC, &desc)) {
perror("PTP_PIN_GETFUNC");
break;
}
printf("name %s index %u func %u chan %u\n",
desc.name, desc.index, desc.func, desc.chan);
}
}
if (oneshot) {
install_handler(SIGALRM, handle_alarm);
/* Create a timer. */
sigevent.sigev_notify = SIGEV_SIGNAL;
sigevent.sigev_signo = SIGALRM;
if (timer_create(clkid, &sigevent, &timerid)) {
perror("timer_create");
return -1;
}
/* Start the timer. */
memset(&timeout, 0, sizeof(timeout));
timeout.it_value.tv_sec = oneshot;
if (timer_settime(timerid, 0, &timeout, NULL)) {
perror("timer_settime");
return -1;
}
pause();
timer_delete(timerid);
}
if (periodic) {
install_handler(SIGALRM, handle_alarm);
/* Create a timer. */
sigevent.sigev_notify = SIGEV_SIGNAL;
sigevent.sigev_signo = SIGALRM;
if (timer_create(clkid, &sigevent, &timerid)) {
perror("timer_create");
return -1;
}
/* Start the timer. */
memset(&timeout, 0, sizeof(timeout));
timeout.it_interval.tv_sec = periodic;
timeout.it_value.tv_sec = periodic;
if (timer_settime(timerid, 0, &timeout, NULL)) {
perror("timer_settime");
return -1;
}
while (1) {
pause();
}
timer_delete(timerid);
}
if (perout >= 0) {
if (clock_gettime(clkid, &ts)) {
perror("clock_gettime");
return -1;
}
memset(&perout_request, 0, sizeof(perout_request));
perout_request.index = index;
perout_request.start.sec = ts.tv_sec + 2;
perout_request.start.nsec = 0;
perout_request.period.sec = 0;
perout_request.period.nsec = perout;
if (ioctl(fd, PTP_PEROUT_REQUEST, &perout_request)) {
perror("PTP_PEROUT_REQUEST");
} else {
puts("periodic output request okay");
}
}
if (pin_index >= 0) {
memset(&desc, 0, sizeof(desc));
desc.index = pin_index;
desc.func = pin_func;
desc.chan = index;
if (ioctl(fd, PTP_PIN_SETFUNC, &desc)) {
perror("PTP_PIN_SETFUNC");
} else {
puts("set pin function okay");
}
}
if (pps != -1) {
int enable = pps ? 1 : 0;
if (ioctl(fd, PTP_ENABLE_PPS, enable)) {
perror("PTP_ENABLE_PPS");
} else {
puts("pps for system time request okay");
}
}
if (pct_offset) {
if (n_samples <= 0 || n_samples > 25) {
puts("n_samples should be between 1 and 25");
usage(progname);
return -1;
}
sysoff = calloc(1, sizeof(*sysoff));
if (!sysoff) {
perror("calloc");
return -1;
}
sysoff->n_samples = n_samples;
if (ioctl(fd, PTP_SYS_OFFSET, sysoff))
perror("PTP_SYS_OFFSET");
else
puts("system and phc clock time offset request okay");
pct = &sysoff->ts[0];
for (i = 0; i < sysoff->n_samples; i++) {
t1 = pctns(pct+2*i);
tp = pctns(pct+2*i+1);
t2 = pctns(pct+2*i+2);
interval = t2 - t1;
offset = (t2 + t1) / 2 - tp;
printf("system time: %lld.%u\n",
(pct+2*i)->sec, (pct+2*i)->nsec);
printf("phc time: %lld.%u\n",
(pct+2*i+1)->sec, (pct+2*i+1)->nsec);
printf("system time: %lld.%u\n",
(pct+2*i+2)->sec, (pct+2*i+2)->nsec);
printf("system/phc clock time offset is %" PRId64 " ns\n"
"system clock time delay is %" PRId64 " ns\n",
offset, interval);
}
free(sysoff);
}
close(fd);
return 0;
}

View file

@ -1,33 +0,0 @@
# PTP 1588 clock support - User space test program
#
# Copyright (C) 2010 OMICRON electronics GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
CC = $(CROSS_COMPILE)gcc
INC = -I$(KBUILD_OUTPUT)/usr/include
CFLAGS = -Wall $(INC)
LDLIBS = -lrt
PROGS = testptp
all: $(PROGS)
testptp: testptp.o
clean:
rm -f testptp.o
distclean: clean
rm -f $(PROGS)

View file

@ -1,7 +1,5 @@
00-INDEX
- this file.
Makefile
- Makefile for the example sourcefiles.
butterfly
- AVR Butterfly SPI driver overview and pin configuration.
ep93xx_spi

View file

@ -1 +0,0 @@
hpet_example

View file

@ -4,12 +4,8 @@ highres.txt
- High resolution timers and dynamic ticks design notes
hpet.txt
- High Precision Event Timer Driver for Linux
hpet_example.c
- sample hpet timer test program
hrtimers.txt
- subsystem for high-resolution kernel timers
Makefile
- Build and link hpet_example
NO_HZ.txt
- Summary of the different methods for the scheduler clock-interrupts management.
timekeeping.txt

View file

@ -1,5 +0,0 @@
# List of programs to build
hostprogs-$(CONFIG_X86) := hpet_example
# Tell kbuild to always build the programs
always := $(hostprogs-y)

View file

@ -25,4 +25,4 @@ arch/x86/kernel/hpet.c.
The driver provides a userspace API which resembles the API found in the
RTC driver framework. An example user space program is provided in
file:Documentation/timers/hpet_example.c
file:samples/timers/hpet_example.c

View file

@ -1,294 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <memory.h>
#include <malloc.h>
#include <time.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <errno.h>
#include <sys/time.h>
#include <linux/hpet.h>
extern void hpet_open_close(int, const char **);
extern void hpet_info(int, const char **);
extern void hpet_poll(int, const char **);
extern void hpet_fasync(int, const char **);
extern void hpet_read(int, const char **);
#include <sys/poll.h>
#include <sys/ioctl.h>
struct hpet_command {
char *command;
void (*func)(int argc, const char ** argv);
} hpet_command[] = {
{
"open-close",
hpet_open_close
},
{
"info",
hpet_info
},
{
"poll",
hpet_poll
},
{
"fasync",
hpet_fasync
},
};
int
main(int argc, const char ** argv)
{
unsigned int i;
argc--;
argv++;
if (!argc) {
fprintf(stderr, "-hpet: requires command\n");
return -1;
}
for (i = 0; i < (sizeof (hpet_command) / sizeof (hpet_command[0])); i++)
if (!strcmp(argv[0], hpet_command[i].command)) {
argc--;
argv++;
fprintf(stderr, "-hpet: executing %s\n",
hpet_command[i].command);
hpet_command[i].func(argc, argv);
return 0;
}
fprintf(stderr, "do_hpet: command %s not implemented\n", argv[0]);
return -1;
}
void
hpet_open_close(int argc, const char **argv)
{
int fd;
if (argc != 1) {
fprintf(stderr, "hpet_open_close: device-name\n");
return;
}
fd = open(argv[0], O_RDONLY);
if (fd < 0)
fprintf(stderr, "hpet_open_close: open failed\n");
else
close(fd);
return;
}
void
hpet_info(int argc, const char **argv)
{
struct hpet_info info;
int fd;
if (argc != 1) {
fprintf(stderr, "hpet_info: device-name\n");
return;
}
fd = open(argv[0], O_RDONLY);
if (fd < 0) {
fprintf(stderr, "hpet_info: open of %s failed\n", argv[0]);
return;
}
if (ioctl(fd, HPET_INFO, &info) < 0) {
fprintf(stderr, "hpet_info: failed to get info\n");
goto out;
}
fprintf(stderr, "hpet_info: hi_irqfreq 0x%lx hi_flags 0x%lx ",
info.hi_ireqfreq, info.hi_flags);
fprintf(stderr, "hi_hpet %d hi_timer %d\n",
info.hi_hpet, info.hi_timer);
out:
close(fd);
return;
}
void
hpet_poll(int argc, const char **argv)
{
unsigned long freq;
int iterations, i, fd;
struct pollfd pfd;
struct hpet_info info;
struct timeval stv, etv;
struct timezone tz;
long usec;
if (argc != 3) {
fprintf(stderr, "hpet_poll: device-name freq iterations\n");
return;
}
freq = atoi(argv[1]);
iterations = atoi(argv[2]);
fd = open(argv[0], O_RDONLY);
if (fd < 0) {
fprintf(stderr, "hpet_poll: open of %s failed\n", argv[0]);
return;
}
if (ioctl(fd, HPET_IRQFREQ, freq) < 0) {
fprintf(stderr, "hpet_poll: HPET_IRQFREQ failed\n");
goto out;
}
if (ioctl(fd, HPET_INFO, &info) < 0) {
fprintf(stderr, "hpet_poll: failed to get info\n");
goto out;
}
fprintf(stderr, "hpet_poll: info.hi_flags 0x%lx\n", info.hi_flags);
if (info.hi_flags && (ioctl(fd, HPET_EPI, 0) < 0)) {
fprintf(stderr, "hpet_poll: HPET_EPI failed\n");
goto out;
}
if (ioctl(fd, HPET_IE_ON, 0) < 0) {
fprintf(stderr, "hpet_poll, HPET_IE_ON failed\n");
goto out;
}
pfd.fd = fd;
pfd.events = POLLIN;
for (i = 0; i < iterations; i++) {
pfd.revents = 0;
gettimeofday(&stv, &tz);
if (poll(&pfd, 1, -1) < 0)
fprintf(stderr, "hpet_poll: poll failed\n");
else {
long data;
gettimeofday(&etv, &tz);
usec = stv.tv_sec * 1000000 + stv.tv_usec;
usec = (etv.tv_sec * 1000000 + etv.tv_usec) - usec;
fprintf(stderr,
"hpet_poll: expired time = 0x%lx\n", usec);
fprintf(stderr, "hpet_poll: revents = 0x%x\n",
pfd.revents);
if (read(fd, &data, sizeof(data)) != sizeof(data)) {
fprintf(stderr, "hpet_poll: read failed\n");
}
else
fprintf(stderr, "hpet_poll: data 0x%lx\n",
data);
}
}
out:
close(fd);
return;
}
static int hpet_sigio_count;
static void
hpet_sigio(int val)
{
fprintf(stderr, "hpet_sigio: called\n");
hpet_sigio_count++;
}
void
hpet_fasync(int argc, const char **argv)
{
unsigned long freq;
int iterations, i, fd, value;
sig_t oldsig;
struct hpet_info info;
hpet_sigio_count = 0;
fd = -1;
if ((oldsig = signal(SIGIO, hpet_sigio)) == SIG_ERR) {
fprintf(stderr, "hpet_fasync: failed to set signal handler\n");
return;
}
if (argc != 3) {
fprintf(stderr, "hpet_fasync: device-name freq iterations\n");
goto out;
}
fd = open(argv[0], O_RDONLY);
if (fd < 0) {
fprintf(stderr, "hpet_fasync: failed to open %s\n", argv[0]);
return;
}
if ((fcntl(fd, F_SETOWN, getpid()) == 1) ||
((value = fcntl(fd, F_GETFL)) == 1) ||
(fcntl(fd, F_SETFL, value | O_ASYNC) == 1)) {
fprintf(stderr, "hpet_fasync: fcntl failed\n");
goto out;
}
freq = atoi(argv[1]);
iterations = atoi(argv[2]);
if (ioctl(fd, HPET_IRQFREQ, freq) < 0) {
fprintf(stderr, "hpet_fasync: HPET_IRQFREQ failed\n");
goto out;
}
if (ioctl(fd, HPET_INFO, &info) < 0) {
fprintf(stderr, "hpet_fasync: failed to get info\n");
goto out;
}
fprintf(stderr, "hpet_fasync: info.hi_flags 0x%lx\n", info.hi_flags);
if (info.hi_flags && (ioctl(fd, HPET_EPI, 0) < 0)) {
fprintf(stderr, "hpet_fasync: HPET_EPI failed\n");
goto out;
}
if (ioctl(fd, HPET_IE_ON, 0) < 0) {
fprintf(stderr, "hpet_fasync, HPET_IE_ON failed\n");
goto out;
}
for (i = 0; i < iterations; i++) {
(void) pause();
fprintf(stderr, "hpet_fasync: count = %d\n", hpet_sigio_count);
}
out:
signal(SIGIO, oldsig);
if (fd >= 0)
close(fd);
return;
}

View file

@ -1,2 +0,0 @@
vdso_test
vdso_standalone_test_x86

View file

@ -1,17 +0,0 @@
ifndef CROSS_COMPILE
# vdso_test won't build for glibc < 2.16, so disable it
# hostprogs-y := vdso_test
hostprogs-$(CONFIG_X86) := vdso_standalone_test_x86
vdso_standalone_test_x86-objs := vdso_standalone_test_x86.o parse_vdso.o
vdso_test-objs := parse_vdso.o vdso_test.o
# Tell kbuild to always build the programs
always := $(hostprogs-y)
HOSTCFLAGS := -I$(objtree)/usr/include -std=gnu99
HOSTCFLAGS_vdso_standalone_test_x86.o := -fno-asynchronous-unwind-tables -fno-stack-protector
HOSTLOADLIBES_vdso_standalone_test_x86 := -nostdlib
ifeq ($(CONFIG_X86_32),y)
HOSTLOADLIBES_vdso_standalone_test_x86 += -lgcc_s
endif
endif

View file

@ -1,269 +0,0 @@
/*
* parse_vdso.c: Linux reference vDSO parser
* Written by Andrew Lutomirski, 2011-2014.
*
* This code is meant to be linked in to various programs that run on Linux.
* As such, it is available with as few restrictions as possible. This file
* is licensed under the Creative Commons Zero License, version 1.0,
* available at http://creativecommons.org/publicdomain/zero/1.0/legalcode
*
* The vDSO is a regular ELF DSO that the kernel maps into user space when
* it starts a program. It works equally well in statically and dynamically
* linked binaries.
*
* This code is tested on x86. In principle it should work on any
* architecture that has a vDSO.
*/
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <limits.h>
#include <elf.h>
/*
* To use this vDSO parser, first call one of the vdso_init_* functions.
* If you've already parsed auxv, then pass the value of AT_SYSINFO_EHDR
* to vdso_init_from_sysinfo_ehdr. Otherwise pass auxv to vdso_init_from_auxv.
* Then call vdso_sym for each symbol you want. For example, to look up
* gettimeofday on x86_64, use:
*
* <some pointer> = vdso_sym("LINUX_2.6", "gettimeofday");
* or
* <some pointer> = vdso_sym("LINUX_2.6", "__vdso_gettimeofday");
*
* vdso_sym will return 0 if the symbol doesn't exist or if the init function
* failed or was not called. vdso_sym is a little slow, so its return value
* should be cached.
*
* vdso_sym is threadsafe; the init functions are not.
*
* These are the prototypes:
*/
extern void vdso_init_from_auxv(void *auxv);
extern void vdso_init_from_sysinfo_ehdr(uintptr_t base);
extern void *vdso_sym(const char *version, const char *name);
/* And here's the code. */
#ifndef ELF_BITS
# if ULONG_MAX > 0xffffffffUL
# define ELF_BITS 64
# else
# define ELF_BITS 32
# endif
#endif
#define ELF_BITS_XFORM2(bits, x) Elf##bits##_##x
#define ELF_BITS_XFORM(bits, x) ELF_BITS_XFORM2(bits, x)
#define ELF(x) ELF_BITS_XFORM(ELF_BITS, x)
static struct vdso_info
{
bool valid;
/* Load information */
uintptr_t load_addr;
uintptr_t load_offset; /* load_addr - recorded vaddr */
/* Symbol table */
ELF(Sym) *symtab;
const char *symstrings;
ELF(Word) *bucket, *chain;
ELF(Word) nbucket, nchain;
/* Version table */
ELF(Versym) *versym;
ELF(Verdef) *verdef;
} vdso_info;
/* Straight from the ELF specification. */
static unsigned long elf_hash(const unsigned char *name)
{
unsigned long h = 0, g;
while (*name)
{
h = (h << 4) + *name++;
if (g = h & 0xf0000000)
h ^= g >> 24;
h &= ~g;
}
return h;
}
void vdso_init_from_sysinfo_ehdr(uintptr_t base)
{
size_t i;
bool found_vaddr = false;
vdso_info.valid = false;
vdso_info.load_addr = base;
ELF(Ehdr) *hdr = (ELF(Ehdr)*)base;
if (hdr->e_ident[EI_CLASS] !=
(ELF_BITS == 32 ? ELFCLASS32 : ELFCLASS64)) {
return; /* Wrong ELF class -- check ELF_BITS */
}
ELF(Phdr) *pt = (ELF(Phdr)*)(vdso_info.load_addr + hdr->e_phoff);
ELF(Dyn) *dyn = 0;
/*
* We need two things from the segment table: the load offset
* and the dynamic table.
*/
for (i = 0; i < hdr->e_phnum; i++)
{
if (pt[i].p_type == PT_LOAD && !found_vaddr) {
found_vaddr = true;
vdso_info.load_offset = base
+ (uintptr_t)pt[i].p_offset
- (uintptr_t)pt[i].p_vaddr;
} else if (pt[i].p_type == PT_DYNAMIC) {
dyn = (ELF(Dyn)*)(base + pt[i].p_offset);
}
}
if (!found_vaddr || !dyn)
return; /* Failed */
/*
* Fish out the useful bits of the dynamic table.
*/
ELF(Word) *hash = 0;
vdso_info.symstrings = 0;
vdso_info.symtab = 0;
vdso_info.versym = 0;
vdso_info.verdef = 0;
for (i = 0; dyn[i].d_tag != DT_NULL; i++) {
switch (dyn[i].d_tag) {
case DT_STRTAB:
vdso_info.symstrings = (const char *)
((uintptr_t)dyn[i].d_un.d_ptr
+ vdso_info.load_offset);
break;
case DT_SYMTAB:
vdso_info.symtab = (ELF(Sym) *)
((uintptr_t)dyn[i].d_un.d_ptr
+ vdso_info.load_offset);
break;
case DT_HASH:
hash = (ELF(Word) *)
((uintptr_t)dyn[i].d_un.d_ptr
+ vdso_info.load_offset);
break;
case DT_VERSYM:
vdso_info.versym = (ELF(Versym) *)
((uintptr_t)dyn[i].d_un.d_ptr
+ vdso_info.load_offset);
break;
case DT_VERDEF:
vdso_info.verdef = (ELF(Verdef) *)
((uintptr_t)dyn[i].d_un.d_ptr
+ vdso_info.load_offset);
break;
}
}
if (!vdso_info.symstrings || !vdso_info.symtab || !hash)
return; /* Failed */
if (!vdso_info.verdef)
vdso_info.versym = 0;
/* Parse the hash table header. */
vdso_info.nbucket = hash[0];
vdso_info.nchain = hash[1];
vdso_info.bucket = &hash[2];
vdso_info.chain = &hash[vdso_info.nbucket + 2];
/* That's all we need. */
vdso_info.valid = true;
}
static bool vdso_match_version(ELF(Versym) ver,
const char *name, ELF(Word) hash)
{
/*
* This is a helper function to check if the version indexed by
* ver matches name (which hashes to hash).
*
* The version definition table is a mess, and I don't know how
* to do this in better than linear time without allocating memory
* to build an index. I also don't know why the table has
* variable size entries in the first place.
*
* For added fun, I can't find a comprehensible specification of how
* to parse all the weird flags in the table.
*
* So I just parse the whole table every time.
*/
/* First step: find the version definition */
ver &= 0x7fff; /* Apparently bit 15 means "hidden" */
ELF(Verdef) *def = vdso_info.verdef;
while(true) {
if ((def->vd_flags & VER_FLG_BASE) == 0
&& (def->vd_ndx & 0x7fff) == ver)
break;
if (def->vd_next == 0)
return false; /* No definition. */
def = (ELF(Verdef) *)((char *)def + def->vd_next);
}
/* Now figure out whether it matches. */
ELF(Verdaux) *aux = (ELF(Verdaux)*)((char *)def + def->vd_aux);
return def->vd_hash == hash
&& !strcmp(name, vdso_info.symstrings + aux->vda_name);
}
void *vdso_sym(const char *version, const char *name)
{
unsigned long ver_hash;
if (!vdso_info.valid)
return 0;
ver_hash = elf_hash(version);
ELF(Word) chain = vdso_info.bucket[elf_hash(name) % vdso_info.nbucket];
for (; chain != STN_UNDEF; chain = vdso_info.chain[chain]) {
ELF(Sym) *sym = &vdso_info.symtab[chain];
/* Check for a defined global or weak function w/ right name. */
if (ELF64_ST_TYPE(sym->st_info) != STT_FUNC)
continue;
if (ELF64_ST_BIND(sym->st_info) != STB_GLOBAL &&
ELF64_ST_BIND(sym->st_info) != STB_WEAK)
continue;
if (sym->st_shndx == SHN_UNDEF)
continue;
if (strcmp(name, vdso_info.symstrings + sym->st_name))
continue;
/* Check symbol version. */
if (vdso_info.versym
&& !vdso_match_version(vdso_info.versym[chain],
version, ver_hash))
continue;
return (void *)(vdso_info.load_offset + sym->st_value);
}
return 0;
}
void vdso_init_from_auxv(void *auxv)
{
ELF(auxv_t) *elf_auxv = auxv;
for (int i = 0; elf_auxv[i].a_type != AT_NULL; i++)
{
if (elf_auxv[i].a_type == AT_SYSINFO_EHDR) {
vdso_init_from_sysinfo_ehdr(elf_auxv[i].a_un.a_val);
return;
}
}
vdso_info.valid = false;
}

View file

@ -1,128 +0,0 @@
/*
* vdso_test.c: Sample code to test parse_vdso.c on x86
* Copyright (c) 2011-2014 Andy Lutomirski
* Subject to the GNU General Public License, version 2
*
* You can amuse yourself by compiling with:
* gcc -std=gnu99 -nostdlib
* -Os -fno-asynchronous-unwind-tables -flto -lgcc_s
* vdso_standalone_test_x86.c parse_vdso.c
* to generate a small binary. On x86_64, you can omit -lgcc_s
* if you want the binary to be completely standalone.
*/
#include <sys/syscall.h>
#include <sys/time.h>
#include <unistd.h>
#include <stdint.h>
extern void *vdso_sym(const char *version, const char *name);
extern void vdso_init_from_sysinfo_ehdr(uintptr_t base);
extern void vdso_init_from_auxv(void *auxv);
/* We need a libc functions... */
int strcmp(const char *a, const char *b)
{
/* This implementation is buggy: it never returns -1. */
while (*a || *b) {
if (*a != *b)
return 1;
if (*a == 0 || *b == 0)
return 1;
a++;
b++;
}
return 0;
}
/* ...and two syscalls. This is x86-specific. */
static inline long x86_syscall3(long nr, long a0, long a1, long a2)
{
long ret;
#ifdef __x86_64__
asm volatile ("syscall" : "=a" (ret) : "a" (nr),
"D" (a0), "S" (a1), "d" (a2) :
"cc", "memory", "rcx",
"r8", "r9", "r10", "r11" );
#else
asm volatile ("int $0x80" : "=a" (ret) : "a" (nr),
"b" (a0), "c" (a1), "d" (a2) :
"cc", "memory" );
#endif
return ret;
}
static inline long linux_write(int fd, const void *data, size_t len)
{
return x86_syscall3(__NR_write, fd, (long)data, (long)len);
}
static inline void linux_exit(int code)
{
x86_syscall3(__NR_exit, code, 0, 0);
}
void to_base10(char *lastdig, time_t n)
{
while (n) {
*lastdig = (n % 10) + '0';
n /= 10;
lastdig--;
}
}
__attribute__((externally_visible)) void c_main(void **stack)
{
/* Parse the stack */
long argc = (long)*stack;
stack += argc + 2;
/* Now we're pointing at the environment. Skip it. */
while(*stack)
stack++;
stack++;
/* Now we're pointing at auxv. Initialize the vDSO parser. */
vdso_init_from_auxv((void *)stack);
/* Find gettimeofday. */
typedef long (*gtod_t)(struct timeval *tv, struct timezone *tz);
gtod_t gtod = (gtod_t)vdso_sym("LINUX_2.6", "__vdso_gettimeofday");
if (!gtod)
linux_exit(1);
struct timeval tv;
long ret = gtod(&tv, 0);
if (ret == 0) {
char buf[] = "The time is .000000\n";
to_base10(buf + 31, tv.tv_sec);
to_base10(buf + 38, tv.tv_usec);
linux_write(1, buf, sizeof(buf) - 1);
} else {
linux_exit(ret);
}
linux_exit(0);
}
/*
* This is the real entry point. It passes the initial stack into
* the C entry point.
*/
asm (
".text\n"
".global _start\n"
".type _start,@function\n"
"_start:\n\t"
#ifdef __x86_64__
"mov %rsp,%rdi\n\t"
"jmp c_main"
#else
"push %esp\n\t"
"call c_main\n\t"
"int $3"
#endif
);

View file

@ -1,52 +0,0 @@
/*
* vdso_test.c: Sample code to test parse_vdso.c
* Copyright (c) 2014 Andy Lutomirski
* Subject to the GNU General Public License, version 2
*
* Compile with:
* gcc -std=gnu99 vdso_test.c parse_vdso.c
*
* Tested on x86, 32-bit and 64-bit. It may work on other architectures, too.
*/
#include <stdint.h>
#include <elf.h>
#include <stdio.h>
#include <sys/auxv.h>
#include <sys/time.h>
extern void *vdso_sym(const char *version, const char *name);
extern void vdso_init_from_sysinfo_ehdr(uintptr_t base);
extern void vdso_init_from_auxv(void *auxv);
int main(int argc, char **argv)
{
unsigned long sysinfo_ehdr = getauxval(AT_SYSINFO_EHDR);
if (!sysinfo_ehdr) {
printf("AT_SYSINFO_EHDR is not present!\n");
return 0;
}
vdso_init_from_sysinfo_ehdr(getauxval(AT_SYSINFO_EHDR));
/* Find gettimeofday. */
typedef long (*gtod_t)(struct timeval *tv, struct timezone *tz);
gtod_t gtod = (gtod_t)vdso_sym("LINUX_2.6", "__vdso_gettimeofday");
if (!gtod) {
printf("Could not find __vdso_gettimeofday\n");
return 1;
}
struct timeval tv;
long ret = gtod(&tv, 0);
if (ret == 0) {
printf("The time is %lld.%06lld\n",
(long long)tv.tv_sec, (long long)tv.tv_usec);
} else {
printf("__vdso_gettimeofday failed\n");
}
return 0;
}

View file

@ -1 +0,0 @@
subdir-y := src

View file

@ -1,2 +0,0 @@
watchdog-simple
watchdog-test

View file

@ -1,5 +0,0 @@
# List of programs to build
hostprogs-y := watchdog-simple watchdog-test
# Tell kbuild to always build the programs
always := $(hostprogs-y)

View file

@ -1,24 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main(void)
{
int fd = open("/dev/watchdog", O_WRONLY);
int ret = 0;
if (fd == -1) {
perror("watchdog");
exit(EXIT_FAILURE);
}
while (1) {
ret = write(fd, "\0", 1);
if (ret != 1) {
ret = -1;
break;
}
sleep(10);
}
close(fd);
return ret;
}

View file

@ -1,105 +0,0 @@
/*
* Watchdog Driver Test Program
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/watchdog.h>
int fd;
const char v = 'V';
/*
* This function simply sends an IOCTL to the driver, which in turn ticks
* the PC Watchdog card to reset its internal timer so it doesn't trigger
* a computer reset.
*/
static void keep_alive(void)
{
int dummy;
printf(".");
ioctl(fd, WDIOC_KEEPALIVE, &dummy);
}
/*
* The main program. Run the program with "-d" to disable the card,
* or "-e" to enable the card.
*/
static void term(int sig)
{
int ret = write(fd, &v, 1);
close(fd);
if (ret < 0)
printf("\nStopping watchdog ticks failed (%d)...\n", errno);
else
printf("\nStopping watchdog ticks...\n");
exit(0);
}
int main(int argc, char *argv[])
{
int flags;
unsigned int ping_rate = 1;
int ret;
setbuf(stdout, NULL);
fd = open("/dev/watchdog", O_WRONLY);
if (fd == -1) {
printf("Watchdog device not enabled.\n");
exit(-1);
}
if (argc > 1) {
if (!strncasecmp(argv[1], "-d", 2)) {
flags = WDIOS_DISABLECARD;
ioctl(fd, WDIOC_SETOPTIONS, &flags);
printf("Watchdog card disabled.\n");
goto end;
} else if (!strncasecmp(argv[1], "-e", 2)) {
flags = WDIOS_ENABLECARD;
ioctl(fd, WDIOC_SETOPTIONS, &flags);
printf("Watchdog card enabled.\n");
goto end;
} else if (!strncasecmp(argv[1], "-t", 2) && argv[2]) {
flags = atoi(argv[2]);
ioctl(fd, WDIOC_SETTIMEOUT, &flags);
printf("Watchdog timeout set to %u seconds.\n", flags);
goto end;
} else if (!strncasecmp(argv[1], "-p", 2) && argv[2]) {
ping_rate = strtoul(argv[2], NULL, 0);
printf("Watchdog ping rate set to %u seconds.\n", ping_rate);
} else {
printf("-d to disable, -e to enable, -t <n> to set " \
"the timeout,\n-p <n> to set the ping rate, and \n");
printf("run by itself to tick the card.\n");
goto end;
}
}
printf("Watchdog Ticking Away!\n");
signal(SIGINT, term);
while(1) {
keep_alive();
sleep(ping_rate);
}
end:
ret = write(fd, &v, 1);
if (ret < 0)
printf("Stopping watchdog ticks failed (%d)...\n", errno);
close(fd);
return 0;
}

View file

@ -37,7 +37,7 @@ activates as soon as /dev/watchdog is opened and will reboot unless
the watchdog is pinged within a certain time, this time is called the
timeout or margin. The simplest way to ping the watchdog is to write
some data to the device. So a very simple watchdog daemon would look
like this source file: see Documentation/watchdog/src/watchdog-simple.c
like this source file: see samples/watchdog/watchdog-simple.c
A more advanced driver could for example check that a HTTP server is
still responding before doing the write call to ping the watchdog.

View file

@ -47,4 +47,4 @@ The external event interfaces on the WDT boards are not currently supported.
Minor numbers are however allocated for it.
Example Watchdog Driver: see Documentation/watchdog/src/watchdog-simple.c
Example Watchdog Driver: see samples/watchdog/watchdog-simple.c