firewire: Generalize resource tracking for cdev implementation.
Generalize the way we keep track of the various resources and assign a unique handle to each resource. Signed-off-by: Kristian Høgsberg <krh@redhat.com> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
This commit is contained in:
parent
66dea3e5f6
commit
3964a4496e
2 changed files with 119 additions and 119 deletions
|
@ -36,16 +36,16 @@
|
||||||
#include "fw-device.h"
|
#include "fw-device.h"
|
||||||
#include "fw-device-cdev.h"
|
#include "fw-device-cdev.h"
|
||||||
|
|
||||||
/*
|
|
||||||
* todo
|
|
||||||
*
|
|
||||||
* - bus resets sends a new packet with new generation and node id
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* dequeue_event() just kfree()'s the event, so the event has to be
|
/* dequeue_event() just kfree()'s the event, so the event has to be
|
||||||
* the first field in the struct. */
|
* the first field in the struct. */
|
||||||
|
|
||||||
|
struct client;
|
||||||
|
struct client_resource {
|
||||||
|
struct list_head link;
|
||||||
|
void (*release)(struct client *client, struct client_resource *r);
|
||||||
|
u32 handle;
|
||||||
|
};
|
||||||
|
|
||||||
struct event {
|
struct event {
|
||||||
struct { void *data; size_t size; } v[2];
|
struct { void *data; size_t size; } v[2];
|
||||||
struct list_head link;
|
struct list_head link;
|
||||||
|
@ -60,7 +60,7 @@ struct response {
|
||||||
struct event event;
|
struct event event;
|
||||||
struct fw_transaction transaction;
|
struct fw_transaction transaction;
|
||||||
struct client *client;
|
struct client *client;
|
||||||
struct list_head link;
|
struct client_resource resource;
|
||||||
struct fw_cdev_event_response response;
|
struct fw_cdev_event_response response;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -74,11 +74,7 @@ struct client {
|
||||||
struct fw_device *device;
|
struct fw_device *device;
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
u32 resource_handle;
|
u32 resource_handle;
|
||||||
struct list_head handler_list;
|
struct list_head resource_list;
|
||||||
struct list_head request_list;
|
|
||||||
struct list_head transaction_list;
|
|
||||||
struct list_head descriptor_list;
|
|
||||||
u32 request_serial;
|
|
||||||
struct list_head event_list;
|
struct list_head event_list;
|
||||||
wait_queue_head_t wait;
|
wait_queue_head_t wait;
|
||||||
u64 bus_reset_closure;
|
u64 bus_reset_closure;
|
||||||
|
@ -118,10 +114,7 @@ static int fw_device_op_open(struct inode *inode, struct file *file)
|
||||||
|
|
||||||
client->device = fw_device_get(device);
|
client->device = fw_device_get(device);
|
||||||
INIT_LIST_HEAD(&client->event_list);
|
INIT_LIST_HEAD(&client->event_list);
|
||||||
INIT_LIST_HEAD(&client->handler_list);
|
INIT_LIST_HEAD(&client->resource_list);
|
||||||
INIT_LIST_HEAD(&client->request_list);
|
|
||||||
INIT_LIST_HEAD(&client->transaction_list);
|
|
||||||
INIT_LIST_HEAD(&client->descriptor_list);
|
|
||||||
spin_lock_init(&client->lock);
|
spin_lock_init(&client->lock);
|
||||||
init_waitqueue_head(&client->wait);
|
init_waitqueue_head(&client->wait);
|
||||||
|
|
||||||
|
@ -304,6 +297,53 @@ static int ioctl_get_info(struct client *client, void __user *arg)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_client_resource(struct client *client, struct client_resource *resource)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&client->lock, flags);
|
||||||
|
list_add_tail(&resource->link, &client->resource_list);
|
||||||
|
resource->handle = client->resource_handle++;
|
||||||
|
spin_unlock_irqrestore(&client->lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
release_client_resource(struct client *client, u32 handle,
|
||||||
|
struct client_resource **resource)
|
||||||
|
{
|
||||||
|
struct client_resource *r;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&client->lock, flags);
|
||||||
|
list_for_each_entry(r, &client->resource_list, link) {
|
||||||
|
if (r->handle == handle) {
|
||||||
|
list_del(&r->link);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&client->lock, flags);
|
||||||
|
|
||||||
|
if (&r->link == &client->resource_list)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (resource)
|
||||||
|
*resource = r;
|
||||||
|
else
|
||||||
|
r->release(client, r);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
release_transaction(struct client *client, struct client_resource *resource)
|
||||||
|
{
|
||||||
|
struct response *response =
|
||||||
|
container_of(resource, struct response, resource);
|
||||||
|
|
||||||
|
fw_cancel_transaction(client->device->card, &response->transaction);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
complete_transaction(struct fw_card *card, int rcode,
|
complete_transaction(struct fw_card *card, int rcode,
|
||||||
void *payload, size_t length, void *data)
|
void *payload, size_t length, void *data)
|
||||||
|
@ -319,7 +359,7 @@ complete_transaction(struct fw_card *card, int rcode,
|
||||||
response->response.length);
|
response->response.length);
|
||||||
|
|
||||||
spin_lock_irqsave(&client->lock, flags);
|
spin_lock_irqsave(&client->lock, flags);
|
||||||
list_del(&response->link);
|
list_del(&response->resource.link);
|
||||||
spin_unlock_irqrestore(&client->lock, flags);
|
spin_unlock_irqrestore(&client->lock, flags);
|
||||||
|
|
||||||
response->response.type = FW_CDEV_EVENT_RESPONSE;
|
response->response.type = FW_CDEV_EVENT_RESPONSE;
|
||||||
|
@ -334,7 +374,6 @@ static ssize_t ioctl_send_request(struct client *client, void __user *arg)
|
||||||
struct fw_device *device = client->device;
|
struct fw_device *device = client->device;
|
||||||
struct fw_cdev_send_request request;
|
struct fw_cdev_send_request request;
|
||||||
struct response *response;
|
struct response *response;
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
if (copy_from_user(&request, arg, sizeof request))
|
if (copy_from_user(&request, arg, sizeof request))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
@ -358,9 +397,8 @@ static ssize_t ioctl_send_request(struct client *client, void __user *arg)
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&client->lock, flags);
|
response->resource.release = release_transaction;
|
||||||
list_add_tail(&response->link, &client->transaction_list);
|
add_client_resource(client, &response->resource);
|
||||||
spin_unlock_irqrestore(&client->lock, flags);
|
|
||||||
|
|
||||||
fw_send_request(device->card, &response->transaction,
|
fw_send_request(device->card, &response->transaction,
|
||||||
request.tcode & 0x1f,
|
request.tcode & 0x1f,
|
||||||
|
@ -381,15 +419,14 @@ struct address_handler {
|
||||||
struct fw_address_handler handler;
|
struct fw_address_handler handler;
|
||||||
__u64 closure;
|
__u64 closure;
|
||||||
struct client *client;
|
struct client *client;
|
||||||
struct list_head link;
|
struct client_resource resource;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct request {
|
struct request {
|
||||||
struct fw_request *request;
|
struct fw_request *request;
|
||||||
void *data;
|
void *data;
|
||||||
size_t length;
|
size_t length;
|
||||||
u32 serial;
|
struct client_resource resource;
|
||||||
struct list_head link;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct request_event {
|
struct request_event {
|
||||||
|
@ -397,6 +434,17 @@ struct request_event {
|
||||||
struct fw_cdev_event_request request;
|
struct fw_cdev_event_request request;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
release_request(struct client *client, struct client_resource *resource)
|
||||||
|
{
|
||||||
|
struct request *request =
|
||||||
|
container_of(resource, struct request, resource);
|
||||||
|
|
||||||
|
fw_send_response(client->device->card, request->request,
|
||||||
|
RCODE_CONFLICT_ERROR);
|
||||||
|
kfree(request);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_request(struct fw_card *card, struct fw_request *r,
|
handle_request(struct fw_card *card, struct fw_request *r,
|
||||||
int tcode, int destination, int source,
|
int tcode, int destination, int source,
|
||||||
|
@ -407,7 +455,6 @@ handle_request(struct fw_card *card, struct fw_request *r,
|
||||||
struct address_handler *handler = callback_data;
|
struct address_handler *handler = callback_data;
|
||||||
struct request *request;
|
struct request *request;
|
||||||
struct request_event *e;
|
struct request_event *e;
|
||||||
unsigned long flags;
|
|
||||||
struct client *client = handler->client;
|
struct client *client = handler->client;
|
||||||
|
|
||||||
request = kmalloc(sizeof *request, GFP_ATOMIC);
|
request = kmalloc(sizeof *request, GFP_ATOMIC);
|
||||||
|
@ -423,27 +470,35 @@ handle_request(struct fw_card *card, struct fw_request *r,
|
||||||
request->data = payload;
|
request->data = payload;
|
||||||
request->length = length;
|
request->length = length;
|
||||||
|
|
||||||
spin_lock_irqsave(&client->lock, flags);
|
request->resource.release = release_request;
|
||||||
request->serial = client->request_serial++;
|
add_client_resource(client, &request->resource);
|
||||||
list_add_tail(&request->link, &client->request_list);
|
|
||||||
spin_unlock_irqrestore(&client->lock, flags);
|
|
||||||
|
|
||||||
e->request.type = FW_CDEV_EVENT_REQUEST;
|
e->request.type = FW_CDEV_EVENT_REQUEST;
|
||||||
e->request.tcode = tcode;
|
e->request.tcode = tcode;
|
||||||
e->request.offset = offset;
|
e->request.offset = offset;
|
||||||
e->request.length = length;
|
e->request.length = length;
|
||||||
e->request.serial = request->serial;
|
e->request.handle = request->resource.handle;
|
||||||
e->request.closure = handler->closure;
|
e->request.closure = handler->closure;
|
||||||
|
|
||||||
queue_event(client, &e->event,
|
queue_event(client, &e->event,
|
||||||
&e->request, sizeof e->request, payload, length);
|
&e->request, sizeof e->request, payload, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
release_address_handler(struct client *client,
|
||||||
|
struct client_resource *resource)
|
||||||
|
{
|
||||||
|
struct address_handler *handler =
|
||||||
|
container_of(resource, struct address_handler, resource);
|
||||||
|
|
||||||
|
fw_core_remove_address_handler(&handler->handler);
|
||||||
|
kfree(handler);
|
||||||
|
}
|
||||||
|
|
||||||
static int ioctl_allocate(struct client *client, void __user *arg)
|
static int ioctl_allocate(struct client *client, void __user *arg)
|
||||||
{
|
{
|
||||||
struct fw_cdev_allocate request;
|
struct fw_cdev_allocate request;
|
||||||
struct address_handler *handler;
|
struct address_handler *handler;
|
||||||
unsigned long flags;
|
|
||||||
struct fw_address_region region;
|
struct fw_address_region region;
|
||||||
|
|
||||||
if (copy_from_user(&request, arg, sizeof request))
|
if (copy_from_user(&request, arg, sizeof request))
|
||||||
|
@ -466,9 +521,12 @@ static int ioctl_allocate(struct client *client, void __user *arg)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&client->lock, flags);
|
handler->resource.release = release_address_handler;
|
||||||
list_add_tail(&handler->link, &client->handler_list);
|
add_client_resource(client, &handler->resource);
|
||||||
spin_unlock_irqrestore(&client->lock, flags);
|
request.handle = handler->resource.handle;
|
||||||
|
|
||||||
|
if (copy_to_user(arg, &request, sizeof request))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -476,57 +534,30 @@ static int ioctl_allocate(struct client *client, void __user *arg)
|
||||||
static int ioctl_deallocate(struct client *client, void __user *arg)
|
static int ioctl_deallocate(struct client *client, void __user *arg)
|
||||||
{
|
{
|
||||||
struct fw_cdev_deallocate request;
|
struct fw_cdev_deallocate request;
|
||||||
struct address_handler *handler;
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
if (copy_from_user(&request, arg, sizeof request))
|
if (copy_from_user(&request, arg, sizeof request))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
spin_lock_irqsave(&client->lock, flags);
|
return release_client_resource(client, request.handle, NULL);
|
||||||
list_for_each_entry(handler, &client->handler_list, link) {
|
|
||||||
if (handler->handler.offset == request.offset) {
|
|
||||||
list_del(&handler->link);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
spin_unlock_irqrestore(&client->lock, flags);
|
|
||||||
|
|
||||||
if (&handler->link == &client->handler_list)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
fw_core_remove_address_handler(&handler->handler);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ioctl_send_response(struct client *client, void __user *arg)
|
static int ioctl_send_response(struct client *client, void __user *arg)
|
||||||
{
|
{
|
||||||
struct fw_cdev_send_response request;
|
struct fw_cdev_send_response request;
|
||||||
|
struct client_resource *resource;
|
||||||
struct request *r;
|
struct request *r;
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
if (copy_from_user(&request, arg, sizeof request))
|
if (copy_from_user(&request, arg, sizeof request))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
if (release_client_resource(client, request.handle, &resource) < 0)
|
||||||
spin_lock_irqsave(&client->lock, flags);
|
|
||||||
list_for_each_entry(r, &client->request_list, link) {
|
|
||||||
if (r->serial == request.serial) {
|
|
||||||
list_del(&r->link);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
spin_unlock_irqrestore(&client->lock, flags);
|
|
||||||
|
|
||||||
if (&r->link == &client->request_list)
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
r = container_of(resource, struct request, resource);
|
||||||
if (request.length < r->length)
|
if (request.length < r->length)
|
||||||
r->length = request.length;
|
r->length = request.length;
|
||||||
if (copy_from_user(r->data, u64_to_uptr(request.data), r->length))
|
if (copy_from_user(r->data, u64_to_uptr(request.data), r->length))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
fw_send_response(client->device->card, r->request, request.rcode);
|
fw_send_response(client->device->card, r->request, request.rcode);
|
||||||
|
|
||||||
kfree(r);
|
kfree(r);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -547,16 +578,24 @@ static int ioctl_initiate_bus_reset(struct client *client, void __user *arg)
|
||||||
|
|
||||||
struct descriptor {
|
struct descriptor {
|
||||||
struct fw_descriptor d;
|
struct fw_descriptor d;
|
||||||
struct list_head link;
|
struct client_resource resource;
|
||||||
u32 handle;
|
|
||||||
u32 data[0];
|
u32 data[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void release_descriptor(struct client *client,
|
||||||
|
struct client_resource *resource)
|
||||||
|
{
|
||||||
|
struct descriptor *descriptor =
|
||||||
|
container_of(resource, struct descriptor, resource);
|
||||||
|
|
||||||
|
fw_core_remove_descriptor(&descriptor->d);
|
||||||
|
kfree(descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
static int ioctl_add_descriptor(struct client *client, void __user *arg)
|
static int ioctl_add_descriptor(struct client *client, void __user *arg)
|
||||||
{
|
{
|
||||||
struct fw_cdev_add_descriptor request;
|
struct fw_cdev_add_descriptor request;
|
||||||
struct descriptor *descriptor;
|
struct descriptor *descriptor;
|
||||||
unsigned long flags;
|
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (copy_from_user(&request, arg, sizeof request))
|
if (copy_from_user(&request, arg, sizeof request))
|
||||||
|
@ -587,12 +626,10 @@ static int ioctl_add_descriptor(struct client *client, void __user *arg)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&client->lock, flags);
|
descriptor->resource.release = release_descriptor;
|
||||||
list_add_tail(&descriptor->link, &client->descriptor_list);
|
add_client_resource(client, &descriptor->resource);
|
||||||
descriptor->handle = client->resource_handle++;
|
request.handle = descriptor->resource.handle;
|
||||||
spin_unlock_irqrestore(&client->lock, flags);
|
|
||||||
|
|
||||||
request.handle = descriptor->handle;
|
|
||||||
if (copy_to_user(arg, &request, sizeof request))
|
if (copy_to_user(arg, &request, sizeof request))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
|
@ -602,28 +639,11 @@ static int ioctl_add_descriptor(struct client *client, void __user *arg)
|
||||||
static int ioctl_remove_descriptor(struct client *client, void __user *arg)
|
static int ioctl_remove_descriptor(struct client *client, void __user *arg)
|
||||||
{
|
{
|
||||||
struct fw_cdev_remove_descriptor request;
|
struct fw_cdev_remove_descriptor request;
|
||||||
struct descriptor *d;
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
if (copy_from_user(&request, arg, sizeof request))
|
if (copy_from_user(&request, arg, sizeof request))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
spin_lock_irqsave(&client->lock, flags);
|
return release_client_resource(client, request.handle, NULL);
|
||||||
list_for_each_entry(d, &client->descriptor_list, link) {
|
|
||||||
if (d->handle == request.handle) {
|
|
||||||
list_del(&d->link);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
spin_unlock_irqrestore(&client->lock, flags);
|
|
||||||
|
|
||||||
if (&d->link == &client->descriptor_list)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
fw_core_remove_descriptor(&d->d);
|
|
||||||
kfree(d);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -895,11 +915,8 @@ static int fw_device_op_mmap(struct file *file, struct vm_area_struct *vma)
|
||||||
static int fw_device_op_release(struct inode *inode, struct file *file)
|
static int fw_device_op_release(struct inode *inode, struct file *file)
|
||||||
{
|
{
|
||||||
struct client *client = file->private_data;
|
struct client *client = file->private_data;
|
||||||
struct address_handler *h, *next_h;
|
|
||||||
struct request *r, *next_r;
|
|
||||||
struct event *e, *next_e;
|
struct event *e, *next_e;
|
||||||
struct response *t, *next_t;
|
struct client_resource *r, *next_r;
|
||||||
struct descriptor *d, *next_d;
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
if (client->buffer.pages)
|
if (client->buffer.pages)
|
||||||
|
@ -908,26 +925,8 @@ static int fw_device_op_release(struct inode *inode, struct file *file)
|
||||||
if (client->iso_context)
|
if (client->iso_context)
|
||||||
fw_iso_context_destroy(client->iso_context);
|
fw_iso_context_destroy(client->iso_context);
|
||||||
|
|
||||||
list_for_each_entry_safe(h, next_h, &client->handler_list, link) {
|
list_for_each_entry_safe(r, next_r, &client->resource_list, link)
|
||||||
fw_core_remove_address_handler(&h->handler);
|
r->release(client, r);
|
||||||
kfree(h);
|
|
||||||
}
|
|
||||||
|
|
||||||
list_for_each_entry_safe(r, next_r, &client->request_list, link) {
|
|
||||||
fw_send_response(client->device->card, r->request,
|
|
||||||
RCODE_CONFLICT_ERROR);
|
|
||||||
kfree(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
list_for_each_entry_safe(t, next_t, &client->transaction_list, link) {
|
|
||||||
fw_cancel_transaction(client->device->card, &t->transaction);
|
|
||||||
kfree(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
list_for_each_entry_safe(d, next_d, &client->descriptor_list, link) {
|
|
||||||
fw_core_remove_descriptor(&d->d);
|
|
||||||
kfree(d);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME: We should wait for the async tasklets to stop
|
/* FIXME: We should wait for the async tasklets to stop
|
||||||
* running before freeing the memory. */
|
* running before freeing the memory. */
|
||||||
|
|
|
@ -103,7 +103,7 @@ struct fw_cdev_event_request {
|
||||||
__u32 type;
|
__u32 type;
|
||||||
__u32 tcode;
|
__u32 tcode;
|
||||||
__u64 offset;
|
__u64 offset;
|
||||||
__u32 serial;
|
__u32 handle;
|
||||||
__u32 length;
|
__u32 length;
|
||||||
__u32 data[0];
|
__u32 data[0];
|
||||||
};
|
};
|
||||||
|
@ -186,17 +186,18 @@ struct fw_cdev_send_response {
|
||||||
__u32 rcode;
|
__u32 rcode;
|
||||||
__u32 length;
|
__u32 length;
|
||||||
__u64 data;
|
__u64 data;
|
||||||
__u32 serial;
|
__u32 handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fw_cdev_allocate {
|
struct fw_cdev_allocate {
|
||||||
__u64 offset;
|
__u64 offset;
|
||||||
__u64 closure;
|
__u64 closure;
|
||||||
__u32 length;
|
__u32 length;
|
||||||
|
__u32 handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fw_cdev_deallocate {
|
struct fw_cdev_deallocate {
|
||||||
__u64 offset;
|
__u32 handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define FW_CDEV_LONG_RESET 0
|
#define FW_CDEV_LONG_RESET 0
|
||||||
|
|
Loading…
Reference in a new issue