diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2021-04-26 20:03:17 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2021-04-26 20:03:17 +0200 |
commit | 8e3a3249502d8ff92d73d827fb41dd44c5a16f76 (patch) | |
tree | 033e620f253013f37426c51fdb1699e65dc9770d /drivers/soundwire/bus.c | |
parent | Merge tag 'platform-drivers-x86-v5.13-1' of git://git.kernel.org/pub/scm/linu... (diff) | |
parent | bluetooth: eliminate the potential race condition when removing the HCI contr... (diff) | |
download | linux-8e3a3249502d8ff92d73d827fb41dd44c5a16f76.tar.xz linux-8e3a3249502d8ff92d73d827fb41dd44c5a16f76.zip |
Merge tag 'char-misc-5.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char/misc driver updates from Greg KH:
"Here is the big set of various smaller driver subsystem updates for
5.13-rc1.
Major bits in here are:
- habanalabs driver updates
- hwtracing driver updates
- interconnect driver updates
- mhi driver updates
- extcon driver updates
- fpga driver updates
- new binder features added
- nvmem driver updates
- phy driver updates
- soundwire driver updates
- smaller misc and char driver fixes and updates.
- bluetooth driver bugfix that maintainer wanted to go through this
tree.
All of these have been in linux-next with no reported issues"
* tag 'char-misc-5.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (330 commits)
bluetooth: eliminate the potential race condition when removing the HCI controller
coresight: etm-perf: Fix define build issue when built as module
phy: Revert "phy: ti: j721e-wiz: add missing of_node_put"
phy: ti: j721e-wiz: Add missing include linux/slab.h
phy: phy-twl4030-usb: Fix possible use-after-free in twl4030_usb_remove()
stm class: Use correct UUID APIs
intel_th: pci: Add Alder Lake-M support
intel_th: pci: Add Rocket Lake CPU support
intel_th: Consistency and off-by-one fix
intel_th: Constify attribute_group structs
intel_th: Constify all drvdata references
stm class: Remove an unused function
habanalabs/gaudi: Fix uninitialized return code rc when read size is zero
greybus: es2: fix kernel-doc warnings
mei: me: add Alder Lake P device id.
dw-xdata-pcie: Update outdated info and improve text format
dw-xdata-pcie: Fix documentation build warns
fbdev: zero-fill colormap in fbcmap.c
firmware: qcom-scm: Fix QCOM_SCM configuration
speakup: i18n: Switch to kmemdup_nul() in spk_msg_set()
...
Diffstat (limited to 'drivers/soundwire/bus.c')
-rw-r--r-- | drivers/soundwire/bus.c | 100 |
1 files changed, 75 insertions, 25 deletions
diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index 46885429928a..a9e0aa72654d 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -44,13 +44,13 @@ int sdw_bus_master_add(struct sdw_bus *bus, struct device *parent, } ret = sdw_get_id(bus); - if (ret) { + if (ret < 0) { dev_err(parent, "Failed to get bus id\n"); return ret; } ret = sdw_master_device_add(bus, parent, fwnode); - if (ret) { + if (ret < 0) { dev_err(parent, "Failed to add master device at link %d\n", bus->link_id); return ret; @@ -121,7 +121,7 @@ int sdw_bus_master_add(struct sdw_bus *bus, struct device *parent, else ret = -ENOTSUPP; /* No ACPI/DT so error out */ - if (ret) { + if (ret < 0) { dev_err(bus->dev, "Finding slaves failed:%d\n", ret); return ret; } @@ -422,7 +422,7 @@ sdw_bread_no_pm(struct sdw_bus *bus, u16 dev_num, u32 addr) ret = sdw_fill_msg(&msg, NULL, addr, 1, dev_num, SDW_MSG_FLAG_READ, &buf); - if (ret) + if (ret < 0) return ret; ret = sdw_transfer(bus, &msg); @@ -440,7 +440,7 @@ sdw_bwrite_no_pm(struct sdw_bus *bus, u16 dev_num, u32 addr, u8 value) ret = sdw_fill_msg(&msg, NULL, addr, 1, dev_num, SDW_MSG_FLAG_WRITE, &value); - if (ret) + if (ret < 0) return ret; return sdw_transfer(bus, &msg); @@ -454,7 +454,7 @@ int sdw_bread_no_pm_unlocked(struct sdw_bus *bus, u16 dev_num, u32 addr) ret = sdw_fill_msg(&msg, NULL, addr, 1, dev_num, SDW_MSG_FLAG_READ, &buf); - if (ret) + if (ret < 0) return ret; ret = sdw_transfer_unlocked(bus, &msg); @@ -472,7 +472,7 @@ int sdw_bwrite_no_pm_unlocked(struct sdw_bus *bus, u16 dev_num, u32 addr, u8 val ret = sdw_fill_msg(&msg, NULL, addr, 1, dev_num, SDW_MSG_FLAG_WRITE, &value); - if (ret) + if (ret < 0) return ret; return sdw_transfer_unlocked(bus, &msg); @@ -593,7 +593,7 @@ EXPORT_SYMBOL(sdw_write); /* called with bus_lock held */ static struct sdw_slave *sdw_get_slave(struct sdw_bus *bus, int i) { - struct sdw_slave *slave = NULL; + struct sdw_slave *slave; list_for_each_entry(slave, &bus->slaves, node) { if (slave->dev_num == i) @@ -603,7 +603,7 @@ static struct sdw_slave *sdw_get_slave(struct sdw_bus *bus, int i) return NULL; } -static int sdw_compare_devid(struct sdw_slave *slave, struct sdw_slave_id id) +int sdw_compare_devid(struct sdw_slave *slave, struct sdw_slave_id id) { if (slave->id.mfg_id != id.mfg_id || slave->id.part_id != id.part_id || @@ -614,6 +614,7 @@ static int sdw_compare_devid(struct sdw_slave *slave, struct sdw_slave_id id) return 0; } +EXPORT_SYMBOL(sdw_compare_devid); /* called with bus_lock held */ static int sdw_get_device_num(struct sdw_slave *slave) @@ -698,6 +699,7 @@ void sdw_extract_slave_id(struct sdw_bus *bus, "SDW Slave class_id 0x%02x, mfg_id 0x%04x, part_id 0x%04x, unique_id 0x%x, version 0x%x\n", id->class_id, id->mfg_id, id->part_id, id->unique_id, id->sdw_version); } +EXPORT_SYMBOL(sdw_extract_slave_id); static int sdw_program_device_num(struct sdw_bus *bus) { @@ -705,7 +707,7 @@ static int sdw_program_device_num(struct sdw_bus *bus) struct sdw_slave *slave, *_s; struct sdw_slave_id id; struct sdw_msg msg; - bool found = false; + bool found; int count = 0, ret; u64 addr; @@ -737,6 +739,7 @@ static int sdw_program_device_num(struct sdw_bus *bus) sdw_extract_slave_id(bus, addr, &id); + found = false; /* Now compare with entries */ list_for_each_entry_safe(slave, _s, &bus->slaves, node) { if (sdw_compare_devid(slave, id) == 0) { @@ -749,7 +752,7 @@ static int sdw_program_device_num(struct sdw_bus *bus) * dev_num */ ret = sdw_assign_device_num(slave); - if (ret) { + if (ret < 0) { dev_err(bus->dev, "Assign dev_num failed:%d\n", ret); @@ -875,14 +878,18 @@ static int sdw_slave_clk_stop_prepare(struct sdw_slave *slave, if (wake_en) val |= SDW_SCP_SYSTEMCTRL_WAKE_UP_EN; } else { - val = sdw_read_no_pm(slave, SDW_SCP_SYSTEMCTRL); - + ret = sdw_read_no_pm(slave, SDW_SCP_SYSTEMCTRL); + if (ret < 0) { + dev_err(&slave->dev, "SDW_SCP_SYSTEMCTRL read failed:%d\n", ret); + return ret; + } + val = ret; val &= ~(SDW_SCP_SYSTEMCTRL_CLK_STP_PREP); } ret = sdw_write_no_pm(slave, SDW_SCP_SYSTEMCTRL, val); - if (ret != 0) + if (ret < 0) dev_err(&slave->dev, "Clock Stop prepare failed for slave: %d", ret); @@ -895,11 +902,15 @@ static int sdw_bus_wait_for_clk_prep_deprep(struct sdw_bus *bus, u16 dev_num) int val; do { - val = sdw_bread_no_pm(bus, dev_num, SDW_SCP_STAT) & - SDW_SCP_STAT_CLK_STP_NF; + val = sdw_bread_no_pm(bus, dev_num, SDW_SCP_STAT); + if (val < 0) { + dev_err(bus->dev, "SDW_SCP_STAT bread failed:%d\n", val); + return val; + } + val &= SDW_SCP_STAT_CLK_STP_NF; if (!val) { - dev_info(bus->dev, "clock stop prep/de-prep done slave:%d", - dev_num); + dev_dbg(bus->dev, "clock stop prep/de-prep done slave:%d", + dev_num); return 0; } @@ -1253,6 +1264,7 @@ static int sdw_slave_set_frequency(struct sdw_slave *slave) static int sdw_initialize_slave(struct sdw_slave *slave) { struct sdw_slave_prop *prop = &slave->prop; + int status; int ret; u8 val; @@ -1260,6 +1272,44 @@ static int sdw_initialize_slave(struct sdw_slave *slave) if (ret < 0) return ret; + if (slave->bus->prop.quirks & SDW_MASTER_QUIRKS_CLEAR_INITIAL_CLASH) { + /* Clear bus clash interrupt before enabling interrupt mask */ + status = sdw_read_no_pm(slave, SDW_SCP_INT1); + if (status < 0) { + dev_err(&slave->dev, + "SDW_SCP_INT1 (BUS_CLASH) read failed:%d\n", status); + return status; + } + if (status & SDW_SCP_INT1_BUS_CLASH) { + dev_warn(&slave->dev, "Bus clash detected before INT mask is enabled\n"); + ret = sdw_write_no_pm(slave, SDW_SCP_INT1, SDW_SCP_INT1_BUS_CLASH); + if (ret < 0) { + dev_err(&slave->dev, + "SDW_SCP_INT1 (BUS_CLASH) write failed:%d\n", ret); + return ret; + } + } + } + if ((slave->bus->prop.quirks & SDW_MASTER_QUIRKS_CLEAR_INITIAL_PARITY) && + !(slave->prop.quirks & SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY)) { + /* Clear parity interrupt before enabling interrupt mask */ + status = sdw_read_no_pm(slave, SDW_SCP_INT1); + if (status < 0) { + dev_err(&slave->dev, + "SDW_SCP_INT1 (PARITY) read failed:%d\n", status); + return status; + } + if (status & SDW_SCP_INT1_PARITY) { + dev_warn(&slave->dev, "PARITY error detected before INT mask is enabled\n"); + ret = sdw_write_no_pm(slave, SDW_SCP_INT1, SDW_SCP_INT1_PARITY); + if (ret < 0) { + dev_err(&slave->dev, + "SDW_SCP_INT1 (PARITY) write failed:%d\n", ret); + return ret; + } + } + } + /* * Set SCP_INT1_MASK register, typically bus clash and * implementation-defined interrupt mask. The Parity detection @@ -1589,7 +1639,7 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave) ret = sdw_read_no_pm(slave, SDW_SCP_INT1); if (ret < 0) { dev_err(&slave->dev, - "SDW_SCP_INT1 read failed:%d\n", ret); + "SDW_SCP_INT1 recheck read failed:%d\n", ret); goto io_err; } _buf = ret; @@ -1597,7 +1647,7 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave) ret = sdw_nread_no_pm(slave, SDW_SCP_INTSTAT2, 2, _buf2); if (ret < 0) { dev_err(&slave->dev, - "SDW_SCP_INT2/3 read failed:%d\n", ret); + "SDW_SCP_INT2/3 recheck read failed:%d\n", ret); goto io_err; } @@ -1605,7 +1655,7 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave) ret = sdw_read_no_pm(slave, SDW_DP0_INT); if (ret < 0) { dev_err(&slave->dev, - "SDW_DP0_INT read failed:%d\n", ret); + "SDW_DP0_INT recheck read failed:%d\n", ret); goto io_err; } sdca_cascade = ret & SDW_DP0_SDCA_CASCADE; @@ -1701,7 +1751,7 @@ int sdw_handle_slave_status(struct sdw_bus *bus, if (status[0] == SDW_SLAVE_ATTACHED) { dev_dbg(bus->dev, "Slave attached, programming device number\n"); ret = sdw_program_device_num(bus); - if (ret) + if (ret < 0) dev_err(bus->dev, "Slave attach failed: %d\n", ret); /* * programming a device number will have side effects, @@ -1735,7 +1785,7 @@ int sdw_handle_slave_status(struct sdw_bus *bus, case SDW_SLAVE_ALERT: ret = sdw_handle_slave_alerts(slave); - if (ret) + if (ret < 0) dev_err(&slave->dev, "Slave %d alert handling failed: %d\n", i, ret); @@ -1754,7 +1804,7 @@ int sdw_handle_slave_status(struct sdw_bus *bus, attached_initializing = true; ret = sdw_initialize_slave(slave); - if (ret) + if (ret < 0) dev_err(&slave->dev, "Slave %d initialization failed: %d\n", i, ret); @@ -1768,7 +1818,7 @@ int sdw_handle_slave_status(struct sdw_bus *bus, } ret = sdw_update_slave_status(slave, status[i]); - if (ret) + if (ret < 0) dev_err(&slave->dev, "Update Slave status failed:%d\n", ret); if (attached_initializing) { |