136 lines
3.1 KiB
C
136 lines
3.1 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
#include <inttypes.h>
|
|
|
|
#include <stdint.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/syslog.h>
|
|
#include <sys/time.h>
|
|
#include <linux/types.h>
|
|
|
|
#include <libnvme.h>
|
|
|
|
#include "logging.h"
|
|
|
|
int log_level;
|
|
|
|
int map_log_level(int verbose, bool quiet)
|
|
{
|
|
int log_level;
|
|
|
|
/*
|
|
* LOG_NOTICE is unused thus the user has to provide two 'v' for getting
|
|
* any feedback at all. Thus skip this level
|
|
*/
|
|
verbose++;
|
|
|
|
switch (verbose) {
|
|
case 0:
|
|
log_level = LOG_WARNING;
|
|
break;
|
|
case 1:
|
|
log_level = LOG_NOTICE;
|
|
break;
|
|
case 2:
|
|
log_level = LOG_INFO;
|
|
break;
|
|
default:
|
|
log_level = LOG_DEBUG;
|
|
break;
|
|
}
|
|
if (quiet)
|
|
log_level = LOG_ERR;
|
|
|
|
return log_level;
|
|
}
|
|
|
|
static void nvme_show_common(struct nvme_passthru_cmd *cmd)
|
|
{
|
|
printf("opcode : %02x\n", cmd->opcode);
|
|
printf("flags : %02x\n", cmd->flags);
|
|
printf("rsvd1 : %04x\n", cmd->rsvd1);
|
|
printf("nsid : %08x\n", cmd->nsid);
|
|
printf("cdw2 : %08x\n", cmd->cdw2);
|
|
printf("cdw3 : %08x\n", cmd->cdw3);
|
|
printf("data_len : %08x\n", cmd->data_len);
|
|
printf("metadata_len : %08x\n", cmd->metadata_len);
|
|
printf("addr : %"PRIx64"\n", (uint64_t)(uintptr_t)cmd->addr);
|
|
printf("metadata : %"PRIx64"\n", (uint64_t)(uintptr_t)cmd->metadata);
|
|
printf("cdw10 : %08x\n", cmd->cdw10);
|
|
printf("cdw11 : %08x\n", cmd->cdw11);
|
|
printf("cdw12 : %08x\n", cmd->cdw12);
|
|
printf("cdw13 : %08x\n", cmd->cdw13);
|
|
printf("cdw14 : %08x\n", cmd->cdw14);
|
|
printf("cdw15 : %08x\n", cmd->cdw15);
|
|
printf("timeout_ms : %08x\n", cmd->timeout_ms);
|
|
}
|
|
|
|
static void nvme_show_command(struct nvme_passthru_cmd *cmd, int err)
|
|
{
|
|
nvme_show_common(cmd);
|
|
printf("result : %08x\n", cmd->result);
|
|
printf("err : %d\n", err);
|
|
}
|
|
|
|
static void nvme_show_command64(struct nvme_passthru_cmd64 *cmd, int err)
|
|
{
|
|
nvme_show_common((struct nvme_passthru_cmd *)cmd);
|
|
printf("result : %"PRIx64"\n", (uint64_t)(uintptr_t)cmd->result);
|
|
printf("err : %d\n", err);
|
|
}
|
|
|
|
static void nvme_show_latency(struct timeval start, struct timeval end)
|
|
{
|
|
printf("latency : %lu us\n",
|
|
(end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec));
|
|
}
|
|
|
|
int nvme_submit_passthru(int fd, unsigned long ioctl_cmd,
|
|
struct nvme_passthru_cmd *cmd, __u32 *result)
|
|
{
|
|
struct timeval start;
|
|
struct timeval end;
|
|
int err;
|
|
|
|
if (log_level >= LOG_DEBUG)
|
|
gettimeofday(&start, NULL);
|
|
|
|
err = ioctl(fd, ioctl_cmd, cmd);
|
|
|
|
if (log_level >= LOG_DEBUG) {
|
|
gettimeofday(&end, NULL);
|
|
nvme_show_command(cmd, err);
|
|
nvme_show_latency(start, end);
|
|
}
|
|
|
|
if (err >= 0 && result)
|
|
*result = cmd->result;
|
|
|
|
return err;
|
|
}
|
|
|
|
int nvme_submit_passthru64(int fd, unsigned long ioctl_cmd,
|
|
struct nvme_passthru_cmd64 *cmd,
|
|
__u64 *result)
|
|
{
|
|
struct timeval start;
|
|
struct timeval end;
|
|
int err;
|
|
|
|
if (log_level >= LOG_DEBUG)
|
|
gettimeofday(&start, NULL);
|
|
|
|
|
|
err = ioctl(fd, ioctl_cmd, cmd);
|
|
|
|
if (log_level >= LOG_DEBUG) {
|
|
gettimeofday(&end, NULL);
|
|
nvme_show_command64(cmd, err);
|
|
nvme_show_latency(start, end);
|
|
}
|
|
|
|
if (err >= 0 && result)
|
|
*result = cmd->result;
|
|
|
|
return err;
|
|
}
|