__u32                           rule_locs[0];
 };
 
+struct ethtool_rxfh_indir {
+       __u32   cmd;
+       /* On entry, this is the array size of the user buffer.  On
+        * return from ETHTOOL_GRXFHINDIR, this is the array size of
+        * the hardware indirection table. */
+       __u32   size;
+       __u32   ring_index[0];  /* ring/queue index for each hash value */
+};
+
 struct ethtool_rx_ntuple_flow_spec {
        __u32            flow_type;
        union {
        int     (*set_rx_ntuple)(struct net_device *,
                                 struct ethtool_rx_ntuple *);
        int     (*get_rx_ntuple)(struct net_device *, u32 stringset, void *);
+       int     (*get_rxfh_indir)(struct net_device *,
+                                 struct ethtool_rxfh_indir *);
+       int     (*set_rxfh_indir)(struct net_device *,
+                                 const struct ethtool_rxfh_indir *);
 };
 #endif /* __KERNEL__ */
 
 #define ETHTOOL_SRXNTUPLE      0x00000035 /* Add an n-tuple filter to device */
 #define ETHTOOL_GRXNTUPLE      0x00000036 /* Get n-tuple filters from device */
 #define ETHTOOL_GSSET_INFO     0x00000037 /* Get string set info */
+#define ETHTOOL_GRXFHINDIR     0x00000038 /* Get RX flow hash indir'n table */
+#define ETHTOOL_SRXFHINDIR     0x00000039 /* Set RX flow hash indir'n table */
 
 /* compatibility with older code */
 #define SPARC_ETH_GSET         ETHTOOL_GSET
 
        return ret;
 }
 
+static noinline_for_stack int ethtool_get_rxfh_indir(struct net_device *dev,
+                                                    void __user *useraddr)
+{
+       struct ethtool_rxfh_indir *indir;
+       u32 table_size;
+       size_t full_size;
+       int ret;
+
+       if (!dev->ethtool_ops->get_rxfh_indir)
+               return -EOPNOTSUPP;
+
+       if (copy_from_user(&table_size,
+                          useraddr + offsetof(struct ethtool_rxfh_indir, size),
+                          sizeof(table_size)))
+               return -EFAULT;
+
+       if (table_size >
+           (KMALLOC_MAX_SIZE - sizeof(*indir)) / sizeof(*indir->ring_index))
+               return -ENOMEM;
+       full_size = sizeof(*indir) + sizeof(*indir->ring_index) * table_size;
+       indir = kmalloc(full_size, GFP_USER);
+       if (!indir)
+               return -ENOMEM;
+
+       indir->cmd = ETHTOOL_GRXFHINDIR;
+       indir->size = table_size;
+       ret = dev->ethtool_ops->get_rxfh_indir(dev, indir);
+       if (ret)
+               goto out;
+
+       if (copy_to_user(useraddr, indir, full_size))
+               ret = -EFAULT;
+
+out:
+       kfree(indir);
+       return ret;
+}
+
+static noinline_for_stack int ethtool_set_rxfh_indir(struct net_device *dev,
+                                                    void __user *useraddr)
+{
+       struct ethtool_rxfh_indir *indir;
+       u32 table_size;
+       size_t full_size;
+       int ret;
+
+       if (!dev->ethtool_ops->set_rxfh_indir)
+               return -EOPNOTSUPP;
+
+       if (copy_from_user(&table_size,
+                          useraddr + offsetof(struct ethtool_rxfh_indir, size),
+                          sizeof(table_size)))
+               return -EFAULT;
+
+       if (table_size >
+           (KMALLOC_MAX_SIZE - sizeof(*indir)) / sizeof(*indir->ring_index))
+               return -ENOMEM;
+       full_size = sizeof(*indir) + sizeof(*indir->ring_index) * table_size;
+       indir = kmalloc(full_size, GFP_USER);
+       if (!indir)
+               return -ENOMEM;
+
+       if (copy_from_user(indir, useraddr, full_size)) {
+               ret = -EFAULT;
+               goto out;
+       }
+
+       ret = dev->ethtool_ops->set_rxfh_indir(dev, indir);
+
+out:
+       kfree(indir);
+       return ret;
+}
+
 static void __rx_ntuple_filter_add(struct ethtool_rx_ntuple_list *list,
                        struct ethtool_rx_ntuple_flow_spec *spec,
                        struct ethtool_rx_ntuple_flow_spec_container *fsc)
        case ETHTOOL_GSSET_INFO:
                rc = ethtool_get_sset_info(dev, useraddr);
                break;
+       case ETHTOOL_GRXFHINDIR:
+               rc = ethtool_get_rxfh_indir(dev, useraddr);
+               break;
+       case ETHTOOL_SRXFHINDIR:
+               rc = ethtool_set_rxfh_indir(dev, useraddr);
+               break;
        default:
                rc = -EOPNOTSUPP;
        }