/* ISO 15765-2:2016 supports more than 4095 byte per ISO PDU as the FF_DL can
  * take full 32 bit values (4 Gbyte). We would need some good concept to handle
- * this between user space and kernel space. For now increase the static buffer
- * to something about 64 kbyte to be able to test this new functionality.
+ * this between user space and kernel space. For now set the static buffer to
+ * something about 8 kbyte to be able to test this new functionality.
  */
-#define MAX_MSG_LENGTH 66000
+#define DEFAULT_MAX_PDU_SIZE 8300
+
+/* maximum PDU size before ISO 15765-2:2016 extension was 4095 */
+#define MAX_12BIT_PDU_SIZE 4095
+
+/* limit the isotp pdu size from the optional module parameter to 1MByte */
+#define MAX_PDU_SIZE (1025 * 1024U)
+
+static unsigned int max_pdu_size __read_mostly = DEFAULT_MAX_PDU_SIZE;
+module_param(max_pdu_size, uint, 0444);
+MODULE_PARM_DESC(max_pdu_size, "maximum isotp pdu size (default "
+                __stringify(DEFAULT_MAX_PDU_SIZE) ")");
 
 /* N_PCI type values in bits 7-4 of N_PCI bytes */
 #define N_PCI_SF 0x00  /* single frame */
 };
 
 struct tpcon {
-       unsigned int idx;
+       u8 *buf;
+       unsigned int buflen;
        unsigned int len;
+       unsigned int idx;
        u32 state;
        u8 bs;
        u8 sn;
        u8 ll_dl;
-       u8 buf[MAX_MSG_LENGTH + 1];
+       u8 sbuf[DEFAULT_MAX_PDU_SIZE];
 };
 
 struct isotp_sock {
        if (so->rx.len + ae + off + ff_pci_sz < so->rx.ll_dl)
                return 1;
 
-       if (so->rx.len > MAX_MSG_LENGTH) {
+       /* PDU size > default => try max_pdu_size */
+       if (so->rx.len > so->rx.buflen && so->rx.buflen < max_pdu_size) {
+               u8 *newbuf = kmalloc(max_pdu_size, GFP_ATOMIC);
+
+               if (newbuf) {
+                       so->rx.buf = newbuf;
+                       so->rx.buflen = max_pdu_size;
+               }
+       }
+
+       if (so->rx.len > so->rx.buflen) {
                /* send FC frame with overflow status */
                isotp_send_fc(sk, ae, ISOTP_FC_OVFLW);
                return 1;
                cf->data[0] = so->opt.ext_address;
 
        /* create N_PCI bytes with 12/32 bit FF_DL data length */
-       if (so->tx.len > 4095) {
+       if (so->tx.len > MAX_12BIT_PDU_SIZE) {
                /* use 32 bit FF_DL notation */
                cf->data[ae] = N_PCI_FF;
                cf->data[ae + 1] = 0;
                so->tx.state = ISOTP_SENDING;
        }
 
-       if (!size || size > MAX_MSG_LENGTH) {
+       /* PDU size > default => try max_pdu_size */
+       if (size > so->tx.buflen && so->tx.buflen < max_pdu_size) {
+               u8 *newbuf = kmalloc(max_pdu_size, GFP_KERNEL);
+
+               if (newbuf) {
+                       so->tx.buf = newbuf;
+                       so->tx.buflen = max_pdu_size;
+               }
+       }
+
+       if (!size || size > so->tx.buflen) {
                err = -EINVAL;
                goto err_out_drop;
        }
        so->ifindex = 0;
        so->bound = 0;
 
+       if (so->rx.buf != so->rx.sbuf)
+               kfree(so->rx.buf);
+
+       if (so->tx.buf != so->tx.sbuf)
+               kfree(so->tx.buf);
+
        sock_orphan(sk);
        sock->sk = NULL;
 
        so->rx.state = ISOTP_IDLE;
        so->tx.state = ISOTP_IDLE;
 
+       so->rx.buf = so->rx.sbuf;
+       so->tx.buf = so->tx.sbuf;
+       so->rx.buflen = ARRAY_SIZE(so->rx.sbuf);
+       so->tx.buflen = ARRAY_SIZE(so->tx.sbuf);
+
        hrtimer_init(&so->rxtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT);
        so->rxtimer.function = isotp_rx_timer_handler;
        hrtimer_init(&so->txtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT);
 {
        int err;
 
-       pr_info("can: isotp protocol\n");
+       max_pdu_size = max_t(unsigned int, max_pdu_size, MAX_12BIT_PDU_SIZE);
+       max_pdu_size = min_t(unsigned int, max_pdu_size, MAX_PDU_SIZE);
+
+       pr_info("can: isotp protocol (max_pdu_size %d)\n", max_pdu_size);
 
        err = can_proto_register(&isotp_can_proto);
        if (err < 0)