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 */ 93 extern void nvme_str_trim(char *s); 94 95 /* 96 * Split string into tokens 97 */ 98 extern 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 */ 110 static 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 */ 151 extern int nvme_parse_sysfs_value(const char *filename, unsigned long *val); 152 153 /* 154 * Get a file size in Bytes. 155 */ 156 extern uint64_t nvme_file_get_size(int fd); 157 158 /* 159 * Get a block device block size in Bytes. 160 */ 161 extern ssize_t nvme_dev_get_blocklen(int fd); 162 163 /* 164 * Get current time in nano seconds. 165 */ 166 static 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 */ 183 static 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 */ 191 static 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> 201 static inline void nvme_pause(void) 202 { 203 _mm_pause(); 204 } 205 #else 206 static inline void nvme_pause(void) {} 207 #endif 208 209 #ifdef __HAIKU__ 210 static inline void 211 nvme_usleep(int usecs) 212 { 213 snooze(usecs); 214 } 215 216 static inline void 217 nvme_msleep(int msecs) 218 { 219 snooze(msecs * 1000LL); 220 } 221 #else 222 /* 223 * Micro-seconds sleep. 224 */ 225 static 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 */ 237 static 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 */ 252 extern 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 */ 317 static 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 */ 325 static 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 */ 341 static 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 */ 365 static 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 */ 373 static 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 */ 381 static 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 */ 390 static 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 */ 413 extern void nvme_ctrlr_cleanup(void); 414 415 #endif /* __NVME_COMMON_H__ */ 416