aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c134
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl4965-base.c144
3 files changed, 137 insertions, 142 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index ca32fb3b9e1b..8c8b51dea57b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -704,3 +704,137 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags)
704} 704}
705EXPORT_SYMBOL(iwl_send_statistics_request); 705EXPORT_SYMBOL(iwl_send_statistics_request);
706 706
707/**
708 * iwl_verify_inst_sparse - verify runtime uCode image in card vs. host,
709 * using sample data 100 bytes apart. If these sample points are good,
710 * it's a pretty good bet that everything between them is good, too.
711 */
712static int iwlcore_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len)
713{
714 u32 val;
715 int ret = 0;
716 u32 errcnt = 0;
717 u32 i;
718
719 IWL_DEBUG_INFO("ucode inst image size is %u\n", len);
720
721 ret = iwl_grab_nic_access(priv);
722 if (ret)
723 return ret;
724
725 for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) {
726 /* read data comes through single port, auto-incr addr */
727 /* NOTE: Use the debugless read so we don't flood kernel log
728 * if IWL_DL_IO is set */
729 iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR,
730 i + RTC_INST_LOWER_BOUND);
731 val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
732 if (val != le32_to_cpu(*image)) {
733 ret = -EIO;
734 errcnt++;
735 if (errcnt >= 3)
736 break;
737 }
738 }
739
740 iwl_release_nic_access(priv);
741
742 return ret;
743}
744
745/**
746 * iwlcore_verify_inst_full - verify runtime uCode image in card vs. host,
747 * looking at all data.
748 */
749static int iwl_verify_inst_full(struct iwl_priv *priv, __le32 *image,
750 u32 len)
751{
752 u32 val;
753 u32 save_len = len;
754 int ret = 0;
755 u32 errcnt;
756
757 IWL_DEBUG_INFO("ucode inst image size is %u\n", len);
758
759 ret = iwl_grab_nic_access(priv);
760 if (ret)
761 return ret;
762
763 iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, RTC_INST_LOWER_BOUND);
764
765 errcnt = 0;
766 for (; len > 0; len -= sizeof(u32), image++) {
767 /* read data comes through single port, auto-incr addr */
768 /* NOTE: Use the debugless read so we don't flood kernel log
769 * if IWL_DL_IO is set */
770 val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
771 if (val != le32_to_cpu(*image)) {
772 IWL_ERROR("uCode INST section is invalid at "
773 "offset 0x%x, is 0x%x, s/b 0x%x\n",
774 save_len - len, val, le32_to_cpu(*image));
775 ret = -EIO;
776 errcnt++;
777 if (errcnt >= 20)
778 break;
779 }
780 }
781
782 iwl_release_nic_access(priv);
783
784 if (!errcnt)
785 IWL_DEBUG_INFO
786 ("ucode image in INSTRUCTION memory is good\n");
787
788 return ret;
789}
790
791/**
792 * iwl_verify_ucode - determine which instruction image is in SRAM,
793 * and verify its contents
794 */
795int iwl_verify_ucode(struct iwl_priv *priv)
796{
797 __le32 *image;
798 u32 len;
799 int ret;
800
801 /* Try bootstrap */
802 image = (__le32 *)priv->ucode_boot.v_addr;
803 len = priv->ucode_boot.len;
804 ret = iwlcore_verify_inst_sparse(priv, image, len);
805 if (!ret) {
806 IWL_DEBUG_INFO("Bootstrap uCode is good in inst SRAM\n");
807 return 0;
808 }
809
810 /* Try initialize */
811 image = (__le32 *)priv->ucode_init.v_addr;
812 len = priv->ucode_init.len;
813 ret = iwlcore_verify_inst_sparse(priv, image, len);
814 if (!ret) {
815 IWL_DEBUG_INFO("Initialize uCode is good in inst SRAM\n");
816 return 0;
817 }
818
819 /* Try runtime/protocol */
820 image = (__le32 *)priv->ucode_code.v_addr;
821 len = priv->ucode_code.len;
822 ret = iwlcore_verify_inst_sparse(priv, image, len);
823 if (!ret) {
824 IWL_DEBUG_INFO("Runtime uCode is good in inst SRAM\n");
825 return 0;
826 }
827
828 IWL_ERROR("NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n");
829
830 /* Since nothing seems to match, show first several data entries in
831 * instruction SRAM, so maybe visual inspection will give a clue.
832 * Selection of bootstrap image (vs. other images) is arbitrary. */
833 image = (__le32 *)priv->ucode_boot.v_addr;
834 len = priv->ucode_boot.len;
835 ret = iwl_verify_inst_full(priv, image, len);
836
837 return ret;
838}
839EXPORT_SYMBOL(iwl_verify_ucode);
840
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index e18940dbd13c..8196ef7303af 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -253,6 +253,7 @@ enum iwlcore_card_notify {
253int iwlcore_low_level_notify(struct iwl_priv *priv, 253int iwlcore_low_level_notify(struct iwl_priv *priv,
254 enum iwlcore_card_notify notify); 254 enum iwlcore_card_notify notify);
255extern int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags); 255extern int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags);
256extern int iwl_verify_ucode(struct iwl_priv *priv);
256int iwl_send_lq_cmd(struct iwl_priv *priv, 257int iwl_send_lq_cmd(struct iwl_priv *priv,
257 struct iwl_link_quality_cmd *lq, u8 flags); 258 struct iwl_link_quality_cmd *lq, u8 flags);
258 259
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index e24527313ab6..011f6114c338 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -4512,146 +4512,6 @@ static void iwl4965_dealloc_ucode_pci(struct iwl_priv *priv)
4512 iwl_free_fw_desc(priv->pci_dev, &priv->ucode_boot); 4512 iwl_free_fw_desc(priv->pci_dev, &priv->ucode_boot);
4513} 4513}
4514 4514
4515/**
4516 * iwl4965_verify_inst_full - verify runtime uCode image in card vs. host,
4517 * looking at all data.
4518 */
4519static int iwl4965_verify_inst_full(struct iwl_priv *priv, __le32 *image,
4520 u32 len)
4521{
4522 u32 val;
4523 u32 save_len = len;
4524 int rc = 0;
4525 u32 errcnt;
4526
4527 IWL_DEBUG_INFO("ucode inst image size is %u\n", len);
4528
4529 rc = iwl_grab_nic_access(priv);
4530 if (rc)
4531 return rc;
4532
4533 iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, RTC_INST_LOWER_BOUND);
4534
4535 errcnt = 0;
4536 for (; len > 0; len -= sizeof(u32), image++) {
4537 /* read data comes through single port, auto-incr addr */
4538 /* NOTE: Use the debugless read so we don't flood kernel log
4539 * if IWL_DL_IO is set */
4540 val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
4541 if (val != le32_to_cpu(*image)) {
4542 IWL_ERROR("uCode INST section is invalid at "
4543 "offset 0x%x, is 0x%x, s/b 0x%x\n",
4544 save_len - len, val, le32_to_cpu(*image));
4545 rc = -EIO;
4546 errcnt++;
4547 if (errcnt >= 20)
4548 break;
4549 }
4550 }
4551
4552 iwl_release_nic_access(priv);
4553
4554 if (!errcnt)
4555 IWL_DEBUG_INFO
4556 ("ucode image in INSTRUCTION memory is good\n");
4557
4558 return rc;
4559}
4560
4561
4562/**
4563 * iwl4965_verify_inst_sparse - verify runtime uCode image in card vs. host,
4564 * using sample data 100 bytes apart. If these sample points are good,
4565 * it's a pretty good bet that everything between them is good, too.
4566 */
4567static int iwl4965_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len)
4568{
4569 u32 val;
4570 int rc = 0;
4571 u32 errcnt = 0;
4572 u32 i;
4573
4574 IWL_DEBUG_INFO("ucode inst image size is %u\n", len);
4575
4576 rc = iwl_grab_nic_access(priv);
4577 if (rc)
4578 return rc;
4579
4580 for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) {
4581 /* read data comes through single port, auto-incr addr */
4582 /* NOTE: Use the debugless read so we don't flood kernel log
4583 * if IWL_DL_IO is set */
4584 iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR,
4585 i + RTC_INST_LOWER_BOUND);
4586 val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
4587 if (val != le32_to_cpu(*image)) {
4588#if 0 /* Enable this if you want to see details */
4589 IWL_ERROR("uCode INST section is invalid at "
4590 "offset 0x%x, is 0x%x, s/b 0x%x\n",
4591 i, val, *image);
4592#endif
4593 rc = -EIO;
4594 errcnt++;
4595 if (errcnt >= 3)
4596 break;
4597 }
4598 }
4599
4600 iwl_release_nic_access(priv);
4601
4602 return rc;
4603}
4604
4605
4606/**
4607 * iwl4965_verify_ucode - determine which instruction image is in SRAM,
4608 * and verify its contents
4609 */
4610static int iwl4965_verify_ucode(struct iwl_priv *priv)
4611{
4612 __le32 *image;
4613 u32 len;
4614 int rc = 0;
4615
4616 /* Try bootstrap */
4617 image = (__le32 *)priv->ucode_boot.v_addr;
4618 len = priv->ucode_boot.len;
4619 rc = iwl4965_verify_inst_sparse(priv, image, len);
4620 if (rc == 0) {
4621 IWL_DEBUG_INFO("Bootstrap uCode is good in inst SRAM\n");
4622 return 0;
4623 }
4624
4625 /* Try initialize */
4626 image = (__le32 *)priv->ucode_init.v_addr;
4627 len = priv->ucode_init.len;
4628 rc = iwl4965_verify_inst_sparse(priv, image, len);
4629 if (rc == 0) {
4630 IWL_DEBUG_INFO("Initialize uCode is good in inst SRAM\n");
4631 return 0;
4632 }
4633
4634 /* Try runtime/protocol */
4635 image = (__le32 *)priv->ucode_code.v_addr;
4636 len = priv->ucode_code.len;
4637 rc = iwl4965_verify_inst_sparse(priv, image, len);
4638 if (rc == 0) {
4639 IWL_DEBUG_INFO("Runtime uCode is good in inst SRAM\n");
4640 return 0;
4641 }
4642
4643 IWL_ERROR("NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n");
4644
4645 /* Since nothing seems to match, show first several data entries in
4646 * instruction SRAM, so maybe visual inspection will give a clue.
4647 * Selection of bootstrap image (vs. other images) is arbitrary. */
4648 image = (__le32 *)priv->ucode_boot.v_addr;
4649 len = priv->ucode_boot.len;
4650 rc = iwl4965_verify_inst_full(priv, image, len);
4651
4652 return rc;
4653}
4654
4655static void iwl4965_nic_start(struct iwl_priv *priv) 4515static void iwl4965_nic_start(struct iwl_priv *priv)
4656{ 4516{
4657 /* Remove all resets to allow NIC to operate */ 4517 /* Remove all resets to allow NIC to operate */
@@ -4927,7 +4787,7 @@ static void iwl4965_init_alive_start(struct iwl_priv *priv)
4927 /* Bootstrap uCode has loaded initialize uCode ... verify inst image. 4787 /* Bootstrap uCode has loaded initialize uCode ... verify inst image.
4928 * This is a paranoid check, because we would not have gotten the 4788 * This is a paranoid check, because we would not have gotten the
4929 * "initialize" alive if code weren't properly loaded. */ 4789 * "initialize" alive if code weren't properly loaded. */
4930 if (iwl4965_verify_ucode(priv)) { 4790 if (iwl_verify_ucode(priv)) {
4931 /* Runtime instruction load was bad; 4791 /* Runtime instruction load was bad;
4932 * take it all the way back down so we can try again */ 4792 * take it all the way back down so we can try again */
4933 IWL_DEBUG_INFO("Bad \"initialize\" uCode load.\n"); 4793 IWL_DEBUG_INFO("Bad \"initialize\" uCode load.\n");
@@ -4975,7 +4835,7 @@ static void iwl4965_alive_start(struct iwl_priv *priv)
4975 /* Initialize uCode has loaded Runtime uCode ... verify inst image. 4835 /* Initialize uCode has loaded Runtime uCode ... verify inst image.
4976 * This is a paranoid check, because we would not have gotten the 4836 * This is a paranoid check, because we would not have gotten the
4977 * "runtime" alive if code weren't properly loaded. */ 4837 * "runtime" alive if code weren't properly loaded. */
4978 if (iwl4965_verify_ucode(priv)) { 4838 if (iwl_verify_ucode(priv)) {
4979 /* Runtime instruction load was bad; 4839 /* Runtime instruction load was bad;
4980 * take it all the way back down so we can try again */ 4840 * take it all the way back down so we can try again */
4981 IWL_DEBUG_INFO("Bad runtime uCode load.\n"); 4841 IWL_DEBUG_INFO("Bad runtime uCode load.\n");