1
0
mirror of https://git.FreeBSD.org/src.git synced 2025-01-26 16:18:31 +00:00

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
This commit is contained in:
Kenneth D. Merry 2010-06-29 22:07:53 +00:00
parent 03286b3576
commit 4201341ff7
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=209599
5 changed files with 135 additions and 113 deletions

View File

@ -128,6 +128,7 @@ static void mpt_send_event_ack(struct mpt_softc *mpt, request_t *ack_req,
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, int tn, int needreset)
/* 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, int tn, int needreset)
/* 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, int portenable)
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);
}
}

View File

@ -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 offset)
/* 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_softc *mpt);
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,

View File

@ -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 ccb *ccb)
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, request_t *req, int ioindex)
/*
* 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.
*/

View File

@ -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);

View File

@ -646,7 +646,7 @@ mpt_terminate_raid_thread(struct mpt_softc *mpt)
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.