0001
0002
0003
0004
0005
0006 #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
0007
0008 #include "msm_disp_snapshot.h"
0009
0010 static ssize_t __maybe_unused disp_devcoredump_read(char *buffer, loff_t offset,
0011 size_t count, void *data, size_t datalen)
0012 {
0013 struct drm_print_iterator iter;
0014 struct drm_printer p;
0015 struct msm_disp_state *disp_state;
0016
0017 disp_state = data;
0018
0019 iter.data = buffer;
0020 iter.offset = 0;
0021 iter.start = offset;
0022 iter.remain = count;
0023
0024 p = drm_coredump_printer(&iter);
0025
0026 msm_disp_state_print(disp_state, &p);
0027
0028 return count - iter.remain;
0029 }
0030
0031 struct msm_disp_state *
0032 msm_disp_snapshot_state_sync(struct msm_kms *kms)
0033 {
0034 struct drm_device *drm_dev = kms->dev;
0035 struct msm_disp_state *disp_state;
0036
0037 WARN_ON(!mutex_is_locked(&kms->dump_mutex));
0038
0039 disp_state = kzalloc(sizeof(struct msm_disp_state), GFP_KERNEL);
0040 if (!disp_state)
0041 return ERR_PTR(-ENOMEM);
0042
0043 disp_state->dev = drm_dev->dev;
0044 disp_state->drm_dev = drm_dev;
0045
0046 INIT_LIST_HEAD(&disp_state->blocks);
0047
0048 msm_disp_snapshot_capture_state(disp_state);
0049
0050 return disp_state;
0051 }
0052
0053 static void _msm_disp_snapshot_work(struct kthread_work *work)
0054 {
0055 struct msm_kms *kms = container_of(work, struct msm_kms, dump_work);
0056 struct msm_disp_state *disp_state;
0057 struct drm_printer p;
0058
0059
0060 mutex_lock(&kms->dump_mutex);
0061 disp_state = msm_disp_snapshot_state_sync(kms);
0062 mutex_unlock(&kms->dump_mutex);
0063
0064 if (IS_ERR(disp_state))
0065 return;
0066
0067 if (MSM_DISP_SNAPSHOT_DUMP_IN_CONSOLE) {
0068 p = drm_info_printer(disp_state->drm_dev->dev);
0069 msm_disp_state_print(disp_state, &p);
0070 }
0071
0072
0073
0074
0075
0076
0077 dev_coredumpm(disp_state->dev, THIS_MODULE, disp_state, 0, GFP_KERNEL,
0078 disp_devcoredump_read, msm_disp_state_free);
0079 }
0080
0081 void msm_disp_snapshot_state(struct drm_device *drm_dev)
0082 {
0083 struct msm_drm_private *priv;
0084 struct msm_kms *kms;
0085
0086 if (!drm_dev) {
0087 DRM_ERROR("invalid params\n");
0088 return;
0089 }
0090
0091 priv = drm_dev->dev_private;
0092 kms = priv->kms;
0093
0094 kthread_queue_work(kms->dump_worker, &kms->dump_work);
0095 }
0096
0097 int msm_disp_snapshot_init(struct drm_device *drm_dev)
0098 {
0099 struct msm_drm_private *priv;
0100 struct msm_kms *kms;
0101
0102 if (!drm_dev) {
0103 DRM_ERROR("invalid params\n");
0104 return -EINVAL;
0105 }
0106
0107 priv = drm_dev->dev_private;
0108 kms = priv->kms;
0109
0110 mutex_init(&kms->dump_mutex);
0111
0112 kms->dump_worker = kthread_create_worker(0, "%s", "disp_snapshot");
0113 if (IS_ERR(kms->dump_worker))
0114 DRM_ERROR("failed to create disp state task\n");
0115
0116 kthread_init_work(&kms->dump_work, _msm_disp_snapshot_work);
0117
0118 return 0;
0119 }
0120
0121 void msm_disp_snapshot_destroy(struct drm_device *drm_dev)
0122 {
0123 struct msm_kms *kms;
0124 struct msm_drm_private *priv;
0125
0126 if (!drm_dev) {
0127 DRM_ERROR("invalid params\n");
0128 return;
0129 }
0130
0131 priv = drm_dev->dev_private;
0132 kms = priv->kms;
0133
0134 if (kms->dump_worker)
0135 kthread_destroy_worker(kms->dump_worker);
0136
0137 mutex_destroy(&kms->dump_mutex);
0138 }