diff options
author | Johannes Berg <johannes.berg@intel.com> | 2011-04-16 11:29:24 -0400 |
---|---|---|
committer | Wey-Yi Guy <wey-yi.w.guy@intel.com> | 2011-04-22 13:21:18 -0400 |
commit | dbf28e21ca391110e90ccad05dda79d2e2f60e0e (patch) | |
tree | 76aa45ec1cfb00c09b9cae51742c475ab821911a /drivers/net/wireless | |
parent | ca7966c88e44233fac113579071a6f55e00ef5ac (diff) |
iwlagn: combine firmware code/data
On new hardware, ucode images always come in
pairs: code and data. Therefore, combine the
variables into an appropriate struct and use
that when both code and data are needed.
Also, combine allocation and copying so that
we have less code in total.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 23 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 98 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-debugfs.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-dev.h | 11 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-helpers.h | 24 |
6 files changed, 65 insertions, 98 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index 56dc7712aa70..c3ae2e44fcc9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | |||
@@ -161,17 +161,16 @@ static int iwlagn_load_section(struct iwl_priv *priv, const char *name, | |||
161 | } | 161 | } |
162 | 162 | ||
163 | static int iwlagn_load_given_ucode(struct iwl_priv *priv, | 163 | static int iwlagn_load_given_ucode(struct iwl_priv *priv, |
164 | struct fw_desc *inst_image, | 164 | struct fw_img *image) |
165 | struct fw_desc *data_image) | ||
166 | { | 165 | { |
167 | int ret = 0; | 166 | int ret = 0; |
168 | 167 | ||
169 | ret = iwlagn_load_section(priv, "INST", inst_image, | 168 | ret = iwlagn_load_section(priv, "INST", &image->code, |
170 | IWLAGN_RTC_INST_LOWER_BOUND); | 169 | IWLAGN_RTC_INST_LOWER_BOUND); |
171 | if (ret) | 170 | if (ret) |
172 | return ret; | 171 | return ret; |
173 | 172 | ||
174 | return iwlagn_load_section(priv, "DATA", data_image, | 173 | return iwlagn_load_section(priv, "DATA", &image->data, |
175 | IWLAGN_RTC_DATA_LOWER_BOUND); | 174 | IWLAGN_RTC_DATA_LOWER_BOUND); |
176 | } | 175 | } |
177 | 176 | ||
@@ -557,16 +556,16 @@ static void iwl_print_mismatch_inst(struct iwl_priv *priv, | |||
557 | * iwl_verify_ucode - determine which instruction image is in SRAM, | 556 | * iwl_verify_ucode - determine which instruction image is in SRAM, |
558 | * and verify its contents | 557 | * and verify its contents |
559 | */ | 558 | */ |
560 | static int iwl_verify_ucode(struct iwl_priv *priv, struct fw_desc *fw_desc) | 559 | static int iwl_verify_ucode(struct iwl_priv *priv, struct fw_img *img) |
561 | { | 560 | { |
562 | if (!iwlcore_verify_inst_sparse(priv, fw_desc)) { | 561 | if (!iwlcore_verify_inst_sparse(priv, &img->code)) { |
563 | IWL_DEBUG_INFO(priv, "uCode is good in inst SRAM\n"); | 562 | IWL_DEBUG_INFO(priv, "uCode is good in inst SRAM\n"); |
564 | return 0; | 563 | return 0; |
565 | } | 564 | } |
566 | 565 | ||
567 | IWL_ERR(priv, "UCODE IMAGE IN INSTRUCTION SRAM NOT VALID!!\n"); | 566 | IWL_ERR(priv, "UCODE IMAGE IN INSTRUCTION SRAM NOT VALID!!\n"); |
568 | 567 | ||
569 | iwl_print_mismatch_inst(priv, fw_desc); | 568 | iwl_print_mismatch_inst(priv, &img->code); |
570 | return -EIO; | 569 | return -EIO; |
571 | } | 570 | } |
572 | 571 | ||
@@ -602,8 +601,7 @@ static void iwlagn_alive_fn(struct iwl_priv *priv, | |||
602 | #define UCODE_CALIB_TIMEOUT (2*HZ) | 601 | #define UCODE_CALIB_TIMEOUT (2*HZ) |
603 | 602 | ||
604 | int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, | 603 | int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, |
605 | struct fw_desc *inst_image, | 604 | struct fw_img *image, |
606 | struct fw_desc *data_image, | ||
607 | int subtype, int alternate_subtype) | 605 | int subtype, int alternate_subtype) |
608 | { | 606 | { |
609 | struct iwl_notification_wait alive_wait; | 607 | struct iwl_notification_wait alive_wait; |
@@ -621,7 +619,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, | |||
621 | old_type = priv->ucode_type; | 619 | old_type = priv->ucode_type; |
622 | priv->ucode_type = subtype; | 620 | priv->ucode_type = subtype; |
623 | 621 | ||
624 | ret = iwlagn_load_given_ucode(priv, inst_image, data_image); | 622 | ret = iwlagn_load_given_ucode(priv, image); |
625 | if (ret) { | 623 | if (ret) { |
626 | priv->ucode_type = old_type; | 624 | priv->ucode_type = old_type; |
627 | iwlagn_remove_notification(priv, &alive_wait); | 625 | iwlagn_remove_notification(priv, &alive_wait); |
@@ -656,7 +654,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, | |||
656 | return -EIO; | 654 | return -EIO; |
657 | } | 655 | } |
658 | 656 | ||
659 | ret = iwl_verify_ucode(priv, inst_image); | 657 | ret = iwl_verify_ucode(priv, image); |
660 | if (ret) { | 658 | if (ret) { |
661 | priv->ucode_type = old_type; | 659 | priv->ucode_type = old_type; |
662 | return ret; | 660 | return ret; |
@@ -684,7 +682,7 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv) | |||
684 | lockdep_assert_held(&priv->mutex); | 682 | lockdep_assert_held(&priv->mutex); |
685 | 683 | ||
686 | /* No init ucode required? Curious, but maybe ok */ | 684 | /* No init ucode required? Curious, but maybe ok */ |
687 | if (!priv->ucode_init.len) | 685 | if (!priv->ucode_init.code.len) |
688 | return 0; | 686 | return 0; |
689 | 687 | ||
690 | if (priv->ucode_type != UCODE_SUBTYPE_NONE_LOADED) | 688 | if (priv->ucode_type != UCODE_SUBTYPE_NONE_LOADED) |
@@ -696,7 +694,6 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv) | |||
696 | 694 | ||
697 | /* Will also start the device */ | 695 | /* Will also start the device */ |
698 | ret = iwlagn_load_ucode_wait_alive(priv, &priv->ucode_init, | 696 | ret = iwlagn_load_ucode_wait_alive(priv, &priv->ucode_init, |
699 | &priv->ucode_init_data, | ||
700 | UCODE_SUBTYPE_INIT, -1); | 697 | UCODE_SUBTYPE_INIT, -1); |
701 | if (ret) | 698 | if (ret) |
702 | goto error; | 699 | goto error; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 12cd5e0352bc..f30735b656c0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -1173,12 +1173,42 @@ static struct attribute_group iwl_attribute_group = { | |||
1173 | * | 1173 | * |
1174 | ******************************************************************************/ | 1174 | ******************************************************************************/ |
1175 | 1175 | ||
1176 | static void iwl_free_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc) | ||
1177 | { | ||
1178 | if (desc->v_addr) | ||
1179 | dma_free_coherent(&pci_dev->dev, desc->len, | ||
1180 | desc->v_addr, desc->p_addr); | ||
1181 | desc->v_addr = NULL; | ||
1182 | desc->len = 0; | ||
1183 | } | ||
1184 | |||
1185 | static void iwl_free_fw_img(struct pci_dev *pci_dev, struct fw_img *img) | ||
1186 | { | ||
1187 | iwl_free_fw_desc(pci_dev, &img->code); | ||
1188 | iwl_free_fw_desc(pci_dev, &img->data); | ||
1189 | } | ||
1190 | |||
1191 | static int iwl_alloc_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc, | ||
1192 | const void *data, size_t len) | ||
1193 | { | ||
1194 | if (!len) { | ||
1195 | desc->v_addr = NULL; | ||
1196 | return -EINVAL; | ||
1197 | } | ||
1198 | |||
1199 | desc->v_addr = dma_alloc_coherent(&pci_dev->dev, len, | ||
1200 | &desc->p_addr, GFP_KERNEL); | ||
1201 | if (!desc->v_addr) | ||
1202 | return -ENOMEM; | ||
1203 | desc->len = len; | ||
1204 | memcpy(desc->v_addr, data, len); | ||
1205 | return 0; | ||
1206 | } | ||
1207 | |||
1176 | static void iwl_dealloc_ucode_pci(struct iwl_priv *priv) | 1208 | static void iwl_dealloc_ucode_pci(struct iwl_priv *priv) |
1177 | { | 1209 | { |
1178 | iwl_free_fw_desc(priv->pci_dev, &priv->ucode_code); | 1210 | iwl_free_fw_img(priv->pci_dev, &priv->ucode_rt); |
1179 | iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data); | 1211 | iwl_free_fw_img(priv->pci_dev, &priv->ucode_init); |
1180 | iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init); | ||
1181 | iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init_data); | ||
1182 | } | 1212 | } |
1183 | 1213 | ||
1184 | struct iwlagn_ucode_capabilities { | 1214 | struct iwlagn_ucode_capabilities { |
@@ -1647,24 +1677,20 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
1647 | /* Runtime instructions and 2 copies of data: | 1677 | /* Runtime instructions and 2 copies of data: |
1648 | * 1) unmodified from disk | 1678 | * 1) unmodified from disk |
1649 | * 2) backup cache for save/restore during power-downs */ | 1679 | * 2) backup cache for save/restore during power-downs */ |
1650 | priv->ucode_code.len = pieces.inst_size; | 1680 | if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_rt.code, |
1651 | iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_code); | 1681 | pieces.inst, pieces.inst_size)) |
1652 | 1682 | goto err_pci_alloc; | |
1653 | priv->ucode_data.len = pieces.data_size; | 1683 | if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_rt.data, |
1654 | iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data); | 1684 | pieces.data, pieces.data_size)) |
1655 | |||
1656 | if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr) | ||
1657 | goto err_pci_alloc; | 1685 | goto err_pci_alloc; |
1658 | 1686 | ||
1659 | /* Initialization instructions and data */ | 1687 | /* Initialization instructions and data */ |
1660 | if (pieces.init_size && pieces.init_data_size) { | 1688 | if (pieces.init_size && pieces.init_data_size) { |
1661 | priv->ucode_init.len = pieces.init_size; | 1689 | if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init.code, |
1662 | iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init); | 1690 | pieces.init, pieces.init_size)) |
1663 | 1691 | goto err_pci_alloc; | |
1664 | priv->ucode_init_data.len = pieces.init_data_size; | 1692 | if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init.data, |
1665 | iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init_data); | 1693 | pieces.init_data, pieces.init_data_size)) |
1666 | |||
1667 | if (!priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr) | ||
1668 | goto err_pci_alloc; | 1694 | goto err_pci_alloc; |
1669 | } | 1695 | } |
1670 | 1696 | ||
@@ -1701,39 +1727,6 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
1701 | else | 1727 | else |
1702 | priv->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; | 1728 | priv->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; |
1703 | 1729 | ||
1704 | /* Copy images into buffers for card's bus-master reads ... */ | ||
1705 | |||
1706 | /* Runtime instructions (first block of data in file) */ | ||
1707 | IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode instr len %Zd\n", | ||
1708 | pieces.inst_size); | ||
1709 | memcpy(priv->ucode_code.v_addr, pieces.inst, pieces.inst_size); | ||
1710 | |||
1711 | IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n", | ||
1712 | priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr); | ||
1713 | |||
1714 | /* | ||
1715 | * Runtime data | ||
1716 | * NOTE: Copy into backup buffer will be done in iwl_up() | ||
1717 | */ | ||
1718 | IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode data len %Zd\n", | ||
1719 | pieces.data_size); | ||
1720 | memcpy(priv->ucode_data.v_addr, pieces.data, pieces.data_size); | ||
1721 | |||
1722 | /* Initialization instructions */ | ||
1723 | if (pieces.init_size) { | ||
1724 | IWL_DEBUG_INFO(priv, "Copying (but not loading) init instr len %Zd\n", | ||
1725 | pieces.init_size); | ||
1726 | memcpy(priv->ucode_init.v_addr, pieces.init, pieces.init_size); | ||
1727 | } | ||
1728 | |||
1729 | /* Initialization data */ | ||
1730 | if (pieces.init_data_size) { | ||
1731 | IWL_DEBUG_INFO(priv, "Copying (but not loading) init data len %Zd\n", | ||
1732 | pieces.init_data_size); | ||
1733 | memcpy(priv->ucode_init_data.v_addr, pieces.init_data, | ||
1734 | pieces.init_data_size); | ||
1735 | } | ||
1736 | |||
1737 | /* | 1730 | /* |
1738 | * figure out the offset of chain noise reset and gain commands | 1731 | * figure out the offset of chain noise reset and gain commands |
1739 | * base on the size of standard phy calibration commands table size | 1732 | * base on the size of standard phy calibration commands table size |
@@ -2450,8 +2443,7 @@ static int __iwl_up(struct iwl_priv *priv) | |||
2450 | } | 2443 | } |
2451 | 2444 | ||
2452 | ret = iwlagn_load_ucode_wait_alive(priv, | 2445 | ret = iwlagn_load_ucode_wait_alive(priv, |
2453 | &priv->ucode_code, | 2446 | &priv->ucode_rt, |
2454 | &priv->ucode_data, | ||
2455 | UCODE_SUBTYPE_REGULAR, | 2447 | UCODE_SUBTYPE_REGULAR, |
2456 | UCODE_SUBTYPE_REGULAR_NEW); | 2448 | UCODE_SUBTYPE_REGULAR_NEW); |
2457 | if (ret) { | 2449 | if (ret) { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index cf05f87ec80e..c475ac427596 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h | |||
@@ -164,8 +164,7 @@ int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type); | |||
164 | void iwlagn_send_prio_tbl(struct iwl_priv *priv); | 164 | void iwlagn_send_prio_tbl(struct iwl_priv *priv); |
165 | int iwlagn_run_init_ucode(struct iwl_priv *priv); | 165 | int iwlagn_run_init_ucode(struct iwl_priv *priv); |
166 | int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, | 166 | int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, |
167 | struct fw_desc *inst_image, | 167 | struct fw_img *image, |
168 | struct fw_desc *data_image, | ||
169 | int subtype, int alternate_subtype); | 168 | int subtype, int alternate_subtype); |
170 | 169 | ||
171 | /* lib */ | 170 | /* lib */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 2b606889b64b..7bd4f5af5b0d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c | |||
@@ -227,9 +227,9 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, | |||
227 | if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) { | 227 | if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) { |
228 | priv->dbgfs_sram_offset = 0x800000; | 228 | priv->dbgfs_sram_offset = 0x800000; |
229 | if (priv->ucode_type == UCODE_SUBTYPE_INIT) | 229 | if (priv->ucode_type == UCODE_SUBTYPE_INIT) |
230 | priv->dbgfs_sram_len = priv->ucode_init_data.len; | 230 | priv->dbgfs_sram_len = priv->ucode_init.data.len; |
231 | else | 231 | else |
232 | priv->dbgfs_sram_len = priv->ucode_data.len; | 232 | priv->dbgfs_sram_len = priv->ucode_rt.data.len; |
233 | } | 233 | } |
234 | len = priv->dbgfs_sram_len; | 234 | len = priv->dbgfs_sram_len; |
235 | 235 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 414968c6b7cf..857eb0e9e397 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -479,6 +479,10 @@ struct fw_desc { | |||
479 | u32 len; /* bytes */ | 479 | u32 len; /* bytes */ |
480 | }; | 480 | }; |
481 | 481 | ||
482 | struct fw_img { | ||
483 | struct fw_desc code, data; | ||
484 | }; | ||
485 | |||
482 | /* v1/v2 uCode file layout */ | 486 | /* v1/v2 uCode file layout */ |
483 | struct iwl_ucode_header { | 487 | struct iwl_ucode_header { |
484 | __le32 ver; /* major/minor/API/serial */ | 488 | __le32 ver; /* major/minor/API/serial */ |
@@ -1266,10 +1270,9 @@ struct iwl_priv { | |||
1266 | int fw_index; /* firmware we're trying to load */ | 1270 | int fw_index; /* firmware we're trying to load */ |
1267 | u32 ucode_ver; /* version of ucode, copy of | 1271 | u32 ucode_ver; /* version of ucode, copy of |
1268 | iwl_ucode.ver */ | 1272 | iwl_ucode.ver */ |
1269 | struct fw_desc ucode_code; /* runtime inst */ | 1273 | struct fw_img ucode_rt; |
1270 | struct fw_desc ucode_data; /* runtime data original */ | 1274 | struct fw_img ucode_init; |
1271 | struct fw_desc ucode_init; /* initialization inst */ | 1275 | |
1272 | struct fw_desc ucode_init_data; /* initialization data */ | ||
1273 | enum iwlagn_ucode_subtype ucode_type; | 1276 | enum iwlagn_ucode_subtype ucode_type; |
1274 | u8 ucode_write_complete; /* the image write is complete */ | 1277 | u8 ucode_write_complete; /* the image write is complete */ |
1275 | char firmware_name[25]; | 1278 | char firmware_name[25]; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index 9309ff2df4c2..41207a3645b8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h | |||
@@ -64,30 +64,6 @@ static inline int iwl_queue_dec_wrap(int index, int n_bd) | |||
64 | return --index & (n_bd - 1); | 64 | return --index & (n_bd - 1); |
65 | } | 65 | } |
66 | 66 | ||
67 | /* TODO: Move fw_desc functions to iwl-pci.ko */ | ||
68 | static inline void iwl_free_fw_desc(struct pci_dev *pci_dev, | ||
69 | struct fw_desc *desc) | ||
70 | { | ||
71 | if (desc->v_addr) | ||
72 | dma_free_coherent(&pci_dev->dev, desc->len, | ||
73 | desc->v_addr, desc->p_addr); | ||
74 | desc->v_addr = NULL; | ||
75 | desc->len = 0; | ||
76 | } | ||
77 | |||
78 | static inline int iwl_alloc_fw_desc(struct pci_dev *pci_dev, | ||
79 | struct fw_desc *desc) | ||
80 | { | ||
81 | if (!desc->len) { | ||
82 | desc->v_addr = NULL; | ||
83 | return -EINVAL; | ||
84 | } | ||
85 | |||
86 | desc->v_addr = dma_alloc_coherent(&pci_dev->dev, desc->len, | ||
87 | &desc->p_addr, GFP_KERNEL); | ||
88 | return (desc->v_addr != NULL) ? 0 : -ENOMEM; | ||
89 | } | ||
90 | |||
91 | /* | 67 | /* |
92 | * we have 8 bits used like this: | 68 | * we have 8 bits used like this: |
93 | * | 69 | * |