--=_courier-3803-1053617665-0001-2
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
On Wed, May 21, 2003 at 01:07:36PM -0700, Greg KH wrote:
> On Wed, May 21, 2003 at 08:52:12PM +0200, Manuel Estrada Sainz wrote:
> > On Wed, May 21, 2003 at 12:23:18AM -0700, Greg KH wrote:
> > > Oops, forgot to respond to this, sorry...
> > >
> > > On Sun, May 18, 2003 at 12:19:22AM +0200, Manuel Estrada Sainz wrote:
> > [snip]
> > > > - There is a timeout, changeable from userspace. Feedback on a
> > > > reasonable default value appreciated.
> > >
> > > Is this really needed? Especially as you now have:
> >
> > There is currently no way to know if hotplug couldn't be called at all
> > or if it failed because it didn't have firmware load support.
> >
> > If that happens, we would be waiting for ever. And I'd rather make that
> > a countable number of seconds :)
> >
> > I'll make '0' mean no timeout at all.
>
> Ok, that's fine with me. A bit of documentation for all of this might
> be nice. Just add some kerneldoc comments to your public functions, and
> you should be fine.
Done. I am not a good documentation writer, but the attached patches
should include enough documentation to understand how things work.
> > I am not sure on how to implement "if a driver that uses it is
> > selected" and not sure on where to add the Kconfig entries to make it
> > available to out-of-kernel modules.
>
> You could do something like what has been done for the mii module. Look
> at lib/Makefile and drivers/usb/net/Makefile.mii for an example.
>
> I'm not saying that this is the best way, but it could be one solution.
> Ideally, the user would never have to select the firmware core option,
> it would just get automatically built if a driver that needs it is also
> selected.
But if a driver not in the kernel tree needs it, the user should be
able to enable it unconditionally, like the CRC32 stuff.
And currently there is no in-kernel driver that uses it, so the only
way to enable it is manually.
Once Atmel PCMCIA driver (which will use it) gets in, the new 'enable'
kconfig keyword should be already available and no makefile tricks will
be needed.
[snip]
> Add a bit of documentation, and some build integration,
Until drivers start using it, there is not much build integration to
do.
> and I'd think you are finished. Unless anyone else has any
> objections?
Simon Kelley had an objection, it was badly corrupting kernel memory :-/.
It was a bug in the sysfs pieces which is now fixed.
So I am finished :-) What do I do now? Should I send it to Linus or you
take care of that?
> Very nice job, thanks again for doing this.
No problem.
News:
- Fixed the sysfs corruption problem.
- Use refcounting with class_device instances.
- I had to add support for 'release forwarding' to
the class subsystem.
- Removed firmware_sample_firmware_class.c
- It is ugly, if found interesting, it should get
polished first.
- Removed FW_LOADER_SAMPLE Kconfig/Makefile stuff.
- Some more formatting changes.
Patches:
incremental.diff:
For easier reading as usual.
firmware-class.diff.bz2:
The code itself
firmware-class-sample-driver.diff.bz2:
The sample driver, for easier ignoring :)
class-casts+release.diff.bz2:
to_class_dev/to_class_dev_attr and 'release forwarding'
changes.
sysfs-bin-header.diff.bz2
sysfs-bin-lost-dget.diff.bz2
sysfs-bin-flexible-size.diff.bz2:
sysfs bits. This time, they don't corrupt kernel memory :-/
(I'll send them to Patrick Mochel in a few moments.)
Have a nice day
Manuel
--
--- Manuel Estrada Sainz <ranty@debian.org>
<ranty@bigfoot.com>
<ranty@users.sourceforge.net>
------------------------ <manuel.estrada@hispalinux.es> -------------------
Let us have the serenity to accept the things we cannot change, courage to
change the things we can, and wisdom to know the difference.
--=_courier-3803-1053617665-0001-2
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="incremental.diff"
diff -u linux-2.5.mine/drivers/base/class.c linux-2.5.mine/drivers/base/class.c
--- linux-2.5.mine/drivers/base/class.c 2003-05-21 10:19:41.000000000 +0200
+++ linux-2.5.mine/drivers/base/class.c 2003-05-22 16:51:46.000000000 +0200
@@ -179,7 +179,15 @@
.store = class_device_attr_store,
};
+static void class_dev_release(struct kobject * kobj)
+{
+ struct class_device *class_dev = to_class_dev(kobj);
+ if (class_dev->release)
+ class_dev->release(class_dev);
+}
+
static struct kobj_type ktype_class_device = {
+ .release = &class_dev_release,
.sysfs_ops = &class_dev_sysfs_ops,
};
only in patch2:
unchanged:
--- linux-2.5.orig/include/linux/device.h 2003-05-22 13:05:16.000000000 +0200
+++ linux-2.5.mine/include/linux/device.h 2003-05-22 12:05:45.000000000 +0200
@@ -204,6 +204,7 @@
void * class_data; /* class-specific data */
char class_id[BUS_ID_SIZE]; /* unique to this class */
+ void (*release)(struct class_device * class_dev);
};
static inline void *
diff -u linux-2.5.mine/drivers/base/Kconfig.lib linux-2.5.mine/drivers/base/Kconfig.lib
--- linux-2.5.mine/drivers/base/Kconfig.lib 2003-05-21 16:24:14.000000000 +0200
+++ linux-2.5.mine/drivers/base/Kconfig.lib 2003-05-22 13:11:42.000000000 +0200
@@ -12,6 +11,0 @@
-config FW_LOADER_SAMPLE
- tristate "Hotplug firmware loading samples"
- ---help---
- This should not get in the kernel, it is just here to make playing
- with firmware loading easier.
-
diff -u linux-2.5.mine/drivers/base/Makefile linux-2.5.mine/drivers/base/Makefile
--- linux-2.5.mine/drivers/base/Makefile 2003-05-21 16:25:44.000000000 +0200
+++ linux-2.5.mine/drivers/base/Makefile 2003-05-22 13:12:20.000000000 +0200
@@ -6,9 +6,2 @@
obj-$(CONFIG_FW_LOADER) += firmware_class.o
-
-#The next three lines are just to make testing easier and should not get into
-#the kernel
-obj-$(CONFIG_FW_LOADER_SAMPLE) += firmware_class.o
-obj-$(CONFIG_FW_LOADER_SAMPLE) += firmware_sample_driver.o \
- firmware_sample_firmware_class.o
-
obj-$(CONFIG_NUMA) += node.o memblk.o
diff -u linux-2.5.mine/drivers/base/firmware_class.c linux-2.5.mine/drivers/base/firmware_class.c
--- linux-2.5.mine/drivers/base/firmware_class.c 2003-05-21 16:38:06.000000000 +0200
+++ linux-2.5.mine/drivers/base/firmware_class.c 2003-05-22 16:49:39.000000000 +0200
@@ -3,6 +3,19 @@
*
* Copyright (c) 2003 Manuel Estrada Sainz <ranty@debian.org>
*
+ * Simple hotplug script sample:
+ *
+ * HOTPLUG_FW_DIR=/usr/lib/hotplug/firmware/
+ * echo 1 > /sysfs/$DEVPATH/loading
+ * cat $HOTPLUG_FW_DIR/$FIRMWARE > /sysfs/$DEVPATH/data
+ * echo 0 > /sysfs/$DEVPATH/loading
+ *
+ * To cancel the load in case of error:
+ *
+ * echo -1 > /sysfs/$DEVPATH/loading
+ *
+ * Both $DEVPATH and $FIRMWARE are already provided in the environment.
+ *
*/
#include <linux/device.h>
@@ -36,6 +49,17 @@
{
return sprintf(buf, "%d\n", loading_timeout);
}
+
+/**
+ * firmware_timeout_store:
+ * Description:
+ * Sets the number of seconds to wait for the firmware. Once
+ * this expires an error will be return to the driver and no
+ * firmware will be provided.
+ *
+ * Note: zero means 'wait for ever'
+ *
+ **/
static ssize_t
firmware_timeout_store(struct class *class, const char *buf, size_t count)
{
@@ -77,6 +101,16 @@
struct firmware_priv *fw_priv = class_get_devdata(class_dev);
return sprintf(buf, "%d\n", fw_priv->loading);
}
+
+/**
+ * firmware_loading_store: - loading control file
+ * Description:
+ * The relevant values are:
+ *
+ * 1: Start a load, discarding any previous partial load.
+ * 0: Conclude the load and handle the data to the driver code.
+ * -1: Conclude the load with an error and discard any written data.
+ **/
static ssize_t
firmware_loading_store(struct class_device *class_dev,
const char *buf, size_t count)
@@ -125,7 +159,7 @@
if (offset + count > fw->size)
count = fw->size - offset;
- memcpy(buffer, fw->data, fw->size);
+ memcpy(buffer, fw->data + offset, count);
return count;
}
static int
@@ -152,6 +186,15 @@
BUG_ON(min_size > fw_priv->alloc_size);
return 0;
}
+
+/**
+ * firmware_data_write:
+ *
+ * Description:
+ *
+ * Data written to the 'data' attribute will be later handled to
+ * the driver as a firmware image.
+ **/
static ssize_t
firmware_data_write(struct kobject *kobj,
char *buffer, loff_t offset, size_t count)
@@ -180,10 +223,17 @@
.read = firmware_data_read,
.write = firmware_data_write,
};
+
+static void
+fw_class_dev_release(struct class_device *class_dev)
+{
+ kfree(class_dev);
+}
+
static void
firmware_class_timeout(u_long data)
{
- struct firmware_priv *fw_priv = (struct firmware_priv *)data;
+ struct firmware_priv *fw_priv = (struct firmware_priv *) data;
fw_priv->abort = 1;
wmb();
complete(&fw_priv->completion);
@@ -196,16 +246,18 @@
class_dev->class_id[BUS_ID_SIZE - 1] = '\0';
}
static int
-fw_setup_class_device(struct class_device *class_dev,
+fw_setup_class_device(struct class_device **class_dev_p,
const char *fw_name, struct device *device)
{
int retval = 0;
struct firmware_priv *fw_priv = kmalloc(sizeof (struct firmware_priv),
GFP_KERNEL);
+ struct class_device *class_dev = kmalloc(sizeof (struct class_device),
+ GFP_KERNEL);
- if (!fw_priv) {
+ if (!fw_priv || !class_dev) {
retval = -ENOMEM;
- goto out;
+ goto error_kfree;
}
memset(fw_priv, 0, sizeof (*fw_priv));
memset(class_dev, 0, sizeof (*class_dev));
@@ -221,16 +273,17 @@
class_dev->dev = device;
fw_priv->timeout.function = firmware_class_timeout;
- fw_priv->timeout.data = (u_long)fw_priv;
+ fw_priv->timeout.data = (u_long) fw_priv;
init_timer(&fw_priv->timeout);
+ class_dev->release = fw_class_dev_release;
class_dev->class = &firmware_class;
class_set_devdata(class_dev, fw_priv);
retval = class_device_register(class_dev);
if (retval) {
printk(KERN_ERR "%s: class_device_register failed\n",
__FUNCTION__);
- goto error_free_fw_priv;
+ goto error_kfree;
}
retval = sysfs_create_bin_file(&class_dev->kobj, &fw_priv->attr_data);
@@ -265,9 +318,12 @@
sysfs_remove_bin_file(&class_dev->kobj, &fw_priv->attr_data);
error_unreg_class_dev:
class_device_unregister(class_dev);
-error_free_fw_priv:
+error_kfree:
kfree(fw_priv);
+ kfree(class_dev);
+ *class_dev_p = NULL;
out:
+ *class_dev_p = class_dev;
return retval;
}
static void
@@ -280,25 +336,32 @@
class_device_unregister(class_dev);
}
+/**
+ * request_firmware: - request firmware to hotplug and wait for it
+ * Description:
+ * @firmware will be used to return a firmware image by the name
+ * of @name for device @device.
+ *
+ * Should be called from user context where sleeping is allowed.
+ *
+ * @name will be use as $FIRMWARE in the hotplug environment and
+ * should be distinctive enough not to be confused with any other
+ * firmware image for this or any other device.
+ **/
int
request_firmware(const struct firmware **firmware, const char *name,
struct device *device)
{
- struct class_device *class_dev = kmalloc(sizeof (struct class_device),
- GFP_KERNEL);
+ struct class_device *class_dev;
struct firmware_priv *fw_priv;
int retval;
- if (!class_dev)
- return -ENOMEM;
+ if (!firmware)
+ return -EINVAL;
- if (!firmware) {
- retval = -EINVAL;
- goto out;
- }
*firmware = NULL;
- retval = fw_setup_class_device(class_dev, name, device);
+ retval = fw_setup_class_device(&class_dev, name, device);
if (retval)
goto out;
@@ -323,10 +386,12 @@
}
kfree(fw_priv);
out:
- kfree(class_dev);
return retval;
}
+/**
+ * release_firmware: - release the resource associated with a firmware image
+ **/
void
release_firmware(const struct firmware *fw)
{
@@ -336,6 +401,15 @@
}
}
+/**
+ * register_firmware: - provide a firmware image for later usage
+ *
+ * Description:
+ * Make sure that @data will be available by requesting firmware @name.
+ *
+ * Note: This will not be possible until some kind of persistence
+ * is available.
+ **/
void
register_firmware(const char *name, const u8 *data, size_t size)
{
@@ -368,6 +442,20 @@
kfree(fw_work);
}
+/**
+ * request_firmware_nowait:
+ *
+ * Description:
+ * Asynchronous variant of request_firmware() for contexts where
+ * it is not possible to sleep.
+ *
+ * @cont will be called asynchronously when the firmware request is over.
+ *
+ * @context will be passed over to @cont.
+ *
+ * @fw may be %NULL if firmware request fails.
+ *
+ **/
int
request_firmware_nowait(
struct module *module,
diff -u linux-2.5.mine/include/linux/firmware.h linux-2.5.mine/include/linux/firmware.h
--- linux-2.5.mine/include/linux/firmware.h 2003-05-17 22:16:36.000000000 +0200
+++ linux-2.5.mine/include/linux/firmware.h 2003-05-22 16:55:06.000000000 +0200
@@ -9,12 +9,12 @@
};
-int request_firmware (const struct firmware **fw, const char *name,
- struct device *device);
-int request_firmware_nowait (
+int request_firmware(const struct firmware **fw, const char *name,
+ struct device *device);
+int request_firmware_nowait(
struct module *module,
const char *name, struct device *device, void *context,
void (*cont)(const struct firmware *fw, void *context));
/* Maybe 'device' should be 'struct device *' */
-void release_firmware (const struct firmware *fw);
-void register_firmware (const char *name, const u8 *data, size_t size);
+void release_firmware(const struct firmware *fw);
+void register_firmware(const char *name, const u8 *data, size_t size);
#endif
diff -u linux-2.5.mine/fs/sysfs/bin.c linux-2.5.mine/fs/sysfs/bin.c
--- linux-2.5.mine/fs/sysfs/bin.c 2003-05-17 14:53:01.000000000 +0200
+++ linux-2.5.mine/fs/sysfs/bin.c 2003-05-22 16:52:42.000000000 +0200
@@ -33,7 +33,7 @@
if (count > PAGE_SIZE)
count = PAGE_SIZE;
- if(size){
+ if (size) {
if (offs > size)
return 0;
if (offs + count > size)
@@ -46,7 +46,7 @@
count = ret;
ret = -EFAULT;
- if (copy_to_user(userbuf, buffer + offs, count) != 0)
+ if (copy_to_user(userbuf, buffer, count) != 0)
goto Done;
*off = offs + count;
@@ -84,7 +84,7 @@
}
ret = -EFAULT;
- if (copy_from_user(buffer + offs, userbuf, count))
+ if (copy_from_user(buffer, userbuf, count))
goto Done;
count = flush_write(dentry, buffer, offs, count);
diff -u linux-2.5.mine/fs/sysfs/inode.c linux-2.5.mine/fs/sysfs/inode.c
--- linux-2.5.mine/fs/sysfs/inode.c 2003-05-17 20:30:34.000000000 +0200
+++ linux-2.5.mine/fs/sysfs/inode.c 2003-05-22 16:53:59.000000000 +0200
@@ -60,7 +60,7 @@
Proceed:
if (init)
error = init(inode);
- if (!error){
+ if (!error) {
d_instantiate(dentry, inode);
dget(dentry); /* Extra count - pin the dentry in core */
} else
--=_courier-3803-1053617665-0001-2
Content-Type: application/octet-stream
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="firmware-class.diff.bz2"
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
EpP/xdyRThQkDK4yk8A=
--=_courier-3803-1053617665-0001-2
Content-Type: application/octet-stream
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="firmware-class-sample-driver.diff.bz2"
QlpoOTFBWSZTWZT55ncAAyXfgH4we//+/3/v346////6UAWe5ltsmDVZhQAohJImjQmmUyan
iT1NDTRkyD0gPUMBA8oGnmlDQOaNGhphANMCaaAMhoYgDRiNDBGQASmiBQnpTamn6o02EJp6
gGjQAGmgADQNBkOaNGhphANMCaaAMhoYgDRiNDBGQASJI0mCaaZCap5kyppo9TT1GgaaAaPU
BoDTQNNNFSYjcQgyQNoGhtoX1jSIBppgtgY/A1eMOi3IU9vFwxQwpGK0L4J1tImLuO5REp6C
AgS1HDlbrwYcD0dpFsMVbs60So7WSEsTNZ5NgLr88l5IvsJGfZvCqTneVOw0jeRykwqVW6or
qZUyOO2WY8XRw6eKgnDQUu81l8aPjHtVK007QJNUYPweiTl1wB6jx5lGAVLipAqrC84IMRwk
NxKe3irgacolOV2zTv+6ZXVFcQrtPLwRVi2eqzQecrnOzOInlPCk88sjOrf3ipa5nVVumoJJ
2x3ahTX+AzbWzxfm+LPcde8HWns1GOM49MzPTPoGM0QhKy1Sxt73WC5uZRQEVz3Za4HonahY
m1pSonA1emSvbJWUQUbHZRRsOjLP3BYNjaF8Qkg2MQ3CrhITzshrdhAX8iKVrvy9n1i68lR9
PZ/wWxiwWrTgDevDGa+49CaNcBwNIY9NBO4JsQacO5pNXdo1+TZg4CIobN6pCnJ5I1LUySnA
PFqxaJn89AP6Ot17EbjCpJ4ZHbqINxbfS8OFMszBusRYpDk5HBzFmUMYZiG/4l+FpWdalrFo
TLjct7SbauUrmbVIuZfZVaQqCK+CrUFQ9QU6pMhccS1rqUy08oYJdlbCtJmodlrW89SWUwC6
rStdjArZQlWJWKhI2o2KZQCW5VaTVp9KxWJ67nQO93BzwY3zbhJrbLiWEVgbCcD5KFcTD7Rn
zoYB3IebJcGR3JqCQaZUsSUT9yk2g0Il/uFXB8aqPTUAD8qJgEfwI1hGBjNQFyosPKEYIPLB
yfd5A1jaWttsoJyBtEmlKcFingj5QtvGjct6VGi7UOGyVjkXXJyJAtIiwFrjidnTCC++48ky
YBMLm2jHlyaM09aHQiAfUzyqEkzxDRDDlHqQOciE46cE7ClUzhKt0OdYpJBSxVUogBgqBkc1
HWW0BWKiwHbkRqRfukiw5gmwtPMG3jtpDJLZvR+x489czSGaDsYvJmGs6zjsIMGYBiqFIUQx
VNMXOOLk2iA7QJYOgPqntof+uJW8C4oCx1BdBadiOagyMxJ3303jygSnmnegEOAa14NzjOdQ
6BGNsxZ37Wr79CKOJMhXh1Pp0I0swVwEdaCswsR8rbEl3ptvqWzX4JQ4bGrQRbklolcBjNZ1
6OHSD4v149iACGhsRRQr+WkPRDVhI3qyViuFbgbr5wdFnI19pMAMxINT0a/MgpypVf4hMWOk
hUgxK8yLZJjBjGTgCbaGgr1G17UWIHv4rhXzBblVYWnQKWpms8NVyDDgQQXYlyMAAxuVdPqA
SzAwrRtNkRENgnVCJDYmxAbKsqzKXIZIKy4DaCIqEgtC0KUHXYqKEE2sAKpvW14ik7aw9BZp
yBcAjF4jiITbayRMvX0RQcMFAe8eMg1NYD0mdbLRimjmBZUF4Nwsr0fYRacCkbDyObQwkWun
IrNVNMJ2szFhAWKSGWiWicwKN5VdJA6iLq1CKxZ1K4XpR3wjRwV66rld4cAwspXp1IK8QRRi
ANLpRchaTkjBpDYkU7kFSUsaXYcs0ZIvA2HiLt6Uk0mv+LuSKcKEhKfPM7g=
--=_courier-3803-1053617665-0001-2
Content-Type: application/octet-stream
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="class-casts+release.diff.bz2"
QlpoOTFBWSZTWSsZv5UAAhVfgAowSX//+14hCxq////6UAM7bPHbuAAwyk0gZAYjQNAxADQA
PKAANFTyniahkyMQAAAAAAAA00EhJ5QDTamTT1DQDJoBo0zU0AHMAmAmRgBGJiYTCYIaYmmA
VJIKbSPSaGEU/RGU0DamTRo9QNoQep6j7ATKsUlirDAPAdpB7rTE1s4DHcxFlvf1KOdUK1c6
UsEf5Bk1sBG0OrJZGg33zWgxRYoRAEYgujdFMhOEMDe+yGUCwDhjjhbNkCQwxFA9N4mpTT9E
IQ5TSWEkVnlTf9yeBhAVGmDgVceEyK8neSS9CYpm1LURrGmHmAoFgsswCh6wwfbIj7hWtBMl
VtcQxLzpzXFRSiddMxtSpZFIx0unL2fTT29lrYmDiaOiUqVNM9SU8iV3JXOxmq6anaxtykwM
xeTomxS4vFHGV8apSqqqo9aGhKT3JZNqXJYOgtBXkFNsmFqQpKTCXlEuNIBOAngUhhgnFNUC
QA0Q4cOihK6QEe44nEpFQUUG6G51EGVQZxUEzKuVWe+gIBcLoeLozABIFsBUR5KXJCVlK+fQ
zdq53j9ve9fsm6PfFYQlTK2spxKstf7fBzUeC9PiT+gaWCYzvquFilT3k1RLp8490oqiO7xz
wcRWzKW2cVXLvkqWqS/+DwlxlPIOROa/R34SfNdIaiowfZLFw4cM93wqlV/t3HUxjHFiuUqq
qhemcl0cVOzz4Jf6Ji0yYmg0rC5ekn3zW6PGdhruNzmWTsHOzv5IyuTODTGzq5ZloTabGlXk
nUc5cGzu0E190THu9NWTMG5MpcTUXybUw0m6Q30bSg3p2+TVUpR0nVHIWYuRN2zzbc2e9zMl
Kk1yxZg0/9yVzWcGMYpwJkyReHozztaNoxsida3KhrZ4dl4Or5KldGN3U57dbGl66pji6Y66
SZLHGmceplglTfVYNgUF4bWnr2B6ZPPt49s410nKGmJw+gloN7RL+cL40Nbix3oShT/F3JFO
FCQKxm/lQA==
--=_courier-3803-1053617665-0001-2
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment; filename="sysfs-bin-flexible-size.diff.bz2"
BZh91AY&SYV=86=B3N=00=01=BF=DF=80=020`=7F=FF=BFo=AF=DF=10=BF=EF=DF=FA@=02=
=BC=03 =00=E6=04=C4=D0a2d=C9=91=84=C14=D3#=13=00C=00=D4=06=88@=0D=1A=1A=00=
=00=00=00=00=00=E6=04=C4=D0a2d=C9=91=84=C14=D3#=13=00C=00T=92=13@=D1O*x=99=
=3DI=E4=9BP=C9=93&!=8D&ji=E9=1BML=9A=0C)=A9=82=E2=E2=CB=95w=B1e=94U=F7=DC]k=
=AA=ADK=97)K=AERZ=D6=B8=AB4=CF=0D\=B5sE=96=9C=D7N=EA=AA=8C=12=9D=CA=B2=A64j=
=B8=B4b=ADX=E1}=F5=91&jS=DD!=CE=ECN=C6=E7>=9A=E8=EA3=EF4O_M=9D?5=A9=E2=D3=
=F4=DA=A6=DAN=A6=B5=91z=94=C1=D3=F9q=F6=1E6=D6=C5=8E=05%=AC=A2=B8t{/d=C32=
=B0/=BD=BE=C6q=99=E0p=D6=F1=D6=B7=12=D2s|m"=E7=85=9F=BF=98=F4.=BE=E2=B6=AC=
=A7=B2=95=F8=B42=88=A4=FB=A9V=B2h=C7=C0=FB2=E1r=96=95=AD=E2=F3=F3=F9=DF=AED=
=E1=B0=AB[=A1]=1Fb=AD;=D3e=A65=9BLs=98=9BO=EFB=ACw=8D=9A=07=02C=80=E3=10@[=
=E1C=04P=B6=98JeE=A1=A9Z=90Mb=80@=80=12J;=08=CAm=94<=12=EB=C4"=00=B5=12=DD=
=078b=1F=92O:=A8M=00#Bc=9C,*X=A2=9B-=ED=F8/fq'=A5RM=15#q=E6=16>=F3=AA?=97=
=96=F8=F9F/3e=BA=9E=F8=DC=A7=B63=BDQ=D6=C1=F2W=C7=CB=F2]=96w=AE=9B=97=BA=F4=
=C7=EC=C9=F1=EB=8EF1=CD=3Do=A7=8Dg=FA=F7=BB? =8D=EFt=ED=9C_=E1=CAr]R=BDF=A7=
=BA=E3=F8=150=89=D5=CB;oy;=8D=D5#=8E|$=DD|=DBg#=D2QF=CB=E4=9EO=AC=86=13"=91=
m=E9rQ=19=9E=8D=ED=CCCI=C6X=D0=C4=BE=A45=EB`}NV=0D=C6=062MK=B4K=15=C6=B9=99=
=D7=A7k=B5=CC=D5=1A=12=F8=DF$=B2=A1=C1c=8D5>=A5<=06=D2=8A=1A=1D=B1=B0=B6=B7=
=CC=B8N=C9=B0=C9T5=EC=B1=CB=AF|dTb=EE=EE=99=E3=89=B7N=A5=C4=97=8E=92=B4=93S=
=2E=06s=9DJ=89=B5B=D2=AA=9C=B3=BFS=BC`=CB=05=F9=A3=93=821=13=9F=18=CEkd=C7I=
=AAa=B0=D5=B9=BC=E0f=92hq=AB=FF=17rE8P=90V=86=B3N
--=_courier-3803-1053617665-0001-2
Content-Type: application/octet-stream
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="sysfs-bin-header.diff.bz2"
QlpoOTFBWSZTWQiLF+sAAJ/fgAIwQH/7+kgBCQC//9/6MAFWUAwAA0AAZNAAAGgEqnomTUPS
GgMmmho0ADQ0ASSI1T9IJ7SaZAmTJkNDQwNTR5WbhsH2adI0ImKatVsHbRCtEEUJcJd76cpR
iHBYzhkVSt2QFKC5OtLMRlTdWwxsGgCzKikZ6YgTscDUOUieEx2DWPnbH6bArCAS4MzBQHmK
AhSKJBY8qnYXSEGEooakTYGEIg4JrS5Fo1dVWfuwS8yVvt5b9/MiZ3DDkbtqdePkYGOiXELZ
igNL4eCOySluDoNVQc0XTd0T70NtrKsVJjSebA6p8QwsROodAuPcrAhFEEsyWAYIg19GAyTi
KWEXJX4SxxKdFFynM74xmB5xcI/rEu6XKxVn4tUz9bHNDZQZeKpQUMiLM9SDJihITCHCziMi
NOgLwFpVfA0XksCKT/F3JFOFCQCIsX6w
--=_courier-3803-1053617665-0001-2
Content-Type: application/octet-stream
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="sysfs-bin-lost-dget.diff.bz2"
QlpoOTFBWSZTWXU+4F4AAIJfgAIwYH//uk4BSQCv595qMAE1tsQ0JqjQe1TQ0aaZHqBoADQe
oNTTJTJ4ptQ0D0EBpoABoCUKR6U/KeptUz1BlDIxGRkegjeqYAl8huDA8iRDJf11sRRUaTvY
HrXMpXBUkBV7R1ksdNj5qD885YujXCmfRyOSnUGGZkQsQcTVWqiYGhLMHB6qzbT3oC1YVwar
giDgtdfgF7gRDf8jDxTgMYgYsgEpeZkAwWhDNUJOJhoBht54dL4wtbNPSqJQk3hKNaC2fjqy
wsnA+wuhs6kUV2hZdIf8bARVkb+F+8qLzKtsPWafi2BwBiFhiRvAhSg0xVeHegPmOCZO4ljV
LVELb60qDC9E/mB7xYOgEJtFSqjwiDk0ASLwllBXPiacsnalSuErrLXBEK6ZExhGf8XckU4U
JB1PuBeA
--=_courier-3803-1053617665-0001-2--