#define DIGITAL_DID_MAX        14
 
-#define DIGITAL_LR_BITS_PAYLOAD_SIZE_254B 0x30
-#define DIGITAL_FSL_BITS_PAYLOAD_SIZE_254B \
-                               (DIGITAL_LR_BITS_PAYLOAD_SIZE_254B >> 4)
+#define DIGITAL_PAYLOAD_SIZE_MAX       254
+#define DIGITAL_PAYLOAD_BITS_TO_PP(s)  (((s) & 0x3) << 4)
+#define DIGITAL_PAYLOAD_PP_TO_BITS(s)  (((s) >> 4) & 0x3)
+#define DIGITAL_PAYLOAD_BITS_TO_FSL(s) ((s) & 0x3)
+#define DIGITAL_PAYLOAD_FSL_TO_BITS(s) ((s) & 0x3)
+
 #define DIGITAL_GB_BIT 0x02
 
 #define DIGITAL_NFC_DEP_PFB_TYPE(pfb) ((pfb) & 0xE0)
 static void digital_in_recv_dep_res(struct nfc_digital_dev *ddev, void *arg,
                                    struct sk_buff *resp);
 
+static const u8 digital_payload_bits_map[4] = {
+       [0] = 64,
+       [1] = 128,
+       [2] = 192,
+       [3] = 254
+};
+
+static u8 digital_payload_bits_to_size(u8 payload_bits)
+{
+       if (payload_bits >= ARRAY_SIZE(digital_payload_bits_map))
+               return 0;
+
+       return digital_payload_bits_map[payload_bits];
+}
+
+static u8 digital_payload_size_to_bits(u8 payload_size)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(digital_payload_bits_map); i++)
+               if (digital_payload_bits_map[i] == payload_size)
+                       return i;
+
+       return 0xff;
+}
+
 static void digital_skb_push_dep_sod(struct nfc_digital_dev *ddev,
                                     struct sk_buff *skb)
 {
        struct sk_buff *skb;
        struct digital_psl_req *psl_req;
        int rc;
+       u8 payload_size, payload_bits;
 
        skb = digital_skb_alloc(ddev, sizeof(*psl_req));
        if (!skb)
        psl_req->cmd = DIGITAL_CMD_PSL_REQ;
        psl_req->did = 0;
        psl_req->brs = (0x2 << 3) | 0x2; /* 424F both directions */
-       psl_req->fsl = DIGITAL_FSL_BITS_PAYLOAD_SIZE_254B;
+
+       payload_size = min(ddev->local_payload_max, ddev->remote_payload_max);
+       payload_bits = digital_payload_size_to_bits(payload_size);
+       psl_req->fsl = DIGITAL_PAYLOAD_BITS_TO_FSL(payload_bits);
+
+       ddev->local_payload_max = payload_size;
+       ddev->remote_payload_max = payload_size;
 
        digital_skb_push_dep_sod(ddev, skb);
 
 {
        struct nfc_target *target = arg;
        struct digital_atr_res *atr_res;
-       u8 gb_len;
+       u8 gb_len, payload_bits;
        int rc;
 
        if (IS_ERR(resp)) {
 
        atr_res = (struct digital_atr_res *)resp->data;
 
+       payload_bits = DIGITAL_PAYLOAD_PP_TO_BITS(atr_res->pp);
+       ddev->remote_payload_max = digital_payload_bits_to_size(payload_bits);
+
+       if (!ddev->remote_payload_max) {
+               rc = -EINVAL;
+               goto exit;
+       }
+
        rc = nfc_set_remote_general_bytes(ddev->nfc_dev, atr_res->gb, gb_len);
        if (rc)
                goto exit;
        struct digital_atr_req *atr_req;
        uint size;
        int rc;
+       u8 payload_bits;
 
        size = DIGITAL_ATR_REQ_MIN_SIZE + gb_len;
 
        atr_req->bs = 0;
        atr_req->br = 0;
 
-       atr_req->pp = DIGITAL_LR_BITS_PAYLOAD_SIZE_254B;
+       ddev->local_payload_max = DIGITAL_PAYLOAD_SIZE_MAX;
+       payload_bits = digital_payload_size_to_bits(ddev->local_payload_max);
+       atr_req->pp = DIGITAL_PAYLOAD_BITS_TO_PP(payload_bits);
 
        if (gb_len) {
                atr_req->pp |= DIGITAL_GB_BIT;
                goto exit;
        }
 
+       if (resp->len > ddev->local_payload_max) {
+               rc = -EMSGSIZE;
+               goto exit;
+       }
+
        size = sizeof(struct digital_dep_req_res);
        dep_res = (struct digital_dep_req_res *)resp->data;
 
 
        skb_push(skb, sizeof(struct digital_dep_req_res));
 
+       if (skb->len > ddev->remote_payload_max)
+               return -EMSGSIZE;
+
        dep_req = (struct digital_dep_req_res *)skb->data;
        dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
        dep_req->cmd = DIGITAL_CMD_DEP_REQ;
                goto exit;
        }
 
+       if (resp->len > ddev->local_payload_max) {
+               rc = -EMSGSIZE;
+               goto exit;
+       }
+
        size = sizeof(struct digital_dep_req_res);
        dep_req = (struct digital_dep_req_res *)resp->data;
 
        struct digital_dep_req_res *dep_res;
 
        skb_push(skb, sizeof(struct digital_dep_req_res));
+
+       if (skb->len > ddev->remote_payload_max)
+               return -EMSGSIZE;
+
        dep_res = (struct digital_dep_req_res *)skb->data;
 
        dep_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
        int rc;
        struct digital_psl_req *psl_req;
        u8 rf_tech;
-       u8 dsi;
+       u8 dsi, payload_size, payload_bits;
 
        if (IS_ERR(resp)) {
                rc = PTR_ERR(resp);
                goto exit;
        }
 
+       payload_bits = DIGITAL_PAYLOAD_FSL_TO_BITS(psl_req->fsl);
+       payload_size = digital_payload_bits_to_size(payload_bits);
+
+       if (!payload_size || (payload_size > min(ddev->local_payload_max,
+                                                ddev->remote_payload_max))) {
+               rc = -EINVAL;
+               goto exit;
+       }
+
+       ddev->local_payload_max = payload_size;
+       ddev->remote_payload_max = payload_size;
+
        rc = digital_tg_send_psl_res(ddev, psl_req->did, rf_tech);
 
 exit:
 {
        struct digital_atr_res *atr_res;
        struct sk_buff *skb;
-       u8 *gb;
+       u8 *gb, payload_bits;
        size_t gb_len;
        int rc;
 
        atr_res->cmd = DIGITAL_CMD_ATR_RES;
        memcpy(atr_res->nfcid3, atr_req->nfcid3, sizeof(atr_req->nfcid3));
        atr_res->to = 8;
-       atr_res->pp = DIGITAL_LR_BITS_PAYLOAD_SIZE_254B;
+
+       ddev->local_payload_max = DIGITAL_PAYLOAD_SIZE_MAX;
+       payload_bits = digital_payload_size_to_bits(ddev->local_payload_max);
+       atr_res->pp = DIGITAL_PAYLOAD_BITS_TO_PP(payload_bits);
+
        if (gb_len) {
                skb_put(skb, gb_len);
 
        int rc;
        struct digital_atr_req *atr_req;
        size_t gb_len, min_size;
-       u8 poll_tech_count;
+       u8 poll_tech_count, payload_bits;
 
        if (IS_ERR(resp)) {
                rc = PTR_ERR(resp);
                goto exit;
        }
 
+       payload_bits = DIGITAL_PAYLOAD_PP_TO_BITS(atr_req->pp);
+       ddev->remote_payload_max = digital_payload_bits_to_size(payload_bits);
+
+       if (!ddev->remote_payload_max) {
+               rc = -EINVAL;
+               goto exit;
+       }
+
        ddev->did = atr_req->did;
 
        rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,