diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl3945-base.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl3945-base.c | 86 |
1 files changed, 65 insertions, 21 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 748ac1222abb..33239f197984 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -1557,6 +1557,20 @@ static void get_eeprom_mac(struct iwl3945_priv *priv, u8 *mac) | |||
1557 | memcpy(mac, priv->eeprom.mac_address, 6); | 1557 | memcpy(mac, priv->eeprom.mac_address, 6); |
1558 | } | 1558 | } |
1559 | 1559 | ||
1560 | /* | ||
1561 | * Clear the OWNER_MSK, to establish driver (instead of uCode running on | ||
1562 | * embedded controller) as EEPROM reader; each read is a series of pulses | ||
1563 | * to/from the EEPROM chip, not a single event, so even reads could conflict | ||
1564 | * if they weren't arbitrated by some ownership mechanism. Here, the driver | ||
1565 | * simply claims ownership, which should be safe when this function is called | ||
1566 | * (i.e. before loading uCode!). | ||
1567 | */ | ||
1568 | static inline int iwl3945_eeprom_acquire_semaphore(struct iwl3945_priv *priv) | ||
1569 | { | ||
1570 | _iwl3945_clear_bit(priv, CSR_EEPROM_GP, CSR_EEPROM_GP_IF_OWNER_MSK); | ||
1571 | return 0; | ||
1572 | } | ||
1573 | |||
1560 | /** | 1574 | /** |
1561 | * iwl3945_eeprom_init - read EEPROM contents | 1575 | * iwl3945_eeprom_init - read EEPROM contents |
1562 | * | 1576 | * |
@@ -2792,7 +2806,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, | |||
2792 | #endif | 2806 | #endif |
2793 | 2807 | ||
2794 | /* drop all data frame if we are not associated */ | 2808 | /* drop all data frame if we are not associated */ |
2795 | if (!iwl3945_is_associated(priv) && !priv->assoc_id && | 2809 | if ((!iwl3945_is_associated(priv) || !priv->assoc_id) && |
2796 | ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) { | 2810 | ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) { |
2797 | IWL_DEBUG_DROP("Dropping - !iwl3945_is_associated\n"); | 2811 | IWL_DEBUG_DROP("Dropping - !iwl3945_is_associated\n"); |
2798 | goto drop_unlock; | 2812 | goto drop_unlock; |
@@ -4745,8 +4759,9 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv) | |||
4745 | #ifdef CONFIG_IWL3945_DEBUG | 4759 | #ifdef CONFIG_IWL3945_DEBUG |
4746 | if (iwl3945_debug_level & (IWL_DL_ISR)) { | 4760 | if (iwl3945_debug_level & (IWL_DL_ISR)) { |
4747 | /* NIC fires this, but we don't use it, redundant with WAKEUP */ | 4761 | /* NIC fires this, but we don't use it, redundant with WAKEUP */ |
4748 | if (inta & CSR_INT_BIT_MAC_CLK_ACTV) | 4762 | if (inta & CSR_INT_BIT_SCD) |
4749 | IWL_DEBUG_ISR("Microcode started or stopped.\n"); | 4763 | IWL_DEBUG_ISR("Scheduler finished to transmit " |
4764 | "the frame/frames.\n"); | ||
4750 | 4765 | ||
4751 | /* Alive notification via Rx interrupt will do the real work */ | 4766 | /* Alive notification via Rx interrupt will do the real work */ |
4752 | if (inta & CSR_INT_BIT_ALIVE) | 4767 | if (inta & CSR_INT_BIT_ALIVE) |
@@ -4754,7 +4769,7 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv) | |||
4754 | } | 4769 | } |
4755 | #endif | 4770 | #endif |
4756 | /* Safely ignore these bits for debug checks below */ | 4771 | /* Safely ignore these bits for debug checks below */ |
4757 | inta &= ~(CSR_INT_BIT_MAC_CLK_ACTV | CSR_INT_BIT_ALIVE); | 4772 | inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE); |
4758 | 4773 | ||
4759 | /* HW RF KILL switch toggled (4965 only) */ | 4774 | /* HW RF KILL switch toggled (4965 only) */ |
4760 | if (inta & CSR_INT_BIT_RF_KILL) { | 4775 | if (inta & CSR_INT_BIT_RF_KILL) { |
@@ -4890,8 +4905,11 @@ static irqreturn_t iwl3945_isr(int irq, void *data) | |||
4890 | IWL_DEBUG_ISR("ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", | 4905 | IWL_DEBUG_ISR("ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", |
4891 | inta, inta_mask, inta_fh); | 4906 | inta, inta_mask, inta_fh); |
4892 | 4907 | ||
4908 | inta &= ~CSR_INT_BIT_SCD; | ||
4909 | |||
4893 | /* iwl3945_irq_tasklet() will service interrupts and re-enable them */ | 4910 | /* iwl3945_irq_tasklet() will service interrupts and re-enable them */ |
4894 | tasklet_schedule(&priv->irq_tasklet); | 4911 | if (likely(inta || inta_fh)) |
4912 | tasklet_schedule(&priv->irq_tasklet); | ||
4895 | unplugged: | 4913 | unplugged: |
4896 | spin_unlock(&priv->lock); | 4914 | spin_unlock(&priv->lock); |
4897 | 4915 | ||
@@ -5146,6 +5164,15 @@ static int iwl3945_init_channel_map(struct iwl3945_priv *priv) | |||
5146 | return 0; | 5164 | return 0; |
5147 | } | 5165 | } |
5148 | 5166 | ||
5167 | /* | ||
5168 | * iwl3945_free_channel_map - undo allocations in iwl3945_init_channel_map | ||
5169 | */ | ||
5170 | static void iwl3945_free_channel_map(struct iwl3945_priv *priv) | ||
5171 | { | ||
5172 | kfree(priv->channel_info); | ||
5173 | priv->channel_count = 0; | ||
5174 | } | ||
5175 | |||
5149 | /* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after | 5176 | /* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after |
5150 | * sending probe req. This should be set long enough to hear probe responses | 5177 | * sending probe req. This should be set long enough to hear probe responses |
5151 | * from more than one AP. */ | 5178 | * from more than one AP. */ |
@@ -5471,6 +5498,17 @@ static int iwl3945_init_geos(struct iwl3945_priv *priv) | |||
5471 | return 0; | 5498 | return 0; |
5472 | } | 5499 | } |
5473 | 5500 | ||
5501 | /* | ||
5502 | * iwl3945_free_geos - undo allocations in iwl3945_init_geos | ||
5503 | */ | ||
5504 | static void iwl3945_free_geos(struct iwl3945_priv *priv) | ||
5505 | { | ||
5506 | kfree(priv->modes); | ||
5507 | kfree(priv->ieee_channels); | ||
5508 | kfree(priv->ieee_rates); | ||
5509 | clear_bit(STATUS_GEO_CONFIGURED, &priv->status); | ||
5510 | } | ||
5511 | |||
5474 | /****************************************************************************** | 5512 | /****************************************************************************** |
5475 | * | 5513 | * |
5476 | * uCode download functions | 5514 | * uCode download functions |
@@ -6130,15 +6168,6 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv) | |||
6130 | /* Clear out the uCode error bit if it is set */ | 6168 | /* Clear out the uCode error bit if it is set */ |
6131 | clear_bit(STATUS_FW_ERROR, &priv->status); | 6169 | clear_bit(STATUS_FW_ERROR, &priv->status); |
6132 | 6170 | ||
6133 | rc = iwl3945_init_channel_map(priv); | ||
6134 | if (rc) { | ||
6135 | IWL_ERROR("initializing regulatory failed: %d\n", rc); | ||
6136 | return; | ||
6137 | } | ||
6138 | |||
6139 | iwl3945_init_geos(priv); | ||
6140 | iwl3945_reset_channel_flag(priv); | ||
6141 | |||
6142 | if (iwl3945_is_rfkill(priv)) | 6171 | if (iwl3945_is_rfkill(priv)) |
6143 | return; | 6172 | return; |
6144 | 6173 | ||
@@ -6599,7 +6628,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data) | |||
6599 | * that based on the direct_mask added to each channel entry */ | 6628 | * that based on the direct_mask added to each channel entry */ |
6600 | scan->tx_cmd.len = cpu_to_le16( | 6629 | scan->tx_cmd.len = cpu_to_le16( |
6601 | iwl3945_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data, | 6630 | iwl3945_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data, |
6602 | IWL_MAX_SCAN_SIZE - sizeof(scan), 0)); | 6631 | IWL_MAX_SCAN_SIZE - sizeof(*scan), 0)); |
6603 | scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; | 6632 | scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; |
6604 | scan->tx_cmd.sta_id = priv->hw_setting.bcast_sta_id; | 6633 | scan->tx_cmd.sta_id = priv->hw_setting.bcast_sta_id; |
6605 | scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; | 6634 | scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; |
@@ -7120,7 +7149,7 @@ static void iwl3945_config_ap(struct iwl3945_priv *priv) | |||
7120 | { | 7149 | { |
7121 | int rc = 0; | 7150 | int rc = 0; |
7122 | 7151 | ||
7123 | if (priv->status & STATUS_EXIT_PENDING) | 7152 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
7124 | return; | 7153 | return; |
7125 | 7154 | ||
7126 | /* The following should be done only at AP bring up */ | 7155 | /* The following should be done only at AP bring up */ |
@@ -8614,11 +8643,24 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
8614 | IWL_DEBUG_INFO("MAC address: %s\n", print_mac(mac, priv->mac_addr)); | 8643 | IWL_DEBUG_INFO("MAC address: %s\n", print_mac(mac, priv->mac_addr)); |
8615 | SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr); | 8644 | SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr); |
8616 | 8645 | ||
8646 | err = iwl3945_init_channel_map(priv); | ||
8647 | if (err) { | ||
8648 | IWL_ERROR("initializing regulatory failed: %d\n", err); | ||
8649 | goto out_remove_sysfs; | ||
8650 | } | ||
8651 | |||
8652 | err = iwl3945_init_geos(priv); | ||
8653 | if (err) { | ||
8654 | IWL_ERROR("initializing geos failed: %d\n", err); | ||
8655 | goto out_free_channel_map; | ||
8656 | } | ||
8657 | iwl3945_reset_channel_flag(priv); | ||
8658 | |||
8617 | iwl3945_rate_control_register(priv->hw); | 8659 | iwl3945_rate_control_register(priv->hw); |
8618 | err = ieee80211_register_hw(priv->hw); | 8660 | err = ieee80211_register_hw(priv->hw); |
8619 | if (err) { | 8661 | if (err) { |
8620 | IWL_ERROR("Failed to register network device (error %d)\n", err); | 8662 | IWL_ERROR("Failed to register network device (error %d)\n", err); |
8621 | goto out_remove_sysfs; | 8663 | goto out_free_geos; |
8622 | } | 8664 | } |
8623 | 8665 | ||
8624 | priv->hw->conf.beacon_int = 100; | 8666 | priv->hw->conf.beacon_int = 100; |
@@ -8628,6 +8670,10 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
8628 | 8670 | ||
8629 | return 0; | 8671 | return 0; |
8630 | 8672 | ||
8673 | out_free_geos: | ||
8674 | iwl3945_free_geos(priv); | ||
8675 | out_free_channel_map: | ||
8676 | iwl3945_free_channel_map(priv); | ||
8631 | out_remove_sysfs: | 8677 | out_remove_sysfs: |
8632 | sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group); | 8678 | sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group); |
8633 | 8679 | ||
@@ -8702,10 +8748,8 @@ static void iwl3945_pci_remove(struct pci_dev *pdev) | |||
8702 | pci_disable_device(pdev); | 8748 | pci_disable_device(pdev); |
8703 | pci_set_drvdata(pdev, NULL); | 8749 | pci_set_drvdata(pdev, NULL); |
8704 | 8750 | ||
8705 | kfree(priv->channel_info); | 8751 | iwl3945_free_channel_map(priv); |
8706 | 8752 | iwl3945_free_geos(priv); | |
8707 | kfree(priv->ieee_channels); | ||
8708 | kfree(priv->ieee_rates); | ||
8709 | 8753 | ||
8710 | if (priv->ibss_beacon) | 8754 | if (priv->ibss_beacon) |
8711 | dev_kfree_skb(priv->ibss_beacon); | 8755 | dev_kfree_skb(priv->ibss_beacon); |