You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'master'
This commit is contained in:
@@ -19,6 +19,8 @@
|
||||
#include <linux/list.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "base.h"
|
||||
|
||||
/* This is a private structure used to tie the classdev and the
|
||||
* container .. it should never be visible outside this file */
|
||||
struct internal_container {
|
||||
|
||||
@@ -1,3 +1,15 @@
|
||||
|
||||
/* initialisation functions */
|
||||
|
||||
extern int devices_init(void);
|
||||
extern int buses_init(void);
|
||||
extern int classes_init(void);
|
||||
extern int firmware_init(void);
|
||||
extern int platform_bus_init(void);
|
||||
extern int system_bus_init(void);
|
||||
extern int cpu_dev_init(void);
|
||||
extern int attribute_container_init(void);
|
||||
|
||||
extern int bus_add_device(struct device * dev);
|
||||
extern void bus_remove_device(struct device * dev);
|
||||
|
||||
|
||||
+102
-52
@@ -99,7 +99,8 @@ struct class * class_get(struct class * cls)
|
||||
|
||||
void class_put(struct class * cls)
|
||||
{
|
||||
subsys_put(&cls->subsys);
|
||||
if (cls)
|
||||
subsys_put(&cls->subsys);
|
||||
}
|
||||
|
||||
|
||||
@@ -165,14 +166,25 @@ void class_unregister(struct class * cls)
|
||||
|
||||
static void class_create_release(struct class *cls)
|
||||
{
|
||||
pr_debug("%s called for %s\n", __FUNCTION__, cls->name);
|
||||
kfree(cls);
|
||||
}
|
||||
|
||||
static void class_device_create_release(struct class_device *class_dev)
|
||||
{
|
||||
pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id);
|
||||
kfree(class_dev);
|
||||
}
|
||||
|
||||
/* needed to allow these devices to have parent class devices */
|
||||
static int class_device_create_hotplug(struct class_device *class_dev,
|
||||
char **envp, int num_envp,
|
||||
char *buffer, int buffer_size)
|
||||
{
|
||||
pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* class_create - create a struct class structure
|
||||
* @owner: pointer to the module that is to "own" this struct class
|
||||
@@ -301,10 +313,12 @@ static void class_dev_release(struct kobject * kobj)
|
||||
kfree(cd->devt_attr);
|
||||
cd->devt_attr = NULL;
|
||||
|
||||
if (cls->release)
|
||||
if (cd->release)
|
||||
cd->release(cd);
|
||||
else if (cls->release)
|
||||
cls->release(cd);
|
||||
else {
|
||||
printk(KERN_ERR "Device class '%s' does not have a release() function, "
|
||||
printk(KERN_ERR "Class Device '%s' does not have a release() function, "
|
||||
"it is broken and must be fixed.\n",
|
||||
cd->class_id);
|
||||
WARN_ON(1);
|
||||
@@ -382,14 +396,18 @@ static int class_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
|
||||
buffer = &buffer[length];
|
||||
buffer_size -= length;
|
||||
|
||||
if (class_dev->class->hotplug) {
|
||||
/* have the bus specific function add its stuff */
|
||||
retval = class_dev->class->hotplug (class_dev, envp, num_envp,
|
||||
buffer, buffer_size);
|
||||
if (retval) {
|
||||
pr_debug ("%s - hotplug() returned %d\n",
|
||||
__FUNCTION__, retval);
|
||||
}
|
||||
if (class_dev->hotplug) {
|
||||
/* have the class device specific function add its stuff */
|
||||
retval = class_dev->hotplug(class_dev, envp, num_envp,
|
||||
buffer, buffer_size);
|
||||
if (retval)
|
||||
pr_debug("class_dev->hotplug() returned %d\n", retval);
|
||||
} else if (class_dev->class->hotplug) {
|
||||
/* have the class specific function add its stuff */
|
||||
retval = class_dev->class->hotplug(class_dev, envp, num_envp,
|
||||
buffer, buffer_size);
|
||||
if (retval)
|
||||
pr_debug("class->hotplug() returned %d\n", retval);
|
||||
}
|
||||
|
||||
return retval;
|
||||
@@ -442,6 +460,13 @@ static ssize_t show_dev(struct class_device *class_dev, char *buf)
|
||||
return print_dev_t(buf, class_dev->devt);
|
||||
}
|
||||
|
||||
static ssize_t store_uevent(struct class_device *class_dev,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
|
||||
return count;
|
||||
}
|
||||
|
||||
void class_device_initialize(struct class_device *class_dev)
|
||||
{
|
||||
kobj_set_kset_s(class_dev, class_obj_subsys);
|
||||
@@ -469,34 +494,45 @@ static char *make_class_name(struct class_device *class_dev)
|
||||
|
||||
int class_device_add(struct class_device *class_dev)
|
||||
{
|
||||
struct class * parent = NULL;
|
||||
struct class_interface * class_intf;
|
||||
struct class *parent_class = NULL;
|
||||
struct class_device *parent_class_dev = NULL;
|
||||
struct class_interface *class_intf;
|
||||
char *class_name = NULL;
|
||||
int error;
|
||||
int error = -EINVAL;
|
||||
|
||||
class_dev = class_device_get(class_dev);
|
||||
if (!class_dev)
|
||||
return -EINVAL;
|
||||
|
||||
if (!strlen(class_dev->class_id)) {
|
||||
error = -EINVAL;
|
||||
if (!strlen(class_dev->class_id))
|
||||
goto register_done;
|
||||
}
|
||||
|
||||
parent = class_get(class_dev->class);
|
||||
parent_class = class_get(class_dev->class);
|
||||
if (!parent_class)
|
||||
goto register_done;
|
||||
parent_class_dev = class_device_get(class_dev->parent);
|
||||
|
||||
pr_debug("CLASS: registering class device: ID = '%s'\n",
|
||||
class_dev->class_id);
|
||||
|
||||
/* first, register with generic layer. */
|
||||
kobject_set_name(&class_dev->kobj, "%s", class_dev->class_id);
|
||||
if (parent)
|
||||
class_dev->kobj.parent = &parent->subsys.kset.kobj;
|
||||
if (parent_class_dev)
|
||||
class_dev->kobj.parent = &parent_class_dev->kobj;
|
||||
else
|
||||
class_dev->kobj.parent = &parent_class->subsys.kset.kobj;
|
||||
|
||||
if ((error = kobject_add(&class_dev->kobj)))
|
||||
error = kobject_add(&class_dev->kobj);
|
||||
if (error)
|
||||
goto register_done;
|
||||
|
||||
/* add the needed attributes to this device */
|
||||
class_dev->uevent_attr.attr.name = "uevent";
|
||||
class_dev->uevent_attr.attr.mode = S_IWUSR;
|
||||
class_dev->uevent_attr.attr.owner = parent_class->owner;
|
||||
class_dev->uevent_attr.store = store_uevent;
|
||||
class_device_create_file(class_dev, &class_dev->uevent_attr);
|
||||
|
||||
if (MAJOR(class_dev->devt)) {
|
||||
struct class_device_attribute *attr;
|
||||
attr = kzalloc(sizeof(*attr), GFP_KERNEL);
|
||||
@@ -505,12 +541,10 @@ int class_device_add(struct class_device *class_dev)
|
||||
kobject_del(&class_dev->kobj);
|
||||
goto register_done;
|
||||
}
|
||||
|
||||
attr->attr.name = "dev";
|
||||
attr->attr.mode = S_IRUGO;
|
||||
attr->attr.owner = parent->owner;
|
||||
attr->attr.owner = parent_class->owner;
|
||||
attr->show = show_dev;
|
||||
attr->store = NULL;
|
||||
class_device_create_file(class_dev, attr);
|
||||
class_dev->devt_attr = attr;
|
||||
}
|
||||
@@ -524,20 +558,23 @@ int class_device_add(struct class_device *class_dev)
|
||||
class_name);
|
||||
}
|
||||
|
||||
/* notify any interfaces this device is now here */
|
||||
if (parent) {
|
||||
down(&parent->sem);
|
||||
list_add_tail(&class_dev->node, &parent->children);
|
||||
list_for_each_entry(class_intf, &parent->interfaces, node)
|
||||
if (class_intf->add)
|
||||
class_intf->add(class_dev);
|
||||
up(&parent->sem);
|
||||
}
|
||||
kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
|
||||
|
||||
/* notify any interfaces this device is now here */
|
||||
if (parent_class) {
|
||||
down(&parent_class->sem);
|
||||
list_add_tail(&class_dev->node, &parent_class->children);
|
||||
list_for_each_entry(class_intf, &parent_class->interfaces, node)
|
||||
if (class_intf->add)
|
||||
class_intf->add(class_dev, class_intf);
|
||||
up(&parent_class->sem);
|
||||
}
|
||||
|
||||
register_done:
|
||||
if (error && parent)
|
||||
class_put(parent);
|
||||
if (error) {
|
||||
class_put(parent_class);
|
||||
class_device_put(parent_class_dev);
|
||||
}
|
||||
class_device_put(class_dev);
|
||||
kfree(class_name);
|
||||
return error;
|
||||
@@ -552,21 +589,28 @@ int class_device_register(struct class_device *class_dev)
|
||||
/**
|
||||
* class_device_create - creates a class device and registers it with sysfs
|
||||
* @cs: pointer to the struct class that this device should be registered to.
|
||||
* @parent: pointer to the parent struct class_device of this new device, if any.
|
||||
* @dev: the dev_t for the char device to be added.
|
||||
* @device: a pointer to a struct device that is assiociated with this class device.
|
||||
* @fmt: string for the class device's name
|
||||
*
|
||||
* This function can be used by char device classes. A struct
|
||||
* class_device will be created in sysfs, registered to the specified
|
||||
* class. A "dev" file will be created, showing the dev_t for the
|
||||
* device. The pointer to the struct class_device will be returned from
|
||||
* the call. Any further sysfs files that might be required can be
|
||||
* created using this pointer.
|
||||
* class.
|
||||
* A "dev" file will be created, showing the dev_t for the device, if
|
||||
* the dev_t is not 0,0.
|
||||
* If a pointer to a parent struct class_device is passed in, the newly
|
||||
* created struct class_device will be a child of that device in sysfs.
|
||||
* The pointer to the struct class_device will be returned from the
|
||||
* call. Any further sysfs files that might be required can be created
|
||||
* using this pointer.
|
||||
*
|
||||
* Note: the struct class passed to this function must have previously
|
||||
* been created with a call to class_create().
|
||||
*/
|
||||
struct class_device *class_device_create(struct class *cls, dev_t devt,
|
||||
struct class_device *class_device_create(struct class *cls,
|
||||
struct class_device *parent,
|
||||
dev_t devt,
|
||||
struct device *device, char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
@@ -585,6 +629,9 @@ struct class_device *class_device_create(struct class *cls, dev_t devt,
|
||||
class_dev->devt = devt;
|
||||
class_dev->dev = device;
|
||||
class_dev->class = cls;
|
||||
class_dev->parent = parent;
|
||||
class_dev->release = class_device_create_release;
|
||||
class_dev->hotplug = class_device_create_hotplug;
|
||||
|
||||
va_start(args, fmt);
|
||||
vsnprintf(class_dev->class_id, BUS_ID_SIZE, fmt, args);
|
||||
@@ -602,17 +649,18 @@ error:
|
||||
|
||||
void class_device_del(struct class_device *class_dev)
|
||||
{
|
||||
struct class * parent = class_dev->class;
|
||||
struct class_interface * class_intf;
|
||||
struct class *parent_class = class_dev->class;
|
||||
struct class_device *parent_device = class_dev->parent;
|
||||
struct class_interface *class_intf;
|
||||
char *class_name = NULL;
|
||||
|
||||
if (parent) {
|
||||
down(&parent->sem);
|
||||
if (parent_class) {
|
||||
down(&parent_class->sem);
|
||||
list_del_init(&class_dev->node);
|
||||
list_for_each_entry(class_intf, &parent->interfaces, node)
|
||||
list_for_each_entry(class_intf, &parent_class->interfaces, node)
|
||||
if (class_intf->remove)
|
||||
class_intf->remove(class_dev);
|
||||
up(&parent->sem);
|
||||
class_intf->remove(class_dev, class_intf);
|
||||
up(&parent_class->sem);
|
||||
}
|
||||
|
||||
if (class_dev->dev) {
|
||||
@@ -620,6 +668,7 @@ void class_device_del(struct class_device *class_dev)
|
||||
sysfs_remove_link(&class_dev->kobj, "device");
|
||||
sysfs_remove_link(&class_dev->dev->kobj, class_name);
|
||||
}
|
||||
class_device_remove_file(class_dev, &class_dev->uevent_attr);
|
||||
if (class_dev->devt_attr)
|
||||
class_device_remove_file(class_dev, class_dev->devt_attr);
|
||||
class_device_remove_attrs(class_dev);
|
||||
@@ -627,8 +676,8 @@ void class_device_del(struct class_device *class_dev)
|
||||
kobject_hotplug(&class_dev->kobj, KOBJ_REMOVE);
|
||||
kobject_del(&class_dev->kobj);
|
||||
|
||||
if (parent)
|
||||
class_put(parent);
|
||||
class_device_put(parent_device);
|
||||
class_put(parent_class);
|
||||
kfree(class_name);
|
||||
}
|
||||
|
||||
@@ -708,7 +757,8 @@ struct class_device * class_device_get(struct class_device *class_dev)
|
||||
|
||||
void class_device_put(struct class_device *class_dev)
|
||||
{
|
||||
kobject_put(&class_dev->kobj);
|
||||
if (class_dev)
|
||||
kobject_put(&class_dev->kobj);
|
||||
}
|
||||
|
||||
|
||||
@@ -728,7 +778,7 @@ int class_interface_register(struct class_interface *class_intf)
|
||||
list_add_tail(&class_intf->node, &parent->interfaces);
|
||||
if (class_intf->add) {
|
||||
list_for_each_entry(class_dev, &parent->children, node)
|
||||
class_intf->add(class_dev);
|
||||
class_intf->add(class_dev, class_intf);
|
||||
}
|
||||
up(&parent->sem);
|
||||
|
||||
@@ -747,7 +797,7 @@ void class_interface_unregister(struct class_interface *class_intf)
|
||||
list_del_init(&class_intf->node);
|
||||
if (class_intf->remove) {
|
||||
list_for_each_entry(class_dev, &parent->children, node)
|
||||
class_intf->remove(class_dev);
|
||||
class_intf->remove(class_dev, class_intf);
|
||||
}
|
||||
up(&parent->sem);
|
||||
|
||||
|
||||
+19
-2
@@ -154,6 +154,13 @@ static struct kset_hotplug_ops device_hotplug_ops = {
|
||||
.hotplug = dev_hotplug,
|
||||
};
|
||||
|
||||
static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
kobject_hotplug(&dev->kobj, KOBJ_ADD);
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* device_subsys - structure to be registered with kobject core.
|
||||
*/
|
||||
@@ -225,6 +232,7 @@ void device_initialize(struct device *dev)
|
||||
klist_children_put);
|
||||
INIT_LIST_HEAD(&dev->dma_pools);
|
||||
init_MUTEX(&dev->sem);
|
||||
device_init_wakeup(dev, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -258,6 +266,14 @@ int device_add(struct device *dev)
|
||||
|
||||
if ((error = kobject_add(&dev->kobj)))
|
||||
goto Error;
|
||||
|
||||
dev->uevent_attr.attr.name = "uevent";
|
||||
dev->uevent_attr.attr.mode = S_IWUSR;
|
||||
if (dev->driver)
|
||||
dev->uevent_attr.attr.owner = dev->driver->owner;
|
||||
dev->uevent_attr.store = store_uevent;
|
||||
device_create_file(dev, &dev->uevent_attr);
|
||||
|
||||
kobject_hotplug(&dev->kobj, KOBJ_ADD);
|
||||
if ((error = device_pm_add(dev)))
|
||||
goto PMError;
|
||||
@@ -349,6 +365,7 @@ void device_del(struct device * dev)
|
||||
|
||||
if (parent)
|
||||
klist_del(&dev->knode_parent);
|
||||
device_remove_file(dev, &dev->uevent_attr);
|
||||
|
||||
/* Notify the platform of the removal, in case they
|
||||
* need to do anything...
|
||||
@@ -390,11 +407,11 @@ static struct device * next_device(struct klist_iter * i)
|
||||
|
||||
/**
|
||||
* device_for_each_child - device child iterator.
|
||||
* @dev: parent struct device.
|
||||
* @parent: parent struct device.
|
||||
* @data: data for the callback.
|
||||
* @fn: function to be called for each device.
|
||||
*
|
||||
* Iterate over @dev's child devices, and call @fn for each,
|
||||
* Iterate over @parent's child devices, and call @fn for each,
|
||||
* passing it @data.
|
||||
*
|
||||
* We check the return of @fn each time. If it returns anything
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <linux/topology.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
#include "base.h"
|
||||
|
||||
struct sysdev_class cpu_sysdev_class = {
|
||||
set_kset_name("cpu"),
|
||||
|
||||
@@ -28,6 +28,7 @@ static struct device * next_device(struct klist_iter * i)
|
||||
/**
|
||||
* driver_for_each_device - Iterator for devices bound to a driver.
|
||||
* @drv: Driver we're iterating.
|
||||
* @start: Device to begin with
|
||||
* @data: Data to pass to the callback.
|
||||
* @fn: Function to call for each device.
|
||||
*
|
||||
@@ -57,7 +58,7 @@ EXPORT_SYMBOL_GPL(driver_for_each_device);
|
||||
|
||||
/**
|
||||
* driver_find_device - device iterator for locating a particular device.
|
||||
* @driver: The device's driver
|
||||
* @drv: The device's driver
|
||||
* @start: Device to begin with
|
||||
* @data: Data to pass to match function
|
||||
* @match: Callback function to check device
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
#include "base.h"
|
||||
|
||||
static decl_subsys(firmware, NULL, NULL);
|
||||
|
||||
|
||||
+2
-8
@@ -10,14 +10,8 @@
|
||||
#include <linux/device.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
extern int devices_init(void);
|
||||
extern int buses_init(void);
|
||||
extern int classes_init(void);
|
||||
extern int firmware_init(void);
|
||||
extern int platform_bus_init(void);
|
||||
extern int system_bus_init(void);
|
||||
extern int cpu_dev_init(void);
|
||||
extern int attribute_container_init(void);
|
||||
#include "base.h"
|
||||
|
||||
/**
|
||||
* driver_init - initialize driver model.
|
||||
*
|
||||
|
||||
+8
-14
@@ -17,6 +17,8 @@
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#include "base.h"
|
||||
|
||||
struct device platform_bus = {
|
||||
.bus_id = "platform",
|
||||
};
|
||||
@@ -279,13 +281,9 @@ static int platform_suspend(struct device * dev, pm_message_t state)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (dev->driver && dev->driver->suspend) {
|
||||
ret = dev->driver->suspend(dev, state, SUSPEND_DISABLE);
|
||||
if (ret == 0)
|
||||
ret = dev->driver->suspend(dev, state, SUSPEND_SAVE_STATE);
|
||||
if (ret == 0)
|
||||
ret = dev->driver->suspend(dev, state, SUSPEND_POWER_DOWN);
|
||||
}
|
||||
if (dev->driver && dev->driver->suspend)
|
||||
ret = dev->driver->suspend(dev, state);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -293,13 +291,9 @@ static int platform_resume(struct device * dev)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (dev->driver && dev->driver->resume) {
|
||||
ret = dev->driver->resume(dev, RESUME_POWER_ON);
|
||||
if (ret == 0)
|
||||
ret = dev->driver->resume(dev, RESUME_RESTORE_STATE);
|
||||
if (ret == 0)
|
||||
ret = dev->driver->resume(dev, RESUME_ENABLE);
|
||||
}
|
||||
if (dev->driver && dev->driver->resume)
|
||||
ret = dev->driver->resume(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -48,8 +48,81 @@ static ssize_t state_store(struct device * dev, struct device_attribute *attr, c
|
||||
static DEVICE_ATTR(state, 0644, state_show, state_store);
|
||||
|
||||
|
||||
/*
|
||||
* wakeup - Report/change current wakeup option for device
|
||||
*
|
||||
* Some devices support "wakeup" events, which are hardware signals
|
||||
* used to activate devices from suspended or low power states. Such
|
||||
* devices have one of three values for the sysfs power/wakeup file:
|
||||
*
|
||||
* + "enabled\n" to issue the events;
|
||||
* + "disabled\n" not to do so; or
|
||||
* + "\n" for temporary or permanent inability to issue wakeup.
|
||||
*
|
||||
* (For example, unconfigured USB devices can't issue wakeups.)
|
||||
*
|
||||
* Familiar examples of devices that can issue wakeup events include
|
||||
* keyboards and mice (both PS2 and USB styles), power buttons, modems,
|
||||
* "Wake-On-LAN" Ethernet links, GPIO lines, and more. Some events
|
||||
* will wake the entire system from a suspend state; others may just
|
||||
* wake up the device (if the system as a whole is already active).
|
||||
* Some wakeup events use normal IRQ lines; other use special out
|
||||
* of band signaling.
|
||||
*
|
||||
* It is the responsibility of device drivers to enable (or disable)
|
||||
* wakeup signaling as part of changing device power states, respecting
|
||||
* the policy choices provided through the driver model.
|
||||
*
|
||||
* Devices may not be able to generate wakeup events from all power
|
||||
* states. Also, the events may be ignored in some configurations;
|
||||
* for example, they might need help from other devices that aren't
|
||||
* active, or which may have wakeup disabled. Some drivers rely on
|
||||
* wakeup events internally (unless they are disabled), keeping
|
||||
* their hardware in low power modes whenever they're unused. This
|
||||
* saves runtime power, without requiring system-wide sleep states.
|
||||
*/
|
||||
|
||||
static const char enabled[] = "enabled";
|
||||
static const char disabled[] = "disabled";
|
||||
|
||||
static ssize_t
|
||||
wake_show(struct device * dev, struct device_attribute *attr, char * buf)
|
||||
{
|
||||
return sprintf(buf, "%s\n", device_can_wakeup(dev)
|
||||
? (device_may_wakeup(dev) ? enabled : disabled)
|
||||
: "");
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
wake_store(struct device * dev, struct device_attribute *attr,
|
||||
const char * buf, size_t n)
|
||||
{
|
||||
char *cp;
|
||||
int len = n;
|
||||
|
||||
if (!device_can_wakeup(dev))
|
||||
return -EINVAL;
|
||||
|
||||
cp = memchr(buf, '\n', n);
|
||||
if (cp)
|
||||
len = cp - buf;
|
||||
if (len == sizeof enabled - 1
|
||||
&& strncmp(buf, enabled, sizeof enabled - 1) == 0)
|
||||
device_set_wakeup_enable(dev, 1);
|
||||
else if (len == sizeof disabled - 1
|
||||
&& strncmp(buf, disabled, sizeof disabled - 1) == 0)
|
||||
device_set_wakeup_enable(dev, 0);
|
||||
else
|
||||
return -EINVAL;
|
||||
return n;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(wakeup, 0644, wake_show, wake_store);
|
||||
|
||||
|
||||
static struct attribute * power_attrs[] = {
|
||||
&dev_attr_state.attr,
|
||||
&dev_attr_wakeup.attr,
|
||||
NULL,
|
||||
};
|
||||
static struct attribute_group pm_attr_group = {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */
|
||||
#define VERSION "12"
|
||||
#define VERSION "14"
|
||||
#define AOE_MAJOR 152
|
||||
#define DEVICE_NAME "aoe"
|
||||
|
||||
|
||||
@@ -224,7 +224,7 @@ aoechr_init(void)
|
||||
return PTR_ERR(aoe_class);
|
||||
}
|
||||
for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
|
||||
class_device_create(aoe_class,
|
||||
class_device_create(aoe_class, NULL,
|
||||
MKDEV(AOE_MAJOR, chardevs[i].minor),
|
||||
NULL, chardevs[i].name);
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include "aoe.h"
|
||||
|
||||
#define TIMERTICK (HZ / 10)
|
||||
@@ -311,16 +312,16 @@ ataid_complete(struct aoedev *d, unsigned char *id)
|
||||
u16 n;
|
||||
|
||||
/* word 83: command set supported */
|
||||
n = le16_to_cpup((__le16 *) &id[83<<1]);
|
||||
n = le16_to_cpu(get_unaligned((__le16 *) &id[83<<1]));
|
||||
|
||||
/* word 86: command set/feature enabled */
|
||||
n |= le16_to_cpup((__le16 *) &id[86<<1]);
|
||||
n |= le16_to_cpu(get_unaligned((__le16 *) &id[86<<1]));
|
||||
|
||||
if (n & (1<<10)) { /* bit 10: LBA 48 */
|
||||
d->flags |= DEVFL_EXT;
|
||||
|
||||
/* word 100: number lba48 sectors */
|
||||
ssize = le64_to_cpup((__le64 *) &id[100<<1]);
|
||||
ssize = le64_to_cpu(get_unaligned((__le64 *) &id[100<<1]));
|
||||
|
||||
/* set as in ide-disk.c:init_idedisk_capacity */
|
||||
d->geo.cylinders = ssize;
|
||||
@@ -331,12 +332,12 @@ ataid_complete(struct aoedev *d, unsigned char *id)
|
||||
d->flags &= ~DEVFL_EXT;
|
||||
|
||||
/* number lba28 sectors */
|
||||
ssize = le32_to_cpup((__le32 *) &id[60<<1]);
|
||||
ssize = le32_to_cpu(get_unaligned((__le32 *) &id[60<<1]));
|
||||
|
||||
/* NOTE: obsolete in ATA 6 */
|
||||
d->geo.cylinders = le16_to_cpup((__le16 *) &id[54<<1]);
|
||||
d->geo.heads = le16_to_cpup((__le16 *) &id[55<<1]);
|
||||
d->geo.sectors = le16_to_cpup((__le16 *) &id[56<<1]);
|
||||
d->geo.cylinders = le16_to_cpu(get_unaligned((__le16 *) &id[54<<1]));
|
||||
d->geo.heads = le16_to_cpu(get_unaligned((__le16 *) &id[55<<1]));
|
||||
d->geo.sectors = le16_to_cpu(get_unaligned((__le16 *) &id[56<<1]));
|
||||
}
|
||||
d->ssize = ssize;
|
||||
d->geo.start = 0;
|
||||
|
||||
@@ -337,10 +337,30 @@ static ssize_t disk_attr_show(struct kobject *kobj, struct attribute *attr,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t disk_attr_store(struct kobject * kobj, struct attribute * attr,
|
||||
const char *page, size_t count)
|
||||
{
|
||||
struct gendisk *disk = to_disk(kobj);
|
||||
struct disk_attribute *disk_attr =
|
||||
container_of(attr,struct disk_attribute,attr);
|
||||
ssize_t ret = 0;
|
||||
|
||||
if (disk_attr->store)
|
||||
ret = disk_attr->store(disk, page, count);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct sysfs_ops disk_sysfs_ops = {
|
||||
.show = &disk_attr_show,
|
||||
.store = &disk_attr_store,
|
||||
};
|
||||
|
||||
static ssize_t disk_uevent_store(struct gendisk * disk,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
kobject_hotplug(&disk->kobj, KOBJ_ADD);
|
||||
return count;
|
||||
}
|
||||
static ssize_t disk_dev_read(struct gendisk * disk, char *page)
|
||||
{
|
||||
dev_t base = MKDEV(disk->major, disk->first_minor);
|
||||
@@ -382,6 +402,10 @@ static ssize_t disk_stats_read(struct gendisk * disk, char *page)
|
||||
jiffies_to_msecs(disk_stat_read(disk, io_ticks)),
|
||||
jiffies_to_msecs(disk_stat_read(disk, time_in_queue)));
|
||||
}
|
||||
static struct disk_attribute disk_attr_uevent = {
|
||||
.attr = {.name = "uevent", .mode = S_IWUSR },
|
||||
.store = disk_uevent_store
|
||||
};
|
||||
static struct disk_attribute disk_attr_dev = {
|
||||
.attr = {.name = "dev", .mode = S_IRUGO },
|
||||
.show = disk_dev_read
|
||||
@@ -404,6 +428,7 @@ static struct disk_attribute disk_attr_stat = {
|
||||
};
|
||||
|
||||
static struct attribute * default_attrs[] = {
|
||||
&disk_attr_uevent.attr,
|
||||
&disk_attr_dev.attr,
|
||||
&disk_attr_range.attr,
|
||||
&disk_attr_removable.attr,
|
||||
|
||||
@@ -674,7 +674,7 @@ static int __init pg_init(void)
|
||||
for (unit = 0; unit < PG_UNITS; unit++) {
|
||||
struct pg *dev = &devices[unit];
|
||||
if (dev->present) {
|
||||
class_device_create(pg_class, MKDEV(major, unit),
|
||||
class_device_create(pg_class, NULL, MKDEV(major, unit),
|
||||
NULL, "pg%u", unit);
|
||||
err = devfs_mk_cdev(MKDEV(major, unit),
|
||||
S_IFCHR | S_IRUSR | S_IWUSR, "pg/%u",
|
||||
|
||||
@@ -971,7 +971,7 @@ static int __init pt_init(void)
|
||||
devfs_mk_dir("pt");
|
||||
for (unit = 0; unit < PT_UNITS; unit++)
|
||||
if (pt[unit].present) {
|
||||
class_device_create(pt_class, MKDEV(major, unit),
|
||||
class_device_create(pt_class, NULL, MKDEV(major, unit),
|
||||
NULL, "pt%d", unit);
|
||||
err = devfs_mk_cdev(MKDEV(major, unit),
|
||||
S_IFCHR | S_IRUSR | S_IWUSR,
|
||||
@@ -980,7 +980,7 @@ static int __init pt_init(void)
|
||||
class_device_destroy(pt_class, MKDEV(major, unit));
|
||||
goto out_class;
|
||||
}
|
||||
class_device_create(pt_class, MKDEV(major, unit + 128),
|
||||
class_device_create(pt_class, NULL, MKDEV(major, unit + 128),
|
||||
NULL, "pt%dn", unit);
|
||||
err = devfs_mk_cdev(MKDEV(major, unit + 128),
|
||||
S_IFCHR | S_IRUSR | S_IWUSR,
|
||||
|
||||
+37
-14
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* sx8.c: Driver for Promise SATA SX8 looks-like-I2O hardware
|
||||
*
|
||||
* Copyright 2004 Red Hat, Inc.
|
||||
* Copyright 2004-2005 Red Hat, Inc.
|
||||
*
|
||||
* Author/maintainer: Jeff Garzik <jgarzik@pobox.com>
|
||||
*
|
||||
@@ -31,10 +31,6 @@
|
||||
#include <asm/semaphore.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
MODULE_AUTHOR("Jeff Garzik");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Promise SATA SX8 block driver");
|
||||
|
||||
#if 0
|
||||
#define CARM_DEBUG
|
||||
#define CARM_VERBOSE_DEBUG
|
||||
@@ -45,9 +41,35 @@ MODULE_DESCRIPTION("Promise SATA SX8 block driver");
|
||||
#undef CARM_NDEBUG
|
||||
|
||||
#define DRV_NAME "sx8"
|
||||
#define DRV_VERSION "0.8"
|
||||
#define DRV_VERSION "1.0"
|
||||
#define PFX DRV_NAME ": "
|
||||
|
||||
MODULE_AUTHOR("Jeff Garzik");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Promise SATA SX8 block driver");
|
||||
MODULE_VERSION(DRV_VERSION);
|
||||
|
||||
/*
|
||||
* SX8 hardware has a single message queue for all ATA ports.
|
||||
* When this driver was written, the hardware (firmware?) would
|
||||
* corrupt data eventually, if more than one request was outstanding.
|
||||
* As one can imagine, having 8 ports bottlenecking on a single
|
||||
* command hurts performance.
|
||||
*
|
||||
* Based on user reports, later versions of the hardware (firmware?)
|
||||
* seem to be able to survive with more than one command queued.
|
||||
*
|
||||
* Therefore, we default to the safe option -- 1 command -- but
|
||||
* allow the user to increase this.
|
||||
*
|
||||
* SX8 should be able to support up to ~60 queued commands (CARM_MAX_REQ),
|
||||
* but problems seem to occur when you exceed ~30, even on newer hardware.
|
||||
*/
|
||||
static int max_queue = 1;
|
||||
module_param(max_queue, int, 0444);
|
||||
MODULE_PARM_DESC(max_queue, "Maximum number of queued commands. (min==1, max==30, safe==1)");
|
||||
|
||||
|
||||
#define NEXT_RESP(idx) ((idx + 1) % RMSG_Q_LEN)
|
||||
|
||||
/* 0xf is just arbitrary, non-zero noise; this is sorta like poisoning */
|
||||
@@ -90,12 +112,10 @@ enum {
|
||||
|
||||
/* command message queue limits */
|
||||
CARM_MAX_REQ = 64, /* max command msgs per host */
|
||||
CARM_MAX_Q = 1, /* one command at a time */
|
||||
CARM_MSG_LOW_WATER = (CARM_MAX_REQ / 4), /* refill mark */
|
||||
|
||||
/* S/G limits, host-wide and per-request */
|
||||
CARM_MAX_REQ_SG = 32, /* max s/g entries per request */
|
||||
CARM_SG_BOUNDARY = 0xffffUL, /* s/g segment boundary */
|
||||
CARM_MAX_HOST_SG = 600, /* max s/g entries per host */
|
||||
CARM_SG_LOW_WATER = (CARM_MAX_HOST_SG / 4), /* re-fill mark */
|
||||
|
||||
@@ -181,6 +201,10 @@ enum {
|
||||
FL_DYN_MAJOR = (1 << 17),
|
||||
};
|
||||
|
||||
enum {
|
||||
CARM_SG_BOUNDARY = 0xffffUL, /* s/g segment boundary */
|
||||
};
|
||||
|
||||
enum scatter_gather_types {
|
||||
SGT_32BIT = 0,
|
||||
SGT_64BIT = 1,
|
||||
@@ -218,7 +242,6 @@ static const char *state_name[] = {
|
||||
|
||||
struct carm_port {
|
||||
unsigned int port_no;
|
||||
unsigned int n_queued;
|
||||
struct gendisk *disk;
|
||||
struct carm_host *host;
|
||||
|
||||
@@ -448,7 +471,7 @@ static inline int carm_lookup_bucket(u32 msg_size)
|
||||
for (i = 0; i < ARRAY_SIZE(msg_sizes); i++)
|
||||
if (msg_size <= msg_sizes[i])
|
||||
return i;
|
||||
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
@@ -509,7 +532,7 @@ static struct carm_request *carm_get_request(struct carm_host *host)
|
||||
if (host->hw_sg_used >= (CARM_MAX_HOST_SG - CARM_MAX_REQ_SG))
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < CARM_MAX_Q; i++)
|
||||
for (i = 0; i < max_queue; i++)
|
||||
if ((host->msg_alloc & (1ULL << i)) == 0) {
|
||||
struct carm_request *crq = &host->req[i];
|
||||
crq->port = NULL;
|
||||
@@ -521,14 +544,14 @@ static struct carm_request *carm_get_request(struct carm_host *host)
|
||||
assert(host->n_msgs <= CARM_MAX_REQ);
|
||||
return crq;
|
||||
}
|
||||
|
||||
|
||||
DPRINTK("no request available, returning NULL\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int carm_put_request(struct carm_host *host, struct carm_request *crq)
|
||||
{
|
||||
assert(crq->tag < CARM_MAX_Q);
|
||||
assert(crq->tag < max_queue);
|
||||
|
||||
if (unlikely((host->msg_alloc & (1ULL << crq->tag)) == 0))
|
||||
return -EINVAL; /* tried to clear a tag that was not active */
|
||||
@@ -791,7 +814,7 @@ static inline void carm_end_rq(struct carm_host *host, struct carm_request *crq,
|
||||
int is_ok)
|
||||
{
|
||||
carm_end_request_queued(host, crq, is_ok);
|
||||
if (CARM_MAX_Q == 1)
|
||||
if (max_queue == 1)
|
||||
carm_round_robin(host);
|
||||
else if ((host->n_msgs <= CARM_MSG_LOW_WATER) &&
|
||||
(host->hw_sg_used <= CARM_SG_LOW_WATER)) {
|
||||
|
||||
@@ -55,14 +55,6 @@ config BT_HCIUART_BCSP
|
||||
|
||||
Say Y here to compile support for HCI BCSP protocol.
|
||||
|
||||
config BT_HCIUART_BCSP_TXCRC
|
||||
bool "Transmit CRC with every BCSP packet"
|
||||
depends on BT_HCIUART_BCSP
|
||||
help
|
||||
If you say Y here, a 16-bit CRC checksum will be transmitted along with
|
||||
every BCSP (BlueCore Serial Protocol) packet sent to the Bluetooth chip.
|
||||
This increases reliability, but slightly reduces efficiency.
|
||||
|
||||
config BT_HCIBCM203X
|
||||
tristate "HCI BCM203x USB driver"
|
||||
depends on USB
|
||||
|
||||
@@ -550,6 +550,9 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *
|
||||
if (ignore)
|
||||
return -ENODEV;
|
||||
|
||||
if (intf->cur_altsetting->desc.bInterfaceNumber > 0)
|
||||
return -ENODEV;
|
||||
|
||||
data = kmalloc(sizeof(*data), GFP_KERNEL);
|
||||
if (!data) {
|
||||
BT_ERR("Can't allocate data structure");
|
||||
|
||||
+100
-60
@@ -1,35 +1,27 @@
|
||||
/*
|
||||
BlueCore Serial Protocol (BCSP) for Linux Bluetooth stack (BlueZ).
|
||||
Copyright 2002 by Fabrizio Gennari <fabrizio.gennari@philips.com>
|
||||
|
||||
Based on
|
||||
hci_h4.c by Maxim Krasnyansky <maxk@qualcomm.com>
|
||||
ABCSP by Carl Orsborn <cjo@csr.com>
|
||||
|
||||
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;
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
|
||||
CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
|
||||
COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
|
||||
SOFTWARE IS DISCLAIMED.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id: hci_bcsp.c,v 1.2 2002/09/26 05:05:14 maxk Exp $
|
||||
*
|
||||
* Bluetooth HCI UART driver
|
||||
*
|
||||
* Copyright (C) 2002-2003 Fabrizio Gennari <fabrizio.gennari@philips.com>
|
||||
* Copyright (C) 2004-2005 Marcel Holtmann <marcel@holtmann.org>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#define VERSION "0.2"
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
@@ -52,16 +44,56 @@
|
||||
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
|
||||
#include "hci_uart.h"
|
||||
#include "hci_bcsp.h"
|
||||
|
||||
#ifndef CONFIG_BT_HCIUART_DEBUG
|
||||
#undef BT_DBG
|
||||
#define BT_DBG( A... )
|
||||
#endif
|
||||
|
||||
#define VERSION "0.3"
|
||||
|
||||
static int txcrc = 1;
|
||||
static int hciextn = 1;
|
||||
|
||||
#define BCSP_TXWINSIZE 4
|
||||
|
||||
#define BCSP_ACK_PKT 0x05
|
||||
#define BCSP_LE_PKT 0x06
|
||||
|
||||
struct bcsp_struct {
|
||||
struct sk_buff_head unack; /* Unack'ed packets queue */
|
||||
struct sk_buff_head rel; /* Reliable packets queue */
|
||||
struct sk_buff_head unrel; /* Unreliable packets queue */
|
||||
|
||||
unsigned long rx_count;
|
||||
struct sk_buff *rx_skb;
|
||||
u8 rxseq_txack; /* rxseq == txack. */
|
||||
u8 rxack; /* Last packet sent by us that the peer ack'ed */
|
||||
struct timer_list tbcsp;
|
||||
|
||||
enum {
|
||||
BCSP_W4_PKT_DELIMITER,
|
||||
BCSP_W4_PKT_START,
|
||||
BCSP_W4_BCSP_HDR,
|
||||
BCSP_W4_DATA,
|
||||
BCSP_W4_CRC
|
||||
} rx_state;
|
||||
|
||||
enum {
|
||||
BCSP_ESCSTATE_NOESC,
|
||||
BCSP_ESCSTATE_ESC
|
||||
} rx_esc_state;
|
||||
|
||||
u8 use_crc;
|
||||
u16 message_crc;
|
||||
u8 txack_req; /* Do we need to send ack's to the peer? */
|
||||
|
||||
/* Reliable packet sequence number - used to assign seq to each rel pkt. */
|
||||
u8 msgq_txseq;
|
||||
};
|
||||
|
||||
/* ---- BCSP CRC calculation ---- */
|
||||
|
||||
/* Table for calculating CRC for polynomial 0x1021, LSB processed first,
|
||||
@@ -111,6 +143,7 @@ static u16 bcsp_crc_reverse(u16 crc)
|
||||
rev |= (crc & 1);
|
||||
crc = crc >> 1;
|
||||
}
|
||||
|
||||
return (rev);
|
||||
}
|
||||
|
||||
@@ -119,6 +152,7 @@ static u16 bcsp_crc_reverse(u16 crc)
|
||||
static void bcsp_slip_msgdelim(struct sk_buff *skb)
|
||||
{
|
||||
const char pkt_delim = 0xc0;
|
||||
|
||||
memcpy(skb_put(skb, 1), &pkt_delim, 1);
|
||||
}
|
||||
|
||||
@@ -173,11 +207,8 @@ static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data,
|
||||
{
|
||||
struct sk_buff *nskb;
|
||||
u8 hdr[4], chan;
|
||||
int rel, i;
|
||||
|
||||
#ifdef CONFIG_BT_HCIUART_BCSP_TXCRC
|
||||
u16 BCSP_CRC_INIT(bcsp_txmsg_crc);
|
||||
#endif
|
||||
int rel, i;
|
||||
|
||||
switch (pkt_type) {
|
||||
case HCI_ACLDATA_PKT:
|
||||
@@ -240,9 +271,9 @@ static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data,
|
||||
BT_DBG("Sending packet with seqno %u", bcsp->msgq_txseq);
|
||||
bcsp->msgq_txseq = ++(bcsp->msgq_txseq) & 0x07;
|
||||
}
|
||||
#ifdef CONFIG_BT_HCIUART_BCSP_TXCRC
|
||||
hdr[0] |= 0x40;
|
||||
#endif
|
||||
|
||||
if (bcsp->use_crc)
|
||||
hdr[0] |= 0x40;
|
||||
|
||||
hdr[1] = ((len << 4) & 0xff) | chan;
|
||||
hdr[2] = len >> 4;
|
||||
@@ -251,25 +282,25 @@ static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data,
|
||||
/* Put BCSP header */
|
||||
for (i = 0; i < 4; i++) {
|
||||
bcsp_slip_one_byte(nskb, hdr[i]);
|
||||
#ifdef CONFIG_BT_HCIUART_BCSP_TXCRC
|
||||
bcsp_crc_update(&bcsp_txmsg_crc, hdr[i]);
|
||||
#endif
|
||||
|
||||
if (bcsp->use_crc)
|
||||
bcsp_crc_update(&bcsp_txmsg_crc, hdr[i]);
|
||||
}
|
||||
|
||||
/* Put payload */
|
||||
for (i = 0; i < len; i++) {
|
||||
bcsp_slip_one_byte(nskb, data[i]);
|
||||
#ifdef CONFIG_BT_HCIUART_BCSP_TXCRC
|
||||
bcsp_crc_update(&bcsp_txmsg_crc, data[i]);
|
||||
#endif
|
||||
|
||||
if (bcsp->use_crc)
|
||||
bcsp_crc_update(&bcsp_txmsg_crc, data[i]);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BT_HCIUART_BCSP_TXCRC
|
||||
/* Put CRC */
|
||||
bcsp_txmsg_crc = bcsp_crc_reverse(bcsp_txmsg_crc);
|
||||
bcsp_slip_one_byte(nskb, (u8) ((bcsp_txmsg_crc >> 8) & 0x00ff));
|
||||
bcsp_slip_one_byte(nskb, (u8) (bcsp_txmsg_crc & 0x00ff));
|
||||
#endif
|
||||
if (bcsp->use_crc) {
|
||||
bcsp_txmsg_crc = bcsp_crc_reverse(bcsp_txmsg_crc);
|
||||
bcsp_slip_one_byte(nskb, (u8) ((bcsp_txmsg_crc >> 8) & 0x00ff));
|
||||
bcsp_slip_one_byte(nskb, (u8) (bcsp_txmsg_crc & 0x00ff));
|
||||
}
|
||||
|
||||
bcsp_slip_msgdelim(nskb);
|
||||
return nskb;
|
||||
@@ -317,7 +348,6 @@ static struct sk_buff *bcsp_dequeue(struct hci_uart *hu)
|
||||
|
||||
spin_unlock_irqrestore(&bcsp->unack.lock, flags);
|
||||
|
||||
|
||||
/* We could not send a reliable packet, either because there are
|
||||
none or because there are too many unack'ed pkts. Did we receive
|
||||
any packets we have not acknowledged yet ? */
|
||||
@@ -363,7 +393,7 @@ static void bcsp_pkt_cull(struct bcsp_struct *bcsp)
|
||||
BT_ERR("Peer acked invalid packet");
|
||||
|
||||
BT_DBG("Removing %u pkts out of %u, up to seqno %u",
|
||||
pkts_to_be_removed, bcsp->unack.qlen, (seqno - 1) & 0x07);
|
||||
pkts_to_be_removed, bcsp->unack.qlen, (seqno - 1) & 0x07);
|
||||
|
||||
for (i = 0, skb = ((struct sk_buff *) &bcsp->unack)->next; i < pkts_to_be_removed
|
||||
&& skb != (struct sk_buff *) &bcsp->unack; i++) {
|
||||
@@ -374,8 +404,10 @@ static void bcsp_pkt_cull(struct bcsp_struct *bcsp)
|
||||
kfree_skb(skb);
|
||||
skb = nskb;
|
||||
}
|
||||
|
||||
if (bcsp->unack.qlen == 0)
|
||||
del_timer(&bcsp->tbcsp);
|
||||
|
||||
spin_unlock_irqrestore(&bcsp->unack.lock, flags);
|
||||
|
||||
if (i != pkts_to_be_removed)
|
||||
@@ -530,6 +562,7 @@ static inline void bcsp_complete_rx_pkt(struct hci_uart *hu)
|
||||
|
||||
hci_recv_frame(bcsp->rx_skb);
|
||||
}
|
||||
|
||||
bcsp->rx_state = BCSP_W4_PKT_DELIMITER;
|
||||
bcsp->rx_skb = NULL;
|
||||
}
|
||||
@@ -598,8 +631,8 @@ static int bcsp_recv(struct hci_uart *hu, void *data, int count)
|
||||
|
||||
BT_ERR ("Checksum failed: computed %04x received %04x",
|
||||
bcsp_crc_reverse(bcsp->message_crc),
|
||||
(bcsp->rx_skb-> data[bcsp->rx_skb->len - 2] << 8) +
|
||||
bcsp->rx_skb->data[bcsp->rx_skb->len - 1]);
|
||||
(bcsp->rx_skb-> data[bcsp->rx_skb->len - 2] << 8) +
|
||||
bcsp->rx_skb->data[bcsp->rx_skb->len - 1]);
|
||||
|
||||
kfree_skb(bcsp->rx_skb);
|
||||
bcsp->rx_state = BCSP_W4_PKT_DELIMITER;
|
||||
@@ -633,7 +666,7 @@ static int bcsp_recv(struct hci_uart *hu, void *data, int count)
|
||||
bcsp->rx_count = 4;
|
||||
bcsp->rx_esc_state = BCSP_ESCSTATE_NOESC;
|
||||
BCSP_CRC_INIT(bcsp->message_crc);
|
||||
|
||||
|
||||
/* Do not increment ptr or decrement count
|
||||
* Allocate packet. Max len of a BCSP pkt=
|
||||
* 0xFFF (payload) +4 (header) +2 (crc) */
|
||||
@@ -698,6 +731,9 @@ static int bcsp_open(struct hci_uart *hu)
|
||||
|
||||
bcsp->rx_state = BCSP_W4_PKT_DELIMITER;
|
||||
|
||||
if (txcrc)
|
||||
bcsp->use_crc = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -718,18 +754,19 @@ static int bcsp_close(struct hci_uart *hu)
|
||||
}
|
||||
|
||||
static struct hci_uart_proto bcsp = {
|
||||
.id = HCI_UART_BCSP,
|
||||
.open = bcsp_open,
|
||||
.close = bcsp_close,
|
||||
.enqueue = bcsp_enqueue,
|
||||
.dequeue = bcsp_dequeue,
|
||||
.recv = bcsp_recv,
|
||||
.flush = bcsp_flush
|
||||
.id = HCI_UART_BCSP,
|
||||
.open = bcsp_open,
|
||||
.close = bcsp_close,
|
||||
.enqueue = bcsp_enqueue,
|
||||
.dequeue = bcsp_dequeue,
|
||||
.recv = bcsp_recv,
|
||||
.flush = bcsp_flush
|
||||
};
|
||||
|
||||
int bcsp_init(void)
|
||||
{
|
||||
int err = hci_uart_register_proto(&bcsp);
|
||||
|
||||
if (!err)
|
||||
BT_INFO("HCI BCSP protocol initialized");
|
||||
else
|
||||
@@ -743,5 +780,8 @@ int bcsp_deinit(void)
|
||||
return hci_uart_unregister_proto(&bcsp);
|
||||
}
|
||||
|
||||
module_param(txcrc, bool, 0644);
|
||||
MODULE_PARM_DESC(txcrc, "Transmit CRC with every BCSP packet");
|
||||
|
||||
module_param(hciextn, bool, 0644);
|
||||
MODULE_PARM_DESC(hciextn, "Convert HCI Extensions into BCSP packets");
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user