Commit dfd3ad98 authored by Russell King's avatar Russell King

[PCMCIA] Prevent class_device related oops.

Although no such oops has been reported, removing a socket driver
while a file under /sysfs/class/pcmcia_socket/pcmcia_socket* is
held open by user space could potentially cause an oops.

Plug this by preventing pcmcia_unregister_socket from returning
until all references by sysfs to the pcmcia socket have been dropped.
parent 8ae9c851
......@@ -387,6 +387,12 @@ static void pcmcia_remove_socket(struct class_device *class_dev)
socket->ss_entry = NULL;
}
static void pcmcia_release_socket(struct class_device *class_dev)
{
struct pcmcia_socket *socket = class_get_devdata(class_dev);
complete(&socket->socket_released);
}
/**
* pcmcia_register_socket - add a new pcmcia socket device
......@@ -450,6 +456,8 @@ void pcmcia_unregister_socket(struct pcmcia_socket *socket)
DEBUG(0, "cs: pcmcia_unregister_socket(0x%p)\n", socket->ss_entry);
init_completion(&socket->socket_released);
/* remove from the device core */
class_device_unregister(&socket->dev);
......@@ -457,6 +465,9 @@ void pcmcia_unregister_socket(struct pcmcia_socket *socket)
down_write(&pcmcia_socket_list_rwsem);
list_del(&socket->socket_list);
up_write(&pcmcia_socket_list_rwsem);
/* wait for sysfs to drop all references */
wait_for_completion(&socket->socket_released);
} /* pcmcia_unregister_socket */
EXPORT_SYMBOL(pcmcia_unregister_socket);
......@@ -2496,6 +2507,7 @@ EXPORT_SYMBOL(MTDHelperEntry);
struct class pcmcia_socket_class = {
.name = "pcmcia_socket",
.release = pcmcia_release_socket,
};
EXPORT_SYMBOL(pcmcia_socket_class);
......
......@@ -193,6 +193,7 @@ struct pcmcia_socket {
char *fake_cis;
struct list_head socket_list;
struct completion socket_released;
/* deprecated */
unsigned int sock; /* socket number */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment