summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAjit Khaparde <ajitk@serverengines.com>2009-09-03 08:33:08 +0530
committerJeff Garzik <jgarzik@redhat.com>2009-11-25 09:42:47 -0500
commit9efed0a996f30e1f2d2d33611b209fee6faabc2c (patch)
tree6c733c529a510aff40c5648de56c489e7e49857d
parent0bae92474a3d96070c1235928d0ce821c051583c (diff)
downloadethtool-9efed0a996f30e1f2d2d33611b209fee6faabc2c.tar.gz
ethtool: Add option to flash firmware image from specified file, to a device.
This patch adds a new "-f" option to the ethtool utility to flash a firmware image specified by a file, to a network device. The filename is passed to the network driver which will flash the image on the chip using the request_firmware path. The region "on the chip" to be flashed can be specified by an option. It is up to the device driver to enumerate the region number passed by ethtool, to the region to be flashed. The default behavior is to flash all the regions on the chip. Usage: ethtool -f <interface name> <filename of firmware image> ethtool -f <interface name> <filename of firmware image> [ REGION-NUMBER-TO-FLASH ] Signed-off-by: Ajit Khaparde <ajitk@serverengines.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
-rw-r--r--ethtool-copy.h25
-rw-r--r--ethtool.815
-rw-r--r--ethtool.c55
3 files changed, 91 insertions, 4 deletions
diff --git a/ethtool-copy.h b/ethtool-copy.h
index d9bb957..dc1c089 100644
--- a/ethtool-copy.h
+++ b/ethtool-copy.h
@@ -30,12 +30,13 @@ struct ethtool_cmd {
__u32 maxtxpkt; /* Tx pkts before generating tx int */
__u32 maxrxpkt; /* Rx pkts before generating rx int */
__u16 speed_hi;
- __u16 reserved2;
+ __u8 eth_tp_mdix;
+ __u8 reserved2;
__u32 lp_advertising; /* Features the link partner advertises */
__u32 reserved[2];
};
-static __inline__ void ethtool_cmd_speed_set(struct ethtool_cmd *ep,
+static inline void ethtool_cmd_speed_set(struct ethtool_cmd *ep,
__u32 speed)
{
@@ -43,7 +44,7 @@ static __inline__ void ethtool_cmd_speed_set(struct ethtool_cmd *ep,
ep->speed_hi = (__u16)(speed >> 16);
}
-static __inline__ __u32 ethtool_cmd_speed(struct ethtool_cmd *ep)
+static inline __u32 ethtool_cmd_speed(struct ethtool_cmd *ep)
{
return (ep->speed_hi << 16) | ep->speed;
}
@@ -361,6 +362,18 @@ struct ethtool_rxnfc {
__u32 rule_locs[0];
};
+#define ETHTOOL_FLASH_MAX_FILENAME 128
+enum ethtool_flash_op_type {
+ ETHTOOL_FLASH_ALL_REGIONS = 0,
+};
+
+/* for passing firmware flashing related parameters */
+struct ethtool_flash {
+ __u32 cmd;
+ __u32 region;
+ char data[ETHTOOL_FLASH_MAX_FILENAME];
+};
+
/* CMDs currently supported */
#define ETHTOOL_GSET 0x00000001 /* Get settings. */
@@ -415,6 +428,7 @@ struct ethtool_rxnfc {
#define ETHTOOL_GRXCLSRLALL 0x00000030 /* Get all RX classification rule */
#define ETHTOOL_SRXCLSRLDEL 0x00000031 /* Delete RX classification rule */
#define ETHTOOL_SRXCLSRLINS 0x00000032 /* Insert RX classification rule */
+#define ETHTOOL_FLASHDEV 0x00000033 /* Flash firmware to device */
/* compatibility with older code */
#define SPARC_ETH_GSET ETHTOOL_GSET
@@ -504,6 +518,11 @@ struct ethtool_rxnfc {
#define AUTONEG_DISABLE 0x00
#define AUTONEG_ENABLE 0x01
+/* Mode MDI or MDI-X */
+#define ETH_TP_MDI_INVALID 0x00
+#define ETH_TP_MDI 0x01
+#define ETH_TP_MDI_X 0x02
+
/* Wake-On-Lan options. */
#define WAKE_PHY (1 << 0)
#define WAKE_UCAST (1 << 1)
diff --git a/ethtool.8 b/ethtool.8
index 7a6f52b..8921e45 100644
--- a/ethtool.8
+++ b/ethtool.8
@@ -207,6 +207,11 @@ ethtool \- Display or change ethernet card settings
.I ethX
.RB [ rx-flow-hash \ \*(FL
.RB \ \*(HO]
+
+.B ethtool \-f|\-\-flash
+.I ethX
+.RI FILE
+.RI [ N ]
.SH DESCRIPTION
.BI ethtool
is used for querying settings of an ethernet device and changing them.
@@ -498,6 +503,16 @@ Hash on bytes 2 and 3 of the Layer 4 header of the rx packet.
Discard all packets of this flow type. When this option is set, all other options are ignored.
.PD
.RE
+.TP
+.B \-f \-\-flash \ FILE
+Flash firmware image from the specified file to a region on the adapter.
+By default this will flash all the regions on the adapter.
+.TP
+.B N
+A number to identify flash region where the image should be flashed.
+Default region is 0 which denotes all regions in the flash.
+.PD
+.RE
.SH BUGS
Not supported (in part or whole) on all ethernet drivers.
.SH AUTHOR
diff --git a/ethtool.c b/ethtool.c
index a409e02..52915d6 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -77,6 +77,7 @@ static char *unparse_rxfhashopts(u64 opts);
static int dump_rxfhash(int fhash, u64 val);
static int do_srxclass(int fd, struct ifreq *ifr);
static int do_grxclass(int fd, struct ifreq *ifr);
+static int do_flash(int fd, struct ifreq *ifr);
static int send_ioctl(int fd, struct ifreq *ifr);
static enum {
@@ -101,6 +102,7 @@ static enum {
MODE_GSTATS,
MODE_GNFC,
MODE_SNFC,
+ MODE_FLASHDEV,
} mode = MODE_GSET;
static struct option {
@@ -188,6 +190,9 @@ static struct option {
"options",
" [ rx-flow-hash tcp4|udp4|ah4|sctp4|"
"tcp6|udp6|ah6|sctp6 ]\n" },
+ { "-f", "--flash", MODE_FLASHDEV, "FILENAME " "Flash firmware image "
+ "from the specified file to a region on the device",
+ " [ REGION-NUMBER-TO-FLASH ]\n" },
{ "-N", "--config-nfc", MODE_SNFC, "Configure Rx network flow "
"classification options",
" [ rx-flow-hash tcp4|udp4|ah4|sctp4|"
@@ -304,6 +309,9 @@ static int rx_fhash_get = 0;
static int rx_fhash_set = 0;
static u32 rx_fhash_val = 0;
static int rx_fhash_changed = 0;
+static char *flash_file = NULL;
+static int flash = -1;
+static int flash_region = -1;
static enum {
ONLINE=0,
OFFLINE,
@@ -496,7 +504,8 @@ static void parse_cmdline(int argc, char **argp)
(mode == MODE_GSTATS) ||
(mode == MODE_GNFC) ||
(mode == MODE_SNFC) ||
- (mode == MODE_PHYS_ID)) {
+ (mode == MODE_PHYS_ID) ||
+ (mode == MODE_FLASHDEV)) {
devname = argp[i];
break;
}
@@ -516,6 +525,10 @@ static void parse_cmdline(int argc, char **argp)
if (phys_id_time < 0)
show_usage(1);
break;
+ } else if (mode == MODE_FLASHDEV) {
+ flash_file = argp[i];
+ flash = 1;
+ break;
}
/* fallthrough */
default:
@@ -590,6 +603,12 @@ static void parse_cmdline(int argc, char **argp)
show_usage(1);
break;
}
+ if (mode == MODE_FLASHDEV) {
+ flash_region = strtol(argp[i], NULL, 0);
+ if ((flash_region < 0))
+ show_usage(1);
+ break;
+ }
if (mode == MODE_SNFC) {
if (!strcmp(argp[i], "rx-flow-hash")) {
i += 1;
@@ -1516,6 +1535,8 @@ static int doit(void)
return do_grxclass(fd, &ifr);
} else if (mode == MODE_SNFC) {
return do_srxclass(fd, &ifr);
+ } else if (mode == MODE_FLASHDEV) {
+ return do_flash(fd, &ifr);
}
return 69;
@@ -2410,6 +2431,38 @@ static int do_grxclass(int fd, struct ifreq *ifr)
return 0;
}
+static int do_flash(int fd, struct ifreq *ifr)
+{
+ struct ethtool_flash efl;
+ int err;
+
+ if (flash < 0) {
+ fprintf(stdout, "Missing filename argument\n");
+ show_usage(1);
+ return 98;
+ }
+
+ if (strlen(flash_file) > ETHTOOL_FLASH_MAX_FILENAME - 1) {
+ fprintf(stdout, "Filename too long\n");
+ return 99;
+ }
+
+ efl.cmd = ETHTOOL_FLASHDEV;
+ strcpy(efl.data, flash_file);
+
+ if (flash_region < 0)
+ efl.region = ETHTOOL_FLASH_ALL_REGIONS;
+ else
+ efl.region = flash_region;
+
+ ifr->ifr_data = (caddr_t)&efl;
+ err = send_ioctl(fd, ifr);
+ if (err < 0)
+ perror("Flashing failed");
+
+ return err;
+}
+
static int send_ioctl(int fd, struct ifreq *ifr)
{
return ioctl(fd, SIOCETHTOOL, ifr);