From owner-p4-projects@FreeBSD.ORG Wed Jun 10 13:13:15 2009 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id CBD4A1065670; Wed, 10 Jun 2009 13:13:14 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 8BA1C106564A for ; Wed, 10 Jun 2009 13:13:14 +0000 (UTC) (envelope-from mav@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 788528FC1A for ; Wed, 10 Jun 2009 13:13:14 +0000 (UTC) (envelope-from mav@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id n5ADDE1T063937 for ; Wed, 10 Jun 2009 13:13:14 GMT (envelope-from mav@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id n5ADDEvZ063935 for perforce@freebsd.org; Wed, 10 Jun 2009 13:13:14 GMT (envelope-from mav@freebsd.org) Date: Wed, 10 Jun 2009 13:13:14 GMT Message-Id: <200906101313.n5ADDEvZ063935@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to mav@freebsd.org using -f From: Alexander Motin To: Perforce Change Reviews Cc: Subject: PERFORCE change 163986 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 10 Jun 2009 13:13:15 -0000 http://perforce.freebsd.org/chv.cgi?CH=163986 Change 163986 by mav@mav_mavbook on 2009/06/10 13:13:05 Change controller DMA memory layout. This allows driver to adapt any defined MAXPHYS size. Separate receive FIS area to different busdma tag as it has different alignment requirements and access patterns. Affected files ... .. //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.c#22 edit .. //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.h#10 edit Differences ... ==== //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.c#22 (text+ko) ==== @@ -89,8 +89,6 @@ static void ahciaction(struct cam_sim *sim, union ccb *ccb); static void ahcipoll(struct cam_sim *sim); -#define MAXWSPCSZ PAGE_SIZE*11 - /* * AHCI v1.x compliant SATA chipset support functions */ @@ -631,7 +629,7 @@ work = ch->dma.work_bus + AHCI_CL_OFFSET; ATA_OUTL(ch->r_mem, AHCI_P_CLB, work & 0xffffffff); ATA_OUTL(ch->r_mem, AHCI_P_CLBU, work >> 32); - work = ch->dma.work_bus + AHCI_FB_OFFSET; + work = ch->dma.rfis_bus; ATA_OUTL(ch->r_mem, AHCI_P_FB, work & 0xffffffff); ATA_OUTL(ch->r_mem, AHCI_P_FBU, work >> 32); /* Activate the channel and power/spin up device */ @@ -671,38 +669,46 @@ struct ahci_channel *ch = device_get_softc(dev); struct ahci_dc_cb_args dcba; - ch->dma.alignment = 2; - ch->dma.boundary = 65536; - ch->dma.segsize = 65536; - ch->dma.max_iosize = AHCI_DMA_ENTRIES * PAGE_SIZE; if (ch->caps & AHCI_CAP_64BIT) ch->dma.max_address = BUS_SPACE_MAXADDR; else ch->dma.max_address = BUS_SPACE_MAXADDR_32BIT; - - if (bus_dma_tag_create(bus_get_dma_tag(dev), PAGE_SIZE, 64 * 1024, + /* Command area. */ + if (bus_dma_tag_create(bus_get_dma_tag(dev), 1024, 0, ch->dma.max_address, BUS_SPACE_MAXADDR, - NULL, NULL, MAXWSPCSZ, 1, MAXWSPCSZ, + NULL, NULL, AHCI_WORK_SIZE, 1, AHCI_WORK_SIZE, 0, NULL, NULL, &ch->dma.work_tag)) goto error; - if (bus_dmamem_alloc(ch->dma.work_tag, (void **)&ch->dma.work, 0, &ch->dma.work_map)) goto error; - if (bus_dmamap_load(ch->dma.work_tag, ch->dma.work_map, ch->dma.work, - MAXWSPCSZ, ahci_dmasetupc_cb, &dcba, 0) || dcba.error) { + AHCI_WORK_SIZE, ahci_dmasetupc_cb, &dcba, 0) || dcba.error) { bus_dmamem_free(ch->dma.work_tag, ch->dma.work, ch->dma.work_map); goto error; } ch->dma.work_bus = dcba.maddr; - - if (bus_dma_tag_create(bus_get_dma_tag(dev), - ch->dma.alignment, ch->dma.boundary, + /* FIS receive area. */ + if (bus_dma_tag_create(bus_get_dma_tag(dev), 4096, 0, + ch->dma.max_address, BUS_SPACE_MAXADDR, + NULL, NULL, 4096, 1, 4096, + 0, NULL, NULL, &ch->dma.rfis_tag)) + goto error; + if (bus_dmamem_alloc(ch->dma.rfis_tag, (void **)&ch->dma.rfis, 0, + &ch->dma.rfis_map)) + goto error; + if (bus_dmamap_load(ch->dma.rfis_tag, ch->dma.rfis_map, ch->dma.rfis, + 4096, ahci_dmasetupc_cb, &dcba, 0) || dcba.error) { + bus_dmamem_free(ch->dma.rfis_tag, ch->dma.rfis, ch->dma.rfis_map); + goto error; + } + ch->dma.rfis_bus = dcba.maddr; + /* Data area. */ + if (bus_dma_tag_create(bus_get_dma_tag(dev), 2, 0, ch->dma.max_address, BUS_SPACE_MAXADDR, NULL, NULL, - ch->dma.max_iosize * ch->numslots, - AHCI_DMA_ENTRIES, ch->dma.segsize, + AHCI_SG_ENTRIES * PAGE_SIZE * ch->numslots, + AHCI_SG_ENTRIES, AHCI_PRD_MAX, 0, busdma_lock_mutex, &ch->mtx, &ch->dma.data_tag)) { goto error; } @@ -731,6 +737,13 @@ bus_dma_tag_destroy(ch->dma.data_tag); ch->dma.data_tag = NULL; } + if (ch->dma.rfis_bus) { + bus_dmamap_unload(ch->dma.rfis_tag, ch->dma.rfis_map); + bus_dmamem_free(ch->dma.rfis_tag, ch->dma.rfis, ch->dma.rfis_map); + ch->dma.rfis_bus = 0; + ch->dma.rfis_map = NULL; + ch->dma.rfis = NULL; + } if (ch->dma.work_bus) { bus_dmamap_unload(ch->dma.work_tag, ch->dma.work_map); bus_dmamem_free(ch->dma.work_tag, ch->dma.work, ch->dma.work_map); @@ -748,7 +761,6 @@ ahci_slotsalloc(device_t dev) { struct ahci_channel *ch = device_get_softc(dev); - struct ahci_dc_cb_args dcba; int i; /* Alloc and setup command/dma slots */ @@ -762,22 +774,6 @@ slot->ccb = NULL; callout_init_mtx(&slot->timeout, &ch->mtx, 0); - if (bus_dma_tag_create(bus_get_dma_tag(dev), PAGE_SIZE, PAGE_SIZE, - ch->dma.max_address, BUS_SPACE_MAXADDR, - NULL, NULL, PAGE_SIZE, 1, PAGE_SIZE, - 0, NULL, NULL, &slot->dma.sg_tag)) { - device_printf(ch->dev, "FAILURE - create sg_tag\n"); - } - - if (bus_dmamem_alloc(slot->dma.sg_tag, (void **)&slot->dma.sg, - 0, &slot->dma.sg_map)) - device_printf(ch->dev, "FAILURE - alloc sg_map\n"); - - if (bus_dmamap_load(slot->dma.sg_tag, slot->dma.sg_map, slot->dma.sg, PAGE_SIZE, - ahci_dmasetupc_cb, &dcba, BUS_DMA_NOWAIT) || dcba.error) - device_printf(ch->dev, "FAILURE - load sg\n"); - slot->dma.sg_bus = dcba.maddr; - if (bus_dmamap_create(ch->dma.data_tag, 0, &slot->dma.data_map)) device_printf(ch->dev, "FAILURE - create data_map\n"); } @@ -793,20 +789,6 @@ for (i = 0; i < ch->numslots; i++) { struct ahci_slot *slot = &ch->slot[i]; - if (slot->dma.sg_tag) { - bus_dma_tag_destroy(slot->dma.sg_tag); - slot->dma.sg_tag = NULL; - } - if (slot->dma.sg_bus) { - bus_dmamap_unload(slot->dma.sg_tag, slot->dma.sg_map); - slot->dma.sg_bus = 0; - } - if (slot->dma.sg_map) { - bus_dmamem_free(slot->dma.sg_tag, slot->dma.sg, slot->dma.sg_map); - bus_dmamap_destroy(slot->dma.sg_tag, slot->dma.sg_map); - slot->dma.sg = NULL; - slot->dma.sg_map = NULL; - } if (slot->dma.data_map) { bus_dmamap_destroy(ch->dma.data_tag, slot->dma.data_map); slot->dma.data_map = NULL; @@ -1007,8 +989,6 @@ prd[i].dbc = htole32((segs[i].ds_len - 1) & AHCI_PRD_MASK); } slot->dma.nsegs = nsegs; - bus_dmamap_sync(slot->dma.sg_tag, slot->dma.sg_map, - BUS_DMASYNC_PREWRITE); bus_dmamap_sync(ch->dma.data_tag, slot->dma.data_map, ((slot->ccb->ccb_h.flags & CAM_DIR_IN) ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE)); @@ -1055,6 +1035,10 @@ clp->bytecount = 0; clp->cmd_table_phys = htole64(ch->dma.work_bus + AHCI_CT_OFFSET + (AHCI_CT_SIZE * slot->slot)); + bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map, + BUS_DMASYNC_PREWRITE); + bus_dmamap_sync(ch->dma.rfis_tag, ch->dma.rfis_map, + BUS_DMASYNC_PREREAD); /* Set ACTIVE bit for NCQ commands. */ if ((ccb->ccb_h.func_code == XPT_ATA_IO) && (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA)) { @@ -1148,37 +1132,40 @@ device_t dev = slot->dev; struct ahci_channel *ch = device_get_softc(dev); union ccb *ccb = slot->ccb; -// struct ahci_cmd_list *clp; //device_printf(dev, "%s slot %d\n", __func__, slot->slot); /* Cancel command execution timeout */ callout_stop(&slot->timeout); - /* Read result registers to the result struct */ + bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map, + BUS_DMASYNC_POSTWRITE); + /* Read result registers to the result struct + * May be incorrect if several commands finished same time, + * so read only when sure. + */ if (ccb->ccb_h.func_code == XPT_ATA_IO) { struct ata_res *res = &ccb->ataio.res; - u_int8_t *fis = ch->dma.work + AHCI_FB_OFFSET + 0x40; + + if (et == AHCI_ERR_REAL || + ccb->ataio.cmd.flags & CAM_ATAIO_CONTROL) { + u_int8_t *fis = ch->dma.rfis + 0x40; - res->status = fis[2]; - res->error = fis[3]; - res->lba_low = fis[4]; - res->lba_mid = fis[5]; - res->lba_high = fis[6]; - res->device = fis[7]; - res->lba_low_exp = fis[8]; - res->lba_mid_exp = fis[9]; - res->lba_high_exp = fis[10]; - res->sector_count = fis[12]; - res->sector_count_exp = fis[13]; + bus_dmamap_sync(ch->dma.rfis_tag, ch->dma.rfis_map, + BUS_DMASYNC_POSTREAD); + res->status = fis[2]; + res->error = fis[3]; + res->lba_low = fis[4]; + res->lba_mid = fis[5]; + res->lba_high = fis[6]; + res->device = fis[7]; + res->lba_low_exp = fis[8]; + res->lba_mid_exp = fis[9]; + res->lba_high_exp = fis[10]; + res->sector_count = fis[12]; + res->sector_count_exp = fis[13]; + } else + bzero(res, sizeof(*res)); } -#if 0 - /* record how much data we actually moved */ - clp = (struct ahci_cmd_list *) - (ch->dma.work + AHCI_CL_OFFSET + (AHCI_CL_SIZE * slot->slot)); - request->donecount = clp->bytecount; -#endif if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { - bus_dmamap_sync(slot->dma.sg_tag, slot->dma.sg_map, - BUS_DMASYNC_POSTWRITE); bus_dmamap_sync(ch->dma.data_tag, slot->dma.data_map, (ccb->ccb_h.flags & CAM_DIR_IN) ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); ==== //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.h#10 (text+ko) ==== @@ -240,26 +240,36 @@ #define AHCI_P_SNTF 0x3C #define AHCI_P_FBS 0x40 +/* Just to be sure, if building as module. */ +#if MAXPHYS < 512 * 1024 +#undef MAXPHYS +#define MAXPHYS 512 * 1024 +#endif +/* Pessimistic prognosis on number of required S/G entries */ +#define AHCI_SG_ENTRIES (roundup(btoc(MAXPHYS) + 1, 8)) +/* Command list. 32 commands. First, 1Kbyte aligned. */ +#define AHCI_CL_OFFSET 0 #define AHCI_CL_SIZE 32 -#define AHCI_CL_OFFSET 0 -#define AHCI_FB_OFFSET (AHCI_CL_SIZE * 32) -#define AHCI_CT_OFFSET (AHCI_FB_OFFSET + 4096) -#define AHCI_CT_SIZE (1024 + 128) +/* Command tables. Up to 32 commands, Each, 128byte aligned. */ +#define AHCI_CT_OFFSET (AHCI_CL_OFFSET + AHCI_CL_SIZE * AHCI_MAX_SLOTS) +#define AHCI_CT_SIZE (128 + AHCI_SG_ENTRIES * 16) +/* Total main work area. */ +#define AHCI_WORK_SIZE (AHCI_CT_OFFSET + AHCI_CT_SIZE * ch->numslots) struct ahci_dma_prd { u_int64_t dba; u_int32_t reserved; u_int32_t dbc; /* 0 based */ -#define AHCI_PRD_MASK 0x003fffff /* max 4MB */ -#define AHCI_PRD_IPC (1<<31) +#define AHCI_PRD_MASK 0x003fffff /* max 4MB */ +#define AHCI_PRD_MAX (AHCI_PRD_MASK + 1) +#define AHCI_PRD_IPC (1 << 31) } __packed; struct ahci_cmd_tab { u_int8_t cfis[64]; u_int8_t acmd[32]; u_int8_t reserved[32]; -#define AHCI_DMA_ENTRIES 64 - struct ahci_dma_prd prd_tab[AHCI_DMA_ENTRIES]; + struct ahci_dma_prd prd_tab[AHCI_SG_ENTRIES]; } __packed; struct ahci_cmd_list { @@ -276,24 +286,11 @@ u_int64_t cmd_table_phys; /* 128byte aligned */ } __packed; -/* DMA register defines */ -#define ATA_DMA_ENTRIES 256 - /* misc defines */ #define ATA_IRQ_RID 0 #define ATA_INTR_FLAGS (INTR_MPSAFE|INTR_TYPE_BIO|INTR_ENTROPY) -/* structure for holding DMA Physical Region Descriptors (PRD) entries */ -struct ata_dma_prdentry { - u_int32_t addr; - u_int32_t count; -}; - struct ata_dmaslot { - bus_dma_tag_t sg_tag; /* SG list DMA tag */ - bus_dmamap_t sg_map; /* SG list DMA map */ - void *sg; /* DMA transfer table */ - bus_addr_t sg_bus; /* bus address of dmatab */ bus_dmamap_t data_map; /* data DMA map */ int nsegs; /* Number of segs loaded */ }; @@ -302,22 +299,16 @@ struct ata_dma { bus_dma_tag_t work_tag; /* workspace DMA tag */ bus_dmamap_t work_map; /* workspace DMA map */ - u_int8_t *work; /* workspace */ - bus_addr_t work_bus; /* bus address of dmatab */ - + uint8_t *work; /* workspace */ + bus_addr_t work_bus; /* bus address of work */ + bus_dma_tag_t rfis_tag; /* RFIS list DMA tag */ + bus_dmamap_t rfis_map; /* RFIS list DMA map */ + uint8_t *rfis; /* FIS receive area */ + bus_addr_t rfis_bus; /* bus address of rfis */ bus_dma_tag_t data_tag; /* data DMA tag */ - - u_int32_t alignment; /* DMA SG list alignment */ - u_int32_t boundary; /* DMA SG list boundary */ - u_int32_t segsize; /* DMA SG list segment size */ - u_int32_t max_iosize; /* DMA data max IO size */ u_int64_t max_address; /* highest DMA'able address */ }; -#define ATA_MASTER 0x00 -#define ATA_SLAVE 0x01 -#define ATA_PM 0x0f - enum ahci_slot_states { AHCI_SLOT_EMPTY, AHCI_SLOT_LOADING, @@ -334,7 +325,6 @@ struct callout timeout; /* Execution timeout */ }; - /* structure describing an ATA channel */ struct ahci_channel { device_t dev; /* Device handle */