diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/base/regmap/internal.h | 8 | ||||
| -rw-r--r-- | drivers/base/regmap/regcache.c | 16 | ||||
| -rw-r--r-- | drivers/base/regmap/regmap.c | 32 | ||||
| -rw-r--r-- | drivers/net/ethernet/amd/pcnet32.c | 31 | ||||
| -rw-r--r-- | drivers/net/ethernet/emulex/benet/be.h | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/emulex/benet/be_cmds.c | 17 | ||||
| -rw-r--r-- | drivers/net/ethernet/emulex/benet/be_cmds.h | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/emulex/benet/be_main.c | 131 | ||||
| -rw-r--r-- | drivers/net/usb/cx82310_eth.c | 30 |
9 files changed, 191 insertions, 78 deletions
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h index beb8b27d4621..a13587b5c2be 100644 --- a/drivers/base/regmap/internal.h +++ b/drivers/base/regmap/internal.h | |||
| @@ -243,4 +243,12 @@ extern struct regcache_ops regcache_rbtree_ops; | |||
| 243 | extern struct regcache_ops regcache_lzo_ops; | 243 | extern struct regcache_ops regcache_lzo_ops; |
| 244 | extern struct regcache_ops regcache_flat_ops; | 244 | extern struct regcache_ops regcache_flat_ops; |
| 245 | 245 | ||
| 246 | static inline const char *regmap_name(const struct regmap *map) | ||
| 247 | { | ||
| 248 | if (map->dev) | ||
| 249 | return dev_name(map->dev); | ||
| 250 | |||
| 251 | return map->name; | ||
| 252 | } | ||
| 253 | |||
| 246 | #endif | 254 | #endif |
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c index da84f544c544..87db9893b463 100644 --- a/drivers/base/regmap/regcache.c +++ b/drivers/base/regmap/regcache.c | |||
| @@ -218,7 +218,7 @@ int regcache_read(struct regmap *map, | |||
| 218 | ret = map->cache_ops->read(map, reg, value); | 218 | ret = map->cache_ops->read(map, reg, value); |
| 219 | 219 | ||
| 220 | if (ret == 0) | 220 | if (ret == 0) |
| 221 | trace_regmap_reg_read_cache(map->dev, reg, *value); | 221 | trace_regmap_reg_read_cache(map, reg, *value); |
| 222 | 222 | ||
| 223 | return ret; | 223 | return ret; |
| 224 | } | 224 | } |
| @@ -311,7 +311,7 @@ int regcache_sync(struct regmap *map) | |||
| 311 | dev_dbg(map->dev, "Syncing %s cache\n", | 311 | dev_dbg(map->dev, "Syncing %s cache\n", |
| 312 | map->cache_ops->name); | 312 | map->cache_ops->name); |
| 313 | name = map->cache_ops->name; | 313 | name = map->cache_ops->name; |
| 314 | trace_regcache_sync(map->dev, name, "start"); | 314 | trace_regcache_sync(map, name, "start"); |
| 315 | 315 | ||
| 316 | if (!map->cache_dirty) | 316 | if (!map->cache_dirty) |
| 317 | goto out; | 317 | goto out; |
| @@ -346,7 +346,7 @@ out: | |||
| 346 | 346 | ||
| 347 | regmap_async_complete(map); | 347 | regmap_async_complete(map); |
| 348 | 348 | ||
| 349 | trace_regcache_sync(map->dev, name, "stop"); | 349 | trace_regcache_sync(map, name, "stop"); |
| 350 | 350 | ||
| 351 | return ret; | 351 | return ret; |
| 352 | } | 352 | } |
| @@ -381,7 +381,7 @@ int regcache_sync_region(struct regmap *map, unsigned int min, | |||
| 381 | name = map->cache_ops->name; | 381 | name = map->cache_ops->name; |
| 382 | dev_dbg(map->dev, "Syncing %s cache from %d-%d\n", name, min, max); | 382 | dev_dbg(map->dev, "Syncing %s cache from %d-%d\n", name, min, max); |
| 383 | 383 | ||
| 384 | trace_regcache_sync(map->dev, name, "start region"); | 384 | trace_regcache_sync(map, name, "start region"); |
| 385 | 385 | ||
| 386 | if (!map->cache_dirty) | 386 | if (!map->cache_dirty) |
| 387 | goto out; | 387 | goto out; |
| @@ -401,7 +401,7 @@ out: | |||
| 401 | 401 | ||
| 402 | regmap_async_complete(map); | 402 | regmap_async_complete(map); |
| 403 | 403 | ||
| 404 | trace_regcache_sync(map->dev, name, "stop region"); | 404 | trace_regcache_sync(map, name, "stop region"); |
| 405 | 405 | ||
| 406 | return ret; | 406 | return ret; |
| 407 | } | 407 | } |
| @@ -428,7 +428,7 @@ int regcache_drop_region(struct regmap *map, unsigned int min, | |||
| 428 | 428 | ||
| 429 | map->lock(map->lock_arg); | 429 | map->lock(map->lock_arg); |
| 430 | 430 | ||
| 431 | trace_regcache_drop_region(map->dev, min, max); | 431 | trace_regcache_drop_region(map, min, max); |
| 432 | 432 | ||
| 433 | ret = map->cache_ops->drop(map, min, max); | 433 | ret = map->cache_ops->drop(map, min, max); |
| 434 | 434 | ||
| @@ -455,7 +455,7 @@ void regcache_cache_only(struct regmap *map, bool enable) | |||
| 455 | map->lock(map->lock_arg); | 455 | map->lock(map->lock_arg); |
| 456 | WARN_ON(map->cache_bypass && enable); | 456 | WARN_ON(map->cache_bypass && enable); |
| 457 | map->cache_only = enable; | 457 | map->cache_only = enable; |
| 458 | trace_regmap_cache_only(map->dev, enable); | 458 | trace_regmap_cache_only(map, enable); |
| 459 | map->unlock(map->lock_arg); | 459 | map->unlock(map->lock_arg); |
| 460 | } | 460 | } |
| 461 | EXPORT_SYMBOL_GPL(regcache_cache_only); | 461 | EXPORT_SYMBOL_GPL(regcache_cache_only); |
| @@ -493,7 +493,7 @@ void regcache_cache_bypass(struct regmap *map, bool enable) | |||
| 493 | map->lock(map->lock_arg); | 493 | map->lock(map->lock_arg); |
| 494 | WARN_ON(map->cache_only && enable); | 494 | WARN_ON(map->cache_only && enable); |
| 495 | map->cache_bypass = enable; | 495 | map->cache_bypass = enable; |
| 496 | trace_regmap_cache_bypass(map->dev, enable); | 496 | trace_regmap_cache_bypass(map, enable); |
| 497 | map->unlock(map->lock_arg); | 497 | map->unlock(map->lock_arg); |
| 498 | } | 498 | } |
| 499 | EXPORT_SYMBOL_GPL(regcache_cache_bypass); | 499 | EXPORT_SYMBOL_GPL(regcache_cache_bypass); |
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index f99b098ddabf..dbfe6a69c3da 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c | |||
| @@ -1281,7 +1281,7 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg, | |||
| 1281 | if (map->async && map->bus->async_write) { | 1281 | if (map->async && map->bus->async_write) { |
| 1282 | struct regmap_async *async; | 1282 | struct regmap_async *async; |
| 1283 | 1283 | ||
| 1284 | trace_regmap_async_write_start(map->dev, reg, val_len); | 1284 | trace_regmap_async_write_start(map, reg, val_len); |
| 1285 | 1285 | ||
| 1286 | spin_lock_irqsave(&map->async_lock, flags); | 1286 | spin_lock_irqsave(&map->async_lock, flags); |
| 1287 | async = list_first_entry_or_null(&map->async_free, | 1287 | async = list_first_entry_or_null(&map->async_free, |
| @@ -1339,8 +1339,7 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg, | |||
| 1339 | return ret; | 1339 | return ret; |
| 1340 | } | 1340 | } |
| 1341 | 1341 | ||
| 1342 | trace_regmap_hw_write_start(map->dev, reg, | 1342 | trace_regmap_hw_write_start(map, reg, val_len / map->format.val_bytes); |
| 1343 | val_len / map->format.val_bytes); | ||
| 1344 | 1343 | ||
| 1345 | /* If we're doing a single register write we can probably just | 1344 | /* If we're doing a single register write we can probably just |
| 1346 | * send the work_buf directly, otherwise try to do a gather | 1345 | * send the work_buf directly, otherwise try to do a gather |
| @@ -1372,8 +1371,7 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg, | |||
| 1372 | kfree(buf); | 1371 | kfree(buf); |
| 1373 | } | 1372 | } |
| 1374 | 1373 | ||
| 1375 | trace_regmap_hw_write_done(map->dev, reg, | 1374 | trace_regmap_hw_write_done(map, reg, val_len / map->format.val_bytes); |
| 1376 | val_len / map->format.val_bytes); | ||
| 1377 | 1375 | ||
| 1378 | return ret; | 1376 | return ret; |
| 1379 | } | 1377 | } |
| @@ -1407,12 +1405,12 @@ static int _regmap_bus_formatted_write(void *context, unsigned int reg, | |||
| 1407 | 1405 | ||
| 1408 | map->format.format_write(map, reg, val); | 1406 | map->format.format_write(map, reg, val); |
| 1409 | 1407 | ||
| 1410 | trace_regmap_hw_write_start(map->dev, reg, 1); | 1408 | trace_regmap_hw_write_start(map, reg, 1); |
| 1411 | 1409 | ||
| 1412 | ret = map->bus->write(map->bus_context, map->work_buf, | 1410 | ret = map->bus->write(map->bus_context, map->work_buf, |
| 1413 | map->format.buf_size); | 1411 | map->format.buf_size); |
| 1414 | 1412 | ||
| 1415 | trace_regmap_hw_write_done(map->dev, reg, 1); | 1413 | trace_regmap_hw_write_done(map, reg, 1); |
| 1416 | 1414 | ||
| 1417 | return ret; | 1415 | return ret; |
| 1418 | } | 1416 | } |
| @@ -1470,7 +1468,7 @@ int _regmap_write(struct regmap *map, unsigned int reg, | |||
| 1470 | dev_info(map->dev, "%x <= %x\n", reg, val); | 1468 | dev_info(map->dev, "%x <= %x\n", reg, val); |
| 1471 | #endif | 1469 | #endif |
| 1472 | 1470 | ||
| 1473 | trace_regmap_reg_write(map->dev, reg, val); | 1471 | trace_regmap_reg_write(map, reg, val); |
| 1474 | 1472 | ||
| 1475 | return map->reg_write(context, reg, val); | 1473 | return map->reg_write(context, reg, val); |
| 1476 | } | 1474 | } |
| @@ -1773,7 +1771,7 @@ static int _regmap_raw_multi_reg_write(struct regmap *map, | |||
| 1773 | for (i = 0; i < num_regs; i++) { | 1771 | for (i = 0; i < num_regs; i++) { |
| 1774 | int reg = regs[i].reg; | 1772 | int reg = regs[i].reg; |
| 1775 | int val = regs[i].def; | 1773 | int val = regs[i].def; |
| 1776 | trace_regmap_hw_write_start(map->dev, reg, 1); | 1774 | trace_regmap_hw_write_start(map, reg, 1); |
| 1777 | map->format.format_reg(u8, reg, map->reg_shift); | 1775 | map->format.format_reg(u8, reg, map->reg_shift); |
| 1778 | u8 += reg_bytes + pad_bytes; | 1776 | u8 += reg_bytes + pad_bytes; |
| 1779 | map->format.format_val(u8, val, 0); | 1777 | map->format.format_val(u8, val, 0); |
| @@ -1788,7 +1786,7 @@ static int _regmap_raw_multi_reg_write(struct regmap *map, | |||
| 1788 | 1786 | ||
| 1789 | for (i = 0; i < num_regs; i++) { | 1787 | for (i = 0; i < num_regs; i++) { |
| 1790 | int reg = regs[i].reg; | 1788 | int reg = regs[i].reg; |
| 1791 | trace_regmap_hw_write_done(map->dev, reg, 1); | 1789 | trace_regmap_hw_write_done(map, reg, 1); |
| 1792 | } | 1790 | } |
| 1793 | return ret; | 1791 | return ret; |
| 1794 | } | 1792 | } |
| @@ -2059,15 +2057,13 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, | |||
| 2059 | */ | 2057 | */ |
| 2060 | u8[0] |= map->read_flag_mask; | 2058 | u8[0] |= map->read_flag_mask; |
| 2061 | 2059 | ||
| 2062 | trace_regmap_hw_read_start(map->dev, reg, | 2060 | trace_regmap_hw_read_start(map, reg, val_len / map->format.val_bytes); |
| 2063 | val_len / map->format.val_bytes); | ||
| 2064 | 2061 | ||
| 2065 | ret = map->bus->read(map->bus_context, map->work_buf, | 2062 | ret = map->bus->read(map->bus_context, map->work_buf, |
| 2066 | map->format.reg_bytes + map->format.pad_bytes, | 2063 | map->format.reg_bytes + map->format.pad_bytes, |
| 2067 | val, val_len); | 2064 | val, val_len); |
| 2068 | 2065 | ||
| 2069 | trace_regmap_hw_read_done(map->dev, reg, | 2066 | trace_regmap_hw_read_done(map, reg, val_len / map->format.val_bytes); |
| 2070 | val_len / map->format.val_bytes); | ||
| 2071 | 2067 | ||
| 2072 | return ret; | 2068 | return ret; |
| 2073 | } | 2069 | } |
| @@ -2123,7 +2119,7 @@ static int _regmap_read(struct regmap *map, unsigned int reg, | |||
| 2123 | dev_info(map->dev, "%x => %x\n", reg, *val); | 2119 | dev_info(map->dev, "%x => %x\n", reg, *val); |
| 2124 | #endif | 2120 | #endif |
| 2125 | 2121 | ||
| 2126 | trace_regmap_reg_read(map->dev, reg, *val); | 2122 | trace_regmap_reg_read(map, reg, *val); |
| 2127 | 2123 | ||
| 2128 | if (!map->cache_bypass) | 2124 | if (!map->cache_bypass) |
| 2129 | regcache_write(map, reg, *val); | 2125 | regcache_write(map, reg, *val); |
| @@ -2480,7 +2476,7 @@ void regmap_async_complete_cb(struct regmap_async *async, int ret) | |||
| 2480 | struct regmap *map = async->map; | 2476 | struct regmap *map = async->map; |
| 2481 | bool wake; | 2477 | bool wake; |
| 2482 | 2478 | ||
| 2483 | trace_regmap_async_io_complete(map->dev); | 2479 | trace_regmap_async_io_complete(map); |
| 2484 | 2480 | ||
| 2485 | spin_lock(&map->async_lock); | 2481 | spin_lock(&map->async_lock); |
| 2486 | list_move(&async->list, &map->async_free); | 2482 | list_move(&async->list, &map->async_free); |
| @@ -2525,7 +2521,7 @@ int regmap_async_complete(struct regmap *map) | |||
| 2525 | if (!map->bus || !map->bus->async_write) | 2521 | if (!map->bus || !map->bus->async_write) |
| 2526 | return 0; | 2522 | return 0; |
| 2527 | 2523 | ||
| 2528 | trace_regmap_async_complete_start(map->dev); | 2524 | trace_regmap_async_complete_start(map); |
| 2529 | 2525 | ||
| 2530 | wait_event(map->async_waitq, regmap_async_is_done(map)); | 2526 | wait_event(map->async_waitq, regmap_async_is_done(map)); |
| 2531 | 2527 | ||
| @@ -2534,7 +2530,7 @@ int regmap_async_complete(struct regmap *map) | |||
| 2534 | map->async_ret = 0; | 2530 | map->async_ret = 0; |
| 2535 | spin_unlock_irqrestore(&map->async_lock, flags); | 2531 | spin_unlock_irqrestore(&map->async_lock, flags); |
| 2536 | 2532 | ||
| 2537 | trace_regmap_async_complete_done(map->dev); | 2533 | trace_regmap_async_complete_done(map); |
| 2538 | 2534 | ||
| 2539 | return ret; | 2535 | return ret; |
| 2540 | } | 2536 | } |
diff --git a/drivers/net/ethernet/amd/pcnet32.c b/drivers/net/ethernet/amd/pcnet32.c index 11d6e6561df1..15a8190a6f75 100644 --- a/drivers/net/ethernet/amd/pcnet32.c +++ b/drivers/net/ethernet/amd/pcnet32.c | |||
| @@ -1543,7 +1543,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) | |||
| 1543 | { | 1543 | { |
| 1544 | struct pcnet32_private *lp; | 1544 | struct pcnet32_private *lp; |
| 1545 | int i, media; | 1545 | int i, media; |
| 1546 | int fdx, mii, fset, dxsuflo; | 1546 | int fdx, mii, fset, dxsuflo, sram; |
| 1547 | int chip_version; | 1547 | int chip_version; |
| 1548 | char *chipname; | 1548 | char *chipname; |
| 1549 | struct net_device *dev; | 1549 | struct net_device *dev; |
| @@ -1580,7 +1580,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) | |||
| 1580 | } | 1580 | } |
| 1581 | 1581 | ||
| 1582 | /* initialize variables */ | 1582 | /* initialize variables */ |
| 1583 | fdx = mii = fset = dxsuflo = 0; | 1583 | fdx = mii = fset = dxsuflo = sram = 0; |
| 1584 | chip_version = (chip_version >> 12) & 0xffff; | 1584 | chip_version = (chip_version >> 12) & 0xffff; |
| 1585 | 1585 | ||
| 1586 | switch (chip_version) { | 1586 | switch (chip_version) { |
| @@ -1613,6 +1613,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) | |||
| 1613 | chipname = "PCnet/FAST III 79C973"; /* PCI */ | 1613 | chipname = "PCnet/FAST III 79C973"; /* PCI */ |
| 1614 | fdx = 1; | 1614 | fdx = 1; |
| 1615 | mii = 1; | 1615 | mii = 1; |
| 1616 | sram = 1; | ||
| 1616 | break; | 1617 | break; |
| 1617 | case 0x2626: | 1618 | case 0x2626: |
| 1618 | chipname = "PCnet/Home 79C978"; /* PCI */ | 1619 | chipname = "PCnet/Home 79C978"; /* PCI */ |
| @@ -1636,6 +1637,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) | |||
| 1636 | chipname = "PCnet/FAST III 79C975"; /* PCI */ | 1637 | chipname = "PCnet/FAST III 79C975"; /* PCI */ |
| 1637 | fdx = 1; | 1638 | fdx = 1; |
| 1638 | mii = 1; | 1639 | mii = 1; |
| 1640 | sram = 1; | ||
| 1639 | break; | 1641 | break; |
| 1640 | case 0x2628: | 1642 | case 0x2628: |
| 1641 | chipname = "PCnet/PRO 79C976"; | 1643 | chipname = "PCnet/PRO 79C976"; |
| @@ -1664,6 +1666,31 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) | |||
| 1664 | dxsuflo = 1; | 1666 | dxsuflo = 1; |
| 1665 | } | 1667 | } |
| 1666 | 1668 | ||
| 1669 | /* | ||
| 1670 | * The Am79C973/Am79C975 controllers come with 12K of SRAM | ||
| 1671 | * which we can use for the Tx/Rx buffers but most importantly, | ||
| 1672 | * the use of SRAM allow us to use the BCR18:NOUFLO bit to avoid | ||
| 1673 | * Tx fifo underflows. | ||
| 1674 | */ | ||
| 1675 | if (sram) { | ||
| 1676 | /* | ||
| 1677 | * The SRAM is being configured in two steps. First we | ||
| 1678 | * set the SRAM size in the BCR25:SRAM_SIZE bits. According | ||
| 1679 | * to the datasheet, each bit corresponds to a 512-byte | ||
| 1680 | * page so we can have at most 24 pages. The SRAM_SIZE | ||
| 1681 | * holds the value of the upper 8 bits of the 16-bit SRAM size. | ||
| 1682 | * The low 8-bits start at 0x00 and end at 0xff. So the | ||
| 1683 | * address range is from 0x0000 up to 0x17ff. Therefore, | ||
| 1684 | * the SRAM_SIZE is set to 0x17. The next step is to set | ||
| 1685 | * the BCR26:SRAM_BND midway through so the Tx and Rx | ||
| 1686 | * buffers can share the SRAM equally. | ||
| 1687 | */ | ||
| 1688 | a->write_bcr(ioaddr, 25, 0x17); | ||
| 1689 | a->write_bcr(ioaddr, 26, 0xc); | ||
| 1690 | /* And finally enable the NOUFLO bit */ | ||
| 1691 | a->write_bcr(ioaddr, 18, a->read_bcr(ioaddr, 18) | (1 << 11)); | ||
| 1692 | } | ||
| 1693 | |||
| 1667 | dev = alloc_etherdev(sizeof(*lp)); | 1694 | dev = alloc_etherdev(sizeof(*lp)); |
| 1668 | if (!dev) { | 1695 | if (!dev) { |
| 1669 | ret = -ENOMEM; | 1696 | ret = -ENOMEM; |
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index 27de37aa90af..27b9fe99a9bd 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h | |||
| @@ -354,6 +354,7 @@ struct be_vf_cfg { | |||
| 354 | u16 vlan_tag; | 354 | u16 vlan_tag; |
| 355 | u32 tx_rate; | 355 | u32 tx_rate; |
| 356 | u32 plink_tracking; | 356 | u32 plink_tracking; |
| 357 | u32 privileges; | ||
| 357 | }; | 358 | }; |
| 358 | 359 | ||
| 359 | enum vf_state { | 360 | enum vf_state { |
| @@ -423,6 +424,7 @@ struct be_adapter { | |||
| 423 | 424 | ||
| 424 | u8 __iomem *csr; /* CSR BAR used only for BE2/3 */ | 425 | u8 __iomem *csr; /* CSR BAR used only for BE2/3 */ |
| 425 | u8 __iomem *db; /* Door Bell */ | 426 | u8 __iomem *db; /* Door Bell */ |
| 427 | u8 __iomem *pcicfg; /* On SH,BEx only. Shadow of PCI config space */ | ||
| 426 | 428 | ||
| 427 | struct mutex mbox_lock; /* For serializing mbox cmds to BE card */ | 429 | struct mutex mbox_lock; /* For serializing mbox cmds to BE card */ |
| 428 | struct be_dma_mem mbox_mem; | 430 | struct be_dma_mem mbox_mem; |
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index 36916cfa70f9..7f05f309e935 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c | |||
| @@ -1902,15 +1902,11 @@ int be_cmd_modify_eqd(struct be_adapter *adapter, struct be_set_eqd *set_eqd, | |||
| 1902 | { | 1902 | { |
| 1903 | int num_eqs, i = 0; | 1903 | int num_eqs, i = 0; |
| 1904 | 1904 | ||
| 1905 | if (lancer_chip(adapter) && num > 8) { | 1905 | while (num) { |
| 1906 | while (num) { | 1906 | num_eqs = min(num, 8); |
| 1907 | num_eqs = min(num, 8); | 1907 | __be_cmd_modify_eqd(adapter, &set_eqd[i], num_eqs); |
| 1908 | __be_cmd_modify_eqd(adapter, &set_eqd[i], num_eqs); | 1908 | i += num_eqs; |
| 1909 | i += num_eqs; | 1909 | num -= num_eqs; |
| 1910 | num -= num_eqs; | ||
| 1911 | } | ||
| 1912 | } else { | ||
| 1913 | __be_cmd_modify_eqd(adapter, set_eqd, num); | ||
| 1914 | } | 1910 | } |
| 1915 | 1911 | ||
| 1916 | return 0; | 1912 | return 0; |
| @@ -1918,7 +1914,7 @@ int be_cmd_modify_eqd(struct be_adapter *adapter, struct be_set_eqd *set_eqd, | |||
| 1918 | 1914 | ||
| 1919 | /* Uses sycnhronous mcc */ | 1915 | /* Uses sycnhronous mcc */ |
| 1920 | int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array, | 1916 | int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array, |
| 1921 | u32 num) | 1917 | u32 num, u32 domain) |
| 1922 | { | 1918 | { |
| 1923 | struct be_mcc_wrb *wrb; | 1919 | struct be_mcc_wrb *wrb; |
| 1924 | struct be_cmd_req_vlan_config *req; | 1920 | struct be_cmd_req_vlan_config *req; |
| @@ -1936,6 +1932,7 @@ int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array, | |||
| 1936 | be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | 1932 | be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, |
| 1937 | OPCODE_COMMON_NTWK_VLAN_CONFIG, sizeof(*req), | 1933 | OPCODE_COMMON_NTWK_VLAN_CONFIG, sizeof(*req), |
| 1938 | wrb, NULL); | 1934 | wrb, NULL); |
| 1935 | req->hdr.domain = domain; | ||
| 1939 | 1936 | ||
| 1940 | req->interface_id = if_id; | 1937 | req->interface_id = if_id; |
| 1941 | req->untagged = BE_IF_FLAGS_UNTAGGED & be_if_cap_flags(adapter) ? 1 : 0; | 1938 | req->untagged = BE_IF_FLAGS_UNTAGGED & be_if_cap_flags(adapter) ? 1 : 0; |
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h index db761e8e42a3..a7634a3f052a 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.h +++ b/drivers/net/ethernet/emulex/benet/be_cmds.h | |||
| @@ -2256,7 +2256,7 @@ int lancer_cmd_get_pport_stats(struct be_adapter *adapter, | |||
| 2256 | int be_cmd_get_fw_ver(struct be_adapter *adapter); | 2256 | int be_cmd_get_fw_ver(struct be_adapter *adapter); |
| 2257 | int be_cmd_modify_eqd(struct be_adapter *adapter, struct be_set_eqd *, int num); | 2257 | int be_cmd_modify_eqd(struct be_adapter *adapter, struct be_set_eqd *, int num); |
| 2258 | int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array, | 2258 | int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array, |
| 2259 | u32 num); | 2259 | u32 num, u32 domain); |
| 2260 | int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 status); | 2260 | int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 status); |
| 2261 | int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc); | 2261 | int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc); |
| 2262 | int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc); | 2262 | int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc); |
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 0a816859aca5..e6b790f0d9dc 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c | |||
| @@ -1171,7 +1171,7 @@ static int be_vid_config(struct be_adapter *adapter) | |||
| 1171 | for_each_set_bit(i, adapter->vids, VLAN_N_VID) | 1171 | for_each_set_bit(i, adapter->vids, VLAN_N_VID) |
| 1172 | vids[num++] = cpu_to_le16(i); | 1172 | vids[num++] = cpu_to_le16(i); |
| 1173 | 1173 | ||
| 1174 | status = be_cmd_vlan_config(adapter, adapter->if_handle, vids, num); | 1174 | status = be_cmd_vlan_config(adapter, adapter->if_handle, vids, num, 0); |
| 1175 | if (status) { | 1175 | if (status) { |
| 1176 | dev_err(dev, "Setting HW VLAN filtering failed\n"); | 1176 | dev_err(dev, "Setting HW VLAN filtering failed\n"); |
| 1177 | /* Set to VLAN promisc mode as setting VLAN filter failed */ | 1177 | /* Set to VLAN promisc mode as setting VLAN filter failed */ |
| @@ -1380,11 +1380,67 @@ static int be_get_vf_config(struct net_device *netdev, int vf, | |||
| 1380 | return 0; | 1380 | return 0; |
| 1381 | } | 1381 | } |
| 1382 | 1382 | ||
| 1383 | static int be_set_vf_tvt(struct be_adapter *adapter, int vf, u16 vlan) | ||
| 1384 | { | ||
| 1385 | struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf]; | ||
| 1386 | u16 vids[BE_NUM_VLANS_SUPPORTED]; | ||
| 1387 | int vf_if_id = vf_cfg->if_handle; | ||
| 1388 | int status; | ||
| 1389 | |||
| 1390 | /* Enable Transparent VLAN Tagging */ | ||
| 1391 | status = be_cmd_set_hsw_config(adapter, vlan, vf + 1, vf_if_id, 0); | ||
| 1392 | if (status) | ||
| 1393 | return status; | ||
| 1394 | |||
| 1395 | /* Clear pre-programmed VLAN filters on VF if any, if TVT is enabled */ | ||
| 1396 | vids[0] = 0; | ||
| 1397 | status = be_cmd_vlan_config(adapter, vf_if_id, vids, 1, vf + 1); | ||
| 1398 | if (!status) | ||
| 1399 | dev_info(&adapter->pdev->dev, | ||
| 1400 | "Cleared guest VLANs on VF%d", vf); | ||
| 1401 | |||
| 1402 | /* After TVT is enabled, disallow VFs to program VLAN filters */ | ||
| 1403 | if (vf_cfg->privileges & BE_PRIV_FILTMGMT) { | ||
| 1404 | status = be_cmd_set_fn_privileges(adapter, vf_cfg->privileges & | ||
| 1405 | ~BE_PRIV_FILTMGMT, vf + 1); | ||
| 1406 | if (!status) | ||
| 1407 | vf_cfg->privileges &= ~BE_PRIV_FILTMGMT; | ||
| 1408 | } | ||
| 1409 | return 0; | ||
| 1410 | } | ||
| 1411 | |||
| 1412 | static int be_clear_vf_tvt(struct be_adapter *adapter, int vf) | ||
| 1413 | { | ||
| 1414 | struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf]; | ||
| 1415 | struct device *dev = &adapter->pdev->dev; | ||
| 1416 | int status; | ||
| 1417 | |||
| 1418 | /* Reset Transparent VLAN Tagging. */ | ||
| 1419 | status = be_cmd_set_hsw_config(adapter, BE_RESET_VLAN_TAG_ID, vf + 1, | ||
| 1420 | vf_cfg->if_handle, 0); | ||
| 1421 | if (status) | ||
| 1422 | return status; | ||
| 1423 | |||
| 1424 | /* Allow VFs to program VLAN filtering */ | ||
| 1425 | if (!(vf_cfg->privileges & BE_PRIV_FILTMGMT)) { | ||
| 1426 | status = be_cmd_set_fn_privileges(adapter, vf_cfg->privileges | | ||
| 1427 | BE_PRIV_FILTMGMT, vf + 1); | ||
| 1428 | if (!status) { | ||
| 1429 | vf_cfg->privileges |= BE_PRIV_FILTMGMT; | ||
| 1430 | dev_info(dev, "VF%d: FILTMGMT priv enabled", vf); | ||
| 1431 | } | ||
| 1432 | } | ||
| 1433 | |||
| 1434 | dev_info(dev, | ||
| 1435 | "Disable/re-enable i/f in VM to clear Transparent VLAN tag"); | ||
| 1436 | return 0; | ||
| 1437 | } | ||
| 1438 | |||
| 1383 | static int be_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos) | 1439 | static int be_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos) |
| 1384 | { | 1440 | { |
| 1385 | struct be_adapter *adapter = netdev_priv(netdev); | 1441 | struct be_adapter *adapter = netdev_priv(netdev); |
| 1386 | struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf]; | 1442 | struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf]; |
| 1387 | int status = 0; | 1443 | int status; |
| 1388 | 1444 | ||
| 1389 | if (!sriov_enabled(adapter)) | 1445 | if (!sriov_enabled(adapter)) |
| 1390 | return -EPERM; | 1446 | return -EPERM; |
| @@ -1394,24 +1450,19 @@ static int be_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos) | |||
| 1394 | 1450 | ||
| 1395 | if (vlan || qos) { | 1451 | if (vlan || qos) { |
| 1396 | vlan |= qos << VLAN_PRIO_SHIFT; | 1452 | vlan |= qos << VLAN_PRIO_SHIFT; |
| 1397 | if (vf_cfg->vlan_tag != vlan) | 1453 | status = be_set_vf_tvt(adapter, vf, vlan); |
| 1398 | status = be_cmd_set_hsw_config(adapter, vlan, vf + 1, | ||
| 1399 | vf_cfg->if_handle, 0); | ||
| 1400 | } else { | 1454 | } else { |
| 1401 | /* Reset Transparent Vlan Tagging. */ | 1455 | status = be_clear_vf_tvt(adapter, vf); |
| 1402 | status = be_cmd_set_hsw_config(adapter, BE_RESET_VLAN_TAG_ID, | ||
| 1403 | vf + 1, vf_cfg->if_handle, 0); | ||
| 1404 | } | 1456 | } |
| 1405 | 1457 | ||
| 1406 | if (status) { | 1458 | if (status) { |
| 1407 | dev_err(&adapter->pdev->dev, | 1459 | dev_err(&adapter->pdev->dev, |
| 1408 | "VLAN %d config on VF %d failed : %#x\n", vlan, | 1460 | "VLAN %d config on VF %d failed : %#x\n", vlan, vf, |
| 1409 | vf, status); | 1461 | status); |
| 1410 | return be_cmd_status(status); | 1462 | return be_cmd_status(status); |
| 1411 | } | 1463 | } |
| 1412 | 1464 | ||
| 1413 | vf_cfg->vlan_tag = vlan; | 1465 | vf_cfg->vlan_tag = vlan; |
| 1414 | |||
| 1415 | return 0; | 1466 | return 0; |
| 1416 | } | 1467 | } |
| 1417 | 1468 | ||
| @@ -2772,14 +2823,12 @@ void be_detect_error(struct be_adapter *adapter) | |||
| 2772 | } | 2823 | } |
| 2773 | } | 2824 | } |
| 2774 | } else { | 2825 | } else { |
| 2775 | pci_read_config_dword(adapter->pdev, | 2826 | ue_lo = ioread32(adapter->pcicfg + PCICFG_UE_STATUS_LOW); |
| 2776 | PCICFG_UE_STATUS_LOW, &ue_lo); | 2827 | ue_hi = ioread32(adapter->pcicfg + PCICFG_UE_STATUS_HIGH); |
| 2777 | pci_read_config_dword(adapter->pdev, | 2828 | ue_lo_mask = ioread32(adapter->pcicfg + |
| 2778 | PCICFG_UE_STATUS_HIGH, &ue_hi); | 2829 | PCICFG_UE_STATUS_LOW_MASK); |
| 2779 | pci_read_config_dword(adapter->pdev, | 2830 | ue_hi_mask = ioread32(adapter->pcicfg + |
| 2780 | PCICFG_UE_STATUS_LOW_MASK, &ue_lo_mask); | 2831 | PCICFG_UE_STATUS_HI_MASK); |
| 2781 | pci_read_config_dword(adapter->pdev, | ||
| 2782 | PCICFG_UE_STATUS_HI_MASK, &ue_hi_mask); | ||
| 2783 | 2832 | ||
| 2784 | ue_lo = (ue_lo & ~ue_lo_mask); | 2833 | ue_lo = (ue_lo & ~ue_lo_mask); |
| 2785 | ue_hi = (ue_hi & ~ue_hi_mask); | 2834 | ue_hi = (ue_hi & ~ue_hi_mask); |
| @@ -3339,7 +3388,6 @@ static int be_if_create(struct be_adapter *adapter, u32 *if_handle, | |||
| 3339 | u32 cap_flags, u32 vf) | 3388 | u32 cap_flags, u32 vf) |
| 3340 | { | 3389 | { |
| 3341 | u32 en_flags; | 3390 | u32 en_flags; |
| 3342 | int status; | ||
| 3343 | 3391 | ||
| 3344 | en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST | | 3392 | en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST | |
| 3345 | BE_IF_FLAGS_MULTICAST | BE_IF_FLAGS_PASS_L3L4_ERRORS | | 3393 | BE_IF_FLAGS_MULTICAST | BE_IF_FLAGS_PASS_L3L4_ERRORS | |
| @@ -3347,10 +3395,7 @@ static int be_if_create(struct be_adapter *adapter, u32 *if_handle, | |||
| 3347 | 3395 | ||
| 3348 | en_flags &= cap_flags; | 3396 | en_flags &= cap_flags; |
| 3349 | 3397 | ||
| 3350 | status = be_cmd_if_create(adapter, cap_flags, en_flags, | 3398 | return be_cmd_if_create(adapter, cap_flags, en_flags, if_handle, vf); |
| 3351 | if_handle, vf); | ||
| 3352 | |||
| 3353 | return status; | ||
| 3354 | } | 3399 | } |
| 3355 | 3400 | ||
| 3356 | static int be_vfs_if_create(struct be_adapter *adapter) | 3401 | static int be_vfs_if_create(struct be_adapter *adapter) |
| @@ -3368,8 +3413,13 @@ static int be_vfs_if_create(struct be_adapter *adapter) | |||
| 3368 | if (!BE3_chip(adapter)) { | 3413 | if (!BE3_chip(adapter)) { |
| 3369 | status = be_cmd_get_profile_config(adapter, &res, | 3414 | status = be_cmd_get_profile_config(adapter, &res, |
| 3370 | vf + 1); | 3415 | vf + 1); |
| 3371 | if (!status) | 3416 | if (!status) { |
| 3372 | cap_flags = res.if_cap_flags; | 3417 | cap_flags = res.if_cap_flags; |
| 3418 | /* Prevent VFs from enabling VLAN promiscuous | ||
| 3419 | * mode | ||
| 3420 | */ | ||
| 3421 | cap_flags &= ~BE_IF_FLAGS_VLAN_PROMISCUOUS; | ||
| 3422 | } | ||
| 3373 | } | 3423 | } |
| 3374 | 3424 | ||
| 3375 | status = be_if_create(adapter, &vf_cfg->if_handle, | 3425 | status = be_if_create(adapter, &vf_cfg->if_handle, |
| @@ -3403,7 +3453,6 @@ static int be_vf_setup(struct be_adapter *adapter) | |||
| 3403 | struct device *dev = &adapter->pdev->dev; | 3453 | struct device *dev = &adapter->pdev->dev; |
| 3404 | struct be_vf_cfg *vf_cfg; | 3454 | struct be_vf_cfg *vf_cfg; |
| 3405 | int status, old_vfs, vf; | 3455 | int status, old_vfs, vf; |
| 3406 | u32 privileges; | ||
| 3407 | 3456 | ||
| 3408 | old_vfs = pci_num_vf(adapter->pdev); | 3457 | old_vfs = pci_num_vf(adapter->pdev); |
| 3409 | 3458 | ||
| @@ -3433,15 +3482,18 @@ static int be_vf_setup(struct be_adapter *adapter) | |||
| 3433 | 3482 | ||
| 3434 | for_all_vfs(adapter, vf_cfg, vf) { | 3483 | for_all_vfs(adapter, vf_cfg, vf) { |
| 3435 | /* Allow VFs to programs MAC/VLAN filters */ | 3484 | /* Allow VFs to programs MAC/VLAN filters */ |
| 3436 | status = be_cmd_get_fn_privileges(adapter, &privileges, vf + 1); | 3485 | status = be_cmd_get_fn_privileges(adapter, &vf_cfg->privileges, |
| 3437 | if (!status && !(privileges & BE_PRIV_FILTMGMT)) { | 3486 | vf + 1); |
| 3487 | if (!status && !(vf_cfg->privileges & BE_PRIV_FILTMGMT)) { | ||
| 3438 | status = be_cmd_set_fn_privileges(adapter, | 3488 | status = be_cmd_set_fn_privileges(adapter, |
| 3439 | privileges | | 3489 | vf_cfg->privileges | |
| 3440 | BE_PRIV_FILTMGMT, | 3490 | BE_PRIV_FILTMGMT, |
| 3441 | vf + 1); | 3491 | vf + 1); |
| 3442 | if (!status) | 3492 | if (!status) { |
| 3493 | vf_cfg->privileges |= BE_PRIV_FILTMGMT; | ||
| 3443 | dev_info(dev, "VF%d has FILTMGMT privilege\n", | 3494 | dev_info(dev, "VF%d has FILTMGMT privilege\n", |
| 3444 | vf); | 3495 | vf); |
| 3496 | } | ||
| 3445 | } | 3497 | } |
| 3446 | 3498 | ||
| 3447 | /* Allow full available bandwidth */ | 3499 | /* Allow full available bandwidth */ |
| @@ -4820,24 +4872,37 @@ static int be_roce_map_pci_bars(struct be_adapter *adapter) | |||
| 4820 | 4872 | ||
| 4821 | static int be_map_pci_bars(struct be_adapter *adapter) | 4873 | static int be_map_pci_bars(struct be_adapter *adapter) |
| 4822 | { | 4874 | { |
| 4875 | struct pci_dev *pdev = adapter->pdev; | ||
| 4823 | u8 __iomem *addr; | 4876 | u8 __iomem *addr; |
| 4824 | 4877 | ||
| 4825 | if (BEx_chip(adapter) && be_physfn(adapter)) { | 4878 | if (BEx_chip(adapter) && be_physfn(adapter)) { |
| 4826 | adapter->csr = pci_iomap(adapter->pdev, 2, 0); | 4879 | adapter->csr = pci_iomap(pdev, 2, 0); |
| 4827 | if (!adapter->csr) | 4880 | if (!adapter->csr) |
| 4828 | return -ENOMEM; | 4881 | return -ENOMEM; |
| 4829 | } | 4882 | } |
| 4830 | 4883 | ||
| 4831 | addr = pci_iomap(adapter->pdev, db_bar(adapter), 0); | 4884 | addr = pci_iomap(pdev, db_bar(adapter), 0); |
| 4832 | if (!addr) | 4885 | if (!addr) |
| 4833 | goto pci_map_err; | 4886 | goto pci_map_err; |
| 4834 | adapter->db = addr; | 4887 | adapter->db = addr; |
| 4835 | 4888 | ||
| 4889 | if (skyhawk_chip(adapter) || BEx_chip(adapter)) { | ||
| 4890 | if (be_physfn(adapter)) { | ||
| 4891 | /* PCICFG is the 2nd BAR in BE2 */ | ||
| 4892 | addr = pci_iomap(pdev, BE2_chip(adapter) ? 1 : 0, 0); | ||
| 4893 | if (!addr) | ||
| 4894 | goto pci_map_err; | ||
| 4895 | adapter->pcicfg = addr; | ||
| 4896 | } else { | ||
| 4897 | adapter->pcicfg = adapter->db + SRIOV_VF_PCICFG_OFFSET; | ||
| 4898 | } | ||
| 4899 | } | ||
| 4900 | |||
| 4836 | be_roce_map_pci_bars(adapter); | 4901 | be_roce_map_pci_bars(adapter); |
| 4837 | return 0; | 4902 | return 0; |
| 4838 | 4903 | ||
| 4839 | pci_map_err: | 4904 | pci_map_err: |
| 4840 | dev_err(&adapter->pdev->dev, "Error in mapping PCI BARs\n"); | 4905 | dev_err(&pdev->dev, "Error in mapping PCI BARs\n"); |
| 4841 | be_unmap_pci_bars(adapter); | 4906 | be_unmap_pci_bars(adapter); |
| 4842 | return -ENOMEM; | 4907 | return -ENOMEM; |
| 4843 | } | 4908 | } |
diff --git a/drivers/net/usb/cx82310_eth.c b/drivers/net/usb/cx82310_eth.c index fe48f4c51373..1762ad3910b2 100644 --- a/drivers/net/usb/cx82310_eth.c +++ b/drivers/net/usb/cx82310_eth.c | |||
| @@ -46,8 +46,7 @@ enum cx82310_status { | |||
| 46 | }; | 46 | }; |
| 47 | 47 | ||
| 48 | #define CMD_PACKET_SIZE 64 | 48 | #define CMD_PACKET_SIZE 64 |
| 49 | /* first command after power on can take around 8 seconds */ | 49 | #define CMD_TIMEOUT 100 |
| 50 | #define CMD_TIMEOUT 15000 | ||
| 51 | #define CMD_REPLY_RETRY 5 | 50 | #define CMD_REPLY_RETRY 5 |
| 52 | 51 | ||
| 53 | #define CX82310_MTU 1514 | 52 | #define CX82310_MTU 1514 |
| @@ -78,8 +77,9 @@ static int cx82310_cmd(struct usbnet *dev, enum cx82310_cmd cmd, bool reply, | |||
| 78 | ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, CMD_EP), buf, | 77 | ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, CMD_EP), buf, |
| 79 | CMD_PACKET_SIZE, &actual_len, CMD_TIMEOUT); | 78 | CMD_PACKET_SIZE, &actual_len, CMD_TIMEOUT); |
| 80 | if (ret < 0) { | 79 | if (ret < 0) { |
| 81 | dev_err(&dev->udev->dev, "send command %#x: error %d\n", | 80 | if (cmd != CMD_GET_LINK_STATUS) |
| 82 | cmd, ret); | 81 | dev_err(&dev->udev->dev, "send command %#x: error %d\n", |
| 82 | cmd, ret); | ||
| 83 | goto end; | 83 | goto end; |
| 84 | } | 84 | } |
| 85 | 85 | ||
| @@ -90,8 +90,10 @@ static int cx82310_cmd(struct usbnet *dev, enum cx82310_cmd cmd, bool reply, | |||
| 90 | buf, CMD_PACKET_SIZE, &actual_len, | 90 | buf, CMD_PACKET_SIZE, &actual_len, |
| 91 | CMD_TIMEOUT); | 91 | CMD_TIMEOUT); |
| 92 | if (ret < 0) { | 92 | if (ret < 0) { |
| 93 | dev_err(&dev->udev->dev, | 93 | if (cmd != CMD_GET_LINK_STATUS) |
| 94 | "reply receive error %d\n", ret); | 94 | dev_err(&dev->udev->dev, |
| 95 | "reply receive error %d\n", | ||
| 96 | ret); | ||
| 95 | goto end; | 97 | goto end; |
| 96 | } | 98 | } |
| 97 | if (actual_len > 0) | 99 | if (actual_len > 0) |
| @@ -134,6 +136,8 @@ static int cx82310_bind(struct usbnet *dev, struct usb_interface *intf) | |||
| 134 | int ret; | 136 | int ret; |
| 135 | char buf[15]; | 137 | char buf[15]; |
| 136 | struct usb_device *udev = dev->udev; | 138 | struct usb_device *udev = dev->udev; |
| 139 | u8 link[3]; | ||
| 140 | int timeout = 50; | ||
| 137 | 141 | ||
| 138 | /* avoid ADSL modems - continue only if iProduct is "USB NET CARD" */ | 142 | /* avoid ADSL modems - continue only if iProduct is "USB NET CARD" */ |
| 139 | if (usb_string(udev, udev->descriptor.iProduct, buf, sizeof(buf)) > 0 | 143 | if (usb_string(udev, udev->descriptor.iProduct, buf, sizeof(buf)) > 0 |
| @@ -160,6 +164,20 @@ static int cx82310_bind(struct usbnet *dev, struct usb_interface *intf) | |||
| 160 | if (!dev->partial_data) | 164 | if (!dev->partial_data) |
| 161 | return -ENOMEM; | 165 | return -ENOMEM; |
| 162 | 166 | ||
| 167 | /* wait for firmware to become ready (indicated by the link being up) */ | ||
| 168 | while (--timeout) { | ||
| 169 | ret = cx82310_cmd(dev, CMD_GET_LINK_STATUS, true, NULL, 0, | ||
| 170 | link, sizeof(link)); | ||
| 171 | /* the command can time out during boot - it's not an error */ | ||
| 172 | if (!ret && link[0] == 1 && link[2] == 1) | ||
| 173 | break; | ||
| 174 | msleep(500); | ||
| 175 | }; | ||
| 176 | if (!timeout) { | ||
| 177 | dev_err(&udev->dev, "firmware not ready in time\n"); | ||
| 178 | return -ETIMEDOUT; | ||
| 179 | } | ||
| 180 | |||
| 163 | /* enable ethernet mode (?) */ | 181 | /* enable ethernet mode (?) */ |
| 164 | ret = cx82310_cmd(dev, CMD_ETHERNET_MODE, true, "\x01", 1, NULL, 0); | 182 | ret = cx82310_cmd(dev, CMD_ETHERNET_MODE, true, "\x01", 1, NULL, 0); |
| 165 | if (ret) { | 183 | if (ret) { |
