diff options
author | Shripad Nunjundarao <shripad.nunjundarao@emulex.com> | 2011-05-16 03:36:59 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-05-16 14:13:53 -0400 |
commit | 485bf569ba798b4702bc2efbfd3a355fe2c8db04 (patch) | |
tree | e0de5f64bfcf568d5a3a186df5106c2829415e3b /drivers/net/benet | |
parent | 005d569600b404cae0b356e3c4085290ecc17775 (diff) |
be2net: FW download for Lancer
Added implementation of FW download feature for Lancer.
Signed-off-by: Shripad Nunjundarao <shripad.nunjundarao@emulex.com>
Signed-off-by: Sevin Xavier <selvin.xavier@emulex.com>
Signed-off-by: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/benet')
-rw-r--r-- | drivers/net/benet/be_cmds.c | 78 | ||||
-rw-r--r-- | drivers/net/benet/be_cmds.h | 36 | ||||
-rw-r--r-- | drivers/net/benet/be_main.c | 129 |
3 files changed, 223 insertions, 20 deletions
diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index aaef0c731b9a..2463b1c97922 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c | |||
@@ -71,7 +71,8 @@ static int be_mcc_compl_process(struct be_adapter *adapter, | |||
71 | compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) & | 71 | compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) & |
72 | CQE_STATUS_COMPL_MASK; | 72 | CQE_STATUS_COMPL_MASK; |
73 | 73 | ||
74 | if ((compl->tag0 == OPCODE_COMMON_WRITE_FLASHROM) && | 74 | if (((compl->tag0 == OPCODE_COMMON_WRITE_FLASHROM) || |
75 | (compl->tag0 == OPCODE_COMMON_WRITE_OBJECT)) && | ||
75 | (compl->tag1 == CMD_SUBSYSTEM_COMMON)) { | 76 | (compl->tag1 == CMD_SUBSYSTEM_COMMON)) { |
76 | adapter->flash_status = compl_status; | 77 | adapter->flash_status = compl_status; |
77 | complete(&adapter->flash_compl); | 78 | complete(&adapter->flash_compl); |
@@ -1801,6 +1802,81 @@ err: | |||
1801 | return status; | 1802 | return status; |
1802 | } | 1803 | } |
1803 | 1804 | ||
1805 | int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd, | ||
1806 | u32 data_size, u32 data_offset, const char *obj_name, | ||
1807 | u32 *data_written, u8 *addn_status) | ||
1808 | { | ||
1809 | struct be_mcc_wrb *wrb; | ||
1810 | struct lancer_cmd_req_write_object *req; | ||
1811 | struct lancer_cmd_resp_write_object *resp; | ||
1812 | void *ctxt = NULL; | ||
1813 | int status; | ||
1814 | |||
1815 | spin_lock_bh(&adapter->mcc_lock); | ||
1816 | adapter->flash_status = 0; | ||
1817 | |||
1818 | wrb = wrb_from_mccq(adapter); | ||
1819 | if (!wrb) { | ||
1820 | status = -EBUSY; | ||
1821 | goto err_unlock; | ||
1822 | } | ||
1823 | |||
1824 | req = embedded_payload(wrb); | ||
1825 | |||
1826 | be_wrb_hdr_prepare(wrb, sizeof(struct lancer_cmd_req_write_object), | ||
1827 | true, 1, OPCODE_COMMON_WRITE_OBJECT); | ||
1828 | wrb->tag1 = CMD_SUBSYSTEM_COMMON; | ||
1829 | |||
1830 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | ||
1831 | OPCODE_COMMON_WRITE_OBJECT, | ||
1832 | sizeof(struct lancer_cmd_req_write_object)); | ||
1833 | |||
1834 | ctxt = &req->context; | ||
1835 | AMAP_SET_BITS(struct amap_lancer_write_obj_context, | ||
1836 | write_length, ctxt, data_size); | ||
1837 | |||
1838 | if (data_size == 0) | ||
1839 | AMAP_SET_BITS(struct amap_lancer_write_obj_context, | ||
1840 | eof, ctxt, 1); | ||
1841 | else | ||
1842 | AMAP_SET_BITS(struct amap_lancer_write_obj_context, | ||
1843 | eof, ctxt, 0); | ||
1844 | |||
1845 | be_dws_cpu_to_le(ctxt, sizeof(req->context)); | ||
1846 | req->write_offset = cpu_to_le32(data_offset); | ||
1847 | strcpy(req->object_name, obj_name); | ||
1848 | req->descriptor_count = cpu_to_le32(1); | ||
1849 | req->buf_len = cpu_to_le32(data_size); | ||
1850 | req->addr_low = cpu_to_le32((cmd->dma + | ||
1851 | sizeof(struct lancer_cmd_req_write_object)) | ||
1852 | & 0xFFFFFFFF); | ||
1853 | req->addr_high = cpu_to_le32(upper_32_bits(cmd->dma + | ||
1854 | sizeof(struct lancer_cmd_req_write_object))); | ||
1855 | |||
1856 | be_mcc_notify(adapter); | ||
1857 | spin_unlock_bh(&adapter->mcc_lock); | ||
1858 | |||
1859 | if (!wait_for_completion_timeout(&adapter->flash_compl, | ||
1860 | msecs_to_jiffies(12000))) | ||
1861 | status = -1; | ||
1862 | else | ||
1863 | status = adapter->flash_status; | ||
1864 | |||
1865 | resp = embedded_payload(wrb); | ||
1866 | if (!status) { | ||
1867 | *data_written = le32_to_cpu(resp->actual_write_len); | ||
1868 | } else { | ||
1869 | *addn_status = resp->additional_status; | ||
1870 | status = resp->status; | ||
1871 | } | ||
1872 | |||
1873 | return status; | ||
1874 | |||
1875 | err_unlock: | ||
1876 | spin_unlock_bh(&adapter->mcc_lock); | ||
1877 | return status; | ||
1878 | } | ||
1879 | |||
1804 | int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, | 1880 | int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, |
1805 | u32 flash_type, u32 flash_opcode, u32 buf_size) | 1881 | u32 flash_type, u32 flash_opcode, u32 buf_size) |
1806 | { | 1882 | { |
diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h index 9cff226c94f1..8148cc66cbe9 100644 --- a/drivers/net/benet/be_cmds.h +++ b/drivers/net/benet/be_cmds.h | |||
@@ -193,6 +193,7 @@ struct be_mcc_mailbox { | |||
193 | #define OPCODE_COMMON_GET_PHY_DETAILS 102 | 193 | #define OPCODE_COMMON_GET_PHY_DETAILS 102 |
194 | #define OPCODE_COMMON_SET_DRIVER_FUNCTION_CAP 103 | 194 | #define OPCODE_COMMON_SET_DRIVER_FUNCTION_CAP 103 |
195 | #define OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES 121 | 195 | #define OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES 121 |
196 | #define OPCODE_COMMON_WRITE_OBJECT 172 | ||
196 | 197 | ||
197 | #define OPCODE_ETH_RSS_CONFIG 1 | 198 | #define OPCODE_ETH_RSS_CONFIG 1 |
198 | #define OPCODE_ETH_ACPI_CONFIG 2 | 199 | #define OPCODE_ETH_ACPI_CONFIG 2 |
@@ -1131,6 +1132,36 @@ struct be_cmd_write_flashrom { | |||
1131 | struct flashrom_params params; | 1132 | struct flashrom_params params; |
1132 | }; | 1133 | }; |
1133 | 1134 | ||
1135 | /**************** Lancer Firmware Flash ************/ | ||
1136 | struct amap_lancer_write_obj_context { | ||
1137 | u8 write_length[24]; | ||
1138 | u8 reserved1[7]; | ||
1139 | u8 eof; | ||
1140 | } __packed; | ||
1141 | |||
1142 | struct lancer_cmd_req_write_object { | ||
1143 | struct be_cmd_req_hdr hdr; | ||
1144 | u8 context[sizeof(struct amap_lancer_write_obj_context) / 8]; | ||
1145 | u32 write_offset; | ||
1146 | u8 object_name[104]; | ||
1147 | u32 descriptor_count; | ||
1148 | u32 buf_len; | ||
1149 | u32 addr_low; | ||
1150 | u32 addr_high; | ||
1151 | }; | ||
1152 | |||
1153 | struct lancer_cmd_resp_write_object { | ||
1154 | u8 opcode; | ||
1155 | u8 subsystem; | ||
1156 | u8 rsvd1[2]; | ||
1157 | u8 status; | ||
1158 | u8 additional_status; | ||
1159 | u8 rsvd2[2]; | ||
1160 | u32 resp_len; | ||
1161 | u32 actual_resp_len; | ||
1162 | u32 actual_write_len; | ||
1163 | }; | ||
1164 | |||
1134 | /************************ WOL *******************************/ | 1165 | /************************ WOL *******************************/ |
1135 | struct be_cmd_req_acpi_wol_magic_config{ | 1166 | struct be_cmd_req_acpi_wol_magic_config{ |
1136 | struct be_cmd_req_hdr hdr; | 1167 | struct be_cmd_req_hdr hdr; |
@@ -1481,6 +1512,11 @@ extern int be_cmd_get_beacon_state(struct be_adapter *adapter, | |||
1481 | extern int be_cmd_write_flashrom(struct be_adapter *adapter, | 1512 | extern int be_cmd_write_flashrom(struct be_adapter *adapter, |
1482 | struct be_dma_mem *cmd, u32 flash_oper, | 1513 | struct be_dma_mem *cmd, u32 flash_oper, |
1483 | u32 flash_opcode, u32 buf_size); | 1514 | u32 flash_opcode, u32 buf_size); |
1515 | extern int lancer_cmd_write_object(struct be_adapter *adapter, | ||
1516 | struct be_dma_mem *cmd, | ||
1517 | u32 data_size, u32 data_offset, | ||
1518 | const char *obj_name, | ||
1519 | u32 *data_written, u8 *addn_status); | ||
1484 | int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, | 1520 | int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, |
1485 | int offset); | 1521 | int offset); |
1486 | extern int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac, | 1522 | extern int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac, |
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 93be84ce9bad..7322a511e936 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c | |||
@@ -2712,7 +2712,6 @@ static int be_flash_data(struct be_adapter *adapter, | |||
2712 | "cmd to write to flash rom failed.\n"); | 2712 | "cmd to write to flash rom failed.\n"); |
2713 | return -1; | 2713 | return -1; |
2714 | } | 2714 | } |
2715 | yield(); | ||
2716 | } | 2715 | } |
2717 | } | 2716 | } |
2718 | return 0; | 2717 | return 0; |
@@ -2730,32 +2729,98 @@ static int get_ufigen_type(struct flash_file_hdr_g2 *fhdr) | |||
2730 | return 0; | 2729 | return 0; |
2731 | } | 2730 | } |
2732 | 2731 | ||
2733 | int be_load_fw(struct be_adapter *adapter, u8 *func) | 2732 | static int lancer_fw_download(struct be_adapter *adapter, |
2733 | const struct firmware *fw) | ||
2734 | { | 2734 | { |
2735 | char fw_file[ETHTOOL_FLASH_MAX_FILENAME]; | 2735 | #define LANCER_FW_DOWNLOAD_CHUNK (32 * 1024) |
2736 | const struct firmware *fw; | 2736 | #define LANCER_FW_DOWNLOAD_LOCATION "/prg" |
2737 | struct flash_file_hdr_g2 *fhdr; | ||
2738 | struct flash_file_hdr_g3 *fhdr3; | ||
2739 | struct image_hdr *img_hdr_ptr = NULL; | ||
2740 | struct be_dma_mem flash_cmd; | 2737 | struct be_dma_mem flash_cmd; |
2741 | int status, i = 0, num_imgs = 0; | 2738 | struct lancer_cmd_req_write_object *req; |
2742 | const u8 *p; | 2739 | const u8 *data_ptr = NULL; |
2740 | u8 *dest_image_ptr = NULL; | ||
2741 | size_t image_size = 0; | ||
2742 | u32 chunk_size = 0; | ||
2743 | u32 data_written = 0; | ||
2744 | u32 offset = 0; | ||
2745 | int status = 0; | ||
2746 | u8 add_status = 0; | ||
2743 | 2747 | ||
2744 | if (!netif_running(adapter->netdev)) { | 2748 | if (!IS_ALIGNED(fw->size, sizeof(u32))) { |
2745 | dev_err(&adapter->pdev->dev, | 2749 | dev_err(&adapter->pdev->dev, |
2746 | "Firmware load not allowed (interface is down)\n"); | 2750 | "FW Image not properly aligned. " |
2747 | return -EPERM; | 2751 | "Length must be 4 byte aligned.\n"); |
2752 | status = -EINVAL; | ||
2753 | goto lancer_fw_exit; | ||
2748 | } | 2754 | } |
2749 | 2755 | ||
2750 | strcpy(fw_file, func); | 2756 | flash_cmd.size = sizeof(struct lancer_cmd_req_write_object) |
2757 | + LANCER_FW_DOWNLOAD_CHUNK; | ||
2758 | flash_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, flash_cmd.size, | ||
2759 | &flash_cmd.dma, GFP_KERNEL); | ||
2760 | if (!flash_cmd.va) { | ||
2761 | status = -ENOMEM; | ||
2762 | dev_err(&adapter->pdev->dev, | ||
2763 | "Memory allocation failure while flashing\n"); | ||
2764 | goto lancer_fw_exit; | ||
2765 | } | ||
2751 | 2766 | ||
2752 | status = request_firmware(&fw, fw_file, &adapter->pdev->dev); | 2767 | req = flash_cmd.va; |
2753 | if (status) | 2768 | dest_image_ptr = flash_cmd.va + |
2754 | goto fw_exit; | 2769 | sizeof(struct lancer_cmd_req_write_object); |
2770 | image_size = fw->size; | ||
2771 | data_ptr = fw->data; | ||
2772 | |||
2773 | while (image_size) { | ||
2774 | chunk_size = min_t(u32, image_size, LANCER_FW_DOWNLOAD_CHUNK); | ||
2775 | |||
2776 | /* Copy the image chunk content. */ | ||
2777 | memcpy(dest_image_ptr, data_ptr, chunk_size); | ||
2778 | |||
2779 | status = lancer_cmd_write_object(adapter, &flash_cmd, | ||
2780 | chunk_size, offset, LANCER_FW_DOWNLOAD_LOCATION, | ||
2781 | &data_written, &add_status); | ||
2782 | |||
2783 | if (status) | ||
2784 | break; | ||
2785 | |||
2786 | offset += data_written; | ||
2787 | data_ptr += data_written; | ||
2788 | image_size -= data_written; | ||
2789 | } | ||
2790 | |||
2791 | if (!status) { | ||
2792 | /* Commit the FW written */ | ||
2793 | status = lancer_cmd_write_object(adapter, &flash_cmd, | ||
2794 | 0, offset, LANCER_FW_DOWNLOAD_LOCATION, | ||
2795 | &data_written, &add_status); | ||
2796 | } | ||
2797 | |||
2798 | dma_free_coherent(&adapter->pdev->dev, flash_cmd.size, flash_cmd.va, | ||
2799 | flash_cmd.dma); | ||
2800 | if (status) { | ||
2801 | dev_err(&adapter->pdev->dev, | ||
2802 | "Firmware load error. " | ||
2803 | "Status code: 0x%x Additional Status: 0x%x\n", | ||
2804 | status, add_status); | ||
2805 | goto lancer_fw_exit; | ||
2806 | } | ||
2807 | |||
2808 | dev_info(&adapter->pdev->dev, "Firmware flashed successfully\n"); | ||
2809 | lancer_fw_exit: | ||
2810 | return status; | ||
2811 | } | ||
2812 | |||
2813 | static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw) | ||
2814 | { | ||
2815 | struct flash_file_hdr_g2 *fhdr; | ||
2816 | struct flash_file_hdr_g3 *fhdr3; | ||
2817 | struct image_hdr *img_hdr_ptr = NULL; | ||
2818 | struct be_dma_mem flash_cmd; | ||
2819 | const u8 *p; | ||
2820 | int status = 0, i = 0, num_imgs = 0; | ||
2755 | 2821 | ||
2756 | p = fw->data; | 2822 | p = fw->data; |
2757 | fhdr = (struct flash_file_hdr_g2 *) p; | 2823 | fhdr = (struct flash_file_hdr_g2 *) p; |
2758 | dev_info(&adapter->pdev->dev, "Flashing firmware file %s\n", fw_file); | ||
2759 | 2824 | ||
2760 | flash_cmd.size = sizeof(struct be_cmd_write_flashrom) + 32*1024; | 2825 | flash_cmd.size = sizeof(struct be_cmd_write_flashrom) + 32*1024; |
2761 | flash_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, flash_cmd.size, | 2826 | flash_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, flash_cmd.size, |
@@ -2764,7 +2829,7 @@ int be_load_fw(struct be_adapter *adapter, u8 *func) | |||
2764 | status = -ENOMEM; | 2829 | status = -ENOMEM; |
2765 | dev_err(&adapter->pdev->dev, | 2830 | dev_err(&adapter->pdev->dev, |
2766 | "Memory allocation failure while flashing\n"); | 2831 | "Memory allocation failure while flashing\n"); |
2767 | goto fw_exit; | 2832 | goto be_fw_exit; |
2768 | } | 2833 | } |
2769 | 2834 | ||
2770 | if ((adapter->generation == BE_GEN3) && | 2835 | if ((adapter->generation == BE_GEN3) && |
@@ -2792,11 +2857,37 @@ int be_load_fw(struct be_adapter *adapter, u8 *func) | |||
2792 | flash_cmd.dma); | 2857 | flash_cmd.dma); |
2793 | if (status) { | 2858 | if (status) { |
2794 | dev_err(&adapter->pdev->dev, "Firmware load error\n"); | 2859 | dev_err(&adapter->pdev->dev, "Firmware load error\n"); |
2795 | goto fw_exit; | 2860 | goto be_fw_exit; |
2796 | } | 2861 | } |
2797 | 2862 | ||
2798 | dev_info(&adapter->pdev->dev, "Firmware flashed successfully\n"); | 2863 | dev_info(&adapter->pdev->dev, "Firmware flashed successfully\n"); |
2799 | 2864 | ||
2865 | be_fw_exit: | ||
2866 | return status; | ||
2867 | } | ||
2868 | |||
2869 | int be_load_fw(struct be_adapter *adapter, u8 *fw_file) | ||
2870 | { | ||
2871 | const struct firmware *fw; | ||
2872 | int status; | ||
2873 | |||
2874 | if (!netif_running(adapter->netdev)) { | ||
2875 | dev_err(&adapter->pdev->dev, | ||
2876 | "Firmware load not allowed (interface is down)\n"); | ||
2877 | return -1; | ||
2878 | } | ||
2879 | |||
2880 | status = request_firmware(&fw, fw_file, &adapter->pdev->dev); | ||
2881 | if (status) | ||
2882 | goto fw_exit; | ||
2883 | |||
2884 | dev_info(&adapter->pdev->dev, "Flashing firmware file %s\n", fw_file); | ||
2885 | |||
2886 | if (lancer_chip(adapter)) | ||
2887 | status = lancer_fw_download(adapter, fw); | ||
2888 | else | ||
2889 | status = be_fw_download(adapter, fw); | ||
2890 | |||
2800 | fw_exit: | 2891 | fw_exit: |
2801 | release_firmware(fw); | 2892 | release_firmware(fw); |
2802 | return status; | 2893 | return status; |