diff options
Diffstat (limited to 'drivers/scsi/megaraid')
-rw-r--r-- | drivers/scsi/megaraid/mega_common.h | 1 | ||||
-rw-r--r-- | drivers/scsi/megaraid/megaraid_mbox.c | 171 | ||||
-rw-r--r-- | drivers/scsi/megaraid/megaraid_mbox.h | 4 | ||||
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas.c | 112 |
4 files changed, 67 insertions, 221 deletions
diff --git a/drivers/scsi/megaraid/mega_common.h b/drivers/scsi/megaraid/mega_common.h index 26e1e6c55654..fef9ac958754 100644 --- a/drivers/scsi/megaraid/mega_common.h +++ b/drivers/scsi/megaraid/mega_common.h @@ -21,6 +21,7 @@ #include <linux/types.h> #include <linux/pci.h> #include <linux/spinlock.h> +#include <linux/mutex.h> #include <linux/interrupt.h> #include <linux/delay.h> #include <linux/blkdev.h> diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c index 04d0b6918c61..c46685a03a9f 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.c +++ b/drivers/scsi/megaraid/megaraid_mbox.c @@ -1378,8 +1378,6 @@ megaraid_mbox_mksgl(adapter_t *adapter, scb_t *scb) { struct scatterlist *sgl; mbox_ccb_t *ccb; - struct page *page; - unsigned long offset; struct scsi_cmnd *scp; int sgcnt; int i; @@ -1388,48 +1386,16 @@ megaraid_mbox_mksgl(adapter_t *adapter, scb_t *scb) scp = scb->scp; ccb = (mbox_ccb_t *)scb->ccb; + sgcnt = scsi_dma_map(scp); + BUG_ON(sgcnt < 0 || sgcnt > adapter->sglen); + // no mapping required if no data to be transferred - if (!scp->request_buffer || !scp->request_bufflen) + if (!sgcnt) return 0; - if (!scp->use_sg) { /* scatter-gather list not used */ - - page = virt_to_page(scp->request_buffer); - - offset = ((unsigned long)scp->request_buffer & ~PAGE_MASK); - - ccb->buf_dma_h = pci_map_page(adapter->pdev, page, offset, - scp->request_bufflen, - scb->dma_direction); - scb->dma_type = MRAID_DMA_WBUF; - - /* - * We need to handle special 64-bit commands that need a - * minimum of 1 SG - */ - sgcnt = 1; - ccb->sgl64[0].address = ccb->buf_dma_h; - ccb->sgl64[0].length = scp->request_bufflen; - - return sgcnt; - } - - sgl = (struct scatterlist *)scp->request_buffer; - - // The number of sg elements returned must not exceed our limit - sgcnt = pci_map_sg(adapter->pdev, sgl, scp->use_sg, - scb->dma_direction); - - if (sgcnt > adapter->sglen) { - con_log(CL_ANN, (KERN_CRIT - "megaraid critical: too many sg elements:%d\n", - sgcnt)); - BUG(); - } - scb->dma_type = MRAID_DMA_WSG; - for (i = 0; i < sgcnt; i++, sgl++) { + scsi_for_each_sg(scp, sgl, sgcnt, i) { ccb->sgl64[i].address = sg_dma_address(sgl); ccb->sgl64[i].length = sg_dma_len(sgl); } @@ -1489,19 +1455,11 @@ mbox_post_cmd(adapter_t *adapter, scb_t *scb) adapter->outstanding_cmds++; - if (scb->dma_direction == PCI_DMA_TODEVICE) { - if (!scb->scp->use_sg) { // sg list not used - pci_dma_sync_single_for_device(adapter->pdev, - ccb->buf_dma_h, - scb->scp->request_bufflen, - PCI_DMA_TODEVICE); - } - else { - pci_dma_sync_sg_for_device(adapter->pdev, - scb->scp->request_buffer, - scb->scp->use_sg, PCI_DMA_TODEVICE); - } - } + if (scb->dma_direction == PCI_DMA_TODEVICE) + pci_dma_sync_sg_for_device(adapter->pdev, + scsi_sglist(scb->scp), + scsi_sg_count(scb->scp), + PCI_DMA_TODEVICE); mbox->busy = 1; // Set busy mbox->poll = 0; @@ -1624,29 +1582,26 @@ megaraid_mbox_build_cmd(adapter_t *adapter, struct scsi_cmnd *scp, int *busy) return scb; case MODE_SENSE: - if (scp->use_sg) { - struct scatterlist *sgl; - caddr_t vaddr; + { + struct scatterlist *sgl; + caddr_t vaddr; - sgl = (struct scatterlist *)scp->request_buffer; - if (sgl->page) { - vaddr = (caddr_t) - (page_address((&sgl[0])->page) - + (&sgl[0])->offset); + sgl = scsi_sglist(scp); + if (sgl->page) { + vaddr = (caddr_t) + (page_address((&sgl[0])->page) + + (&sgl[0])->offset); - memset(vaddr, 0, scp->cmnd[4]); - } - else { - con_log(CL_ANN, (KERN_WARNING - "megaraid mailbox: invalid sg:%d\n", - __LINE__)); - } + memset(vaddr, 0, scp->cmnd[4]); } else { - memset(scp->request_buffer, 0, scp->cmnd[4]); + con_log(CL_ANN, (KERN_WARNING + "megaraid mailbox: invalid sg:%d\n", + __LINE__)); } - scp->result = (DID_OK << 16); - return NULL; + } + scp->result = (DID_OK << 16); + return NULL; case INQUIRY: /* @@ -1716,7 +1671,7 @@ megaraid_mbox_build_cmd(adapter_t *adapter, struct scsi_cmnd *scp, int *busy) mbox->cmd = MBOXCMD_PASSTHRU64; scb->dma_direction = scp->sc_data_direction; - pthru->dataxferlen = scp->request_bufflen; + pthru->dataxferlen = scsi_bufflen(scp); pthru->dataxferaddr = ccb->sgl_dma_h; pthru->numsge = megaraid_mbox_mksgl(adapter, scb); @@ -2050,8 +2005,8 @@ megaraid_mbox_prepare_pthru(adapter_t *adapter, scb_t *scb, memcpy(pthru->cdb, scp->cmnd, scp->cmd_len); - if (scp->request_bufflen) { - pthru->dataxferlen = scp->request_bufflen; + if (scsi_bufflen(scp)) { + pthru->dataxferlen = scsi_bufflen(scp); pthru->dataxferaddr = ccb->sgl_dma_h; pthru->numsge = megaraid_mbox_mksgl(adapter, scb); } @@ -2099,8 +2054,8 @@ megaraid_mbox_prepare_epthru(adapter_t *adapter, scb_t *scb, memcpy(epthru->cdb, scp->cmnd, scp->cmd_len); - if (scp->request_bufflen) { - epthru->dataxferlen = scp->request_bufflen; + if (scsi_bufflen(scp)) { + epthru->dataxferlen = scsi_bufflen(scp); epthru->dataxferaddr = ccb->sgl_dma_h; epthru->numsge = megaraid_mbox_mksgl(adapter, scb); } @@ -2266,37 +2221,13 @@ megaraid_mbox_sync_scb(adapter_t *adapter, scb_t *scb) ccb = (mbox_ccb_t *)scb->ccb; - switch (scb->dma_type) { - - case MRAID_DMA_WBUF: - if (scb->dma_direction == PCI_DMA_FROMDEVICE) { - pci_dma_sync_single_for_cpu(adapter->pdev, - ccb->buf_dma_h, - scb->scp->request_bufflen, + if (scb->dma_direction == PCI_DMA_FROMDEVICE) + pci_dma_sync_sg_for_cpu(adapter->pdev, + scsi_sglist(scb->scp), + scsi_sg_count(scb->scp), PCI_DMA_FROMDEVICE); - } - - pci_unmap_page(adapter->pdev, ccb->buf_dma_h, - scb->scp->request_bufflen, scb->dma_direction); - - break; - - case MRAID_DMA_WSG: - if (scb->dma_direction == PCI_DMA_FROMDEVICE) { - pci_dma_sync_sg_for_cpu(adapter->pdev, - scb->scp->request_buffer, - scb->scp->use_sg, PCI_DMA_FROMDEVICE); - } - - pci_unmap_sg(adapter->pdev, scb->scp->request_buffer, - scb->scp->use_sg, scb->dma_direction); - - break; - - default: - break; - } + scsi_dma_unmap(scb->scp); return; } @@ -2399,24 +2330,16 @@ megaraid_mbox_dpc(unsigned long devp) if (scp->cmnd[0] == INQUIRY && status == 0 && islogical == 0 && IS_RAID_CH(raid_dev, scb->dev_channel)) { - if (scp->use_sg) { - sgl = (struct scatterlist *) - scp->request_buffer; - - if (sgl->page) { - c = *(unsigned char *) + sgl = scsi_sglist(scp); + if (sgl->page) { + c = *(unsigned char *) (page_address((&sgl[0])->page) + - (&sgl[0])->offset); - } - else { - con_log(CL_ANN, (KERN_WARNING - "megaraid mailbox: invalid sg:%d\n", - __LINE__)); - c = 0; - } - } - else { - c = *(uint8_t *)scp->request_buffer; + (&sgl[0])->offset); + } else { + con_log(CL_ANN, (KERN_WARNING + "megaraid mailbox: invalid sg:%d\n", + __LINE__)); + c = 0; } if ((c & 0x1F ) == TYPE_DISK) { @@ -3957,7 +3880,7 @@ megaraid_sysfs_alloc_resources(adapter_t *adapter) megaraid_sysfs_free_resources(adapter); } - sema_init(&raid_dev->sysfs_sem, 1); + mutex_init(&raid_dev->sysfs_mtx); init_waitqueue_head(&raid_dev->sysfs_wait_q); @@ -4058,7 +3981,7 @@ megaraid_sysfs_get_ldmap(adapter_t *adapter) /* * Allow only one read at a time to go through the sysfs attributes */ - down(&raid_dev->sysfs_sem); + mutex_lock(&raid_dev->sysfs_mtx); uioc = raid_dev->sysfs_uioc; mbox64 = raid_dev->sysfs_mbox64; @@ -4134,7 +4057,7 @@ megaraid_sysfs_get_ldmap(adapter_t *adapter) del_timer_sync(timerp); - up(&raid_dev->sysfs_sem); + mutex_unlock(&raid_dev->sysfs_mtx); return rval; } diff --git a/drivers/scsi/megaraid/megaraid_mbox.h b/drivers/scsi/megaraid/megaraid_mbox.h index 9de803cebd4b..626459d1e902 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.h +++ b/drivers/scsi/megaraid/megaraid_mbox.h @@ -168,7 +168,7 @@ typedef struct { * @hw_error : set if FW not responding * @fast_load : If set, skip physical device scanning * @channel_class : channel class, RAID or SCSI - * @sysfs_sem : semaphore to serialize access to sysfs res. + * @sysfs_mtx : mutex to serialize access to sysfs res. * @sysfs_uioc : management packet to issue FW calls from sysfs * @sysfs_mbox64 : mailbox packet to issue FW calls from sysfs * @sysfs_buffer : data buffer for FW commands issued from sysfs @@ -208,7 +208,7 @@ typedef struct { int hw_error; int fast_load; uint8_t channel_class; - struct semaphore sysfs_sem; + struct mutex sysfs_mtx; uioc_t *sysfs_uioc; mbox64_t *sysfs_mbox64; caddr_t sysfs_buffer; diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index e2cf12ef3688..b7f2e613c903 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c @@ -433,34 +433,15 @@ megasas_make_sgl32(struct megasas_instance *instance, struct scsi_cmnd *scp, int sge_count; struct scatterlist *os_sgl; - /* - * Return 0 if there is no data transfer - */ - if (!scp->request_buffer || !scp->request_bufflen) - return 0; + sge_count = scsi_dma_map(scp); + BUG_ON(sge_count < 0); - if (!scp->use_sg) { - mfi_sgl->sge32[0].phys_addr = pci_map_single(instance->pdev, - scp-> - request_buffer, - scp-> - request_bufflen, - scp-> - sc_data_direction); - mfi_sgl->sge32[0].length = scp->request_bufflen; - - return 1; - } - - os_sgl = (struct scatterlist *)scp->request_buffer; - sge_count = pci_map_sg(instance->pdev, os_sgl, scp->use_sg, - scp->sc_data_direction); - - for (i = 0; i < sge_count; i++, os_sgl++) { - mfi_sgl->sge32[i].length = sg_dma_len(os_sgl); - mfi_sgl->sge32[i].phys_addr = sg_dma_address(os_sgl); + if (sge_count) { + scsi_for_each_sg(scp, os_sgl, sge_count, i) { + mfi_sgl->sge32[i].length = sg_dma_len(os_sgl); + mfi_sgl->sge32[i].phys_addr = sg_dma_address(os_sgl); + } } - return sge_count; } @@ -481,35 +462,15 @@ megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp, int sge_count; struct scatterlist *os_sgl; - /* - * Return 0 if there is no data transfer - */ - if (!scp->request_buffer || !scp->request_bufflen) - return 0; - - if (!scp->use_sg) { - mfi_sgl->sge64[0].phys_addr = pci_map_single(instance->pdev, - scp-> - request_buffer, - scp-> - request_bufflen, - scp-> - sc_data_direction); - - mfi_sgl->sge64[0].length = scp->request_bufflen; - - return 1; - } - - os_sgl = (struct scatterlist *)scp->request_buffer; - sge_count = pci_map_sg(instance->pdev, os_sgl, scp->use_sg, - scp->sc_data_direction); + sge_count = scsi_dma_map(scp); + BUG_ON(sge_count < 0); - for (i = 0; i < sge_count; i++, os_sgl++) { - mfi_sgl->sge64[i].length = sg_dma_len(os_sgl); - mfi_sgl->sge64[i].phys_addr = sg_dma_address(os_sgl); + if (sge_count) { + scsi_for_each_sg(scp, os_sgl, sge_count, i) { + mfi_sgl->sge64[i].length = sg_dma_len(os_sgl); + mfi_sgl->sge64[i].phys_addr = sg_dma_address(os_sgl); + } } - return sge_count; } @@ -593,7 +554,7 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp, pthru->cdb_len = scp->cmd_len; pthru->timeout = 0; pthru->flags = flags; - pthru->data_xfer_len = scp->request_bufflen; + pthru->data_xfer_len = scsi_bufflen(scp); memcpy(pthru->cdb, scp->cmnd, scp->cmd_len); @@ -1195,45 +1156,6 @@ megasas_complete_abort(struct megasas_instance *instance, } /** - * megasas_unmap_sgbuf - Unmap SG buffers - * @instance: Adapter soft state - * @cmd: Completed command - */ -static void -megasas_unmap_sgbuf(struct megasas_instance *instance, struct megasas_cmd *cmd) -{ - dma_addr_t buf_h; - u8 opcode; - - if (cmd->scmd->use_sg) { - pci_unmap_sg(instance->pdev, cmd->scmd->request_buffer, - cmd->scmd->use_sg, cmd->scmd->sc_data_direction); - return; - } - - if (!cmd->scmd->request_bufflen) - return; - - opcode = cmd->frame->hdr.cmd; - - if ((opcode == MFI_CMD_LD_READ) || (opcode == MFI_CMD_LD_WRITE)) { - if (IS_DMA64) - buf_h = cmd->frame->io.sgl.sge64[0].phys_addr; - else - buf_h = cmd->frame->io.sgl.sge32[0].phys_addr; - } else { - if (IS_DMA64) - buf_h = cmd->frame->pthru.sgl.sge64[0].phys_addr; - else - buf_h = cmd->frame->pthru.sgl.sge32[0].phys_addr; - } - - pci_unmap_single(instance->pdev, buf_h, cmd->scmd->request_bufflen, - cmd->scmd->sc_data_direction); - return; -} - -/** * megasas_complete_cmd - Completes a command * @instance: Adapter soft state * @cmd: Command to be completed @@ -1281,7 +1203,7 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, atomic_dec(&instance->fw_outstanding); - megasas_unmap_sgbuf(instance, cmd); + scsi_dma_unmap(cmd->scmd); cmd->scmd->scsi_done(cmd->scmd); megasas_return_cmd(instance, cmd); @@ -1329,7 +1251,7 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, atomic_dec(&instance->fw_outstanding); - megasas_unmap_sgbuf(instance, cmd); + scsi_dma_unmap(cmd->scmd); cmd->scmd->scsi_done(cmd->scmd); megasas_return_cmd(instance, cmd); |