svn commit: r209599 - head/sys/dev/mpt

Kenneth D. Merry ken at FreeBSD.org
Tue Jun 29 22:07:54 UTC 2010


Author: ken
Date: Tue Jun 29 22:07:53 2010
New Revision: 209599
URL: http://svn.freebsd.org/changeset/base/209599

Log:
  Change the mpt driver to allow larger I/O sizes.
  
  The mpt driver previously didn't report a 'maxio' size to CAM, and so the
  da(4) driver limited I/O sizes to DFLTPHYS (64K) by default.  The number
  of scatter gather segments allowed, as reported to busdma, was
  (128K / PAGE_SIZE) + 1, or 33 on architectures with 4K pages.
  
  Change things around so that we wait until we've determined how many
  segments the adapter can support before creating the busdma tag used for
  buffers, so we can potentially support more S/G segments and therefore
  larger I/O sizes.
  
  Also, fix some things that were broken about the module unload path.  It
  still gets hung up inside CAM, though.
  
  mpt.c:		Move some busdma initialization calls in here, and call
  		them just after we've gotten the IOCFacts, and know how
  		many S/G segments this adapter can support.
  
  mpt.h:		Get rid of MPT_MAXPHYS, it is no longer used.
  
  		Add max_cam_seg_cnt, which is used to report our maximum
  		I/O size up to CAM.
  
  mpt_cam.c:	Use max_cam_seg_cnt to report our maximum I/O size to CAM.
  
  		Fix the locking in mpt_cam_detach().
  
  mpt_pci.c:	Pull some busdma initialization and teardown out and put
  		it in mpt.c.  We now delay it until we know many scatter
  		gather segments the adapter can support, and therefore
  		how to setup our busdma tags.
  
  mpt_raid.c:	Make sure we wake up the right wait channel to get the
  		raid thread to wake up when we're trying to shut it down.
  
  Reviewed by:	gibbs, mjacob
  MFC after:	2 weeks

Modified:
  head/sys/dev/mpt/mpt.c
  head/sys/dev/mpt/mpt.h
  head/sys/dev/mpt/mpt_cam.c
  head/sys/dev/mpt/mpt_pci.c
  head/sys/dev/mpt/mpt_raid.c

Modified: head/sys/dev/mpt/mpt.c
==============================================================================
--- head/sys/dev/mpt/mpt.c	Tue Jun 29 21:56:42 2010	(r209598)
+++ head/sys/dev/mpt/mpt.c	Tue Jun 29 22:07:53 2010	(r209599)
@@ -128,6 +128,7 @@ static void mpt_send_event_ack(struct mp
 static int mpt_send_event_request(struct mpt_softc *mpt, int onoff);
 static int mpt_soft_reset(struct mpt_softc *mpt);
 static void mpt_hard_reset(struct mpt_softc *mpt);
+static void mpt_dma_buf_free(struct mpt_softc *mpt);
 static int mpt_configure_ioc(struct mpt_softc *mpt, int, int);
 static int mpt_enable_ioc(struct mpt_softc *mpt, int);
 
@@ -2246,14 +2247,6 @@ mpt_core_attach(struct mpt_softc *mpt)
 	TAILQ_INIT(&mpt->request_pending_list);
 	TAILQ_INIT(&mpt->request_free_list);
 	TAILQ_INIT(&mpt->request_timeout_list);
-	MPT_LOCK(mpt);
-	for (val = 0; val < MPT_MAX_REQUESTS(mpt); val++) {
-		request_t *req = &mpt->request_pool[val];
-		req->state = REQ_STATE_ALLOCATED;
-		mpt_callout_init(mpt, &req->callout);
-		mpt_free_request(mpt, req);
-	}
-	MPT_UNLOCK(mpt);
 	for (val = 0; val < MPT_MAX_LUNS; val++) {
 		STAILQ_INIT(&mpt->trt[val].atios);
 		STAILQ_INIT(&mpt->trt[val].inots);
@@ -2346,6 +2339,8 @@ mpt_core_detach(struct mpt_softc *mpt)
 		request_t *req = &mpt->request_pool[val];
 		mpt_callout_drain(mpt, &req->callout);
 	}
+
+	mpt_dma_buf_free(mpt);
 }
 
 int
@@ -2480,6 +2475,104 @@ mpt_download_fw(struct mpt_softc *mpt)
 	return (0);
 }
 
+int
+mpt_dma_buf_alloc(struct mpt_softc *mpt)
+{
+	struct mpt_map_info mi;
+	uint8_t *vptr;
+	uint32_t pptr, end;
+	int i, error;
+
+	/* Create a child tag for data buffers */
+	if (mpt_dma_tag_create(mpt, mpt->parent_dmat, 1,
+	    0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
+	    NULL, NULL, MAXBSIZE, mpt->max_cam_seg_cnt,
+	    BUS_SPACE_MAXSIZE_32BIT, 0, &mpt->buffer_dmat) != 0) {
+		mpt_prt(mpt, "cannot create a dma tag for data buffers\n");
+		return (1);
+	}
+
+	/* Create a child tag for request buffers */
+	if (mpt_dma_tag_create(mpt, mpt->parent_dmat, PAGE_SIZE, 0,
+	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
+	    NULL, NULL, MPT_REQ_MEM_SIZE(mpt), 1, BUS_SPACE_MAXSIZE_32BIT, 0,
+	    &mpt->request_dmat) != 0) {
+		mpt_prt(mpt, "cannot create a dma tag for requests\n");
+		return (1);
+	}
+
+	/* Allocate some DMA accessable memory for requests */
+	if (bus_dmamem_alloc(mpt->request_dmat, (void **)&mpt->request,
+	    BUS_DMA_NOWAIT, &mpt->request_dmap) != 0) {
+		mpt_prt(mpt, "cannot allocate %d bytes of request memory\n",
+		    MPT_REQ_MEM_SIZE(mpt));
+		return (1);
+	}
+
+	mi.mpt = mpt;
+	mi.error = 0;
+
+	/* Load and lock it into "bus space" */
+	bus_dmamap_load(mpt->request_dmat, mpt->request_dmap, mpt->request,
+	    MPT_REQ_MEM_SIZE(mpt), mpt_map_rquest, &mi, 0);
+
+	if (mi.error) {
+		mpt_prt(mpt, "error %d loading dma map for DMA request queue\n",
+		    mi.error);
+		return (1);
+	}
+	mpt->request_phys = mi.phys;
+
+	/*
+	 * Now create per-request dma maps
+	 */
+	i = 0;
+	pptr =  mpt->request_phys;
+	vptr =  mpt->request;
+	end = pptr + MPT_REQ_MEM_SIZE(mpt);
+	while(pptr < end) {
+		request_t *req = &mpt->request_pool[i];
+		req->index = i++;
+
+		/* Store location of Request Data */
+		req->req_pbuf = pptr;
+		req->req_vbuf = vptr;
+
+		pptr += MPT_REQUEST_AREA;
+		vptr += MPT_REQUEST_AREA;
+
+		req->sense_pbuf = (pptr - MPT_SENSE_SIZE);
+		req->sense_vbuf = (vptr - MPT_SENSE_SIZE);
+
+		error = bus_dmamap_create(mpt->buffer_dmat, 0, &req->dmap);
+		if (error) {
+			mpt_prt(mpt, "error %d creating per-cmd DMA maps\n",
+			    error);
+			return (1);
+		}
+	}
+
+	return (0);
+}
+
+static void
+mpt_dma_buf_free(struct mpt_softc *mpt)
+{
+	int i;
+	if (mpt->request_dmat == 0) {
+		mpt_lprt(mpt, MPT_PRT_DEBUG, "already released dma memory\n");
+		return;
+	}
+	for (i = 0; i < MPT_MAX_REQUESTS(mpt); i++) {
+		bus_dmamap_destroy(mpt->buffer_dmat, mpt->request_pool[i].dmap);
+	}
+	bus_dmamap_unload(mpt->request_dmat, mpt->request_dmap);
+	bus_dmamem_free(mpt->request_dmat, mpt->request, mpt->request_dmap);
+	bus_dma_tag_destroy(mpt->request_dmat);
+	mpt->request_dmat = 0;
+	bus_dma_tag_destroy(mpt->buffer_dmat);
+}
+
 /*
  * Allocate/Initialize data structures for the controller.  Called
  * once at instance startup.
@@ -2488,7 +2581,7 @@ static int
 mpt_configure_ioc(struct mpt_softc *mpt, int tn, int needreset)
 {
 	PTR_MSG_PORT_FACTS_REPLY pfp;
-	int error,  port;
+	int error, port, val;
 	size_t len;
 
 	if (tn == MPT_MAX_TRYS) {
@@ -2548,7 +2641,7 @@ mpt_configure_ioc(struct mpt_softc *mpt,
 
 	/* limited by the number of chain areas the card will support */
 	if (mpt->max_seg_cnt > mpt->ioc_facts.MaxChainDepth) {
-		mpt_lprt(mpt, MPT_PRT_DEBUG,
+		mpt_lprt(mpt, MPT_PRT_INFO,
 		    "chain depth limited to %u (from %u)\n",
 		    mpt->ioc_facts.MaxChainDepth, mpt->max_seg_cnt);
 		mpt->max_seg_cnt = mpt->ioc_facts.MaxChainDepth;
@@ -2557,17 +2650,37 @@ mpt_configure_ioc(struct mpt_softc *mpt,
 	/* converted to the number of simple sges in chain segments. */
 	mpt->max_seg_cnt *= (MPT_NSGL(mpt) - 1);
 
-	mpt_lprt(mpt, MPT_PRT_DEBUG, "Maximum Segment Count: %u\n",
-	    mpt->max_seg_cnt);
-	mpt_lprt(mpt, MPT_PRT_DEBUG, "MsgLength=%u IOCNumber = %d\n",
+	/*
+	 * Use this as the basis for reporting the maximum I/O size to CAM.
+	 */
+	mpt->max_cam_seg_cnt = min(mpt->max_seg_cnt, (MAXPHYS / PAGE_SIZE) + 1);
+
+	error = mpt_dma_buf_alloc(mpt);
+	if (error != 0) {
+		mpt_prt(mpt, "mpt_dma_buf_alloc() failed!\n");
+		return (EIO);
+	}
+
+	for (val = 0; val < MPT_MAX_REQUESTS(mpt); val++) {
+		request_t *req = &mpt->request_pool[val];
+		req->state = REQ_STATE_ALLOCATED;
+		mpt_callout_init(mpt, &req->callout);
+		mpt_free_request(mpt, req);
+	}
+
+	mpt_lprt(mpt, MPT_PRT_INFO, "Maximum Segment Count: %u, Maximum "
+		 "CAM Segment Count: %u\n", mpt->max_seg_cnt,
+		 mpt->max_cam_seg_cnt);
+
+	mpt_lprt(mpt, MPT_PRT_INFO, "MsgLength=%u IOCNumber = %d\n",
 	    mpt->ioc_facts.MsgLength, mpt->ioc_facts.IOCNumber);
-	mpt_lprt(mpt, MPT_PRT_DEBUG,
+	mpt_lprt(mpt, MPT_PRT_INFO,
 	    "IOCFACTS: GlobalCredits=%d BlockSize=%u bytes "
 	    "Request Frame Size %u bytes Max Chain Depth %u\n",
 	    mpt->ioc_facts.GlobalCredits, mpt->ioc_facts.BlockSize,
 	    mpt->ioc_facts.RequestFrameSize << 2,
 	    mpt->ioc_facts.MaxChainDepth);
-	mpt_lprt(mpt, MPT_PRT_DEBUG, "IOCFACTS: Num Ports %d, FWImageSize %d, "
+	mpt_lprt(mpt, MPT_PRT_INFO, "IOCFACTS: Num Ports %d, FWImageSize %d, "
 	    "Flags=%#x\n", mpt->ioc_facts.NumberOfPorts,
 	    mpt->ioc_facts.FWImageSize, mpt->ioc_facts.Flags);
 
@@ -2757,7 +2870,7 @@ mpt_enable_ioc(struct mpt_softc *mpt, in
 		mpt_send_event_request(mpt, 1);
 
 		if (mpt_send_port_enable(mpt, 0) != MPT_OK) {
-			mpt_prt(mpt, "failed to enable port 0\n");
+			mpt_prt(mpt, "%s: failed to enable port 0\n", __func__);
 			return (ENXIO);
 		}
 	}

Modified: head/sys/dev/mpt/mpt.h
==============================================================================
--- head/sys/dev/mpt/mpt.h	Tue Jun 29 21:56:42 2010	(r209598)
+++ head/sys/dev/mpt/mpt.h	Tue Jun 29 22:07:53 2010	(r209599)
@@ -743,6 +743,7 @@ struct mpt_softc {
 	bus_addr_t		request_phys;	/* BusAddr of request memory */
 
 	uint32_t		max_seg_cnt;	/* calculated after IOC facts */
+	uint32_t		max_cam_seg_cnt;/* calculated from MAXPHYS*/
 
 	/*
 	 * Hardware management
@@ -995,9 +996,6 @@ mpt_pio_read(struct mpt_softc *mpt, int 
 /* Max MPT Reply we are willing to accept (must be power of 2) */
 #define MPT_REPLY_SIZE   	256
 
-/* Max i/o size, based on legacy MAXPHYS.  Can be increased. */
-#define MPT_MAXPHYS		(128 * 1024)
-
 /*
  * Must be less than 16384 in order for target mode to work
  */
@@ -1281,6 +1279,7 @@ void		mpt_check_doorbell(struct mpt_soft
 void		mpt_dump_reply_frame(struct mpt_softc *mpt,
 				     MSG_DEFAULT_REPLY *reply_frame);
 
+int		mpt_dma_buf_alloc(struct mpt_softc *mpt);
 void		mpt_set_config_regs(struct mpt_softc *);
 int		mpt_issue_cfg_req(struct mpt_softc */*mpt*/, request_t */*req*/,
 				  cfgparms_t *params,

Modified: head/sys/dev/mpt/mpt_cam.c
==============================================================================
--- head/sys/dev/mpt/mpt_cam.c	Tue Jun 29 21:56:42 2010	(r209598)
+++ head/sys/dev/mpt/mpt_cam.c	Tue Jun 29 22:07:53 2010	(r209599)
@@ -1205,25 +1205,21 @@ mpt_cam_detach(struct mpt_softc *mpt)
 		free(mpt->sas_portinfo, M_DEVBUF);
 		mpt->sas_portinfo = NULL;
 	}
-	MPT_UNLOCK(mpt);
 
 	if (mpt->sim != NULL) {
 		xpt_free_path(mpt->path);
-		MPT_LOCK(mpt);
 		xpt_bus_deregister(cam_sim_path(mpt->sim));
-		MPT_UNLOCK(mpt);
 		cam_sim_free(mpt->sim, TRUE);
 		mpt->sim = NULL;
 	}
 
 	if (mpt->phydisk_sim != NULL) {
 		xpt_free_path(mpt->phydisk_path);
-		MPT_LOCK(mpt);
 		xpt_bus_deregister(cam_sim_path(mpt->phydisk_sim));
-		MPT_UNLOCK(mpt);
 		cam_sim_free(mpt->phydisk_sim, TRUE);
 		mpt->phydisk_sim = NULL;
 	}
+	MPT_UNLOCK(mpt);
 }
 
 /* This routine is used after a system crash to dump core onto the swap device.
@@ -3586,6 +3582,7 @@ mpt_action(struct cam_sim *sim, union cc
 		cpi->target_sprt = 0;
 		cpi->hba_eng_cnt = 0;
 		cpi->max_target = mpt->port_facts[0].MaxDevices - 1;
+		cpi->maxio = (mpt->max_cam_seg_cnt - 1) * PAGE_SIZE;
 		/*
 		 * FC cards report MAX_DEVICES of 512, but
 		 * the MSG_SCSI_IO_REQUEST target id field
@@ -4226,7 +4223,7 @@ mpt_fc_post_els(struct mpt_softc *mpt, r
 	/*
 	 * Okay, set up ELS buffer pointers. ELS buffer pointers
 	 * consist of a TE SGL element (with details length of zero)
-	 * followe by a SIMPLE SGL element which holds the address
+	 * followed by a SIMPLE SGL element which holds the address
 	 * of the buffer.
 	 */
 

Modified: head/sys/dev/mpt/mpt_pci.c
==============================================================================
--- head/sys/dev/mpt/mpt_pci.c	Tue Jun 29 21:56:42 2010	(r209598)
+++ head/sys/dev/mpt/mpt_pci.c	Tue Jun 29 22:07:53 2010	(r209599)
@@ -720,9 +720,6 @@ mpt_pci_shutdown(device_t dev)
 static int
 mpt_dma_mem_alloc(struct mpt_softc *mpt)
 {
-	int i, error, nsegs;
-	uint8_t *vptr;
-	uint32_t pptr, end;
 	size_t len;
 	struct mpt_map_info mi;
 
@@ -795,82 +792,6 @@ mpt_dma_mem_alloc(struct mpt_softc *mpt)
 	}
 	mpt->reply_phys = mi.phys;
 
-	/* Create a child tag for data buffers */
-
-	/*
-	 * XXX: we should say that nsegs is 'unrestricted, but that
-	 * XXX: tickles a horrible bug in the busdma code. Instead,
-	 * XXX: we'll derive a reasonable segment limit from MPT_MAXPHYS
-	 */
-	nsegs = (MPT_MAXPHYS / PAGE_SIZE) + 1;
-	if (mpt_dma_tag_create(mpt, mpt->parent_dmat, 1,
-	    0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
-	    NULL, NULL, MAXBSIZE, nsegs, BUS_SPACE_MAXSIZE_32BIT, 0,
-	    &mpt->buffer_dmat) != 0) {
-		mpt_prt(mpt, "cannot create a dma tag for data buffers\n");
-		return (1);
-	}
-
-	/* Create a child tag for request buffers */
-	if (mpt_dma_tag_create(mpt, mpt->parent_dmat, PAGE_SIZE, 0,
-	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
-	    NULL, NULL, MPT_REQ_MEM_SIZE(mpt), 1, BUS_SPACE_MAXSIZE_32BIT, 0,
-	    &mpt->request_dmat) != 0) {
-		mpt_prt(mpt, "cannot create a dma tag for requests\n");
-		return (1);
-	}
-
-	/* Allocate some DMA accessable memory for requests */
-	if (bus_dmamem_alloc(mpt->request_dmat, (void **)&mpt->request,
-	    BUS_DMA_NOWAIT, &mpt->request_dmap) != 0) {
-		mpt_prt(mpt, "cannot allocate %d bytes of request memory\n",
-		    MPT_REQ_MEM_SIZE(mpt));
-		return (1);
-	}
-
-	mi.mpt = mpt;
-	mi.error = 0;
-
-	/* Load and lock it into "bus space" */
-        bus_dmamap_load(mpt->request_dmat, mpt->request_dmap, mpt->request,
-	    MPT_REQ_MEM_SIZE(mpt), mpt_map_rquest, &mi, 0);
-
-	if (mi.error) {
-		mpt_prt(mpt, "error %d loading dma map for DMA request queue\n",
-		    mi.error);
-		return (1);
-	}
-	mpt->request_phys = mi.phys;
-
-	/*
-	 * Now create per-request dma maps
-	 */
-	i = 0;
-	pptr =  mpt->request_phys;
-	vptr =  mpt->request;
-	end = pptr + MPT_REQ_MEM_SIZE(mpt);
-	while(pptr < end) {
-		request_t *req = &mpt->request_pool[i];
-		req->index = i++;
-
-		/* Store location of Request Data */
-		req->req_pbuf = pptr;
-		req->req_vbuf = vptr;
-
-		pptr += MPT_REQUEST_AREA;
-		vptr += MPT_REQUEST_AREA;
-
-		req->sense_pbuf = (pptr - MPT_SENSE_SIZE);
-		req->sense_vbuf = (vptr - MPT_SENSE_SIZE);
-
-		error = bus_dmamap_create(mpt->buffer_dmat, 0, &req->dmap);
-		if (error) {
-			mpt_prt(mpt, "error %d creating per-cmd DMA maps\n",
-			    error);
-			return (1);
-		}
-	}
-
 	return (0);
 }
 
@@ -881,7 +802,6 @@ mpt_dma_mem_alloc(struct mpt_softc *mpt)
 static void
 mpt_dma_mem_free(struct mpt_softc *mpt)
 {
-	int i;
 
         /* Make sure we aren't double destroying */
         if (mpt->reply_dmat == 0) {
@@ -889,13 +809,6 @@ mpt_dma_mem_free(struct mpt_softc *mpt)
 		return;
         }
                 
-	for (i = 0; i < MPT_MAX_REQUESTS(mpt); i++) {
-		bus_dmamap_destroy(mpt->buffer_dmat, mpt->request_pool[i].dmap);
-	}
-	bus_dmamap_unload(mpt->request_dmat, mpt->request_dmap);
-	bus_dmamem_free(mpt->request_dmat, mpt->request, mpt->request_dmap);
-	bus_dma_tag_destroy(mpt->request_dmat);
-	bus_dma_tag_destroy(mpt->buffer_dmat);
 	bus_dmamap_unload(mpt->reply_dmat, mpt->reply_dmap);
 	bus_dmamem_free(mpt->reply_dmat, mpt->reply, mpt->reply_dmap);
 	bus_dma_tag_destroy(mpt->reply_dmat);

Modified: head/sys/dev/mpt/mpt_raid.c
==============================================================================
--- head/sys/dev/mpt/mpt_raid.c	Tue Jun 29 21:56:42 2010	(r209598)
+++ head/sys/dev/mpt/mpt_raid.c	Tue Jun 29 22:07:53 2010	(r209599)
@@ -646,7 +646,7 @@ mpt_terminate_raid_thread(struct mpt_sof
 		return;
 	}
 	mpt->shutdwn_raid = 1;
-	wakeup(mpt->raid_volumes);
+	wakeup(&mpt->raid_volumes);
 	/*
 	 * Sleep on a slightly different location
 	 * for this interlock just for added safety.


More information about the svn-src-head mailing list