> > +static void amd_sdwc_process_ping_status(u64 response, struct amd_sdwc_ctrl *ctrl) > +{ > + u64 slave_stat = 0; > + u32 val = 0; > + u16 dev_index; > + > + /* slave status from ping response*/ response */ > + slave_stat = FIELD_GET(AMD_SDW_MCP_SLAVE_STAT_0_3, response); > + slave_stat |= FIELD_GET(AMD_SDW_MCP_SLAVE_STAT_4_11, response) << 8; > + > + dev_dbg(ctrl->dev, "%s: slave_stat:0x%llx\n", __func__, slave_stat); > + for (dev_index = 0; dev_index <= SDW_MAX_DEVICES; ++dev_index) { > + val = (slave_stat >> (dev_index * 2)) & AMD_SDW_MCP_SLAVE_STATUS_MASK; > + dev_dbg(ctrl->dev, "%s val:0x%x\n", __func__, val); > + switch (val) { > + case SDW_SLAVE_ATTACHED: > + ctrl->status[dev_index] = SDW_SLAVE_ATTACHED; > + break; > + case SDW_SLAVE_UNATTACHED: > + ctrl->status[dev_index] = SDW_SLAVE_UNATTACHED; > + break; > + case SDW_SLAVE_ALERT: > + ctrl->status[dev_index] = SDW_SLAVE_ALERT; > + break; > + default: > + ctrl->status[dev_index] = SDW_SLAVE_RESERVED; > + break; > + } > + } > +} > + > +static void amd_sdwc_read_and_process_ping_status(struct amd_sdwc_ctrl *ctrl) > +{ > + u64 response = 0; > + > + mutex_lock(&ctrl->bus.msg_lock); > + response = amd_sdwc_send_cmd_get_resp(ctrl, 0, 0); > + mutex_unlock(&ctrl->bus.msg_lock); > + amd_sdwc_process_ping_status(response, ctrl); Is this saying that you actually need to send a PING frame manually every time the manager needs to check the device status, including interrupts? > +} > + > static u32 amd_sdwc_read_ping_status(struct sdw_bus *bus) > { > struct amd_sdwc_ctrl *ctrl = to_amd_sdw(bus); > @@ -1132,6 +1173,119 @@ static int amd_sdwc_register_dais(struct amd_sdwc_ctrl *ctrl) > dais, num_dais); > } > > +static void amd_sdwc_update_slave_status_work(struct work_struct *work) > +{ > + struct amd_sdwc_ctrl *ctrl = > + container_of(work, struct amd_sdwc_ctrl, amd_sdw_work); > + u32 sw_status_change_mask_0to7_reg; > + u32 sw_status_change_mask_8to11_reg; > + > + switch (ctrl->instance) { > + case ACP_SDW0: > + sw_status_change_mask_0to7_reg = SW_STATE_CHANGE_STATUS_MASK_0TO7; > + sw_status_change_mask_8to11_reg = SW_STATE_CHANGE_STATUS_MASK_8TO11; > + break; > + case ACP_SDW1: > + sw_status_change_mask_0to7_reg = P1_SW_STATE_CHANGE_STATUS_MASK_0TO7; > + sw_status_change_mask_8to11_reg = P1_SW_STATE_CHANGE_STATUS_MASK_8TO11; > + break; > + default: > + dev_err(ctrl->dev, "Invalid Soundwire controller instance\n"); > + return; > + } > + > + if (ctrl->status[0] == SDW_SLAVE_ATTACHED) { > + acp_reg_writel(0, ctrl->mmio + sw_status_change_mask_0to7_reg); > + acp_reg_writel(0, ctrl->mmio + sw_status_change_mask_8to11_reg); > + } > + > +update_status: > + sdw_handle_slave_status(&ctrl->bus, ctrl->status); > + if (ctrl->status[0] == SDW_SLAVE_ATTACHED) { > + acp_reg_writel(AMD_SDW_IRQ_MASK_0TO7, ctrl->mmio + sw_status_change_mask_0to7_reg); > + acp_reg_writel(AMD_SDW_IRQ_MASK_8TO11, > + ctrl->mmio + sw_status_change_mask_8to11_reg); > + amd_sdwc_read_and_process_ping_status(ctrl); > + goto update_status; > + } well no, you have to use some sort of retry count. You cannot handle interrupts in a loop like this, a faulty or chatty device would keep signaling an issue and you would be stuck here for a while. In addition, it's not clear if this is really needed. We added this loop in cadence_master.c because of issues with multiple devices becoming attached at the same time and how the hardware works. As it turns out, this update_status loop seems to be a paranoid case, the actually cause for devices de-attaching was found by Cirrus Logic and fixed in "soundwire: cadence: fix updating slave status when a bus has multiple peripherals" You would need to explain how the status is detected and if any race conditions can occur.