From mboxrd@z Thu Jan 1 00:00:00 1970 Return-path: Received: from mail-ww0-f44.google.com ([74.125.82.44]:46273 "EHLO mail-ww0-f44.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756729Ab0KMB0T convert rfc822-to-8bit (ORCPT ); Fri, 12 Nov 2010 20:26:19 -0500 Received: by mail-ww0-f44.google.com with SMTP id 22so492216wwb.1 for ; Fri, 12 Nov 2010 17:26:18 -0800 (PST) MIME-Version: 1.0 In-Reply-To: <1289611433-5119-4-git-send-email-brian@cozybit.com> References: <1288659351-22313-1-git-send-email-brian@cozybit.com> <1289611433-5119-4-git-send-email-brian@cozybit.com> From: Brian Cavagnolo Date: Fri, 12 Nov 2010 17:25:58 -0800 Message-ID: Subject: Re: [PATCH V2 3/7] mwl8k: factor out firmware loading and hw init code To: linux-wireless@vger.kernel.org Cc: buytenh@wantstofly.org, Brian Cavagnolo Content-Type: text/plain; charset=ISO-8859-1 Sender: linux-wireless-owner@vger.kernel.org List-ID: My apologies. This is also a V2 patch despite the subject. On Fri, Nov 12, 2010 at 5:23 PM, Brian Cavagnolo wrote: > This is in preparation for supporting different fw images for > different interface types, and for supporting asynchronous > firmware loading. > > Based on a patch from Pradeep Nemavat > and Yogesh Powar > > Signed-off-by: Brian Cavagnolo > --- >  drivers/net/wireless/mwl8k.c |  345 ++++++++++++++++++++++++++---------------- >  1 files changed, 214 insertions(+), 131 deletions(-) > > diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c > index cfda87a..7bd8615 100644 > --- a/drivers/net/wireless/mwl8k.c > +++ b/drivers/net/wireless/mwl8k.c > @@ -3942,73 +3942,10 @@ static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = { >  }; >  MODULE_DEVICE_TABLE(pci, mwl8k_pci_id_table); > > -static int __devinit mwl8k_probe(struct pci_dev *pdev, > -                                const struct pci_device_id *id) > +static int mwl8k_init_firmware(struct ieee80211_hw *hw) >  { > -       static int printed_version = 0; > -       struct ieee80211_hw *hw; > -       struct mwl8k_priv *priv; > +       struct mwl8k_priv *priv = hw->priv; >        int rc; > -       int i; > - > -       if (!printed_version) { > -               printk(KERN_INFO "%s version %s\n", MWL8K_DESC, MWL8K_VERSION); > -               printed_version = 1; > -       } > - > - > -       rc = pci_enable_device(pdev); > -       if (rc) { > -               printk(KERN_ERR "%s: Cannot enable new PCI device\n", > -                      MWL8K_NAME); > -               return rc; > -       } > - > -       rc = pci_request_regions(pdev, MWL8K_NAME); > -       if (rc) { > -               printk(KERN_ERR "%s: Cannot obtain PCI resources\n", > -                      MWL8K_NAME); > -               goto err_disable_device; > -       } > - > -       pci_set_master(pdev); > - > - > -       hw = ieee80211_alloc_hw(sizeof(*priv), &mwl8k_ops); > -       if (hw == NULL) { > -               printk(KERN_ERR "%s: ieee80211 alloc failed\n", MWL8K_NAME); > -               rc = -ENOMEM; > -               goto err_free_reg; > -       } > - > -       SET_IEEE80211_DEV(hw, &pdev->dev); > -       pci_set_drvdata(pdev, hw); > - > -       priv = hw->priv; > -       priv->hw = hw; > -       priv->pdev = pdev; > -       priv->device_info = &mwl8k_info_tbl[id->driver_data]; > - > - > -       priv->sram = pci_iomap(pdev, 0, 0x10000); > -       if (priv->sram == NULL) { > -               wiphy_err(hw->wiphy, "Cannot map device SRAM\n"); > -               goto err_iounmap; > -       } > - > -       /* > -        * If BAR0 is a 32 bit BAR, the register BAR will be BAR1. > -        * If BAR0 is a 64 bit BAR, the register BAR will be BAR2. > -        */ > -       priv->regs = pci_iomap(pdev, 1, 0x10000); > -       if (priv->regs == NULL) { > -               priv->regs = pci_iomap(pdev, 2, 0x10000); > -               if (priv->regs == NULL) { > -                       wiphy_err(hw->wiphy, "Cannot map device registers\n"); > -                       goto err_iounmap; > -               } > -       } > - > >        /* Reset firmware and hardware */ >        mwl8k_hw_reset(priv); > @@ -4017,19 +3954,26 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, >        rc = mwl8k_request_firmware(priv); >        if (rc) { >                wiphy_err(hw->wiphy, "Firmware files not found\n"); > -               goto err_stop_firmware; > +               return rc; >        } > >        /* Load firmware into hardware */ >        rc = mwl8k_load_firmware(hw); > -       if (rc) { > +       if (rc) >                wiphy_err(hw->wiphy, "Cannot start firmware\n"); > -               goto err_stop_firmware; > -       } > >        /* Reclaim memory once firmware is successfully loaded */ >        mwl8k_release_firmware(priv); > > +       return rc; > +} > + > +/* initialize hw after successfully loading a firmware image */ > +static int mwl8k_probe_hw(struct ieee80211_hw *hw) > +{ > +       struct mwl8k_priv *priv = hw->priv; > +       int rc = 0; > +       int i; > >        if (priv->ap_fw) { >                priv->rxd_ops = priv->device_info->ap_rxd_ops; > @@ -4046,58 +3990,11 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, >        priv->wmm_enabled = false; >        priv->pending_tx_pkts = 0; > > - > -       /* > -        * Extra headroom is the size of the required DMA header > -        * minus the size of the smallest 802.11 frame (CTS frame). > -        */ > -       hw->extra_tx_headroom = > -               sizeof(struct mwl8k_dma_data) - sizeof(struct ieee80211_cts); > - > -       hw->channel_change_time = 10; > - > -       hw->queues = MWL8K_TX_QUEUES; > - > -       /* Set rssi values to dBm */ > -       hw->flags |= IEEE80211_HW_SIGNAL_DBM; > -       hw->vif_data_size = sizeof(struct mwl8k_vif); > -       hw->sta_data_size = sizeof(struct mwl8k_sta); > - > -       priv->macids_used = 0; > -       INIT_LIST_HEAD(&priv->vif_list); > - > -       /* Set default radio state and preamble */ > -       priv->radio_on = 0; > -       priv->radio_short_preamble = 0; > - > -       /* Finalize join worker */ > -       INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker); > - > -       /* TX reclaim and RX tasklets.  */ > -       tasklet_init(&priv->poll_tx_task, mwl8k_tx_poll, (unsigned long)hw); > -       tasklet_disable(&priv->poll_tx_task); > -       tasklet_init(&priv->poll_rx_task, mwl8k_rx_poll, (unsigned long)hw); > -       tasklet_disable(&priv->poll_rx_task); > - > -       /* Power management cookie */ > -       priv->cookie = pci_alloc_consistent(priv->pdev, 4, &priv->cookie_dma); > -       if (priv->cookie == NULL) > -               goto err_stop_firmware; > - >        rc = mwl8k_rxq_init(hw, 0); >        if (rc) > -               goto err_free_cookie; > +               goto err_stop_firmware; >        rxq_refill(hw, 0, INT_MAX); > > -       mutex_init(&priv->fw_mutex); > -       priv->fw_mutex_owner = NULL; > -       priv->fw_mutex_depth = 0; > -       priv->hostcmd_wait = NULL; > - > -       spin_lock_init(&priv->tx_lock); > - > -       priv->tx_wait = NULL; > - >        for (i = 0; i < MWL8K_TX_QUEUES; i++) { >                rc = mwl8k_txq_init(hw, i); >                if (rc) > @@ -4137,13 +4034,6 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, >                goto err_free_irq; >        } > > -       hw->wiphy->interface_modes = 0; > -       if (priv->ap_macids_supported) > -               hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP); > -       if (priv->sta_macids_supported) > -               hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_STATION); > - > - >        /* Turn radio off */ >        rc = mwl8k_cmd_radio_disable(hw); >        if (rc) { > @@ -4162,12 +4052,6 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, >        iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); >        free_irq(priv->pdev->irq, hw); > > -       rc = ieee80211_register_hw(hw); > -       if (rc) { > -               wiphy_err(hw->wiphy, "Cannot register device\n"); > -               goto err_free_queues; > -       } > - >        wiphy_info(hw->wiphy, "%s v%d, %pm, %s firmware %u.%u.%u.%u\n", >                   priv->device_info->part_name, >                   priv->hw_rev, hw->wiphy->perm_addr, > @@ -4186,14 +4070,213 @@ err_free_queues: >                mwl8k_txq_deinit(hw, i); >        mwl8k_rxq_deinit(hw, 0); > > +err_stop_firmware: > +       mwl8k_hw_reset(priv); > + > +       return rc; > +} > + > +/* > + * invoke mwl8k_reload_firmware to change the firmware image after the device > + * has already been registered > + */ > +static int mwl8k_reload_firmware(struct ieee80211_hw *hw, char *fw_image) > +{ > +       int i, rc = 0; > +       struct mwl8k_priv *priv = hw->priv; > + > +       mwl8k_stop(hw); > +       mwl8k_rxq_deinit(hw, 0); > + > +       for (i = 0; i < MWL8K_TX_QUEUES; i++) > +               mwl8k_txq_deinit(hw, i); > + > +       rc = mwl8k_init_firmware(hw, fw_image); > +       if (rc) > +               goto fail; > + > +       rc = mwl8k_probe_hw(hw); > +       if (rc) > +               goto fail; > + > +       rc = mwl8k_start(hw); > +       if (rc) > +               goto fail; > + > +       rc = mwl8k_config(hw, ~0); > +       if (rc) > +               goto fail; > + > +       for (i = 0; i < MWL8K_TX_QUEUES; i++) { > +               rc = mwl8k_conf_tx(hw, i, &priv->wmm_params[i]); > +               if (rc) > +                       goto fail; > +       } > + > +       return rc; > + > +fail: > +       printk(KERN_WARNING "mwl8k: Failed to reload firmware image.\n"); > +       return rc; > +} > + > +static int mwl8k_firmware_load_success(struct mwl8k_priv *priv) > +{ > +       struct ieee80211_hw *hw = priv->hw; > +       int i, rc; > + > +       /* > +        * Extra headroom is the size of the required DMA header > +        * minus the size of the smallest 802.11 frame (CTS frame). > +        */ > +       hw->extra_tx_headroom = > +               sizeof(struct mwl8k_dma_data) - sizeof(struct ieee80211_cts); > + > +       hw->channel_change_time = 10; > + > +       hw->queues = MWL8K_TX_QUEUES; > + > +       /* Set rssi values to dBm */ > +       hw->flags |= IEEE80211_HW_SIGNAL_DBM; > +       hw->vif_data_size = sizeof(struct mwl8k_vif); > +       hw->sta_data_size = sizeof(struct mwl8k_sta); > + > +       priv->macids_used = 0; > +       INIT_LIST_HEAD(&priv->vif_list); > + > +       /* Set default radio state and preamble */ > +       priv->radio_on = 0; > +       priv->radio_short_preamble = 0; > + > +       /* Finalize join worker */ > +       INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker); > + > +       /* TX reclaim and RX tasklets.  */ > +       tasklet_init(&priv->poll_tx_task, mwl8k_tx_poll, (unsigned long)hw); > +       tasklet_disable(&priv->poll_tx_task); > +       tasklet_init(&priv->poll_rx_task, mwl8k_rx_poll, (unsigned long)hw); > +       tasklet_disable(&priv->poll_rx_task); > + > +       /* Power management cookie */ > +       priv->cookie = pci_alloc_consistent(priv->pdev, 4, &priv->cookie_dma); > +       if (priv->cookie == NULL) > +               return -ENOMEM; > + > +       mutex_init(&priv->fw_mutex); > +       priv->fw_mutex_owner = NULL; > +       priv->fw_mutex_depth = 0; > +       priv->hostcmd_wait = NULL; > + > +       spin_lock_init(&priv->tx_lock); > + > +       priv->tx_wait = NULL; > + > +       rc = mwl8k_probe_hw(hw); > +       if (rc) > +               goto err_free_cookie; > + > +       hw->wiphy->interface_modes = 0; > +       if (priv->ap_macids_supported || priv->device_info->fw_image_ap) > +               hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP); > +       if (priv->sta_macids_supported || priv->device_info->fw_image_sta) > +               hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_STATION); > + > +       rc = ieee80211_register_hw(hw); > +       if (rc) { > +               wiphy_err(hw->wiphy, "Cannot register device\n"); > +               goto err_unprobe_hw; > +       } > + > +       return 0; > + > +err_unprobe_hw: > +       for (i = 0; i < MWL8K_TX_QUEUES; i++) > +               mwl8k_txq_deinit(hw, i); > +       mwl8k_rxq_deinit(hw, 0); > + >  err_free_cookie: >        if (priv->cookie != NULL) >                pci_free_consistent(priv->pdev, 4, >                                priv->cookie, priv->cookie_dma); > > +       return rc; > +} > +static int __devinit mwl8k_probe(struct pci_dev *pdev, > +                                const struct pci_device_id *id) > +{ > +       static int printed_version; > +       struct ieee80211_hw *hw; > +       struct mwl8k_priv *priv; > +       int rc; > + > +       if (!printed_version) { > +               printk(KERN_INFO "%s version %s\n", MWL8K_DESC, MWL8K_VERSION); > +               printed_version = 1; > +       } > + > + > +       rc = pci_enable_device(pdev); > +       if (rc) { > +               printk(KERN_ERR "%s: Cannot enable new PCI device\n", > +                      MWL8K_NAME); > +               return rc; > +       } > + > +       rc = pci_request_regions(pdev, MWL8K_NAME); > +       if (rc) { > +               printk(KERN_ERR "%s: Cannot obtain PCI resources\n", > +                      MWL8K_NAME); > +               goto err_disable_device; > +       } > + > +       pci_set_master(pdev); > + > + > +       hw = ieee80211_alloc_hw(sizeof(*priv), &mwl8k_ops); > +       if (hw == NULL) { > +               printk(KERN_ERR "%s: ieee80211 alloc failed\n", MWL8K_NAME); > +               rc = -ENOMEM; > +               goto err_free_reg; > +       } > + > +       SET_IEEE80211_DEV(hw, &pdev->dev); > +       pci_set_drvdata(pdev, hw); > + > +       priv = hw->priv; > +       priv->hw = hw; > +       priv->pdev = pdev; > +       priv->device_info = &mwl8k_info_tbl[id->driver_data]; > + > + > +       priv->sram = pci_iomap(pdev, 0, 0x10000); > +       if (priv->sram == NULL) { > +               wiphy_err(hw->wiphy, "Cannot map device SRAM\n"); > +               goto err_iounmap; > +       } > + > +       /* > +        * If BAR0 is a 32 bit BAR, the register BAR will be BAR1. > +        * If BAR0 is a 64 bit BAR, the register BAR will be BAR2. > +        */ > +       priv->regs = pci_iomap(pdev, 1, 0x10000); > +       if (priv->regs == NULL) { > +               priv->regs = pci_iomap(pdev, 2, 0x10000); > +               if (priv->regs == NULL) { > +                       wiphy_err(hw->wiphy, "Cannot map device registers\n"); > +                       goto err_iounmap; > +               } > +       } > + > +       rc = mwl8k_init_firmware(hw); > +       if (rc) > +               goto err_stop_firmware; > + > +       rc = mwl8k_firmware_load_success(priv); > +       if (!rc) > +               return rc; > + >  err_stop_firmware: >        mwl8k_hw_reset(priv); > -       mwl8k_release_firmware(priv); > >  err_iounmap: >        if (priv->regs != NULL) > -- > 1.7.1.1 > >