Skip to content

Commit f07c369

Browse files
committed
Merge tag 'firewire-updates-6.18' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394
Pull firewire updates from Takashi Sakamoto: "This update includes the following changes: - Removal of the deprecated debug parameter from firewire-ohci module - Replacement of the module-local workqueue in 1394 OHCI PCI driver with a companion IRQ thread - Refactoring of bus management code - Additional minor code cleanup The existing tracepoints serve as an alternative to the removed debug parameter. The use of IRQ thread is experimental, as it handles 1394 OHCI SelfIDComplete event only. It may be replaced in the future releases with another approach; e.g. by providing workqueue from core functionality" * tag 'firewire-updates-6.18' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394: (43 commits) firewire: core: fix undefined reference error in ARM EABI Revert "firewire: core: disable bus management work temporarily during updating topology" Revert "firewire: core: shrink critical section of fw_card spinlock in bm_work" firewire: core: suppress overflow warning when computing jiffies from isochronous cycle firewire: core: minor code refactoring to delete useless local variable firewire: core; eliminate pick_me goto label firewire: core: code refactoring to split contention procedure for bus manager firewire: core: code refactoring for the case of generation mismatch firewire: core: use switch statement to evaluate transaction result to CSR_BUS_MANAGER_ID firewire: core: remove useless generation check firewire: core: use struct_size and flex_array_size in ioctl_add_descriptor firewire: core: shrink critical section of fw_card spinlock in bm_work firewire: core: disable bus management work temporarily during updating topology firewire: core: schedule bm_work item outside of spin lock firewire: core: annotate fw_destroy_nodes with must-hold-lock firewire: core: use spin lock specific to timer for split transaction firewire: core: use spin lock specific to transaction firewire: core: use spin lock specific to topology map firewire: core: maintain phy packet receivers locally in cdev layer firewire: core: use scoped_guard() to manage critical section to update topology ...
2 parents d347921 + 40d4c76 commit f07c369

8 files changed

Lines changed: 518 additions & 627 deletions

File tree

drivers/firewire/core-card.c

Lines changed: 261 additions & 229 deletions
Large diffs are not rendered by default.

drivers/firewire/core-cdev.c

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@
4747
#define FW_CDEV_VERSION_AUTO_FLUSH_ISO_OVERFLOW 5
4848
#define FW_CDEV_VERSION_EVENT_ASYNC_TSTAMP 6
4949

50+
static DEFINE_SPINLOCK(phy_receiver_list_lock);
51+
static LIST_HEAD(phy_receiver_list);
52+
5053
struct client {
5154
u32 version;
5255
struct fw_device *device;
@@ -937,11 +940,12 @@ static int ioctl_add_descriptor(struct client *client, union ioctl_arg *arg)
937940
if (a->length > 256)
938941
return -EINVAL;
939942

940-
r = kmalloc(sizeof(*r) + a->length * 4, GFP_KERNEL);
943+
r = kmalloc(struct_size(r, data, a->length), GFP_KERNEL);
941944
if (r == NULL)
942945
return -ENOMEM;
943946

944-
if (copy_from_user(r->data, u64_to_uptr(a->data), a->length * 4)) {
947+
if (copy_from_user(r->data, u64_to_uptr(a->data),
948+
flex_array_size(r, data, a->length))) {
945949
ret = -EFAULT;
946950
goto failed;
947951
}
@@ -1324,8 +1328,8 @@ static void iso_resource_work(struct work_struct *work)
13241328
todo = r->todo;
13251329
// Allow 1000ms grace period for other reallocations.
13261330
if (todo == ISO_RES_ALLOC &&
1327-
time_before64(get_jiffies_64(), client->device->card->reset_jiffies + HZ)) {
1328-
schedule_iso_resource(r, DIV_ROUND_UP(HZ, 3));
1331+
time_is_after_jiffies64(client->device->card->reset_jiffies + secs_to_jiffies(1))) {
1332+
schedule_iso_resource(r, msecs_to_jiffies(333));
13291333
skip = true;
13301334
} else {
13311335
// We could be called twice within the same generation.
@@ -1669,15 +1673,16 @@ static int ioctl_send_phy_packet(struct client *client, union ioctl_arg *arg)
16691673
static int ioctl_receive_phy_packets(struct client *client, union ioctl_arg *arg)
16701674
{
16711675
struct fw_cdev_receive_phy_packets *a = &arg->receive_phy_packets;
1672-
struct fw_card *card = client->device->card;
16731676

16741677
/* Access policy: Allow this ioctl only on local nodes' device files. */
16751678
if (!client->device->is_local)
16761679
return -ENOSYS;
16771680

1678-
guard(spinlock_irq)(&card->lock);
1681+
// NOTE: This can be without irq when we can guarantee that __fw_send_request() for local
1682+
// destination never runs in any type of IRQ context.
1683+
scoped_guard(spinlock_irq, &phy_receiver_list_lock)
1684+
list_move_tail(&client->phy_receiver_link, &phy_receiver_list);
16791685

1680-
list_move_tail(&client->phy_receiver_link, &card->phy_receiver_list);
16811686
client->phy_receiver_closure = a->closure;
16821687

16831688
return 0;
@@ -1687,10 +1692,17 @@ void fw_cdev_handle_phy_packet(struct fw_card *card, struct fw_packet *p)
16871692
{
16881693
struct client *client;
16891694

1690-
guard(spinlock_irqsave)(&card->lock);
1695+
// NOTE: This can be without irqsave when we can guarantee that __fw_send_request() for local
1696+
// destination never runs in any type of IRQ context.
1697+
guard(spinlock_irqsave)(&phy_receiver_list_lock);
1698+
1699+
list_for_each_entry(client, &phy_receiver_list, phy_receiver_link) {
1700+
struct inbound_phy_packet_event *e;
1701+
1702+
if (client->device->card != card)
1703+
continue;
16911704

1692-
list_for_each_entry(client, &card->phy_receiver_list, phy_receiver_link) {
1693-
struct inbound_phy_packet_event *e = kmalloc(sizeof(*e) + 8, GFP_ATOMIC);
1705+
e = kmalloc(sizeof(*e) + 8, GFP_ATOMIC);
16941706
if (e == NULL)
16951707
break;
16961708

@@ -1857,7 +1869,9 @@ static int fw_device_op_release(struct inode *inode, struct file *file)
18571869
struct client_resource *resource;
18581870
unsigned long index;
18591871

1860-
scoped_guard(spinlock_irq, &client->device->card->lock)
1872+
// NOTE: This can be without irq when we can guarantee that __fw_send_request() for local
1873+
// destination never runs in any type of IRQ context.
1874+
scoped_guard(spinlock_irq, &phy_receiver_list_lock)
18611875
list_del(&client->phy_receiver_link);
18621876

18631877
scoped_guard(mutex, &client->device->client_list_mutex)

drivers/firewire/core-device.c

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -847,16 +847,15 @@ static void fw_schedule_device_work(struct fw_device *device,
847847
*/
848848

849849
#define MAX_RETRIES 10
850-
#define RETRY_DELAY (3 * HZ)
851-
#define INITIAL_DELAY (HZ / 2)
852-
#define SHUTDOWN_DELAY (2 * HZ)
850+
#define RETRY_DELAY secs_to_jiffies(3)
851+
#define INITIAL_DELAY msecs_to_jiffies(500)
852+
#define SHUTDOWN_DELAY secs_to_jiffies(2)
853853

854854
static void fw_device_shutdown(struct work_struct *work)
855855
{
856856
struct fw_device *device = from_work(device, work, work.work);
857857

858-
if (time_before64(get_jiffies_64(),
859-
device->card->reset_jiffies + SHUTDOWN_DELAY)
858+
if (time_is_after_jiffies64(device->card->reset_jiffies + SHUTDOWN_DELAY)
860859
&& !list_empty(&device->card->link)) {
861860
fw_schedule_device_work(device, SHUTDOWN_DELAY);
862861
return;
@@ -887,7 +886,7 @@ static void fw_device_release(struct device *dev)
887886
* bus manager work looks at this node.
888887
*/
889888
scoped_guard(spinlock_irqsave, &card->lock)
890-
device->node->data = NULL;
889+
fw_node_set_device(device->node, NULL);
891890

892891
fw_node_put(device->node);
893892
kfree(device->config_rom);
@@ -1007,7 +1006,7 @@ static void fw_device_init(struct work_struct *work)
10071006
int ret;
10081007

10091008
/*
1010-
* All failure paths here set node->data to NULL, so that we
1009+
* All failure paths here call fw_node_set_device(node, NULL), so that we
10111010
* don't try to do device_for_each_child() on a kfree()'d
10121011
* device.
10131012
*/
@@ -1051,9 +1050,9 @@ static void fw_device_init(struct work_struct *work)
10511050
struct fw_node *obsolete_node = reused->node;
10521051

10531052
device->node = obsolete_node;
1054-
device->node->data = device;
1053+
fw_node_set_device(device->node, device);
10551054
reused->node = current_node;
1056-
reused->node->data = reused;
1055+
fw_node_set_device(reused->node, reused);
10571056

10581057
reused->max_speed = device->max_speed;
10591058
reused->node_id = current_node->node_id;
@@ -1292,7 +1291,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
12921291
* FW_NODE_UPDATED callbacks can update the node_id
12931292
* and generation for the device.
12941293
*/
1295-
node->data = device;
1294+
fw_node_set_device(node, device);
12961295

12971296
/*
12981297
* Many devices are slow to respond after bus resets,
@@ -1307,7 +1306,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
13071306

13081307
case FW_NODE_INITIATED_RESET:
13091308
case FW_NODE_LINK_ON:
1310-
device = node->data;
1309+
device = fw_node_get_device(node);
13111310
if (device == NULL)
13121311
goto create;
13131312

@@ -1324,7 +1323,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
13241323
break;
13251324

13261325
case FW_NODE_UPDATED:
1327-
device = node->data;
1326+
device = fw_node_get_device(node);
13281327
if (device == NULL)
13291328
break;
13301329

@@ -1339,7 +1338,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
13391338

13401339
case FW_NODE_DESTROYED:
13411340
case FW_NODE_LINK_OFF:
1342-
if (!node->data)
1341+
if (!fw_node_get_device(node))
13431342
break;
13441343

13451344
/*
@@ -1354,7 +1353,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
13541353
* the device in shutdown state to have that code fail
13551354
* to create the device.
13561355
*/
1357-
device = node->data;
1356+
device = fw_node_get_device(node);
13581357
if (atomic_xchg(&device->state,
13591358
FW_DEVICE_GONE) == FW_DEVICE_RUNNING) {
13601359
device->workfn = fw_device_shutdown;

drivers/firewire/core-topology.c

Lines changed: 47 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ static struct fw_node *build_tree(struct fw_card *card, const u32 *sid, int self
241241
// If PHYs report different gap counts, set an invalid count which will force a gap
242242
// count reconfiguration and a reset.
243243
if (phy_packet_self_id_zero_get_gap_count(self_id_sequence[0]) != gap_count)
244-
gap_count = 0;
244+
gap_count = GAP_COUNT_MISMATCHED;
245245

246246
update_hop_count(node);
247247

@@ -325,9 +325,11 @@ static void report_found_node(struct fw_card *card,
325325
card->bm_retries = 0;
326326
}
327327

328-
/* Must be called with card->lock held */
329328
void fw_destroy_nodes(struct fw_card *card)
329+
__must_hold(&card->lock)
330330
{
331+
lockdep_assert_held(&card->lock);
332+
331333
card->color++;
332334
if (card->local_node != NULL)
333335
for_each_fw_node(card, card->local_node, report_lost_node);
@@ -435,20 +437,22 @@ static void update_tree(struct fw_card *card, struct fw_node *root)
435437
}
436438
}
437439

438-
static void update_topology_map(struct fw_card *card,
439-
u32 *self_ids, int self_id_count)
440+
static void update_topology_map(__be32 *buffer, size_t buffer_size, int root_node_id,
441+
const u32 *self_ids, int self_id_count)
440442
{
441-
int node_count = (card->root_node->node_id & 0x3f) + 1;
442-
__be32 *map = card->topology_map;
443+
__be32 *map = buffer;
444+
int node_count = (root_node_id & 0x3f) + 1;
445+
446+
memset(map, 0, buffer_size);
443447

444448
*map++ = cpu_to_be32((self_id_count + 2) << 16);
445-
*map++ = cpu_to_be32(be32_to_cpu(card->topology_map[1]) + 1);
449+
*map++ = cpu_to_be32(be32_to_cpu(buffer[1]) + 1);
446450
*map++ = cpu_to_be32((node_count << 16) | self_id_count);
447451

448452
while (self_id_count--)
449453
*map++ = cpu_to_be32p(self_ids++);
450454

451-
fw_compute_block_crc(card->topology_map);
455+
fw_compute_block_crc(buffer);
452456
}
453457

454458
void fw_core_handle_bus_reset(struct fw_card *card, int node_id, int generation,
@@ -458,46 +462,45 @@ void fw_core_handle_bus_reset(struct fw_card *card, int node_id, int generation,
458462

459463
trace_bus_reset_handle(card->index, generation, node_id, bm_abdicate, self_ids, self_id_count);
460464

461-
guard(spinlock_irqsave)(&card->lock);
462-
463-
/*
464-
* If the selfID buffer is not the immediate successor of the
465-
* previously processed one, we cannot reliably compare the
466-
* old and new topologies.
467-
*/
468-
if (!is_next_generation(generation, card->generation) &&
469-
card->local_node != NULL) {
470-
fw_destroy_nodes(card);
471-
card->bm_retries = 0;
465+
scoped_guard(spinlock, &card->lock) {
466+
// If the selfID buffer is not the immediate successor of the
467+
// previously processed one, we cannot reliably compare the
468+
// old and new topologies.
469+
if (!is_next_generation(generation, card->generation) && card->local_node != NULL) {
470+
fw_destroy_nodes(card);
471+
card->bm_retries = 0;
472+
}
473+
card->broadcast_channel_allocated = card->broadcast_channel_auto_allocated;
474+
card->node_id = node_id;
475+
// Update node_id before generation to prevent anybody from using
476+
// a stale node_id together with a current generation.
477+
smp_wmb();
478+
card->generation = generation;
479+
card->reset_jiffies = get_jiffies_64();
480+
card->bm_node_id = 0xffff;
481+
card->bm_abdicate = bm_abdicate;
482+
483+
local_node = build_tree(card, self_ids, self_id_count, generation);
484+
485+
card->color++;
486+
487+
if (local_node == NULL) {
488+
fw_err(card, "topology build failed\n");
489+
// FIXME: We need to issue a bus reset in this case.
490+
} else if (card->local_node == NULL) {
491+
card->local_node = local_node;
492+
for_each_fw_node(card, local_node, report_found_node);
493+
} else {
494+
update_tree(card, local_node);
495+
}
472496
}
473497

474-
card->broadcast_channel_allocated = card->broadcast_channel_auto_allocated;
475-
card->node_id = node_id;
476-
/*
477-
* Update node_id before generation to prevent anybody from using
478-
* a stale node_id together with a current generation.
479-
*/
480-
smp_wmb();
481-
card->generation = generation;
482-
card->reset_jiffies = get_jiffies_64();
483-
card->bm_node_id = 0xffff;
484-
card->bm_abdicate = bm_abdicate;
485498
fw_schedule_bm_work(card, 0);
486499

487-
local_node = build_tree(card, self_ids, self_id_count, generation);
488-
489-
update_topology_map(card, self_ids, self_id_count);
490-
491-
card->color++;
492-
493-
if (local_node == NULL) {
494-
fw_err(card, "topology build failed\n");
495-
/* FIXME: We need to issue a bus reset in this case. */
496-
} else if (card->local_node == NULL) {
497-
card->local_node = local_node;
498-
for_each_fw_node(card, local_node, report_found_node);
499-
} else {
500-
update_tree(card, local_node);
500+
// Just used by transaction layer.
501+
scoped_guard(spinlock, &card->topology_map.lock) {
502+
update_topology_map(card->topology_map.buffer, sizeof(card->topology_map.buffer),
503+
card->root_node->node_id, self_ids, self_id_count);
501504
}
502505
}
503506
EXPORT_SYMBOL(fw_core_handle_bus_reset);

0 commit comments

Comments
 (0)