forked from rrcarlosr/Jetpack
252 lines
6.3 KiB
C
252 lines
6.3 KiB
C
/*
|
|
* Copyright (c) 2013 Luis R. Rodriguez <mcgrof@do-not-panic.com>
|
|
*
|
|
* Linux backport symbols for kernels 3.10.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/module.h>
|
|
#include <linux/err.h>
|
|
#include <linux/proc_fs.h>
|
|
#include <linux/random.h>
|
|
#include <linux/tty.h>
|
|
#include <linux/pci.h>
|
|
#include <linux/pci_regs.h>
|
|
#include <linux/of.h>
|
|
#include <linux/mm.h>
|
|
#include <linux/skbuff.h>
|
|
|
|
void proc_set_size(struct proc_dir_entry *de, loff_t size)
|
|
{
|
|
de->size = size;
|
|
}
|
|
EXPORT_SYMBOL_GPL(proc_set_size);
|
|
|
|
void proc_set_user(struct proc_dir_entry *de, kuid_t uid, kgid_t gid)
|
|
{
|
|
de->uid = uid;
|
|
de->gid = gid;
|
|
}
|
|
EXPORT_SYMBOL_GPL(proc_set_user);
|
|
|
|
/* get_random_int() was not exported for module use until 3.10-rc.
|
|
Implement it here in terms of the more expensive get_random_bytes()
|
|
*/
|
|
unsigned int get_random_int(void)
|
|
{
|
|
unsigned int r;
|
|
get_random_bytes(&r, sizeof(r));
|
|
|
|
return r;
|
|
}
|
|
EXPORT_SYMBOL_GPL(get_random_int);
|
|
|
|
#if defined(CONFIG_TTY) || LINUX_VERSION_IS_LESS(3,9,0)
|
|
/**
|
|
* tty_port_tty_wakeup - helper to wake up a tty
|
|
*
|
|
* @port: tty port
|
|
*/
|
|
void tty_port_tty_wakeup(struct tty_port *port)
|
|
{
|
|
struct tty_struct *tty = tty_port_tty_get(port);
|
|
|
|
if (tty) {
|
|
tty_wakeup(tty);
|
|
tty_kref_put(tty);
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(tty_port_tty_wakeup);
|
|
|
|
/**
|
|
* tty_port_tty_hangup - helper to hang up a tty
|
|
*
|
|
* @port: tty port
|
|
* @check_clocal: hang only ttys with CLOCAL unset?
|
|
*/
|
|
void tty_port_tty_hangup(struct tty_port *port, bool check_clocal)
|
|
{
|
|
struct tty_struct *tty = tty_port_tty_get(port);
|
|
|
|
if (tty && (!check_clocal || !C_CLOCAL(tty)))
|
|
tty_hangup(tty);
|
|
tty_kref_put(tty);
|
|
}
|
|
EXPORT_SYMBOL_GPL(tty_port_tty_hangup);
|
|
#endif /* CONFIG_TTY */
|
|
|
|
#ifdef CONFIG_PCI_IOV
|
|
/*
|
|
* pci_vfs_assigned - returns number of VFs are assigned to a guest
|
|
* @dev: the PCI device
|
|
*
|
|
* Returns number of VFs belonging to this device that are assigned to a guest.
|
|
* If device is not a physical function returns -ENODEV.
|
|
*/
|
|
int pci_vfs_assigned(struct pci_dev *dev)
|
|
{
|
|
struct pci_dev *vfdev;
|
|
unsigned int vfs_assigned = 0;
|
|
unsigned short dev_id;
|
|
|
|
/* only search if we are a PF */
|
|
if (!dev->is_physfn)
|
|
return 0;
|
|
|
|
/*
|
|
* determine the device ID for the VFs, the vendor ID will be the
|
|
* same as the PF so there is no need to check for that one
|
|
*/
|
|
pci_read_config_word(dev, dev->sriov->pos + PCI_SRIOV_VF_DID, &dev_id);
|
|
|
|
/* loop through all the VFs to see if we own any that are assigned */
|
|
vfdev = pci_get_device(dev->vendor, dev_id, NULL);
|
|
while (vfdev) {
|
|
/*
|
|
* It is considered assigned if it is a virtual function with
|
|
* our dev as the physical function and the assigned bit is set
|
|
*/
|
|
if (vfdev->is_virtfn && (vfdev->physfn == dev) &&
|
|
(vfdev->dev_flags & PCI_DEV_FLAGS_ASSIGNED))
|
|
vfs_assigned++;
|
|
|
|
vfdev = pci_get_device(dev->vendor, dev_id, vfdev);
|
|
}
|
|
|
|
return vfs_assigned;
|
|
}
|
|
EXPORT_SYMBOL_GPL(pci_vfs_assigned);
|
|
#endif /* CONFIG_PCI_IOV */
|
|
|
|
#ifdef CONFIG_OF
|
|
/**
|
|
* of_property_read_u32_index - Find and read a u32 from a multi-value property.
|
|
*
|
|
* @np: device node from which the property value is to be read.
|
|
* @propname: name of the property to be searched.
|
|
* @index: index of the u32 in the list of values
|
|
* @out_value: pointer to return value, modified only if no error.
|
|
*
|
|
* Search for a property in a device node and read nth 32-bit value from
|
|
* it. Returns 0 on success, -EINVAL if the property does not exist,
|
|
* -ENODATA if property does not have a value, and -EOVERFLOW if the
|
|
* property data isn't large enough.
|
|
*
|
|
* The out_value is modified only if a valid u32 value can be decoded.
|
|
*/
|
|
int of_property_read_u32_index(const struct device_node *np,
|
|
const char *propname,
|
|
u32 index, u32 *out_value)
|
|
{
|
|
const u32 *val = of_find_property_value_of_size(np, propname,
|
|
((index + 1) * sizeof(*out_value)));
|
|
|
|
if (IS_ERR(val))
|
|
return PTR_ERR(val);
|
|
|
|
*out_value = be32_to_cpup(((__be32 *)val) + index);
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL_GPL(of_property_read_u32_index);
|
|
#endif /* CONFIG_OF */
|
|
|
|
static inline void set_page_count(struct page *page, int v)
|
|
{
|
|
atomic_set(&page->_count, v);
|
|
}
|
|
|
|
/*
|
|
* Turn a non-refcounted page (->_count == 0) into refcounted with
|
|
* a count of one.
|
|
*/
|
|
static inline void set_page_refcounted(struct page *page)
|
|
{
|
|
VM_BUG_ON(PageTail(page));
|
|
VM_BUG_ON(atomic_read(&page->_count));
|
|
set_page_count(page, 1);
|
|
}
|
|
|
|
/*
|
|
* split_page takes a non-compound higher-order page, and splits it into
|
|
* n (1<<order) sub-pages: page[0..n]
|
|
* Each sub-page must be freed individually.
|
|
*
|
|
* Note: this is probably too low level an operation for use in drivers.
|
|
* Please consult with lkml before using this in your driver.
|
|
*/
|
|
void split_page(struct page *page, unsigned int order)
|
|
{
|
|
int i;
|
|
|
|
VM_BUG_ON(PageCompound(page));
|
|
VM_BUG_ON(!page_count(page));
|
|
|
|
#ifdef CONFIG_KMEMCHECK
|
|
/*
|
|
* Split shadow pages too, because free(page[0]) would
|
|
* otherwise free the whole shadow.
|
|
*/
|
|
if (kmemcheck_page_is_tracked(page))
|
|
split_page(virt_to_page(page[0].shadow), order);
|
|
#endif
|
|
|
|
for (i = 1; i < (1 << order); i++)
|
|
set_page_refcounted(page + i);
|
|
}
|
|
EXPORT_SYMBOL_GPL(split_page);
|
|
|
|
struct action_devres {
|
|
void *data;
|
|
void (*action)(void *);
|
|
};
|
|
|
|
static void devm_action_release(struct device *dev, void *res)
|
|
{
|
|
struct action_devres *devres = res;
|
|
|
|
devres->action(devres->data);
|
|
}
|
|
|
|
/**
|
|
* devm_add_action() - add a custom action to list of managed resources
|
|
* @dev: Device that owns the action
|
|
* @action: Function that should be called
|
|
* @data: Pointer to data passed to @action implementation
|
|
*
|
|
* This adds a custom action to the list of managed resources so that
|
|
* it gets executed as part of standard resource unwinding.
|
|
*/
|
|
int devm_add_action(struct device *dev, void (*action)(void *), void *data)
|
|
{
|
|
struct action_devres *devres;
|
|
|
|
devres = devres_alloc(devm_action_release,
|
|
sizeof(struct action_devres), GFP_KERNEL);
|
|
if (!devres)
|
|
return -ENOMEM;
|
|
|
|
devres->data = data;
|
|
devres->action = action;
|
|
|
|
devres_add(dev, devres);
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL_GPL(devm_add_action);
|
|
|
|
#if ((LINUX_VERSION_IS_LESS(3,10,0) && LINUX_VERSION_IS_GEQ(3,3,0)) || LINUX_VERSION_IS_LESS(3,2,98))
|
|
void kfree_skb_list(struct sk_buff *segs)
|
|
{
|
|
while (segs) {
|
|
struct sk_buff *next = segs->next;
|
|
|
|
kfree_skb(segs);
|
|
segs = next;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(kfree_skb_list);
|
|
#endif
|