Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'firewire-updates-6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394

Pull firewire updates from Takashi Sakamoto:
"This update replaces the remaining tasklet usage in the FireWire
subsystem with workqueue for asynchronous packet transmission. With
this change, tasklets are now fully eliminated from the subsystem.

Asynchronous packet transmission is used for serial bus topology
management as well as for the operation of the SBP-2 protocol driver
(firewire-sbp2). To ensure reliability during low-memory conditions,
the associated workqueue is created with the WQ_MEM_RECLAIM flag,
allowing it to participate in memory reclaim paths. Other attributes
are aligned with those used for isochronous packet handling, which was
migrated to workqueues in v6.12.

The workqueues are sleepable and support preemptible work items,
making them more suitable for real-time workloads that benefit from
timely task preemption at the system level.

There remains an issue where 'schedule()' may be called within an RCU
read-side critical section, due to a direct replacement of
'tasklet_disable_in_atomic()' with 'disable_work_sync()'. A proposed
fix for this has been posted[1], and is currently under review and
testing. It is expected to be sent upstream later"

Link: https://lore.kernel.org/lkml/20250728015125.17825-1-o-takashi@sakamocchi.jp/ [1]

* tag 'firewire-updates-6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394:
firewire: ohci: reduce the size of common context structure by extracting members into AT structure
firewire: core: minor code refactoring to localize table of gap count
firewire: ohci: use workqueue to handle events of AT request/response contexts
firewire: ohci: use workqueue to handle events of AR request/response contexts
firewire: core: allocate workqueue for AR/AT request/response contexts
firewire: core: use from_work() macro to expand parent structure of work_struct
firewire: ohci: use from_work() macro to expand parent structure of work_struct
firewire: ohci: correct code comments about bus_reset tasklet

+146 -116
+39 -20
drivers/firewire/core-card.c
··· 237 237 238 238 static void br_work(struct work_struct *work) 239 239 { 240 - struct fw_card *card = container_of(work, struct fw_card, br_work.work); 240 + struct fw_card *card = from_work(card, work, br_work.work); 241 241 242 242 /* Delay for 2s after last reset per IEEE 1394 clause 8.2.1. */ 243 243 if (card->reset_jiffies != 0 && ··· 273 273 fw_device_set_broadcast_channel); 274 274 } 275 275 276 - static const char gap_count_table[] = { 277 - 63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40 278 - }; 279 - 280 276 void fw_schedule_bm_work(struct fw_card *card, unsigned long delay) 281 277 { 282 278 fw_card_get(card); ··· 282 286 283 287 static void bm_work(struct work_struct *work) 284 288 { 285 - struct fw_card *card = container_of(work, struct fw_card, bm_work.work); 289 + static const char gap_count_table[] = { 290 + 63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40 291 + }; 292 + struct fw_card *card = from_work(card, work, bm_work.work); 286 293 struct fw_device *root_device, *irm_device; 287 294 struct fw_node *root_node; 288 295 int root_id, new_root_id, irm_id, bm_id, local_id; ··· 573 574 int fw_card_add(struct fw_card *card, u32 max_receive, u32 link_speed, u64 guid, 574 575 unsigned int supported_isoc_contexts) 575 576 { 576 - struct workqueue_struct *isoc_wq; 577 577 int ret; 578 578 579 579 // This workqueue should be: ··· 587 589 // * == WQ_SYSFS Parameters are available via sysfs. 588 590 // * max_active == n_it + n_ir A hardIRQ could notify events for multiple isochronous 589 591 // contexts if they are scheduled to the same cycle. 590 - isoc_wq = alloc_workqueue("firewire-isoc-card%u", 591 - WQ_UNBOUND | WQ_FREEZABLE | WQ_HIGHPRI | WQ_SYSFS, 592 - supported_isoc_contexts, card->index); 593 - if (!isoc_wq) 592 + card->isoc_wq = alloc_workqueue("firewire-isoc-card%u", 593 + WQ_UNBOUND | WQ_FREEZABLE | WQ_HIGHPRI | WQ_SYSFS, 594 + supported_isoc_contexts, card->index); 595 + if (!card->isoc_wq) 594 596 return -ENOMEM; 597 + 598 + // This workqueue should be: 599 + // * != WQ_BH Sleepable. 600 + // * == WQ_UNBOUND Any core can process data for asynchronous context. 601 + // * == WQ_MEM_RECLAIM Used for any backend of block device. 602 + // * == WQ_FREEZABLE The target device would not be available when being freezed. 603 + // * == WQ_HIGHPRI High priority to process semi-realtime timestamped data. 604 + // * == WQ_SYSFS Parameters are available via sysfs. 605 + // * max_active == 4 A hardIRQ could notify events for a pair of requests and 606 + // response AR/AT contexts. 607 + card->async_wq = alloc_workqueue("firewire-async-card%u", 608 + WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_FREEZABLE | WQ_HIGHPRI | WQ_SYSFS, 609 + 4, card->index); 610 + if (!card->async_wq) { 611 + ret = -ENOMEM; 612 + goto err_isoc; 613 + } 595 614 596 615 card->max_receive = max_receive; 597 616 card->link_speed = link_speed; 598 617 card->guid = guid; 599 618 600 - guard(mutex)(&card_mutex); 619 + scoped_guard(mutex, &card_mutex) { 620 + generate_config_rom(card, tmp_config_rom); 621 + ret = card->driver->enable(card, tmp_config_rom, config_rom_length); 622 + if (ret < 0) 623 + goto err_async; 601 624 602 - generate_config_rom(card, tmp_config_rom); 603 - ret = card->driver->enable(card, tmp_config_rom, config_rom_length); 604 - if (ret < 0) { 605 - destroy_workqueue(isoc_wq); 606 - return ret; 625 + list_add_tail(&card->link, &card_list); 607 626 } 608 627 609 - card->isoc_wq = isoc_wq; 610 - list_add_tail(&card->link, &card_list); 611 - 612 628 return 0; 629 + err_async: 630 + destroy_workqueue(card->async_wq); 631 + err_isoc: 632 + destroy_workqueue(card->isoc_wq); 633 + return ret; 613 634 } 614 635 EXPORT_SYMBOL(fw_card_add); 615 636 ··· 761 744 dummy_driver.stop_iso = card->driver->stop_iso; 762 745 card->driver = &dummy_driver; 763 746 drain_workqueue(card->isoc_wq); 747 + drain_workqueue(card->async_wq); 764 748 765 749 scoped_guard(spinlock_irqsave, &card->lock) 766 750 fw_destroy_nodes(card); ··· 771 753 wait_for_completion(&card->done); 772 754 773 755 destroy_workqueue(card->isoc_wq); 756 + destroy_workqueue(card->async_wq); 774 757 775 758 WARN_ON(!list_empty(&card->transaction_list)); 776 759 }
+1 -2
drivers/firewire/core-cdev.c
··· 1313 1313 static void iso_resource_work(struct work_struct *work) 1314 1314 { 1315 1315 struct iso_resource_event *e; 1316 - struct iso_resource *r = 1317 - container_of(work, struct iso_resource, work.work); 1316 + struct iso_resource *r = from_work(r, work, work.work); 1318 1317 struct client *client = r->client; 1319 1318 unsigned long index = r->resource.handle; 1320 1319 int generation, channel, bandwidth, todo;
+5 -10
drivers/firewire/core-device.c
··· 853 853 854 854 static void fw_device_shutdown(struct work_struct *work) 855 855 { 856 - struct fw_device *device = 857 - container_of(work, struct fw_device, work.work); 856 + struct fw_device *device = from_work(device, work, work.work); 858 857 859 858 if (time_before64(get_jiffies_64(), 860 859 device->card->reset_jiffies + SHUTDOWN_DELAY) ··· 920 921 921 922 static void fw_device_update(struct work_struct *work) 922 923 { 923 - struct fw_device *device = 924 - container_of(work, struct fw_device, work.work); 924 + struct fw_device *device = from_work(device, work, work.work); 925 925 926 926 fw_device_cdev_update(device); 927 927 device_for_each_child(&device->device, NULL, update_unit); ··· 1000 1002 1001 1003 static void fw_device_init(struct work_struct *work) 1002 1004 { 1003 - struct fw_device *device = 1004 - container_of(work, struct fw_device, work.work); 1005 + struct fw_device *device = from_work(device, work, work.work); 1005 1006 struct fw_card *card = device->card; 1006 1007 struct device *found; 1007 1008 u32 minor; ··· 1181 1184 1182 1185 static void fw_device_refresh(struct work_struct *work) 1183 1186 { 1184 - struct fw_device *device = 1185 - container_of(work, struct fw_device, work.work); 1187 + struct fw_device *device = from_work(device, work, work.work); 1186 1188 struct fw_card *card = device->card; 1187 1189 int ret, node_id = device->node_id; 1188 1190 bool changed; ··· 1247 1251 1248 1252 static void fw_device_workfn(struct work_struct *work) 1249 1253 { 1250 - struct fw_device *device = container_of(to_delayed_work(work), 1251 - struct fw_device, work); 1254 + struct fw_device *device = from_work(device, to_delayed_work(work), work); 1252 1255 device->workfn(work); 1253 1256 } 1254 1257
+4 -3
drivers/firewire/core-transaction.c
··· 557 557 * 558 558 * region->start, ->end, and handler->length have to be quadlet-aligned. 559 559 * 560 - * When a request is received that falls within the specified address range, 561 - * the specified callback is invoked. The parameters passed to the callback 562 - * give the details of the particular request. 560 + * When a request is received that falls within the specified address range, the specified callback 561 + * is invoked. The parameters passed to the callback give the details of the particular request. 562 + * The callback is invoked in the workqueue context in most cases. However, if the request is 563 + * initiated by the local node, the callback is invoked in the initiator's context. 563 564 * 564 565 * To be called in process context. 565 566 * Return value: 0 on success, non-zero otherwise.
+2 -2
drivers/firewire/net.c
··· 1007 1007 1008 1008 spin_lock_irqsave(&dev->lock, flags); 1009 1009 1010 - /* If the AT tasklet already ran, we may be last user. */ 1010 + /* If the AT work item already ran, we may be last user. */ 1011 1011 free = (ptask->outstanding_pkts == 0 && !ptask->enqueued); 1012 1012 if (!free) 1013 1013 ptask->enqueued = true; ··· 1026 1026 1027 1027 spin_lock_irqsave(&dev->lock, flags); 1028 1028 1029 - /* If the AT tasklet already ran, we may be last user. */ 1029 + /* If the AT work item already ran, we may be last user. */ 1030 1030 free = (ptask->outstanding_pkts == 0 && !ptask->enqueued); 1031 1031 if (!free) 1032 1032 ptask->enqueued = true;
+85 -77
drivers/firewire/ohci.c
··· 101 101 void *pointer; 102 102 unsigned int last_buffer_index; 103 103 u32 regs; 104 - struct tasklet_struct tasklet; 104 + struct work_struct work; 105 105 }; 106 106 107 107 struct context; ··· 128 128 int total_allocation; 129 129 u32 current_bus; 130 130 bool running; 131 - bool flushing; 132 131 133 132 /* 134 133 * List of page-sized buffers for storing DMA descriptors. ··· 156 157 int prev_z; 157 158 158 159 descriptor_callback_t callback; 160 + }; 159 161 160 - struct tasklet_struct tasklet; 162 + struct at_context { 163 + struct context context; 164 + struct work_struct work; 165 + bool flushing; 161 166 }; 162 167 163 168 struct iso_context { ··· 207 204 208 205 struct ar_context ar_request_ctx; 209 206 struct ar_context ar_response_ctx; 210 - struct context at_request_ctx; 211 - struct context at_response_ctx; 207 + struct at_context at_request_ctx; 208 + struct at_context at_response_ctx; 212 209 213 210 u32 it_context_support; 214 211 u32 it_context_mask; /* unoccupied IT contexts */ ··· 1019 1016 } 1020 1017 } 1021 1018 1022 - static void ar_context_tasklet(unsigned long data) 1019 + static void ohci_ar_context_work(struct work_struct *work) 1023 1020 { 1024 - struct ar_context *ctx = (struct ar_context *)data; 1021 + struct ar_context *ctx = from_work(ctx, work, work); 1025 1022 unsigned int end_buffer_index, end_buffer_offset; 1026 1023 void *p, *end; 1027 1024 ··· 1029 1026 if (!p) 1030 1027 return; 1031 1028 1032 - end_buffer_index = ar_search_last_active_buffer(ctx, 1033 - &end_buffer_offset); 1029 + end_buffer_index = ar_search_last_active_buffer(ctx, &end_buffer_offset); 1034 1030 ar_sync_buffers_for_cpu(ctx, end_buffer_index, end_buffer_offset); 1035 1031 end = ctx->buffer + end_buffer_index * PAGE_SIZE + end_buffer_offset; 1036 1032 1037 1033 if (end_buffer_index < ar_first_buffer_index(ctx)) { 1038 - /* 1039 - * The filled part of the overall buffer wraps around; handle 1040 - * all packets up to the buffer end here. If the last packet 1041 - * wraps around, its tail will be visible after the buffer end 1042 - * because the buffer start pages are mapped there again. 1043 - */ 1034 + // The filled part of the overall buffer wraps around; handle all packets up to the 1035 + // buffer end here. If the last packet wraps around, its tail will be visible after 1036 + // the buffer end because the buffer start pages are mapped there again. 1044 1037 void *buffer_end = ctx->buffer + AR_BUFFERS * PAGE_SIZE; 1045 1038 p = handle_ar_packets(ctx, p, buffer_end); 1046 1039 if (p < buffer_end) 1047 1040 goto error; 1048 - /* adjust p to point back into the actual buffer */ 1041 + // adjust p to point back into the actual buffer 1049 1042 p -= AR_BUFFERS * PAGE_SIZE; 1050 1043 } 1051 1044 ··· 1056 1057 ar_recycle_buffers(ctx, end_buffer_index); 1057 1058 1058 1059 return; 1059 - 1060 1060 error: 1061 1061 ctx->pointer = NULL; 1062 1062 } ··· 1071 1073 1072 1074 ctx->regs = regs; 1073 1075 ctx->ohci = ohci; 1074 - tasklet_init(&ctx->tasklet, ar_context_tasklet, (unsigned long)ctx); 1076 + INIT_WORK(&ctx->work, ohci_ar_context_work); 1075 1077 1076 1078 for (i = 0; i < AR_BUFFERS; i++) { 1077 1079 ctx->pages[i] = dma_alloc_pages(dev, PAGE_SIZE, &dma_addr, ··· 1179 1181 } 1180 1182 } 1181 1183 1182 - static void context_tasklet(unsigned long data) 1184 + static void ohci_at_context_work(struct work_struct *work) 1183 1185 { 1184 - struct context *ctx = (struct context *) data; 1186 + struct at_context *ctx = from_work(ctx, work, work); 1185 1187 1186 - context_retire_descriptors(ctx); 1188 + context_retire_descriptors(&ctx->context); 1187 1189 } 1188 1190 1189 1191 static void ohci_isoc_context_work(struct work_struct *work) 1190 1192 { 1191 - struct fw_iso_context *base = container_of(work, struct fw_iso_context, work); 1193 + struct fw_iso_context *base = from_work(base, work, work); 1192 1194 struct iso_context *isoc_ctx = container_of(base, struct iso_context, base); 1193 1195 1194 1196 context_retire_descriptors(&isoc_ctx->context); ··· 1246 1248 ctx->buffer_tail = list_entry(ctx->buffer_list.next, 1247 1249 struct descriptor_buffer, list); 1248 1250 1249 - tasklet_init(&ctx->tasklet, context_tasklet, (unsigned long)ctx); 1250 1251 ctx->callback = callback; 1251 1252 1252 1253 /* ··· 1385 1388 * Must always be called with the ochi->lock held to ensure proper 1386 1389 * generation handling and locking around packet queue manipulation. 1387 1390 */ 1388 - static int at_context_queue_packet(struct context *ctx, 1389 - struct fw_packet *packet) 1391 + static int at_context_queue_packet(struct at_context *ctx, struct fw_packet *packet) 1390 1392 { 1391 - struct fw_ohci *ohci = ctx->ohci; 1393 + struct context *context = &ctx->context; 1394 + struct fw_ohci *ohci = context->ohci; 1392 1395 dma_addr_t d_bus, payload_bus; 1393 1396 struct driver_data *driver_data; 1394 1397 struct descriptor *d, *last; 1395 1398 __le32 *header; 1396 1399 int z, tcode; 1397 1400 1398 - d = context_get_descriptors(ctx, 4, &d_bus); 1401 + d = context_get_descriptors(context, 4, &d_bus); 1399 1402 if (d == NULL) { 1400 1403 packet->ack = RCODE_SEND_ERROR; 1401 1404 return -1; ··· 1425 1428 ohci1394_at_data_set_destination_id(header, 1426 1429 async_header_get_destination(packet->header)); 1427 1430 1428 - if (ctx == &ctx->ohci->at_response_ctx) { 1431 + if (ctx == &ohci->at_response_ctx) { 1429 1432 ohci1394_at_data_set_rcode(header, async_header_get_rcode(packet->header)); 1430 1433 } else { 1431 1434 ohci1394_at_data_set_destination_offset(header, ··· 1514 1517 return -1; 1515 1518 } 1516 1519 1517 - context_append(ctx, d, z, 4 - z); 1520 + context_append(context, d, z, 4 - z); 1518 1521 1519 - if (ctx->running) 1520 - reg_write(ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE); 1522 + if (context->running) 1523 + reg_write(ohci, CONTROL_SET(context->regs), CONTEXT_WAKE); 1521 1524 else 1522 - context_run(ctx, 0); 1525 + context_run(context, 0); 1523 1526 1524 1527 return 0; 1525 1528 } 1526 1529 1527 - static void at_context_flush(struct context *ctx) 1530 + static void at_context_flush(struct at_context *ctx) 1528 1531 { 1529 - tasklet_disable(&ctx->tasklet); 1532 + // Avoid dead lock due to programming mistake. 1533 + if (WARN_ON_ONCE(current_work() == &ctx->work)) 1534 + return; 1530 1535 1531 - ctx->flushing = true; 1532 - context_tasklet((unsigned long)ctx); 1533 - ctx->flushing = false; 1536 + disable_work_sync(&ctx->work); 1534 1537 1535 - tasklet_enable(&ctx->tasklet); 1538 + WRITE_ONCE(ctx->flushing, true); 1539 + ohci_at_context_work(&ctx->work); 1540 + WRITE_ONCE(ctx->flushing, false); 1541 + 1542 + enable_work(&ctx->work); 1536 1543 } 1537 1544 1538 1545 static int handle_at_packet(struct context *context, 1539 1546 struct descriptor *d, 1540 1547 struct descriptor *last) 1541 1548 { 1549 + struct at_context *ctx = container_of(context, struct at_context, context); 1550 + struct fw_ohci *ohci = ctx->context.ohci; 1542 1551 struct driver_data *driver_data; 1543 1552 struct fw_packet *packet; 1544 - struct fw_ohci *ohci = context->ohci; 1545 1553 int evt; 1546 1554 1547 - if (last->transfer_status == 0 && !context->flushing) 1555 + if (last->transfer_status == 0 && !READ_ONCE(ctx->flushing)) 1548 1556 /* This descriptor isn't done yet, stop iteration. */ 1549 1557 return 0; 1550 1558 ··· 1583 1581 break; 1584 1582 1585 1583 case OHCI1394_evt_missing_ack: 1586 - if (context->flushing) 1584 + if (READ_ONCE(ctx->flushing)) 1587 1585 packet->ack = RCODE_GENERATION; 1588 1586 else { 1589 1587 /* ··· 1605 1603 break; 1606 1604 1607 1605 case OHCI1394_evt_no_status: 1608 - if (context->flushing) { 1606 + if (READ_ONCE(ctx->flushing)) { 1609 1607 packet->ack = RCODE_GENERATION; 1610 1608 break; 1611 1609 } ··· 1702 1700 fw_core_handle_response(&ohci->card, &response); 1703 1701 } 1704 1702 1705 - static void handle_local_request(struct context *ctx, struct fw_packet *packet) 1703 + static void handle_local_request(struct at_context *ctx, struct fw_packet *packet) 1706 1704 { 1705 + struct fw_ohci *ohci = ctx->context.ohci; 1707 1706 u64 offset, csr; 1708 1707 1709 - if (ctx == &ctx->ohci->at_request_ctx) { 1708 + if (ctx == &ohci->at_request_ctx) { 1710 1709 packet->ack = ACK_PENDING; 1711 - packet->callback(packet, &ctx->ohci->card, packet->ack); 1710 + packet->callback(packet, &ohci->card, packet->ack); 1712 1711 } 1713 1712 1714 1713 offset = async_header_get_offset(packet->header); ··· 1717 1714 1718 1715 /* Handle config rom reads. */ 1719 1716 if (csr >= CSR_CONFIG_ROM && csr < CSR_CONFIG_ROM_END) 1720 - handle_local_rom(ctx->ohci, packet, csr); 1717 + handle_local_rom(ohci, packet, csr); 1721 1718 else switch (csr) { 1722 1719 case CSR_BUS_MANAGER_ID: 1723 1720 case CSR_BANDWIDTH_AVAILABLE: 1724 1721 case CSR_CHANNELS_AVAILABLE_HI: 1725 1722 case CSR_CHANNELS_AVAILABLE_LO: 1726 - handle_local_lock(ctx->ohci, packet, csr); 1723 + handle_local_lock(ohci, packet, csr); 1727 1724 break; 1728 1725 default: 1729 - if (ctx == &ctx->ohci->at_request_ctx) 1730 - fw_core_handle_request(&ctx->ohci->card, packet); 1726 + if (ctx == &ohci->at_request_ctx) 1727 + fw_core_handle_request(&ohci->card, packet); 1731 1728 else 1732 - fw_core_handle_response(&ctx->ohci->card, packet); 1729 + fw_core_handle_response(&ohci->card, packet); 1733 1730 break; 1734 1731 } 1735 1732 1736 - if (ctx == &ctx->ohci->at_response_ctx) { 1733 + if (ctx == &ohci->at_response_ctx) { 1737 1734 packet->ack = ACK_COMPLETE; 1738 - packet->callback(packet, &ctx->ohci->card, packet->ack); 1735 + packet->callback(packet, &ohci->card, packet->ack); 1739 1736 } 1740 1737 } 1741 1738 1742 - static void at_context_transmit(struct context *ctx, struct fw_packet *packet) 1739 + static void at_context_transmit(struct at_context *ctx, struct fw_packet *packet) 1743 1740 { 1741 + struct fw_ohci *ohci = ctx->context.ohci; 1744 1742 unsigned long flags; 1745 1743 int ret; 1746 1744 1747 - spin_lock_irqsave(&ctx->ohci->lock, flags); 1745 + spin_lock_irqsave(&ohci->lock, flags); 1748 1746 1749 - if (async_header_get_destination(packet->header) == ctx->ohci->node_id && 1750 - ctx->ohci->generation == packet->generation) { 1751 - spin_unlock_irqrestore(&ctx->ohci->lock, flags); 1747 + if (async_header_get_destination(packet->header) == ohci->node_id && 1748 + ohci->generation == packet->generation) { 1749 + spin_unlock_irqrestore(&ohci->lock, flags); 1752 1750 1753 1751 // Timestamping on behalf of the hardware. 1754 - packet->timestamp = cycle_time_to_ohci_tstamp(get_cycle_time(ctx->ohci)); 1752 + packet->timestamp = cycle_time_to_ohci_tstamp(get_cycle_time(ohci)); 1755 1753 1756 1754 handle_local_request(ctx, packet); 1757 1755 return; 1758 1756 } 1759 1757 1760 1758 ret = at_context_queue_packet(ctx, packet); 1761 - spin_unlock_irqrestore(&ctx->ohci->lock, flags); 1759 + spin_unlock_irqrestore(&ohci->lock, flags); 1762 1760 1763 1761 if (ret < 0) { 1764 1762 // Timestamping on behalf of the hardware. 1765 - packet->timestamp = cycle_time_to_ohci_tstamp(get_cycle_time(ctx->ohci)); 1763 + packet->timestamp = cycle_time_to_ohci_tstamp(get_cycle_time(ohci)); 1766 1764 1767 - packet->callback(packet, &ctx->ohci->card, packet->ack); 1765 + packet->callback(packet, &ohci->card, packet->ack); 1768 1766 } 1769 1767 } 1770 1768 ··· 2032 2028 2033 2029 static void bus_reset_work(struct work_struct *work) 2034 2030 { 2035 - struct fw_ohci *ohci = 2036 - container_of(work, struct fw_ohci, bus_reset_work); 2031 + struct fw_ohci *ohci = from_work(ohci, work, bus_reset_work); 2037 2032 int self_id_count, generation, new_generation, i, j; 2038 2033 u32 reg, quadlet; 2039 2034 void *free_rom = NULL; ··· 2144 2141 // FIXME: Document how the locking works. 2145 2142 scoped_guard(spinlock_irq, &ohci->lock) { 2146 2143 ohci->generation = -1; // prevent AT packet queueing 2147 - context_stop(&ohci->at_request_ctx); 2148 - context_stop(&ohci->at_response_ctx); 2144 + context_stop(&ohci->at_request_ctx.context); 2145 + context_stop(&ohci->at_response_ctx.context); 2149 2146 } 2150 2147 2151 2148 /* ··· 2242 2239 } 2243 2240 2244 2241 if (event & OHCI1394_RQPkt) 2245 - tasklet_schedule(&ohci->ar_request_ctx.tasklet); 2242 + queue_work(ohci->card.async_wq, &ohci->ar_request_ctx.work); 2246 2243 2247 2244 if (event & OHCI1394_RSPkt) 2248 - tasklet_schedule(&ohci->ar_response_ctx.tasklet); 2245 + queue_work(ohci->card.async_wq, &ohci->ar_response_ctx.work); 2249 2246 2250 2247 if (event & OHCI1394_reqTxComplete) 2251 - tasklet_schedule(&ohci->at_request_ctx.tasklet); 2248 + queue_work(ohci->card.async_wq, &ohci->at_request_ctx.work); 2252 2249 2253 2250 if (event & OHCI1394_respTxComplete) 2254 - tasklet_schedule(&ohci->at_response_ctx.tasklet); 2251 + queue_work(ohci->card.async_wq, &ohci->at_response_ctx.work); 2255 2252 2256 2253 if (event & OHCI1394_isochRx) { 2257 2254 iso_event = reg_read(ohci, OHCI1394_IsoRecvIntEventClear); ··· 2531 2528 * They shouldn't do that in this initial case where the link 2532 2529 * isn't enabled. This means we have to use the same 2533 2530 * workaround here, setting the bus header to 0 and then write 2534 - * the right values in the bus reset tasklet. 2531 + * the right values in the bus reset work item. 2535 2532 */ 2536 2533 2537 2534 if (config_rom) { ··· 2620 2617 * during the atomic update, even on little endian 2621 2618 * architectures. The workaround we use is to put a 0 in the 2622 2619 * header quadlet; 0 is endian agnostic and means that the 2623 - * config rom isn't ready yet. In the bus reset tasklet we 2620 + * config rom isn't ready yet. In the bus reset work item we 2624 2621 * then set up the real values for the two registers. 2625 2622 * 2626 2623 * We use ohci->lock to avoid racing with the code that sets ··· 2662 2659 /* 2663 2660 * Now initiate a bus reset to have the changes take 2664 2661 * effect. We clean up the old config rom memory and DMA 2665 - * mappings in the bus reset tasklet, since the OHCI 2662 + * mappings in the bus reset work item, since the OHCI 2666 2663 * controller could need to access it before the bus reset 2667 2664 * takes effect. 2668 2665 */ ··· 2689 2686 static int ohci_cancel_packet(struct fw_card *card, struct fw_packet *packet) 2690 2687 { 2691 2688 struct fw_ohci *ohci = fw_ohci(card); 2692 - struct context *ctx = &ohci->at_request_ctx; 2689 + struct at_context *ctx = &ohci->at_request_ctx; 2693 2690 struct driver_data *driver_data = packet->driver_data; 2694 2691 int ret = -ENOENT; 2695 2692 2696 - tasklet_disable_in_atomic(&ctx->tasklet); 2693 + // Avoid dead lock due to programming mistake. 2694 + if (WARN_ON_ONCE(current_work() == &ctx->work)) 2695 + return 0; 2696 + disable_work_sync(&ctx->work); 2697 2697 2698 2698 if (packet->ack != 0) 2699 2699 goto out; ··· 2715 2709 packet->callback(packet, &ohci->card, packet->ack); 2716 2710 ret = 0; 2717 2711 out: 2718 - tasklet_enable(&ctx->tasklet); 2712 + enable_work(&ctx->work); 2719 2713 2720 2714 return ret; 2721 2715 } ··· 3773 3767 if (err < 0) 3774 3768 return err; 3775 3769 3776 - err = context_init(&ohci->at_request_ctx, ohci, 3770 + err = context_init(&ohci->at_request_ctx.context, ohci, 3777 3771 OHCI1394_AsReqTrContextControlSet, handle_at_packet); 3778 3772 if (err < 0) 3779 3773 return err; 3774 + INIT_WORK(&ohci->at_request_ctx.work, ohci_at_context_work); 3780 3775 3781 - err = context_init(&ohci->at_response_ctx, ohci, 3776 + err = context_init(&ohci->at_response_ctx.context, ohci, 3782 3777 OHCI1394_AsRspTrContextControlSet, handle_at_packet); 3783 3778 if (err < 0) 3784 3779 return err; 3780 + INIT_WORK(&ohci->at_response_ctx.work, ohci_at_context_work); 3785 3781 3786 3782 reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, ~0); 3787 3783 ohci->ir_context_channels = ~0ULL;
+10 -2
include/linux/firewire.h
··· 136 136 __be32 maint_utility_register; 137 137 138 138 struct workqueue_struct *isoc_wq; 139 + struct workqueue_struct *async_wq; 139 140 }; 140 141 141 142 static inline struct fw_card *fw_card_get(struct fw_card *card) ··· 308 307 * For successful transmission, the status code is the ack received 309 308 * from the destination. Otherwise it is one of the juju-specific 310 309 * rcodes: RCODE_SEND_ERROR, _CANCELLED, _BUSY, _GENERATION, _NO_ACK. 311 - * The callback can be called from tasklet context and thus 312 - * must never block. 310 + * The callback can be called from workqueue and thus must never block. 313 311 */ 314 312 fw_packet_callback_t callback; 315 313 int ack; ··· 381 381 * 382 382 * A variation of __fw_send_request() to generate callback for response subaction without time 383 383 * stamp. 384 + * 385 + * The callback is invoked in the workqueue context in most cases. However, if an error is detected 386 + * before queueing or the destination address refers to the local node, it is invoked in the 387 + * current context instead. 384 388 */ 385 389 static inline void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode, 386 390 int destination_id, int generation, int speed, ··· 414 410 * @callback_data: data to be passed to the transaction completion callback 415 411 * 416 412 * A variation of __fw_send_request() to generate callback for response subaction with time stamp. 413 + * 414 + * The callback is invoked in the workqueue context in most cases. However, if an error is detected 415 + * before queueing or the destination address refers to the local node, it is invoked in the current 416 + * context instead. 417 417 */ 418 418 static inline void fw_send_request_with_tstamp(struct fw_card *card, struct fw_transaction *t, 419 419 int tcode, int destination_id, int generation, int speed, unsigned long long offset,