Merge tag 'drm-misc-next-2020-01-02' of git://anongit.freedesktop.org/drm/drm-misc...
[platform/kernel/linux-rpi.git] / drivers / gpu / drm / arm / display / komeda / komeda_crtc.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
4  * Author: James.Qian.Wang <james.qian.wang@arm.com>
5  *
6  */
7 #include <linux/clk.h>
8 #include <linux/pm_runtime.h>
9 #include <linux/spinlock.h>
10
11 #include <drm/drm_atomic.h>
12 #include <drm/drm_atomic_helper.h>
13 #include <drm/drm_crtc_helper.h>
14 #include <drm/drm_plane_helper.h>
15 #include <drm/drm_print.h>
16 #include <drm/drm_vblank.h>
17
18 #include "komeda_dev.h"
19 #include "komeda_kms.h"
20
21 void komeda_crtc_get_color_config(struct drm_crtc_state *crtc_st,
22                                   u32 *color_depths, u32 *color_formats)
23 {
24         struct drm_connector *conn;
25         struct drm_connector_state *conn_st;
26         u32 conn_color_formats = ~0u;
27         int i, min_bpc = 31, conn_bpc = 0;
28
29         for_each_new_connector_in_state(crtc_st->state, conn, conn_st, i) {
30                 if (conn_st->crtc != crtc_st->crtc)
31                         continue;
32
33                 conn_bpc = conn->display_info.bpc ? conn->display_info.bpc : 8;
34                 conn_color_formats &= conn->display_info.color_formats;
35
36                 if (conn_bpc < min_bpc)
37                         min_bpc = conn_bpc;
38         }
39
40         /* connector doesn't config any color_format, use RGB444 as default */
41         if (!conn_color_formats)
42                 conn_color_formats = DRM_COLOR_FORMAT_RGB444;
43
44         *color_depths = GENMASK(min_bpc, 0);
45         *color_formats = conn_color_formats;
46 }
47
48 static void komeda_crtc_update_clock_ratio(struct komeda_crtc_state *kcrtc_st)
49 {
50         u64 pxlclk, aclk;
51
52         if (!kcrtc_st->base.active) {
53                 kcrtc_st->clock_ratio = 0;
54                 return;
55         }
56
57         pxlclk = kcrtc_st->base.adjusted_mode.crtc_clock * 1000ULL;
58         aclk = komeda_crtc_get_aclk(kcrtc_st);
59
60         kcrtc_st->clock_ratio = div64_u64(aclk << 32, pxlclk);
61 }
62
63 /**
64  * komeda_crtc_atomic_check - build display output data flow
65  * @crtc: DRM crtc
66  * @state: the crtc state object
67  *
68  * crtc_atomic_check is the final check stage, so beside build a display data
69  * pipeline according to the crtc_state, but still needs to release or disable
70  * the unclaimed pipeline resources.
71  *
72  * RETURNS:
73  * Zero for success or -errno
74  */
75 static int
76 komeda_crtc_atomic_check(struct drm_crtc *crtc,
77                          struct drm_crtc_state *state)
78 {
79         struct komeda_crtc *kcrtc = to_kcrtc(crtc);
80         struct komeda_crtc_state *kcrtc_st = to_kcrtc_st(state);
81         int err;
82
83         if (drm_atomic_crtc_needs_modeset(state))
84                 komeda_crtc_update_clock_ratio(kcrtc_st);
85
86         if (state->active) {
87                 err = komeda_build_display_data_flow(kcrtc, kcrtc_st);
88                 if (err)
89                         return err;
90         }
91
92         /* release unclaimed pipeline resources */
93         err = komeda_release_unclaimed_resources(kcrtc->slave, kcrtc_st);
94         if (err)
95                 return err;
96
97         err = komeda_release_unclaimed_resources(kcrtc->master, kcrtc_st);
98         if (err)
99                 return err;
100
101         return 0;
102 }
103
104 /* For active a crtc, mainly need two parts of preparation
105  * 1. adjust display operation mode.
106  * 2. enable needed clk
107  */
108 static int
109 komeda_crtc_prepare(struct komeda_crtc *kcrtc)
110 {
111         struct komeda_dev *mdev = kcrtc->base.dev->dev_private;
112         struct komeda_pipeline *master = kcrtc->master;
113         struct komeda_crtc_state *kcrtc_st = to_kcrtc_st(kcrtc->base.state);
114         struct drm_display_mode *mode = &kcrtc_st->base.adjusted_mode;
115         u32 new_mode;
116         int err;
117
118         mutex_lock(&mdev->lock);
119
120         new_mode = mdev->dpmode | BIT(master->id);
121         if (WARN_ON(new_mode == mdev->dpmode)) {
122                 err = 0;
123                 goto unlock;
124         }
125
126         err = mdev->funcs->change_opmode(mdev, new_mode);
127         if (err) {
128                 DRM_ERROR("failed to change opmode: 0x%x -> 0x%x.\n,",
129                           mdev->dpmode, new_mode);
130                 goto unlock;
131         }
132
133         mdev->dpmode = new_mode;
134         /* Only need to enable aclk on single display mode, but no need to
135          * enable aclk it on dual display mode, since the dual mode always
136          * switch from single display mode, the aclk already enabled, no need
137          * to enable it again.
138          */
139         if (new_mode != KOMEDA_MODE_DUAL_DISP) {
140                 err = clk_set_rate(mdev->aclk, komeda_crtc_get_aclk(kcrtc_st));
141                 if (err)
142                         DRM_ERROR("failed to set aclk.\n");
143                 err = clk_prepare_enable(mdev->aclk);
144                 if (err)
145                         DRM_ERROR("failed to enable aclk.\n");
146         }
147
148         err = clk_set_rate(master->pxlclk, mode->crtc_clock * 1000);
149         if (err)
150                 DRM_ERROR("failed to set pxlclk for pipe%d\n", master->id);
151         err = clk_prepare_enable(master->pxlclk);
152         if (err)
153                 DRM_ERROR("failed to enable pxl clk for pipe%d.\n", master->id);
154
155 unlock:
156         mutex_unlock(&mdev->lock);
157
158         return err;
159 }
160
161 static int
162 komeda_crtc_unprepare(struct komeda_crtc *kcrtc)
163 {
164         struct komeda_dev *mdev = kcrtc->base.dev->dev_private;
165         struct komeda_pipeline *master = kcrtc->master;
166         u32 new_mode;
167         int err;
168
169         mutex_lock(&mdev->lock);
170
171         new_mode = mdev->dpmode & (~BIT(master->id));
172
173         if (WARN_ON(new_mode == mdev->dpmode)) {
174                 err = 0;
175                 goto unlock;
176         }
177
178         err = mdev->funcs->change_opmode(mdev, new_mode);
179         if (err) {
180                 DRM_ERROR("failed to change opmode: 0x%x -> 0x%x.\n,",
181                           mdev->dpmode, new_mode);
182                 goto unlock;
183         }
184
185         mdev->dpmode = new_mode;
186
187         clk_disable_unprepare(master->pxlclk);
188         if (new_mode == KOMEDA_MODE_INACTIVE)
189                 clk_disable_unprepare(mdev->aclk);
190
191 unlock:
192         mutex_unlock(&mdev->lock);
193
194         return err;
195 }
196
197 void komeda_crtc_handle_event(struct komeda_crtc   *kcrtc,
198                               struct komeda_events *evts)
199 {
200         struct drm_crtc *crtc = &kcrtc->base;
201         u32 events = evts->pipes[kcrtc->master->id];
202
203         if (events & KOMEDA_EVENT_VSYNC)
204                 drm_crtc_handle_vblank(crtc);
205
206         if (events & KOMEDA_EVENT_EOW) {
207                 struct komeda_wb_connector *wb_conn = kcrtc->wb_conn;
208
209                 if (wb_conn)
210                         drm_writeback_signal_completion(&wb_conn->base, 0);
211                 else
212                         DRM_WARN("CRTC[%d]: EOW happen but no wb_connector.\n",
213                                  drm_crtc_index(&kcrtc->base));
214         }
215         /* will handle it together with the write back support */
216         if (events & KOMEDA_EVENT_EOW)
217                 DRM_DEBUG("EOW.\n");
218
219         if (events & KOMEDA_EVENT_FLIP) {
220                 unsigned long flags;
221                 struct drm_pending_vblank_event *event;
222
223                 spin_lock_irqsave(&crtc->dev->event_lock, flags);
224                 if (kcrtc->disable_done) {
225                         complete_all(kcrtc->disable_done);
226                         kcrtc->disable_done = NULL;
227                 } else if (crtc->state->event) {
228                         event = crtc->state->event;
229                         /*
230                          * Consume event before notifying drm core that flip
231                          * happened.
232                          */
233                         crtc->state->event = NULL;
234                         drm_crtc_send_vblank_event(crtc, event);
235                 } else {
236                         DRM_WARN("CRTC[%d]: FLIP happen but no pending commit.\n",
237                                  drm_crtc_index(&kcrtc->base));
238                 }
239                 spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
240         }
241 }
242
243 static void
244 komeda_crtc_do_flush(struct drm_crtc *crtc,
245                      struct drm_crtc_state *old)
246 {
247         struct komeda_crtc *kcrtc = to_kcrtc(crtc);
248         struct komeda_crtc_state *kcrtc_st = to_kcrtc_st(crtc->state);
249         struct komeda_dev *mdev = kcrtc->base.dev->dev_private;
250         struct komeda_pipeline *master = kcrtc->master;
251         struct komeda_pipeline *slave = kcrtc->slave;
252         struct komeda_wb_connector *wb_conn = kcrtc->wb_conn;
253         struct drm_connector_state *conn_st;
254
255         DRM_DEBUG_ATOMIC("CRTC%d_FLUSH: active_pipes: 0x%x, affected: 0x%x.\n",
256                          drm_crtc_index(crtc),
257                          kcrtc_st->active_pipes, kcrtc_st->affected_pipes);
258
259         /* step 1: update the pipeline/component state to HW */
260         if (has_bit(master->id, kcrtc_st->affected_pipes))
261                 komeda_pipeline_update(master, old->state);
262
263         if (slave && has_bit(slave->id, kcrtc_st->affected_pipes))
264                 komeda_pipeline_update(slave, old->state);
265
266         conn_st = wb_conn ? wb_conn->base.base.state : NULL;
267         if (conn_st && conn_st->writeback_job)
268                 drm_writeback_queue_job(&wb_conn->base, conn_st);
269
270         /* step 2: notify the HW to kickoff the update */
271         mdev->funcs->flush(mdev, master->id, kcrtc_st->active_pipes);
272 }
273
274 static void
275 komeda_crtc_atomic_enable(struct drm_crtc *crtc,
276                           struct drm_crtc_state *old)
277 {
278         pm_runtime_get_sync(crtc->dev->dev);
279         komeda_crtc_prepare(to_kcrtc(crtc));
280         drm_crtc_vblank_on(crtc);
281         WARN_ON(drm_crtc_vblank_get(crtc));
282         komeda_crtc_do_flush(crtc, old);
283 }
284
285 static void
286 komeda_crtc_flush_and_wait_for_flip_done(struct komeda_crtc *kcrtc,
287                                          struct completion *input_flip_done)
288 {
289         struct drm_device *drm = kcrtc->base.dev;
290         struct komeda_dev *mdev = kcrtc->master->mdev;
291         struct completion *flip_done;
292         struct completion temp;
293         int timeout;
294
295         /* if caller doesn't send a flip_done, use a private flip_done */
296         if (input_flip_done) {
297                 flip_done = input_flip_done;
298         } else {
299                 init_completion(&temp);
300                 kcrtc->disable_done = &temp;
301                 flip_done = &temp;
302         }
303
304         mdev->funcs->flush(mdev, kcrtc->master->id, 0);
305
306         /* wait the flip take affect.*/
307         timeout = wait_for_completion_timeout(flip_done, HZ);
308         if (timeout == 0) {
309                 DRM_ERROR("wait pipe%d flip done timeout\n", kcrtc->master->id);
310                 if (!input_flip_done) {
311                         unsigned long flags;
312
313                         spin_lock_irqsave(&drm->event_lock, flags);
314                         kcrtc->disable_done = NULL;
315                         spin_unlock_irqrestore(&drm->event_lock, flags);
316                 }
317         }
318 }
319
320 static void
321 komeda_crtc_atomic_disable(struct drm_crtc *crtc,
322                            struct drm_crtc_state *old)
323 {
324         struct komeda_crtc *kcrtc = to_kcrtc(crtc);
325         struct komeda_crtc_state *old_st = to_kcrtc_st(old);
326         struct komeda_pipeline *master = kcrtc->master;
327         struct komeda_pipeline *slave  = kcrtc->slave;
328         struct completion *disable_done;
329         bool needs_phase2 = false;
330
331         DRM_DEBUG_ATOMIC("CRTC%d_DISABLE: active_pipes: 0x%x, affected: 0x%x\n",
332                          drm_crtc_index(crtc),
333                          old_st->active_pipes, old_st->affected_pipes);
334
335         if (slave && has_bit(slave->id, old_st->active_pipes))
336                 komeda_pipeline_disable(slave, old->state);
337
338         if (has_bit(master->id, old_st->active_pipes))
339                 needs_phase2 = komeda_pipeline_disable(master, old->state);
340
341         /* crtc_disable has two scenarios according to the state->active switch.
342          * 1. active -> inactive
343          *    this commit is a disable commit. and the commit will be finished
344          *    or done after the disable operation. on this case we can directly
345          *    use the crtc->state->event to tracking the HW disable operation.
346          * 2. active -> active
347          *    the crtc->commit is not for disable, but a modeset operation when
348          *    crtc is active, such commit actually has been completed by 3
349          *    DRM operations:
350          *    crtc_disable, update_planes(crtc_flush), crtc_enable
351          *    so on this case the crtc->commit is for the whole process.
352          *    we can not use it for tracing the disable, we need a temporary
353          *    flip_done for tracing the disable. and crtc->state->event for
354          *    the crtc_enable operation.
355          *    That's also the reason why skip modeset commit in
356          *    komeda_crtc_atomic_flush()
357          */
358         disable_done = (needs_phase2 || crtc->state->active) ?
359                        NULL : &crtc->state->commit->flip_done;
360
361         /* wait phase 1 disable done */
362         komeda_crtc_flush_and_wait_for_flip_done(kcrtc, disable_done);
363
364         /* phase 2 */
365         if (needs_phase2) {
366                 komeda_pipeline_disable(kcrtc->master, old->state);
367
368                 disable_done = crtc->state->active ?
369                                NULL : &crtc->state->commit->flip_done;
370
371                 komeda_crtc_flush_and_wait_for_flip_done(kcrtc, disable_done);
372         }
373
374         drm_crtc_vblank_put(crtc);
375         drm_crtc_vblank_off(crtc);
376         komeda_crtc_unprepare(kcrtc);
377         pm_runtime_put(crtc->dev->dev);
378 }
379
380 static void
381 komeda_crtc_atomic_flush(struct drm_crtc *crtc,
382                          struct drm_crtc_state *old)
383 {
384         /* commit with modeset will be handled in enable/disable */
385         if (drm_atomic_crtc_needs_modeset(crtc->state))
386                 return;
387
388         komeda_crtc_do_flush(crtc, old);
389 }
390
391 /* Returns the minimum frequency of the aclk rate (main engine clock) in Hz */
392 static unsigned long
393 komeda_calc_min_aclk_rate(struct komeda_crtc *kcrtc,
394                           unsigned long pxlclk)
395 {
396         /* Once dual-link one display pipeline drives two display outputs,
397          * the aclk needs run on the double rate of pxlclk
398          */
399         if (kcrtc->master->dual_link)
400                 return pxlclk * 2;
401         else
402                 return pxlclk;
403 }
404
405 /* Get current aclk rate that specified by state */
406 unsigned long komeda_crtc_get_aclk(struct komeda_crtc_state *kcrtc_st)
407 {
408         struct drm_crtc *crtc = kcrtc_st->base.crtc;
409         struct komeda_dev *mdev = crtc->dev->dev_private;
410         unsigned long pxlclk = kcrtc_st->base.adjusted_mode.crtc_clock * 1000;
411         unsigned long min_aclk;
412
413         min_aclk = komeda_calc_min_aclk_rate(to_kcrtc(crtc), pxlclk);
414
415         return clk_round_rate(mdev->aclk, min_aclk);
416 }
417
418 static enum drm_mode_status
419 komeda_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *m)
420 {
421         struct komeda_dev *mdev = crtc->dev->dev_private;
422         struct komeda_crtc *kcrtc = to_kcrtc(crtc);
423         struct komeda_pipeline *master = kcrtc->master;
424         unsigned long min_pxlclk, min_aclk;
425
426         if (m->flags & DRM_MODE_FLAG_INTERLACE)
427                 return MODE_NO_INTERLACE;
428
429         min_pxlclk = m->clock * 1000;
430         if (master->dual_link)
431                 min_pxlclk /= 2;
432
433         if (min_pxlclk != clk_round_rate(master->pxlclk, min_pxlclk)) {
434                 DRM_DEBUG_ATOMIC("pxlclk doesn't support %lu Hz\n", min_pxlclk);
435
436                 return MODE_NOCLOCK;
437         }
438
439         min_aclk = komeda_calc_min_aclk_rate(to_kcrtc(crtc), min_pxlclk);
440         if (clk_round_rate(mdev->aclk, min_aclk) < min_aclk) {
441                 DRM_DEBUG_ATOMIC("engine clk can't satisfy the requirement of %s-clk: %lu.\n",
442                                  m->name, min_pxlclk);
443
444                 return MODE_CLOCK_HIGH;
445         }
446
447         return MODE_OK;
448 }
449
450 static bool komeda_crtc_mode_fixup(struct drm_crtc *crtc,
451                                    const struct drm_display_mode *m,
452                                    struct drm_display_mode *adjusted_mode)
453 {
454         struct komeda_crtc *kcrtc = to_kcrtc(crtc);
455         unsigned long clk_rate;
456
457         drm_mode_set_crtcinfo(adjusted_mode, 0);
458         /* In dual link half the horizontal settings */
459         if (kcrtc->master->dual_link) {
460                 adjusted_mode->crtc_clock /= 2;
461                 adjusted_mode->crtc_hdisplay /= 2;
462                 adjusted_mode->crtc_hsync_start /= 2;
463                 adjusted_mode->crtc_hsync_end /= 2;
464                 adjusted_mode->crtc_htotal /= 2;
465         }
466
467         clk_rate = adjusted_mode->crtc_clock * 1000;
468         /* crtc_clock will be used as the komeda output pixel clock */
469         adjusted_mode->crtc_clock = clk_round_rate(kcrtc->master->pxlclk,
470                                                    clk_rate) / 1000;
471
472         return true;
473 }
474
475 static const struct drm_crtc_helper_funcs komeda_crtc_helper_funcs = {
476         .atomic_check   = komeda_crtc_atomic_check,
477         .atomic_flush   = komeda_crtc_atomic_flush,
478         .atomic_enable  = komeda_crtc_atomic_enable,
479         .atomic_disable = komeda_crtc_atomic_disable,
480         .mode_valid     = komeda_crtc_mode_valid,
481         .mode_fixup     = komeda_crtc_mode_fixup,
482 };
483
484 static void komeda_crtc_reset(struct drm_crtc *crtc)
485 {
486         struct komeda_crtc_state *state;
487
488         if (crtc->state)
489                 __drm_atomic_helper_crtc_destroy_state(crtc->state);
490
491         kfree(to_kcrtc_st(crtc->state));
492         crtc->state = NULL;
493
494         state = kzalloc(sizeof(*state), GFP_KERNEL);
495         if (state) {
496                 crtc->state = &state->base;
497                 crtc->state->crtc = crtc;
498         }
499 }
500
501 static struct drm_crtc_state *
502 komeda_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
503 {
504         struct komeda_crtc_state *old = to_kcrtc_st(crtc->state);
505         struct komeda_crtc_state *new;
506
507         new = kzalloc(sizeof(*new), GFP_KERNEL);
508         if (!new)
509                 return NULL;
510
511         __drm_atomic_helper_crtc_duplicate_state(crtc, &new->base);
512
513         new->affected_pipes = old->active_pipes;
514         new->clock_ratio = old->clock_ratio;
515         new->max_slave_zorder = old->max_slave_zorder;
516
517         return &new->base;
518 }
519
520 static void komeda_crtc_atomic_destroy_state(struct drm_crtc *crtc,
521                                              struct drm_crtc_state *state)
522 {
523         __drm_atomic_helper_crtc_destroy_state(state);
524         kfree(to_kcrtc_st(state));
525 }
526
527 static int komeda_crtc_vblank_enable(struct drm_crtc *crtc)
528 {
529         struct komeda_dev *mdev = crtc->dev->dev_private;
530         struct komeda_crtc *kcrtc = to_kcrtc(crtc);
531
532         mdev->funcs->on_off_vblank(mdev, kcrtc->master->id, true);
533         return 0;
534 }
535
536 static void komeda_crtc_vblank_disable(struct drm_crtc *crtc)
537 {
538         struct komeda_dev *mdev = crtc->dev->dev_private;
539         struct komeda_crtc *kcrtc = to_kcrtc(crtc);
540
541         mdev->funcs->on_off_vblank(mdev, kcrtc->master->id, false);
542 }
543
544 static const struct drm_crtc_funcs komeda_crtc_funcs = {
545         .gamma_set              = drm_atomic_helper_legacy_gamma_set,
546         .destroy                = drm_crtc_cleanup,
547         .set_config             = drm_atomic_helper_set_config,
548         .page_flip              = drm_atomic_helper_page_flip,
549         .reset                  = komeda_crtc_reset,
550         .atomic_duplicate_state = komeda_crtc_atomic_duplicate_state,
551         .atomic_destroy_state   = komeda_crtc_atomic_destroy_state,
552         .enable_vblank          = komeda_crtc_vblank_enable,
553         .disable_vblank         = komeda_crtc_vblank_disable,
554 };
555
556 int komeda_kms_setup_crtcs(struct komeda_kms_dev *kms,
557                            struct komeda_dev *mdev)
558 {
559         struct komeda_crtc *crtc;
560         struct komeda_pipeline *master;
561         char str[16];
562         int i;
563
564         kms->n_crtcs = 0;
565
566         for (i = 0; i < mdev->n_pipelines; i++) {
567                 crtc = &kms->crtcs[kms->n_crtcs];
568                 master = mdev->pipelines[i];
569
570                 crtc->master = master;
571                 crtc->slave  = komeda_pipeline_get_slave(master);
572
573                 if (crtc->slave)
574                         sprintf(str, "pipe-%d", crtc->slave->id);
575                 else
576                         sprintf(str, "None");
577
578                 DRM_INFO("CRTC-%d: master(pipe-%d) slave(%s).\n",
579                          kms->n_crtcs, master->id, str);
580
581                 kms->n_crtcs++;
582         }
583
584         return 0;
585 }
586
587 static struct drm_plane *
588 get_crtc_primary(struct komeda_kms_dev *kms, struct komeda_crtc *crtc)
589 {
590         struct komeda_plane *kplane;
591         struct drm_plane *plane;
592
593         drm_for_each_plane(plane, &kms->base) {
594                 if (plane->type != DRM_PLANE_TYPE_PRIMARY)
595                         continue;
596
597                 kplane = to_kplane(plane);
598                 /* only master can be primary */
599                 if (kplane->layer->base.pipeline == crtc->master)
600                         return plane;
601         }
602
603         return NULL;
604 }
605
606 static int komeda_crtc_add(struct komeda_kms_dev *kms,
607                            struct komeda_crtc *kcrtc)
608 {
609         struct drm_crtc *crtc = &kcrtc->base;
610         int err;
611
612         err = drm_crtc_init_with_planes(&kms->base, crtc,
613                                         get_crtc_primary(kms, kcrtc), NULL,
614                                         &komeda_crtc_funcs, NULL);
615         if (err)
616                 return err;
617
618         drm_crtc_helper_add(crtc, &komeda_crtc_helper_funcs);
619         drm_crtc_vblank_reset(crtc);
620
621         crtc->port = kcrtc->master->of_output_port;
622
623         drm_crtc_enable_color_mgmt(crtc, 0, true, KOMEDA_COLOR_LUT_SIZE);
624
625         return err;
626 }
627
628 int komeda_kms_add_crtcs(struct komeda_kms_dev *kms, struct komeda_dev *mdev)
629 {
630         int i, err;
631
632         for (i = 0; i < kms->n_crtcs; i++) {
633                 err = komeda_crtc_add(kms, &kms->crtcs[i]);
634                 if (err)
635                         return err;
636         }
637
638         return 0;
639 }