Skip to content

Commit

Permalink
[SCSI] megaraid_sas: add the IEEE SGE support to SAS2 controller
Browse files Browse the repository at this point in the history
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: James Bottomley <James.Bottomley@suse.de>
  • Loading branch information
Yang, Bo authored and James Bottomley committed Oct 29, 2009
1 parent 7bebf5c commit f4c9a13
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 7 deletions.
80 changes: 73 additions & 7 deletions drivers/scsi/megaraid/megaraid_sas.c
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,35 @@ megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp,
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
* @frame_type : type of frame- io or pthru frame
Expand All @@ -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)
*/

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 sge_bytes;
Expand All @@ -714,19 +744,27 @@ static u32 megasas_get_frame_count(u8 sge_count, u8 frame_type)
sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) :
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
* 3 SGEs for 32-bit SGLs for ldio &
* 1 SGEs for 64-bit SGLs and
* 2 SGEs for 32-bit SGLs for 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;
else
num_cnt = sge_count - 2;
} else {
if (IS_DMA64)
if (instance->flag_ieee == 1) {
num_cnt = sge_count - 1;
} else if (IS_DMA64)
num_cnt = sge_count - 2;
else
num_cnt = sge_count - 3;
Expand Down Expand Up @@ -775,6 +813,10 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp,
else if (scp->sc_data_direction == PCI_DMA_NONE)
flags = MFI_FRAME_DIR_NONE;

if (instance->flag_ieee == 1) {
flags |= MFI_FRAME_IEEE;
}

/*
* Prepare the DCDB frame
*/
Expand Down Expand Up @@ -804,7 +846,11 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp,
/*
* 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->sge_count = megasas_make_sgl64(instance, scp,
&pthru->sgl);
Expand All @@ -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
* 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);

return cmd->frame_count;
Expand Down Expand Up @@ -854,6 +900,10 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp,
else if (scp->sc_data_direction == PCI_DMA_FROMDEVICE)
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
*/
Expand Down Expand Up @@ -924,7 +974,11 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp,
/*
* 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->sge_count = megasas_make_sgl64(instance, scp, &ldio->sgl);
} else
Expand All @@ -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
* 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;
}
Expand Down Expand Up @@ -1929,6 +1984,10 @@ static int megasas_create_frame_pool(struct megasas_instance *instance)
sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) :
sizeof(struct megasas_sge32);

if (instance->flag_ieee) {
sge_sz = sizeof(struct megasas_sge_skinny);
}

/*
* Calculated the number of 64byte frames required for SGL
*/
Expand Down Expand Up @@ -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].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
* application wants us to register for AEN, we have to abort this
Expand Down Expand Up @@ -2895,6 +2959,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
*instance->producer = 0;
*instance->consumer = 0;
megasas_poll_wait_aen = 0;
instance->flag_ieee = 0;

instance->evt_detail = pci_alloc_consistent(pdev,
sizeof(struct
Expand Down Expand Up @@ -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) ||
(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
instance->flag_ieee = 1;
sema_init(&instance->ioctl_sem, MEGASAS_SKINNY_INT_CMDS);
} else
sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS);
Expand Down
9 changes: 9 additions & 0 deletions drivers/scsi/megaraid/megaraid_sas.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
#define MFI_FRAME_DIR_WRITE 0x0008
#define MFI_FRAME_DIR_READ 0x0010
#define MFI_FRAME_DIR_BOTH 0x0018
#define MFI_FRAME_IEEE 0x0020

/*
* Definition for cmd_status
Expand Down Expand Up @@ -732,10 +733,17 @@ struct megasas_sge64 {

} __attribute__ ((packed));

struct megasas_sge_skinny {
u64 phys_addr;
u32 length;
u32 flag;
} __packed;

union megasas_sgl {

struct megasas_sge32 sge32[1];
struct megasas_sge64 sge64[1];
struct megasas_sge_skinny sge_skinny[1];

} __attribute__ ((packed));

Expand Down Expand Up @@ -1210,6 +1218,7 @@ struct megasas_instance {

u8 flag;
u8 unload;
u8 flag_ieee;
unsigned long last_time;

struct timer_list io_completion_timer;
Expand Down

0 comments on commit f4c9a13

Please sign in to comment.