summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/firewire/lib.c18
-rw-r--r--sound/firewire/lib.h1
2 files changed, 18 insertions, 1 deletions
diff --git a/sound/firewire/lib.c b/sound/firewire/lib.c
index 3e9afd7d402c..9a98c7cd8744 100644
--- a/sound/firewire/lib.c
+++ b/sound/firewire/lib.c
@@ -76,6 +76,9 @@ static void async_midi_port_callback(struct fw_card *card, int rcode,
76 76
77 if (rcode == RCODE_COMPLETE && substream != NULL) 77 if (rcode == RCODE_COMPLETE && substream != NULL)
78 snd_rawmidi_transmit_ack(substream, port->consume_bytes); 78 snd_rawmidi_transmit_ack(substream, port->consume_bytes);
79 else if (!rcode_is_permanent_error(rcode))
80 /* To start next transaction immediately for recovery. */
81 port->next_ktime = ktime_set(0, 0);
79 82
80 port->idling = true; 83 port->idling = true;
81 84
@@ -99,6 +102,12 @@ static void midi_port_work(struct work_struct *work)
99 if (substream == NULL || snd_rawmidi_transmit_empty(substream)) 102 if (substream == NULL || snd_rawmidi_transmit_empty(substream))
100 return; 103 return;
101 104
105 /* Do it in next chance. */
106 if (ktime_after(port->next_ktime, ktime_get())) {
107 schedule_work(&port->work);
108 return;
109 }
110
102 /* 111 /*
103 * Fill the buffer. The callee must use snd_rawmidi_transmit_peek(). 112 * Fill the buffer. The callee must use snd_rawmidi_transmit_peek().
104 * Later, snd_rawmidi_transmit_ack() is called. 113 * Later, snd_rawmidi_transmit_ack() is called.
@@ -107,8 +116,10 @@ static void midi_port_work(struct work_struct *work)
107 port->consume_bytes = port->fill(substream, port->buf); 116 port->consume_bytes = port->fill(substream, port->buf);
108 if (port->consume_bytes <= 0) { 117 if (port->consume_bytes <= 0) {
109 /* Do it in next chance, immediately. */ 118 /* Do it in next chance, immediately. */
110 if (port->consume_bytes == 0) 119 if (port->consume_bytes == 0) {
120 port->next_ktime = ktime_set(0, 0);
111 schedule_work(&port->work); 121 schedule_work(&port->work);
122 }
112 return; 123 return;
113 } 124 }
114 125
@@ -118,6 +129,10 @@ static void midi_port_work(struct work_struct *work)
118 else 129 else
119 type = TCODE_WRITE_BLOCK_REQUEST; 130 type = TCODE_WRITE_BLOCK_REQUEST;
120 131
132 /* Set interval to next transaction. */
133 port->next_ktime = ktime_add_ns(ktime_get(),
134 port->consume_bytes * 8 * NSEC_PER_SEC / 31250);
135
121 /* Start this transaction. */ 136 /* Start this transaction. */
122 port->idling = false; 137 port->idling = false;
123 138
@@ -162,6 +177,7 @@ int snd_fw_async_midi_port_init(struct snd_fw_async_midi_port *port,
162 port->addr = addr; 177 port->addr = addr;
163 port->fill = fill; 178 port->fill = fill;
164 port->idling = true; 179 port->idling = true;
180 port->next_ktime = ktime_set(0, 0);
165 181
166 INIT_WORK(&port->work, midi_port_work); 182 INIT_WORK(&port->work, midi_port_work);
167 183
diff --git a/sound/firewire/lib.h b/sound/firewire/lib.h
index 0af06f44e8c2..59e086587212 100644
--- a/sound/firewire/lib.h
+++ b/sound/firewire/lib.h
@@ -31,6 +31,7 @@ struct snd_fw_async_midi_port {
31 struct fw_device *parent; 31 struct fw_device *parent;
32 struct work_struct work; 32 struct work_struct work;
33 bool idling; 33 bool idling;
34 ktime_t next_ktime;
34 35
35 u64 addr; 36 u64 addr;
36 struct fw_transaction transaction; 37 struct fw_transaction transaction;