diff options
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_attr.c | 33 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 1 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_hw4.h | 44 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 102 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 90 |
5 files changed, 259 insertions, 11 deletions
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 6ecd6daffc15..135a53baa735 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c | |||
| @@ -755,18 +755,18 @@ lpfc_issue_reset(struct device *dev, struct device_attribute *attr, | |||
| 755 | } | 755 | } |
| 756 | 756 | ||
| 757 | /** | 757 | /** |
| 758 | * lpfc_sli4_fw_dump_request - Request firmware to perform a firmware dump | 758 | * lpfc_sli4_pdev_reg_request - Request physical dev to perform a register acc |
| 759 | * @phba: lpfc_hba pointer. | 759 | * @phba: lpfc_hba pointer. |
| 760 | * | 760 | * |
| 761 | * Description: | 761 | * Description: |
| 762 | * Request SLI4 interface type-2 device to perform a dump of firmware dump | 762 | * Request SLI4 interface type-2 device to perform a physical register set |
| 763 | * object into it's /dbg directory of the flash file system. | 763 | * access. |
| 764 | * | 764 | * |
| 765 | * Returns: | 765 | * Returns: |
| 766 | * zero for success | 766 | * zero for success |
| 767 | **/ | 767 | **/ |
| 768 | static ssize_t | 768 | static ssize_t |
| 769 | lpfc_sli4_fw_dump_request(struct lpfc_hba *phba) | 769 | lpfc_sli4_pdev_reg_request(struct lpfc_hba *phba, uint32_t opcode) |
| 770 | { | 770 | { |
| 771 | struct completion online_compl; | 771 | struct completion online_compl; |
| 772 | uint32_t reg_val; | 772 | uint32_t reg_val; |
| @@ -776,6 +776,11 @@ lpfc_sli4_fw_dump_request(struct lpfc_hba *phba) | |||
| 776 | if (!phba->cfg_enable_hba_reset) | 776 | if (!phba->cfg_enable_hba_reset) |
| 777 | return -EIO; | 777 | return -EIO; |
| 778 | 778 | ||
| 779 | if ((phba->sli_rev < LPFC_SLI_REV4) || | ||
| 780 | (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) != | ||
| 781 | LPFC_SLI_INTF_IF_TYPE_2)) | ||
| 782 | return -EPERM; | ||
| 783 | |||
| 779 | status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE); | 784 | status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE); |
| 780 | 785 | ||
| 781 | if (status != 0) | 786 | if (status != 0) |
| @@ -786,7 +791,14 @@ lpfc_sli4_fw_dump_request(struct lpfc_hba *phba) | |||
| 786 | 791 | ||
| 787 | reg_val = readl(phba->sli4_hba.conf_regs_memmap_p + | 792 | reg_val = readl(phba->sli4_hba.conf_regs_memmap_p + |
| 788 | LPFC_CTL_PDEV_CTL_OFFSET); | 793 | LPFC_CTL_PDEV_CTL_OFFSET); |
| 789 | reg_val |= LPFC_FW_DUMP_REQUEST; | 794 | |
| 795 | if (opcode == LPFC_FW_DUMP) | ||
| 796 | reg_val |= LPFC_FW_DUMP_REQUEST; | ||
| 797 | else if (opcode == LPFC_FW_RESET) | ||
| 798 | reg_val |= LPFC_CTL_PDEV_CTL_FRST; | ||
| 799 | else if (opcode == LPFC_DV_RESET) | ||
| 800 | reg_val |= LPFC_CTL_PDEV_CTL_DRST; | ||
| 801 | |||
| 790 | writel(reg_val, phba->sli4_hba.conf_regs_memmap_p + | 802 | writel(reg_val, phba->sli4_hba.conf_regs_memmap_p + |
| 791 | LPFC_CTL_PDEV_CTL_OFFSET); | 803 | LPFC_CTL_PDEV_CTL_OFFSET); |
| 792 | /* flush */ | 804 | /* flush */ |
| @@ -904,12 +916,11 @@ lpfc_board_mode_store(struct device *dev, struct device_attribute *attr, | |||
| 904 | else | 916 | else |
| 905 | status = lpfc_do_offline(phba, LPFC_EVT_KILL); | 917 | status = lpfc_do_offline(phba, LPFC_EVT_KILL); |
| 906 | else if (strncmp(buf, "dump", sizeof("dump") - 1) == 0) | 918 | else if (strncmp(buf, "dump", sizeof("dump") - 1) == 0) |
| 907 | if ((phba->sli_rev < LPFC_SLI_REV4) || | 919 | status = lpfc_sli4_pdev_reg_request(phba, LPFC_FW_DUMP); |
| 908 | (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) != | 920 | else if (strncmp(buf, "fw_reset", sizeof("fw_reset") - 1) == 0) |
| 909 | LPFC_SLI_INTF_IF_TYPE_2)) | 921 | status = lpfc_sli4_pdev_reg_request(phba, LPFC_FW_RESET); |
| 910 | return -EPERM; | 922 | else if (strncmp(buf, "dv_reset", sizeof("dv_reset") - 1) == 0) |
| 911 | else | 923 | status = lpfc_sli4_pdev_reg_request(phba, LPFC_DV_RESET); |
| 912 | status = lpfc_sli4_fw_dump_request(phba); | ||
| 913 | else | 924 | else |
| 914 | return -EINVAL; | 925 | return -EINVAL; |
| 915 | 926 | ||
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 3b9a6152b7f9..0b63cb2610d0 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |||
| @@ -430,5 +430,6 @@ void lpfc_cleanup_wt_rrqs(struct lpfc_hba *); | |||
| 430 | void lpfc_cleanup_vports_rrqs(struct lpfc_vport *, struct lpfc_nodelist *); | 430 | void lpfc_cleanup_vports_rrqs(struct lpfc_vport *, struct lpfc_nodelist *); |
| 431 | struct lpfc_node_rrq *lpfc_get_active_rrq(struct lpfc_vport *, uint16_t, | 431 | struct lpfc_node_rrq *lpfc_get_active_rrq(struct lpfc_vport *, uint16_t, |
| 432 | uint32_t); | 432 | uint32_t); |
| 433 | int lpfc_wr_object(struct lpfc_hba *, struct list_head *, uint32_t, uint32_t *); | ||
| 433 | /* functions to support SR-IOV */ | 434 | /* functions to support SR-IOV */ |
| 434 | int lpfc_sli_probe_sriov_nr_virtfn(struct lpfc_hba *, int); | 435 | int lpfc_sli_probe_sriov_nr_virtfn(struct lpfc_hba *, int); |
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 115915d4a60a..61a40fd1ad18 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h | |||
| @@ -821,6 +821,7 @@ struct mbox_header { | |||
| 821 | #define LPFC_MBOX_OPCODE_MQ_CREATE_EXT 0x5A | 821 | #define LPFC_MBOX_OPCODE_MQ_CREATE_EXT 0x5A |
| 822 | #define LPFC_MBOX_OPCODE_GET_FUNCTION_CONFIG 0xA0 | 822 | #define LPFC_MBOX_OPCODE_GET_FUNCTION_CONFIG 0xA0 |
| 823 | #define LPFC_MBOX_OPCODE_GET_PROFILE_CONFIG 0xA4 | 823 | #define LPFC_MBOX_OPCODE_GET_PROFILE_CONFIG 0xA4 |
| 824 | #define LPFC_MBOX_OPCODE_WRITE_OBJECT 0xAC | ||
| 824 | #define LPFC_MBOX_OPCODE_GET_SLI4_PARAMETERS 0xB5 | 825 | #define LPFC_MBOX_OPCODE_GET_SLI4_PARAMETERS 0xB5 |
| 825 | 826 | ||
| 826 | /* FCoE Opcodes */ | 827 | /* FCoE Opcodes */ |
| @@ -2372,6 +2373,29 @@ struct lpfc_mbx_get_prof_cfg { | |||
| 2372 | #define MB_CEQ_STATUS_QUEUE_FLUSHING 0x4 | 2373 | #define MB_CEQ_STATUS_QUEUE_FLUSHING 0x4 |
| 2373 | #define MB_CQE_STATUS_DMA_FAILED 0x5 | 2374 | #define MB_CQE_STATUS_DMA_FAILED 0x5 |
| 2374 | 2375 | ||
| 2376 | #define LPFC_MBX_WR_CONFIG_MAX_BDE 8 | ||
| 2377 | struct lpfc_mbx_wr_object { | ||
| 2378 | struct mbox_header header; | ||
| 2379 | union { | ||
| 2380 | struct { | ||
| 2381 | uint32_t word4; | ||
| 2382 | #define lpfc_wr_object_eof_SHIFT 31 | ||
| 2383 | #define lpfc_wr_object_eof_MASK 0x00000001 | ||
| 2384 | #define lpfc_wr_object_eof_WORD word4 | ||
| 2385 | #define lpfc_wr_object_write_length_SHIFT 0 | ||
| 2386 | #define lpfc_wr_object_write_length_MASK 0x00FFFFFF | ||
| 2387 | #define lpfc_wr_object_write_length_WORD word4 | ||
| 2388 | uint32_t write_offset; | ||
| 2389 | uint32_t object_name[26]; | ||
| 2390 | uint32_t bde_count; | ||
| 2391 | struct ulp_bde64 bde[LPFC_MBX_WR_CONFIG_MAX_BDE]; | ||
| 2392 | } request; | ||
| 2393 | struct { | ||
| 2394 | uint32_t actual_write_length; | ||
| 2395 | } response; | ||
| 2396 | } u; | ||
| 2397 | }; | ||
| 2398 | |||
| 2375 | /* mailbox queue entry structure */ | 2399 | /* mailbox queue entry structure */ |
| 2376 | struct lpfc_mqe { | 2400 | struct lpfc_mqe { |
| 2377 | uint32_t word0; | 2401 | uint32_t word0; |
| @@ -2421,6 +2445,7 @@ struct lpfc_mqe { | |||
| 2421 | struct lpfc_mbx_get_func_cfg get_func_cfg; | 2445 | struct lpfc_mbx_get_func_cfg get_func_cfg; |
| 2422 | struct lpfc_mbx_get_prof_cfg get_prof_cfg; | 2446 | struct lpfc_mbx_get_prof_cfg get_prof_cfg; |
| 2423 | struct lpfc_mbx_nop nop; | 2447 | struct lpfc_mbx_nop nop; |
| 2448 | struct lpfc_mbx_wr_object wr_object; | ||
| 2424 | } un; | 2449 | } un; |
| 2425 | }; | 2450 | }; |
| 2426 | 2451 | ||
| @@ -2966,9 +2991,28 @@ union lpfc_wqe { | |||
| 2966 | struct gen_req64_wqe gen_req; | 2991 | struct gen_req64_wqe gen_req; |
| 2967 | }; | 2992 | }; |
| 2968 | 2993 | ||
| 2994 | #define LPFC_GROUP_OJECT_MAGIC_NUM 0xfeaa0001 | ||
| 2995 | #define LPFC_FILE_TYPE_GROUP 0xf7 | ||
| 2996 | #define LPFC_FILE_ID_GROUP 0xa2 | ||
| 2997 | struct lpfc_grp_hdr { | ||
| 2998 | uint32_t size; | ||
| 2999 | uint32_t magic_number; | ||
| 3000 | uint32_t word2; | ||
| 3001 | #define lpfc_grp_hdr_file_type_SHIFT 24 | ||
| 3002 | #define lpfc_grp_hdr_file_type_MASK 0x000000FF | ||
| 3003 | #define lpfc_grp_hdr_file_type_WORD word2 | ||
| 3004 | #define lpfc_grp_hdr_id_SHIFT 16 | ||
| 3005 | #define lpfc_grp_hdr_id_MASK 0x000000FF | ||
| 3006 | #define lpfc_grp_hdr_id_WORD word2 | ||
| 3007 | uint8_t rev_name[128]; | ||
| 3008 | }; | ||
| 3009 | |||
| 2969 | #define FCP_COMMAND 0x0 | 3010 | #define FCP_COMMAND 0x0 |
| 2970 | #define FCP_COMMAND_DATA_OUT 0x1 | 3011 | #define FCP_COMMAND_DATA_OUT 0x1 |
| 2971 | #define ELS_COMMAND_NON_FIP 0xC | 3012 | #define ELS_COMMAND_NON_FIP 0xC |
| 2972 | #define ELS_COMMAND_FIP 0xD | 3013 | #define ELS_COMMAND_FIP 0xD |
| 2973 | #define OTHER_COMMAND 0x8 | 3014 | #define OTHER_COMMAND 0x8 |
| 2974 | 3015 | ||
| 3016 | #define LPFC_FW_DUMP 1 | ||
| 3017 | #define LPFC_FW_RESET 2 | ||
| 3018 | #define LPFC_DV_RESET 3 | ||
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index e81912cd257e..2b535cff4b2a 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | #include <linux/ctype.h> | 30 | #include <linux/ctype.h> |
| 31 | #include <linux/aer.h> | 31 | #include <linux/aer.h> |
| 32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
| 33 | #include <linux/firmware.h> | ||
| 33 | 34 | ||
| 34 | #include <scsi/scsi.h> | 35 | #include <scsi/scsi.h> |
| 35 | #include <scsi/scsi_device.h> | 36 | #include <scsi/scsi_device.h> |
| @@ -8775,6 +8776,97 @@ lpfc_sli4_get_els_iocb_cnt(struct lpfc_hba *phba) | |||
| 8775 | } | 8776 | } |
| 8776 | 8777 | ||
| 8777 | /** | 8778 | /** |
| 8779 | * lpfc_write_firmware - attempt to write a firmware image to the port | ||
| 8780 | * @phba: pointer to lpfc hba data structure. | ||
| 8781 | * @fw: pointer to firmware image returned from request_firmware. | ||
| 8782 | * | ||
| 8783 | * returns the number of bytes written if write is successful. | ||
| 8784 | * returns a negative error value if there were errors. | ||
| 8785 | * returns 0 if firmware matches currently active firmware on port. | ||
| 8786 | **/ | ||
| 8787 | int | ||
| 8788 | lpfc_write_firmware(struct lpfc_hba *phba, const struct firmware *fw) | ||
| 8789 | { | ||
| 8790 | char fwrev[32]; | ||
| 8791 | struct lpfc_grp_hdr *image = (struct lpfc_grp_hdr *)fw->data; | ||
| 8792 | struct list_head dma_buffer_list; | ||
| 8793 | int i, rc = 0; | ||
| 8794 | struct lpfc_dmabuf *dmabuf, *next; | ||
| 8795 | uint32_t offset = 0, temp_offset = 0; | ||
| 8796 | |||
| 8797 | INIT_LIST_HEAD(&dma_buffer_list); | ||
| 8798 | if ((image->magic_number != LPFC_GROUP_OJECT_MAGIC_NUM) || | ||
| 8799 | (bf_get(lpfc_grp_hdr_file_type, image) != LPFC_FILE_TYPE_GROUP) || | ||
| 8800 | (bf_get(lpfc_grp_hdr_id, image) != LPFC_FILE_ID_GROUP) || | ||
| 8801 | (image->size != fw->size)) { | ||
| 8802 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
| 8803 | "3022 Invalid FW image found. " | ||
| 8804 | "Magic:%d Type:%x ID:%x\n", | ||
| 8805 | image->magic_number, | ||
| 8806 | bf_get(lpfc_grp_hdr_file_type, image), | ||
| 8807 | bf_get(lpfc_grp_hdr_id, image)); | ||
| 8808 | return -EINVAL; | ||
| 8809 | } | ||
| 8810 | lpfc_decode_firmware_rev(phba, fwrev, 1); | ||
| 8811 | if (strncmp(fwrev, image->rev_name, strnlen(fwrev, 16))) { | ||
| 8812 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
| 8813 | "3023 Updating Firmware. Current Version:%s " | ||
| 8814 | "New Version:%s\n", | ||
| 8815 | fwrev, image->rev_name); | ||
| 8816 | for (i = 0; i < LPFC_MBX_WR_CONFIG_MAX_BDE; i++) { | ||
| 8817 | dmabuf = kzalloc(sizeof(struct lpfc_dmabuf), | ||
| 8818 | GFP_KERNEL); | ||
| 8819 | if (!dmabuf) { | ||
| 8820 | rc = -ENOMEM; | ||
| 8821 | goto out; | ||
| 8822 | } | ||
| 8823 | dmabuf->virt = dma_alloc_coherent(&phba->pcidev->dev, | ||
| 8824 | SLI4_PAGE_SIZE, | ||
| 8825 | &dmabuf->phys, | ||
| 8826 | GFP_KERNEL); | ||
| 8827 | if (!dmabuf->virt) { | ||
| 8828 | kfree(dmabuf); | ||
| 8829 | rc = -ENOMEM; | ||
| 8830 | goto out; | ||
| 8831 | } | ||
| 8832 | list_add_tail(&dmabuf->list, &dma_buffer_list); | ||
| 8833 | } | ||
| 8834 | while (offset < fw->size) { | ||
| 8835 | temp_offset = offset; | ||
| 8836 | list_for_each_entry(dmabuf, &dma_buffer_list, list) { | ||
| 8837 | if (offset + SLI4_PAGE_SIZE > fw->size) { | ||
| 8838 | temp_offset += fw->size - offset; | ||
| 8839 | memcpy(dmabuf->virt, | ||
| 8840 | fw->data + temp_offset, | ||
| 8841 | fw->size - offset); | ||
| 8842 | break; | ||
| 8843 | } | ||
| 8844 | temp_offset += SLI4_PAGE_SIZE; | ||
| 8845 | memcpy(dmabuf->virt, fw->data + temp_offset, | ||
| 8846 | SLI4_PAGE_SIZE); | ||
| 8847 | } | ||
| 8848 | rc = lpfc_wr_object(phba, &dma_buffer_list, | ||
| 8849 | (fw->size - offset), &offset); | ||
| 8850 | if (rc) { | ||
| 8851 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
| 8852 | "3024 Firmware update failed. " | ||
| 8853 | "%d\n", rc); | ||
| 8854 | goto out; | ||
| 8855 | } | ||
| 8856 | } | ||
| 8857 | rc = offset; | ||
| 8858 | } | ||
| 8859 | out: | ||
| 8860 | list_for_each_entry_safe(dmabuf, next, &dma_buffer_list, list) { | ||
| 8861 | list_del(&dmabuf->list); | ||
| 8862 | dma_free_coherent(&phba->pcidev->dev, SLI4_PAGE_SIZE, | ||
| 8863 | dmabuf->virt, dmabuf->phys); | ||
| 8864 | kfree(dmabuf); | ||
| 8865 | } | ||
| 8866 | return rc; | ||
| 8867 | } | ||
| 8868 | |||
| 8869 | /** | ||
| 8778 | * lpfc_pci_probe_one_s4 - PCI probe func to reg SLI-4 device to PCI subsys | 8870 | * lpfc_pci_probe_one_s4 - PCI probe func to reg SLI-4 device to PCI subsys |
| 8779 | * @pdev: pointer to PCI device | 8871 | * @pdev: pointer to PCI device |
| 8780 | * @pid: pointer to PCI device identifier | 8872 | * @pid: pointer to PCI device identifier |
| @@ -8803,6 +8895,8 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
| 8803 | int mcnt; | 8895 | int mcnt; |
| 8804 | int adjusted_fcp_eq_count; | 8896 | int adjusted_fcp_eq_count; |
| 8805 | int fcp_qidx; | 8897 | int fcp_qidx; |
| 8898 | const struct firmware *fw; | ||
| 8899 | uint8_t file_name[16]; | ||
| 8806 | 8900 | ||
| 8807 | /* Allocate memory for HBA structure */ | 8901 | /* Allocate memory for HBA structure */ |
| 8808 | phba = lpfc_hba_alloc(pdev); | 8902 | phba = lpfc_hba_alloc(pdev); |
| @@ -8957,6 +9051,14 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
| 8957 | /* Perform post initialization setup */ | 9051 | /* Perform post initialization setup */ |
| 8958 | lpfc_post_init_setup(phba); | 9052 | lpfc_post_init_setup(phba); |
| 8959 | 9053 | ||
| 9054 | /* check for firmware upgrade or downgrade */ | ||
| 9055 | snprintf(file_name, 16, "%s.grp", phba->ModelName); | ||
| 9056 | error = request_firmware(&fw, file_name, &phba->pcidev->dev); | ||
| 9057 | if (!error) { | ||
| 9058 | lpfc_write_firmware(phba, fw); | ||
| 9059 | release_firmware(fw); | ||
| 9060 | } | ||
| 9061 | |||
| 8960 | /* Check if there are static vports to be created. */ | 9062 | /* Check if there are static vports to be created. */ |
| 8961 | lpfc_create_static_vport(phba); | 9063 | lpfc_create_static_vport(phba); |
| 8962 | 9064 | ||
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index dd911d6d0ee5..fcfa8c8cfb67 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
| @@ -13500,6 +13500,96 @@ out: | |||
| 13500 | } | 13500 | } |
| 13501 | 13501 | ||
| 13502 | /** | 13502 | /** |
| 13503 | * lpfc_wr_object - write an object to the firmware | ||
| 13504 | * @phba: HBA structure that indicates port to create a queue on. | ||
| 13505 | * @dmabuf_list: list of dmabufs to write to the port. | ||
| 13506 | * @size: the total byte value of the objects to write to the port. | ||
| 13507 | * @offset: the current offset to be used to start the transfer. | ||
| 13508 | * | ||
| 13509 | * This routine will create a wr_object mailbox command to send to the port. | ||
| 13510 | * the mailbox command will be constructed using the dma buffers described in | ||
| 13511 | * @dmabuf_list to create a list of BDEs. This routine will fill in as many | ||
| 13512 | * BDEs that the imbedded mailbox can support. The @offset variable will be | ||
| 13513 | * used to indicate the starting offset of the transfer and will also return | ||
| 13514 | * the offset after the write object mailbox has completed. @size is used to | ||
| 13515 | * determine the end of the object and whether the eof bit should be set. | ||
| 13516 | * | ||
| 13517 | * Return 0 is successful and offset will contain the the new offset to use | ||
| 13518 | * for the next write. | ||
| 13519 | * Return negative value for error cases. | ||
| 13520 | **/ | ||
| 13521 | int | ||
| 13522 | lpfc_wr_object(struct lpfc_hba *phba, struct list_head *dmabuf_list, | ||
| 13523 | uint32_t size, uint32_t *offset) | ||
| 13524 | { | ||
| 13525 | struct lpfc_mbx_wr_object *wr_object; | ||
| 13526 | LPFC_MBOXQ_t *mbox; | ||
| 13527 | int rc = 0, i = 0; | ||
| 13528 | uint32_t shdr_status, shdr_add_status; | ||
| 13529 | uint32_t mbox_tmo; | ||
| 13530 | union lpfc_sli4_cfg_shdr *shdr; | ||
| 13531 | struct lpfc_dmabuf *dmabuf; | ||
| 13532 | uint32_t written = 0; | ||
| 13533 | |||
| 13534 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
| 13535 | if (!mbox) | ||
| 13536 | return -ENOMEM; | ||
| 13537 | |||
| 13538 | lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_COMMON, | ||
| 13539 | LPFC_MBOX_OPCODE_WRITE_OBJECT, | ||
| 13540 | sizeof(struct lpfc_mbx_wr_object) - | ||
| 13541 | sizeof(struct lpfc_sli4_cfg_mhdr), LPFC_SLI4_MBX_EMBED); | ||
| 13542 | |||
| 13543 | wr_object = (struct lpfc_mbx_wr_object *)&mbox->u.mqe.un.wr_object; | ||
| 13544 | wr_object->u.request.write_offset = *offset; | ||
| 13545 | sprintf((uint8_t *)wr_object->u.request.object_name, "/"); | ||
| 13546 | wr_object->u.request.object_name[0] = | ||
| 13547 | cpu_to_le32(wr_object->u.request.object_name[0]); | ||
| 13548 | bf_set(lpfc_wr_object_eof, &wr_object->u.request, 0); | ||
| 13549 | list_for_each_entry(dmabuf, dmabuf_list, list) { | ||
| 13550 | if (i >= LPFC_MBX_WR_CONFIG_MAX_BDE || written >= size) | ||
| 13551 | break; | ||
| 13552 | wr_object->u.request.bde[i].addrLow = putPaddrLow(dmabuf->phys); | ||
| 13553 | wr_object->u.request.bde[i].addrHigh = | ||
| 13554 | putPaddrHigh(dmabuf->phys); | ||
| 13555 | if (written + SLI4_PAGE_SIZE >= size) { | ||
| 13556 | wr_object->u.request.bde[i].tus.f.bdeSize = | ||
| 13557 | (size - written); | ||
| 13558 | written += (size - written); | ||
| 13559 | bf_set(lpfc_wr_object_eof, &wr_object->u.request, 1); | ||
| 13560 | } else { | ||
| 13561 | wr_object->u.request.bde[i].tus.f.bdeSize = | ||
| 13562 | SLI4_PAGE_SIZE; | ||
| 13563 | written += SLI4_PAGE_SIZE; | ||
| 13564 | } | ||
| 13565 | i++; | ||
| 13566 | } | ||
| 13567 | wr_object->u.request.bde_count = i; | ||
| 13568 | bf_set(lpfc_wr_object_write_length, &wr_object->u.request, written); | ||
| 13569 | if (!phba->sli4_hba.intr_enable) | ||
| 13570 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); | ||
| 13571 | else { | ||
| 13572 | mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG); | ||
| 13573 | rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo); | ||
| 13574 | } | ||
| 13575 | /* The IOCTL status is embedded in the mailbox subheader. */ | ||
| 13576 | shdr = (union lpfc_sli4_cfg_shdr *) &wr_object->header.cfg_shdr; | ||
| 13577 | shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); | ||
| 13578 | shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response); | ||
| 13579 | if (rc != MBX_TIMEOUT) | ||
| 13580 | mempool_free(mbox, phba->mbox_mem_pool); | ||
| 13581 | if (shdr_status || shdr_add_status || rc) { | ||
| 13582 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
| 13583 | "3025 Write Object mailbox failed with " | ||
| 13584 | "status x%x add_status x%x, mbx status x%x\n", | ||
| 13585 | shdr_status, shdr_add_status, rc); | ||
| 13586 | rc = -ENXIO; | ||
| 13587 | } else | ||
| 13588 | *offset += wr_object->u.response.actual_write_length; | ||
| 13589 | return rc; | ||
| 13590 | } | ||
| 13591 | |||
| 13592 | /** | ||
| 13503 | * lpfc_cleanup_pending_mbox - Free up vport discovery mailbox commands. | 13593 | * lpfc_cleanup_pending_mbox - Free up vport discovery mailbox commands. |
| 13504 | * @vport: pointer to vport data structure. | 13594 | * @vport: pointer to vport data structure. |
| 13505 | * | 13595 | * |
