diff --git a/sys/dev/isci/isci.c b/sys/dev/isci/isci.c index 6a1b4a8d57cc..4d2f4bdf035e 100644 --- a/sys/dev/isci/isci.c +++ b/sys/dev/isci/isci.c @@ -185,6 +185,7 @@ isci_detach(device_t device) for (i = 0; i < isci->controller_count; i++) { struct ISCI_CONTROLLER *controller = &isci->controllers[i]; SCI_STATUS status; + void *unmap_buffer; if (controller->scif_controller_handle != NULL) { scic_controller_disable_interrupts( @@ -218,6 +219,13 @@ isci_detach(device_t device) if (controller->remote_device_memory != NULL) free(controller->remote_device_memory, M_ISCI); + + while (1) { + sci_pool_get(controller->unmap_buffer_pool, unmap_buffer); + if (unmap_buffer == NULL) + break; + contigfree(unmap_buffer, PAGE_SIZE, M_ISCI); + } } /* The SCIF controllers have been stopped, so we can now diff --git a/sys/dev/isci/isci.h b/sys/dev/isci/isci.h index cdba7de1806b..48236b9dca99 100644 --- a/sys/dev/isci/isci.h +++ b/sys/dev/isci/isci.h @@ -175,6 +175,7 @@ struct ISCI_CONTROLLER SCI_POOL_CREATE(remote_device_pool, struct ISCI_REMOTE_DEVICE *, SCI_MAX_REMOTE_DEVICES); SCI_POOL_CREATE(request_pool, struct ISCI_REQUEST *, SCI_MAX_IO_REQUESTS); SCI_POOL_CREATE(timer_pool, struct ISCI_TIMER *, SCI_MAX_TIMERS); + SCI_POOL_CREATE(unmap_buffer_pool, void *, SCI_MAX_REMOTE_DEVICES); }; struct ISCI_REQUEST diff --git a/sys/dev/isci/isci_controller.c b/sys/dev/isci/isci_controller.c index 49785cbfd158..1255201fe835 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) diff --git a/sys/dev/isci/scil/sati_unmap.c b/sys/dev/isci/scil/sati_unmap.c index cc8327b3bc25..4cd6e9c41952 100644 --- a/sys/dev/isci/scil/sati_unmap.c +++ b/sys/dev/isci/scil/sati_unmap.c @@ -335,8 +335,8 @@ SATI_STATUS sati_unmap_initial_processing( sati_scsi_sense_data_construct( sequence, scsi_io, - SCSI_STATUS_CHECK_CONDITION, - SCSI_SENSE_ABORTED_COMMAND, + SCSI_STATUS_BUSY, + SCSI_SENSE_NO_SENSE, SCSI_ASC_NO_ADDITIONAL_SENSE, SCSI_ASCQ_NO_ADDITIONAL_SENSE ); diff --git a/sys/dev/isci/scil/scif_sas_sati_binding.h b/sys/dev/isci/scil/scif_sas_sati_binding.h index 99c94333a78b..329efd7794f9 100644 --- a/sys/dev/isci/scil/scif_sas_sati_binding.h +++ b/sys/dev/isci/scil/scif_sas_sati_binding.h @@ -183,22 +183,16 @@ extern "C" { { \ SCIF_SAS_REQUEST_T* fw_request = (SCIF_SAS_REQUEST_T*)scsi_io; \ SCI_PHYSICAL_MEMORY_DESCRIPTOR_T mde; \ - SCI_PHYSICAL_ADDRESS phys_addr; \ mde.virtual_address = NULL; \ - sci_cb_make_physical_address(mde.physical_address, 0, 0); \ sci_base_mde_construct( \ &mde, 4, length, SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS \ ); \ scif_cb_controller_allocate_memory( \ fw_request->device->domain->controller, &mde \ ); \ - scic_cb_io_request_get_physical_address(fw_request->device->domain->controller, \ - NULL, \ - mde.virtual_address, \ - &phys_addr); \ *(virt_address) = mde.virtual_address; \ - *(phys_address_low) = sci_cb_physical_address_lower(phys_addr); \ - *(phys_address_high) = sci_cb_physical_address_upper(phys_addr); \ + *(phys_address_low) = sci_cb_physical_address_lower(mde.physical_address); \ + *(phys_address_high) = sci_cb_physical_address_upper(mde.physical_address); \ } #define sati_cb_free_dma_buffer(scsi_io, virt_address) \ @@ -206,7 +200,6 @@ extern "C" { SCIF_SAS_REQUEST_T* fw_request = (SCIF_SAS_REQUEST_T*)scsi_io; \ SCI_PHYSICAL_MEMORY_DESCRIPTOR_T mde; \ mde.virtual_address = virt_address; \ - sci_cb_make_physical_address(mde.physical_address, 0, 0); \ sci_base_mde_construct( \ &mde, 4, 0, SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS \ ); \ diff --git a/sys/dev/isci/scil/scif_sas_stp_io_request.c b/sys/dev/isci/scil/scif_sas_stp_io_request.c index 36910bd70962..cca50c64f969 100644 --- a/sys/dev/isci/scil/scif_sas_stp_io_request.c +++ b/sys/dev/isci/scil/scif_sas_stp_io_request.c @@ -171,6 +171,8 @@ SCI_STATUS scif_sas_stp_io_request_constructed_complete_handler( ); } + sati_sequence_terminate(&fw_io->parent.stp.sequence, fw_io, fw_io); + return SCI_SUCCESS; } /**