@@ -1182,6 +1182,47 @@ static void context_tasklet(unsigned long data)
1182
1182
}
1183
1183
}
1184
1184
1185
+ static void ohci_isoc_context_work (struct work_struct * work )
1186
+ {
1187
+ struct fw_iso_context * base = container_of (work , struct fw_iso_context , work );
1188
+ struct iso_context * isoc_ctx = container_of (base , struct iso_context , base );
1189
+ struct context * ctx = & isoc_ctx -> context ;
1190
+ struct descriptor * d , * last ;
1191
+ u32 address ;
1192
+ int z ;
1193
+ struct descriptor_buffer * desc ;
1194
+
1195
+ desc = list_entry (ctx -> buffer_list .next , struct descriptor_buffer , list );
1196
+ last = ctx -> last ;
1197
+ while (last -> branch_address != 0 ) {
1198
+ struct descriptor_buffer * old_desc = desc ;
1199
+
1200
+ address = le32_to_cpu (last -> branch_address );
1201
+ z = address & 0xf ;
1202
+ address &= ~0xf ;
1203
+ ctx -> current_bus = address ;
1204
+
1205
+ // If the branch address points to a buffer outside of the current buffer, advance
1206
+ // to the next buffer.
1207
+ if (address < desc -> buffer_bus || address >= desc -> buffer_bus + desc -> used )
1208
+ desc = list_entry (desc -> list .next , struct descriptor_buffer , list );
1209
+ d = desc -> buffer + (address - desc -> buffer_bus ) / sizeof (* d );
1210
+ last = find_branch_descriptor (d , z );
1211
+
1212
+ if (!ctx -> callback (ctx , d , last ))
1213
+ break ;
1214
+
1215
+ if (old_desc != desc ) {
1216
+ // If we've advanced to the next buffer, move the previous buffer to the
1217
+ // free list.
1218
+ old_desc -> used = 0 ;
1219
+ guard (spinlock_irqsave )(& ctx -> ohci -> lock );
1220
+ list_move_tail (& old_desc -> list , & ctx -> buffer_list );
1221
+ }
1222
+ ctx -> last = last ;
1223
+ }
1224
+ }
1225
+
1185
1226
/*
1186
1227
* Allocate a new buffer and add it to the list of free buffers for this
1187
1228
* context. Must be called with ohci->lock held.
@@ -2242,8 +2283,7 @@ static irqreturn_t irq_handler(int irq, void *data)
2242
2283
2243
2284
while (iso_event ) {
2244
2285
i = ffs (iso_event ) - 1 ;
2245
- tasklet_schedule (
2246
- & ohci -> ir_context_list [i ].context .tasklet );
2286
+ fw_iso_context_queue_work (& ohci -> ir_context_list [i ].base );
2247
2287
iso_event &= ~(1 << i );
2248
2288
}
2249
2289
}
@@ -2254,8 +2294,7 @@ static irqreturn_t irq_handler(int irq, void *data)
2254
2294
2255
2295
while (iso_event ) {
2256
2296
i = ffs (iso_event ) - 1 ;
2257
- tasklet_schedule (
2258
- & ohci -> it_context_list [i ].context .tasklet );
2297
+ fw_iso_context_queue_work (& ohci -> it_context_list [i ].base );
2259
2298
iso_event &= ~(1 << i );
2260
2299
}
2261
2300
}
@@ -3130,6 +3169,7 @@ static struct fw_iso_context *ohci_allocate_iso_context(struct fw_card *card,
3130
3169
ret = context_init (& ctx -> context , ohci , regs , callback );
3131
3170
if (ret < 0 )
3132
3171
goto out_with_header ;
3172
+ fw_iso_context_init_work (& ctx -> base , ohci_isoc_context_work );
3133
3173
3134
3174
if (type == FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL ) {
3135
3175
set_multichannel_mask (ohci , 0 );
@@ -3227,7 +3267,6 @@ static int ohci_stop_iso(struct fw_iso_context *base)
3227
3267
}
3228
3268
flush_writes (ohci );
3229
3269
context_stop (& ctx -> context );
3230
- tasklet_kill (& ctx -> context .tasklet );
3231
3270
3232
3271
return 0 ;
3233
3272
}
@@ -3584,10 +3623,8 @@ static int ohci_flush_iso_completions(struct fw_iso_context *base)
3584
3623
struct iso_context * ctx = container_of (base , struct iso_context , base );
3585
3624
int ret = 0 ;
3586
3625
3587
- tasklet_disable_in_atomic (& ctx -> context .tasklet );
3588
-
3589
3626
if (!test_and_set_bit_lock (0 , & ctx -> flushing_completions )) {
3590
- context_tasklet (( unsigned long ) & ctx -> context );
3627
+ ohci_isoc_context_work ( & base -> work );
3591
3628
3592
3629
switch (base -> type ) {
3593
3630
case FW_ISO_CONTEXT_TRANSMIT :
@@ -3607,8 +3644,6 @@ static int ohci_flush_iso_completions(struct fw_iso_context *base)
3607
3644
smp_mb__after_atomic ();
3608
3645
}
3609
3646
3610
- tasklet_enable (& ctx -> context .tasklet );
3611
-
3612
3647
return ret ;
3613
3648
}
3614
3649
0 commit comments