|
@@ -109,6 +109,7 @@ static inline struct f_midi *func_to_midi(struct usb_function *f)
|
|
|
|
|
|
static void f_midi_transmit(struct f_midi *midi);
|
|
static void f_midi_transmit(struct f_midi *midi);
|
|
static void f_midi_rmidi_free(struct snd_rawmidi *rmidi);
|
|
static void f_midi_rmidi_free(struct snd_rawmidi *rmidi);
|
|
|
|
+static void f_midi_free_inst(struct usb_function_instance *f);
|
|
|
|
|
|
DECLARE_UAC_AC_HEADER_DESCRIPTOR(1);
|
|
DECLARE_UAC_AC_HEADER_DESCRIPTOR(1);
|
|
DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(1);
|
|
DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(1);
|
|
@@ -1102,7 +1103,7 @@ static ssize_t f_midi_opts_##name##_store(struct config_item *item, \
|
|
u32 num; \
|
|
u32 num; \
|
|
\
|
|
\
|
|
mutex_lock(&opts->lock); \
|
|
mutex_lock(&opts->lock); \
|
|
- if (opts->refcnt) { \
|
|
|
|
|
|
+ if (opts->refcnt > 1) { \
|
|
ret = -EBUSY; \
|
|
ret = -EBUSY; \
|
|
goto end; \
|
|
goto end; \
|
|
} \
|
|
} \
|
|
@@ -1157,7 +1158,7 @@ static ssize_t f_midi_opts_id_store(struct config_item *item,
|
|
char *c;
|
|
char *c;
|
|
|
|
|
|
mutex_lock(&opts->lock);
|
|
mutex_lock(&opts->lock);
|
|
- if (opts->refcnt) {
|
|
|
|
|
|
+ if (opts->refcnt > 1) {
|
|
ret = -EBUSY;
|
|
ret = -EBUSY;
|
|
goto end;
|
|
goto end;
|
|
}
|
|
}
|
|
@@ -1198,13 +1199,21 @@ static const struct config_item_type midi_func_type = {
|
|
static void f_midi_free_inst(struct usb_function_instance *f)
|
|
static void f_midi_free_inst(struct usb_function_instance *f)
|
|
{
|
|
{
|
|
struct f_midi_opts *opts;
|
|
struct f_midi_opts *opts;
|
|
|
|
+ bool free = false;
|
|
|
|
|
|
opts = container_of(f, struct f_midi_opts, func_inst);
|
|
opts = container_of(f, struct f_midi_opts, func_inst);
|
|
|
|
|
|
- if (opts->id_allocated)
|
|
|
|
- kfree(opts->id);
|
|
|
|
|
|
+ mutex_lock(&opts->lock);
|
|
|
|
+ if (!--opts->refcnt) {
|
|
|
|
+ free = true;
|
|
|
|
+ }
|
|
|
|
+ mutex_unlock(&opts->lock);
|
|
|
|
|
|
- kfree(opts);
|
|
|
|
|
|
+ if (free) {
|
|
|
|
+ if (opts->id_allocated)
|
|
|
|
+ kfree(opts->id);
|
|
|
|
+ kfree(opts);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
static struct usb_function_instance *f_midi_alloc_inst(void)
|
|
static struct usb_function_instance *f_midi_alloc_inst(void)
|
|
@@ -1223,6 +1232,7 @@ static struct usb_function_instance *f_midi_alloc_inst(void)
|
|
opts->qlen = 32;
|
|
opts->qlen = 32;
|
|
opts->in_ports = 1;
|
|
opts->in_ports = 1;
|
|
opts->out_ports = 1;
|
|
opts->out_ports = 1;
|
|
|
|
+ opts->refcnt = 1;
|
|
|
|
|
|
config_group_init_type_name(&opts->func_inst.group, "",
|
|
config_group_init_type_name(&opts->func_inst.group, "",
|
|
&midi_func_type);
|
|
&midi_func_type);
|
|
@@ -1234,6 +1244,7 @@ static void f_midi_free(struct usb_function *f)
|
|
{
|
|
{
|
|
struct f_midi *midi;
|
|
struct f_midi *midi;
|
|
struct f_midi_opts *opts;
|
|
struct f_midi_opts *opts;
|
|
|
|
+ bool free = false;
|
|
|
|
|
|
midi = func_to_midi(f);
|
|
midi = func_to_midi(f);
|
|
opts = container_of(f->fi, struct f_midi_opts, func_inst);
|
|
opts = container_of(f->fi, struct f_midi_opts, func_inst);
|
|
@@ -1242,9 +1253,12 @@ static void f_midi_free(struct usb_function *f)
|
|
kfree(midi->id);
|
|
kfree(midi->id);
|
|
kfifo_free(&midi->in_req_fifo);
|
|
kfifo_free(&midi->in_req_fifo);
|
|
kfree(midi);
|
|
kfree(midi);
|
|
- --opts->refcnt;
|
|
|
|
|
|
+ free = true;
|
|
}
|
|
}
|
|
mutex_unlock(&opts->lock);
|
|
mutex_unlock(&opts->lock);
|
|
|
|
+
|
|
|
|
+ if (free)
|
|
|
|
+ f_midi_free_inst(&opts->func_inst);
|
|
}
|
|
}
|
|
|
|
|
|
static void f_midi_rmidi_free(struct snd_rawmidi *rmidi)
|
|
static void f_midi_rmidi_free(struct snd_rawmidi *rmidi)
|