asix_common.c 16.0 KB
Newer Older
1 2
/*
 * ASIX AX8817X based USB 2.0 Ethernet Devices
3
 * Copyright (C) 2003-2006 David Hollis <dhollis@davehollis.com>
4
 * Copyright (C) 2005 Phil Chang <pchang23@sbcglobal.net>
5
 * Copyright (C) 2006 James Painter <jamie.painter@iname.com>
6 7 8 9 10 11 12 13 14 15 16 17 18
 * Copyright (c) 2002-2003 TiVo Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 21
 */

C
Christian Riesch 已提交
22 23 24 25
#include "asix.h"

int asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
		  u16 size, void *data)
26
{
27 28 29 30 31 32 33 34
	int ret;
	ret = usbnet_read_cmd(dev, cmd,
			       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
			       value, index, data, size);

	if (ret != size && ret >= 0)
		return -EINVAL;
	return ret;
35 36
}

C
Christian Riesch 已提交
37 38
int asix_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
		   u16 size, void *data)
39
{
40 41 42
	return usbnet_write_cmd(dev, cmd,
				USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
				value, index, data, size);
43 44
}

C
Christian Riesch 已提交
45 46
void asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
			  u16 size, void *data)
47
{
48 49 50
	usbnet_write_cmd_async(dev, cmd,
			       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
			       value, index, data, size);
51 52
}

53 54
int asix_rx_fixup_internal(struct usbnet *dev, struct sk_buff *skb,
			   struct asix_rx_fixup_info *rx)
55
{
56
	int offset = 0;
57
	u16 size;
58

59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
	/* When an Ethernet frame spans multiple URB socket buffers,
	 * do a sanity test for the Data header synchronisation.
	 * Attempt to detect the situation of the previous socket buffer having
	 * been truncated or a socket buffer was missing. These situations
	 * cause a discontinuity in the data stream and therefore need to avoid
	 * appending bad data to the end of the current netdev socket buffer.
	 * Also avoid unnecessarily discarding a good current netdev socket
	 * buffer.
	 */
	if (rx->remaining && (rx->remaining + sizeof(u32) <= skb->len)) {
		offset = ((rx->remaining + 1) & 0xfffe) + sizeof(u32);
		rx->header = get_unaligned_le32(skb->data + offset);
		offset = 0;

		size = (u16)(rx->header & 0x7ff);
		if (size != ((~rx->header >> 16) & 0x7ff)) {
			netdev_err(dev->net, "asix_rx_fixup() Data Header synchronisation was lost, remaining %d\n",
				   rx->remaining);
77 78 79 80 81 82 83 84
			if (rx->ax_skb) {
				kfree_skb(rx->ax_skb);
				rx->ax_skb = NULL;
				/* Discard the incomplete netdev Ethernet frame
				 * and assume the Data header is at the start of
				 * the current URB socket buffer.
				 */
			}
85 86 87 88
			rx->remaining = 0;
		}
	}

89
	while (offset + sizeof(u16) <= skb->len) {
90
		u16 copy_length;
91
		unsigned char *data;
92

93
		if (!rx->remaining) {
94 95 96 97 98 99 100 101 102 103 104 105 106
			if (skb->len - offset == sizeof(u16)) {
				rx->header = get_unaligned_le16(
						skb->data + offset);
				rx->split_head = true;
				offset += sizeof(u16);
				break;
			}

			if (rx->split_head == true) {
				rx->header |= (get_unaligned_le16(
						skb->data + offset) << 16);
				rx->split_head = false;
				offset += sizeof(u16);
107 108 109 110 111
			} else {
				rx->header = get_unaligned_le32(skb->data +
								offset);
				offset += sizeof(u32);
			}
112

113 114 115
			/* take frame length from Data header 32-bit word */
			size = (u16)(rx->header & 0x7ff);
			if (size != ((~rx->header >> 16) & 0x7ff)) {
116 117 118 119
				netdev_err(dev->net, "asix_rx_fixup() Bad Header Length 0x%x, offset %d\n",
					   rx->header, offset);
				return 0;
			}
120 121 122 123 124 125
			if (size > dev->net->mtu + ETH_HLEN + VLAN_HLEN) {
				netdev_err(dev->net, "asix_rx_fixup() Bad RX Length %d\n",
					   size);
				return 0;
			}

126 127 128 129 130
			/* Sometimes may fail to get a netdev socket buffer but
			 * continue to process the URB socket buffer so that
			 * synchronisation of the Ethernet frame Data header
			 * word is maintained.
			 */
131
			rx->ax_skb = netdev_alloc_skb_ip_align(dev->net, size);
132

133
			rx->remaining = size;
134 135
		}

136 137 138 139 140 141
		if (rx->remaining > skb->len - offset) {
			copy_length = skb->len - offset;
			rx->remaining -= copy_length;
		} else {
			copy_length = rx->remaining;
			rx->remaining = 0;
142
		}
143

144 145 146 147 148 149
		if (rx->ax_skb) {
			data = skb_put(rx->ax_skb, copy_length);
			memcpy(data, skb->data + offset, copy_length);
			if (!rx->remaining)
				usbnet_skb_return(dev, rx->ax_skb);
		}
150

151
		offset += (copy_length + 1) & 0xfffe;
152 153
	}

154
	if (skb->len != offset) {
155 156
		netdev_err(dev->net, "asix_rx_fixup() Bad SKB Length %d, %d\n",
			   skb->len, offset);
157 158
		return 0;
	}
159

160 161 162
	return 1;
}

163 164 165 166 167 168 169 170
int asix_rx_fixup_common(struct usbnet *dev, struct sk_buff *skb)
{
	struct asix_common_private *dp = dev->driver_priv;
	struct asix_rx_fixup_info *rx = &dp->rx_fixup_info;

	return asix_rx_fixup_internal(dev, skb, rx);
}

C
Christian Riesch 已提交
171 172
struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
			      gfp_t flags)
173 174 175 176 177 178 179
{
	int padlen;
	int headroom = skb_headroom(skb);
	int tailroom = skb_tailroom(skb);
	u32 packet_len;
	u32 padbytes = 0xffff0000;

180
	padlen = ((skb->len + 4) & (dev->maxpacket - 1)) ? 0 : 4;
181

E
Eric Dumazet 已提交
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
	/* We need to push 4 bytes in front of frame (packet_len)
	 * and maybe add 4 bytes after the end (if padlen is 4)
	 *
	 * Avoid skb_copy_expand() expensive call, using following rules :
	 * - We are allowed to push 4 bytes in headroom if skb_header_cloned()
	 *   is false (and if we have 4 bytes of headroom)
	 * - We are allowed to put 4 bytes at tail if skb_cloned()
	 *   is false (and if we have 4 bytes of tailroom)
	 *
	 * TCP packets for example are cloned, but skb_header_release()
	 * was called in tcp stack, allowing us to use headroom for our needs.
	 */
	if (!skb_header_cloned(skb) &&
	    !(padlen && skb_cloned(skb)) &&
	    headroom + tailroom >= 4 + padlen) {
		/* following should not happen, but better be safe */
		if (headroom < 4 ||
		    tailroom < padlen) {
200
			skb->data = memmove(skb->head + 4, skb->data, skb->len);
201
			skb_set_tail_pointer(skb, skb->len);
202 203 204
		}
	} else {
		struct sk_buff *skb2;
E
Eric Dumazet 已提交
205

206 207 208 209 210 211 212
		skb2 = skb_copy_expand(skb, 4, padlen, flags);
		dev_kfree_skb_any(skb);
		skb = skb2;
		if (!skb)
			return NULL;
	}

E
Eric Dumazet 已提交
213
	packet_len = ((skb->len ^ 0x0000ffff) << 16) + skb->len;
214
	skb_push(skb, 4);
215
	cpu_to_le32s(&packet_len);
216
	skb_copy_to_linear_data(skb, &packet_len, sizeof(packet_len));
217

218
	if (padlen) {
219
		cpu_to_le32s(&padbytes);
220
		memcpy(skb_tail_pointer(skb), &padbytes, sizeof(padbytes));
221 222
		skb_put(skb, sizeof(padbytes));
	}
223

224
	usbnet_set_skb_tx_stats(skb, 1, 0);
225 226 227
	return skb;
}

C
Christian Riesch 已提交
228
int asix_set_sw_mii(struct usbnet *dev)
229 230 231 232
{
	int ret;
	ret = asix_write_cmd(dev, AX_CMD_SET_SW_MII, 0x0000, 0, 0, NULL);
	if (ret < 0)
233
		netdev_err(dev->net, "Failed to enable software MII access\n");
234 235 236
	return ret;
}

C
Christian Riesch 已提交
237
int asix_set_hw_mii(struct usbnet *dev)
238 239 240 241
{
	int ret;
	ret = asix_write_cmd(dev, AX_CMD_SET_HW_MII, 0x0000, 0, 0, NULL);
	if (ret < 0)
242
		netdev_err(dev->net, "Failed to enable hardware MII access\n");
243 244 245
	return ret;
}

246
int asix_read_phy_addr(struct usbnet *dev, int internal)
247
{
248
	int offset = (internal ? 1 : 0);
A
Al Viro 已提交
249 250
	u8 buf[2];
	int ret = asix_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf);
251

252
	netdev_dbg(dev->net, "asix_get_phy_addr()\n");
253

A
Al Viro 已提交
254
	if (ret < 0) {
255
		netdev_err(dev->net, "Error reading PHYID register: %02x\n", ret);
A
Al Viro 已提交
256
		goto out;
257
	}
258 259
	netdev_dbg(dev->net, "asix_get_phy_addr() returning 0x%04x\n",
		   *((__le16 *)buf));
260
	ret = buf[offset];
A
Al Viro 已提交
261 262

out:
263 264 265
	return ret;
}

266 267 268 269 270 271 272
int asix_get_phy_addr(struct usbnet *dev)
{
	/* return the address of the internal phy */
	return asix_read_phy_addr(dev, 1);
}


C
Christian Riesch 已提交
273
int asix_sw_reset(struct usbnet *dev, u8 flags)
274 275 276 277 278
{
	int ret;

        ret = asix_write_cmd(dev, AX_CMD_SW_RESET, flags, 0, 0, NULL);
	if (ret < 0)
279
		netdev_err(dev->net, "Failed to send software reset: %02x\n", ret);
280 281 282

	return ret;
}
283

C
Christian Riesch 已提交
284
u16 asix_read_rx_ctl(struct usbnet *dev)
285
{
A
Al Viro 已提交
286 287
	__le16 v;
	int ret = asix_read_cmd(dev, AX_CMD_READ_RX_CTL, 0, 0, 2, &v);
288

A
Al Viro 已提交
289
	if (ret < 0) {
290
		netdev_err(dev->net, "Error reading RX_CTL register: %02x\n", ret);
A
Al Viro 已提交
291
		goto out;
292
	}
A
Al Viro 已提交
293 294
	ret = le16_to_cpu(v);
out:
295 296 297
	return ret;
}

C
Christian Riesch 已提交
298
int asix_write_rx_ctl(struct usbnet *dev, u16 mode)
299 300 301
{
	int ret;

302
	netdev_dbg(dev->net, "asix_write_rx_ctl() - mode = 0x%04x\n", mode);
303 304
	ret = asix_write_cmd(dev, AX_CMD_WRITE_RX_CTL, mode, 0, 0, NULL);
	if (ret < 0)
305 306
		netdev_err(dev->net, "Failed to write RX_CTL mode to 0x%04x: %02x\n",
			   mode, ret);
307 308 309 310

	return ret;
}

C
Christian Riesch 已提交
311
u16 asix_read_medium_status(struct usbnet *dev)
312
{
A
Al Viro 已提交
313 314
	__le16 v;
	int ret = asix_read_cmd(dev, AX_CMD_READ_MEDIUM_STATUS, 0, 0, 2, &v);
315

A
Al Viro 已提交
316
	if (ret < 0) {
317 318
		netdev_err(dev->net, "Error reading Medium Status register: %02x\n",
			   ret);
319
		return ret;	/* TODO: callers not checking for error ret */
320
	}
321 322 323

	return le16_to_cpu(v);

324 325
}

C
Christian Riesch 已提交
326
int asix_write_medium_mode(struct usbnet *dev, u16 mode)
327
{
328
	int ret;
329

330
	netdev_dbg(dev->net, "asix_write_medium_mode() - mode = 0x%04x\n", mode);
331 332
	ret = asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
	if (ret < 0)
333 334
		netdev_err(dev->net, "Failed to write Medium Mode mode to 0x%04x: %02x\n",
			   mode, ret);
335

336 337
	return ret;
}
338

C
Christian Riesch 已提交
339
int asix_write_gpio(struct usbnet *dev, u16 value, int sleep)
340 341
{
	int ret;
342

343
	netdev_dbg(dev->net, "asix_write_gpio() - value = 0x%04x\n", value);
344 345
	ret = asix_write_cmd(dev, AX_CMD_WRITE_GPIOS, value, 0, 0, NULL);
	if (ret < 0)
346 347
		netdev_err(dev->net, "Failed to write GPIO value 0x%04x: %02x\n",
			   value, ret);
348

349 350 351 352
	if (sleep)
		msleep(sleep);

	return ret;
353 354
}

355 356 357
/*
 * AX88772 & AX88178 have a 16-bit RX_CTL value
 */
C
Christian Riesch 已提交
358
void asix_set_multicast(struct net_device *net)
359 360
{
	struct usbnet *dev = netdev_priv(net);
361
	struct asix_data *data = (struct asix_data *)&dev->data;
362
	u16 rx_ctl = AX_DEFAULT_RX_CTL;
363 364

	if (net->flags & IFF_PROMISC) {
365
		rx_ctl |= AX_RX_CTL_PRO;
366
	} else if (net->flags & IFF_ALLMULTI ||
367
		   netdev_mc_count(net) > AX_MAX_MCAST) {
368
		rx_ctl |= AX_RX_CTL_AMALL;
369
	} else if (netdev_mc_empty(net)) {
370 371 372 373 374 375
		/* just broadcast and directed */
	} else {
		/* We use the 20 byte dev->data
		 * for our 8 byte filter buffer
		 * to avoid allocating memory that
		 * is tricky to free later */
376
		struct netdev_hw_addr *ha;
377 378 379 380 381
		u32 crc_bits;

		memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE);

		/* Build the multicast hash filter. */
382 383
		netdev_for_each_mc_addr(ha, net) {
			crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26;
384 385 386 387
			data->multi_filter[crc_bits >> 3] |=
			    1 << (crc_bits & 7);
		}

388
		asix_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0,
389 390
				   AX_MCAST_FILTER_SIZE, data->multi_filter);

391
		rx_ctl |= AX_RX_CTL_AM;
392 393
	}

394
	asix_write_cmd_async(dev, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL);
395 396
}

C
Christian Riesch 已提交
397
int asix_mdio_read(struct net_device *netdev, int phy_id, int loc)
398 399
{
	struct usbnet *dev = netdev_priv(netdev);
A
Al Viro 已提交
400
	__le16 res;
401

402
	mutex_lock(&dev->phy_mutex);
403 404
	asix_set_sw_mii(dev);
	asix_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id,
A
Al Viro 已提交
405
				(__u16)loc, 2, &res);
406
	asix_set_hw_mii(dev);
407
	mutex_unlock(&dev->phy_mutex);
408

409 410
	netdev_dbg(dev->net, "asix_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x\n",
		   phy_id, loc, le16_to_cpu(res));
411

A
Al Viro 已提交
412
	return le16_to_cpu(res);
413 414
}

C
Christian Riesch 已提交
415
void asix_mdio_write(struct net_device *netdev, int phy_id, int loc, int val)
416 417
{
	struct usbnet *dev = netdev_priv(netdev);
A
Al Viro 已提交
418
	__le16 res = cpu_to_le16(val);
419

420 421
	netdev_dbg(dev->net, "asix_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x\n",
		   phy_id, loc, val);
422
	mutex_lock(&dev->phy_mutex);
423
	asix_set_sw_mii(dev);
A
Al Viro 已提交
424
	asix_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id, (__u16)loc, 2, &res);
425
	asix_set_hw_mii(dev);
426
	mutex_unlock(&dev->phy_mutex);
427 428
}

C
Christian Riesch 已提交
429
void asix_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
430 431 432 433
{
	struct usbnet *dev = netdev_priv(net);
	u8 opt;

434
	if (asix_read_cmd(dev, AX_CMD_READ_MONITOR_MODE, 0, 0, 1, &opt) < 0) {
435 436 437 438 439 440
		wolinfo->supported = 0;
		wolinfo->wolopts = 0;
		return;
	}
	wolinfo->supported = WAKE_PHY | WAKE_MAGIC;
	wolinfo->wolopts = 0;
441 442 443 444
	if (opt & AX_MONITOR_LINK)
		wolinfo->wolopts |= WAKE_PHY;
	if (opt & AX_MONITOR_MAGIC)
		wolinfo->wolopts |= WAKE_MAGIC;
445 446
}

C
Christian Riesch 已提交
447
int asix_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
448 449 450 451 452 453 454 455 456
{
	struct usbnet *dev = netdev_priv(net);
	u8 opt = 0;

	if (wolinfo->wolopts & WAKE_PHY)
		opt |= AX_MONITOR_LINK;
	if (wolinfo->wolopts & WAKE_MAGIC)
		opt |= AX_MONITOR_MAGIC;

457
	if (asix_write_cmd(dev, AX_CMD_WRITE_MONITOR_MODE,
A
Al Viro 已提交
458
			      opt, 0, 0, NULL) < 0)
459 460 461 462 463
		return -EINVAL;

	return 0;
}

C
Christian Riesch 已提交
464
int asix_get_eeprom_len(struct net_device *net)
465
{
466
	return AX_EEPROM_LEN;
467 468
}

C
Christian Riesch 已提交
469 470
int asix_get_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom,
		    u8 *data)
471 472
{
	struct usbnet *dev = netdev_priv(net);
473 474
	u16 *eeprom_buff;
	int first_word, last_word;
475 476
	int i;

477
	if (eeprom->len == 0)
478 479 480 481
		return -EINVAL;

	eeprom->magic = AX_EEPROM_MAGIC;

482 483 484 485 486 487 488 489
	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;

490
	/* ax8817x returns 2 bytes from eeprom on read */
491 492 493 494 495 496
	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;
		}
497
	}
498 499 500

	memcpy(data, (u8 *)eeprom_buff + (eeprom->offset & 1), eeprom->len);
	kfree(eeprom_buff);
501 502 503
	return 0;
}

504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584
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;
}

C
Christian Riesch 已提交
585
void asix_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info)
586 587 588
{
	/* Inherit standard device info */
	usbnet_get_drvinfo(net, info);
589 590
	strlcpy(info->driver, DRIVER_NAME, sizeof(info->driver));
	strlcpy(info->version, DRIVER_VERSION, sizeof(info->version));
591
	info->eedump_len = AX_EEPROM_LEN;
592 593
}

C
Christian Riesch 已提交
594
int asix_set_mac_address(struct net_device *net, void *p)
595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616
{
	struct usbnet *dev = netdev_priv(net);
	struct asix_data *data = (struct asix_data *)&dev->data;
	struct sockaddr *addr = p;

	if (netif_running(net))
		return -EBUSY;
	if (!is_valid_ether_addr(addr->sa_data))
		return -EADDRNOTAVAIL;

	memcpy(net->dev_addr, addr->sa_data, ETH_ALEN);

	/* We use the 20 byte dev->data
	 * for our 6 byte mac buffer
	 * to avoid allocating memory that
	 * is tricky to free later */
	memcpy(data->mac_addr, addr->sa_data, ETH_ALEN);
	asix_write_cmd_async(dev, AX_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN,
							data->mac_addr);

	return 0;
}