aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorRon Mercer <ron.mercer@qlogic.com>2009-10-21 07:07:40 -0400
committerDavid S. Miller <davem@davemloft.net>2009-10-22 00:45:40 -0400
commitbc083ce98eeb42205e99495481c8616d30916f6e (patch)
treeb6111dd22d2d3a9102362b2e2a6b75e8aa928b74 /drivers
parentd8eb59dc8b9e77bb4fa5420ff80142759ad5cd7b (diff)
qlge: Add ethtool wake on LAN function.
Signed-off-by: Ron Mercer <ron.mercer@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/qlge/qlge.h4
-rw-r--r--drivers/net/qlge/qlge_ethtool.c32
-rw-r--r--drivers/net/qlge/qlge_main.c66
-rw-r--r--drivers/net/qlge/qlge_mpi.c70
4 files changed, 172 insertions, 0 deletions
diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h
index a5bb3a536538..ba2977699204 100644
--- a/drivers/net/qlge/qlge.h
+++ b/drivers/net/qlge/qlge.h
@@ -796,6 +796,7 @@ enum {
796 MB_WOL_BCAST = (1 << 5), 796 MB_WOL_BCAST = (1 << 5),
797 MB_WOL_LINK_UP = (1 << 6), 797 MB_WOL_LINK_UP = (1 << 6),
798 MB_WOL_LINK_DOWN = (1 << 7), 798 MB_WOL_LINK_DOWN = (1 << 7),
799 MB_WOL_MODE_ON = (1 << 16), /* Wake on Lan Mode on */
799 MB_CMD_SET_WOL_FLTR = 0x00000111, /* Wake On Lan Filter */ 800 MB_CMD_SET_WOL_FLTR = 0x00000111, /* Wake On Lan Filter */
800 MB_CMD_CLEAR_WOL_FLTR = 0x00000112, /* Wake On Lan Filter */ 801 MB_CMD_CLEAR_WOL_FLTR = 0x00000112, /* Wake On Lan Filter */
801 MB_CMD_SET_WOL_MAGIC = 0x00000113, /* Wake On Lan Magic Packet */ 802 MB_CMD_SET_WOL_MAGIC = 0x00000113, /* Wake On Lan Magic Packet */
@@ -1646,6 +1647,9 @@ int ql_mb_get_fw_state(struct ql_adapter *qdev);
1646int ql_cam_route_initialize(struct ql_adapter *qdev); 1647int ql_cam_route_initialize(struct ql_adapter *qdev);
1647int ql_read_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 *data); 1648int ql_read_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 *data);
1648int ql_mb_about_fw(struct ql_adapter *qdev); 1649int ql_mb_about_fw(struct ql_adapter *qdev);
1650int ql_wol(struct ql_adapter *qdev);
1651int ql_mb_wol_set_magic(struct ql_adapter *qdev, u32 enable_wol);
1652int ql_mb_wol_mode(struct ql_adapter *qdev, u32 wol);
1649int ql_mb_set_led_cfg(struct ql_adapter *qdev, u32 led_config); 1653int ql_mb_set_led_cfg(struct ql_adapter *qdev, u32 led_config);
1650int ql_mb_get_led_cfg(struct ql_adapter *qdev); 1654int ql_mb_get_led_cfg(struct ql_adapter *qdev);
1651void ql_link_on(struct ql_adapter *qdev); 1655void ql_link_on(struct ql_adapter *qdev);
diff --git a/drivers/net/qlge/qlge_ethtool.c b/drivers/net/qlge/qlge_ethtool.c
index 0c0549bc7bde..019f35fb10c1 100644
--- a/drivers/net/qlge/qlge_ethtool.c
+++ b/drivers/net/qlge/qlge_ethtool.c
@@ -371,6 +371,36 @@ static void ql_get_drvinfo(struct net_device *ndev,
371 drvinfo->eedump_len = 0; 371 drvinfo->eedump_len = 0;
372} 372}
373 373
374static void ql_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
375{
376 struct ql_adapter *qdev = netdev_priv(ndev);
377 /* What we support. */
378 wol->supported = WAKE_MAGIC;
379 /* What we've currently got set. */
380 wol->wolopts = qdev->wol;
381}
382
383static int ql_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
384{
385 struct ql_adapter *qdev = netdev_priv(ndev);
386 int status;
387
388 if (wol->wolopts & ~WAKE_MAGIC)
389 return -EINVAL;
390 qdev->wol = wol->wolopts;
391
392 QPRINTK(qdev, DRV, INFO, "Set wol option 0x%x on %s\n",
393 qdev->wol, ndev->name);
394 if (!qdev->wol) {
395 u32 wol = 0;
396 status = ql_mb_wol_mode(qdev, wol);
397 QPRINTK(qdev, DRV, ERR, "WOL %s (wol code 0x%x) on %s\n",
398 (status == 0) ? "cleared sucessfully" : "clear failed",
399 wol, qdev->ndev->name);
400 }
401
402 return 0;
403}
374 404
375static int ql_phys_id(struct net_device *ndev, u32 data) 405static int ql_phys_id(struct net_device *ndev, u32 data)
376{ 406{
@@ -523,6 +553,8 @@ static void ql_set_msglevel(struct net_device *ndev, u32 value)
523const struct ethtool_ops qlge_ethtool_ops = { 553const struct ethtool_ops qlge_ethtool_ops = {
524 .get_settings = ql_get_settings, 554 .get_settings = ql_get_settings,
525 .get_drvinfo = ql_get_drvinfo, 555 .get_drvinfo = ql_get_drvinfo,
556 .get_wol = ql_get_wol,
557 .set_wol = ql_set_wol,
526 .get_msglevel = ql_get_msglevel, 558 .get_msglevel = ql_get_msglevel,
527 .set_msglevel = ql_set_msglevel, 559 .set_msglevel = ql_set_msglevel,
528 .get_link = ethtool_op_get_link, 560 .get_link = ethtool_op_get_link,
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c
index 34242fbcadff..dd0ea0277550 100644
--- a/drivers/net/qlge/qlge_main.c
+++ b/drivers/net/qlge/qlge_main.c
@@ -3335,6 +3335,22 @@ static int ql_adapter_initialize(struct ql_adapter *qdev)
3335 * the same MAC address. 3335 * the same MAC address.
3336 */ 3336 */
3337 ql_write32(qdev, RST_FO, RST_FO_RR_MASK | RST_FO_RR_RCV_FUNC_CQ); 3337 ql_write32(qdev, RST_FO, RST_FO_RR_MASK | RST_FO_RR_RCV_FUNC_CQ);
3338 /* Reroute all packets to our Interface.
3339 * They may have been routed to MPI firmware
3340 * due to WOL.
3341 */
3342 value = ql_read32(qdev, MGMT_RCV_CFG);
3343 value &= ~MGMT_RCV_CFG_RM;
3344 mask = 0xffff0000;
3345
3346 /* Sticky reg needs clearing due to WOL. */
3347 ql_write32(qdev, MGMT_RCV_CFG, mask);
3348 ql_write32(qdev, MGMT_RCV_CFG, mask | value);
3349
3350 /* Default WOL is enable on Mezz cards */
3351 if (qdev->pdev->subsystem_device == 0x0068 ||
3352 qdev->pdev->subsystem_device == 0x0180)
3353 qdev->wol = WAKE_MAGIC;
3338 3354
3339 /* Start up the rx queues. */ 3355 /* Start up the rx queues. */
3340 for (i = 0; i < qdev->rx_ring_count; i++) { 3356 for (i = 0; i < qdev->rx_ring_count; i++) {
@@ -3449,6 +3465,55 @@ static void ql_display_dev_info(struct net_device *ndev)
3449 QPRINTK(qdev, PROBE, INFO, "MAC address %pM\n", ndev->dev_addr); 3465 QPRINTK(qdev, PROBE, INFO, "MAC address %pM\n", ndev->dev_addr);
3450} 3466}
3451 3467
3468int ql_wol(struct ql_adapter *qdev)
3469{
3470 int status = 0;
3471 u32 wol = MB_WOL_DISABLE;
3472
3473 /* The CAM is still intact after a reset, but if we
3474 * are doing WOL, then we may need to program the
3475 * routing regs. We would also need to issue the mailbox
3476 * commands to instruct the MPI what to do per the ethtool
3477 * settings.
3478 */
3479
3480 if (qdev->wol & (WAKE_ARP | WAKE_MAGICSECURE | WAKE_PHY | WAKE_UCAST |
3481 WAKE_MCAST | WAKE_BCAST)) {
3482 QPRINTK(qdev, IFDOWN, ERR,
3483 "Unsupported WOL paramter. qdev->wol = 0x%x.\n",
3484 qdev->wol);
3485 return -EINVAL;
3486 }
3487
3488 if (qdev->wol & WAKE_MAGIC) {
3489 status = ql_mb_wol_set_magic(qdev, 1);
3490 if (status) {
3491 QPRINTK(qdev, IFDOWN, ERR,
3492 "Failed to set magic packet on %s.\n",
3493 qdev->ndev->name);
3494 return status;
3495 } else
3496 QPRINTK(qdev, DRV, INFO,
3497 "Enabled magic packet successfully on %s.\n",
3498 qdev->ndev->name);
3499
3500 wol |= MB_WOL_MAGIC_PKT;
3501 }
3502
3503 if (qdev->wol) {
3504 /* Reroute all packets to Management Interface */
3505 ql_write32(qdev, MGMT_RCV_CFG, (MGMT_RCV_CFG_RM |
3506 (MGMT_RCV_CFG_RM << 16)));
3507 wol |= MB_WOL_MODE_ON;
3508 status = ql_mb_wol_mode(qdev, wol);
3509 QPRINTK(qdev, DRV, ERR, "WOL %s (wol code 0x%x) on %s\n",
3510 (status == 0) ? "Sucessfully set" : "Failed", wol,
3511 qdev->ndev->name);
3512 }
3513
3514 return status;
3515}
3516
3452static int ql_adapter_down(struct ql_adapter *qdev) 3517static int ql_adapter_down(struct ql_adapter *qdev)
3453{ 3518{
3454 int i, status = 0; 3519 int i, status = 0;
@@ -4285,6 +4350,7 @@ static int qlge_suspend(struct pci_dev *pdev, pm_message_t state)
4285 return err; 4350 return err;
4286 } 4351 }
4287 4352
4353 ql_wol(qdev);
4288 err = pci_save_state(pdev); 4354 err = pci_save_state(pdev);
4289 if (err) 4355 if (err)
4290 return err; 4356 return err;
diff --git a/drivers/net/qlge/qlge_mpi.c b/drivers/net/qlge/qlge_mpi.c
index 14d76f13d1db..80b68539c5aa 100644
--- a/drivers/net/qlge/qlge_mpi.c
+++ b/drivers/net/qlge/qlge_mpi.c
@@ -702,6 +702,76 @@ int ql_mb_get_port_cfg(struct ql_adapter *qdev)
702 return status; 702 return status;
703} 703}
704 704
705int ql_mb_wol_mode(struct ql_adapter *qdev, u32 wol)
706{
707 struct mbox_params mbc;
708 struct mbox_params *mbcp = &mbc;
709 int status;
710
711 memset(mbcp, 0, sizeof(struct mbox_params));
712
713 mbcp->in_count = 2;
714 mbcp->out_count = 1;
715
716 mbcp->mbox_in[0] = MB_CMD_SET_WOL_MODE;
717 mbcp->mbox_in[1] = wol;
718
719
720 status = ql_mailbox_command(qdev, mbcp);
721 if (status)
722 return status;
723
724 if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) {
725 QPRINTK(qdev, DRV, ERR,
726 "Failed to set WOL mode.\n");
727 status = -EIO;
728 }
729 return status;
730}
731
732int ql_mb_wol_set_magic(struct ql_adapter *qdev, u32 enable_wol)
733{
734 struct mbox_params mbc;
735 struct mbox_params *mbcp = &mbc;
736 int status;
737 u8 *addr = qdev->ndev->dev_addr;
738
739 memset(mbcp, 0, sizeof(struct mbox_params));
740
741 mbcp->in_count = 8;
742 mbcp->out_count = 1;
743
744 mbcp->mbox_in[0] = MB_CMD_SET_WOL_MAGIC;
745 if (enable_wol) {
746 mbcp->mbox_in[1] = (u32)addr[0];
747 mbcp->mbox_in[2] = (u32)addr[1];
748 mbcp->mbox_in[3] = (u32)addr[2];
749 mbcp->mbox_in[4] = (u32)addr[3];
750 mbcp->mbox_in[5] = (u32)addr[4];
751 mbcp->mbox_in[6] = (u32)addr[5];
752 mbcp->mbox_in[7] = 0;
753 } else {
754 mbcp->mbox_in[1] = 0;
755 mbcp->mbox_in[2] = 1;
756 mbcp->mbox_in[3] = 1;
757 mbcp->mbox_in[4] = 1;
758 mbcp->mbox_in[5] = 1;
759 mbcp->mbox_in[6] = 1;
760 mbcp->mbox_in[7] = 0;
761 }
762
763 status = ql_mailbox_command(qdev, mbcp);
764 if (status)
765 return status;
766
767 if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) {
768 QPRINTK(qdev, DRV, ERR,
769 "Failed to set WOL mode.\n");
770 status = -EIO;
771 }
772 return status;
773}
774
705/* IDC - Inter Device Communication... 775/* IDC - Inter Device Communication...
706 * Some firmware commands require consent of adjacent FCOE 776 * Some firmware commands require consent of adjacent FCOE
707 * function. This function waits for the OK, or a 777 * function. This function waits for the OK, or a