struct ica_xcRB *xcrb,
                                      struct ap_message *ap_msg)
 {
-       int rc;
        struct response_type *rtype = ap_msg->private;
        struct {
                struct type6_hdr hdr;
                struct CPRBX cprbx;
                /* ... more data blocks ... */
        } __packed * msg = ap_msg->msg;
-
-       /*
-        * Set the queue's reply buffer length minus 128 byte padding
-        * as reply limit for the card firmware.
-        */
-       msg->hdr.fromcardlen1 = min_t(unsigned int, msg->hdr.fromcardlen1,
-                                     zq->reply.bufsize - 128);
-       if (msg->hdr.fromcardlen2)
-               msg->hdr.fromcardlen2 =
-                       zq->reply.bufsize - msg->hdr.fromcardlen1 - 128;
+       unsigned int max_payload_size;
+       int rc, delta;
+
+       /* calculate maximum payload for this card and msg type */
+       max_payload_size = zq->reply.bufsize - sizeof(struct type86_fmt2_msg);
+
+       /* limit each of the two from fields to the maximum payload size */
+       msg->hdr.fromcardlen1 = min(msg->hdr.fromcardlen1, max_payload_size);
+       msg->hdr.fromcardlen2 = min(msg->hdr.fromcardlen2, max_payload_size);
+
+       /* calculate delta if the sum of both exceeds max payload size */
+       delta = msg->hdr.fromcardlen1 + msg->hdr.fromcardlen2
+               - max_payload_size;
+       if (delta > 0) {
+               /*
+                * Sum exceeds maximum payload size, prune fromcardlen1
+                * (always trust fromcardlen2)
+                */
+               if (delta > msg->hdr.fromcardlen1) {
+                       rc = -EINVAL;
+                       goto out;
+               }
+               msg->hdr.fromcardlen1 -= delta;
+       }
 
        init_completion(&rtype->work);
        rc = ap_queue_message(zq->queue, ap_msg);