diff options
author | Ajit Khaparde <ajit.khaparde@emulex.com> | 2012-03-18 02:23:11 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-03-19 16:52:17 -0400 |
commit | 4762f6cec4455f3bbe4ca82c100fe5d85d3c02a2 (patch) | |
tree | 51cf21b4a949b8a3292019f81447d8a9a719d7e3 /drivers/net/ethernet/emulex | |
parent | 277074777cd9c004b1ac32689772370c38fd00e2 (diff) |
be2net: enable WOL by default if h/w supports it
Signed-off-by: Ajit Khaparde <ajit.khaparde@emulex.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/emulex')
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be.h | 26 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_cmds.c | 55 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_cmds.h | 28 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_ethtool.c | 27 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_main.c | 17 |
5 files changed, 136 insertions, 17 deletions
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index ab24e4600695..cabe1b892722 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h | |||
@@ -52,6 +52,10 @@ | |||
52 | #define OC_DEVICE_ID3 0xe220 /* Device id for Lancer cards */ | 52 | #define OC_DEVICE_ID3 0xe220 /* Device id for Lancer cards */ |
53 | #define OC_DEVICE_ID4 0xe228 /* Device id for VF in Lancer */ | 53 | #define OC_DEVICE_ID4 0xe228 /* Device id for VF in Lancer */ |
54 | #define OC_DEVICE_ID5 0x720 /* Device Id for Skyhawk cards */ | 54 | #define OC_DEVICE_ID5 0x720 /* Device Id for Skyhawk cards */ |
55 | #define OC_SUBSYS_DEVICE_ID1 0xE602 | ||
56 | #define OC_SUBSYS_DEVICE_ID2 0xE642 | ||
57 | #define OC_SUBSYS_DEVICE_ID3 0xE612 | ||
58 | #define OC_SUBSYS_DEVICE_ID4 0xE652 | ||
55 | 59 | ||
56 | static inline char *nic_name(struct pci_dev *pdev) | 60 | static inline char *nic_name(struct pci_dev *pdev) |
57 | { | 61 | { |
@@ -365,7 +369,6 @@ struct be_adapter { | |||
365 | bool fw_timeout; | 369 | bool fw_timeout; |
366 | u32 port_num; | 370 | u32 port_num; |
367 | bool promiscuous; | 371 | bool promiscuous; |
368 | bool wol; | ||
369 | u32 function_mode; | 372 | u32 function_mode; |
370 | u32 function_caps; | 373 | u32 function_caps; |
371 | u32 rx_fc; /* Rx flow control */ | 374 | u32 rx_fc; /* Rx flow control */ |
@@ -386,6 +389,8 @@ struct be_adapter { | |||
386 | u32 sli_family; | 389 | u32 sli_family; |
387 | u8 hba_port_num; | 390 | u8 hba_port_num; |
388 | u16 pvid; | 391 | u16 pvid; |
392 | u8 wol_cap; | ||
393 | bool wol; | ||
389 | }; | 394 | }; |
390 | 395 | ||
391 | #define be_physfn(adapter) (!adapter->is_virtfn) | 396 | #define be_physfn(adapter) (!adapter->is_virtfn) |
@@ -549,9 +554,28 @@ static inline bool be_error(struct be_adapter *adapter) | |||
549 | return adapter->eeh_err || adapter->ue_detected || adapter->fw_timeout; | 554 | return adapter->eeh_err || adapter->ue_detected || adapter->fw_timeout; |
550 | } | 555 | } |
551 | 556 | ||
557 | static inline bool be_is_wol_excluded(struct be_adapter *adapter) | ||
558 | { | ||
559 | struct pci_dev *pdev = adapter->pdev; | ||
560 | |||
561 | if (!be_physfn(adapter)) | ||
562 | return true; | ||
563 | |||
564 | switch (pdev->subsystem_device) { | ||
565 | case OC_SUBSYS_DEVICE_ID1: | ||
566 | case OC_SUBSYS_DEVICE_ID2: | ||
567 | case OC_SUBSYS_DEVICE_ID3: | ||
568 | case OC_SUBSYS_DEVICE_ID4: | ||
569 | return true; | ||
570 | default: | ||
571 | return false; | ||
572 | } | ||
573 | } | ||
574 | |||
552 | extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, | 575 | extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, |
553 | u16 num_popped); | 576 | u16 num_popped); |
554 | extern void be_link_status_update(struct be_adapter *adapter, u8 link_status); | 577 | extern void be_link_status_update(struct be_adapter *adapter, u8 link_status); |
555 | extern void be_parse_stats(struct be_adapter *adapter); | 578 | extern void be_parse_stats(struct be_adapter *adapter); |
556 | extern int be_load_fw(struct be_adapter *adapter, u8 *func); | 579 | extern int be_load_fw(struct be_adapter *adapter, u8 *func); |
580 | extern bool be_is_wol_supported(struct be_adapter *adapter); | ||
557 | #endif /* BE_H */ | 581 | #endif /* BE_H */ |
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index 398fb5ca0fe2..d72c2b46963c 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c | |||
@@ -2418,3 +2418,58 @@ err: | |||
2418 | spin_unlock_bh(&adapter->mcc_lock); | 2418 | spin_unlock_bh(&adapter->mcc_lock); |
2419 | return status; | 2419 | return status; |
2420 | } | 2420 | } |
2421 | |||
2422 | int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter) | ||
2423 | { | ||
2424 | struct be_mcc_wrb *wrb; | ||
2425 | struct be_cmd_req_acpi_wol_magic_config_v1 *req; | ||
2426 | int status; | ||
2427 | int payload_len = sizeof(*req); | ||
2428 | struct be_dma_mem cmd; | ||
2429 | |||
2430 | memset(&cmd, 0, sizeof(struct be_dma_mem)); | ||
2431 | cmd.size = sizeof(struct be_cmd_resp_acpi_wol_magic_config_v1); | ||
2432 | cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, | ||
2433 | &cmd.dma); | ||
2434 | if (!cmd.va) { | ||
2435 | dev_err(&adapter->pdev->dev, | ||
2436 | "Memory allocation failure\n"); | ||
2437 | return -ENOMEM; | ||
2438 | } | ||
2439 | |||
2440 | if (mutex_lock_interruptible(&adapter->mbox_lock)) | ||
2441 | return -1; | ||
2442 | |||
2443 | wrb = wrb_from_mbox(adapter); | ||
2444 | if (!wrb) { | ||
2445 | status = -EBUSY; | ||
2446 | goto err; | ||
2447 | } | ||
2448 | |||
2449 | req = cmd.va; | ||
2450 | |||
2451 | be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, | ||
2452 | OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG, | ||
2453 | payload_len, wrb, &cmd); | ||
2454 | |||
2455 | req->hdr.version = 1; | ||
2456 | req->query_options = BE_GET_WOL_CAP; | ||
2457 | |||
2458 | status = be_mbox_notify_wait(adapter); | ||
2459 | if (!status) { | ||
2460 | struct be_cmd_resp_acpi_wol_magic_config_v1 *resp; | ||
2461 | resp = (struct be_cmd_resp_acpi_wol_magic_config_v1 *) cmd.va; | ||
2462 | |||
2463 | /* the command could succeed misleadingly on old f/w | ||
2464 | * which is not aware of the V1 version. fake an error. */ | ||
2465 | if (resp->hdr.response_length < payload_len) { | ||
2466 | status = -1; | ||
2467 | goto err; | ||
2468 | } | ||
2469 | adapter->wol_cap = resp->wol_settings; | ||
2470 | } | ||
2471 | err: | ||
2472 | mutex_unlock(&adapter->mbox_lock); | ||
2473 | pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma); | ||
2474 | return status; | ||
2475 | } | ||
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h index 687c42071411..345d49eeadc8 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.h +++ b/drivers/net/ethernet/emulex/benet/be_cmds.h | |||
@@ -1206,6 +1206,33 @@ struct be_cmd_req_acpi_wol_magic_config{ | |||
1206 | u8 rsvd2[2]; | 1206 | u8 rsvd2[2]; |
1207 | } __packed; | 1207 | } __packed; |
1208 | 1208 | ||
1209 | struct be_cmd_req_acpi_wol_magic_config_v1 { | ||
1210 | struct be_cmd_req_hdr hdr; | ||
1211 | u8 rsvd0[2]; | ||
1212 | u8 query_options; | ||
1213 | u8 rsvd1[5]; | ||
1214 | u32 rsvd2[288]; | ||
1215 | u8 magic_mac[6]; | ||
1216 | u8 rsvd3[22]; | ||
1217 | } __packed; | ||
1218 | |||
1219 | struct be_cmd_resp_acpi_wol_magic_config_v1 { | ||
1220 | struct be_cmd_resp_hdr hdr; | ||
1221 | u8 rsvd0[2]; | ||
1222 | u8 wol_settings; | ||
1223 | u8 rsvd1[5]; | ||
1224 | u32 rsvd2[295]; | ||
1225 | } __packed; | ||
1226 | |||
1227 | #define BE_GET_WOL_CAP 2 | ||
1228 | |||
1229 | #define BE_WOL_CAP 0x1 | ||
1230 | #define BE_PME_D0_CAP 0x8 | ||
1231 | #define BE_PME_D1_CAP 0x10 | ||
1232 | #define BE_PME_D2_CAP 0x20 | ||
1233 | #define BE_PME_D3HOT_CAP 0x40 | ||
1234 | #define BE_PME_D3COLD_CAP 0x80 | ||
1235 | |||
1209 | /********************** LoopBack test *********************/ | 1236 | /********************** LoopBack test *********************/ |
1210 | struct be_cmd_req_loopback_test { | 1237 | struct be_cmd_req_loopback_test { |
1211 | struct be_cmd_req_hdr hdr; | 1238 | struct be_cmd_req_hdr hdr; |
@@ -1590,4 +1617,5 @@ extern int be_cmd_get_mac_from_list(struct be_adapter *adapter, u32 domain, | |||
1590 | bool *pmac_id_active, u32 *pmac_id, u8 *mac); | 1617 | bool *pmac_id_active, u32 *pmac_id, u8 *mac); |
1591 | extern int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array, | 1618 | extern int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array, |
1592 | u8 mac_count, u32 domain); | 1619 | u8 mac_count, u32 domain); |
1620 | extern int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter); | ||
1593 | 1621 | ||
diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c index 30ce17806916..c1ff73cb0e62 100644 --- a/drivers/net/ethernet/emulex/benet/be_ethtool.c +++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c | |||
@@ -600,26 +600,16 @@ be_set_phys_id(struct net_device *netdev, | |||
600 | return 0; | 600 | return 0; |
601 | } | 601 | } |
602 | 602 | ||
603 | static bool | ||
604 | be_is_wol_supported(struct be_adapter *adapter) | ||
605 | { | ||
606 | if (!be_physfn(adapter)) | ||
607 | return false; | ||
608 | else | ||
609 | return true; | ||
610 | } | ||
611 | 603 | ||
612 | static void | 604 | static void |
613 | be_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) | 605 | be_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) |
614 | { | 606 | { |
615 | struct be_adapter *adapter = netdev_priv(netdev); | 607 | struct be_adapter *adapter = netdev_priv(netdev); |
616 | 608 | ||
617 | if (be_is_wol_supported(adapter)) | 609 | if (be_is_wol_supported(adapter)) { |
618 | wol->supported = WAKE_MAGIC; | 610 | wol->supported |= WAKE_MAGIC; |
619 | 611 | wol->wolopts |= WAKE_MAGIC; | |
620 | if (adapter->wol) | 612 | } else |
621 | wol->wolopts = WAKE_MAGIC; | ||
622 | else | ||
623 | wol->wolopts = 0; | 613 | wol->wolopts = 0; |
624 | memset(&wol->sopass, 0, sizeof(wol->sopass)); | 614 | memset(&wol->sopass, 0, sizeof(wol->sopass)); |
625 | } | 615 | } |
@@ -630,9 +620,14 @@ be_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) | |||
630 | struct be_adapter *adapter = netdev_priv(netdev); | 620 | struct be_adapter *adapter = netdev_priv(netdev); |
631 | 621 | ||
632 | if (wol->wolopts & ~WAKE_MAGIC) | 622 | if (wol->wolopts & ~WAKE_MAGIC) |
633 | return -EINVAL; | 623 | return -EOPNOTSUPP; |
624 | |||
625 | if (!be_is_wol_supported(adapter)) { | ||
626 | dev_warn(&adapter->pdev->dev, "WOL not supported\n"); | ||
627 | return -EOPNOTSUPP; | ||
628 | } | ||
634 | 629 | ||
635 | if ((wol->wolopts & WAKE_MAGIC) && be_is_wol_supported(adapter)) | 630 | if (wol->wolopts & WAKE_MAGIC) |
636 | adapter->wol = true; | 631 | adapter->wol = true; |
637 | else | 632 | else |
638 | adapter->wol = false; | 633 | adapter->wol = false; |
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index e3822788f532..050e3ebd4fb3 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c | |||
@@ -3244,6 +3244,12 @@ static void __devexit be_remove(struct pci_dev *pdev) | |||
3244 | free_netdev(adapter->netdev); | 3244 | free_netdev(adapter->netdev); |
3245 | } | 3245 | } |
3246 | 3246 | ||
3247 | bool be_is_wol_supported(struct be_adapter *adapter) | ||
3248 | { | ||
3249 | return ((adapter->wol_cap & BE_WOL_CAP) && | ||
3250 | !be_is_wol_excluded(adapter)) ? true : false; | ||
3251 | } | ||
3252 | |||
3247 | static int be_get_config(struct be_adapter *adapter) | 3253 | static int be_get_config(struct be_adapter *adapter) |
3248 | { | 3254 | { |
3249 | int status; | 3255 | int status; |
@@ -3262,6 +3268,17 @@ static int be_get_config(struct be_adapter *adapter) | |||
3262 | if (status) | 3268 | if (status) |
3263 | return status; | 3269 | return status; |
3264 | 3270 | ||
3271 | status = be_cmd_get_acpi_wol_cap(adapter); | ||
3272 | if (status) { | ||
3273 | /* in case of a failure to get wol capabillities | ||
3274 | * check the exclusion list to determine WOL capability */ | ||
3275 | if (!be_is_wol_excluded(adapter)) | ||
3276 | adapter->wol_cap |= BE_WOL_CAP; | ||
3277 | } | ||
3278 | |||
3279 | if (be_is_wol_supported(adapter)) | ||
3280 | adapter->wol = true; | ||
3281 | |||
3265 | return 0; | 3282 | return 0; |
3266 | } | 3283 | } |
3267 | 3284 | ||