linux/drivers/net/usb/asix_common.c
<<
>>
Prefs
   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 * Copyright (c) 2002-2003 TiVo Inc.
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License as published by
  10 * the Free Software Foundation; either version 2 of the License, or
  11 * (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * 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
  22#include "asix.h"
  23
  24int asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
  25                  u16 size, void *data, int in_pm)
  26{
  27        int ret;
  28        int (*fn)(struct usbnet *, u8, u8, u16, u16, void *, u16);
  29
  30        BUG_ON(!dev);
  31
  32        if (!in_pm)
  33                fn = usbnet_read_cmd;
  34        else
  35                fn = usbnet_read_cmd_nopm;
  36
  37        ret = fn(dev, cmd, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  38                 value, index, data, size);
  39
  40        if (unlikely(ret < 0))
  41                netdev_warn(dev->net, "Failed to read reg index 0x%04x: %d\n",
  42                            index, ret);
  43
  44        return ret;
  45}
  46
  47int asix_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
  48                   u16 size, void *data, int in_pm)
  49{
  50        int ret;
  51        int (*fn)(struct usbnet *, u8, u8, u16, u16, const void *, u16);
  52
  53        BUG_ON(!dev);
  54
  55        if (!in_pm)
  56                fn = usbnet_write_cmd;
  57        else
  58                fn = usbnet_write_cmd_nopm;
  59
  60        ret = fn(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  61                 value, index, data, size);
  62
  63        if (unlikely(ret < 0))
  64                netdev_warn(dev->net, "Failed to write reg index 0x%04x: %d\n",
  65                            index, ret);
  66
  67        return ret;
  68}
  69
  70void asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
  71                          u16 size, void *data)
  72{
  73        usbnet_write_cmd_async(dev, cmd,
  74                               USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  75                               value, index, data, size);
  76}
  77
  78int asix_rx_fixup_internal(struct usbnet *dev, struct sk_buff *skb,
  79                           struct asix_rx_fixup_info *rx)
  80{
  81        int offset = 0;
  82        u16 size;
  83
  84        /* When an Ethernet frame spans multiple URB socket buffers,
  85         * do a sanity test for the Data header synchronisation.
  86         * Attempt to detect the situation of the previous socket buffer having
  87         * been truncated or a socket buffer was missing. These situations
  88         * cause a discontinuity in the data stream and therefore need to avoid
  89         * appending bad data to the end of the current netdev socket buffer.
  90         * Also avoid unnecessarily discarding a good current netdev socket
  91         * buffer.
  92         */
  93        if (rx->remaining && (rx->remaining + sizeof(u32) <= skb->len)) {
  94                offset = ((rx->remaining + 1) & 0xfffe);
  95                rx->header = get_unaligned_le32(skb->data + offset);
  96                offset = 0;
  97
  98                size = (u16)(rx->header & 0x7ff);
  99                if (size != ((~rx->header >> 16) & 0x7ff)) {
 100                        netdev_err(dev->net, "asix_rx_fixup() Data Header synchronisation was lost, remaining %d\n",
 101                                   rx->remaining);
 102                        if (rx->ax_skb) {
 103                                kfree_skb(rx->ax_skb);
 104                                rx->ax_skb = NULL;
 105                                /* Discard the incomplete netdev Ethernet frame
 106                                 * and assume the Data header is at the start of
 107                                 * the current URB socket buffer.
 108                                 */
 109                        }
 110                        rx->remaining = 0;
 111                }
 112        }
 113
 114        while (offset + sizeof(u16) <= skb->len) {
 115                u16 copy_length;
 116                unsigned char *data;
 117
 118                if (!rx->remaining) {
 119                        if (skb->len - offset == sizeof(u16)) {
 120                                rx->header = get_unaligned_le16(
 121                                                skb->data + offset);
 122                                rx->split_head = true;
 123                                offset += sizeof(u16);
 124                                break;
 125                        }
 126
 127                        if (rx->split_head == true) {
 128                                rx->header |= (get_unaligned_le16(
 129                                                skb->data + offset) << 16);
 130                                rx->split_head = false;
 131                                offset += sizeof(u16);
 132                        } else {
 133                                rx->header = get_unaligned_le32(skb->data +
 134                                                                offset);
 135                                offset += sizeof(u32);
 136                        }
 137
 138                        /* take frame length from Data header 32-bit word */
 139                        size = (u16)(rx->header & 0x7ff);
 140                        if (size != ((~rx->header >> 16) & 0x7ff)) {
 141                                netdev_err(dev->net, "asix_rx_fixup() Bad Header Length 0x%x, offset %d\n",
 142                                           rx->header, offset);
 143                                return 0;
 144                        }
 145                        if (size > dev->net->mtu + ETH_HLEN + VLAN_HLEN) {
 146                                netdev_dbg(dev->net, "asix_rx_fixup() Bad RX Length %d\n",
 147                                           size);
 148                                return 0;
 149                        }
 150
 151                        /* Sometimes may fail to get a netdev socket buffer but
 152                         * continue to process the URB socket buffer so that
 153                         * synchronisation of the Ethernet frame Data header
 154                         * word is maintained.
 155                         */
 156                        rx->ax_skb = netdev_alloc_skb_ip_align(dev->net, size);
 157
 158                        rx->remaining = size;
 159                }
 160
 161                if (rx->remaining > skb->len - offset) {
 162                        copy_length = skb->len - offset;
 163                        rx->remaining -= copy_length;
 164                } else {
 165                        copy_length = rx->remaining;
 166                        rx->remaining = 0;
 167                }
 168
 169                if (rx->ax_skb) {
 170                        data = skb_put(rx->ax_skb, copy_length);
 171                        memcpy(data, skb->data + offset, copy_length);
 172                        if (!rx->remaining)
 173                                usbnet_skb_return(dev, rx->ax_skb);
 174                }
 175
 176                offset += (copy_length + 1) & 0xfffe;
 177        }
 178
 179        if (skb->len != offset) {
 180                netdev_err(dev->net, "asix_rx_fixup() Bad SKB Length %d, %d\n",
 181                           skb->len, offset);
 182                return 0;
 183        }
 184
 185        return 1;
 186}
 187
 188int asix_rx_fixup_common(struct usbnet *dev, struct sk_buff *skb)
 189{
 190        struct asix_common_private *dp = dev->driver_priv;
 191        struct asix_rx_fixup_info *rx = &dp->rx_fixup_info;
 192
 193        return asix_rx_fixup_internal(dev, skb, rx);
 194}
 195
 196struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
 197                              gfp_t flags)
 198{
 199        int padlen;
 200        int headroom = skb_headroom(skb);
 201        int tailroom = skb_tailroom(skb);
 202        u32 packet_len;
 203        u32 padbytes = 0xffff0000;
 204
 205        padlen = ((skb->len + 4) & (dev->maxpacket - 1)) ? 0 : 4;
 206
 207        /* We need to push 4 bytes in front of frame (packet_len)
 208         * and maybe add 4 bytes after the end (if padlen is 4)
 209         *
 210         * Avoid skb_copy_expand() expensive call, using following rules :
 211         * - We are allowed to push 4 bytes in headroom if skb_header_cloned()
 212         *   is false (and if we have 4 bytes of headroom)
 213         * - We are allowed to put 4 bytes at tail if skb_cloned()
 214         *   is false (and if we have 4 bytes of tailroom)
 215         *
 216         * TCP packets for example are cloned, but skb_header_release()
 217         * was called in tcp stack, allowing us to use headroom for our needs.
 218         */
 219        if (!skb_header_cloned(skb) &&
 220            !(padlen && skb_cloned(skb)) &&
 221            headroom + tailroom >= 4 + padlen) {
 222                /* following should not happen, but better be safe */
 223                if (headroom < 4 ||
 224                    tailroom < padlen) {
 225                        skb->data = memmove(skb->head + 4, skb->data, skb->len);
 226                        skb_set_tail_pointer(skb, skb->len);
 227                }
 228        } else {
 229                struct sk_buff *skb2;
 230
 231                skb2 = skb_copy_expand(skb, 4, padlen, flags);
 232                dev_kfree_skb_any(skb);
 233                skb = skb2;
 234                if (!skb)
 235                        return NULL;
 236        }
 237
 238        packet_len = ((skb->len ^ 0x0000ffff) << 16) + skb->len;
 239        skb_push(skb, 4);
 240        cpu_to_le32s(&packet_len);
 241        skb_copy_to_linear_data(skb, &packet_len, sizeof(packet_len));
 242
 243        if (padlen) {
 244                cpu_to_le32s(&padbytes);
 245                memcpy(skb_tail_pointer(skb), &padbytes, sizeof(padbytes));
 246                skb_put(skb, sizeof(padbytes));
 247        }
 248
 249        usbnet_set_skb_tx_stats(skb, 1, 0);
 250        return skb;
 251}
 252
 253int asix_set_sw_mii(struct usbnet *dev, int in_pm)
 254{
 255        int ret;
 256        ret = asix_write_cmd(dev, AX_CMD_SET_SW_MII, 0x0000, 0, 0, NULL, in_pm);
 257
 258        if (ret < 0)
 259                netdev_err(dev->net, "Failed to enable software MII access\n");
 260        return ret;
 261}
 262
 263int asix_set_hw_mii(struct usbnet *dev, int in_pm)
 264{
 265        int ret;
 266        ret = asix_write_cmd(dev, AX_CMD_SET_HW_MII, 0x0000, 0, 0, NULL, in_pm);
 267        if (ret < 0)
 268                netdev_err(dev->net, "Failed to enable hardware MII access\n");
 269        return ret;
 270}
 271
 272int asix_read_phy_addr(struct usbnet *dev, int internal)
 273{
 274        int offset = (internal ? 1 : 0);
 275        u8 buf[2];
 276        int ret = asix_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf, 0);
 277
 278        netdev_dbg(dev->net, "asix_get_phy_addr()\n");
 279
 280        if (ret < 0) {
 281                netdev_err(dev->net, "Error reading PHYID register: %02x\n", ret);
 282                goto out;
 283        }
 284        netdev_dbg(dev->net, "asix_get_phy_addr() returning 0x%04x\n",
 285                   *((__le16 *)buf));
 286        ret = buf[offset];
 287
 288out:
 289        return ret;
 290}
 291
 292int asix_get_phy_addr(struct usbnet *dev)
 293{
 294        /* return the address of the internal phy */
 295        return asix_read_phy_addr(dev, 1);
 296}
 297
 298
 299int asix_sw_reset(struct usbnet *dev, u8 flags, int in_pm)
 300{
 301        int ret;
 302
 303        ret = asix_write_cmd(dev, AX_CMD_SW_RESET, flags, 0, 0, NULL, in_pm);
 304        if (ret < 0)
 305                netdev_err(dev->net, "Failed to send software reset: %02x\n", ret);
 306
 307        return ret;
 308}
 309
 310u16 asix_read_rx_ctl(struct usbnet *dev, int in_pm)
 311{
 312        __le16 v;
 313        int ret = asix_read_cmd(dev, AX_CMD_READ_RX_CTL, 0, 0, 2, &v, in_pm);
 314
 315        if (ret < 0) {
 316                netdev_err(dev->net, "Error reading RX_CTL register: %02x\n", ret);
 317                goto out;
 318        }
 319        ret = le16_to_cpu(v);
 320out:
 321        return ret;
 322}
 323
 324int asix_write_rx_ctl(struct usbnet *dev, u16 mode, int in_pm)
 325{
 326        int ret;
 327
 328        netdev_dbg(dev->net, "asix_write_rx_ctl() - mode = 0x%04x\n", mode);
 329        ret = asix_write_cmd(dev, AX_CMD_WRITE_RX_CTL, mode, 0, 0, NULL, in_pm);
 330        if (ret < 0)
 331                netdev_err(dev->net, "Failed to write RX_CTL mode to 0x%04x: %02x\n",
 332                           mode, ret);
 333
 334        return ret;
 335}
 336
 337u16 asix_read_medium_status(struct usbnet *dev, int in_pm)
 338{
 339        __le16 v;
 340        int ret = asix_read_cmd(dev, AX_CMD_READ_MEDIUM_STATUS,
 341                                0, 0, 2, &v, in_pm);
 342
 343        if (ret < 0) {
 344                netdev_err(dev->net, "Error reading Medium Status register: %02x\n",
 345                           ret);
 346                return ret;     /* TODO: callers not checking for error ret */
 347        }
 348
 349        return le16_to_cpu(v);
 350
 351}
 352
 353int asix_write_medium_mode(struct usbnet *dev, u16 mode, int in_pm)
 354{
 355        int ret;
 356
 357        netdev_dbg(dev->net, "asix_write_medium_mode() - mode = 0x%04x\n", mode);
 358        ret = asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE,
 359                             mode, 0, 0, NULL, in_pm);
 360        if (ret < 0)
 361                netdev_err(dev->net, "Failed to write Medium Mode mode to 0x%04x: %02x\n",
 362                           mode, ret);
 363
 364        return ret;
 365}
 366
 367int asix_write_gpio(struct usbnet *dev, u16 value, int sleep, int in_pm)
 368{
 369        int ret;
 370
 371        netdev_dbg(dev->net, "asix_write_gpio() - value = 0x%04x\n", value);
 372        ret = asix_write_cmd(dev, AX_CMD_WRITE_GPIOS, value, 0, 0, NULL, in_pm);
 373        if (ret < 0)
 374                netdev_err(dev->net, "Failed to write GPIO value 0x%04x: %02x\n",
 375                           value, ret);
 376
 377        if (sleep)
 378                msleep(sleep);
 379
 380        return ret;
 381}
 382
 383/*
 384 * AX88772 & AX88178 have a 16-bit RX_CTL value
 385 */
 386void asix_set_multicast(struct net_device *net)
 387{
 388        struct usbnet *dev = netdev_priv(net);
 389        struct asix_data *data = (struct asix_data *)&dev->data;
 390        u16 rx_ctl = AX_DEFAULT_RX_CTL;
 391
 392        if (net->flags & IFF_PROMISC) {
 393                rx_ctl |= AX_RX_CTL_PRO;
 394        } else if (net->flags & IFF_ALLMULTI ||
 395                   netdev_mc_count(net) > AX_MAX_MCAST) {
 396                rx_ctl |= AX_RX_CTL_AMALL;
 397        } else if (netdev_mc_empty(net)) {
 398                /* just broadcast and directed */
 399        } else {
 400                /* We use the 20 byte dev->data
 401                 * for our 8 byte filter buffer
 402                 * to avoid allocating memory that
 403                 * is tricky to free later */
 404                struct netdev_hw_addr *ha;
 405                u32 crc_bits;
 406
 407                memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE);
 408
 409                /* Build the multicast hash filter. */
 410                netdev_for_each_mc_addr(ha, net) {
 411                        crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26;
 412                        data->multi_filter[crc_bits >> 3] |=
 413                            1 << (crc_bits & 7);
 414                }
 415
 416                asix_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0,
 417                                   AX_MCAST_FILTER_SIZE, data->multi_filter);
 418
 419                rx_ctl |= AX_RX_CTL_AM;
 420        }
 421
 422        asix_write_cmd_async(dev, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL);
 423}
 424
 425int asix_mdio_read(struct net_device *netdev, int phy_id, int loc)
 426{
 427        struct usbnet *dev = netdev_priv(netdev);
 428        __le16 res;
 429        u8 smsr;
 430        int i = 0;
 431        int ret;
 432
 433        mutex_lock(&dev->phy_mutex);
 434        do {
 435                ret = asix_set_sw_mii(dev, 0);
 436                if (ret == -ENODEV || ret == -ETIMEDOUT)
 437                        break;
 438                usleep_range(1000, 1100);
 439                ret = asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG,
 440                                    0, 0, 1, &smsr, 0);
 441        } while (!(smsr & AX_HOST_EN) && (i++ < 30) && (ret != -ENODEV));
 442        if (ret == -ENODEV || ret == -ETIMEDOUT) {
 443                mutex_unlock(&dev->phy_mutex);
 444                return ret;
 445        }
 446
 447        asix_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id,
 448                                (__u16)loc, 2, &res, 0);
 449        asix_set_hw_mii(dev, 0);
 450        mutex_unlock(&dev->phy_mutex);
 451
 452        netdev_dbg(dev->net, "asix_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x\n",
 453                        phy_id, loc, le16_to_cpu(res));
 454
 455        return le16_to_cpu(res);
 456}
 457
 458void asix_mdio_write(struct net_device *netdev, int phy_id, int loc, int val)
 459{
 460        struct usbnet *dev = netdev_priv(netdev);
 461        __le16 res = cpu_to_le16(val);
 462        u8 smsr;
 463        int i = 0;
 464        int ret;
 465
 466        netdev_dbg(dev->net, "asix_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x\n",
 467                        phy_id, loc, val);
 468
 469        mutex_lock(&dev->phy_mutex);
 470        do {
 471                ret = asix_set_sw_mii(dev, 0);
 472                if (ret == -ENODEV)
 473                        break;
 474                usleep_range(1000, 1100);
 475                ret = asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG,
 476                                    0, 0, 1, &smsr, 0);
 477        } while (!(smsr & AX_HOST_EN) && (i++ < 30) && (ret != -ENODEV));
 478        if (ret == -ENODEV) {
 479                mutex_unlock(&dev->phy_mutex);
 480                return;
 481        }
 482
 483        asix_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id,
 484                       (__u16)loc, 2, &res, 0);
 485        asix_set_hw_mii(dev, 0);
 486        mutex_unlock(&dev->phy_mutex);
 487}
 488
 489int asix_mdio_read_nopm(struct net_device *netdev, int phy_id, int loc)
 490{
 491        struct usbnet *dev = netdev_priv(netdev);
 492        __le16 res;
 493        u8 smsr;
 494        int i = 0;
 495        int ret;
 496
 497        mutex_lock(&dev->phy_mutex);
 498        do {
 499                ret = asix_set_sw_mii(dev, 1);
 500                if (ret == -ENODEV || ret == -ETIMEDOUT)
 501                        break;
 502                usleep_range(1000, 1100);
 503                ret = asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG,
 504                                    0, 0, 1, &smsr, 1);
 505        } while (!(smsr & AX_HOST_EN) && (i++ < 30) && (ret != -ENODEV));
 506        if (ret == -ENODEV || ret == -ETIMEDOUT) {
 507                mutex_unlock(&dev->phy_mutex);
 508                return ret;
 509        }
 510
 511        asix_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id,
 512                      (__u16)loc, 2, &res, 1);
 513        asix_set_hw_mii(dev, 1);
 514        mutex_unlock(&dev->phy_mutex);
 515
 516        netdev_dbg(dev->net, "asix_mdio_read_nopm() phy_id=0x%02x, loc=0x%02x, returns=0x%04x\n",
 517                        phy_id, loc, le16_to_cpu(res));
 518
 519        return le16_to_cpu(res);
 520}
 521
 522void
 523asix_mdio_write_nopm(struct net_device *netdev, int phy_id, int loc, int val)
 524{
 525        struct usbnet *dev = netdev_priv(netdev);
 526        __le16 res = cpu_to_le16(val);
 527        u8 smsr;
 528        int i = 0;
 529        int ret;
 530
 531        netdev_dbg(dev->net, "asix_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x\n",
 532                        phy_id, loc, val);
 533
 534        mutex_lock(&dev->phy_mutex);
 535        do {
 536                ret = asix_set_sw_mii(dev, 1);
 537                if (ret == -ENODEV)
 538                        break;
 539                usleep_range(1000, 1100);
 540                ret = asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG,
 541                                    0, 0, 1, &smsr, 1);
 542        } while (!(smsr & AX_HOST_EN) && (i++ < 30) && (ret != -ENODEV));
 543        if (ret == -ENODEV) {
 544                mutex_unlock(&dev->phy_mutex);
 545                return;
 546        }
 547
 548        asix_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id,
 549                       (__u16)loc, 2, &res, 1);
 550        asix_set_hw_mii(dev, 1);
 551        mutex_unlock(&dev->phy_mutex);
 552}
 553
 554void asix_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
 555{
 556        struct usbnet *dev = netdev_priv(net);
 557        u8 opt;
 558
 559        if (asix_read_cmd(dev, AX_CMD_READ_MONITOR_MODE,
 560                          0, 0, 1, &opt, 0) < 0) {
 561                wolinfo->supported = 0;
 562                wolinfo->wolopts = 0;
 563                return;
 564        }
 565        wolinfo->supported = WAKE_PHY | WAKE_MAGIC;
 566        wolinfo->wolopts = 0;
 567        if (opt & AX_MONITOR_LINK)
 568                wolinfo->wolopts |= WAKE_PHY;
 569        if (opt & AX_MONITOR_MAGIC)
 570                wolinfo->wolopts |= WAKE_MAGIC;
 571}
 572
 573int asix_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
 574{
 575        struct usbnet *dev = netdev_priv(net);
 576        u8 opt = 0;
 577
 578        if (wolinfo->wolopts & WAKE_PHY)
 579                opt |= AX_MONITOR_LINK;
 580        if (wolinfo->wolopts & WAKE_MAGIC)
 581                opt |= AX_MONITOR_MAGIC;
 582
 583        if (asix_write_cmd(dev, AX_CMD_WRITE_MONITOR_MODE,
 584                              opt, 0, 0, NULL, 0) < 0)
 585                return -EINVAL;
 586
 587        return 0;
 588}
 589
 590int asix_get_eeprom_len(struct net_device *net)
 591{
 592        return AX_EEPROM_LEN;
 593}
 594
 595int asix_get_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom,
 596                    u8 *data)
 597{
 598        struct usbnet *dev = netdev_priv(net);
 599        u16 *eeprom_buff;
 600        int first_word, last_word;
 601        int i;
 602
 603        if (eeprom->len == 0)
 604                return -EINVAL;
 605
 606        eeprom->magic = AX_EEPROM_MAGIC;
 607
 608        first_word = eeprom->offset >> 1;
 609        last_word = (eeprom->offset + eeprom->len - 1) >> 1;
 610
 611        eeprom_buff = kmalloc(sizeof(u16) * (last_word - first_word + 1),
 612                              GFP_KERNEL);
 613        if (!eeprom_buff)
 614                return -ENOMEM;
 615
 616        /* ax8817x returns 2 bytes from eeprom on read */
 617        for (i = first_word; i <= last_word; i++) {
 618                if (asix_read_cmd(dev, AX_CMD_READ_EEPROM, i, 0, 2,
 619                                  &eeprom_buff[i - first_word], 0) < 0) {
 620                        kfree(eeprom_buff);
 621                        return -EIO;
 622                }
 623        }
 624
 625        memcpy(data, (u8 *)eeprom_buff + (eeprom->offset & 1), eeprom->len);
 626        kfree(eeprom_buff);
 627        return 0;
 628}
 629
 630int asix_set_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom,
 631                    u8 *data)
 632{
 633        struct usbnet *dev = netdev_priv(net);
 634        u16 *eeprom_buff;
 635        int first_word, last_word;
 636        int i;
 637        int ret;
 638
 639        netdev_dbg(net, "write EEPROM len %d, offset %d, magic 0x%x\n",
 640                   eeprom->len, eeprom->offset, eeprom->magic);
 641
 642        if (eeprom->len == 0)
 643                return -EINVAL;
 644
 645        if (eeprom->magic != AX_EEPROM_MAGIC)
 646                return -EINVAL;
 647
 648        first_word = eeprom->offset >> 1;
 649        last_word = (eeprom->offset + eeprom->len - 1) >> 1;
 650
 651        eeprom_buff = kmalloc(sizeof(u16) * (last_word - first_word + 1),
 652                              GFP_KERNEL);
 653        if (!eeprom_buff)
 654                return -ENOMEM;
 655
 656        /* align data to 16 bit boundaries, read the missing data from
 657           the EEPROM */
 658        if (eeprom->offset & 1) {
 659                ret = asix_read_cmd(dev, AX_CMD_READ_EEPROM, first_word, 0, 2,
 660                                    &eeprom_buff[0], 0);
 661                if (ret < 0) {
 662                        netdev_err(net, "Failed to read EEPROM at offset 0x%02x.\n", first_word);
 663                        goto free;
 664                }
 665        }
 666
 667        if ((eeprom->offset + eeprom->len) & 1) {
 668                ret = asix_read_cmd(dev, AX_CMD_READ_EEPROM, last_word, 0, 2,
 669                                    &eeprom_buff[last_word - first_word], 0);
 670                if (ret < 0) {
 671                        netdev_err(net, "Failed to read EEPROM at offset 0x%02x.\n", last_word);
 672                        goto free;
 673                }
 674        }
 675
 676        memcpy((u8 *)eeprom_buff + (eeprom->offset & 1), data, eeprom->len);
 677
 678        /* write data to EEPROM */
 679        ret = asix_write_cmd(dev, AX_CMD_WRITE_ENABLE, 0x0000, 0, 0, NULL, 0);
 680        if (ret < 0) {
 681                netdev_err(net, "Failed to enable EEPROM write\n");
 682                goto free;
 683        }
 684        msleep(20);
 685
 686        for (i = first_word; i <= last_word; i++) {
 687                netdev_dbg(net, "write to EEPROM at offset 0x%02x, data 0x%04x\n",
 688                           i, eeprom_buff[i - first_word]);
 689                ret = asix_write_cmd(dev, AX_CMD_WRITE_EEPROM, i,
 690                                     eeprom_buff[i - first_word], 0, NULL, 0);
 691                if (ret < 0) {
 692                        netdev_err(net, "Failed to write EEPROM at offset 0x%02x.\n",
 693                                   i);
 694                        goto free;
 695                }
 696                msleep(20);
 697        }
 698
 699        ret = asix_write_cmd(dev, AX_CMD_WRITE_DISABLE, 0x0000, 0, 0, NULL, 0);
 700        if (ret < 0) {
 701                netdev_err(net, "Failed to disable EEPROM write\n");
 702                goto free;
 703        }
 704
 705        ret = 0;
 706free:
 707        kfree(eeprom_buff);
 708        return ret;
 709}
 710
 711void asix_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info)
 712{
 713        /* Inherit standard device info */
 714        usbnet_get_drvinfo(net, info);
 715        strlcpy(info->driver, DRIVER_NAME, sizeof(info->driver));
 716        strlcpy(info->version, DRIVER_VERSION, sizeof(info->version));
 717}
 718
 719int asix_set_mac_address(struct net_device *net, void *p)
 720{
 721        struct usbnet *dev = netdev_priv(net);
 722        struct asix_data *data = (struct asix_data *)&dev->data;
 723        struct sockaddr *addr = p;
 724
 725        if (netif_running(net))
 726                return -EBUSY;
 727        if (!is_valid_ether_addr(addr->sa_data))
 728                return -EADDRNOTAVAIL;
 729
 730        memcpy(net->dev_addr, addr->sa_data, ETH_ALEN);
 731
 732        /* We use the 20 byte dev->data
 733         * for our 6 byte mac buffer
 734         * to avoid allocating memory that
 735         * is tricky to free later */
 736        memcpy(data->mac_addr, addr->sa_data, ETH_ALEN);
 737        asix_write_cmd_async(dev, AX_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN,
 738                                                        data->mac_addr);
 739
 740        return 0;
 741}
 742