diff options
-rw-r--r-- | drivers/net/ethernet/cavium/liquidio/lio_core.c | 196 | ||||
-rw-r--r-- | drivers/net/ethernet/cavium/liquidio/lio_ethtool.c | 195 | ||||
-rw-r--r-- | drivers/net/ethernet/cavium/liquidio/lio_main.c | 20 | ||||
-rw-r--r-- | drivers/net/ethernet/cavium/liquidio/lio_vf_main.c | 5 | ||||
-rw-r--r-- | drivers/net/ethernet/cavium/liquidio/liquidio_common.h | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/cavium/liquidio/octeon_device.h | 14 | ||||
-rw-r--r-- | drivers/net/ethernet/cavium/liquidio/octeon_network.h | 15 |
7 files changed, 425 insertions, 24 deletions
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_core.c b/drivers/net/ethernet/cavium/liquidio/lio_core.c index 6821afcdc365..8093c5eafea2 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_core.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_core.c | |||
@@ -1481,3 +1481,199 @@ int octnet_get_link_stats(struct net_device *netdev) | |||
1481 | 1481 | ||
1482 | return 0; | 1482 | return 0; |
1483 | } | 1483 | } |
1484 | |||
1485 | static void liquidio_nic_seapi_ctl_callback(struct octeon_device *oct, | ||
1486 | u32 status, | ||
1487 | void *buf) | ||
1488 | { | ||
1489 | struct liquidio_nic_seapi_ctl_context *ctx; | ||
1490 | struct octeon_soft_command *sc = buf; | ||
1491 | |||
1492 | ctx = sc->ctxptr; | ||
1493 | |||
1494 | oct = lio_get_device(ctx->octeon_id); | ||
1495 | if (status) { | ||
1496 | dev_err(&oct->pci_dev->dev, "%s: instruction failed. Status: %llx\n", | ||
1497 | __func__, | ||
1498 | CVM_CAST64(status)); | ||
1499 | } | ||
1500 | ctx->status = status; | ||
1501 | complete(&ctx->complete); | ||
1502 | } | ||
1503 | |||
1504 | int liquidio_set_speed(struct lio *lio, int speed) | ||
1505 | { | ||
1506 | struct liquidio_nic_seapi_ctl_context *ctx; | ||
1507 | struct octeon_device *oct = lio->oct_dev; | ||
1508 | struct oct_nic_seapi_resp *resp; | ||
1509 | struct octeon_soft_command *sc; | ||
1510 | union octnet_cmd *ncmd; | ||
1511 | u32 ctx_size; | ||
1512 | int retval; | ||
1513 | u32 var; | ||
1514 | |||
1515 | if (oct->speed_setting == speed) | ||
1516 | return 0; | ||
1517 | |||
1518 | if (!OCTEON_CN23XX_PF(oct)) { | ||
1519 | dev_err(&oct->pci_dev->dev, "%s: SET SPEED only for PF\n", | ||
1520 | __func__); | ||
1521 | return -EOPNOTSUPP; | ||
1522 | } | ||
1523 | |||
1524 | ctx_size = sizeof(struct liquidio_nic_seapi_ctl_context); | ||
1525 | sc = octeon_alloc_soft_command(oct, OCTNET_CMD_SIZE, | ||
1526 | sizeof(struct oct_nic_seapi_resp), | ||
1527 | ctx_size); | ||
1528 | if (!sc) | ||
1529 | return -ENOMEM; | ||
1530 | |||
1531 | ncmd = sc->virtdptr; | ||
1532 | ctx = sc->ctxptr; | ||
1533 | resp = sc->virtrptr; | ||
1534 | memset(resp, 0, sizeof(struct oct_nic_seapi_resp)); | ||
1535 | |||
1536 | ctx->octeon_id = lio_get_device_id(oct); | ||
1537 | ctx->status = 0; | ||
1538 | init_completion(&ctx->complete); | ||
1539 | |||
1540 | ncmd->u64 = 0; | ||
1541 | ncmd->s.cmd = SEAPI_CMD_SPEED_SET; | ||
1542 | ncmd->s.param1 = speed; | ||
1543 | |||
1544 | octeon_swap_8B_data((u64 *)ncmd, (OCTNET_CMD_SIZE >> 3)); | ||
1545 | |||
1546 | sc->iq_no = lio->linfo.txpciq[0].s.q_no; | ||
1547 | |||
1548 | octeon_prepare_soft_command(oct, sc, OPCODE_NIC, | ||
1549 | OPCODE_NIC_UBOOT_CTL, 0, 0, 0); | ||
1550 | |||
1551 | sc->callback = liquidio_nic_seapi_ctl_callback; | ||
1552 | sc->callback_arg = sc; | ||
1553 | sc->wait_time = 5000; | ||
1554 | |||
1555 | retval = octeon_send_soft_command(oct, sc); | ||
1556 | if (retval == IQ_SEND_FAILED) { | ||
1557 | dev_info(&oct->pci_dev->dev, "Failed to send soft command\n"); | ||
1558 | retval = -EBUSY; | ||
1559 | } else { | ||
1560 | /* Wait for response or timeout */ | ||
1561 | if (wait_for_completion_timeout(&ctx->complete, | ||
1562 | msecs_to_jiffies(10000)) == 0) { | ||
1563 | dev_err(&oct->pci_dev->dev, "%s: sc timeout\n", | ||
1564 | __func__); | ||
1565 | octeon_free_soft_command(oct, sc); | ||
1566 | return -EINTR; | ||
1567 | } | ||
1568 | |||
1569 | retval = resp->status; | ||
1570 | |||
1571 | if (retval) { | ||
1572 | dev_err(&oct->pci_dev->dev, "%s failed, retval=%d\n", | ||
1573 | __func__, retval); | ||
1574 | octeon_free_soft_command(oct, sc); | ||
1575 | return -EIO; | ||
1576 | } | ||
1577 | |||
1578 | var = be32_to_cpu((__force __be32)resp->speed); | ||
1579 | if (var != speed) { | ||
1580 | dev_err(&oct->pci_dev->dev, | ||
1581 | "%s: setting failed speed= %x, expect %x\n", | ||
1582 | __func__, var, speed); | ||
1583 | } | ||
1584 | |||
1585 | oct->speed_setting = var; | ||
1586 | } | ||
1587 | |||
1588 | octeon_free_soft_command(oct, sc); | ||
1589 | |||
1590 | return retval; | ||
1591 | } | ||
1592 | |||
1593 | int liquidio_get_speed(struct lio *lio) | ||
1594 | { | ||
1595 | struct liquidio_nic_seapi_ctl_context *ctx; | ||
1596 | struct octeon_device *oct = lio->oct_dev; | ||
1597 | struct oct_nic_seapi_resp *resp; | ||
1598 | struct octeon_soft_command *sc; | ||
1599 | union octnet_cmd *ncmd; | ||
1600 | u32 ctx_size; | ||
1601 | int retval; | ||
1602 | |||
1603 | ctx_size = sizeof(struct liquidio_nic_seapi_ctl_context); | ||
1604 | sc = octeon_alloc_soft_command(oct, OCTNET_CMD_SIZE, | ||
1605 | sizeof(struct oct_nic_seapi_resp), | ||
1606 | ctx_size); | ||
1607 | if (!sc) | ||
1608 | return -ENOMEM; | ||
1609 | |||
1610 | ncmd = sc->virtdptr; | ||
1611 | ctx = sc->ctxptr; | ||
1612 | resp = sc->virtrptr; | ||
1613 | memset(resp, 0, sizeof(struct oct_nic_seapi_resp)); | ||
1614 | |||
1615 | ctx->octeon_id = lio_get_device_id(oct); | ||
1616 | ctx->status = 0; | ||
1617 | init_completion(&ctx->complete); | ||
1618 | |||
1619 | ncmd->u64 = 0; | ||
1620 | ncmd->s.cmd = SEAPI_CMD_SPEED_GET; | ||
1621 | |||
1622 | octeon_swap_8B_data((u64 *)ncmd, (OCTNET_CMD_SIZE >> 3)); | ||
1623 | |||
1624 | sc->iq_no = lio->linfo.txpciq[0].s.q_no; | ||
1625 | |||
1626 | octeon_prepare_soft_command(oct, sc, OPCODE_NIC, | ||
1627 | OPCODE_NIC_UBOOT_CTL, 0, 0, 0); | ||
1628 | |||
1629 | sc->callback = liquidio_nic_seapi_ctl_callback; | ||
1630 | sc->callback_arg = sc; | ||
1631 | sc->wait_time = 5000; | ||
1632 | |||
1633 | retval = octeon_send_soft_command(oct, sc); | ||
1634 | if (retval == IQ_SEND_FAILED) { | ||
1635 | dev_info(&oct->pci_dev->dev, "Failed to send soft command\n"); | ||
1636 | oct->no_speed_setting = 1; | ||
1637 | oct->speed_setting = 25; | ||
1638 | |||
1639 | retval = -EBUSY; | ||
1640 | } else { | ||
1641 | if (wait_for_completion_timeout(&ctx->complete, | ||
1642 | msecs_to_jiffies(10000)) == 0) { | ||
1643 | dev_err(&oct->pci_dev->dev, "%s: sc timeout\n", | ||
1644 | __func__); | ||
1645 | |||
1646 | oct->speed_setting = 25; | ||
1647 | oct->no_speed_setting = 1; | ||
1648 | |||
1649 | octeon_free_soft_command(oct, sc); | ||
1650 | |||
1651 | return -EINTR; | ||
1652 | } | ||
1653 | retval = resp->status; | ||
1654 | if (retval) { | ||
1655 | dev_err(&oct->pci_dev->dev, | ||
1656 | "%s failed retval=%d\n", __func__, retval); | ||
1657 | oct->no_speed_setting = 1; | ||
1658 | oct->speed_setting = 25; | ||
1659 | octeon_free_soft_command(oct, sc); | ||
1660 | retval = -EIO; | ||
1661 | } else { | ||
1662 | u32 var; | ||
1663 | |||
1664 | var = be32_to_cpu((__force __be32)resp->speed); | ||
1665 | oct->speed_setting = var; | ||
1666 | if (var == 0xffff) { | ||
1667 | oct->no_speed_setting = 1; | ||
1668 | /* unable to access boot variables | ||
1669 | * get the default value based on the NIC type | ||
1670 | */ | ||
1671 | oct->speed_setting = 25; | ||
1672 | } | ||
1673 | } | ||
1674 | } | ||
1675 | |||
1676 | octeon_free_soft_command(oct, sc); | ||
1677 | |||
1678 | return retval; | ||
1679 | } | ||
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c b/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c index a1d84304a608..06f7449c569d 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c | |||
@@ -230,46 +230,147 @@ static int lio_get_link_ksettings(struct net_device *netdev, | |||
230 | struct lio *lio = GET_LIO(netdev); | 230 | struct lio *lio = GET_LIO(netdev); |
231 | struct octeon_device *oct = lio->oct_dev; | 231 | struct octeon_device *oct = lio->oct_dev; |
232 | struct oct_link_info *linfo; | 232 | struct oct_link_info *linfo; |
233 | u32 supported = 0, advertising = 0; | ||
234 | 233 | ||
235 | linfo = &lio->linfo; | 234 | linfo = &lio->linfo; |
236 | 235 | ||
236 | ethtool_link_ksettings_zero_link_mode(ecmd, supported); | ||
237 | ethtool_link_ksettings_zero_link_mode(ecmd, advertising); | ||
238 | |||
237 | switch (linfo->link.s.phy_type) { | 239 | switch (linfo->link.s.phy_type) { |
238 | case LIO_PHY_PORT_TP: | 240 | case LIO_PHY_PORT_TP: |
239 | ecmd->base.port = PORT_TP; | 241 | ecmd->base.port = PORT_TP; |
240 | supported = (SUPPORTED_10000baseT_Full | | ||
241 | SUPPORTED_TP | SUPPORTED_Pause); | ||
242 | advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_Pause); | ||
243 | ecmd->base.autoneg = AUTONEG_DISABLE; | 242 | ecmd->base.autoneg = AUTONEG_DISABLE; |
243 | ethtool_link_ksettings_add_link_mode(ecmd, supported, TP); | ||
244 | ethtool_link_ksettings_add_link_mode(ecmd, supported, Pause); | ||
245 | ethtool_link_ksettings_add_link_mode(ecmd, supported, | ||
246 | 10000baseT_Full); | ||
247 | |||
248 | ethtool_link_ksettings_add_link_mode(ecmd, advertising, Pause); | ||
249 | ethtool_link_ksettings_add_link_mode(ecmd, advertising, | ||
250 | 10000baseT_Full); | ||
251 | |||
244 | break; | 252 | break; |
245 | 253 | ||
246 | case LIO_PHY_PORT_FIBRE: | 254 | case LIO_PHY_PORT_FIBRE: |
247 | ecmd->base.port = PORT_FIBRE; | 255 | if (linfo->link.s.if_mode == INTERFACE_MODE_XAUI || |
248 | 256 | linfo->link.s.if_mode == INTERFACE_MODE_RXAUI || | |
249 | if (linfo->link.s.speed == SPEED_10000) { | 257 | linfo->link.s.if_mode == INTERFACE_MODE_XLAUI || |
250 | supported = SUPPORTED_10000baseT_Full; | 258 | linfo->link.s.if_mode == INTERFACE_MODE_XFI) { |
251 | advertising = ADVERTISED_10000baseT_Full; | 259 | dev_dbg(&oct->pci_dev->dev, "ecmd->base.transceiver is XCVR_EXTERNAL\n"); |
260 | } else { | ||
261 | dev_err(&oct->pci_dev->dev, "Unknown link interface mode: %d\n", | ||
262 | linfo->link.s.if_mode); | ||
252 | } | 263 | } |
253 | 264 | ||
254 | supported |= SUPPORTED_FIBRE | SUPPORTED_Pause; | 265 | ecmd->base.port = PORT_FIBRE; |
255 | advertising |= ADVERTISED_Pause; | ||
256 | ecmd->base.autoneg = AUTONEG_DISABLE; | 266 | ecmd->base.autoneg = AUTONEG_DISABLE; |
267 | ethtool_link_ksettings_add_link_mode(ecmd, supported, FIBRE); | ||
268 | |||
269 | ethtool_link_ksettings_add_link_mode(ecmd, supported, Pause); | ||
270 | ethtool_link_ksettings_add_link_mode(ecmd, advertising, Pause); | ||
271 | if (oct->subsystem_id == OCTEON_CN2350_25GB_SUBSYS_ID || | ||
272 | oct->subsystem_id == OCTEON_CN2360_25GB_SUBSYS_ID) { | ||
273 | if (OCTEON_CN23XX_PF(oct)) { | ||
274 | ethtool_link_ksettings_add_link_mode | ||
275 | (ecmd, supported, 25000baseSR_Full); | ||
276 | ethtool_link_ksettings_add_link_mode | ||
277 | (ecmd, supported, 25000baseKR_Full); | ||
278 | ethtool_link_ksettings_add_link_mode | ||
279 | (ecmd, supported, 25000baseCR_Full); | ||
280 | |||
281 | if (oct->no_speed_setting == 0) { | ||
282 | ethtool_link_ksettings_add_link_mode | ||
283 | (ecmd, supported, | ||
284 | 10000baseSR_Full); | ||
285 | ethtool_link_ksettings_add_link_mode | ||
286 | (ecmd, supported, | ||
287 | 10000baseKR_Full); | ||
288 | ethtool_link_ksettings_add_link_mode | ||
289 | (ecmd, supported, | ||
290 | 10000baseCR_Full); | ||
291 | } | ||
292 | |||
293 | if (oct->no_speed_setting == 0) | ||
294 | liquidio_get_speed(lio); | ||
295 | else | ||
296 | oct->speed_setting = 25; | ||
297 | |||
298 | if (oct->speed_setting == 10) { | ||
299 | ethtool_link_ksettings_add_link_mode | ||
300 | (ecmd, advertising, | ||
301 | 10000baseSR_Full); | ||
302 | ethtool_link_ksettings_add_link_mode | ||
303 | (ecmd, advertising, | ||
304 | 10000baseKR_Full); | ||
305 | ethtool_link_ksettings_add_link_mode | ||
306 | (ecmd, advertising, | ||
307 | 10000baseCR_Full); | ||
308 | } | ||
309 | if (oct->speed_setting == 25) { | ||
310 | ethtool_link_ksettings_add_link_mode | ||
311 | (ecmd, advertising, | ||
312 | 25000baseSR_Full); | ||
313 | ethtool_link_ksettings_add_link_mode | ||
314 | (ecmd, advertising, | ||
315 | 25000baseKR_Full); | ||
316 | ethtool_link_ksettings_add_link_mode | ||
317 | (ecmd, advertising, | ||
318 | 25000baseCR_Full); | ||
319 | } | ||
320 | } else { /* VF */ | ||
321 | if (linfo->link.s.speed == 10000) { | ||
322 | ethtool_link_ksettings_add_link_mode | ||
323 | (ecmd, supported, | ||
324 | 10000baseSR_Full); | ||
325 | ethtool_link_ksettings_add_link_mode | ||
326 | (ecmd, supported, | ||
327 | 10000baseKR_Full); | ||
328 | ethtool_link_ksettings_add_link_mode | ||
329 | (ecmd, supported, | ||
330 | 10000baseCR_Full); | ||
331 | |||
332 | ethtool_link_ksettings_add_link_mode | ||
333 | (ecmd, advertising, | ||
334 | 10000baseSR_Full); | ||
335 | ethtool_link_ksettings_add_link_mode | ||
336 | (ecmd, advertising, | ||
337 | 10000baseKR_Full); | ||
338 | ethtool_link_ksettings_add_link_mode | ||
339 | (ecmd, advertising, | ||
340 | 10000baseCR_Full); | ||
341 | } | ||
342 | |||
343 | if (linfo->link.s.speed == 25000) { | ||
344 | ethtool_link_ksettings_add_link_mode | ||
345 | (ecmd, supported, | ||
346 | 25000baseSR_Full); | ||
347 | ethtool_link_ksettings_add_link_mode | ||
348 | (ecmd, supported, | ||
349 | 25000baseKR_Full); | ||
350 | ethtool_link_ksettings_add_link_mode | ||
351 | (ecmd, supported, | ||
352 | 25000baseCR_Full); | ||
353 | |||
354 | ethtool_link_ksettings_add_link_mode | ||
355 | (ecmd, advertising, | ||
356 | 25000baseSR_Full); | ||
357 | ethtool_link_ksettings_add_link_mode | ||
358 | (ecmd, advertising, | ||
359 | 25000baseKR_Full); | ||
360 | ethtool_link_ksettings_add_link_mode | ||
361 | (ecmd, advertising, | ||
362 | 25000baseCR_Full); | ||
363 | } | ||
364 | } | ||
365 | } else { | ||
366 | ethtool_link_ksettings_add_link_mode(ecmd, supported, | ||
367 | 10000baseT_Full); | ||
368 | ethtool_link_ksettings_add_link_mode(ecmd, advertising, | ||
369 | 10000baseT_Full); | ||
370 | } | ||
257 | break; | 371 | break; |
258 | } | 372 | } |
259 | 373 | ||
260 | if (linfo->link.s.if_mode == INTERFACE_MODE_XAUI || | ||
261 | linfo->link.s.if_mode == INTERFACE_MODE_RXAUI || | ||
262 | linfo->link.s.if_mode == INTERFACE_MODE_XLAUI || | ||
263 | linfo->link.s.if_mode == INTERFACE_MODE_XFI) { | ||
264 | ethtool_convert_legacy_u32_to_link_mode( | ||
265 | ecmd->link_modes.supported, supported); | ||
266 | ethtool_convert_legacy_u32_to_link_mode( | ||
267 | ecmd->link_modes.advertising, advertising); | ||
268 | } else { | ||
269 | dev_err(&oct->pci_dev->dev, "Unknown link interface reported %d\n", | ||
270 | linfo->link.s.if_mode); | ||
271 | } | ||
272 | |||
273 | if (linfo->link.s.link_up) { | 374 | if (linfo->link.s.link_up) { |
274 | ecmd->base.speed = linfo->link.s.speed; | 375 | ecmd->base.speed = linfo->link.s.speed; |
275 | ecmd->base.duplex = linfo->link.s.duplex; | 376 | ecmd->base.duplex = linfo->link.s.duplex; |
@@ -281,6 +382,51 @@ static int lio_get_link_ksettings(struct net_device *netdev, | |||
281 | return 0; | 382 | return 0; |
282 | } | 383 | } |
283 | 384 | ||
385 | static int lio_set_link_ksettings(struct net_device *netdev, | ||
386 | const struct ethtool_link_ksettings *ecmd) | ||
387 | { | ||
388 | const int speed = ecmd->base.speed; | ||
389 | struct lio *lio = GET_LIO(netdev); | ||
390 | struct oct_link_info *linfo; | ||
391 | struct octeon_device *oct; | ||
392 | u32 is25G = 0; | ||
393 | |||
394 | oct = lio->oct_dev; | ||
395 | |||
396 | linfo = &lio->linfo; | ||
397 | |||
398 | if (oct->subsystem_id == OCTEON_CN2350_25GB_SUBSYS_ID || | ||
399 | oct->subsystem_id == OCTEON_CN2360_25GB_SUBSYS_ID) { | ||
400 | is25G = 1; | ||
401 | } else { | ||
402 | return -EOPNOTSUPP; | ||
403 | } | ||
404 | |||
405 | if (oct->no_speed_setting) { | ||
406 | dev_err(&oct->pci_dev->dev, "%s: Changing speed is not supported\n", | ||
407 | __func__); | ||
408 | return -EOPNOTSUPP; | ||
409 | } | ||
410 | |||
411 | if ((ecmd->base.duplex != DUPLEX_UNKNOWN && | ||
412 | ecmd->base.duplex != linfo->link.s.duplex) || | ||
413 | ecmd->base.autoneg != AUTONEG_DISABLE || | ||
414 | (ecmd->base.speed != 10000 && ecmd->base.speed != 25000 && | ||
415 | ecmd->base.speed != SPEED_UNKNOWN)) | ||
416 | return -EOPNOTSUPP; | ||
417 | |||
418 | if ((oct->speed_boot == speed / 1000) && | ||
419 | oct->speed_boot == oct->speed_setting) | ||
420 | return 0; | ||
421 | |||
422 | liquidio_set_speed(lio, speed / 1000); | ||
423 | |||
424 | dev_dbg(&oct->pci_dev->dev, "Port speed is set to %dG\n", | ||
425 | oct->speed_setting); | ||
426 | |||
427 | return 0; | ||
428 | } | ||
429 | |||
284 | static void | 430 | static void |
285 | lio_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) | 431 | lio_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) |
286 | { | 432 | { |
@@ -2966,6 +3112,7 @@ static int lio_set_priv_flags(struct net_device *netdev, u32 flags) | |||
2966 | 3112 | ||
2967 | static const struct ethtool_ops lio_ethtool_ops = { | 3113 | static const struct ethtool_ops lio_ethtool_ops = { |
2968 | .get_link_ksettings = lio_get_link_ksettings, | 3114 | .get_link_ksettings = lio_get_link_ksettings, |
3115 | .set_link_ksettings = lio_set_link_ksettings, | ||
2969 | .get_link = ethtool_op_get_link, | 3116 | .get_link = ethtool_op_get_link, |
2970 | .get_drvinfo = lio_get_drvinfo, | 3117 | .get_drvinfo = lio_get_drvinfo, |
2971 | .get_ringparam = lio_ethtool_get_ringparam, | 3118 | .get_ringparam = lio_ethtool_get_ringparam, |
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c index ee75048b3937..e500528ad751 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_main.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c | |||
@@ -912,6 +912,9 @@ liquidio_probe(struct pci_dev *pdev, | |||
912 | /* set linux specific device pointer */ | 912 | /* set linux specific device pointer */ |
913 | oct_dev->pci_dev = (void *)pdev; | 913 | oct_dev->pci_dev = (void *)pdev; |
914 | 914 | ||
915 | oct_dev->subsystem_id = pdev->subsystem_vendor | | ||
916 | (pdev->subsystem_device << 16); | ||
917 | |||
915 | hs = &handshake[oct_dev->octeon_id]; | 918 | hs = &handshake[oct_dev->octeon_id]; |
916 | init_completion(&hs->init); | 919 | init_completion(&hs->init); |
917 | init_completion(&hs->started); | 920 | init_completion(&hs->started); |
@@ -3664,6 +3667,23 @@ static int setup_nic_devices(struct octeon_device *octeon_dev) | |||
3664 | "NIC ifidx:%d Setup successful\n", i); | 3667 | "NIC ifidx:%d Setup successful\n", i); |
3665 | 3668 | ||
3666 | octeon_free_soft_command(octeon_dev, sc); | 3669 | octeon_free_soft_command(octeon_dev, sc); |
3670 | |||
3671 | if (octeon_dev->subsystem_id == | ||
3672 | OCTEON_CN2350_25GB_SUBSYS_ID || | ||
3673 | octeon_dev->subsystem_id == | ||
3674 | OCTEON_CN2360_25GB_SUBSYS_ID) { | ||
3675 | liquidio_get_speed(lio); | ||
3676 | |||
3677 | if (octeon_dev->speed_setting == 0) { | ||
3678 | octeon_dev->speed_setting = 25; | ||
3679 | octeon_dev->no_speed_setting = 1; | ||
3680 | } | ||
3681 | } else { | ||
3682 | octeon_dev->no_speed_setting = 1; | ||
3683 | octeon_dev->speed_setting = 10; | ||
3684 | } | ||
3685 | octeon_dev->speed_boot = octeon_dev->speed_setting; | ||
3686 | |||
3667 | } | 3687 | } |
3668 | 3688 | ||
3669 | devlink = devlink_alloc(&liquidio_devlink_ops, | 3689 | devlink = devlink_alloc(&liquidio_devlink_ops, |
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c index 6295eeec795c..7fa0212873ac 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c | |||
@@ -411,6 +411,9 @@ liquidio_vf_probe(struct pci_dev *pdev, | |||
411 | /* set linux specific device pointer */ | 411 | /* set linux specific device pointer */ |
412 | oct_dev->pci_dev = pdev; | 412 | oct_dev->pci_dev = pdev; |
413 | 413 | ||
414 | oct_dev->subsystem_id = pdev->subsystem_vendor | | ||
415 | (pdev->subsystem_device << 16); | ||
416 | |||
414 | if (octeon_device_init(oct_dev)) { | 417 | if (octeon_device_init(oct_dev)) { |
415 | liquidio_vf_remove(pdev); | 418 | liquidio_vf_remove(pdev); |
416 | return -ENOMEM; | 419 | return -ENOMEM; |
@@ -2199,6 +2202,8 @@ static int setup_nic_devices(struct octeon_device *octeon_dev) | |||
2199 | "NIC ifidx:%d Setup successful\n", i); | 2202 | "NIC ifidx:%d Setup successful\n", i); |
2200 | 2203 | ||
2201 | octeon_free_soft_command(octeon_dev, sc); | 2204 | octeon_free_soft_command(octeon_dev, sc); |
2205 | |||
2206 | octeon_dev->no_speed_setting = 1; | ||
2202 | } | 2207 | } |
2203 | 2208 | ||
2204 | return 0; | 2209 | return 0; |
diff --git a/drivers/net/ethernet/cavium/liquidio/liquidio_common.h b/drivers/net/ethernet/cavium/liquidio/liquidio_common.h index 026570499dcf..285b24836974 100644 --- a/drivers/net/ethernet/cavium/liquidio/liquidio_common.h +++ b/drivers/net/ethernet/cavium/liquidio/liquidio_common.h | |||
@@ -93,6 +93,7 @@ enum octeon_tag_type { | |||
93 | 93 | ||
94 | #define OPCODE_NIC_VF_REP_PKT 0x15 | 94 | #define OPCODE_NIC_VF_REP_PKT 0x15 |
95 | #define OPCODE_NIC_VF_REP_CMD 0x16 | 95 | #define OPCODE_NIC_VF_REP_CMD 0x16 |
96 | #define OPCODE_NIC_UBOOT_CTL 0x17 | ||
96 | 97 | ||
97 | #define CORE_DRV_TEST_SCATTER_OP 0xFFF5 | 98 | #define CORE_DRV_TEST_SCATTER_OP 0xFFF5 |
98 | 99 | ||
@@ -249,6 +250,9 @@ static inline void add_sg_size(struct octeon_sg_entry *sg_entry, | |||
249 | #define OCTNET_CMD_VLAN_FILTER_ENABLE 0x1 | 250 | #define OCTNET_CMD_VLAN_FILTER_ENABLE 0x1 |
250 | #define OCTNET_CMD_VLAN_FILTER_DISABLE 0x0 | 251 | #define OCTNET_CMD_VLAN_FILTER_DISABLE 0x0 |
251 | 252 | ||
253 | #define SEAPI_CMD_SPEED_SET 0x2 | ||
254 | #define SEAPI_CMD_SPEED_GET 0x3 | ||
255 | |||
252 | #define LIO_CMD_WAIT_TM 100 | 256 | #define LIO_CMD_WAIT_TM 100 |
253 | 257 | ||
254 | /* RX(packets coming from wire) Checksum verification flags */ | 258 | /* RX(packets coming from wire) Checksum verification flags */ |
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_device.h b/drivers/net/ethernet/cavium/liquidio/octeon_device.h index 9430c0a0bb8c..94a4ed88d618 100644 --- a/drivers/net/ethernet/cavium/liquidio/octeon_device.h +++ b/drivers/net/ethernet/cavium/liquidio/octeon_device.h | |||
@@ -43,6 +43,13 @@ | |||
43 | #define OCTEON_CN23XX_REV_1_1 0x01 | 43 | #define OCTEON_CN23XX_REV_1_1 0x01 |
44 | #define OCTEON_CN23XX_REV_2_0 0x80 | 44 | #define OCTEON_CN23XX_REV_2_0 0x80 |
45 | 45 | ||
46 | /**SubsystemId for the chips */ | ||
47 | #define OCTEON_CN2350_10GB_SUBSYS_ID_1 0X3177d | ||
48 | #define OCTEON_CN2350_10GB_SUBSYS_ID_2 0X4177d | ||
49 | #define OCTEON_CN2360_10GB_SUBSYS_ID 0X5177d | ||
50 | #define OCTEON_CN2350_25GB_SUBSYS_ID 0X7177d | ||
51 | #define OCTEON_CN2360_25GB_SUBSYS_ID 0X6177d | ||
52 | |||
46 | /** Endian-swap modes supported by Octeon. */ | 53 | /** Endian-swap modes supported by Octeon. */ |
47 | enum octeon_pci_swap_mode { | 54 | enum octeon_pci_swap_mode { |
48 | OCTEON_PCI_PASSTHROUGH = 0, | 55 | OCTEON_PCI_PASSTHROUGH = 0, |
@@ -430,6 +437,8 @@ struct octeon_device { | |||
430 | 437 | ||
431 | u16 rev_id; | 438 | u16 rev_id; |
432 | 439 | ||
440 | u32 subsystem_id; | ||
441 | |||
433 | u16 pf_num; | 442 | u16 pf_num; |
434 | 443 | ||
435 | u16 vf_num; | 444 | u16 vf_num; |
@@ -584,6 +593,11 @@ struct octeon_device { | |||
584 | struct lio_vf_rep_list vf_rep_list; | 593 | struct lio_vf_rep_list vf_rep_list; |
585 | struct devlink *devlink; | 594 | struct devlink *devlink; |
586 | enum devlink_eswitch_mode eswitch_mode; | 595 | enum devlink_eswitch_mode eswitch_mode; |
596 | |||
597 | /* for 25G NIC speed change */ | ||
598 | u8 speed_boot; | ||
599 | u8 speed_setting; | ||
600 | u8 no_speed_setting; | ||
587 | }; | 601 | }; |
588 | 602 | ||
589 | #define OCT_DRV_ONLINE 1 | 603 | #define OCT_DRV_ONLINE 1 |
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_network.h b/drivers/net/ethernet/cavium/liquidio/octeon_network.h index 8571f11e3c8f..dd3177a526d2 100644 --- a/drivers/net/ethernet/cavium/liquidio/octeon_network.h +++ b/drivers/net/ethernet/cavium/liquidio/octeon_network.h | |||
@@ -81,6 +81,18 @@ struct oct_nic_stats_ctrl { | |||
81 | struct net_device *netdev; | 81 | struct net_device *netdev; |
82 | }; | 82 | }; |
83 | 83 | ||
84 | struct oct_nic_seapi_resp { | ||
85 | u64 rh; | ||
86 | u32 speed; | ||
87 | u64 status; | ||
88 | }; | ||
89 | |||
90 | struct liquidio_nic_seapi_ctl_context { | ||
91 | int octeon_id; | ||
92 | u32 status; | ||
93 | struct completion complete; | ||
94 | }; | ||
95 | |||
84 | /** LiquidIO per-interface network private data */ | 96 | /** LiquidIO per-interface network private data */ |
85 | struct lio { | 97 | struct lio { |
86 | /** State of the interface. Rx/Tx happens only in the RUNNING state. */ | 98 | /** State of the interface. Rx/Tx happens only in the RUNNING state. */ |
@@ -230,6 +242,9 @@ void lio_delete_glists(struct lio *lio); | |||
230 | 242 | ||
231 | int lio_setup_glists(struct octeon_device *oct, struct lio *lio, int num_qs); | 243 | int lio_setup_glists(struct octeon_device *oct, struct lio *lio, int num_qs); |
232 | 244 | ||
245 | int liquidio_get_speed(struct lio *lio); | ||
246 | int liquidio_set_speed(struct lio *lio, int speed); | ||
247 | |||
233 | /** | 248 | /** |
234 | * \brief Net device change_mtu | 249 | * \brief Net device change_mtu |
235 | * @param netdev network device | 250 | * @param netdev network device |