@@ -158,7 +158,7 @@ struct context {
158158
159159 descriptor_callback_t callback ;
160160
161- struct tasklet_struct tasklet ;
161+ struct work_struct work ;
162162};
163163
164164struct iso_context {
@@ -1176,9 +1176,9 @@ static void context_retire_descriptors(struct context *ctx)
11761176 }
11771177}
11781178
1179- static void context_tasklet ( unsigned long data )
1179+ static void ohci_at_context_work ( struct work_struct * work )
11801180{
1181- struct context * ctx = ( struct context * ) data ;
1181+ struct context * ctx = from_work ( ctx , work , work ) ;
11821182
11831183 context_retire_descriptors (ctx );
11841184}
@@ -1243,7 +1243,6 @@ static int context_init(struct context *ctx, struct fw_ohci *ohci,
12431243 ctx -> buffer_tail = list_entry (ctx -> buffer_list .next ,
12441244 struct descriptor_buffer , list );
12451245
1246- tasklet_init (& ctx -> tasklet , context_tasklet , (unsigned long )ctx );
12471246 ctx -> callback = callback ;
12481247
12491248 /*
@@ -1524,13 +1523,17 @@ static int at_context_queue_packet(struct context *ctx,
15241523
15251524static void at_context_flush (struct context * ctx )
15261525{
1527- tasklet_disable (& ctx -> tasklet );
1526+ // Avoid dead lock due to programming mistake.
1527+ if (WARN_ON_ONCE (current_work () == & ctx -> work ))
1528+ return ;
15281529
1529- ctx -> flushing = true;
1530- context_tasklet ((unsigned long )ctx );
1531- ctx -> flushing = false;
1530+ disable_work_sync (& ctx -> work );
15321531
1533- tasklet_enable (& ctx -> tasklet );
1532+ WRITE_ONCE (ctx -> flushing , true);
1533+ ohci_at_context_work (& ctx -> work );
1534+ WRITE_ONCE (ctx -> flushing , false);
1535+
1536+ enable_work (& ctx -> work );
15341537}
15351538
15361539static int handle_at_packet (struct context * context ,
@@ -1542,7 +1545,7 @@ static int handle_at_packet(struct context *context,
15421545 struct fw_ohci * ohci = context -> ohci ;
15431546 int evt ;
15441547
1545- if (last -> transfer_status == 0 && !context -> flushing )
1548+ if (last -> transfer_status == 0 && !READ_ONCE ( context -> flushing ) )
15461549 /* This descriptor isn't done yet, stop iteration. */
15471550 return 0 ;
15481551
@@ -1576,7 +1579,7 @@ static int handle_at_packet(struct context *context,
15761579 break ;
15771580
15781581 case OHCI1394_evt_missing_ack :
1579- if (context -> flushing )
1582+ if (READ_ONCE ( context -> flushing ) )
15801583 packet -> ack = RCODE_GENERATION ;
15811584 else {
15821585 /*
@@ -1598,7 +1601,7 @@ static int handle_at_packet(struct context *context,
15981601 break ;
15991602
16001603 case OHCI1394_evt_no_status :
1601- if (context -> flushing ) {
1604+ if (READ_ONCE ( context -> flushing ) ) {
16021605 packet -> ack = RCODE_GENERATION ;
16031606 break ;
16041607 }
@@ -2239,10 +2242,10 @@ static irqreturn_t irq_handler(int irq, void *data)
22392242 queue_work (ohci -> card .async_wq , & ohci -> ar_response_ctx .work );
22402243
22412244 if (event & OHCI1394_reqTxComplete )
2242- tasklet_schedule ( & ohci -> at_request_ctx .tasklet );
2245+ queue_work ( ohci -> card . async_wq , & ohci -> at_request_ctx .work );
22432246
22442247 if (event & OHCI1394_respTxComplete )
2245- tasklet_schedule ( & ohci -> at_response_ctx .tasklet );
2248+ queue_work ( ohci -> card . async_wq , & ohci -> at_response_ctx .work );
22462249
22472250 if (event & OHCI1394_isochRx ) {
22482251 iso_event = reg_read (ohci , OHCI1394_IsoRecvIntEventClear );
@@ -2684,7 +2687,10 @@ static int ohci_cancel_packet(struct fw_card *card, struct fw_packet *packet)
26842687 struct driver_data * driver_data = packet -> driver_data ;
26852688 int ret = - ENOENT ;
26862689
2687- tasklet_disable_in_atomic (& ctx -> tasklet );
2690+ // Avoid dead lock due to programming mistake.
2691+ if (WARN_ON_ONCE (current_work () == & ctx -> work ))
2692+ return 0 ;
2693+ disable_work_sync (& ctx -> work );
26882694
26892695 if (packet -> ack != 0 )
26902696 goto out ;
@@ -2703,7 +2709,7 @@ static int ohci_cancel_packet(struct fw_card *card, struct fw_packet *packet)
27032709 packet -> callback (packet , & ohci -> card , packet -> ack );
27042710 ret = 0 ;
27052711 out :
2706- tasklet_enable (& ctx -> tasklet );
2712+ enable_work (& ctx -> work );
27072713
27082714 return ret ;
27092715}
@@ -3765,11 +3771,13 @@ static int pci_probe(struct pci_dev *dev,
37653771 OHCI1394_AsReqTrContextControlSet , handle_at_packet );
37663772 if (err < 0 )
37673773 return err ;
3774+ INIT_WORK (& ohci -> at_request_ctx .work , ohci_at_context_work );
37683775
37693776 err = context_init (& ohci -> at_response_ctx , ohci ,
37703777 OHCI1394_AsRspTrContextControlSet , handle_at_packet );
37713778 if (err < 0 )
37723779 return err ;
3780+ INIT_WORK (& ohci -> at_response_ctx .work , ohci_at_context_work );
37733781
37743782 reg_write (ohci , OHCI1394_IsoRecvIntMaskSet , ~0 );
37753783 ohci -> ir_context_channels = ~0ULL ;
0 commit comments