#include <linux/types.h>
 #include <linux/if_ether.h>
+#include <linux/in6.h>
 #include <asm/byteorder.h>
 
 /**
        return 0;
 }
 
+/**
+ * efx_filter_set_ipv6_local - specify IPv6 host, transport protocol and port
+ * @spec: Specification to initialise
+ * @proto: Transport layer protocol number
+ * @host: Local host address (network byte order)
+ * @port: Local port (network byte order)
+ */
+static inline int
+efx_filter_set_ipv6_local(struct efx_filter_spec *spec, u8 proto,
+                         const struct in6_addr *host, __be16 port)
+{
+       spec->match_flags |=
+               EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
+               EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT;
+       spec->ether_type = htons(ETH_P_IPV6);
+       spec->ip_proto = proto;
+       memcpy(spec->loc_host, host, sizeof(spec->loc_host));
+       spec->loc_port = port;
+       return 0;
+}
+
 /**
  * efx_filter_set_ipv4_full - specify IPv4 hosts, transport protocol and ports
  * @spec: Specification to initialise
 
 
 #define        PTP_MIN_LENGTH          63
 
-#define PTP_RXFILTERS_LEN      2
+#define PTP_RXFILTERS_LEN      4
 
-#define PTP_ADDRESS            0xe0000181      /* 224.0.1.129 */
+#define PTP_ADDR_IPV4          0xe0000181      /* 224.0.1.129 */
+#define PTP_ADDR_IPV6          {0xff, 0x0e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
+                               0, 0x01, 0x81}  /* ff0e::181 */
 #define PTP_EVENT_PORT         319
 #define PTP_GENERAL_PORT       320
 
        }
 }
 
-static int efx_ptp_insert_ipv4_filter(struct efx_nic *efx, u16 port)
+static void efx_ptp_init_filter(struct efx_nic *efx,
+                               struct efx_filter_spec *rxfilter)
 {
-       struct efx_ptp_data *ptp = efx->ptp_data;
-       struct efx_filter_spec rxfilter;
-       int rc;
+       struct efx_channel *channel = efx->ptp_data->channel;
+       struct efx_rx_queue *queue = efx_channel_get_rx_queue(channel);
 
-       efx_filter_init_rx(&rxfilter, EFX_FILTER_PRI_REQUIRED, 0,
-                          efx_rx_queue_index(
-                                  efx_channel_get_rx_queue(ptp->channel)));
+       efx_filter_init_rx(rxfilter, EFX_FILTER_PRI_REQUIRED, 0,
+                          efx_rx_queue_index(queue));
+}
 
-       efx_filter_set_ipv4_local(&rxfilter, IPPROTO_UDP, htonl(PTP_ADDRESS),
-                                 htons(port));
+static int efx_ptp_insert_filter(struct efx_nic *efx,
+                                struct efx_filter_spec *rxfilter)
+{
+       struct efx_ptp_data *ptp = efx->ptp_data;
 
-       rc = efx_filter_insert_filter(efx, &rxfilter, true);
+       int rc = efx_filter_insert_filter(efx, rxfilter, true);
        if (rc < 0)
                return rc;
        ptp->rxfilters[ptp->rxfilters_count] = rc;
        return 0;
 }
 
+static int efx_ptp_insert_ipv4_filter(struct efx_nic *efx, u16 port)
+{
+       struct efx_filter_spec rxfilter;
+
+       efx_ptp_init_filter(efx, &rxfilter);
+       efx_filter_set_ipv4_local(&rxfilter, IPPROTO_UDP, htonl(PTP_ADDR_IPV4),
+                                 htons(port));
+       return efx_ptp_insert_filter(efx, &rxfilter);
+}
+
+static int efx_ptp_insert_ipv6_filter(struct efx_nic *efx, u16 port)
+{
+       const struct in6_addr addr = {{PTP_ADDR_IPV6}};
+       struct efx_filter_spec rxfilter;
+
+       efx_ptp_init_filter(efx, &rxfilter);
+       efx_filter_set_ipv6_local(&rxfilter, IPPROTO_UDP, &addr, htons(port));
+       return efx_ptp_insert_filter(efx, &rxfilter);
+}
+
 static int efx_ptp_insert_multicast_filters(struct efx_nic *efx)
 {
        struct efx_ptp_data *ptp = efx->ptp_data;
        if (rc < 0)
                goto fail;
 
+       /* if the NIC supports hw timestamps by the MAC, we can support
+        * PTP over IPv6
+        */
+       if (efx_ptp_use_mac_tx_timestamps(efx)) {
+               rc = efx_ptp_insert_ipv6_filter(efx, PTP_EVENT_PORT);
+               if (rc < 0)
+                       goto fail;
+
+               rc = efx_ptp_insert_ipv6_filter(efx, PTP_GENERAL_PORT);
+               if (rc < 0)
+                       goto fail;
+       }
+
        return 0;
 
 fail: