lkml.org 
[lkml]   [2007]   [Feb]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patches in this message
/
Subject[PATCH 4/5] scsi: megaraid_sas - preallocate memory for ioctl processing
From
Date
Preallocate memory for ioctl processing. This is to avoid situations 
where ioctl fails for lack of memory (when system under heavy stress).
The memory pool will have 8*4K, 4*8K and 1*64K memory chunks

Signed-off-by: Sumant Patro <sumant.patro@lsi.com>

drivers/scsi/megaraid/megaraid_sas.c | 257 ++++++++++++++++++++++++-
drivers/scsi/megaraid/megaraid_sas.h | 32 ++-
2 files changed, 276 insertions(+), 13 deletions(-)

diff -uprN 2.6.new-p3/drivers/scsi/megaraid/megaraid_sas.c 2.6.new-p4/drivers/scsi/megaraid/megaraid_sas.c
--- 2.6.new-p3/drivers/scsi/megaraid/megaraid_sas.c 2007-02-06 08:50:40.000000000 -0800
+++ 2.6.new-p4/drivers/scsi/megaraid/megaraid_sas.c 2007-02-06 13:12:42.000000000 -0800
@@ -74,6 +74,14 @@ static DEFINE_MUTEX(megasas_async_queue_

static u32 megasas_dbg_lvl;

+/* For IOCTL mem pool */
+int arr[MAX_IOCTL_MEM_POOL] = {MAX_4K_BUFF,MAX_8K_BUFF,MAX_64K_BUFF};
+
+int arr_size[MAX_IOCTL_MEM_POOL] =
+ {MEGASAS_INIT_IOCTL_MEM_SIZE/* 4k */,
+ 2*MEGASAS_INIT_IOCTL_MEM_SIZE/* 8k */,
+ 16*MEGASAS_INIT_IOCTL_MEM_SIZE/* 64k */};
+
/**
* megasas_get_cmd - Get a command from the free pool
* @instance: Adapter soft state
@@ -1805,6 +1813,194 @@ megasas_get_ctrl_info(struct megasas_ins
}

/**
+ * megasas_get_ioctl_mem - Get a buff from the free ioctl memory pool
+ * @instance: Adapter soft state
+ * @i: mem pool index
+ *
+ * Returns a free buff from the pool
+ */
+static inline struct megasas_ioctl_mm *
+megasas_get_ioctl_mem(struct megasas_instance* instance, u8 i)
+{
+ unsigned long flags;
+ struct megasas_ioctl_mm *ioctl_mm = NULL;
+
+ if(i >= MAX_IOCTL_MEM_POOL)
+ goto out;
+
+ spin_lock_irqsave(&instance->ioctl_memory_pool_lock, flags);
+
+ if (!list_empty(&instance->ioctl_memory_pool[i])) {
+ ioctl_mm = list_entry((&instance->ioctl_memory_pool[i])->next,
+ struct megasas_ioctl_mm, list);
+ list_del_init(&ioctl_mm->list);
+ } else
+ printk(KERN_DEBUG "megasas: ioctl memory pool empty!\n");
+
+ spin_unlock_irqrestore(&instance->ioctl_memory_pool_lock, flags);
+out:
+ return ioctl_mm;
+}
+
+/**
+ * megasas_return_ioctl_mm - Return memory to ioctl memory pool
+ * @instance: Adapter soft state
+ * @megasas_ioctl_mm: ioctl mem block
+ * @i: mem_pool_index
+ */
+static inline void
+megasas_return_ioctl_mem(struct megasas_instance *instance,
+ struct megasas_ioctl_mm *ioctl_mm, u8 i)
+{
+ unsigned long flags;
+ if(!ioctl_mm){
+ printk(KERN_DEBUG "megasas: Trying to return "
+ "NULL to mem_pool\n");
+ return;
+ }
+ spin_lock_irqsave(&instance->ioctl_memory_pool_lock, flags);
+ list_add_tail(&ioctl_mm->list, &instance->ioctl_memory_pool[i]);
+ spin_unlock_irqrestore(&instance->ioctl_memory_pool_lock, flags);
+}
+
+/**
+ * megasas_free_ioctl_mem_pools - Free all the memory in the ioctl memory pool
+ * @instance: Adapter soft state
+ */
+static void
+megasas_free_ioctl_mem_pools(struct megasas_instance *instance)
+{
+ struct megasas_ioctl_mm *ioctl_mm;
+ u32 i,j;
+ u32 mem_size;
+ if(instance->mem_pool_empty)
+ return;
+ for (i=0; i < MAX_IOCTL_MEM_POOL; i++) {
+ mem_size = arr_size[i];
+ for (j = 0; j < arr[i]; j++) {
+ ioctl_mm = megasas_get_ioctl_mem(instance, i);
+
+ if (ioctl_mm){
+ if(ioctl_mm->vaddr)
+ pci_free_consistent(instance->pdev,
+ mem_size,
+ ioctl_mm->vaddr,
+ ioctl_mm->buf_handle);
+ kfree(ioctl_mm);
+ }
+ }
+ }
+}
+
+/**
+ * megasas_setup_mem_pools - Setup memory in the ioctl memory pool
+ * @instance: Adapter soft state
+ *
+ * The memory pool will have 8x4K, 4*8K and 1x64K memory
+ * ioctl_memory_pool[0] ----> 4k memory list
+ * ioctl_memory_pool[1] ----> 8K memory list
+ * ioctl_memory_pool[2] ----> 64K memory list
+ */
+
+static int
+megasas_setup_mem_pools(struct megasas_instance *instance)
+{
+ struct megasas_ioctl_mm *ioctl_mm;
+ dma_addr_t buf_handle;
+ void *vaddr;
+ u32 i, j;
+ u32 mem_size;
+ for (i=0; i < MAX_IOCTL_MEM_POOL; i++) {
+ mem_size = arr_size[i];
+
+ for (j = 0; j < arr[i]; j++) {
+
+ ioctl_mm = kmalloc(sizeof(struct megasas_ioctl_mm), GFP_KERNEL);
+ if(!ioctl_mm){
+ printk(KERN_DEBUG "megasas:Failed to alloc "
+ "init memory for ioctl \n");
+ goto failed_to_alloc_mem_ioctl;
+ }
+ vaddr = pci_alloc_consistent(instance->pdev,mem_size,
+ &buf_handle);
+ if (!vaddr) {
+ printk(KERN_DEBUG "megasas:Failed to alloc "
+ "memory for ioctl \n");
+ goto failed_to_alloc_mem_ioctl;
+ } else {
+ ioctl_mm->vaddr = vaddr;
+ ioctl_mm->buf_handle = (u32)buf_handle;
+
+ list_add_tail(&ioctl_mm->list,
+ &instance->ioctl_memory_pool[i]);
+ }
+ }
+ }
+ return 0;
+failed_to_alloc_mem_ioctl:
+ megasas_free_ioctl_mem_pools(instance);
+ return 1;
+}
+
+/**
+ * megasas_get_buff_for_sge - Free all the memory in the ioctl memory pool
+ * @instance: Adapter soft state
+ * @cmd: megasas_cmd
+ */
+
+int
+megasas_get_buff_for_sge(struct megasas_iocpacket *ioc,
+ struct megasas_instance *instance,
+ struct megasas_cmd *cmd)
+{
+ int i,n;
+ u8 mem_type;
+ struct megasas_ioctl_mm* ioctl_mm;
+ if(instance->mem_pool_empty)
+ goto empty;
+ for (i = 0; i < ioc->sge_count; i++) {
+ /*
+ * Check if we have buffer to use from our mem_pool
+ * If we donot have enough to satisfy for all sge's then
+ * free that has already been attached to the ioc
+ */
+ mem_type=0xff;
+ if (ioc->sgl[i].iov_len <= MEGASAS_INIT_IOCTL_MEM_SIZE)
+ mem_type=0;
+ else if ((ioc->sgl[i].iov_len > MEGASAS_INIT_IOCTL_MEM_SIZE) &&
+ (ioc->sgl[i].iov_len <= 2*MEGASAS_INIT_IOCTL_MEM_SIZE))
+ mem_type=1;
+ else if ((ioc->sgl[i].iov_len > 2*MEGASAS_INIT_IOCTL_MEM_SIZE) &&
+ (ioc->sgl[i].iov_len <= 16*MEGASAS_INIT_IOCTL_MEM_SIZE))
+ mem_type=2;
+
+ ioctl_mm = megasas_get_ioctl_mem(instance, mem_type);
+
+ if (ioctl_mm) {
+ cmd->ioctl_mem[i]=ioctl_mm;
+ cmd->ioctl_mem_pool_index[i] = mem_type;
+ } else
+ /* Not enough buffer in mem pool
+ * Free all allocated buffer for this ioc
+ */
+ goto out;
+ }
+ return 0;
+out:
+ for (n = 0; n < i; n++) {
+ if ((struct megasas_ioctl_mm *)cmd->ioctl_mem[i]) {
+ megasas_return_ioctl_mem(instance,
+ (struct megasas_ioctl_mm *)cmd->ioctl_mem[i],
+ cmd->ioctl_mem_pool_index[i]);
+ cmd->ioctl_mem[i]=NULL;
+ cmd->ioctl_mem_pool_index[i] = 0xff;
+ }
+ }
+empty:
+ return 1;
+}
+
+/**
* megasas_complete_cmd_dpc - Returns FW's controller structure
* @instance_addr: Address of adapter soft state
*
@@ -2310,7 +2506,7 @@ static int megasas_io_attach(struct mega
static int __devinit
megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
- int rval;
+ int rval,i;
struct Scsi_Host *host;
struct megasas_instance *instance;

@@ -2396,10 +2592,23 @@ megasas_probe_one(struct pci_dev *pdev,
init_waitqueue_head(&instance->abort_cmd_wait_q);

spin_lock_init(&instance->cmd_pool_lock);
+ spin_lock_init(&instance->ioctl_memory_pool_lock);

sema_init(&instance->aen_mutex, 1);
sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS);

+ /*
+ * for-ioctl: initialize ioctl memory list
+ */
+ for (i=0; i<MAX_IOCTL_MEM_POOL; i++) {
+ INIT_LIST_HEAD(&instance->ioctl_memory_pool[i]);
+ }
+
+ if(megasas_setup_mem_pools(instance))
+ instance->mem_pool_empty=1;
+
+ /* end for-ioctl */
+
/*
* Initialize PCI related and misc parameters
*/
@@ -2472,6 +2681,8 @@ megasas_probe_one(struct pci_dev *pdev,
fail_irq:
fail_init_mfi:
fail_alloc_dma_buf:
+ /* Free ioctl mem pool */
+ megasas_free_ioctl_mem_pools(instance);
if (instance->evt_detail)
pci_free_consistent(pdev, sizeof(struct megasas_evt_detail),
instance->evt_detail,
@@ -2600,6 +2811,9 @@ static void megasas_detach_one(struct pc
free_irq(instance->pdev->irq, instance);

megasas_release_mfi(instance);
+ /* Free IOCTL mem pool */
+ megasas_free_ioctl_mem_pools(instance);
+

pci_free_consistent(pdev, sizeof(struct megasas_evt_detail),
instance->evt_detail, instance->evt_detail_h);
@@ -2699,6 +2913,7 @@ megasas_mgmt_fw_ioctl(struct megasas_ins
void *sense = NULL;
dma_addr_t sense_handle;
u32 *sense_ptr;
+ u8 from_pool = 0;

memset(kbuff_arr, 0, sizeof(kbuff_arr));

@@ -2734,18 +2949,30 @@ megasas_mgmt_fw_ioctl(struct megasas_ins
kern_sge32 = (struct megasas_sge32 *)
((unsigned long)cmd->frame + ioc->sgl_off);

+ /*
+ * Check if we have buffer to use from our ioctl mem_pool
+ * If we donot have then try to allocate new buffer
+ */
+ if(!megasas_get_buff_for_sge(ioc,instance,cmd))
+ from_pool = 1;
+
/*
* For each user buffer, create a mirror buffer and copy in
*/
for (i = 0; i < ioc->sge_count; i++) {
- kbuff_arr[i] = pci_alloc_consistent(instance->pdev,
+ if (from_pool) {
+ kbuff_arr[i] = cmd->ioctl_mem[i]->vaddr;
+ buf_handle = cmd->ioctl_mem[i]->buf_handle;
+ } else {
+ kbuff_arr[i] = pci_alloc_consistent(instance->pdev,
ioc->sgl[i].iov_len,
&buf_handle);
- if (!kbuff_arr[i]) {
- printk(KERN_DEBUG "megasas: Failed to alloc "
- "kernel SGL buffer for IOCTL \n");
- error = -ENOMEM;
- goto out;
+ if (!kbuff_arr[i]) {
+ printk(KERN_DEBUG "megasas: Failed to alloc "
+ "kernel SGL buffer for IOCTL \n");
+ error = -ENOMEM;
+ goto out;
+ }
}

/*
@@ -2832,9 +3059,19 @@ megasas_mgmt_fw_ioctl(struct megasas_ins
}

for (i = 0; i < ioc->sge_count && kbuff_arr[i]; i++) {
- pci_free_consistent(instance->pdev,
- kern_sge32[i].length,
- kbuff_arr[i], kern_sge32[i].phys_addr);
+ if (from_pool) {
+ /* Return to the mem pool */
+ if ((struct megasas_ioctl_mm *)cmd->ioctl_mem[i]) {
+ megasas_return_ioctl_mem(instance,
+ (struct megasas_ioctl_mm *)cmd->ioctl_mem[i],
+ cmd->ioctl_mem_pool_index[i]);
+ cmd->ioctl_mem_pool_index[i]=0xff;
+ cmd->ioctl_mem[i]=NULL;
+ }
+ } else
+ pci_free_consistent(instance->pdev,
+ kern_sge32[i].length,
+ kbuff_arr[i], kern_sge32[i].phys_addr);
}

megasas_return_cmd(instance, cmd);
diff -uprN 2.6.new-p3/drivers/scsi/megaraid/megaraid_sas.h 2.6.new-p4/drivers/scsi/megaraid/megaraid_sas.h
--- 2.6.new-p3/drivers/scsi/megaraid/megaraid_sas.h 2007-02-06 08:51:23.000000000 -0800
+++ 2.6.new-p4/drivers/scsi/megaraid/megaraid_sas.h 2007-02-06 10:14:17.000000000 -0800
@@ -539,6 +539,17 @@ struct megasas_ctrl_info {

#define MEGASAS_DBG_LVL 1

+/*
+ * For ioctl memory manager
+ */
+
+#define MAX_IOCTL_MEM_POOL 3
+#define MEGASAS_INIT_IOCTL_MEM_SIZE 4096
+#define MAX_IOCTL_MEM_BLOCK 16
+#define MAX_4K_BUFF 8
+#define MAX_8K_BUFF 4
+#define MAX_64K_BUFF 1
+
/*
* When SCSI mid-layer calls driver's reset routine, driver waits for
* MEGASAS_RESET_WAIT_TIME seconds for all outstanding IO to complete. Note
@@ -1059,6 +1070,12 @@ struct megasas_evt_detail {
u32 (*read_fw_status_reg)(struct megasas_register_set __iomem *);
};

+struct megasas_ioctl_mm {
+ void *vaddr;
+ dma_addr_t buf_handle;
+ struct list_head list;
+};
+
struct megasas_instance {

u32 *producer;
@@ -1085,6 +1102,12 @@ struct megasas_instance {
struct dma_pool *frame_dma_pool;
struct dma_pool *sense_dma_pool;

+ /* ioctl memory */
+ struct list_head ioctl_memory_pool[MAX_IOCTL_MEM_POOL];
+ spinlock_t ioctl_memory_pool_lock;
+ u8 mem_pool_empty;
+ /* end :ioctl memory */
+
struct megasas_evt_detail *evt_detail;
dma_addr_t evt_detail_h;
struct megasas_cmd *aen_cmd;
@@ -1116,6 +1139,9 @@ struct megasas_instance {
((scp->device->channel % 2) * MEGASAS_MAX_DEV_PER_CHANNEL) + \
scp->device->id

+#define MAX_MGMT_ADAPTERS 1024
+#define MAX_IOCTL_SGE 16
+
struct megasas_cmd {

union megasas_frame *frame;
@@ -1132,10 +1158,10 @@ struct megasas_cmd {
struct scsi_cmnd *scmd;
struct megasas_instance *instance;
u32 frame_count;
-};

-#define MAX_MGMT_ADAPTERS 1024
-#define MAX_IOCTL_SGE 16
+ u8 ioctl_mem_pool_index[MAX_IOCTL_SGE]; /*0xff for not in use*/
+ struct megasas_ioctl_mm *ioctl_mem[MAX_IOCTL_SGE];
+};

struct megasas_iocpacket {

diff -uprN 2.6.new-p3/drivers/scsi/megaraid/megaraid_sas.c 2.6.new-p4/drivers/scsi/megaraid/megaraid_sas.c
--- 2.6.new-p3/drivers/scsi/megaraid/megaraid_sas.c 2007-02-06 08:50:40.000000000 -0800
+++ 2.6.new-p4/drivers/scsi/megaraid/megaraid_sas.c 2007-02-06 13:12:42.000000000 -0800
@@ -74,6 +74,14 @@ static DEFINE_MUTEX(megasas_async_queue_

static u32 megasas_dbg_lvl;

+/* For IOCTL mem pool */
+int arr[MAX_IOCTL_MEM_POOL] = {MAX_4K_BUFF,MAX_8K_BUFF,MAX_64K_BUFF};
+
+int arr_size[MAX_IOCTL_MEM_POOL] =
+ {MEGASAS_INIT_IOCTL_MEM_SIZE/* 4k */,
+ 2*MEGASAS_INIT_IOCTL_MEM_SIZE/* 8k */,
+ 16*MEGASAS_INIT_IOCTL_MEM_SIZE/* 64k */};
+
/**
* megasas_get_cmd - Get a command from the free pool
* @instance: Adapter soft state
@@ -1805,6 +1813,194 @@ megasas_get_ctrl_info(struct megasas_ins
}

/**
+ * megasas_get_ioctl_mem - Get a buff from the free ioctl memory pool
+ * @instance: Adapter soft state
+ * @i: mem pool index
+ *
+ * Returns a free buff from the pool
+ */
+static inline struct megasas_ioctl_mm *
+megasas_get_ioctl_mem(struct megasas_instance* instance, u8 i)
+{
+ unsigned long flags;
+ struct megasas_ioctl_mm *ioctl_mm = NULL;
+
+ if(i >= MAX_IOCTL_MEM_POOL)
+ goto out;
+
+ spin_lock_irqsave(&instance->ioctl_memory_pool_lock, flags);
+
+ if (!list_empty(&instance->ioctl_memory_pool[i])) {
+ ioctl_mm = list_entry((&instance->ioctl_memory_pool[i])->next,
+ struct megasas_ioctl_mm, list);
+ list_del_init(&ioctl_mm->list);
+ } else
+ printk(KERN_DEBUG "megasas: ioctl memory pool empty!\n");
+
+ spin_unlock_irqrestore(&instance->ioctl_memory_pool_lock, flags);
+out:
+ return ioctl_mm;
+}
+
+/**
+ * megasas_return_ioctl_mm - Return memory to ioctl memory pool
+ * @instance: Adapter soft state
+ * @megasas_ioctl_mm: ioctl mem block
+ * @i: mem_pool_index
+ */
+static inline void
+megasas_return_ioctl_mem(struct megasas_instance *instance,
+ struct megasas_ioctl_mm *ioctl_mm, u8 i)
+{
+ unsigned long flags;
+ if(!ioctl_mm){
+ printk(KERN_DEBUG "megasas: Trying to return "
+ "NULL to mem_pool\n");
+ return;
+ }
+ spin_lock_irqsave(&instance->ioctl_memory_pool_lock, flags);
+ list_add_tail(&ioctl_mm->list, &instance->ioctl_memory_pool[i]);
+ spin_unlock_irqrestore(&instance->ioctl_memory_pool_lock, flags);
+}
+
+/**
+ * megasas_free_ioctl_mem_pools - Free all the memory in the ioctl memory pool
+ * @instance: Adapter soft state
+ */
+static void
+megasas_free_ioctl_mem_pools(struct megasas_instance *instance)
+{
+ struct megasas_ioctl_mm *ioctl_mm;
+ u32 i,j;
+ u32 mem_size;
+ if(instance->mem_pool_empty)
+ return;
+ for (i=0; i < MAX_IOCTL_MEM_POOL; i++) {
+ mem_size = arr_size[i];
+ for (j = 0; j < arr[i]; j++) {
+ ioctl_mm = megasas_get_ioctl_mem(instance, i);
+
+ if (ioctl_mm){
+ if(ioctl_mm->vaddr)
+ pci_free_consistent(instance->pdev,
+ mem_size,
+ ioctl_mm->vaddr,
+ ioctl_mm->buf_handle);
+ kfree(ioctl_mm);
+ }
+ }
+ }
+}
+
+/**
+ * megasas_setup_mem_pools - Setup memory in the ioctl memory pool
+ * @instance: Adapter soft state
+ *
+ * The memory pool will have 8x4K, 4*8K and 1x64K memory
+ * ioctl_memory_pool[0] ----> 4k memory list
+ * ioctl_memory_pool[1] ----> 8K memory list
+ * ioctl_memory_pool[2] ----> 64K memory list
+ */
+
+static int
+megasas_setup_mem_pools(struct megasas_instance *instance)
+{
+ struct megasas_ioctl_mm *ioctl_mm;
+ dma_addr_t buf_handle;
+ void *vaddr;
+ u32 i, j;
+ u32 mem_size;
+ for (i=0; i < MAX_IOCTL_MEM_POOL; i++) {
+ mem_size = arr_size[i];
+
+ for (j = 0; j < arr[i]; j++) {
+
+ ioctl_mm = kmalloc(sizeof(struct megasas_ioctl_mm), GFP_KERNEL);
+ if(!ioctl_mm){
+ printk(KERN_DEBUG "megasas:Failed to alloc "
+ "init memory for ioctl \n");
+ goto failed_to_alloc_mem_ioctl;
+ }
+ vaddr = pci_alloc_consistent(instance->pdev,mem_size,
+ &buf_handle);
+ if (!vaddr) {
+ printk(KERN_DEBUG "megasas:Failed to alloc "
+ "memory for ioctl \n");
+ goto failed_to_alloc_mem_ioctl;
+ } else {
+ ioctl_mm->vaddr = vaddr;
+ ioctl_mm->buf_handle = (u32)buf_handle;
+
+ list_add_tail(&ioctl_mm->list,
+ &instance->ioctl_memory_pool[i]);
+ }
+ }
+ }
+ return 0;
+failed_to_alloc_mem_ioctl:
+ megasas_free_ioctl_mem_pools(instance);
+ return 1;
+}
+
+/**
+ * megasas_get_buff_for_sge - Free all the memory in the ioctl memory pool
+ * @instance: Adapter soft state
+ * @cmd: megasas_cmd
+ */
+
+int
+megasas_get_buff_for_sge(struct megasas_iocpacket *ioc,
+ struct megasas_instance *instance,
+ struct megasas_cmd *cmd)
+{
+ int i,n;
+ u8 mem_type;
+ struct megasas_ioctl_mm* ioctl_mm;
+ if(instance->mem_pool_empty)
+ goto empty;
+ for (i = 0; i < ioc->sge_count; i++) {
+ /*
+ * Check if we have buffer to use from our mem_pool
+ * If we donot have enough to satisfy for all sge's then
+ * free that has already been attached to the ioc
+ */
+ mem_type=0xff;
+ if (ioc->sgl[i].iov_len <= MEGASAS_INIT_IOCTL_MEM_SIZE)
+ mem_type=0;
+ else if ((ioc->sgl[i].iov_len > MEGASAS_INIT_IOCTL_MEM_SIZE) &&
+ (ioc->sgl[i].iov_len <= 2*MEGASAS_INIT_IOCTL_MEM_SIZE))
+ mem_type=1;
+ else if ((ioc->sgl[i].iov_len > 2*MEGASAS_INIT_IOCTL_MEM_SIZE) &&
+ (ioc->sgl[i].iov_len <= 16*MEGASAS_INIT_IOCTL_MEM_SIZE))
+ mem_type=2;
+
+ ioctl_mm = megasas_get_ioctl_mem(instance, mem_type);
+
+ if (ioctl_mm) {
+ cmd->ioctl_mem[i]=ioctl_mm;
+ cmd->ioctl_mem_pool_index[i] = mem_type;
+ } else
+ /* Not enough buffer in mem pool
+ * Free all allocated buffer for this ioc
+ */
+ goto out;
+ }
+ return 0;
+out:
+ for (n = 0; n < i; n++) {
+ if ((struct megasas_ioctl_mm *)cmd->ioctl_mem[i]) {
+ megasas_return_ioctl_mem(instance,
+ (struct megasas_ioctl_mm *)cmd->ioctl_mem[i],
+ cmd->ioctl_mem_pool_index[i]);
+ cmd->ioctl_mem[i]=NULL;
+ cmd->ioctl_mem_pool_index[i] = 0xff;
+ }
+ }
+empty:
+ return 1;
+}
+
+/**
* megasas_complete_cmd_dpc - Returns FW's controller structure
* @instance_addr: Address of adapter soft state
*
@@ -2310,7 +2506,7 @@ static int megasas_io_attach(struct mega
static int __devinit
megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
- int rval;
+ int rval,i;
struct Scsi_Host *host;
struct megasas_instance *instance;

@@ -2396,10 +2592,23 @@ megasas_probe_one(struct pci_dev *pdev,
init_waitqueue_head(&instance->abort_cmd_wait_q);

spin_lock_init(&instance->cmd_pool_lock);
+ spin_lock_init(&instance->ioctl_memory_pool_lock);

sema_init(&instance->aen_mutex, 1);
sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS);

+ /*
+ * for-ioctl: initialize ioctl memory list
+ */
+ for (i=0; i<MAX_IOCTL_MEM_POOL; i++) {
+ INIT_LIST_HEAD(&instance->ioctl_memory_pool[i]);
+ }
+
+ if(megasas_setup_mem_pools(instance))
+ instance->mem_pool_empty=1;
+
+ /* end for-ioctl */
+
/*
* Initialize PCI related and misc parameters
*/
@@ -2472,6 +2681,8 @@ megasas_probe_one(struct pci_dev *pdev,
fail_irq:
fail_init_mfi:
fail_alloc_dma_buf:
+ /* Free ioctl mem pool */
+ megasas_free_ioctl_mem_pools(instance);
if (instance->evt_detail)
pci_free_consistent(pdev, sizeof(struct megasas_evt_detail),
instance->evt_detail,
@@ -2600,6 +2811,9 @@ static void megasas_detach_one(struct pc
free_irq(instance->pdev->irq, instance);

megasas_release_mfi(instance);
+ /* Free IOCTL mem pool */
+ megasas_free_ioctl_mem_pools(instance);
+

pci_free_consistent(pdev, sizeof(struct megasas_evt_detail),
instance->evt_detail, instance->evt_detail_h);
@@ -2699,6 +2913,7 @@ megasas_mgmt_fw_ioctl(struct megasas_ins
void *sense = NULL;
dma_addr_t sense_handle;
u32 *sense_ptr;
+ u8 from_pool = 0;

memset(kbuff_arr, 0, sizeof(kbuff_arr));

@@ -2734,18 +2949,30 @@ megasas_mgmt_fw_ioctl(struct megasas_ins
kern_sge32 = (struct megasas_sge32 *)
((unsigned long)cmd->frame + ioc->sgl_off);

+ /*
+ * Check if we have buffer to use from our ioctl mem_pool
+ * If we donot have then try to allocate new buffer
+ */
+ if(!megasas_get_buff_for_sge(ioc,instance,cmd))
+ from_pool = 1;
+
/*
* For each user buffer, create a mirror buffer and copy in
*/
for (i = 0; i < ioc->sge_count; i++) {
- kbuff_arr[i] = pci_alloc_consistent(instance->pdev,
+ if (from_pool) {
+ kbuff_arr[i] = cmd->ioctl_mem[i]->vaddr;
+ buf_handle = cmd->ioctl_mem[i]->buf_handle;
+ } else {
+ kbuff_arr[i] = pci_alloc_consistent(instance->pdev,
ioc->sgl[i].iov_len,
&buf_handle);
- if (!kbuff_arr[i]) {
- printk(KERN_DEBUG "megasas: Failed to alloc "
- "kernel SGL buffer for IOCTL \n");
- error = -ENOMEM;
- goto out;
+ if (!kbuff_arr[i]) {
+ printk(KERN_DEBUG "megasas: Failed to alloc "
+ "kernel SGL buffer for IOCTL \n");
+ error = -ENOMEM;
+ goto out;
+ }
}

/*
@@ -2832,9 +3059,19 @@ megasas_mgmt_fw_ioctl(struct megasas_ins
}

for (i = 0; i < ioc->sge_count && kbuff_arr[i]; i++) {
- pci_free_consistent(instance->pdev,
- kern_sge32[i].length,
- kbuff_arr[i], kern_sge32[i].phys_addr);
+ if (from_pool) {
+ /* Return to the mem pool */
+ if ((struct megasas_ioctl_mm *)cmd->ioctl_mem[i]) {
+ megasas_return_ioctl_mem(instance,
+ (struct megasas_ioctl_mm *)cmd->ioctl_mem[i],
+ cmd->ioctl_mem_pool_index[i]);
+ cmd->ioctl_mem_pool_index[i]=0xff;
+ cmd->ioctl_mem[i]=NULL;
+ }
+ } else
+ pci_free_consistent(instance->pdev,
+ kern_sge32[i].length,
+ kbuff_arr[i], kern_sge32[i].phys_addr);
}

megasas_return_cmd(instance, cmd);
diff -uprN 2.6.new-p3/drivers/scsi/megaraid/megaraid_sas.h 2.6.new-p4/drivers/scsi/megaraid/megaraid_sas.h
--- 2.6.new-p3/drivers/scsi/megaraid/megaraid_sas.h 2007-02-06 08:51:23.000000000 -0800
+++ 2.6.new-p4/drivers/scsi/megaraid/megaraid_sas.h 2007-02-06 10:14:17.000000000 -0800
@@ -539,6 +539,17 @@ struct megasas_ctrl_info {

#define MEGASAS_DBG_LVL 1

+/*
+ * For ioctl memory manager
+ */
+
+#define MAX_IOCTL_MEM_POOL 3
+#define MEGASAS_INIT_IOCTL_MEM_SIZE 4096
+#define MAX_IOCTL_MEM_BLOCK 16
+#define MAX_4K_BUFF 8
+#define MAX_8K_BUFF 4
+#define MAX_64K_BUFF 1
+
/*
* When SCSI mid-layer calls driver's reset routine, driver waits for
* MEGASAS_RESET_WAIT_TIME seconds for all outstanding IO to complete. Note
@@ -1059,6 +1070,12 @@ struct megasas_evt_detail {
u32 (*read_fw_status_reg)(struct megasas_register_set __iomem *);
};

+struct megasas_ioctl_mm {
+ void *vaddr;
+ dma_addr_t buf_handle;
+ struct list_head list;
+};
+
struct megasas_instance {

u32 *producer;
@@ -1085,6 +1102,12 @@ struct megasas_instance {
struct dma_pool *frame_dma_pool;
struct dma_pool *sense_dma_pool;

+ /* ioctl memory */
+ struct list_head ioctl_memory_pool[MAX_IOCTL_MEM_POOL];
+ spinlock_t ioctl_memory_pool_lock;
+ u8 mem_pool_empty;
+ /* end :ioctl memory */
+
struct megasas_evt_detail *evt_detail;
dma_addr_t evt_detail_h;
struct megasas_cmd *aen_cmd;
@@ -1116,6 +1139,9 @@ struct megasas_instance {
((scp->device->channel % 2) * MEGASAS_MAX_DEV_PER_CHANNEL) + \
scp->device->id

+#define MAX_MGMT_ADAPTERS 1024
+#define MAX_IOCTL_SGE 16
+
struct megasas_cmd {

union megasas_frame *frame;
@@ -1132,10 +1158,10 @@ struct megasas_cmd {
struct scsi_cmnd *scmd;
struct megasas_instance *instance;
u32 frame_count;
-};

-#define MAX_MGMT_ADAPTERS 1024
-#define MAX_IOCTL_SGE 16
+ u8 ioctl_mem_pool_index[MAX_IOCTL_SGE]; /*0xff for not in use*/
+ struct megasas_ioctl_mm *ioctl_mem[MAX_IOCTL_SGE];
+};

struct megasas_iocpacket {
\
 
 \ /
  Last update: 2007-02-07 04:33    [W:0.096 / U:0.596 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site