@@ -84,6 +84,56 @@ fvmap_calculate_initial_usage(const volatile struct fvmap_header *header,
8484 return ALIGN (max_offset , sizeof (u32 ));
8585}
8686
87+ static int fvmap_expand_gpu_lut (struct vclk * vclk , size_t manual_count ) {
88+ struct vclk_lut * new_lut ;
89+ size_t idx , old_count ;
90+
91+ if (!vclk || !vclk -> lut )
92+ return - EINVAL ;
93+
94+ old_count = vclk -> num_rates ;
95+ if (manual_count <= old_count )
96+ return 0 ;
97+
98+ new_lut = kcalloc (manual_count , sizeof (* new_lut ), GFP_KERNEL );
99+ if (!new_lut )
100+ return - ENOMEM ;
101+
102+ for (idx = 0 ; idx < manual_count ; idx ++ ) {
103+ new_lut [idx ].params =
104+ kcalloc (vclk -> num_list , sizeof (* new_lut [idx ].params ), GFP_KERNEL );
105+ if (!new_lut [idx ].params )
106+ goto err_free ;
107+
108+ if (idx < old_count ) {
109+ new_lut [idx ].rate = vclk -> lut [idx ].rate ;
110+ memcpy (new_lut [idx ].params , vclk -> lut [idx ].params ,
111+ sizeof (unsigned int ) * vclk -> num_list );
112+ } else if (old_count ) {
113+ new_lut [idx ].rate = vclk -> lut [old_count - 1 ].rate ;
114+ memcpy (new_lut [idx ].params , vclk -> lut [old_count - 1 ].params ,
115+ sizeof (unsigned int ) * vclk -> num_list );
116+ }
117+ }
118+
119+ for (idx = 0 ; idx < old_count ; idx ++ )
120+ kfree (vclk -> lut [idx ].params );
121+
122+ kfree (vclk -> lut );
123+
124+ vclk -> lut = new_lut ;
125+ vclk -> num_rates = manual_count ;
126+
127+ return 0 ;
128+
129+ err_free :
130+ while (idx -- )
131+ kfree (new_lut [idx ].params );
132+ kfree (new_lut );
133+
134+ return - ENOMEM ;
135+ }
136+
87137static void fvmap_apply_gpu_manual_table (volatile struct fvmap_header * header ,
88138 struct rate_volt_header * rate_table ,
89139 struct vclk * vclk ) {
@@ -104,8 +154,16 @@ static void fvmap_apply_gpu_manual_table(volatile struct fvmap_header *header,
104154 manual_count * sizeof (struct rate_volt ));
105155 header -> num_of_lv = manual_count ;
106156
107- if (vclk && vclk -> lut && vclk -> num_rates < manual_count )
108- vclk -> num_rates = manual_count ;
157+ if (vclk && vclk -> lut && vclk -> num_rates < manual_count ) {
158+ int ret = fvmap_expand_gpu_lut (vclk , manual_count );
159+
160+ if (ret ) {
161+ pr_err (" G3D: failed to expand LUT to %zu entries (%d)\n" ,
162+ manual_count , ret );
163+ manual_count = min (manual_count , (size_t )vclk -> num_rates );
164+ header -> num_of_lv = manual_count ;
165+ }
166+ }
109167
110168 if (vclk && vclk -> lut ) {
111169 for (idx = 0 ; idx < manual_count && idx < vclk -> num_rates ; idx ++ )
0 commit comments