char    data[ETHTOOL_FLASH_MAX_FILENAME];
 };
 
+/**
+ * struct ethtool_dump - used for retrieving, setting device dump
+ * @cmd: Command number - %ETHTOOL_GET_DUMP_FLAG, %ETHTOOL_GET_DUMP_DATA, or
+ *     %ETHTOOL_SET_DUMP
+ * @version: FW version of the dump, filled in by driver
+ * @flag: driver dependent flag for dump setting, filled in by driver during
+ *       get and filled in by ethtool for set operation
+ * @len: length of dump data, used as the length of the user buffer on entry to
+ *      %ETHTOOL_GET_DUMP_DATA and this is returned as dump length by driver
+ *      for %ETHTOOL_GET_DUMP_FLAG command
+ * @data: data collected for get dump data operation
+ */
+struct ethtool_dump {
+       __u32   cmd;
+       __u32   version;
+       __u32   flag;
+       __u32   len;
+       __u8    data[0];
+};
+
 /* for returning and changing feature sets */
 
 /**
  * @get_channels: Get number of channels.
  * @set_channels: Set number of channels.  Returns a negative error code or
  *     zero.
+ * @get_dump_flag: Get dump flag indicating current dump length, version,
+ *                and flag of the device.
+ * @get_dump_data: Get dump data.
+ * @set_dump: Set dump specific flags to the device.
  *
  * All operations are optional (i.e. the function pointer may be set
  * to %NULL) and callers must take this into account.  Callers must
                                  const struct ethtool_rxfh_indir *);
        void    (*get_channels)(struct net_device *, struct ethtool_channels *);
        int     (*set_channels)(struct net_device *, struct ethtool_channels *);
+       int     (*get_dump_flag)(struct net_device *, struct ethtool_dump *);
+       int     (*get_dump_data)(struct net_device *,
+                                struct ethtool_dump *, void *);
+       int     (*set_dump)(struct net_device *, struct ethtool_dump *);
 
 };
 #endif /* __KERNEL__ */
 #define ETHTOOL_SFEATURES      0x0000003b /* Change device offload settings */
 #define ETHTOOL_GCHANNELS      0x0000003c /* Get no of channels */
 #define ETHTOOL_SCHANNELS      0x0000003d /* Set no of channels */
+#define ETHTOOL_SET_DUMP       0x0000003e /* Set dump settings */
+#define ETHTOOL_GET_DUMP_FLAG  0x0000003f /* Get dump settings */
+#define ETHTOOL_GET_DUMP_DATA  0x00000040 /* Get dump data */
 
 /* compatibility with older code */
 #define SPARC_ETH_GSET         ETHTOOL_GSET
 
        return dev->ethtool_ops->flash_device(dev, &efl);
 }
 
+static int ethtool_set_dump(struct net_device *dev,
+                       void __user *useraddr)
+{
+       struct ethtool_dump dump;
+
+       if (!dev->ethtool_ops->set_dump)
+               return -EOPNOTSUPP;
+
+       if (copy_from_user(&dump, useraddr, sizeof(dump)))
+               return -EFAULT;
+
+       return dev->ethtool_ops->set_dump(dev, &dump);
+}
+
+static int ethtool_get_dump_flag(struct net_device *dev,
+                               void __user *useraddr)
+{
+       int ret;
+       struct ethtool_dump dump;
+       const struct ethtool_ops *ops = dev->ethtool_ops;
+
+       if (!dev->ethtool_ops->get_dump_flag)
+               return -EOPNOTSUPP;
+
+       if (copy_from_user(&dump, useraddr, sizeof(dump)))
+               return -EFAULT;
+
+       ret = ops->get_dump_flag(dev, &dump);
+       if (ret)
+               return ret;
+
+       if (copy_to_user(useraddr, &dump, sizeof(dump)))
+               return -EFAULT;
+       return 0;
+}
+
+static int ethtool_get_dump_data(struct net_device *dev,
+                               void __user *useraddr)
+{
+       int ret;
+       __u32 len;
+       struct ethtool_dump dump, tmp;
+       const struct ethtool_ops *ops = dev->ethtool_ops;
+       void *data = NULL;
+
+       if (!dev->ethtool_ops->get_dump_data ||
+               !dev->ethtool_ops->get_dump_flag)
+               return -EOPNOTSUPP;
+
+       if (copy_from_user(&dump, useraddr, sizeof(dump)))
+               return -EFAULT;
+
+       memset(&tmp, 0, sizeof(tmp));
+       tmp.cmd = ETHTOOL_GET_DUMP_FLAG;
+       ret = ops->get_dump_flag(dev, &tmp);
+       if (ret)
+               return ret;
+
+       len = (tmp.len > dump.len) ? dump.len : tmp.len;
+       if (!len)
+               return -EFAULT;
+
+       data = vzalloc(tmp.len);
+       if (!data)
+               return -ENOMEM;
+       ret = ops->get_dump_data(dev, &dump, data);
+       if (ret)
+               goto out;
+
+       if (copy_to_user(useraddr, &dump, sizeof(dump))) {
+               ret = -EFAULT;
+               goto out;
+       }
+       useraddr += offsetof(struct ethtool_dump, data);
+       if (copy_to_user(useraddr, data, len))
+               ret = -EFAULT;
+out:
+       vfree(data);
+       return ret;
+}
+
 /* The main entry point in this file.  Called from net/core/dev.c */
 
 int dev_ethtool(struct net *net, struct ifreq *ifr)
        case ETHTOOL_SCHANNELS:
                rc = ethtool_set_channels(dev, useraddr);
                break;
+       case ETHTOOL_SET_DUMP:
+               rc = ethtool_set_dump(dev, useraddr);
+               break;
+       case ETHTOOL_GET_DUMP_FLAG:
+               rc = ethtool_get_dump_flag(dev, useraddr);
+               break;
+       case ETHTOOL_GET_DUMP_DATA:
+               rc = ethtool_get_dump_data(dev, useraddr);
+               break;
        default:
                rc = -EOPNOTSUPP;
        }