static void iso_resource_auto_work(struct work_struct *work)
{
struct iso_resource_auto *r = from_work(r, work, work.work);
struct client *client = r->client;
unsigned long index = r->resource.handle;
u64 reset_jiffies;
struct iso_resource_event *e;
int resource_generation, current_generation;
int channel, bandwidth, todo;
bool free = false;
scoped_guard(spinlock_irq, &client->device->card->lock) {
reset_jiffies = client->device->card->reset_jiffies;
current_generation = client->device->generation;
}
scoped_guard(spinlock_irq, &client->lock) {
resource_generation = r->generation;
r->generation = current_generation;
todo = r->todo;
}
switch (todo) {
case ISO_RES_AUTO_ALLOC:
// Allow 1000ms grace period for other reallocations.
if (time_is_after_jiffies64(reset_jiffies + secs_to_jiffies(1))) {
scoped_guard(spinlock_irq, &client->lock)
schedule_iso_resource_auto(r, msecs_to_jiffies(333));
goto out;
}
break;
case ISO_RES_AUTO_REALLOC:
// We could be called twice within the same generation.
if (resource_generation == current_generation)
goto out;
break;
case ISO_RES_AUTO_DEALLOC:
default:
break;
}
bandwidth = r->bandwidth;
fw_iso_resource_manage(client->device->card, current_generation,
r->channels, &channel, &bandwidth,
todo == ISO_RES_AUTO_ALLOC ||
todo == ISO_RES_AUTO_REALLOC);
if (todo == ISO_RES_AUTO_DEALLOC) {
e = no_free_ptr(r->e_dealloc);
} else {
// Is this generation outdated already? As long as this resource sticks in the
// xarray, it will be scheduled again for a newer generation or at shutdown.
if (channel == -EAGAIN)
goto out;
// Finishes successfully.
if (channel >= 0 || bandwidth > 0) {
// Generate no event at reallocation.
if (todo == ISO_RES_AUTO_REALLOC)
goto out;
scoped_guard(spinlock_irq, &client->lock) {
// Transit from allocation to reallocation, except if the client
// requested deallocation in the meantime.
r->todo = ISO_RES_AUTO_REALLOC;
r->channels = 1ULL << channel;
}
} else {
// Allocation or reallocation failure? Pull this resource out of the
// xarray and prepare for deletion, unless the client is shutting down.
scoped_guard(spinlock_irq, &client->lock) {
if (!client->in_shutdown && xa_erase(&client->resource_xa, index)) {
client_put(client);
free = true;
}
}
}
e = no_free_ptr(r->e_alloc);
}
e->iso_resource.handle = r->resource.handle;
e->iso_resource.channel = channel;
e->iso_resource.bandwidth = bandwidth;
queue_event(client, &e->event,
&e->iso_resource, sizeof(e->iso_resource), NULL, 0);
if (free) {
cancel_delayed_work(&r->work);
kfree(r->e_alloc);
kfree(r->e_dealloc);
kfree(r);
}
out:
client_put(client);
}
static void iso_resource_once_work(struct work_struct *work)
{
struct iso_resource_once *r = from_work(r, work, work.work);
struct client *client = r->client;
struct iso_resource_event *e;
int generation, channel, bandwidth;
generation = client->device->generation;
bandwidth = r->bandwidth;
r->generation = generation;
fw_iso_resource_manage(client->device->card, generation, r->channels, &channel, &bandwidth,
r->todo == ISO_RES_ONCE_ALLOC);
e = no_free_ptr(r->event);
e->iso_resource.channel = channel;
e->iso_resource.bandwidth = bandwidth;
queue_event(client, &e->event, &e->iso_resource, sizeof(e->iso_resource), NULL, 0);
cancel_delayed_work(&r->work);
client_put(r->client);
kfree(r);
}
Additionally:
New releases of crates for Rust:
I posted: