diff options
author | Ingo Molnar <mingo@kernel.org> | 2012-03-26 17:18:44 +0200 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2012-03-26 17:19:03 +0200 |
commit | 7fd52392c56361a40f0c630a82b36b95ca31eac6 (patch) | |
tree | 14091de24c6b28ea4cae9826f98aeedb7be091f5 /tools | |
parent | perf: Move mmap page data_head offset assertion out of header (diff) | |
parent | Merge tag 'stable/for-linus-3.4-tag-two' of git://git.kernel.org/pub/scm/linu... (diff) | |
download | linux-7fd52392c56361a40f0c630a82b36b95ca31eac6.tar.xz linux-7fd52392c56361a40f0c630a82b36b95ca31eac6.zip |
Merge branch 'linus' into perf/urgent
Merge reason: we need to fix a non-trivial merge conflict.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/hv/hv_kvp_daemon.c | 458 | ||||
-rw-r--r-- | tools/include/tools/be_byteshift.h | 70 | ||||
-rw-r--r-- | tools/include/tools/le_byteshift.h | 70 | ||||
-rw-r--r-- | tools/perf/util/include/linux/bitops.h | 2 | ||||
-rwxr-xr-x | tools/testing/ktest/ktest.pl | 58 | ||||
-rw-r--r-- | tools/testing/ktest/sample.conf | 14 | ||||
-rw-r--r-- | tools/usb/Makefile | 2 | ||||
-rw-r--r-- | tools/usb/ffs-test.c | 31 | ||||
-rw-r--r-- | tools/usb/testusb.c | 2 |
9 files changed, 614 insertions, 93 deletions
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c index 11224eddcdc2..146fd6147e84 100644 --- a/tools/hv/hv_kvp_daemon.c +++ b/tools/hv/hv_kvp_daemon.c @@ -34,21 +34,13 @@ #include <errno.h> #include <arpa/inet.h> #include <linux/connector.h> +#include <linux/hyperv.h> #include <linux/netlink.h> #include <ifaddrs.h> #include <netdb.h> #include <syslog.h> - -/* - * KYS: TODO. Need to register these in the kernel. - * - * The following definitions are shared with the in-kernel component; do not - * change any of this without making the corresponding changes in - * the KVP kernel component. - */ -#define CN_KVP_IDX 0x9 /* MSFT KVP functionality */ -#define CN_KVP_VAL 0x1 /* This supports queries from the kernel */ -#define CN_KVP_USER_VAL 0x2 /* This supports queries from the user */ +#include <sys/stat.h> +#include <fcntl.h> /* * KVP protocol: The user mode component first registers with the @@ -60,25 +52,8 @@ * We use this infrastructure for also supporting queries from user mode * application for state that may be maintained in the KVP kernel component. * - * XXXKYS: Have a shared header file between the user and kernel (TODO) */ -enum kvp_op { - KVP_REGISTER = 0, /* Register the user mode component*/ - KVP_KERNEL_GET, /*Kernel is requesting the value for the specified key*/ - KVP_KERNEL_SET, /*Kernel is providing the value for the specified key*/ - KVP_USER_GET, /*User is requesting the value for the specified key*/ - KVP_USER_SET /*User is providing the value for the specified key*/ -}; - -#define HV_KVP_EXCHANGE_MAX_KEY_SIZE 512 -#define HV_KVP_EXCHANGE_MAX_VALUE_SIZE 2048 - -struct hv_ku_msg { - __u32 kvp_index; - __u8 kvp_key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; /* Key name */ - __u8 kvp_value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; /* Key value */ -}; enum key_index { FullyQualifiedDomainName = 0, @@ -93,10 +68,6 @@ enum key_index { ProcessorArchitecture }; -/* - * End of shared definitions. - */ - static char kvp_send_buffer[4096]; static char kvp_recv_buffer[4096]; static struct sockaddr_nl addr; @@ -109,6 +80,345 @@ static char *os_build; static char *lic_version; static struct utsname uts_buf; + +#define MAX_FILE_NAME 100 +#define ENTRIES_PER_BLOCK 50 + +struct kvp_record { + __u8 key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; + __u8 value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; +}; + +struct kvp_file_state { + int fd; + int num_blocks; + struct kvp_record *records; + int num_records; + __u8 fname[MAX_FILE_NAME]; +}; + +static struct kvp_file_state kvp_file_info[KVP_POOL_COUNT]; + +static void kvp_acquire_lock(int pool) +{ + struct flock fl = {F_WRLCK, SEEK_SET, 0, 0, 0}; + fl.l_pid = getpid(); + + if (fcntl(kvp_file_info[pool].fd, F_SETLKW, &fl) == -1) { + syslog(LOG_ERR, "Failed to acquire the lock pool: %d", pool); + exit(-1); + } +} + +static void kvp_release_lock(int pool) +{ + struct flock fl = {F_UNLCK, SEEK_SET, 0, 0, 0}; + fl.l_pid = getpid(); + + if (fcntl(kvp_file_info[pool].fd, F_SETLK, &fl) == -1) { + perror("fcntl"); + syslog(LOG_ERR, "Failed to release the lock pool: %d", pool); + exit(-1); + } +} + +static void kvp_update_file(int pool) +{ + FILE *filep; + size_t bytes_written; + + /* + * We are going to write our in-memory registry out to + * disk; acquire the lock first. + */ + kvp_acquire_lock(pool); + + filep = fopen(kvp_file_info[pool].fname, "w"); + if (!filep) { + kvp_release_lock(pool); + syslog(LOG_ERR, "Failed to open file, pool: %d", pool); + exit(-1); + } + + bytes_written = fwrite(kvp_file_info[pool].records, + sizeof(struct kvp_record), + kvp_file_info[pool].num_records, filep); + + fflush(filep); + kvp_release_lock(pool); +} + +static void kvp_update_mem_state(int pool) +{ + FILE *filep; + size_t records_read = 0; + struct kvp_record *record = kvp_file_info[pool].records; + struct kvp_record *readp; + int num_blocks = kvp_file_info[pool].num_blocks; + int alloc_unit = sizeof(struct kvp_record) * ENTRIES_PER_BLOCK; + + kvp_acquire_lock(pool); + + filep = fopen(kvp_file_info[pool].fname, "r"); + if (!filep) { + kvp_release_lock(pool); + syslog(LOG_ERR, "Failed to open file, pool: %d", pool); + exit(-1); + } + while (!feof(filep)) { + readp = &record[records_read]; + records_read += fread(readp, sizeof(struct kvp_record), + ENTRIES_PER_BLOCK * num_blocks, + filep); + + if (!feof(filep)) { + /* + * We have more data to read. + */ + num_blocks++; + record = realloc(record, alloc_unit * num_blocks); + + if (record == NULL) { + syslog(LOG_ERR, "malloc failed"); + exit(-1); + } + continue; + } + break; + } + + kvp_file_info[pool].num_blocks = num_blocks; + kvp_file_info[pool].records = record; + kvp_file_info[pool].num_records = records_read; + + kvp_release_lock(pool); +} +static int kvp_file_init(void) +{ + int ret, fd; + FILE *filep; + size_t records_read; + __u8 *fname; + struct kvp_record *record; + struct kvp_record *readp; + int num_blocks; + int i; + int alloc_unit = sizeof(struct kvp_record) * ENTRIES_PER_BLOCK; + + if (access("/var/opt/hyperv", F_OK)) { + if (mkdir("/var/opt/hyperv", S_IRUSR | S_IWUSR | S_IROTH)) { + syslog(LOG_ERR, " Failed to create /var/opt/hyperv"); + exit(-1); + } + } + + for (i = 0; i < KVP_POOL_COUNT; i++) { + fname = kvp_file_info[i].fname; + records_read = 0; + num_blocks = 1; + sprintf(fname, "/var/opt/hyperv/.kvp_pool_%d", i); + fd = open(fname, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IROTH); + + if (fd == -1) + return 1; + + + filep = fopen(fname, "r"); + if (!filep) + return 1; + + record = malloc(alloc_unit * num_blocks); + if (record == NULL) { + fclose(filep); + return 1; + } + while (!feof(filep)) { + readp = &record[records_read]; + records_read += fread(readp, sizeof(struct kvp_record), + ENTRIES_PER_BLOCK, + filep); + + if (!feof(filep)) { + /* + * We have more data to read. + */ + num_blocks++; + record = realloc(record, alloc_unit * + num_blocks); + if (record == NULL) { + fclose(filep); + return 1; + } + continue; + } + break; + } + kvp_file_info[i].fd = fd; + kvp_file_info[i].num_blocks = num_blocks; + kvp_file_info[i].records = record; + kvp_file_info[i].num_records = records_read; + fclose(filep); + + } + + return 0; +} + +static int kvp_key_delete(int pool, __u8 *key, int key_size) +{ + int i; + int j, k; + int num_records; + struct kvp_record *record; + + /* + * First update the in-memory state. + */ + kvp_update_mem_state(pool); + + num_records = kvp_file_info[pool].num_records; + record = kvp_file_info[pool].records; + + for (i = 0; i < num_records; i++) { + if (memcmp(key, record[i].key, key_size)) + continue; + /* + * Found a match; just move the remaining + * entries up. + */ + if (i == num_records) { + kvp_file_info[pool].num_records--; + kvp_update_file(pool); + return 0; + } + + j = i; + k = j + 1; + for (; k < num_records; k++) { + strcpy(record[j].key, record[k].key); + strcpy(record[j].value, record[k].value); + j++; + } + + kvp_file_info[pool].num_records--; + kvp_update_file(pool); + return 0; + } + return 1; +} + +static int kvp_key_add_or_modify(int pool, __u8 *key, int key_size, __u8 *value, + int value_size) +{ + int i; + int j, k; + int num_records; + struct kvp_record *record; + int num_blocks; + + if ((key_size > HV_KVP_EXCHANGE_MAX_KEY_SIZE) || + (value_size > HV_KVP_EXCHANGE_MAX_VALUE_SIZE)) + return 1; + + /* + * First update the in-memory state. + */ + kvp_update_mem_state(pool); + + num_records = kvp_file_info[pool].num_records; + record = kvp_file_info[pool].records; + num_blocks = kvp_file_info[pool].num_blocks; + + for (i = 0; i < num_records; i++) { + if (memcmp(key, record[i].key, key_size)) + continue; + /* + * Found a match; just update the value - + * this is the modify case. + */ + memcpy(record[i].value, value, value_size); + kvp_update_file(pool); + return 0; + } + + /* + * Need to add a new entry; + */ + if (num_records == (ENTRIES_PER_BLOCK * num_blocks)) { + /* Need to allocate a larger array for reg entries. */ + record = realloc(record, sizeof(struct kvp_record) * + ENTRIES_PER_BLOCK * (num_blocks + 1)); + + if (record == NULL) + return 1; + kvp_file_info[pool].num_blocks++; + + } + memcpy(record[i].value, value, value_size); + memcpy(record[i].key, key, key_size); + kvp_file_info[pool].records = record; + kvp_file_info[pool].num_records++; + kvp_update_file(pool); + return 0; +} + +static int kvp_get_value(int pool, __u8 *key, int key_size, __u8 *value, + int value_size) +{ + int i; + int num_records; + struct kvp_record *record; + + if ((key_size > HV_KVP_EXCHANGE_MAX_KEY_SIZE) || + (value_size > HV_KVP_EXCHANGE_MAX_VALUE_SIZE)) + return 1; + + /* + * First update the in-memory state. + */ + kvp_update_mem_state(pool); + + num_records = kvp_file_info[pool].num_records; + record = kvp_file_info[pool].records; + + for (i = 0; i < num_records; i++) { + if (memcmp(key, record[i].key, key_size)) + continue; + /* + * Found a match; just copy the value out. + */ + memcpy(value, record[i].value, value_size); + return 0; + } + + return 1; +} + +static void kvp_pool_enumerate(int pool, int index, __u8 *key, int key_size, + __u8 *value, int value_size) +{ + struct kvp_record *record; + + /* + * First update our in-memory database. + */ + kvp_update_mem_state(pool); + record = kvp_file_info[pool].records; + + if (index >= kvp_file_info[pool].num_records) { + /* + * This is an invalid index; terminate enumeration; + * - a NULL value will do the trick. + */ + strcpy(value, ""); + return; + } + + memcpy(key, record[index].key, key_size); + memcpy(value, record[index].value, value_size); +} + + void kvp_get_os_info(void) { FILE *file; @@ -332,7 +642,7 @@ int main(void) struct pollfd pfd; struct nlmsghdr *incoming_msg; struct cn_msg *incoming_cn_msg; - struct hv_ku_msg *hv_msg; + struct hv_kvp_msg *hv_msg; char *p; char *key_value; char *key_name; @@ -345,6 +655,11 @@ int main(void) */ kvp_get_os_info(); + if (kvp_file_init()) { + syslog(LOG_ERR, "Failed to initialize the pools"); + exit(-1); + } + fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); if (fd < 0) { syslog(LOG_ERR, "netlink socket creation failed; error:%d", fd); @@ -370,9 +685,11 @@ int main(void) message = (struct cn_msg *)kvp_send_buffer; message->id.idx = CN_KVP_IDX; message->id.val = CN_KVP_VAL; - message->seq = KVP_REGISTER; + + hv_msg = (struct hv_kvp_msg *)message->data; + hv_msg->kvp_hdr.operation = KVP_OP_REGISTER; message->ack = 0; - message->len = 0; + message->len = sizeof(struct hv_kvp_msg); len = netlink_send(fd, message); if (len < 0) { @@ -398,14 +715,15 @@ int main(void) incoming_msg = (struct nlmsghdr *)kvp_recv_buffer; incoming_cn_msg = (struct cn_msg *)NLMSG_DATA(incoming_msg); + hv_msg = (struct hv_kvp_msg *)incoming_cn_msg->data; - switch (incoming_cn_msg->seq) { - case KVP_REGISTER: + switch (hv_msg->kvp_hdr.operation) { + case KVP_OP_REGISTER: /* * Driver is registering with us; stash away the version * information. */ - p = (char *)incoming_cn_msg->data; + p = (char *)hv_msg->body.kvp_register.version; lic_version = malloc(strlen(p) + 1); if (lic_version) { strcpy(lic_version, p); @@ -416,17 +734,65 @@ int main(void) } continue; - case KVP_KERNEL_GET: + /* + * The current protocol with the kernel component uses a + * NULL key name to pass an error condition. + * For the SET, GET and DELETE operations, + * use the existing protocol to pass back error. + */ + + case KVP_OP_SET: + if (kvp_key_add_or_modify(hv_msg->kvp_hdr.pool, + hv_msg->body.kvp_set.data.key, + hv_msg->body.kvp_set.data.key_size, + hv_msg->body.kvp_set.data.value, + hv_msg->body.kvp_set.data.value_size)) + strcpy(hv_msg->body.kvp_set.data.key, ""); + break; + + case KVP_OP_GET: + if (kvp_get_value(hv_msg->kvp_hdr.pool, + hv_msg->body.kvp_set.data.key, + hv_msg->body.kvp_set.data.key_size, + hv_msg->body.kvp_set.data.value, + hv_msg->body.kvp_set.data.value_size)) + strcpy(hv_msg->body.kvp_set.data.key, ""); + break; + + case KVP_OP_DELETE: + if (kvp_key_delete(hv_msg->kvp_hdr.pool, + hv_msg->body.kvp_delete.key, + hv_msg->body.kvp_delete.key_size)) + strcpy(hv_msg->body.kvp_delete.key, ""); break; + default: - continue; + break; + } + + if (hv_msg->kvp_hdr.operation != KVP_OP_ENUMERATE) + goto kvp_done; + + /* + * If the pool is KVP_POOL_AUTO, dynamically generate + * both the key and the value; if not read from the + * appropriate pool. + */ + if (hv_msg->kvp_hdr.pool != KVP_POOL_AUTO) { + kvp_pool_enumerate(hv_msg->kvp_hdr.pool, + hv_msg->body.kvp_enum_data.index, + hv_msg->body.kvp_enum_data.data.key, + HV_KVP_EXCHANGE_MAX_KEY_SIZE, + hv_msg->body.kvp_enum_data.data.value, + HV_KVP_EXCHANGE_MAX_VALUE_SIZE); + goto kvp_done; } - hv_msg = (struct hv_ku_msg *)incoming_cn_msg->data; - key_name = (char *)hv_msg->kvp_key; - key_value = (char *)hv_msg->kvp_value; + hv_msg = (struct hv_kvp_msg *)incoming_cn_msg->data; + key_name = (char *)hv_msg->body.kvp_enum_data.data.key; + key_value = (char *)hv_msg->body.kvp_enum_data.data.value; - switch (hv_msg->kvp_index) { + switch (hv_msg->body.kvp_enum_data.index) { case FullyQualifiedDomainName: kvp_get_domain_name(key_value, HV_KVP_EXCHANGE_MAX_VALUE_SIZE); @@ -483,12 +849,12 @@ int main(void) * already in the receive buffer. Update the cn_msg header to * reflect the key value that has been added to the message */ +kvp_done: incoming_cn_msg->id.idx = CN_KVP_IDX; incoming_cn_msg->id.val = CN_KVP_VAL; - incoming_cn_msg->seq = KVP_USER_SET; incoming_cn_msg->ack = 0; - incoming_cn_msg->len = sizeof(struct hv_ku_msg); + incoming_cn_msg->len = sizeof(struct hv_kvp_msg); len = netlink_send(fd, incoming_cn_msg); if (len < 0) { diff --git a/tools/include/tools/be_byteshift.h b/tools/include/tools/be_byteshift.h new file mode 100644 index 000000000000..f4912e2668ba --- /dev/null +++ b/tools/include/tools/be_byteshift.h @@ -0,0 +1,70 @@ +#ifndef _TOOLS_BE_BYTESHIFT_H +#define _TOOLS_BE_BYTESHIFT_H + +#include <linux/types.h> + +static inline __u16 __get_unaligned_be16(const __u8 *p) +{ + return p[0] << 8 | p[1]; +} + +static inline __u32 __get_unaligned_be32(const __u8 *p) +{ + return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; +} + +static inline __u64 __get_unaligned_be64(const __u8 *p) +{ + return (__u64)__get_unaligned_be32(p) << 32 | + __get_unaligned_be32(p + 4); +} + +static inline void __put_unaligned_be16(__u16 val, __u8 *p) +{ + *p++ = val >> 8; + *p++ = val; +} + +static inline void __put_unaligned_be32(__u32 val, __u8 *p) +{ + __put_unaligned_be16(val >> 16, p); + __put_unaligned_be16(val, p + 2); +} + +static inline void __put_unaligned_be64(__u64 val, __u8 *p) +{ + __put_unaligned_be32(val >> 32, p); + __put_unaligned_be32(val, p + 4); +} + +static inline __u16 get_unaligned_be16(const void *p) +{ + return __get_unaligned_be16((const __u8 *)p); +} + +static inline __u32 get_unaligned_be32(const void *p) +{ + return __get_unaligned_be32((const __u8 *)p); +} + +static inline __u64 get_unaligned_be64(const void *p) +{ + return __get_unaligned_be64((const __u8 *)p); +} + +static inline void put_unaligned_be16(__u16 val, void *p) +{ + __put_unaligned_be16(val, p); +} + +static inline void put_unaligned_be32(__u32 val, void *p) +{ + __put_unaligned_be32(val, p); +} + +static inline void put_unaligned_be64(__u64 val, void *p) +{ + __put_unaligned_be64(val, p); +} + +#endif /* _TOOLS_BE_BYTESHIFT_H */ diff --git a/tools/include/tools/le_byteshift.h b/tools/include/tools/le_byteshift.h new file mode 100644 index 000000000000..c99d45a68bda --- /dev/null +++ b/tools/include/tools/le_byteshift.h @@ -0,0 +1,70 @@ +#ifndef _TOOLS_LE_BYTESHIFT_H +#define _TOOLS_LE_BYTESHIFT_H + +#include <linux/types.h> + +static inline __u16 __get_unaligned_le16(const __u8 *p) +{ + return p[0] | p[1] << 8; +} + +static inline __u32 __get_unaligned_le32(const __u8 *p) +{ + return p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24; +} + +static inline __u64 __get_unaligned_le64(const __u8 *p) +{ + return (__u64)__get_unaligned_le32(p + 4) << 32 | + __get_unaligned_le32(p); +} + +static inline void __put_unaligned_le16(__u16 val, __u8 *p) +{ + *p++ = val; + *p++ = val >> 8; +} + +static inline void __put_unaligned_le32(__u32 val, __u8 *p) +{ + __put_unaligned_le16(val >> 16, p + 2); + __put_unaligned_le16(val, p); +} + +static inline void __put_unaligned_le64(__u64 val, __u8 *p) +{ + __put_unaligned_le32(val >> 32, p + 4); + __put_unaligned_le32(val, p); +} + +static inline __u16 get_unaligned_le16(const void *p) +{ + return __get_unaligned_le16((const __u8 *)p); +} + +static inline __u32 get_unaligned_le32(const void *p) +{ + return __get_unaligned_le32((const __u8 *)p); +} + +static inline __u64 get_unaligned_le64(const void *p) +{ + return __get_unaligned_le64((const __u8 *)p); +} + +static inline void put_unaligned_le16(__u16 val, void *p) +{ + __put_unaligned_le16(val, p); +} + +static inline void put_unaligned_le32(__u32 val, void *p) +{ + __put_unaligned_le32(val, p); +} + +static inline void put_unaligned_le64(__u64 val, void *p) +{ + __put_unaligned_le64(val, p); +} + +#endif /* _TOOLS_LE_BYTESHIFT_H */ diff --git a/tools/perf/util/include/linux/bitops.h b/tools/perf/util/include/linux/bitops.h index 62cdee78db7b..f1584833bd22 100644 --- a/tools/perf/util/include/linux/bitops.h +++ b/tools/perf/util/include/linux/bitops.h @@ -15,7 +15,7 @@ (bit) = find_next_bit((addr), (size), (bit) + 1)) /* same as for_each_set_bit() but use bit as value to start with */ -#define for_each_set_bit_cont(bit, addr, size) \ +#define for_each_set_bit_from(bit, addr, size) \ for ((bit) = find_next_bit((addr), (size), (bit)); \ (bit) < (size); \ (bit) = find_next_bit((addr), (size), (bit) + 1)) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 9507c4b251a8..95d6a6f7c33a 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -46,6 +46,7 @@ my %default = ( "DIE_ON_FAILURE" => 1, "SSH_EXEC" => "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND", "SCP_TO_TARGET" => "scp \$SRC_FILE \$SSH_USER\@\$MACHINE:\$DST_FILE", + "SCP_TO_TARGET_INSTALL" => "\${SCP_TO_TARGET}", "REBOOT" => "ssh \$SSH_USER\@\$MACHINE reboot", "STOP_AFTER_SUCCESS" => 10, "STOP_AFTER_FAILURE" => 60, @@ -86,11 +87,13 @@ my $reboot_on_error; my $switch_to_good; my $switch_to_test; my $poweroff_on_error; +my $reboot_on_success; my $die_on_failure; my $powercycle_after_reboot; my $poweroff_after_halt; my $ssh_exec; my $scp_to_target; +my $scp_to_target_install; my $power_off; my $grub_menu; my $grub_number; @@ -211,6 +214,7 @@ my %option_map = ( "SWITCH_TO_GOOD" => \$switch_to_good, "SWITCH_TO_TEST" => \$switch_to_test, "POWEROFF_ON_ERROR" => \$poweroff_on_error, + "REBOOT_ON_SUCCESS" => \$reboot_on_success, "DIE_ON_FAILURE" => \$die_on_failure, "POWER_OFF" => \$power_off, "POWERCYCLE_AFTER_REBOOT" => \$powercycle_after_reboot, @@ -243,6 +247,7 @@ my %option_map = ( "BUILD_TARGET" => \$build_target, "SSH_EXEC" => \$ssh_exec, "SCP_TO_TARGET" => \$scp_to_target, + "SCP_TO_TARGET_INSTALL" => \$scp_to_target_install, "CHECKOUT" => \$checkout, "TARGET_IMAGE" => \$target_image, "LOCALVERSION" => \$localversion, @@ -1113,7 +1118,6 @@ sub reboot_to_good { if (defined($switch_to_good)) { run_command $switch_to_good; - return; } reboot $time; @@ -1349,8 +1353,7 @@ sub run_ssh { } sub run_scp { - my ($src, $dst) = @_; - my $cp_scp = $scp_to_target; + my ($src, $dst, $cp_scp) = @_; $cp_scp =~ s/\$SRC_FILE/$src/g; $cp_scp =~ s/\$DST_FILE/$dst/g; @@ -1358,6 +1361,22 @@ sub run_scp { return run_command "$cp_scp"; } +sub run_scp_install { + my ($src, $dst) = @_; + + my $cp_scp = $scp_to_target_install; + + return run_scp($src, $dst, $cp_scp); +} + +sub run_scp_mod { + my ($src, $dst) = @_; + + my $cp_scp = $scp_to_target; + + return run_scp($src, $dst, $cp_scp); +} + sub get_grub_index { if ($reboot_type ne "grub") { @@ -1460,6 +1479,7 @@ sub get_sha1 { sub monitor { my $booted = 0; my $bug = 0; + my $bug_ignored = 0; my $skip_call_trace = 0; my $loops; @@ -1531,9 +1551,13 @@ sub monitor { } if ($full_line =~ /call trace:/i) { - if (!$ignore_errors && !$bug && !$skip_call_trace) { - $bug = 1; - $failure_start = time; + if (!$bug && !$skip_call_trace) { + if ($ignore_errors) { + $bug_ignored = 1; + } else { + $bug = 1; + $failure_start = time; + } } } @@ -1595,6 +1619,10 @@ sub monitor { fail "failed - never got a boot prompt." and return 0; } + if ($bug_ignored) { + doprint "WARNING: Call Trace detected but ignored due to IGNORE_ERRORS=1\n"; + } + return 1; } @@ -1621,7 +1649,7 @@ sub install { my $cp_target = eval_kernel_version $target_image; - run_scp "$outputdir/$build_target", "$cp_target" or + run_scp_install "$outputdir/$build_target", "$cp_target" or dodie "failed to copy image"; my $install_mods = 0; @@ -1643,7 +1671,7 @@ sub install { return; } - run_command "$make INSTALL_MOD_PATH=$tmpdir modules_install" or + run_command "$make INSTALL_MOD_STRIP=1 INSTALL_MOD_PATH=$tmpdir modules_install" or dodie "Failed to install modules"; my $modlib = "/lib/modules/$version"; @@ -1656,7 +1684,7 @@ sub install { run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or dodie "making tarball"; - run_scp "$tmpdir/$modtar", "/tmp" or + run_scp_mod "$tmpdir/$modtar", "/tmp" or dodie "failed to copy modules"; unlink "$tmpdir/$modtar"; @@ -2601,7 +2629,7 @@ sub config_bisect { # read directly what we want to check my %config_check; open (IN, $output_config) - or dodie "faied to open $output_config"; + or dodie "failed to open $output_config"; while (<IN>) { if (/^((CONFIG\S*)=.*)/) { @@ -3526,8 +3554,10 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { die "failed to checkout $checkout"; } - $no_reboot = 0; - + # A test may opt to not reboot the box + if ($reboot_on_success) { + $no_reboot = 0; + } if ($test_type eq "bisect") { bisect $i; @@ -3572,8 +3602,12 @@ if ($opt{"POWEROFF_ON_SUCCESS"}) { halt; } elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot) { reboot_to_good; +} elsif (defined($switch_to_good)) { + # still need to get to the good kernel + run_command $switch_to_good; } + doprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n"; exit 0; diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf index 5ea04c6a71bf..b682456afda8 100644 --- a/tools/testing/ktest/sample.conf +++ b/tools/testing/ktest/sample.conf @@ -710,10 +710,18 @@ # The variables SSH_USER, MACHINE and SSH_COMMAND are defined #SSH_EXEC = ssh $SSH_USER@$MACHINE $SSH_COMMAND"; -# The way to copy a file to the target +# The way to copy a file to the target (install and modules) # (default scp $SRC_FILE $SSH_USER@$MACHINE:$DST_FILE) -# The variables SSH_USER, MACHINE, SRC_FILE and DST_FILE are defined. -#SCP_TO_TARGET = scp $SRC_FILE $SSH_USER@$MACHINE:$DST_FILE +# The variables SSH_USER, MACHINE are defined by the config +# SRC_FILE and DST_FILE are ktest internal variables and +# should only have '$' and not the '${}' notation. +# (default scp $SRC_FILE ${SSH_USER}@${MACHINE}:$DST_FILE) +#SCP_TO_TARGET = echo skip scp for $SRC_FILE $DST_FILE + +# If install needs to be different than modules, then this +# option will override the SCP_TO_TARGET for installation. +# (default ${SCP_TO_TARGET} ) +#SCP_TO_TARGET_INSTALL = scp $SRC_FILE tftp@tftpserver:$DST_FILE # The nice way to reboot the target # (default ssh $SSH_USER@$MACHINE reboot) diff --git a/tools/usb/Makefile b/tools/usb/Makefile index 8b704af14349..396d6c44e9d7 100644 --- a/tools/usb/Makefile +++ b/tools/usb/Makefile @@ -3,7 +3,7 @@ CC = $(CROSS_COMPILE)gcc PTHREAD_LIBS = -lpthread WARNINGS = -Wall -Wextra -CFLAGS = $(WARNINGS) -g $(PTHREAD_LIBS) +CFLAGS = $(WARNINGS) -g $(PTHREAD_LIBS) -I../include all: testusb ffs-test %: %.c diff --git a/tools/usb/ffs-test.c b/tools/usb/ffs-test.c index b9c798631699..4b107b5e623f 100644 --- a/tools/usb/ffs-test.c +++ b/tools/usb/ffs-test.c @@ -2,7 +2,7 @@ * ffs-test.c.c -- user mode filesystem api for usb composite function * * Copyright (C) 2010 Samsung Electronics - * Author: Michal Nazarewicz <m.nazarewicz@samsung.com> + * Author: Michal Nazarewicz <mina86@mina86.com> * * 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 @@ -36,6 +36,7 @@ #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> +#include <tools/le_byteshift.h> #include "../../include/linux/usb/functionfs.h" @@ -47,34 +48,6 @@ #define le32_to_cpu(x) le32toh(x) #define le16_to_cpu(x) le16toh(x) -static inline __u16 get_unaligned_le16(const void *_ptr) -{ - const __u8 *ptr = _ptr; - return ptr[0] | (ptr[1] << 8); -} - -static inline __u32 get_unaligned_le32(const void *_ptr) -{ - const __u8 *ptr = _ptr; - return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24); -} - -static inline void put_unaligned_le16(__u16 val, void *_ptr) -{ - __u8 *ptr = _ptr; - *ptr++ = val; - *ptr++ = val >> 8; -} - -static inline void put_unaligned_le32(__u32 val, void *_ptr) -{ - __u8 *ptr = _ptr; - *ptr++ = val; - *ptr++ = val >> 8; - *ptr++ = val >> 16; - *ptr++ = val >> 24; -} - /******************** Messages and Errors ***********************************/ diff --git a/tools/usb/testusb.c b/tools/usb/testusb.c index f08e89463842..6e0f56701e44 100644 --- a/tools/usb/testusb.c +++ b/tools/usb/testusb.c @@ -3,7 +3,7 @@ /* * Copyright (c) 2002 by David Brownell * Copyright (c) 2010 by Samsung Electronics - * Author: Michal Nazarewicz <m.nazarewicz@samsung.com> + * Author: Michal Nazarewicz <mina86@mina86.com> * * 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 |