/* This function reads as much of the page as possible - it may return a short read. If the page is invalid (e.g. the page could not be mapped in or its not in a valid memory resource we null pad the buffer and log to syslog. */ static ssize_t pmem_read_partial(struct file *file, char *buf, size_t count, loff_t *poff) { unsigned long page_offset = *poff % PAGE_SIZE; unsigned long page_physaddr = *poff & PAGE_MASK; size_t to_read = min(PAGE_SIZE - page_offset, count); /* disable preemption to make sure we stay on the cpu where the page is * remapped. If we don't do this we risk being preempted and scheduled on * another cpu with an invalid mapping, returning wrong data. */ //pte_mmap->disable_interrupts_(); /* Manually remap the rogue page to the target offset */ if (pte_mmap->remap_page(pte_mmap, page_physaddr) != PTE_SUCCESS) { DEBUG_LOG("Failed to remap rogue page to %#016lx", page_physaddr); goto invalid_page; } /* Copy the data into the user buffer. */ if (_copy_to_user( buf, (void *)((pte_mmap->rogue_page.value + page_offset)), to_read)) { DEBUG_LOG("Failed to copy page %#016llx to user space", *poff); goto error_copy; } error_copy: /* Increment the file offset. */ *poff += to_read; //pte_mmap->enable_interrupts_(); return to_read; invalid_page: DEBUG_LOG("%016llx is invalid, zero padding...", *poff); if (_copy_to_user(buf, (const void *)zero_page, to_read)) { DEBUG_LOG("Failed to copy zero page for adress %#016llx to user " "space.", *poff); } /* Increment the file offset. */ *poff += to_read; //pte_mmap->enable_interrupts_(); return to_read; };
int ath_ioctl_ethtool(struct ath_softc *sc, int cmd, void *addr) { struct ethtool_drvinfo info = {0}; if (cmd != ETHTOOL_GDRVINFO) return -EOPNOTSUPP; info.cmd = cmd; strncpy(info.driver, version, (sizeof(info.driver) - 1)); strncpy(info.version, dev_info, (sizeof(info.version) - 1)); return _copy_to_user(addr, &info, sizeof(info)) ? -EFAULT : 0; }