Backported fix suspend/resume issue in brcmsmac

Few days ago my Macbook just died therefore I was forced to buy a new laptop cialis overnight. After a quick overview on marked I’ve decided to buy an Toshiba Portege R700 with Intel i5 processor. Unfortunately it has an Broadcom 4727 Wi-Fi card with is only supported by staging brcm80211 module. Generally it works pretty well on 2.6.37 kernel, if you shutdown and power up laptop, but when  you use suspend like I do it doesn’t get up after resume. The module needs to be reloaded to work again.

Thanks to Arend van Spriel this issue were fixed but patch that was send on linux-wireless mailing list doesn’t apply on vanilla 2.6.37 sources.  To get this working I decided to back port this patch, and it appears to be was very simple task ;). So if you are have similar problems with BCM4727 on 2.6.37 like I had here is a patch that clearly apples on 2.6.37 and fix this issue.

diff -uNr drivers-orig/staging/brcm80211/sys/wl_mac80211.c drivers/staging/brcm80211/sys/wl_mac80211.c
--- drivers-orig/staging/brcm80211/sys/wl_mac80211.c   2011-01-05 01:50:19.000000000 +0100
+++ drivers/staging/brcm80211/sys/wl_mac80211.c    2011-01-13 17:28:50.000000000 +0100
@@ -299,7 +299,6 @@
    wl_info_t *wl = hw->priv;
    ASSERT(wl);
    WL_LOCK(wl);
-  wl_down(wl);
    ieee80211_stop_queues(hw);
    WL_UNLOCK(wl);
 
@@ -336,6 +335,14 @@
 static void
 wl_ops_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 {
+  struct wl_info *wl;
+
+  wl = HW_TO_WL(hw);
+
+  /* put driver in down state */
+  WL_LOCK(wl);
+  wl_down(wl);
+  WL_UNLOCK(wl);
    return;
 }
 
@@ -1356,7 +1363,6 @@
    return 0;
 }
 
-#ifdef LINUXSTA_PS
 static int wl_suspend(struct pci_dev *pdev, pm_message_t state)
 {
    wl_info_t *wl;
@@ -1371,11 +1377,12 @@
        return -ENODEV;
    }
 
+  /* only need to flag hw is down for proper resume */
    WL_LOCK(wl);
-  wl_down(wl);
    wl->pub->hw_up = false;
    WL_UNLOCK(wl);
-  pci_save_state(pdev, wl->pci_psstate);
+
+  pci_save_state(pdev);
    pci_disable_device(pdev);
    return pci_set_power_state(pdev, PCI_D3hot);
 }
@@ -1399,7 +1406,7 @@
    if (err)
        return err;
 
-  pci_restore_state(pdev, wl->pci_psstate);
+  pci_restore_state(pdev);
 
    err = pci_enable_device(pdev);
    if (err)
@@ -1411,13 +1418,12 @@
    if ((val & 0x0000ff00) != 0)
        pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
 
-  WL_LOCK(wl);
-  err = wl_up(wl);
-  WL_UNLOCK(wl);
-
+  /*
+   *  done. driver will be put in up state
+   *  in wl_ops_add_interface() call.
+   */
    return err;
 }
-#endif                /* LINUXSTA_PS */
 
 static void wl_remove(struct pci_dev *pdev)
 {
@@ -1452,10 +1458,8 @@
 static struct pci_driver wl_pci_driver = {
  .name  = "brcm80211",
  .probe = wl_pci_probe,
-#ifdef LINUXSTA_PS
  .suspend = wl_suspend,
  .resume  = wl_resume,
-#endif                /* LINUXSTA_PS */
  .remove   = __devexit_p(wl_remove),
  .id_table = wl_id_table,
 };
diff -uNr drivers-orig/staging/brcm80211/sys/wl_mac80211.h drivers/staging/brcm80211/sys/wl_mac80211.h
--- drivers-orig/staging/brcm80211/sys/wl_mac80211.h   2011-01-05 01:50:19.000000000 +0100
+++ drivers/staging/brcm80211/sys/wl_mac80211.h    2011-01-13 17:17:39.000000000 +0100
@@ -84,9 +84,7 @@
    unsigned long flags;        /* current irq flags */
 #endif             /* BCMSDIO */
    bool resched;       /* dpc needs to be and is rescheduled */
-#ifdef LINUXSTA_PS
-  u32 pci_psstate[16];   /* pci ps-state save/restore */
-#endif
+
    /* RPC, handle, lock, txq, workitem */
 #ifdef WLC_HIGH_ONLY
    rpc_info_t *rpc;    /* RPC handle */

BTW. This laptop works pretty good on linux. All parts seams to be working properly (I didn’t tested bluetooth, and finger print scaner because I don’t use it), there are only problems after resuming system from suspend like above described problem with BCM4727 (other problems are connected with back light changing and graphics performance).

UPDATE:

It seams that this patch is included in kernel 2.6.38-rc3