Commit b850dc20 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'firewire-updates-6.10' of...

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

Pull firewire updates from Takashi Sakamoto:
 "During the development period of v6.8 kernel, it became evident that
  there was a lack of helper utilities to trace the initial state of
  bus, while investigating certain PHYs compliant with different
  versions of IEEE 1394 specification.

  This series of changes includes the addition of tracepoints events,
  provided by 'firewire' subsystem. These events enable tracing of how
  firewire core functions during bus reset and asynchronous
  communication over IEEE 1394 bus.

  When implementing the tracepoints events, it was found that the
  existing serialization and deserialization helpers for several types
  of asynchronous packets are scattered across both firewire-core and
  firewire-ohci kernel modules. A set of inline functions is newly added
  to address it, along with some KUnit tests, serving as the foundation
  for the tracepoints events. This renders the dispersed code obsolete.

  The remaining changes constitute the final steps in phasing out the
  usage of deprecated PCI MSI APIs, in continuation from the previous
  version"

* tag 'firewire-updates-6.10' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394: (29 commits)
  firewire: obsolete usage of *-objs in Makefile for KUnit test
  firewire: core: remove flag and width from u64 formats of tracepoints events
  firewire: core: fix type of timestamp for async_inbound_template tracepoints events
  firewire: core: add tracepoint event for handling bus reset
  Revert "firewire: core: option to log bus reset initiation"
  firewire: core: add tracepoints events for initiating bus reset
  firewire: ohci: obsolete OHCI_PARAM_DEBUG_BUSRESETS from debug module parameter
  firewire: ohci: add bus-reset event for initial set of handled irq
  firewire: core: add tracepoints event for asynchronous inbound phy packet
  firewire: core/cdev: add tracepoints events for asynchronous phy packet
  firewire: core: add tracepoints events for asynchronous outbound response
  firewire: core: add tracepoint event for asynchronous inbound request
  firewire: core: add tracepoints event for asynchronous inbound response
  firewire: core: add tracepoints events for asynchronous outbound request
  firewire: core: add support for Linux kernel tracepoints
  firewire: core: replace local macros with common inline functions for isochronous packet header
  firewire: core: add common macro to serialize/deserialize isochronous packet header
  firewire: core: obsolete tcode check macros with inline functions
  firewire: ohci: replace hard-coded values with common macros
  firewire: ohci: replace hard-coded values with inline functions for asynchronous packet header
  ...
parents 4f8b6f25 21151fd8
......@@ -3,3 +3,4 @@ CONFIG_PCI=y
CONFIG_FIREWIRE=y
CONFIG_FIREWIRE_KUNIT_UAPI_TEST=y
CONFIG_FIREWIRE_KUNIT_DEVICE_ATTRIBUTE_TEST=y
CONFIG_FIREWIRE_KUNIT_PACKET_SERDES_TEST=y
......@@ -50,6 +50,22 @@ config FIREWIRE_KUNIT_DEVICE_ATTRIBUTE_TEST
For more information on KUnit and unit tests in general, refer
to the KUnit documentation in Documentation/dev-tools/kunit/.
config FIREWIRE_KUNIT_PACKET_SERDES_TEST
tristate "KUnit tests for packet serialization/deserialization" if !KUNIT_ALL_TESTS
depends on FIREWIRE && KUNIT
default KUNIT_ALL_TESTS
help
This builds the KUnit tests for packet serialization and
deserialization.
KUnit tests run during boot and output the results to the debug
log in TAP format (https://testanything.org/). Only useful for
kernel devs running KUnit test harness and are not for inclusion
into a production build.
For more information on KUnit and unit tests in general, refer
to the KUnit documentation in Documentation/dev-tools/kunit/.
config FIREWIRE_OHCI
tristate "OHCI-1394 controllers"
depends on PCI && FIREWIRE && MMU
......
......@@ -3,7 +3,7 @@
# Makefile for the Linux IEEE 1394 implementation
#
firewire-core-y += core-card.o core-cdev.o core-device.o \
firewire-core-y += core-trace.o core-card.o core-cdev.o core-device.o \
core-iso.o core-topology.o core-transaction.o
firewire-ohci-y += ohci.o
firewire-sbp2-y += sbp2.o
......@@ -16,5 +16,5 @@ obj-$(CONFIG_FIREWIRE_NET) += firewire-net.o
obj-$(CONFIG_FIREWIRE_NOSY) += nosy.o
obj-$(CONFIG_PROVIDE_OHCI1394_DMA_INIT) += init_ohci1394_dma.o
firewire-uapi-test-objs += uapi-test.o
obj-$(CONFIG_FIREWIRE_KUNIT_UAPI_TEST) += firewire-uapi-test.o
obj-$(CONFIG_FIREWIRE_KUNIT_UAPI_TEST) += uapi-test.o
obj-$(CONFIG_FIREWIRE_KUNIT_PACKET_SERDES_TEST) += packet-serdes-test.o
......@@ -23,6 +23,7 @@
#include <asm/byteorder.h>
#include "core.h"
#include <trace/events/firewire.h>
#define define_fw_printk_level(func, kern_level) \
void func(const struct fw_card *card, const char *fmt, ...) \
......@@ -221,11 +222,15 @@ static int reset_bus(struct fw_card *card, bool short_reset)
int reg = short_reset ? 5 : 1;
int bit = short_reset ? PHY_BUS_SHORT_RESET : PHY_BUS_RESET;
trace_bus_reset_initiate(card->generation, short_reset);
return card->driver->update_phy_reg(card, reg, 0, bit);
}
void fw_schedule_bus_reset(struct fw_card *card, bool delayed, bool short_reset)
{
trace_bus_reset_schedule(card->generation, short_reset);
/* We don't try hard to sort out requests of long vs. short resets. */
card->br_short = short_reset;
......@@ -244,6 +249,8 @@ static void br_work(struct work_struct *work)
/* Delay for 2s after last reset per IEEE 1394 clause 8.2.1. */
if (card->reset_jiffies != 0 &&
time_before64(get_jiffies_64(), card->reset_jiffies + 2 * HZ)) {
trace_bus_reset_postpone(card->generation, card->br_short);
if (!queue_delayed_work(fw_workqueue, &card->br_work, 2 * HZ))
fw_card_put(card);
return;
......
......@@ -35,6 +35,7 @@
#include "core.h"
#include <trace/events/firewire.h>
/*
* ABI version history is documented in linux/firewire-cdev.h.
......@@ -1558,6 +1559,9 @@ static void outbound_phy_packet_callback(struct fw_packet *packet,
struct client *e_client = e->client;
u32 rcode;
trace_async_phy_outbound_complete((uintptr_t)packet, status, packet->generation,
packet->timestamp);
switch (status) {
// expected:
case ACK_COMPLETE:
......@@ -1655,6 +1659,9 @@ static int ioctl_send_phy_packet(struct client *client, union ioctl_arg *arg)
memcpy(pp->data, a->data, sizeof(a->data));
}
trace_async_phy_outbound_initiate((uintptr_t)&e->p, e->p.generation, e->p.header[1],
e->p.header[2]);
card->driver->send_request(card, &e->p);
return 0;
......
......@@ -20,6 +20,7 @@
#include <asm/byteorder.h>
#include "core.h"
#include <trace/events/firewire.h>
#define SELF_ID_PHY_ID(q) (((q) >> 24) & 0x3f)
#define SELF_ID_EXTENDED(q) (((q) >> 23) & 0x01)
......@@ -507,6 +508,8 @@ void fw_core_handle_bus_reset(struct fw_card *card, int node_id, int generation,
struct fw_node *local_node;
unsigned long flags;
trace_bus_reset_handle(generation, node_id, bm_abdicate, self_ids, self_id_count);
spin_lock_irqsave(&card->lock, flags);
/*
......
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright (c) 2024 Takashi Sakamoto
#define CREATE_TRACE_POINTS
#include <trace/events/firewire.h>
This diff is collapsed.
......@@ -225,13 +225,20 @@ static inline bool is_next_generation(int new_generation, int old_generation)
#define TCODE_LINK_INTERNAL 0xe
#define TCODE_IS_READ_REQUEST(tcode) (((tcode) & ~1) == 4)
#define TCODE_IS_BLOCK_PACKET(tcode) (((tcode) & 1) != 0)
#define TCODE_IS_LINK_INTERNAL(tcode) ((tcode) == TCODE_LINK_INTERNAL)
#define TCODE_IS_REQUEST(tcode) (((tcode) & 2) == 0)
#define TCODE_IS_RESPONSE(tcode) (((tcode) & 2) != 0)
#define TCODE_HAS_REQUEST_DATA(tcode) (((tcode) & 12) != 4)
#define TCODE_HAS_RESPONSE_DATA(tcode) (((tcode) & 12) != 0)
static inline bool tcode_is_read_request(unsigned int tcode)
{
return (tcode & ~1u) == 4u;
}
static inline bool tcode_is_block_packet(unsigned int tcode)
{
return (tcode & 1u) != 0u;
}
static inline bool tcode_is_link_internal(unsigned int tcode)
{
return (tcode == TCODE_LINK_INTERNAL);
}
#define LOCAL_BUS 0xffc0
......
This diff is collapsed.
// SPDX-License-Identifier: GPL-2.0-or-later
//
// packet-header-definitions.h - The definitions of header fields for IEEE 1394 packet.
//
// Copyright (c) 2024 Takashi Sakamoto
#ifndef _FIREWIRE_PACKET_HEADER_DEFINITIONS_H
#define _FIREWIRE_PACKET_HEADER_DEFINITIONS_H
#define ASYNC_HEADER_QUADLET_COUNT 4
#define ASYNC_HEADER_Q0_DESTINATION_SHIFT 16
#define ASYNC_HEADER_Q0_DESTINATION_MASK 0xffff0000
#define ASYNC_HEADER_Q0_TLABEL_SHIFT 10
#define ASYNC_HEADER_Q0_TLABEL_MASK 0x0000fc00
#define ASYNC_HEADER_Q0_RETRY_SHIFT 8
#define ASYNC_HEADER_Q0_RETRY_MASK 0x00000300
#define ASYNC_HEADER_Q0_TCODE_SHIFT 4
#define ASYNC_HEADER_Q0_TCODE_MASK 0x000000f0
#define ASYNC_HEADER_Q0_PRIORITY_SHIFT 0
#define ASYNC_HEADER_Q0_PRIORITY_MASK 0x0000000f
#define ASYNC_HEADER_Q1_SOURCE_SHIFT 16
#define ASYNC_HEADER_Q1_SOURCE_MASK 0xffff0000
#define ASYNC_HEADER_Q1_RCODE_SHIFT 12
#define ASYNC_HEADER_Q1_RCODE_MASK 0x0000f000
#define ASYNC_HEADER_Q1_RCODE_SHIFT 12
#define ASYNC_HEADER_Q1_RCODE_MASK 0x0000f000
#define ASYNC_HEADER_Q1_OFFSET_HIGH_SHIFT 0
#define ASYNC_HEADER_Q1_OFFSET_HIGH_MASK 0x0000ffff
#define ASYNC_HEADER_Q3_DATA_LENGTH_SHIFT 16
#define ASYNC_HEADER_Q3_DATA_LENGTH_MASK 0xffff0000
#define ASYNC_HEADER_Q3_EXTENDED_TCODE_SHIFT 0
#define ASYNC_HEADER_Q3_EXTENDED_TCODE_MASK 0x0000ffff
static inline unsigned int async_header_get_destination(const u32 header[ASYNC_HEADER_QUADLET_COUNT])
{
return (header[0] & ASYNC_HEADER_Q0_DESTINATION_MASK) >> ASYNC_HEADER_Q0_DESTINATION_SHIFT;
}
static inline unsigned int async_header_get_tlabel(const u32 header[ASYNC_HEADER_QUADLET_COUNT])
{
return (header[0] & ASYNC_HEADER_Q0_TLABEL_MASK) >> ASYNC_HEADER_Q0_TLABEL_SHIFT;
}
static inline unsigned int async_header_get_retry(const u32 header[ASYNC_HEADER_QUADLET_COUNT])
{
return (header[0] & ASYNC_HEADER_Q0_RETRY_MASK) >> ASYNC_HEADER_Q0_RETRY_SHIFT;
}
static inline unsigned int async_header_get_tcode(const u32 header[ASYNC_HEADER_QUADLET_COUNT])
{
return (header[0] & ASYNC_HEADER_Q0_TCODE_MASK) >> ASYNC_HEADER_Q0_TCODE_SHIFT;
}
static inline unsigned int async_header_get_priority(const u32 header[ASYNC_HEADER_QUADLET_COUNT])
{
return (header[0] & ASYNC_HEADER_Q0_PRIORITY_MASK) >> ASYNC_HEADER_Q0_PRIORITY_SHIFT;
}
static inline unsigned int async_header_get_source(const u32 header[ASYNC_HEADER_QUADLET_COUNT])
{
return (header[1] & ASYNC_HEADER_Q1_SOURCE_MASK) >> ASYNC_HEADER_Q1_SOURCE_SHIFT;
}
static inline unsigned int async_header_get_rcode(const u32 header[ASYNC_HEADER_QUADLET_COUNT])
{
return (header[1] & ASYNC_HEADER_Q1_RCODE_MASK) >> ASYNC_HEADER_Q1_RCODE_SHIFT;
}
static inline u64 async_header_get_offset(const u32 header[ASYNC_HEADER_QUADLET_COUNT])
{
u32 hi = (header[1] & ASYNC_HEADER_Q1_OFFSET_HIGH_MASK) >> ASYNC_HEADER_Q1_OFFSET_HIGH_SHIFT;
return (((u64)hi) << 32) | ((u64)header[2]);
}
static inline u32 async_header_get_quadlet_data(const u32 header[ASYNC_HEADER_QUADLET_COUNT])
{
return header[3];
}
static inline unsigned int async_header_get_data_length(const u32 header[ASYNC_HEADER_QUADLET_COUNT])
{
return (header[3] & ASYNC_HEADER_Q3_DATA_LENGTH_MASK) >> ASYNC_HEADER_Q3_DATA_LENGTH_SHIFT;
}
static inline unsigned int async_header_get_extended_tcode(const u32 header[ASYNC_HEADER_QUADLET_COUNT])
{
return (header[3] & ASYNC_HEADER_Q3_EXTENDED_TCODE_MASK) >> ASYNC_HEADER_Q3_EXTENDED_TCODE_SHIFT;
}
static inline void async_header_set_destination(u32 header[ASYNC_HEADER_QUADLET_COUNT],
unsigned int destination)
{
header[0] &= ~ASYNC_HEADER_Q0_DESTINATION_MASK;
header[0] |= (((u32)destination) << ASYNC_HEADER_Q0_DESTINATION_SHIFT) & ASYNC_HEADER_Q0_DESTINATION_MASK;
}
static inline void async_header_set_tlabel(u32 header[ASYNC_HEADER_QUADLET_COUNT],
unsigned int tlabel)
{
header[0] &= ~ASYNC_HEADER_Q0_TLABEL_MASK;
header[0] |= (((u32)tlabel) << ASYNC_HEADER_Q0_TLABEL_SHIFT) & ASYNC_HEADER_Q0_TLABEL_MASK;
}
static inline void async_header_set_retry(u32 header[ASYNC_HEADER_QUADLET_COUNT],
unsigned int retry)
{
header[0] &= ~ASYNC_HEADER_Q0_RETRY_MASK;
header[0] |= (((u32)retry) << ASYNC_HEADER_Q0_RETRY_SHIFT) & ASYNC_HEADER_Q0_RETRY_MASK;
}
static inline void async_header_set_tcode(u32 header[ASYNC_HEADER_QUADLET_COUNT],
unsigned int tcode)
{
header[0] &= ~ASYNC_HEADER_Q0_TCODE_MASK;
header[0] |= (((u32)tcode) << ASYNC_HEADER_Q0_TCODE_SHIFT) & ASYNC_HEADER_Q0_TCODE_MASK;
}
static inline void async_header_set_priority(u32 header[ASYNC_HEADER_QUADLET_COUNT],
unsigned int priority)
{
header[0] &= ~ASYNC_HEADER_Q0_PRIORITY_MASK;
header[0] |= (((u32)priority) << ASYNC_HEADER_Q0_PRIORITY_SHIFT) & ASYNC_HEADER_Q0_PRIORITY_MASK;
}
static inline void async_header_set_source(u32 header[ASYNC_HEADER_QUADLET_COUNT],
unsigned int source)
{
header[1] &= ~ASYNC_HEADER_Q1_SOURCE_MASK;
header[1] |= (((u32)source) << ASYNC_HEADER_Q1_SOURCE_SHIFT) & ASYNC_HEADER_Q1_SOURCE_MASK;
}
static inline void async_header_set_rcode(u32 header[ASYNC_HEADER_QUADLET_COUNT],
unsigned int rcode)
{
header[1] &= ~ASYNC_HEADER_Q1_RCODE_MASK;
header[1] |= (((u32)rcode) << ASYNC_HEADER_Q1_RCODE_SHIFT) & ASYNC_HEADER_Q1_RCODE_MASK;
}
static inline void async_header_set_offset(u32 header[ASYNC_HEADER_QUADLET_COUNT], u64 offset)
{
u32 hi = (u32)(offset >> 32);
header[1] &= ~ASYNC_HEADER_Q1_OFFSET_HIGH_MASK;
header[1] |= (hi << ASYNC_HEADER_Q1_OFFSET_HIGH_SHIFT) & ASYNC_HEADER_Q1_OFFSET_HIGH_MASK;
header[2] = (u32)(offset & 0x00000000ffffffff);
}
static inline void async_header_set_quadlet_data(u32 header[ASYNC_HEADER_QUADLET_COUNT], u32 quadlet_data)
{
header[3] = quadlet_data;
}
static inline void async_header_set_data_length(u32 header[ASYNC_HEADER_QUADLET_COUNT],
unsigned int data_length)
{
header[3] &= ~ASYNC_HEADER_Q3_DATA_LENGTH_MASK;
header[3] |= (((u32)data_length) << ASYNC_HEADER_Q3_DATA_LENGTH_SHIFT) & ASYNC_HEADER_Q3_DATA_LENGTH_MASK;
}
static inline void async_header_set_extended_tcode(u32 header[ASYNC_HEADER_QUADLET_COUNT],
unsigned int extended_tcode)
{
header[3] &= ~ASYNC_HEADER_Q3_EXTENDED_TCODE_MASK;
header[3] |= (((u32)extended_tcode) << ASYNC_HEADER_Q3_EXTENDED_TCODE_SHIFT) & ASYNC_HEADER_Q3_EXTENDED_TCODE_MASK;
}
#define ISOC_HEADER_DATA_LENGTH_SHIFT 16
#define ISOC_HEADER_DATA_LENGTH_MASK 0xffff0000
#define ISOC_HEADER_TAG_SHIFT 14
#define ISOC_HEADER_TAG_MASK 0x0000c000
#define ISOC_HEADER_CHANNEL_SHIFT 8
#define ISOC_HEADER_CHANNEL_MASK 0x00003f00
#define ISOC_HEADER_TCODE_SHIFT 4
#define ISOC_HEADER_TCODE_MASK 0x000000f0
#define ISOC_HEADER_SY_SHIFT 0
#define ISOC_HEADER_SY_MASK 0x0000000f
static inline unsigned int isoc_header_get_data_length(u32 header)
{
return (header & ISOC_HEADER_DATA_LENGTH_MASK) >> ISOC_HEADER_DATA_LENGTH_SHIFT;
}
static inline unsigned int isoc_header_get_tag(u32 header)
{
return (header & ISOC_HEADER_TAG_MASK) >> ISOC_HEADER_TAG_SHIFT;
}
static inline unsigned int isoc_header_get_channel(u32 header)
{
return (header & ISOC_HEADER_CHANNEL_MASK) >> ISOC_HEADER_CHANNEL_SHIFT;
}
static inline unsigned int isoc_header_get_tcode(u32 header)
{
return (header & ISOC_HEADER_TCODE_MASK) >> ISOC_HEADER_TCODE_SHIFT;
}
static inline unsigned int isoc_header_get_sy(u32 header)
{
return (header & ISOC_HEADER_SY_MASK) >> ISOC_HEADER_SY_SHIFT;
}
static inline void isoc_header_set_data_length(u32 *header, unsigned int data_length)
{
*header &= ~ISOC_HEADER_DATA_LENGTH_MASK;
*header |= (((u32)data_length) << ISOC_HEADER_DATA_LENGTH_SHIFT) & ISOC_HEADER_DATA_LENGTH_MASK;
}
static inline void isoc_header_set_tag(u32 *header, unsigned int tag)
{
*header &= ~ISOC_HEADER_TAG_MASK;
*header |= (((u32)tag) << ISOC_HEADER_TAG_SHIFT) & ISOC_HEADER_TAG_MASK;
}
static inline void isoc_header_set_channel(u32 *header, unsigned int channel)
{
*header &= ~ISOC_HEADER_CHANNEL_MASK;
*header |= (((u32)channel) << ISOC_HEADER_CHANNEL_SHIFT) & ISOC_HEADER_CHANNEL_MASK;
}
static inline void isoc_header_set_tcode(u32 *header, unsigned int tcode)
{
*header &= ~ISOC_HEADER_TCODE_MASK;
*header |= (((u32)tcode) << ISOC_HEADER_TCODE_SHIFT) & ISOC_HEADER_TCODE_MASK;
}
static inline void isoc_header_set_sy(u32 *header, unsigned int sy)
{
*header &= ~ISOC_HEADER_SY_MASK;
*header |= (((u32)sy) << ISOC_HEADER_SY_SHIFT) & ISOC_HEADER_SY_MASK;
}
#endif // _FIREWIRE_PACKET_HEADER_DEFINITIONS_H
This diff is collapsed.
......@@ -463,7 +463,8 @@ struct fw_iso_packet {
u32 tag:2; /* tx: Tag in packet header */
u32 sy:4; /* tx: Sy in packet header */
u32 header_length:8; /* Length of immediate header */
u32 header[]; /* tx: Top of 1394 isoch. data_block */
/* tx: Top of 1394 isoch. data_block */
u32 header[] __counted_by(header_length);
};
#define FW_ISO_CONTEXT_TRANSMIT 0
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment