Certain firmware versions, particularly the 8388 found on the XO-1,
do not support the EHS_REMOVE_WAKEUP command that is used to disable
WOL. Sending this command to the card will return a failure that
would get propagated up the stack and cause suspend to fail.
Instead, fall back to an all-zero wakeup mask.
This fixes http://dev.laptop.org/ticket/9967
Signed-off-by: Deepak Saxena <dsaxena@laptop.org>
Signed-off-by: Daniel Drake <dsd@laptop.org>
[includes fixups by Paul Fox]
Signed-off-by: John W. Linville <linville@tuxdriver.com>
        struct cmd_ds_host_sleep cmd_config;
        int ret;
 
+       /*
+        * Certain firmware versions do not support EHS_REMOVE_WAKEUP command
+        * and the card will return a failure.  Since we need to be
+        * able to reset the mask, in those cases we set a 0 mask instead.
+        */
+       if (criteria == EHS_REMOVE_WAKEUP && !priv->ehs_remove_supported)
+               criteria = 0;
+
        cmd_config.hdr.size = cpu_to_le16(sizeof(cmd_config));
        cmd_config.criteria = cpu_to_le32(criteria);
        cmd_config.gpio = priv->wol_gpio;
 
        uint32_t wol_criteria;
        uint8_t wol_gpio;
        uint8_t wol_gap;
+       bool ehs_remove_supported;
 
        /* Transmitting */
        int tx_pending_len;             /* -1 while building packet */
 
        if (device_create_file(&priv->dev->dev, &dev_attr_lbs_flash_boot2))
                lbs_pr_err("cannot register lbs_flash_boot2 attribute\n");
 
+       /*
+        * EHS_REMOVE_WAKEUP is not supported on all versions of the firmware.
+        */
+       priv->wol_criteria = EHS_REMOVE_WAKEUP;
+       if (lbs_host_sleep_cfg(priv, priv->wol_criteria, NULL))
+               priv->ehs_remove_supported = false;
+
        return 0;
 
 err_start_card:
 
        priv->work_thread = create_singlethread_workqueue("lbs_worker");
        INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker);
 
-       priv->wol_criteria = 0xffffffff;
+       priv->wol_criteria = EHS_REMOVE_WAKEUP;
        priv->wol_gpio = 0xff;
        priv->wol_gap = 20;
+       priv->ehs_remove_supported = true;
 
        goto done;