Skip to content
Merged
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
14 changes: 10 additions & 4 deletions drivers/bluetooth/hci_qca.c
Original file line number Diff line number Diff line change
Expand Up @@ -2226,8 +2226,8 @@ static void qca_power_off(struct hci_uart *hu)
bool sw_ctrl_state;
struct qca_power *power;

/* From this point we go into power off state. But serial port is
* still open, stop queueing the IBS data and flush all the buffered
/* From this point we go into power off state. But serial port may
* still be open, stop queueing the IBS data and flush all the buffered
* data in skb's.
*/
spin_lock_irqsave(&qca->hci_ibs_lock, flags);
Expand All @@ -2249,8 +2249,14 @@ static void qca_power_off(struct hci_uart *hu)
case QCA_WCN3990:
case QCA_WCN3991:
case QCA_WCN3998:
host_set_baudrate(hu, 2400);
qca_send_power_pulse(hu, false);
/* Both of these write to the serial port which may have
* already been closed by hci_uart_close(), which closes
* the port if HCI_QUIRK_NON_PERSISTENT_SETUP is set.
*/
if (test_bit(HCI_UART_PROTO_READY, &hu->flags)) {
host_set_baudrate(hu, 2400);
qca_send_power_pulse(hu, false);
}
break;
default:
break;
Expand Down
70 changes: 66 additions & 4 deletions drivers/gpu/drm/bridge/analogix/anx7625.c
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,16 @@ static int anx7625_api_dsi_config(struct anx7625_data *ctx)
return ret;
}

for (int i = 0; i < 5; i++) {
/* Set MIPI RX termination to 75ohm */
ret = anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
MIPI_ANALOG_CTRL_0 + i, 0xf8);
if (ret < 0) {
DRM_DEV_ERROR(dev, "IO error : set lane %d termination fail.\n", i);
return ret;
}
}

/* DSI clock settings */
val = (0 << MIPI_HS_PWD_CLK) |
(0 << MIPI_HS_RT_CLK) |
Expand Down Expand Up @@ -1326,6 +1336,39 @@ static int anx7625_read_hpd_gpio_config_status(struct anx7625_data *ctx)
return anx7625_reg_read(ctx, ctx->i2c.rx_p0_client, GPIO_CTRL_2);
}

static ssize_t mipi_check_sum_err_hs_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct anx7625_data *ctx = dev_get_drvdata(dev);
int ret;

ret = pm_runtime_resume_and_get(dev);
if (ret < 0)
return ret;

mutex_lock(&ctx->lock);
ret = anx7625_reg_read(ctx, ctx->i2c.rx_p1_client, 0x19);
mutex_unlock(&ctx->lock);

pm_runtime_put_autosuspend(dev);

if (ret < 0)
return ret;

return sysfs_emit(buf, "%u\n", !!(ret & BIT(5)));
}
static DEVICE_ATTR_RO(mipi_check_sum_err_hs);

static struct attribute *anx7625_attrs[] = {
&dev_attr_mipi_check_sum_err_hs.attr,
NULL,
};

static const struct attribute_group anx7625_attr_group = {
.attrs = anx7625_attrs,
};

static void anx7625_disable_pd_protocol(struct anx7625_data *ctx)
{
struct device *dev = ctx->dev;
Expand Down Expand Up @@ -1796,6 +1839,9 @@ static void anx7625_work_func(struct work_struct *work)
struct anx7625_data *ctx = container_of(work,
struct anx7625_data, work);

if (!ctx->display)
return;

mutex_lock(&ctx->lock);

if (pm_runtime_suspended(ctx->dev)) {
Expand Down Expand Up @@ -2044,6 +2090,7 @@ static int anx7625_audio_hw_params(struct device *dev, void *data,
wl = AUDIO_W_LEN_20_20MAX;
break;
case 24:
case 32:
wl = AUDIO_W_LEN_24_24MAX;
break;
default:
Expand Down Expand Up @@ -2083,6 +2130,11 @@ static int anx7625_audio_hw_params(struct device *dev, void *data,
ret |= anx7625_write_and(ctx, ctx->i2c.tx_p2_client,
AUDIO_CHANNEL_STATUS_6, ~AUDIO_LAYOUT);


/* Right justified for Qualcomm DSP limitations */
ret |= anx7625_write_or(ctx, ctx->i2c.tx_p2_client,
AUDIO_CONTROL_REGISTER, 1);

/* FS */
switch (params->sample_rate) {
case 32000:
Expand Down Expand Up @@ -2867,20 +2919,24 @@ static int anx7625_i2c_probe(struct i2c_client *client)
}
}

platform->display = true;
platform->aux.name = "anx7625-aux";
platform->aux.dev = dev;
platform->aux.transfer = anx7625_aux_transfer;
platform->aux.wait_hpd_asserted = anx7625_wait_hpd_asserted;
drm_dp_aux_init(&platform->aux);

ret = anx7625_parse_dt(dev, pdata);
if (ret) {
if (ret == -ENODEV) {
/* Not using the display function, but we want USB-C function */
platform->display = false;
} else if (ret) {
if (ret != -EPROBE_DEFER)
DRM_DEV_ERROR(dev, "fail to parse DT : %d\n", ret);
goto free_wq;
}

if (!platform->pdata.is_dpi) {
if (platform->display && !platform->pdata.is_dpi) {
ret = anx7625_setup_dsi_device(platform);
if (ret < 0)
goto free_wq;
Expand All @@ -2904,12 +2960,17 @@ static int anx7625_i2c_probe(struct i2c_client *client)
if (ret)
goto free_wq;

ret = devm_device_add_group(dev, &anx7625_attr_group);
if (ret)
goto free_wq;

/*
* Populating the aux bus will retrigger deferred probe, so it needs to
* be done after calls that might return EPROBE_DEFER, otherwise we can
* get an infinite loop.
*/
ret = devm_of_dp_aux_populate_bus(&platform->aux, anx7625_link_bridge);
if (platform->display)
ret = devm_of_dp_aux_populate_bus(&platform->aux, anx7625_link_bridge);
if (ret) {
if (ret != -ENODEV) {
DRM_DEV_ERROR(dev, "failed to populate aux bus : %d\n", ret);
Expand Down Expand Up @@ -2974,7 +3035,8 @@ static void anx7625_i2c_remove(struct i2c_client *client)

anx7625_typec_unregister(platform);

drm_bridge_remove(&platform->bridge);
if (platform->display)
drm_bridge_remove(&platform->bridge);

if (platform->pdata.intp_irq)
destroy_workqueue(platform->workqueue);
Expand Down
3 changes: 3 additions & 0 deletions drivers/gpu/drm/bridge/analogix/anx7625.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,8 @@
#define MIPI_LANE_CTRL_0 0x05
#define MIPI_TIME_HS_PRPR 0x08

#define MIPI_ANALOG_CTRL_0 0x10

/*
* After MIPI RX protocol layer received video frames,
* Protocol layer starts to reconstruct video stream from PHY
Expand Down Expand Up @@ -509,6 +511,7 @@ struct anx7625_data {
struct mipi_dsi_device *dsi;
struct drm_dp_aux aux;
struct fw_msg send_msg;
bool display;
};

#endif /* __ANX7625_H__ */
2 changes: 2 additions & 0 deletions drivers/tty/serdev/serdev-ttyport.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ static int ttyport_open(struct serdev_controller *ctrl)
err_unlock:
tty_unlock(tty);
tty_release_struct(tty, serport->tty_idx);
serport->tty = NULL;

return ret;
}
Expand All @@ -154,6 +155,7 @@ static void ttyport_close(struct serdev_controller *ctrl)
tty_unlock(tty);

tty_release_struct(tty, serport->tty_idx);
serport->tty = NULL;
}

static unsigned int ttyport_set_baudrate(struct serdev_controller *ctrl, unsigned int speed)
Expand Down
2 changes: 1 addition & 1 deletion net/bluetooth/hci_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -4074,7 +4074,7 @@ static int hci_send_cmd_sync(struct hci_dev *hdev, struct sk_buff *skb)
if (!hdev->sent_cmd) {
skb_queue_head(&hdev->cmd_q, skb);
queue_work(hdev->workqueue, &hdev->cmd_work);
return -EINVAL;
return -ENOMEM;
}

if (hci_skb_opcode(skb) != HCI_OP_NOP) {
Expand Down
2 changes: 2 additions & 0 deletions net/bluetooth/hci_sync.c
Original file line number Diff line number Diff line change
Expand Up @@ -5283,6 +5283,7 @@ int hci_dev_open_sync(struct hci_dev *hdev)
if (hdev->req_skb) {
kfree_skb(hdev->req_skb);
hdev->req_skb = NULL;
hci_dev_clear_flag(hdev, HCI_CMD_PENDING);
}

clear_bit(HCI_RUNNING, &hdev->flags);
Expand Down Expand Up @@ -5467,6 +5468,7 @@ int hci_dev_close_sync(struct hci_dev *hdev)
if (hdev->req_skb) {
kfree_skb(hdev->req_skb);
hdev->req_skb = NULL;
hci_dev_clear_flag(hdev, HCI_CMD_PENDING);
}

clear_bit(HCI_RUNNING, &hdev->flags);
Expand Down
82 changes: 75 additions & 7 deletions sound/soc/codecs/pm4125.c
Original file line number Diff line number Diff line change
Expand Up @@ -842,13 +842,32 @@ static int pm4125_codec_enable_micbias_pullup(struct snd_soc_dapm_widget *w,

static int pm4125_connect_port(struct pm4125_sdw_priv *sdw_priv, u8 port_idx, u8 ch_id, bool enable)
{
struct sdw_port_config *port_config = &sdw_priv->port_config[port_idx - 1];
const struct wcd_sdw_ch_info *ch_info = &sdw_priv->ch_info[ch_id];
struct sdw_port_config *port_config;
const struct wcd_sdw_ch_info *ch_info;
struct sdw_slave *sdev = sdw_priv->sdev;
u8 port_num = ch_info->port_num;
u8 ch_mask = ch_info->ch_mask;
u8 port_num, ch_mask;
u8 mstr_port_num, mstr_ch_mask;

if (!port_idx) /* Invalid port index */
return -EINVAL;

if (sdw_priv->is_tx) {
if (ch_id > PM4125_ADC2)
return -EINVAL;
} else {
if (ch_id > PM4125_COMP_R)
return -EINVAL;
}

ch_info = &sdw_priv->ch_info[ch_id];
port_num = ch_info->port_num;
ch_mask = ch_info->ch_mask;

if (!port_num || port_num > PM4125_MAX_SWR_PORTS)
return -EINVAL;

port_config = &sdw_priv->port_config[port_idx - 1];

port_config->num = port_num;

mstr_port_num = sdev->m_port_map[port_num];
Expand Down Expand Up @@ -888,10 +907,18 @@ static int pm4125_set_compander(struct snd_kcontrol *kcontrol, struct snd_ctl_el
struct soc_mixer_control *mc;
int portidx;
bool hphr;
int ch_idx;

mc = (struct soc_mixer_control *)(kcontrol->private_value);
ch_idx = mc->reg;
hphr = mc->shift;

if (!sdw_priv)
return -EINVAL;

if (ch_idx < 0 || ch_idx > PM4125_COMP_R)
return -EINVAL;

if (hphr) {
if (value == pm4125->comp2_enable)
return 0;
Expand All @@ -904,9 +931,11 @@ static int pm4125_set_compander(struct snd_kcontrol *kcontrol, struct snd_ctl_el
pm4125->comp1_enable = value;
}

portidx = sdw_priv->ch_info[mc->reg].port_num;
portidx = sdw_priv->ch_info[ch_idx].port_num;
if (!portidx)
return 0;

pm4125_connect_port(sdw_priv, portidx, mc->reg, value ? true : false);
pm4125_connect_port(sdw_priv, portidx, ch_idx, value ? true : false);

return 1;
}
Expand All @@ -921,8 +950,24 @@ static int pm4125_get_swr_port(struct snd_kcontrol *kcontrol, struct snd_ctl_ele
int ch_idx = mixer->reg;
int portidx;

if (dai_id < 0 || dai_id >= NUM_CODEC_DAIS)
return -EINVAL;

sdw_priv = pm4125->sdw_priv[dai_id];
if (!sdw_priv)
return -EINVAL;

if (sdw_priv->is_tx) {
if (ch_idx < 0 || ch_idx > PM4125_ADC2)
return -EINVAL;
} else {
if (ch_idx < 0 || ch_idx > PM4125_HPH_R)
return -EINVAL;
}

portidx = sdw_priv->ch_info[ch_idx].port_num;
if (!portidx) /* Invalid port index */
return 0;

ucontrol->value.integer.value[0] = sdw_priv->port_enable[portidx];

Expand All @@ -940,9 +985,24 @@ static int pm4125_set_swr_port(struct snd_kcontrol *kcontrol, struct snd_ctl_ele
int portidx;
bool enable;

if (dai_id < 0 || dai_id >= NUM_CODEC_DAIS)
return -EINVAL;

sdw_priv = pm4125->sdw_priv[dai_id];
if (!sdw_priv)
return -EINVAL;

if (sdw_priv->is_tx) {
if (ch_idx < 0 || ch_idx > PM4125_ADC2)
return -EINVAL;
} else {
if (ch_idx < 0 || ch_idx > PM4125_HPH_R)
return -EINVAL;
}

portidx = sdw_priv->ch_info[ch_idx].port_num;
if (!portidx) /* Invalid port index */
return 0;

enable = ucontrol->value.integer.value[0];

Expand Down Expand Up @@ -1411,8 +1471,16 @@ static int pm4125_codec_free(struct snd_pcm_substream *substream, struct snd_soc
{
struct pm4125_priv *pm4125 = dev_get_drvdata(dai->dev);
struct pm4125_sdw_priv *sdw_priv = pm4125->sdw_priv[dai->id];
int ret;

/* hw_free() can be invoked again on a DAPM-driven route change; avoid a stale stream UAF */
if (!sdw_priv->sruntime)
return 0;

return sdw_stream_remove_slave(sdw_priv->sdev, sdw_priv->sruntime);
ret = sdw_stream_remove_slave(sdw_priv->sdev, sdw_priv->sruntime);
sdw_priv->sruntime = NULL;

return ret;
}

static int pm4125_codec_set_sdw_stream(struct snd_soc_dai *dai, void *stream, int direction)
Expand Down
Loading