Commit f4c9a131 authored by Yang, Bo's avatar Yang, Bo Committed by James Bottomley

[SCSI] megaraid_sas: add the IEEE SGE support to SAS2 controller

To increase the performance, megaraid sas driver added the IEEE SGE
support to support SAS2 controller.

Signed-off-by Bo Yang<bo.yang@lsi.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent 7bebf5c7
...@@ -696,6 +696,35 @@ megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp, ...@@ -696,6 +696,35 @@ megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp,
return sge_count; return sge_count;
} }
/**
* megasas_make_sgl_skinny - Prepares IEEE SGL
* @instance: Adapter soft state
* @scp: SCSI command from the mid-layer
* @mfi_sgl: SGL to be filled in
*
* If successful, this function returns the number of SG elements. Otherwise,
* it returnes -1.
*/
static int
megasas_make_sgl_skinny(struct megasas_instance *instance,
struct scsi_cmnd *scp, union megasas_sgl *mfi_sgl)
{
int i;
int sge_count;
struct scatterlist *os_sgl;
sge_count = scsi_dma_map(scp);
if (sge_count) {
scsi_for_each_sg(scp, os_sgl, sge_count, i) {
mfi_sgl->sge_skinny[i].length = sg_dma_len(os_sgl);
mfi_sgl->sge_skinny[i].phys_addr =
sg_dma_address(os_sgl);
}
}
return sge_count;
}
/** /**
* megasas_get_frame_count - Computes the number of frames * megasas_get_frame_count - Computes the number of frames
* @frame_type : type of frame- io or pthru frame * @frame_type : type of frame- io or pthru frame
...@@ -704,7 +733,8 @@ megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp, ...@@ -704,7 +733,8 @@ megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp,
* Returns the number of frames required for numnber of sge's (sge_count) * Returns the number of frames required for numnber of sge's (sge_count)
*/ */
static u32 megasas_get_frame_count(u8 sge_count, u8 frame_type) static u32 megasas_get_frame_count(struct megasas_instance *instance,
u8 sge_count, u8 frame_type)
{ {
int num_cnt; int num_cnt;
int sge_bytes; int sge_bytes;
...@@ -714,6 +744,10 @@ static u32 megasas_get_frame_count(u8 sge_count, u8 frame_type) ...@@ -714,6 +744,10 @@ static u32 megasas_get_frame_count(u8 sge_count, u8 frame_type)
sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) : sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) :
sizeof(struct megasas_sge32); sizeof(struct megasas_sge32);
if (instance->flag_ieee) {
sge_sz = sizeof(struct megasas_sge_skinny);
}
/* /*
* Main frame can contain 2 SGEs for 64-bit SGLs and * Main frame can contain 2 SGEs for 64-bit SGLs and
* 3 SGEs for 32-bit SGLs for ldio & * 3 SGEs for 32-bit SGLs for ldio &
...@@ -721,12 +755,16 @@ static u32 megasas_get_frame_count(u8 sge_count, u8 frame_type) ...@@ -721,12 +755,16 @@ static u32 megasas_get_frame_count(u8 sge_count, u8 frame_type)
* 2 SGEs for 32-bit SGLs for pthru frame * 2 SGEs for 32-bit SGLs for pthru frame
*/ */
if (unlikely(frame_type == PTHRU_FRAME)) { if (unlikely(frame_type == PTHRU_FRAME)) {
if (IS_DMA64) if (instance->flag_ieee == 1) {
num_cnt = sge_count - 1;
} else if (IS_DMA64)
num_cnt = sge_count - 1; num_cnt = sge_count - 1;
else else
num_cnt = sge_count - 2; num_cnt = sge_count - 2;
} else { } else {
if (IS_DMA64) if (instance->flag_ieee == 1) {
num_cnt = sge_count - 1;
} else if (IS_DMA64)
num_cnt = sge_count - 2; num_cnt = sge_count - 2;
else else
num_cnt = sge_count - 3; num_cnt = sge_count - 3;
...@@ -775,6 +813,10 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp, ...@@ -775,6 +813,10 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp,
else if (scp->sc_data_direction == PCI_DMA_NONE) else if (scp->sc_data_direction == PCI_DMA_NONE)
flags = MFI_FRAME_DIR_NONE; flags = MFI_FRAME_DIR_NONE;
if (instance->flag_ieee == 1) {
flags |= MFI_FRAME_IEEE;
}
/* /*
* Prepare the DCDB frame * Prepare the DCDB frame
*/ */
...@@ -804,7 +846,11 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp, ...@@ -804,7 +846,11 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp,
/* /*
* Construct SGL * Construct SGL
*/ */
if (IS_DMA64) { if (instance->flag_ieee == 1) {
pthru->flags |= MFI_FRAME_SGL64;
pthru->sge_count = megasas_make_sgl_skinny(instance, scp,
&pthru->sgl);
} else if (IS_DMA64) {
pthru->flags |= MFI_FRAME_SGL64; pthru->flags |= MFI_FRAME_SGL64;
pthru->sge_count = megasas_make_sgl64(instance, scp, pthru->sge_count = megasas_make_sgl64(instance, scp,
&pthru->sgl); &pthru->sgl);
...@@ -823,7 +869,7 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp, ...@@ -823,7 +869,7 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp,
* Compute the total number of frames this command consumes. FW uses * Compute the total number of frames this command consumes. FW uses
* this number to pull sufficient number of frames from host memory. * this number to pull sufficient number of frames from host memory.
*/ */
cmd->frame_count = megasas_get_frame_count(pthru->sge_count, cmd->frame_count = megasas_get_frame_count(instance, pthru->sge_count,
PTHRU_FRAME); PTHRU_FRAME);
return cmd->frame_count; return cmd->frame_count;
...@@ -854,6 +900,10 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp, ...@@ -854,6 +900,10 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp,
else if (scp->sc_data_direction == PCI_DMA_FROMDEVICE) else if (scp->sc_data_direction == PCI_DMA_FROMDEVICE)
flags = MFI_FRAME_DIR_READ; flags = MFI_FRAME_DIR_READ;
if (instance->flag_ieee == 1) {
flags |= MFI_FRAME_IEEE;
}
/* /*
* Prepare the Logical IO frame: 2nd bit is zero for all read cmds * Prepare the Logical IO frame: 2nd bit is zero for all read cmds
*/ */
...@@ -924,7 +974,11 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp, ...@@ -924,7 +974,11 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp,
/* /*
* Construct SGL * Construct SGL
*/ */
if (IS_DMA64) { if (instance->flag_ieee) {
ldio->flags |= MFI_FRAME_SGL64;
ldio->sge_count = megasas_make_sgl_skinny(instance, scp,
&ldio->sgl);
} else if (IS_DMA64) {
ldio->flags |= MFI_FRAME_SGL64; ldio->flags |= MFI_FRAME_SGL64;
ldio->sge_count = megasas_make_sgl64(instance, scp, &ldio->sgl); ldio->sge_count = megasas_make_sgl64(instance, scp, &ldio->sgl);
} else } else
...@@ -941,7 +995,8 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp, ...@@ -941,7 +995,8 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp,
* Compute the total number of frames this command consumes. FW uses * Compute the total number of frames this command consumes. FW uses
* this number to pull sufficient number of frames from host memory. * this number to pull sufficient number of frames from host memory.
*/ */
cmd->frame_count = megasas_get_frame_count(ldio->sge_count, IO_FRAME); cmd->frame_count = megasas_get_frame_count(instance,
ldio->sge_count, IO_FRAME);
return cmd->frame_count; return cmd->frame_count;
} }
...@@ -1929,6 +1984,10 @@ static int megasas_create_frame_pool(struct megasas_instance *instance) ...@@ -1929,6 +1984,10 @@ static int megasas_create_frame_pool(struct megasas_instance *instance)
sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) : sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) :
sizeof(struct megasas_sge32); sizeof(struct megasas_sge32);
if (instance->flag_ieee) {
sge_sz = sizeof(struct megasas_sge_skinny);
}
/* /*
* Calculated the number of 64byte frames required for SGL * Calculated the number of 64byte frames required for SGL
*/ */
...@@ -2725,6 +2784,11 @@ megasas_register_aen(struct megasas_instance *instance, u32 seq_num, ...@@ -2725,6 +2784,11 @@ megasas_register_aen(struct megasas_instance *instance, u32 seq_num,
dcmd->sgl.sge32[0].phys_addr = (u32) instance->evt_detail_h; dcmd->sgl.sge32[0].phys_addr = (u32) instance->evt_detail_h;
dcmd->sgl.sge32[0].length = sizeof(struct megasas_evt_detail); dcmd->sgl.sge32[0].length = sizeof(struct megasas_evt_detail);
if (instance->aen_cmd != NULL) {
megasas_return_cmd(instance, cmd);
return 0;
}
/* /*
* Store reference to the cmd used to register for AEN. When an * Store reference to the cmd used to register for AEN. When an
* application wants us to register for AEN, we have to abort this * application wants us to register for AEN, we have to abort this
...@@ -2895,6 +2959,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -2895,6 +2959,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
*instance->producer = 0; *instance->producer = 0;
*instance->consumer = 0; *instance->consumer = 0;
megasas_poll_wait_aen = 0; megasas_poll_wait_aen = 0;
instance->flag_ieee = 0;
instance->evt_detail = pci_alloc_consistent(pdev, instance->evt_detail = pci_alloc_consistent(pdev,
sizeof(struct sizeof(struct
...@@ -2933,6 +2998,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -2933,6 +2998,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) || if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
instance->flag_ieee = 1;
sema_init(&instance->ioctl_sem, MEGASAS_SKINNY_INT_CMDS); sema_init(&instance->ioctl_sem, MEGASAS_SKINNY_INT_CMDS);
} else } else
sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS); sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS);
......
...@@ -96,6 +96,7 @@ ...@@ -96,6 +96,7 @@
#define MFI_FRAME_DIR_WRITE 0x0008 #define MFI_FRAME_DIR_WRITE 0x0008
#define MFI_FRAME_DIR_READ 0x0010 #define MFI_FRAME_DIR_READ 0x0010
#define MFI_FRAME_DIR_BOTH 0x0018 #define MFI_FRAME_DIR_BOTH 0x0018
#define MFI_FRAME_IEEE 0x0020
/* /*
* Definition for cmd_status * Definition for cmd_status
...@@ -732,10 +733,17 @@ struct megasas_sge64 { ...@@ -732,10 +733,17 @@ struct megasas_sge64 {
} __attribute__ ((packed)); } __attribute__ ((packed));
struct megasas_sge_skinny {
u64 phys_addr;
u32 length;
u32 flag;
} __packed;
union megasas_sgl { union megasas_sgl {
struct megasas_sge32 sge32[1]; struct megasas_sge32 sge32[1];
struct megasas_sge64 sge64[1]; struct megasas_sge64 sge64[1];
struct megasas_sge_skinny sge_skinny[1];
} __attribute__ ((packed)); } __attribute__ ((packed));
...@@ -1210,6 +1218,7 @@ struct megasas_instance { ...@@ -1210,6 +1218,7 @@ struct megasas_instance {
u8 flag; u8 flag;
u8 unload; u8 unload;
u8 flag_ieee;
unsigned long last_time; unsigned long last_time;
struct timer_list io_completion_timer; struct timer_list io_completion_timer;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment