@@ -136,6 +136,114 @@ static int vmw_close_channel(struct rpc_channel *channel)
136136 return 0 ;
137137}
138138
139+ /**
140+ * vmw_port_hb_out - Send the message payload either through the
141+ * high-bandwidth port if available, or through the backdoor otherwise.
142+ * @channel: The rpc channel.
143+ * @msg: NULL-terminated message.
144+ * @hb: Whether the high-bandwidth port is available.
145+ *
146+ * Return: The port status.
147+ */
148+ static unsigned long vmw_port_hb_out (struct rpc_channel * channel ,
149+ const char * msg , bool hb )
150+ {
151+ unsigned long si , di , eax , ebx , ecx , edx ;
152+ unsigned long msg_len = strlen (msg );
153+
154+ if (hb ) {
155+ unsigned long bp = channel -> cookie_high ;
156+
157+ si = (uintptr_t ) msg ;
158+ di = channel -> cookie_low ;
159+
160+ VMW_PORT_HB_OUT (
161+ (MESSAGE_STATUS_SUCCESS << 16 ) | VMW_PORT_CMD_HB_MSG ,
162+ msg_len , si , di ,
163+ VMW_HYPERVISOR_HB_PORT | (channel -> channel_id << 16 ),
164+ VMW_HYPERVISOR_MAGIC , bp ,
165+ eax , ebx , ecx , edx , si , di );
166+
167+ return ebx ;
168+ }
169+
170+ /* HB port not available. Send the message 4 bytes at a time. */
171+ ecx = MESSAGE_STATUS_SUCCESS << 16 ;
172+ while (msg_len && (HIGH_WORD (ecx ) & MESSAGE_STATUS_SUCCESS )) {
173+ unsigned int bytes = min_t (size_t , msg_len , 4 );
174+ unsigned long word = 0 ;
175+
176+ memcpy (& word , msg , bytes );
177+ msg_len -= bytes ;
178+ msg += bytes ;
179+ si = channel -> cookie_high ;
180+ di = channel -> cookie_low ;
181+
182+ VMW_PORT (VMW_PORT_CMD_MSG | (MSG_TYPE_SENDPAYLOAD << 16 ),
183+ word , si , di ,
184+ VMW_HYPERVISOR_PORT | (channel -> channel_id << 16 ),
185+ VMW_HYPERVISOR_MAGIC ,
186+ eax , ebx , ecx , edx , si , di );
187+ }
188+
189+ return ecx ;
190+ }
191+
192+ /**
193+ * vmw_port_hb_in - Receive the message payload either through the
194+ * high-bandwidth port if available, or through the backdoor otherwise.
195+ * @channel: The rpc channel.
196+ * @reply: Pointer to buffer holding reply.
197+ * @reply_len: Length of the reply.
198+ * @hb: Whether the high-bandwidth port is available.
199+ *
200+ * Return: The port status.
201+ */
202+ static unsigned long vmw_port_hb_in (struct rpc_channel * channel , char * reply ,
203+ unsigned long reply_len , bool hb )
204+ {
205+ unsigned long si , di , eax , ebx , ecx , edx ;
206+
207+ if (hb ) {
208+ unsigned long bp = channel -> cookie_low ;
209+
210+ si = channel -> cookie_high ;
211+ di = (uintptr_t ) reply ;
212+
213+ VMW_PORT_HB_IN (
214+ (MESSAGE_STATUS_SUCCESS << 16 ) | VMW_PORT_CMD_HB_MSG ,
215+ reply_len , si , di ,
216+ VMW_HYPERVISOR_HB_PORT | (channel -> channel_id << 16 ),
217+ VMW_HYPERVISOR_MAGIC , bp ,
218+ eax , ebx , ecx , edx , si , di );
219+
220+ return ebx ;
221+ }
222+
223+ /* HB port not available. Retrieve the message 4 bytes at a time. */
224+ ecx = MESSAGE_STATUS_SUCCESS << 16 ;
225+ while (reply_len ) {
226+ unsigned int bytes = min_t (unsigned long , reply_len , 4 );
227+
228+ si = channel -> cookie_high ;
229+ di = channel -> cookie_low ;
230+
231+ VMW_PORT (VMW_PORT_CMD_MSG | (MSG_TYPE_RECVPAYLOAD << 16 ),
232+ MESSAGE_STATUS_SUCCESS , si , di ,
233+ VMW_HYPERVISOR_PORT | (channel -> channel_id << 16 ),
234+ VMW_HYPERVISOR_MAGIC ,
235+ eax , ebx , ecx , edx , si , di );
236+
237+ if ((HIGH_WORD (ecx ) & MESSAGE_STATUS_SUCCESS ) == 0 )
238+ break ;
239+
240+ memcpy (reply , & ebx , bytes );
241+ reply_len -= bytes ;
242+ reply += bytes ;
243+ }
244+
245+ return ecx ;
246+ }
139247
140248
141249/**
@@ -148,11 +256,10 @@ static int vmw_close_channel(struct rpc_channel *channel)
148256 */
149257static int vmw_send_msg (struct rpc_channel * channel , const char * msg )
150258{
151- unsigned long eax , ebx , ecx , edx , si , di , bp ;
259+ unsigned long eax , ebx , ecx , edx , si , di ;
152260 size_t msg_len = strlen (msg );
153261 int retries = 0 ;
154262
155-
156263 while (retries < RETRIES ) {
157264 retries ++ ;
158265
@@ -166,23 +273,14 @@ static int vmw_send_msg(struct rpc_channel *channel, const char *msg)
166273 VMW_HYPERVISOR_MAGIC ,
167274 eax , ebx , ecx , edx , si , di );
168275
169- if ((HIGH_WORD (ecx ) & MESSAGE_STATUS_SUCCESS ) == 0 ||
170- (HIGH_WORD (ecx ) & MESSAGE_STATUS_HB ) == 0 ) {
171- /* Expected success + high-bandwidth. Give up. */
276+ if ((HIGH_WORD (ecx ) & MESSAGE_STATUS_SUCCESS ) == 0 ) {
277+ /* Expected success. Give up. */
172278 return - EINVAL ;
173279 }
174280
175281 /* Send msg */
176- si = (uintptr_t ) msg ;
177- di = channel -> cookie_low ;
178- bp = channel -> cookie_high ;
179-
180- VMW_PORT_HB_OUT (
181- (MESSAGE_STATUS_SUCCESS << 16 ) | VMW_PORT_CMD_HB_MSG ,
182- msg_len , si , di ,
183- VMW_HYPERVISOR_HB_PORT | (channel -> channel_id << 16 ),
184- VMW_HYPERVISOR_MAGIC , bp ,
185- eax , ebx , ecx , edx , si , di );
282+ ebx = vmw_port_hb_out (channel , msg ,
283+ !!(HIGH_WORD (ecx ) & MESSAGE_STATUS_HB ));
186284
187285 if ((HIGH_WORD (ebx ) & MESSAGE_STATUS_SUCCESS ) != 0 ) {
188286 return 0 ;
@@ -211,7 +309,7 @@ STACK_FRAME_NON_STANDARD(vmw_send_msg);
211309static int vmw_recv_msg (struct rpc_channel * channel , void * * msg ,
212310 size_t * msg_len )
213311{
214- unsigned long eax , ebx , ecx , edx , si , di , bp ;
312+ unsigned long eax , ebx , ecx , edx , si , di ;
215313 char * reply ;
216314 size_t reply_len ;
217315 int retries = 0 ;
@@ -233,8 +331,7 @@ static int vmw_recv_msg(struct rpc_channel *channel, void **msg,
233331 VMW_HYPERVISOR_MAGIC ,
234332 eax , ebx , ecx , edx , si , di );
235333
236- if ((HIGH_WORD (ecx ) & MESSAGE_STATUS_SUCCESS ) == 0 ||
237- (HIGH_WORD (ecx ) & MESSAGE_STATUS_HB ) == 0 ) {
334+ if ((HIGH_WORD (ecx ) & MESSAGE_STATUS_SUCCESS ) == 0 ) {
238335 DRM_ERROR ("Failed to get reply size for host message.\n" );
239336 return - EINVAL ;
240337 }
@@ -252,17 +349,8 @@ static int vmw_recv_msg(struct rpc_channel *channel, void **msg,
252349
253350
254351 /* Receive buffer */
255- si = channel -> cookie_high ;
256- di = (uintptr_t ) reply ;
257- bp = channel -> cookie_low ;
258-
259- VMW_PORT_HB_IN (
260- (MESSAGE_STATUS_SUCCESS << 16 ) | VMW_PORT_CMD_HB_MSG ,
261- reply_len , si , di ,
262- VMW_HYPERVISOR_HB_PORT | (channel -> channel_id << 16 ),
263- VMW_HYPERVISOR_MAGIC , bp ,
264- eax , ebx , ecx , edx , si , di );
265-
352+ ebx = vmw_port_hb_in (channel , reply , reply_len ,
353+ !!(HIGH_WORD (ecx ) & MESSAGE_STATUS_HB ));
266354 if ((HIGH_WORD (ebx ) & MESSAGE_STATUS_SUCCESS ) == 0 ) {
267355 kfree (reply );
268356
0 commit comments