Index: sys/compat/linuxkpi/common/include/linux/kernel.h =================================================================== --- sys/compat/linuxkpi/common/include/linux/kernel.h +++ sys/compat/linuxkpi/common/include/linux/kernel.h @@ -390,6 +390,24 @@ } static inline int +kstrtou64(const char *cp, unsigned int base, u64 *res) +{ + char *end; + unsigned long long temp; + + *res = temp = strtouq(cp, &end, base); + + /* skip newline character, if any */ + if (*end == '\n') + end++; + if (*cp == 0 || *end != 0) + return (-EINVAL); + if (temp != (u64)temp) + return (-ERANGE); + return (0); +} + +static inline int kstrtobool(const char *s, bool *res) { int len; Index: sys/compat/linuxkpi/common/include/linux/lockdep.h =================================================================== --- sys/compat/linuxkpi/common/include/linux/lockdep.h +++ sys/compat/linuxkpi/common/include/linux/lockdep.h @@ -36,6 +36,7 @@ }; #define lockdep_set_class(lock, key) +#define lockdep_set_subclass(lock, sub) #define lockdep_set_class_and_name(lock, key, name) #define lockdep_set_current_reclaim_state(g) do { } while (0) #define lockdep_clear_current_reclaim_state() do { } while (0) @@ -60,6 +61,7 @@ __lock = __m; return (LOCK_CLASS(__lock)->lc_owner(__lock, &__td) != 0); } +#define lockdep_is_held_type(_m, _t) lockdep_is_held(_m) #else #define lockdep_assert_held(m) do { } while (0) @@ -67,6 +69,7 @@ #define lockdep_assert_held_once(m) do { } while (0) #define lockdep_is_held(m) 1 +#define lockdep_is_held_type(_m, _t) 1 #endif #define might_lock(m) do { } while (0) @@ -75,5 +78,8 @@ #define lock_acquire(...) do { } while (0) #define lock_release(...) do { } while (0) #define lock_acquire_shared_recursive(...) do { } while (0) + +#define mutex_acquire(...) do { } while (0) +#define mutex_release(...) do { } while (0) #endif /* _LINUX_LOCKDEP_H_ */ Index: sys/compat/linuxkpi/common/include/linux/math64.h =================================================================== --- sys/compat/linuxkpi/common/include/linux/math64.h +++ sys/compat/linuxkpi/common/include/linux/math64.h @@ -91,4 +91,13 @@ return ((uint64_t)a * b); } +static inline uint64_t +div64_u64_round_up(uint64_t dividend, uint32_t divisor) +{ + return div64_u64(dividend + divisor - 1, divisor); +} + +#define DIV64_U64_ROUND_UP(ll, d) \ + div64_u64_round_up((ll), (d)) + #endif /* _LINUX_MATH64_H */ Index: sys/compat/linuxkpi/common/include/linux/mutex.h =================================================================== --- sys/compat/linuxkpi/common/include/linux/mutex.h +++ sys/compat/linuxkpi/common/include/linux/mutex.h @@ -66,6 +66,17 @@ linux_mutex_lock_interruptible(_m); \ }) +/* + * reuse the interruptable method since the sx + * lock handles both signals and interrupts + */ +#define mutex_lock_killable(_m) ({ \ + MUTEX_SKIP() ? 0 : \ + linux_mutex_lock_interruptible(_m); \ +}) +#define mutex_lock_killable_nested(_m, _sub) \ + mutex_lock_killable(_m) + #define mutex_unlock(_m) do { \ if (MUTEX_SKIP()) \ break; \ Index: sys/compat/linuxkpi/common/include/linux/pci.h =================================================================== --- sys/compat/linuxkpi/common/include/linux/pci.h +++ sys/compat/linuxkpi/common/include/linux/pci.h @@ -954,6 +954,46 @@ return (PCIE_LNK_WIDTH_UNKNOWN); } +static inline int +pcie_get_mps(struct pci_dev *dev) +{ + return pci_get_max_payload(dev->dev.bsddev); +} + +static inline u32 +PCIE_SPEED2MBS_ENC(enum pci_bus_speed spd) +{ + switch(spd) { + case PCIE_SPEED_16_0GT: + return 16000 * 128 / 130; + case PCIE_SPEED_8_0GT: + return 8000 * 128 / 130; + case PCIE_SPEED_5_0GT: + return 5000 * 8 / 10; + case PCIE_SPEED_2_5GT: + return 2500 * 8 / 10; + default: + return (0); + } +} + +static inline u32 +pcie_bandwidth_available(struct pci_dev *pdev, + struct pci_dev **limiting, + enum pci_bus_speed *speed, + enum pcie_link_width *width) +{ + enum pci_bus_speed nspeed = pcie_get_speed_cap(pdev); + enum pcie_link_width nwidth = pcie_get_width_cap(pdev); + + if (speed) + *speed = nspeed; + if (width) + *width = nwidth; + + return nwidth * PCIE_SPEED2MBS_ENC(nspeed); +} + /* * The following functions can be used to attach/detach the LinuxKPI's * PCI device runtime. The pci_driver and pci_device_id pointer is Index: sys/compat/linuxkpi/common/include/linux/scatterlist.h =================================================================== --- sys/compat/linuxkpi/common/include/linux/scatterlist.h +++ sys/compat/linuxkpi/common/include/linux/scatterlist.h @@ -66,6 +66,10 @@ } internal; }; +struct sg_dma_page_iter { + struct sg_page_iter base; +}; + #define SCATTERLIST_MAX_SEGMENT (-1U & ~(PAGE_SIZE - 1)) #define SG_MAX_SINGLE_ALLOC (PAGE_SIZE / sizeof(struct scatterlist)) @@ -86,6 +90,10 @@ for (_sg_iter_init(sgl, iter, nents, pgoffset); \ (iter)->sg; _sg_iter_next(iter)) +#define for_each_sg_dma_page(sgl, iter, nents, pgoffset) \ + for (_sg_iter_init(sgl, &(iter)->base, nents, pgoffset); \ + (iter)->base.sg; _sg_iter_next(&(iter)->base)) + #define for_each_sg(sglist, sg, sgmax, iter) \ for (iter = 0, sg = (sglist); iter < (sgmax); iter++, sg = sg_next(sg)) @@ -427,6 +435,37 @@ return (1); } +static int +sg_dma_page_count(struct scatterlist *sg) +{ + return PAGE_ALIGN(sg->offset + sg_dma_len(sg)) >> PAGE_SHIFT; +} + +static inline bool +__sg_page_iter_dma_next(struct sg_dma_page_iter *dma_iter) +{ + struct sg_page_iter *piter = &dma_iter->base; + + if (piter->internal.nents == 0) + return (0); + if (piter->sg == NULL) + return (0); + + piter->sg_pgoffset += piter->internal.pg_advance; + piter->internal.pg_advance = 1; + + while (piter->sg_pgoffset >= sg_dma_page_count(piter->sg)) { + piter->sg_pgoffset -= sg_dma_page_count(piter->sg); + piter->sg = sg_next(piter->sg); + if (--piter->internal.nents == 0) + return (0); + if (piter->sg == NULL) + return (0); + } + + return true; +} + static inline void _sg_iter_init(struct scatterlist *sgl, struct sg_page_iter *iter, unsigned int nents, unsigned long pgoffset) @@ -444,9 +483,9 @@ } static inline dma_addr_t -sg_page_iter_dma_address(struct sg_page_iter *spi) +sg_page_iter_dma_address(struct sg_dma_page_iter *dmai) { - return (spi->sg->dma_address + (spi->sg_pgoffset << PAGE_SHIFT)); + return (dmai->base.sg->dma_address + (dmai->base.sg_pgoffset << PAGE_SHIFT)); } static inline struct page *