All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next 1/2] asix: Rework reading from EEPROM
@ 2012-07-19 10:23 Christian Riesch
  2012-07-19 10:23 ` [PATCH net-next 2/2] asix: Add support for programming the EEPROM Christian Riesch
  2012-07-19 17:50 ` [PATCH net-next 1/2] asix: Rework reading from EEPROM David Miller
  0 siblings, 2 replies; 4+ messages in thread
From: Christian Riesch @ 2012-07-19 10:23 UTC (permalink / raw)
  To: netdev; +Cc: Allan Chou, Mark Lord, Grant Grundler, Christian Riesch

The current code for reading the EEPROM via ethtool in the asix
driver has a few issues. It cannot handle odd length values
(accesses must be aligned at 16 bit boundaries) and interprets the
offset provided by ethtool as 16 bit word offset instead as byte offset.

The new code for asix_get_eeprom() introduced by this patch is
modeled after the code in
drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c
and provides read access to the entire EEPROM with arbitrary
offsets and lengths.

Signed-off-by: Christian Riesch <christian.riesch@omicron.at>
---
 drivers/net/usb/asix.h         |    5 ++---
 drivers/net/usb/asix_common.c  |   39 ++++++++++++++++++++++-----------------
 drivers/net/usb/asix_devices.c |    9 ---------
 drivers/net/usb/ax88172a.c     |    3 ---
 4 files changed, 24 insertions(+), 32 deletions(-)

diff --git a/drivers/net/usb/asix.h b/drivers/net/usb/asix.h
index 77d9e4c..fbff177 100644
--- a/drivers/net/usb/asix.h
+++ b/drivers/net/usb/asix.h
@@ -156,8 +156,7 @@
 #define AX_GPIO_RSE		0x80	/* Reload serial EEPROM */
 
 #define AX_EEPROM_MAGIC		0xdeadbeef
-#define AX88172_EEPROM_LEN	0x40
-#define AX88772_EEPROM_LEN	0xff
+#define AX_EEPROM_LEN		0x200
 
 /* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */
 struct asix_data {
@@ -165,7 +164,7 @@ struct asix_data {
 	u8 mac_addr[ETH_ALEN];
 	u8 phymode;
 	u8 ledmode;
-	u8 eeprom_len;
+	u8 res;
 };
 
 int asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
diff --git a/drivers/net/usb/asix_common.c b/drivers/net/usb/asix_common.c
index 336f755..0b5b2d3 100644
--- a/drivers/net/usb/asix_common.c
+++ b/drivers/net/usb/asix_common.c
@@ -478,46 +478,51 @@ int asix_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
 
 int asix_get_eeprom_len(struct net_device *net)
 {
-	struct usbnet *dev = netdev_priv(net);
-	struct asix_data *data = (struct asix_data *)&dev->data;
-
-	return data->eeprom_len;
+	return AX_EEPROM_LEN;
 }
 
 int asix_get_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom,
 		    u8 *data)
 {
 	struct usbnet *dev = netdev_priv(net);
-	__le16 *ebuf = (__le16 *)data;
+	u16 *eeprom_buff;
+	int first_word, last_word;
 	int i;
 
-	/* Crude hack to ensure that we don't overwrite memory
-	 * if an odd length is supplied
-	 */
-	if (eeprom->len % 2)
+	if (eeprom->len == 0)
 		return -EINVAL;
 
 	eeprom->magic = AX_EEPROM_MAGIC;
 
+	first_word = eeprom->offset >> 1;
+	last_word = (eeprom->offset + eeprom->len - 1) >> 1;
+
+	eeprom_buff = kmalloc(sizeof(u16) * (last_word - first_word + 1),
+			      GFP_KERNEL);
+	if (!eeprom_buff)
+		return -ENOMEM;
+
 	/* ax8817x returns 2 bytes from eeprom on read */
-	for (i=0; i < eeprom->len / 2; i++) {
-		if (asix_read_cmd(dev, AX_CMD_READ_EEPROM,
-			eeprom->offset + i, 0, 2, &ebuf[i]) < 0)
-			return -EINVAL;
+	for (i = first_word; i <= last_word; i++) {
+		if (asix_read_cmd(dev, AX_CMD_READ_EEPROM, i, 0, 2,
+				  &(eeprom_buff[i - first_word])) < 0) {
+			kfree(eeprom_buff);
+			return -EIO;
+		}
 	}
+
+	memcpy(data, (u8 *)eeprom_buff + (eeprom->offset & 1), eeprom->len);
+	kfree(eeprom_buff);
 	return 0;
 }
 
 void asix_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info)
 {
-	struct usbnet *dev = netdev_priv(net);
-	struct asix_data *data = (struct asix_data *)&dev->data;
-
 	/* Inherit standard device info */
 	usbnet_get_drvinfo(net, info);
 	strncpy (info->driver, DRIVER_NAME, sizeof info->driver);
 	strncpy (info->version, DRIVER_VERSION, sizeof info->version);
-	info->eedump_len = data->eeprom_len;
+	info->eedump_len = AX_EEPROM_LEN;
 }
 
 int asix_set_mac_address(struct net_device *net, void *p)
diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c
index ed9403b..658c08f 100644
--- a/drivers/net/usb/asix_devices.c
+++ b/drivers/net/usb/asix_devices.c
@@ -201,9 +201,6 @@ static int ax88172_bind(struct usbnet *dev, struct usb_interface *intf)
 	u8 buf[ETH_ALEN];
 	int i;
 	unsigned long gpio_bits = dev->driver_info->data;
-	struct asix_data *data = (struct asix_data *)&dev->data;
-
-	data->eeprom_len = AX88172_EEPROM_LEN;
 
 	usbnet_get_endpoints(dev,intf);
 
@@ -409,12 +406,9 @@ static const struct net_device_ops ax88772_netdev_ops = {
 static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
 {
 	int ret, embd_phy;
-	struct asix_data *data = (struct asix_data *)&dev->data;
 	u8 buf[ETH_ALEN];
 	u32 phyid;
 
-	data->eeprom_len = AX88772_EEPROM_LEN;
-
 	usbnet_get_endpoints(dev,intf);
 
 	/* Get the MAC address */
@@ -767,9 +761,6 @@ static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf)
 {
 	int ret;
 	u8 buf[ETH_ALEN];
-	struct asix_data *data = (struct asix_data *)&dev->data;
-
-	data->eeprom_len = AX88772_EEPROM_LEN;
 
 	usbnet_get_endpoints(dev,intf);
 
diff --git a/drivers/net/usb/ax88172a.c b/drivers/net/usb/ax88172a.c
index 3d0f8fa..97dce0f 100644
--- a/drivers/net/usb/ax88172a.c
+++ b/drivers/net/usb/ax88172a.c
@@ -228,12 +228,9 @@ err:
 static int ax88172a_bind(struct usbnet *dev, struct usb_interface *intf)
 {
 	int ret;
-	struct asix_data *data = (struct asix_data *)&dev->data;
 	u8 buf[ETH_ALEN];
 	struct ax88172a_private *priv;
 
-	data->eeprom_len = AX88772_EEPROM_LEN;
-
 	usbnet_get_endpoints(dev, intf);
 
 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH net-next 2/2] asix: Add support for programming the EEPROM
  2012-07-19 10:23 [PATCH net-next 1/2] asix: Rework reading from EEPROM Christian Riesch
@ 2012-07-19 10:23 ` Christian Riesch
  2012-07-19 17:50   ` David Miller
  2012-07-19 17:50 ` [PATCH net-next 1/2] asix: Rework reading from EEPROM David Miller
  1 sibling, 1 reply; 4+ messages in thread
From: Christian Riesch @ 2012-07-19 10:23 UTC (permalink / raw)
  To: netdev; +Cc: Allan Chou, Mark Lord, Grant Grundler, Christian Riesch

This patch adds the asix_set_eeprom() function to provide support for
programming the configuration EEPROM via ethtool.

Signed-off-by: Christian Riesch <christian.riesch@omicron.at>
---
 drivers/net/usb/asix.h         |    2 +
 drivers/net/usb/asix_common.c  |   81 ++++++++++++++++++++++++++++++++++++++++
 drivers/net/usb/asix_devices.c |    3 +
 drivers/net/usb/ax88172a.c     |    1 +
 4 files changed, 87 insertions(+), 0 deletions(-)

diff --git a/drivers/net/usb/asix.h b/drivers/net/usb/asix.h
index fbff177..e889631 100644
--- a/drivers/net/usb/asix.h
+++ b/drivers/net/usb/asix.h
@@ -208,6 +208,8 @@ int asix_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo);
 int asix_get_eeprom_len(struct net_device *net);
 int asix_get_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom,
 		    u8 *data);
+int asix_set_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom,
+		    u8 *data);
 
 void asix_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info);
 
diff --git a/drivers/net/usb/asix_common.c b/drivers/net/usb/asix_common.c
index 0b5b2d3..774d9ce 100644
--- a/drivers/net/usb/asix_common.c
+++ b/drivers/net/usb/asix_common.c
@@ -516,6 +516,87 @@ int asix_get_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom,
 	return 0;
 }
 
+int asix_set_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom,
+		    u8 *data)
+{
+	struct usbnet *dev = netdev_priv(net);
+	u16 *eeprom_buff;
+	int first_word, last_word;
+	int i;
+	int ret;
+
+	netdev_dbg(net, "write EEPROM len %d, offset %d, magic 0x%x\n",
+		   eeprom->len, eeprom->offset, eeprom->magic);
+
+	if (eeprom->len == 0)
+		return -EINVAL;
+
+	if (eeprom->magic != AX_EEPROM_MAGIC)
+		return -EINVAL;
+
+	first_word = eeprom->offset >> 1;
+	last_word = (eeprom->offset + eeprom->len - 1) >> 1;
+
+	eeprom_buff = kmalloc(sizeof(u16) * (last_word - first_word + 1),
+			      GFP_KERNEL);
+	if (!eeprom_buff)
+		return -ENOMEM;
+
+	/* align data to 16 bit boundaries, read the missing data from
+	   the EEPROM */
+	if (eeprom->offset & 1) {
+		ret = asix_read_cmd(dev, AX_CMD_READ_EEPROM, first_word, 0, 2,
+				    &(eeprom_buff[0]));
+		if (ret < 0) {
+			netdev_err(net, "Failed to read EEPROM at offset 0x%02x.\n", first_word);
+			goto free;
+		}
+	}
+
+	if ((eeprom->offset + eeprom->len) & 1) {
+		ret = asix_read_cmd(dev, AX_CMD_READ_EEPROM, last_word, 0, 2,
+				    &(eeprom_buff[last_word - first_word]));
+		if (ret < 0) {
+			netdev_err(net, "Failed to read EEPROM at offset 0x%02x.\n", last_word);
+			goto free;
+		}
+	}
+
+	memcpy((u8 *)eeprom_buff + (eeprom->offset & 1), data, eeprom->len);
+
+	/* write data to EEPROM */
+	ret = asix_write_cmd(dev, AX_CMD_WRITE_ENABLE, 0x0000, 0, 0, NULL);
+	if (ret < 0) {
+		netdev_err(net, "Failed to enable EEPROM write\n");
+		goto free;
+	}
+	msleep(20);
+
+	for (i = first_word; i <= last_word; i++) {
+		netdev_dbg(net, "write to EEPROM at offset 0x%02x, data 0x%04x\n",
+			   i, eeprom_buff[i - first_word]);
+		ret = asix_write_cmd(dev, AX_CMD_WRITE_EEPROM, i,
+				     eeprom_buff[i - first_word], 0, NULL);
+		if (ret < 0) {
+			netdev_err(net, "Failed to write EEPROM at offset 0x%02x.\n",
+				   i);
+			goto free;
+		}
+		msleep(20);
+	}
+
+	ret = asix_write_cmd(dev, AX_CMD_WRITE_DISABLE, 0x0000, 0, 0, NULL);
+	if (ret < 0) {
+		netdev_err(net, "Failed to disable EEPROM write\n");
+		goto free;
+	}
+
+	ret = 0;
+free:
+	kfree(eeprom_buff);
+	return ret;
+}
+
 void asix_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info)
 {
 	/* Inherit standard device info */
diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c
index 658c08f..4fd48df 100644
--- a/drivers/net/usb/asix_devices.c
+++ b/drivers/net/usb/asix_devices.c
@@ -119,6 +119,7 @@ static const struct ethtool_ops ax88172_ethtool_ops = {
 	.set_wol		= asix_set_wol,
 	.get_eeprom_len		= asix_get_eeprom_len,
 	.get_eeprom		= asix_get_eeprom,
+	.set_eeprom		= asix_set_eeprom,
 	.get_settings		= usbnet_get_settings,
 	.set_settings		= usbnet_set_settings,
 	.nway_reset		= usbnet_nway_reset,
@@ -258,6 +259,7 @@ static const struct ethtool_ops ax88772_ethtool_ops = {
 	.set_wol		= asix_set_wol,
 	.get_eeprom_len		= asix_get_eeprom_len,
 	.get_eeprom		= asix_get_eeprom,
+	.set_eeprom		= asix_set_eeprom,
 	.get_settings		= usbnet_get_settings,
 	.set_settings		= usbnet_set_settings,
 	.nway_reset		= usbnet_nway_reset,
@@ -478,6 +480,7 @@ static const struct ethtool_ops ax88178_ethtool_ops = {
 	.set_wol		= asix_set_wol,
 	.get_eeprom_len		= asix_get_eeprom_len,
 	.get_eeprom		= asix_get_eeprom,
+	.set_eeprom		= asix_set_eeprom,
 	.get_settings		= usbnet_get_settings,
 	.set_settings		= usbnet_set_settings,
 	.nway_reset		= usbnet_nway_reset,
diff --git a/drivers/net/usb/ax88172a.c b/drivers/net/usb/ax88172a.c
index 97dce0f..c8e0aa8 100644
--- a/drivers/net/usb/ax88172a.c
+++ b/drivers/net/usb/ax88172a.c
@@ -194,6 +194,7 @@ static const struct ethtool_ops ax88172a_ethtool_ops = {
 	.set_wol		= asix_set_wol,
 	.get_eeprom_len		= asix_get_eeprom_len,
 	.get_eeprom		= asix_get_eeprom,
+	.set_eeprom		= asix_set_eeprom,
 	.get_settings		= ax88172a_get_settings,
 	.set_settings		= ax88172a_set_settings,
 	.nway_reset		= ax88172a_nway_reset,
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH net-next 1/2] asix: Rework reading from EEPROM
  2012-07-19 10:23 [PATCH net-next 1/2] asix: Rework reading from EEPROM Christian Riesch
  2012-07-19 10:23 ` [PATCH net-next 2/2] asix: Add support for programming the EEPROM Christian Riesch
@ 2012-07-19 17:50 ` David Miller
  1 sibling, 0 replies; 4+ messages in thread
From: David Miller @ 2012-07-19 17:50 UTC (permalink / raw)
  To: christian.riesch; +Cc: netdev, allan, kernel, grundler

From: Christian Riesch <christian.riesch@omicron.at>
Date: Thu, 19 Jul 2012 12:23:06 +0200

> The current code for reading the EEPROM via ethtool in the asix
> driver has a few issues. It cannot handle odd length values
> (accesses must be aligned at 16 bit boundaries) and interprets the
> offset provided by ethtool as 16 bit word offset instead as byte offset.
> 
> The new code for asix_get_eeprom() introduced by this patch is
> modeled after the code in
> drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c
> and provides read access to the entire EEPROM with arbitrary
> offsets and lengths.
> 
> Signed-off-by: Christian Riesch <christian.riesch@omicron.at>

Applied.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH net-next 2/2] asix: Add support for programming the EEPROM
  2012-07-19 10:23 ` [PATCH net-next 2/2] asix: Add support for programming the EEPROM Christian Riesch
@ 2012-07-19 17:50   ` David Miller
  0 siblings, 0 replies; 4+ messages in thread
From: David Miller @ 2012-07-19 17:50 UTC (permalink / raw)
  To: christian.riesch; +Cc: netdev, allan, kernel, grundler

From: Christian Riesch <christian.riesch@omicron.at>
Date: Thu, 19 Jul 2012 12:23:07 +0200

> This patch adds the asix_set_eeprom() function to provide support for
> programming the configuration EEPROM via ethtool.
> 
> Signed-off-by: Christian Riesch <christian.riesch@omicron.at>

Applied.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2012-07-19 17:50 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-07-19 10:23 [PATCH net-next 1/2] asix: Rework reading from EEPROM Christian Riesch
2012-07-19 10:23 ` [PATCH net-next 2/2] asix: Add support for programming the EEPROM Christian Riesch
2012-07-19 17:50   ` David Miller
2012-07-19 17:50 ` [PATCH net-next 1/2] asix: Rework reading from EEPROM David Miller

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.