Merge "diag: mhi: Fix error handling for DCI channel failure"

This commit is contained in:
Linux Build Service Account 2017-07-21 11:08:23 -07:00 committed by Gerrit - the friendly Code Review server
commit be95399835
4 changed files with 73 additions and 18 deletions
Documentation/devicetree/bindings/arm/msm
drivers/char/diag

View file

@ -0,0 +1,12 @@
Qualcomm Technologies, Inc. Diag MHI Driver
Required properties:
-compatible : should be "qcom,diag-mhi".
-qcom,mhi : phandle of MHI Device to connect to.
Example:
qcom,diag {
compatible = "qcom,diag-mhi";
qcom,mhi = <&mhi_wlan>;
};

View file

@ -642,6 +642,7 @@ struct diagchar_dev {
#endif
int time_sync_enabled;
uint8_t uses_time_api;
struct platform_device *pdev;
};
extern struct diagchar_dev *driver;

View file

@ -22,6 +22,8 @@
#include <linux/sched.h>
#include <linux/ratelimit.h>
#include <linux/timer.h>
#include <linux/platform_device.h>
#include <linux/msm_mhi.h>
#ifdef CONFIG_DIAG_OVER_USB
#include <linux/usb/usbdiag.h>
#endif
@ -3589,6 +3591,41 @@ static int diagchar_cleanup(void)
return 0;
}
static int diag_mhi_probe(struct platform_device *pdev)
{
int ret;
if (!mhi_is_device_ready(&pdev->dev, "qcom,mhi"))
return -EPROBE_DEFER;
driver->pdev = pdev;
ret = diag_remote_init();
if (ret) {
diag_remote_exit();
return ret;
}
ret = diagfwd_bridge_init();
if (ret) {
diagfwd_bridge_exit();
return ret;
}
pr_debug("diag: mhi device is ready\n");
return 0;
}
static const struct of_device_id diag_mhi_table[] = {
{.compatible = "qcom,diag-mhi"},
{},
};
static struct platform_driver diag_mhi_driver = {
.probe = diag_mhi_probe,
.driver = {
.name = "DIAG MHI Platform",
.owner = THIS_MODULE,
.of_match_table = diag_mhi_table,
},
};
static int __init diagchar_init(void)
{
dev_t dev;
@ -3676,9 +3713,6 @@ static int __init diagchar_init(void)
if (ret)
goto fail;
ret = diag_masks_init();
if (ret)
goto fail;
ret = diag_remote_init();
if (ret)
goto fail;
ret = diag_mux_init();
@ -3717,9 +3751,7 @@ static int __init diagchar_init(void)
goto fail;
pr_debug("diagchar initialized now");
ret = diagfwd_bridge_init();
if (ret)
diagfwd_bridge_exit();
platform_driver_register(&diag_mhi_driver);
return 0;
fail:
@ -3733,9 +3765,7 @@ fail:
diagfwd_cntl_exit();
diag_dci_exit();
diag_masks_exit();
diag_remote_exit();
return -1;
}
static void diagchar_exit(void)

View file

@ -197,7 +197,7 @@ static void mhi_buf_tbl_clear(struct diag_mhi_info *mhi_info)
struct diag_mhi_buf_tbl_t *item = NULL;
struct diag_mhi_ch_t *ch = NULL;
if (!mhi_info || !mhi_info->enabled)
if (!mhi_info)
return;
/* Clear all the pending reads */
@ -678,7 +678,25 @@ static int diag_mhi_register_ch(int id, struct diag_mhi_ch_t *ch)
atomic_set(&(ch->opened), 0);
ctxt = SET_CH_CTXT(id, ch->type);
ch->client_info.mhi_client_cb = mhi_notifier;
return mhi_register_channel(&ch->hdl, NULL);
ch->client_info.chan = ch->chan;
ch->client_info.dev = &driver->pdev->dev;
ch->client_info.node_name = "qcom,mhi";
ch->client_info.user_data = (void *)(uintptr_t)ctxt;
return mhi_register_channel(&ch->hdl, &ch->client_info);
}
static void diag_mhi_dev_exit(int dev)
{
struct diag_mhi_info *mhi_info = NULL;
mhi_info = &diag_mhi[dev];
if (!mhi_info)
return;
if (mhi_info->mhi_wq)
destroy_workqueue(mhi_info->mhi_wq);
mhi_close(mhi_info->id);
if (mhi_info->mempool_init)
diagmem_exit(driver, mhi_info->mempool);
}
int diag_mhi_init()
@ -726,22 +744,16 @@ int diag_mhi_init()
return 0;
fail:
diag_mhi_exit();
diag_mhi_dev_exit(i);
return -ENOMEM;
}
void diag_mhi_exit()
{
int i;
struct diag_mhi_info *mhi_info = NULL;
for (i = 0; i < NUM_MHI_DEV; i++) {
mhi_info = &diag_mhi[i];
if (mhi_info->mhi_wq)
destroy_workqueue(mhi_info->mhi_wq);
mhi_close(mhi_info->id);
if (mhi_info->mempool_init)
diagmem_exit(driver, mhi_info->mempool);
diag_mhi_dev_exit(i);
}
}