Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions drivers/soundwire/cadence_master.c
Original file line number Diff line number Diff line change
Expand Up @@ -2139,6 +2139,7 @@ EXPORT_SYMBOL(sdw_cdns_bpt_find_bandwidth);
int sdw_cdns_bpt_find_buffer_sizes(int command, /* 0: write, 1: read */
int row, int col, unsigned int data_bytes,
unsigned int requested_bytes_per_frame,
unsigned int bra_block_alignment,
unsigned int *data_per_frame, unsigned int *pdi0_buffer_size,
unsigned int *pdi1_buffer_size, unsigned int *num_frames)
{
Expand All @@ -2163,6 +2164,16 @@ int sdw_cdns_bpt_find_buffer_sizes(int command, /* 0: write, 1: read */
if (requested_bytes_per_frame < actual_bpt_bytes)
actual_bpt_bytes = requested_bytes_per_frame;

if (bra_block_alignment) {
/* align to a multiple of bra_block_alignment */
if (actual_bpt_bytes < bra_block_alignment) {
pr_err("requested bytes per frame %u is smaller than block alignment %u\n",
actual_bpt_bytes, bra_block_alignment);
return -EINVAL;
}
actual_bpt_bytes -= (actual_bpt_bytes % bra_block_alignment);
Comment on lines +2168 to +2174
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aligning actual_bpt_bytes by subtracting actual_bpt_bytes % bra_block_alignment can reduce it to 0 when bra_block_alignment is larger than actual_bpt_bytes (or when requested_bytes_per_frame is smaller than the alignment). That will lead to division-by-zero in the subsequent DIV_ROUND_UP() / / operations. Please validate the alignment input and/or ensure actual_bpt_bytes remains >= 1 (typically return -EINVAL if the alignment cannot be satisfied).

Suggested change
/* align to a multiple of bra_block_alignment */
actual_bpt_bytes -= (actual_bpt_bytes % bra_block_alignment);
/* align to a multiple of bra_block_alignment */
if (actual_bpt_bytes < bra_block_alignment)
return -EINVAL;
actual_bpt_bytes -= (actual_bpt_bytes % bra_block_alignment);
if (!actual_bpt_bytes)
return -EINVAL;

Copilot uses AI. Check for mistakes.
}

*data_per_frame = actual_bpt_bytes;

if (data_bytes < actual_bpt_bytes)
Expand Down
1 change: 1 addition & 0 deletions drivers/soundwire/cadence_master.h
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ int sdw_cdns_bpt_find_bandwidth(int command, /* 0: write, 1: read */
int sdw_cdns_bpt_find_buffer_sizes(int command, /* 0: write, 1: read */
int row, int col, unsigned int data_bytes,
unsigned int requested_bytes_per_frame,
unsigned int bra_block_alignment,
unsigned int *data_per_frame, unsigned int *pdi0_buffer_size,
unsigned int *pdi1_buffer_size, unsigned int *num_frames);

Expand Down
13 changes: 11 additions & 2 deletions drivers/soundwire/intel_ace2x.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ static int intel_ace2x_bpt_open_stream(struct sdw_intel *sdw, struct sdw_slave *
struct sdw_port_config *pconfig;
unsigned int pdi0_buf_size_pre_frame;
unsigned int pdi1_buf_size_pre_frame;
unsigned int max_data_per_frame;
unsigned int pdi0_buffer_size_;
unsigned int pdi1_buffer_size_;
unsigned int pdi0_buffer_size;
Expand Down Expand Up @@ -168,11 +169,18 @@ static int intel_ace2x_bpt_open_stream(struct sdw_intel *sdw, struct sdw_slave *
pdi0_buffer_size = 0;
pdi1_buffer_size = 0;
num_frames = 0;

if (slave->prop.bra_max_data_per_frame)
max_data_per_frame = slave->prop.bra_max_data_per_frame;
else
max_data_per_frame = SDW_BRA_MAX_BYTES_PER_FRAME;

/* Add up pdi buffer size and frame numbers of each BPT sections */
for (i = 0; i < msg->sections; i++) {
ret = sdw_cdns_bpt_find_buffer_sizes(command, cdns->bus.params.row,
cdns->bus.params.col,
msg->sec[i].len, SDW_BPT_MSG_MAX_BYTES,
msg->sec[i].len, max_data_per_frame,
slave->prop.bra_block_alignment,
&data_per_frame, &pdi0_buffer_size_,
&pdi1_buffer_size_, &num_frames_);
if (ret < 0)
Expand All @@ -196,7 +204,8 @@ static int intel_ace2x_bpt_open_stream(struct sdw_intel *sdw, struct sdw_slave *
/* Get buffer size of a full frame */
ret = sdw_cdns_bpt_find_buffer_sizes(command, cdns->bus.params.row,
cdns->bus.params.col,
data_per_frame, SDW_BPT_MSG_MAX_BYTES,
data_per_frame, max_data_per_frame,
slave->prop.bra_block_alignment,
&data_per_frame, &pdi0_buf_size_pre_frame,
&pdi1_buf_size_pre_frame, &fake_num_frames);
if (ret < 0)
Expand Down
6 changes: 6 additions & 0 deletions drivers/soundwire/mipi_disco.c
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,12 @@ int sdw_slave_read_prop(struct sdw_slave *slave)
device_property_read_u32(dev, "mipi-sdw-sdca-interrupt-register-list",
&prop->sdca_interrupt_register_list);

device_property_read_u32(dev, "mipi-sdw-bra-mode-block-alignment",
&prop->bra_block_alignment);

device_property_read_u32(dev, "mipi-sdw-bra-mode-max-data-per-frame",
&prop->bra_max_data_per_frame);

prop->commit_register_supported = mipi_device_property_read_bool(dev,
"mipi-sdw-commit-register-supported");

Expand Down
12 changes: 12 additions & 0 deletions include/linux/soundwire/sdw.h
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,10 @@ struct sdw_dpn_prop {
* @commit_register_supported: is PCP_Commit register supported
* @scp_int1_mask: SCP_INT1_MASK desired settings
* @lane_maps: Lane mapping for the slave, only valid if lane_control_support is set
* @bra_block_alignment: If non-zero the length of data in a BRA frame must be
* a multiple of this number of bytes.
* @bra_max_data_per_frame: If non-zero the maximum data payload size (in bytes per
* frame excluding header, CRC, and footer) for this BRA Mode
* @clock_reg_supported: the Peripheral implements the clock base and scale
* registers introduced with the SoundWire 1.2 specification. SDCA devices
* do not need to set this boolean property as the registers are required.
Expand Down Expand Up @@ -394,6 +398,8 @@ struct sdw_slave_prop {
u8 commit_register_supported;
u8 scp_int1_mask;
u8 lane_maps[SDW_MAX_LANES];
u32 bra_block_alignment;
u32 bra_max_data_per_frame;
bool clock_reg_supported;
bool use_domain_irq;
};
Expand Down Expand Up @@ -838,6 +844,12 @@ struct sdw_defer {
*/
#define SDW_BPT_MSG_MAX_BYTES (1024 * 1024)

/*
* According to mipi SoundWire DisCo Specification_v2-1,
* this maximum value shall not exceed 470.
*/
#define SDW_BRA_MAX_BYTES_PER_FRAME 470

struct sdw_bpt_msg;

/**
Expand Down
Loading