summaryrefslogtreecommitdiffstats
path: root/sys/dev/isci/isci_controller.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/isci/isci_controller.c')
-rw-r--r--sys/dev/isci/isci_controller.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/sys/dev/isci/isci_controller.c b/sys/dev/isci/isci_controller.c
index 49785cb..1255201 100644
--- a/sys/dev/isci/isci_controller.c
+++ b/sys/dev/isci/isci_controller.c
@@ -145,6 +145,14 @@ void scif_cb_controller_stop_complete(SCI_CONTROLLER_HANDLE_T controller,
isci_controller->is_started = FALSE;
}
+static void
+isci_single_map(void *arg, bus_dma_segment_t *seg, int nseg, int error)
+{
+ SCI_PHYSICAL_ADDRESS *phys_addr = arg;
+
+ *phys_addr = seg[0].ds_addr;
+}
+
/**
* @brief This method will be invoked to allocate memory dynamically.
*
@@ -159,7 +167,29 @@ void scif_cb_controller_stop_complete(SCI_CONTROLLER_HANDLE_T controller,
void scif_cb_controller_allocate_memory(SCI_CONTROLLER_HANDLE_T controller,
SCI_PHYSICAL_MEMORY_DESCRIPTOR_T *mde)
{
+ struct ISCI_CONTROLLER *isci_controller = (struct ISCI_CONTROLLER *)
+ sci_object_get_association(controller);
+ /*
+ * Note this routine is only used for buffers needed to translate
+ * SCSI UNMAP commands to ATA DSM commands for SATA disks.
+ *
+ * We first try to pull a buffer from the controller's pool, and only
+ * call contigmalloc if one isn't there.
+ */
+ if (!sci_pool_empty(isci_controller->unmap_buffer_pool)) {
+ sci_pool_get(isci_controller->unmap_buffer_pool,
+ mde->virtual_address);
+ } else
+ mde->virtual_address = contigmalloc(PAGE_SIZE,
+ M_ISCI, M_NOWAIT, 0, BUS_SPACE_MAXADDR,
+ mde->constant_memory_alignment, 0);
+
+ if (mde->virtual_address != NULL)
+ bus_dmamap_load(isci_controller->buffer_dma_tag,
+ NULL, mde->virtual_address, PAGE_SIZE,
+ isci_single_map, &mde->physical_address,
+ BUS_DMA_NOWAIT);
}
/**
@@ -176,7 +206,16 @@ void scif_cb_controller_allocate_memory(SCI_CONTROLLER_HANDLE_T controller,
void scif_cb_controller_free_memory(SCI_CONTROLLER_HANDLE_T controller,
SCI_PHYSICAL_MEMORY_DESCRIPTOR_T * mde)
{
+ struct ISCI_CONTROLLER *isci_controller = (struct ISCI_CONTROLLER *)
+ sci_object_get_association(controller);
+ /*
+ * Put the buffer back into the controller's buffer pool, rather
+ * than invoking configfree. This helps reduce chance we won't
+ * have buffers available when system is under memory pressure.
+ */
+ sci_pool_put(isci_controller->unmap_buffer_pool,
+ mde->virtual_address);
}
void isci_controller_construct(struct ISCI_CONTROLLER *controller,
@@ -228,6 +267,8 @@ void isci_controller_construct(struct ISCI_CONTROLLER *controller,
for ( int i = 0; i < SCI_MAX_TIMERS; i++ ) {
sci_pool_put(controller->timer_pool, timer++);
}
+
+ sci_pool_initialize(controller->unmap_buffer_pool);
}
SCI_STATUS isci_controller_initialize(struct ISCI_CONTROLLER *controller)
OpenPOWER on IntegriCloud