1/*- 2 * BSD LICENSE 3 * 4 * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. 5 * Copyright (c) 2017, Western Digital Corporation or its affiliates. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34#ifndef __NVME_COMMON_H__ 35#define __NVME_COMMON_H__ 36 37#define _GNU_SOURCE 38#define _FILE_OFFSET_BITS 64 39 40#include <stdlib.h> 41#include <stdio.h> 42#include <stdint.h> 43#include <stddef.h> 44#include <stdbool.h> 45#include <stdarg.h> 46#include <string.h> 47#include <ctype.h> 48#include <errno.h> 49#include <inttypes.h> 50#include <unistd.h> 51#include <limits.h> 52#include <time.h> 53#include <sys/types.h> 54#include <sys/cdefs.h> 55#include <sys/queue.h> 56#ifndef __HAIKU__ 57#include <linux/types.h> 58#endif 59 60#include "libnvme/nvme.h" 61#include "nvme_arch.h" 62#include "nvme_log.h" 63 64/* 65 * Check if a branch is likely to be taken. 66 */ 67#ifndef likely 68#if __GNUC__ < 3 69#define likely(x) x 70#else 71#define likely(x) __builtin_expect((x),1) 72#endif 73#endif /* likely */ 74 75/* 76 * Check if a branch is unlikely to be taken. 77 */ 78#ifndef unlikely 79#if __GNUC__ < 3 80#define unlikely(x) x 81#else 82#define unlikely(x) __builtin_expect((x),0) 83#endif 84#endif /* unlikely */ 85 86#ifndef typeof 87#define typeof __typeof__ 88#endif 89 90/* 91 * Trim whitespace from a string in place. 92 */ 93extern void nvme_str_trim(char *s); 94 95/* 96 * Split string into tokens 97 */ 98extern int nvme_str_split(char *string, int stringlen, 99 char **tokens, int maxtokens, char delim); 100 101/* 102 * Converts a numeric string to the equivalent uint64_t value. 103 * As well as straight number conversion, also recognises the suffixes 104 * k, m and g for kilobytes, megabytes and gigabytes respectively. 105 * 106 * If a negative number is passed in, zero is returned. 107 * Zero is also returned in the case of an error with the 108 * strtoull call in the function. 109 */ 110static inline size_t nvme_str2size(const char *str) 111{ 112 unsigned long long size; 113 char *endptr; 114 115 while (isspace((int)*str)) 116 str++; 117 if (*str == '-') 118 return 0; 119 120 errno = 0; 121 size = strtoull(str, &endptr, 0); 122 if (errno) 123 return 0; 124 125 /* Allow 1 space gap between number and unit */ 126 if (*endptr == ' ') 127 endptr++; 128 129 switch (*endptr){ 130 case 'G': 131 case 'g': 132 size *= 1024; 133 /* Fall through */ 134 case 'M': 135 case 'm': 136 /* Fall through */ 137 size *= 1024; 138 case 'K': 139 case 'k': 140 /* Fall through */ 141 size *= 1024; 142 } 143 144 return size; 145} 146 147/* 148 * Function to read a single numeric value from a file on the filesystem. 149 * Used to read information from files on /sys 150 */ 151extern int nvme_parse_sysfs_value(const char *filename, unsigned long *val); 152 153/* 154 * Get a file size in Bytes. 155 */ 156extern uint64_t nvme_file_get_size(int fd); 157 158/* 159 * Get a block device block size in Bytes. 160 */ 161extern ssize_t nvme_dev_get_blocklen(int fd); 162 163/* 164 * Get current time in nano seconds. 165 */ 166static inline unsigned long long nvme_time_nsec(void) 167{ 168#ifdef __HAIKU__ 169 return (unsigned long long)system_time(); 170#else 171 struct timespec ts; 172 173 clock_gettime(CLOCK_REALTIME, &ts); 174 175 return (unsigned long long) ts.tv_sec * 1000000000ULL 176 + (unsigned long long) ts.tv_nsec; 177#endif 178} 179 180/* 181 * Get current time in micro seconds. 182 */ 183static inline unsigned long long nvme_time_usec(void) 184{ 185 return nvme_time_nsec() / 1000; 186} 187 188/* 189 * Get current time in milli seconds. 190 */ 191static inline unsigned long long nvme_time_msec(void) 192{ 193 return nvme_time_nsec() / 1000000; 194} 195 196/* 197 * PAUSE instruction for tight loops (avoid busy waiting) 198 */ 199#ifdef __SSE2__ 200#include <emmintrin.h> 201static inline void nvme_pause(void) 202{ 203 _mm_pause(); 204} 205#else 206static inline void nvme_pause(void) {} 207#endif 208 209#ifdef __HAIKU__ 210static inline void 211nvme_usleep(int usecs) 212{ 213 snooze(usecs); 214} 215 216static inline void 217nvme_msleep(int msecs) 218{ 219 snooze(msecs * 1000LL); 220} 221#else 222/* 223 * Micro-seconds sleep. 224 */ 225static inline void nvme_usleep(int usecs) 226{ 227 struct timeval tv; 228 229 tv.tv_sec = usecs / 1000000; 230 tv.tv_usec = usecs % 1000000; 231 select(0, NULL, NULL, NULL, &tv); 232} 233 234/* 235 * Milli-seconds sleep. 236 */ 237static inline void nvme_msleep(int msecs) 238{ 239 struct timeval tv; 240 241 tv.tv_sec = msecs / 1000; 242 tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000; 243 select(0, NULL, NULL, NULL, &tv); 244} 245#endif 246 247#ifndef __HAIKU__ 248/* 249 * Provide notification of a critical non-recoverable error and stop. 250 * This function should not be called directly. Use nvme_panic() instead. 251 */ 252extern void __nvme_panic(const char *funcname , const char *format, ...) 253#ifdef __GNUC__ 254#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2)) 255 __attribute__((cold)) 256#endif 257#endif 258 __attribute__((noreturn)) 259 __attribute__((format(printf, 2, 3))); 260 261/* 262 * Provide notification of a critical non-recoverable error 263 * and terminate execution abnormally. 264 */ 265#define nvme_panic(format, args...) \ 266 __nvme_panic(__FUNCTION__, format, ## args) 267#else 268#define nvme_panic panic 269#endif 270 271/* 272 * Macro to evaluate a scalar expression and 273 * abort the program if the assertion is false. 274 */ 275#define _nvme_assert_default(exp) \ 276 do { \ 277 if (unlikely(!(exp))) \ 278 nvme_panic("line %d, assert %s failed\n", \ 279 __LINE__, # exp); \ 280 } while (0) 281 282#define _nvme_assert_msg(exp, msg) \ 283 do { \ 284 if (unlikely(!(exp))) \ 285 nvme_panic("%s\n", msg); \ 286 } while (0) 287 288#define _NVME_GET_ASSERT_OVERLOAD(_1, _2, NAME, args...) NAME 289 290#define nvme_assert(args...) \ 291 _NVME_GET_ASSERT_OVERLOAD(args, \ 292 _nvme_assert_msg, \ 293 _nvme_assert_default) \ 294 (args) 295 296/* 297 * Macro to return the minimum of two numbers 298 */ 299#define nvme_min(a, b) ({ \ 300 typeof (a) _a = (a); \ 301 typeof (b) _b = (b); \ 302 _a < _b ? _a : _b; \ 303 }) 304 305/* 306 * Macro to return the maximum of two numbers 307 */ 308#define nvme_max(a, b) ({ \ 309 typeof (a) _a = (a); \ 310 typeof (b) _b = (b); \ 311 _a > _b ? _a : _b; \ 312 }) 313 314/* 315 * Returns true if n is a power of 2. 316 */ 317static inline int nvme_is_pow2(__u64 v) 318{ 319 return v && !(v & (v - 1)); 320} 321 322/* 323 * Return the power of 2 immediately after v. 324 */ 325static inline __u64 nvme_align_pow2(__u64 v) 326{ 327 v--; 328 v |= v >> 1; 329 v |= v >> 2; 330 v |= v >> 4; 331 v |= v >> 8; 332 v |= v >> 16; 333 v |= v >> 32; 334 335 return v + 1; 336} 337 338/* 339 * Calculate log2 of a power of 2 size. 340 */ 341static inline size_t nvme_log2(size_t size) 342{ 343 size_t bits = 0; 344 345 if (!nvme_is_pow2(size)) 346 return 0; 347 348 while (size >>= 1) 349 bits++; 350 351 return bits; 352} 353 354/* 355 * Handle alignements. 356 */ 357#define nvme_align_down(val, align) \ 358 ((val) & (~((typeof(val))((align) - 1)))) 359#define nvme_align_up(val, align) \ 360 nvme_align_down((val) + (align) - 1, (align)) 361 362/* 363 * Test a bit value. 364 */ 365static inline int test_bit(__u8 *bitmap, unsigned int bit) 366{ 367 return bitmap[bit >> 3] & (1U << (bit & 0x7)); 368} 369 370/* 371 * Set a bit. 372 */ 373static inline void set_bit(__u8 *bitmap, unsigned int bit) 374{ 375 bitmap[bit >> 3] |= 1U << (bit & 0x7); 376} 377 378/* 379 * Clear a bit. 380 */ 381static inline void clear_bit(__u8 *bitmap, unsigned int bit) 382{ 383 bitmap[bit >> 3] &= ~(1U << (bit & 0x7)); 384} 385 386/* 387 * Find the first zero bit in a bitmap of size nr_bits. 388 * If no zero bit is found, return -1. 389 */ 390static inline int find_first_zero_bit(__u8 *bitmap, unsigned int nr_bits) 391{ 392 __u64 *b = (__u64 *)bitmap; 393 unsigned int i, j, bit, count = (nr_bits + 63) >> 6; 394 395 for(i = 0; i < count; i++) { 396 if (b[i] != ~0UL) 397 break; 398 } 399 400 bit = i << 6; 401 for (j = bit; j < nr_bits; j++) { 402 if (!test_bit(bitmap, j)) 403 return j; 404 } 405 406 return -1; 407} 408 409/* 410 * Close all open controllers on exit. 411 * Defined in lib/nvme/nvme.c 412 */ 413extern void nvme_ctrlr_cleanup(void); 414 415#endif /* __NVME_COMMON_H__ */ 416