[Midnightbsd-cvs] src [7909] trunk/sys/dev/isci: Fix/add support for SCSI UNMAP to ATA DSM translation.

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Wed Sep 14 15:24:17 EDT 2016


Revision: 7909
          http://svnweb.midnightbsd.org/src/?rev=7909
Author:   laffer1
Date:     2016-09-14 15:24:17 -0400 (Wed, 14 Sep 2016)
Log Message:
-----------
Fix/add support for SCSI UNMAP to ATA DSM translation.

This addresses kernel panic observed when sending SCSI UNMAP
commands to SATA disks attached to isci(4).

1) Flesh out callback routines to allocate/free buffers needed for
translating SCSI UNMAP data to ATA DSM data.
2) Add controller-level pool for storing buffers previously allocated
for UNMAP translation, to lessen chance of no buffer available
under memory pressure.
3) Ensure driver properly handles case where buffer pool is empty
and contigmalloc returns NULL.
4) Clear freeze bit in isci_remote_device_release_lun_queue() before
calling xpt_release_devq to ensure that any ccbs which immediately
start during the call to xpt_release_devq() see an accurate picture
of the frozen_lun_mask.  This code path is extensively exercised
when tagged read/write commands mix with non-tagged DSM commands.

Obtained from: FreeBSD

Modified Paths:
--------------
    trunk/sys/dev/isci/isci.c
    trunk/sys/dev/isci/isci.h
    trunk/sys/dev/isci/isci_controller.c
    trunk/sys/dev/isci/isci_remote_device.c
    trunk/sys/dev/isci/scil/sati_unmap.c
    trunk/sys/dev/isci/scil/scif_sas_sati_binding.h
    trunk/sys/dev/isci/scil/scif_sas_stp_io_request.c

Modified: trunk/sys/dev/isci/isci.c
===================================================================
--- trunk/sys/dev/isci/isci.c	2016-09-14 19:21:48 UTC (rev 7908)
+++ trunk/sys/dev/isci/isci.c	2016-09-14 19:24:17 UTC (rev 7909)
@@ -185,6 +185,7 @@
 	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 @@
 
 		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

Modified: trunk/sys/dev/isci/isci.h
===================================================================
--- trunk/sys/dev/isci/isci.h	2016-09-14 19:21:48 UTC (rev 7908)
+++ trunk/sys/dev/isci/isci.h	2016-09-14 19:24:17 UTC (rev 7909)
@@ -175,6 +175,7 @@
 	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

Modified: trunk/sys/dev/isci/isci_controller.c
===================================================================
--- trunk/sys/dev/isci/isci_controller.c	2016-09-14 19:21:48 UTC (rev 7908)
+++ trunk/sys/dev/isci/isci_controller.c	2016-09-14 19:24:17 UTC (rev 7909)
@@ -145,6 +145,14 @@
 	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_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_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 @@
 	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)

Modified: trunk/sys/dev/isci/isci_remote_device.c
===================================================================
--- trunk/sys/dev/isci/isci_remote_device.c	2016-09-14 19:21:48 UTC (rev 7908)
+++ trunk/sys/dev/isci/isci_remote_device.c	2016-09-14 19:24:17 UTC (rev 7909)
@@ -278,12 +278,12 @@
 	if (remote_device->frozen_lun_mask & (1 << lun)) {
 		struct cam_path *path;
 
+		remote_device->frozen_lun_mask &= ~(1 << lun);
 		xpt_create_path(&path, xpt_periph,
 		    cam_sim_path(remote_device->domain->controller->sim),
 		    remote_device->index, lun);
 		xpt_release_devq(path, 1, TRUE);
 		xpt_free_path(path);
-		remote_device->frozen_lun_mask &= ~(1 << lun);
 	}
 }
 

Modified: trunk/sys/dev/isci/scil/sati_unmap.c
===================================================================
--- trunk/sys/dev/isci/scil/sati_unmap.c	2016-09-14 19:21:48 UTC (rev 7908)
+++ trunk/sys/dev/isci/scil/sati_unmap.c	2016-09-14 19:24:17 UTC (rev 7909)
@@ -335,8 +335,8 @@
       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
       );

Modified: trunk/sys/dev/isci/scil/scif_sas_sati_binding.h
===================================================================
--- trunk/sys/dev/isci/scil/scif_sas_sati_binding.h	2016-09-14 19:21:48 UTC (rev 7908)
+++ trunk/sys/dev/isci/scil/scif_sas_sati_binding.h	2016-09-14 19:24:17 UTC (rev 7909)
@@ -183,9 +183,7 @@
 {                                                                 \
    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    \
    );                                                             \
@@ -192,13 +190,9 @@
    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 @@
    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         \
    );                                                             \

Modified: trunk/sys/dev/isci/scil/scif_sas_stp_io_request.c
===================================================================
--- trunk/sys/dev/isci/scil/scif_sas_stp_io_request.c	2016-09-14 19:21:48 UTC (rev 7908)
+++ trunk/sys/dev/isci/scil/scif_sas_stp_io_request.c	2016-09-14 19:24:17 UTC (rev 7909)
@@ -171,6 +171,8 @@
          );
    }
 
+   sati_sequence_terminate(&fw_io->parent.stp.sequence, fw_io, fw_io);
+
    return SCI_SUCCESS;
 }
 /**



More information about the Midnightbsd-cvs mailing list