@@ -53,18 +53,20 @@ struct ap_queue_status {
5353 */
5454static inline bool ap_instructions_available (void )
5555{
56- register unsigned long reg0 asm ("0" ) = AP_MKQID (0 , 0 );
57- register unsigned long reg1 asm ("1" ) = 0 ;
58- register unsigned long reg2 asm ("2" ) = 0 ;
56+ unsigned long reg0 = AP_MKQID (0 , 0 );
57+ unsigned long reg1 = 0 ;
5958
6059 asm volatile (
61- " .long 0xb2af0000\n" /* PQAP(TAPQ) */
62- "0: la %0,1\n"
60+ " lgr 0,%[reg0]\n" /* qid into gr0 */
61+ " lghi 1,0\n" /* 0 into gr1 */
62+ " lghi 2,0\n" /* 0 into gr2 */
63+ " .long 0xb2af0000\n" /* PQAP(TAPQ) */
64+ "0: la %[reg1],1\n" /* 1 into reg1 */
6365 "1:\n"
6466 EX_TABLE (0b , 1b )
65- : " + d " ( reg1), "+ d " (reg2 )
66- : " d " (reg0)
67- : " cc ");
67+ : [ reg1 ] "+ & d " (reg1 )
68+ : [ reg0 ] "d" (reg0 )
69+ : "cc" , "0" , "1" , "2" );
6870 return reg1 != 0 ;
6971}
7072
@@ -77,14 +79,18 @@ static inline bool ap_instructions_available(void)
7779 */
7880static inline struct ap_queue_status ap_tapq (ap_qid_t qid , unsigned long * info )
7981{
80- register unsigned long reg0 asm ("0" ) = qid ;
81- register struct ap_queue_status reg1 asm ("1" );
82- register unsigned long reg2 asm ("2" );
83-
84- asm volatile (".long 0xb2af0000" /* PQAP(TAPQ) */
85- : "=d" (reg1 ), "=d" (reg2 )
86- : "d" (reg0 )
87- : "cc" );
82+ struct ap_queue_status reg1 ;
83+ unsigned long reg2 ;
84+
85+ asm volatile (
86+ " lgr 0,%[qid]\n" /* qid into gr0 */
87+ " lghi 2,0\n" /* 0 into gr2 */
88+ " .long 0xb2af0000\n" /* PQAP(TAPQ) */
89+ " lgr %[reg1],1\n" /* gr1 (status) into reg1 */
90+ " lgr %[reg2],2\n" /* gr2 into reg2 */
91+ : [reg1 ] "=&d" (reg1 ), [reg2 ] "=&d" (reg2 )
92+ : [qid ] "d" (qid )
93+ : "cc" , "0" , "1" , "2" );
8894 if (info )
8995 * info = reg2 ;
9096 return reg1 ;
@@ -115,14 +121,16 @@ static inline struct ap_queue_status ap_test_queue(ap_qid_t qid,
115121 */
116122static inline struct ap_queue_status ap_rapq (ap_qid_t qid )
117123{
118- register unsigned long reg0 asm ( "0" ) = qid | (1UL << 24 );
119- register struct ap_queue_status reg1 asm ( "1" ) ;
124+ unsigned long reg0 = qid | (1UL << 24 ); /* fc 1UL is RAPQ */
125+ struct ap_queue_status reg1 ;
120126
121127 asm volatile (
122- ".long 0xb2af0000" /* PQAP(RAPQ) */
123- : "=d" (reg1 )
124- : "d" (reg0 )
125- : "cc" );
128+ " lgr 0,%[reg0]\n" /* qid arg into gr0 */
129+ " .long 0xb2af0000\n" /* PQAP(RAPQ) */
130+ " lgr %[reg1],1\n" /* gr1 (status) into reg1 */
131+ : [reg1 ] "=&d" (reg1 )
132+ : [reg0 ] "d" (reg0 )
133+ : "cc" , "0" , "1" );
126134 return reg1 ;
127135}
128136
@@ -134,14 +142,16 @@ static inline struct ap_queue_status ap_rapq(ap_qid_t qid)
134142 */
135143static inline struct ap_queue_status ap_zapq (ap_qid_t qid )
136144{
137- register unsigned long reg0 asm ( "0" ) = qid | (2UL << 24 );
138- register struct ap_queue_status reg1 asm ( "1" ) ;
145+ unsigned long reg0 = qid | (2UL << 24 ); /* fc 2UL is ZAPQ */
146+ struct ap_queue_status reg1 ;
139147
140148 asm volatile (
141- ".long 0xb2af0000" /* PQAP(ZAPQ) */
142- : "=d" (reg1 )
143- : "d" (reg0 )
144- : "cc" );
149+ " lgr 0,%[reg0]\n" /* qid arg into gr0 */
150+ " .long 0xb2af0000\n" /* PQAP(ZAPQ) */
151+ " lgr %[reg1],1\n" /* gr1 (status) into reg1 */
152+ : [reg1 ] "=&d" (reg1 )
153+ : [reg0 ] "d" (reg0 )
154+ : "cc" , "0" , "1" );
145155 return reg1 ;
146156}
147157
@@ -172,18 +182,20 @@ struct ap_config_info {
172182 */
173183static inline int ap_qci (struct ap_config_info * config )
174184{
175- register unsigned long reg0 asm ( "0" ) = 4UL << 24 ;
176- register unsigned long reg1 asm ( "1" ) = - EOPNOTSUPP ;
177- register struct ap_config_info * reg2 asm ( "2" ) = config ;
185+ unsigned long reg0 = 4UL << 24 ; /* fc 4UL is QCI */
186+ unsigned long reg1 = - EOPNOTSUPP ;
187+ struct ap_config_info * reg2 = config ;
178188
179189 asm volatile (
180- ".long 0xb2af0000\n" /* PQAP(QCI) */
181- "0: la %0,0\n"
190+ " lgr 0,%[reg0]\n" /* QCI fc into gr0 */
191+ " lgr 2,%[reg2]\n" /* ptr to config into gr2 */
192+ " .long 0xb2af0000\n" /* PQAP(QCI) */
193+ "0: la %[reg1],0\n" /* good case, QCI fc available */
182194 "1:\n"
183195 EX_TABLE (0b , 1b )
184- : " + d " (reg1)
185- : " d " (reg0), " d " (reg2)
186- : " cc ", " memory ");
196+ : [ reg1 ] " + & d " (reg1)
197+ : [ reg0 ] "d" (reg0 ), [ reg2 ] "d" (reg2 )
198+ : "cc" , "memory" , "0" , "2" );
187199
188200 return reg1 ;
189201}
@@ -220,21 +232,25 @@ static inline struct ap_queue_status ap_aqic(ap_qid_t qid,
220232 struct ap_qirq_ctrl qirqctrl ,
221233 void * ind )
222234{
223- register unsigned long reg0 asm ( "0" ) = qid | (3UL << 24 );
224- register union {
235+ unsigned long reg0 = qid | (3UL << 24 ); /* fc 3UL is AQIC */
236+ union {
225237 unsigned long value ;
226238 struct ap_qirq_ctrl qirqctrl ;
227239 struct ap_queue_status status ;
228- } reg1 asm ( "1" ) ;
229- register void * reg2 asm ( "2" ) = ind ;
240+ } reg1 ;
241+ void * reg2 = ind ;
230242
231243 reg1 .qirqctrl = qirqctrl ;
232244
233245 asm volatile (
234- ".long 0xb2af0000" /* PQAP(AQIC) */
235- : "+d" (reg1 )
236- : "d" (reg0 ), "d" (reg2 )
237- : "cc" );
246+ " lgr 0,%[reg0]\n" /* qid param into gr0 */
247+ " lgr 1,%[reg1]\n" /* irq ctrl into gr1 */
248+ " lgr 2,%[reg2]\n" /* ni addr into gr2 */
249+ " .long 0xb2af0000\n" /* PQAP(AQIC) */
250+ " lgr %[reg1],1\n" /* gr1 (status) into reg1 */
251+ : [reg1 ] "+&d" (reg1 )
252+ : [reg0 ] "d" (reg0 ), [reg2 ] "d" (reg2 )
253+ : "cc" , "0" , "1" , "2" );
238254
239255 return reg1 .status ;
240256}
@@ -268,21 +284,24 @@ union ap_qact_ap_info {
268284static inline struct ap_queue_status ap_qact (ap_qid_t qid , int ifbit ,
269285 union ap_qact_ap_info * apinfo )
270286{
271- register unsigned long reg0 asm ("0" ) = qid | (5UL << 24 )
272- | ((ifbit & 0x01 ) << 22 );
273- register union {
287+ unsigned long reg0 = qid | (5UL << 24 ) | ((ifbit & 0x01 ) << 22 );
288+ union {
274289 unsigned long value ;
275290 struct ap_queue_status status ;
276- } reg1 asm ( "1" ) ;
277- register unsigned long reg2 asm ( "2" ) ;
291+ } reg1 ;
292+ unsigned long reg2 ;
278293
279294 reg1 .value = apinfo -> val ;
280295
281296 asm volatile (
282- ".long 0xb2af0000" /* PQAP(QACT) */
283- : "+d" (reg1 ), "=d" (reg2 )
284- : "d" (reg0 )
285- : "cc" );
297+ " lgr 0,%[reg0]\n" /* qid param into gr0 */
298+ " lgr 1,%[reg1]\n" /* qact in info into gr1 */
299+ " .long 0xb2af0000\n" /* PQAP(QACT) */
300+ " lgr %[reg1],1\n" /* gr1 (status) into reg1 */
301+ " lgr %[reg2],2\n" /* qact out info into reg2 */
302+ : [reg1 ] "+&d" (reg1 ), [reg2 ] "=&d" (reg2 )
303+ : [reg0 ] "d" (reg0 )
304+ : "cc" , "0" , "1" , "2" );
286305 apinfo -> val = reg2 ;
287306 return reg1 .status ;
288307}
@@ -303,19 +322,24 @@ static inline struct ap_queue_status ap_nqap(ap_qid_t qid,
303322 unsigned long long psmid ,
304323 void * msg , size_t length )
305324{
306- register unsigned long reg0 asm ("0" ) = qid | 0x40000000UL ;
307- register struct ap_queue_status reg1 asm ("1" );
308- register unsigned long reg2 asm ("2" ) = (unsigned long) msg ;
309- register unsigned long reg3 asm ("3" ) = (unsigned long) length ;
310- register unsigned long reg4 asm ("4" ) = (unsigned int ) (psmid >> 32 );
311- register unsigned long reg5 asm ("5" ) = psmid & 0xffffffff ;
325+ unsigned long reg0 = qid | 0x40000000UL ; /* 0x4... is last msg part */
326+ union register_pair nqap_r1 , nqap_r2 ;
327+ struct ap_queue_status reg1 ;
328+
329+ nqap_r1 .even = (unsigned int )(psmid >> 32 );
330+ nqap_r1 .odd = psmid & 0xffffffff ;
331+ nqap_r2 .even = (unsigned long )msg ;
332+ nqap_r2 .odd = (unsigned long )length ;
312333
313334 asm volatile (
314- "0: .long 0xb2ad0042\n" /* NQAP */
315- " brc 2,0b"
316- : "+d" (reg0 ), "=d" (reg1 ), "+d" (reg2 ), "+d" (reg3 )
317- : "d" (reg4 ), "d" (reg5 )
318- : "cc" , "memory" );
335+ " lgr 0,%[reg0]\n" /* qid param in gr0 */
336+ "0: .insn rre,0xb2ad0000,%[nqap_r1],%[nqap_r2]\n"
337+ " brc 2,0b\n" /* handle partial completion */
338+ " lgr %[reg1],1\n" /* gr1 (status) into reg1 */
339+ : [reg0 ] "+&d" (reg0 ), [reg1 ] "=&d" (reg1 ),
340+ [nqap_r2 ] "+&d" (nqap_r2 .pair )
341+ : [nqap_r1 ] "d" (nqap_r1 .pair )
342+ : "cc" , "memory" , "0" , "1" );
319343 return reg1 ;
320344}
321345
@@ -325,6 +349,8 @@ static inline struct ap_queue_status ap_nqap(ap_qid_t qid,
325349 * @psmid: Pointer to program supplied message identifier
326350 * @msg: The message text
327351 * @length: The message length
352+ * @reslength: Resitual length on return
353+ * @resgr0: input: gr0 value (only used if != 0), output: resitual gr0 content
328354 *
329355 * Returns AP queue status structure.
330356 * Condition code 1 on DQAP means the receive has taken place
@@ -336,27 +362,65 @@ static inline struct ap_queue_status ap_nqap(ap_qid_t qid,
336362 * Note that gpr2 is used by the DQAP instruction to keep track of
337363 * any 'residual' length, in case the instruction gets interrupted.
338364 * Hence it gets zeroed before the instruction.
365+ * If the message does not fit into the buffer, this function will
366+ * return with a truncated message and the reply in the firmware queue
367+ * is not removed. This is indicated to the caller with an
368+ * ap_queue_status response_code value of all bits on (0xFF) and (if
369+ * the reslength ptr is given) the remaining length is stored in
370+ * *reslength and (if the resgr0 ptr is given) the updated gr0 value
371+ * for further processing of this msg entry is stored in *resgr0. The
372+ * caller needs to detect this situation and should invoke ap_dqap
373+ * with a valid resgr0 ptr and a value in there != 0 to indicate that
374+ * *resgr0 is to be used instead of qid to further process this entry.
339375 */
340376static inline struct ap_queue_status ap_dqap (ap_qid_t qid ,
341377 unsigned long long * psmid ,
342- void * msg , size_t length )
378+ void * msg , size_t length ,
379+ size_t * reslength ,
380+ unsigned long * resgr0 )
343381{
344- register unsigned long reg0 asm("0" ) = qid | 0x80000000UL ;
345- register struct ap_queue_status reg1 asm ("1" );
346- register unsigned long reg2 asm("2" ) = 0UL ;
347- register unsigned long reg4 asm("4" ) = (unsigned long) msg ;
348- register unsigned long reg5 asm("5" ) = (unsigned long) length ;
349- register unsigned long reg6 asm("6" ) = 0UL ;
350- register unsigned long reg7 asm("7" ) = 0UL ;
382+ unsigned long reg0 = resgr0 && * resgr0 ? * resgr0 : qid | 0x80000000UL ;
383+ struct ap_queue_status reg1 ;
384+ unsigned long reg2 ;
385+ union register_pair rp1 , rp2 ;
351386
387+ rp1 .even = 0UL ;
388+ rp1 .odd = 0UL ;
389+ rp2 .even = (unsigned long )msg ;
390+ rp2 .odd = (unsigned long )length ;
352391
353392 asm volatile (
354- "0: .long 0xb2ae0064\n" /* DQAP */
355- " brc 6,0b\n"
356- : "+d" (reg0 ), "=d" (reg1 ), "+d" (reg2 ),
357- "+d" (reg4 ), "+d" (reg5 ), "+d" (reg6 ), "+d" (reg7 )
358- : : "cc" , "memory" );
359- * psmid = (((unsigned long long ) reg6 ) << 32 ) + reg7 ;
393+ " lgr 0,%[reg0]\n" /* qid param into gr0 */
394+ " lghi 2,0\n" /* 0 into gr2 (res length) */
395+ "0: ltgr %N[rp2],%N[rp2]\n" /* check buf len */
396+ " jz 2f\n" /* go out if buf len is 0 */
397+ "1: .insn rre,0xb2ae0000,%[rp1],%[rp2]\n"
398+ " brc 6,0b\n" /* handle partial complete */
399+ "2: lgr %[reg0],0\n" /* gr0 (qid + info) into reg0 */
400+ " lgr %[reg1],1\n" /* gr1 (status) into reg1 */
401+ " lgr %[reg2],2\n" /* gr2 (res length) into reg2 */
402+ : [reg0 ] "+&d" (reg0 ), [reg1 ] "=&d" (reg1 ), [reg2 ] "=&d" (reg2 ),
403+ [rp1 ] "+&d" (rp1 .pair ), [rp2 ] "+&d" (rp2 .pair )
404+ :
405+ : "cc" , "memory" , "0" , "1" , "2" );
406+
407+ if (reslength )
408+ * reslength = reg2 ;
409+ if (reg2 != 0 && rp2 .odd == 0 ) {
410+ /*
411+ * Partially complete, status in gr1 is not set.
412+ * Signal the caller that this dqap is only partially received
413+ * with a special status response code 0xFF and *resgr0 updated
414+ */
415+ reg1 .response_code = 0xFF ;
416+ if (resgr0 )
417+ * resgr0 = reg0 ;
418+ } else {
419+ * psmid = (((unsigned long long )rp1 .even ) << 32 ) + rp1 .odd ;
420+ if (resgr0 )
421+ * resgr0 = 0 ;
422+ }
423+
360424 return reg1 ;
361425}
362426
0 commit comments