[SCSI] lpfc 8.3.24: Add request-firmware support
[pandora-kernel.git] / drivers / scsi / lpfc / lpfc_sli.c
index dd911d6..fcfa8c8 100644 (file)
@@ -13499,6 +13499,96 @@ out:
        return;
 }
 
+/**
+ * lpfc_wr_object - write an object to the firmware
+ * @phba: HBA structure that indicates port to create a queue on.
+ * @dmabuf_list: list of dmabufs to write to the port.
+ * @size: the total byte value of the objects to write to the port.
+ * @offset: the current offset to be used to start the transfer.
+ *
+ * This routine will create a wr_object mailbox command to send to the port.
+ * the mailbox command will be constructed using the dma buffers described in
+ * @dmabuf_list to create a list of BDEs. This routine will fill in as many
+ * BDEs that the imbedded mailbox can support. The @offset variable will be
+ * used to indicate the starting offset of the transfer and will also return
+ * the offset after the write object mailbox has completed. @size is used to
+ * determine the end of the object and whether the eof bit should be set.
+ *
+ * Return 0 is successful and offset will contain the the new offset to use
+ * for the next write.
+ * Return negative value for error cases.
+ **/
+int
+lpfc_wr_object(struct lpfc_hba *phba, struct list_head *dmabuf_list,
+              uint32_t size, uint32_t *offset)
+{
+       struct lpfc_mbx_wr_object *wr_object;
+       LPFC_MBOXQ_t *mbox;
+       int rc = 0, i = 0;
+       uint32_t shdr_status, shdr_add_status;
+       uint32_t mbox_tmo;
+       union lpfc_sli4_cfg_shdr *shdr;
+       struct lpfc_dmabuf *dmabuf;
+       uint32_t written = 0;
+
+       mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+       if (!mbox)
+               return -ENOMEM;
+
+       lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_COMMON,
+                       LPFC_MBOX_OPCODE_WRITE_OBJECT,
+                       sizeof(struct lpfc_mbx_wr_object) -
+                       sizeof(struct lpfc_sli4_cfg_mhdr), LPFC_SLI4_MBX_EMBED);
+
+       wr_object = (struct lpfc_mbx_wr_object *)&mbox->u.mqe.un.wr_object;
+       wr_object->u.request.write_offset = *offset;
+       sprintf((uint8_t *)wr_object->u.request.object_name, "/");
+       wr_object->u.request.object_name[0] =
+               cpu_to_le32(wr_object->u.request.object_name[0]);
+       bf_set(lpfc_wr_object_eof, &wr_object->u.request, 0);
+       list_for_each_entry(dmabuf, dmabuf_list, list) {
+               if (i >= LPFC_MBX_WR_CONFIG_MAX_BDE || written >= size)
+                       break;
+               wr_object->u.request.bde[i].addrLow = putPaddrLow(dmabuf->phys);
+               wr_object->u.request.bde[i].addrHigh =
+                       putPaddrHigh(dmabuf->phys);
+               if (written + SLI4_PAGE_SIZE >= size) {
+                       wr_object->u.request.bde[i].tus.f.bdeSize =
+                               (size - written);
+                       written += (size - written);
+                       bf_set(lpfc_wr_object_eof, &wr_object->u.request, 1);
+               } else {
+                       wr_object->u.request.bde[i].tus.f.bdeSize =
+                               SLI4_PAGE_SIZE;
+                       written += SLI4_PAGE_SIZE;
+               }
+               i++;
+       }
+       wr_object->u.request.bde_count = i;
+       bf_set(lpfc_wr_object_write_length, &wr_object->u.request, written);
+       if (!phba->sli4_hba.intr_enable)
+               rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
+       else {
+               mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG);
+               rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
+       }
+       /* The IOCTL status is embedded in the mailbox subheader. */
+       shdr = (union lpfc_sli4_cfg_shdr *) &wr_object->header.cfg_shdr;
+       shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
+       shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
+       if (rc != MBX_TIMEOUT)
+               mempool_free(mbox, phba->mbox_mem_pool);
+       if (shdr_status || shdr_add_status || rc) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                               "3025 Write Object mailbox failed with "
+                               "status x%x add_status x%x, mbx status x%x\n",
+                               shdr_status, shdr_add_status, rc);
+               rc = -ENXIO;
+       } else
+               *offset += wr_object->u.response.actual_write_length;
+       return rc;
+}
+
 /**
  * lpfc_cleanup_pending_mbox - Free up vport discovery mailbox commands.
  * @vport: pointer to vport data structure.