ahci: use sys_vumap() instead of sys_umap()
This is only an optimization for CPU performance. Callers are currently still required to supply contiguous memory.
This commit is contained in:
parent
70abb127cc
commit
186a4db672
3 changed files with 45 additions and 34 deletions
|
@ -258,8 +258,8 @@ PRIVATE int atapi_exec(struct port_state *ps, int cmd,
|
|||
if (!write && (ps->flags & FLAG_USE_DMADIR))
|
||||
fis.cf_feat |= ATA_FEAT_PACKET_DMADIR;
|
||||
|
||||
prd.prd_phys = ps->tmp_phys;
|
||||
prd.prd_size = size;
|
||||
prd.vp_addr = ps->tmp_phys;
|
||||
prd.vp_size = size;
|
||||
nr_prds++;
|
||||
}
|
||||
|
||||
|
@ -640,8 +640,8 @@ PRIVATE int gen_identify(struct port_state *ps, int blocking)
|
|||
else
|
||||
fis.cf_cmd = ATA_CMD_IDENTIFY;
|
||||
|
||||
prd.prd_phys = ps->tmp_phys;
|
||||
prd.prd_size = ATA_ID_SIZE;
|
||||
prd.vp_addr = ps->tmp_phys;
|
||||
prd.vp_size = ATA_ID_SIZE;
|
||||
|
||||
/* Start the command, and possibly wait for the result. */
|
||||
port_set_cmd(ps, 0, &fis, NULL /*packet*/, &prd, 1, FALSE /*write*/);
|
||||
|
@ -803,10 +803,10 @@ PRIVATE void ct_set_prdt(u8_t *ct, prd_t *prdt, int nr_prds)
|
|||
p = (u32_t *) &ct[AHCI_CT_PRDT_OFF];
|
||||
|
||||
for (i = 0; i < nr_prds; i++, prdt++) {
|
||||
*p++ = prdt->prd_phys;
|
||||
*p++ = prdt->vp_addr;
|
||||
*p++ = 0;
|
||||
*p++ = 0;
|
||||
*p++ = prdt->prd_size - 1;
|
||||
*p++ = prdt->vp_size - 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1026,7 +1026,7 @@ PRIVATE int sum_iovec(struct port_state *ps, endpoint_t endpt,
|
|||
*===========================================================================*/
|
||||
PRIVATE int setup_prdt(struct port_state *ps, endpoint_t endpt,
|
||||
iovec_s_t *iovec, int nr_req, vir_bytes size, vir_bytes lead,
|
||||
prd_t *prdt)
|
||||
int write, prd_t *prdt)
|
||||
{
|
||||
/* Convert (the first part of) an I/O vector to a Physical Region
|
||||
* Descriptor Table describing array that can later be used to set the
|
||||
|
@ -1035,57 +1035,69 @@ PRIVATE int setup_prdt(struct port_state *ps, endpoint_t endpt,
|
|||
* used for padding as appropriate. Return the number of PRD entries,
|
||||
* or a negative error code.
|
||||
*/
|
||||
vir_bytes bytes, trail;
|
||||
phys_bytes phys;
|
||||
int i, r, nr_prds = 0;
|
||||
struct vumap_vir vvec[NR_PRDS];
|
||||
size_t bytes, trail;
|
||||
int i, r, pcount, nr_prds = 0;
|
||||
|
||||
if (lead > 0) {
|
||||
/* Allocate a buffer for the data we don't want. */
|
||||
if ((r = port_get_padbuf(ps, ps->sector_size)) != OK)
|
||||
return r;
|
||||
|
||||
prdt[nr_prds].prd_phys = ps->pad_phys;
|
||||
prdt[nr_prds].prd_size = lead;
|
||||
prdt[nr_prds].vp_addr = ps->pad_phys;
|
||||
prdt[nr_prds].vp_size = lead;
|
||||
nr_prds++;
|
||||
}
|
||||
|
||||
/* The sum of lead, size, trail has to be sector-aligned. */
|
||||
trail = (ps->sector_size - (lead + size)) % ps->sector_size;
|
||||
|
||||
/* Get the physical addresses of the given buffers. */
|
||||
for (i = 0; i < nr_req && size > 0; i++) {
|
||||
bytes = MIN(iovec[i].iov_size, size);
|
||||
|
||||
/* Get the physical address of the given buffer. */
|
||||
if (endpt == SELF)
|
||||
r = sys_umap(endpt, VM_D,
|
||||
(vir_bytes) iovec[i].iov_grant, bytes, &phys);
|
||||
vvec[i].vv_addr = (vir_bytes) iovec[i].iov_grant;
|
||||
else
|
||||
r = sys_umap(endpt, VM_GRANT, iovec[i].iov_grant,
|
||||
bytes, &phys);
|
||||
vvec[i].vv_grant = iovec[i].iov_grant;
|
||||
|
||||
if (r != OK) {
|
||||
dprintf(V_ERR, ("%s: unable to map area from %d "
|
||||
"(%d)\n", ahci_portname(ps), endpt, r));
|
||||
vvec[i].vv_size = bytes;
|
||||
|
||||
size -= bytes;
|
||||
}
|
||||
|
||||
pcount = i;
|
||||
|
||||
if ((r = sys_vumap(endpt, vvec, i, 0, write ? VUA_READ : VUA_WRITE,
|
||||
&prdt[nr_prds], &pcount)) != OK) {
|
||||
dprintf(V_ERR, ("%s: unable to map memory from %d (%d)\n",
|
||||
ahci_portname(ps), endpt, r));
|
||||
return r;
|
||||
}
|
||||
|
||||
assert(pcount > 0 && pcount <= i);
|
||||
|
||||
/* Make sure all buffers are physically contiguous and word-aligned. */
|
||||
for (i = 0; i < pcount; i++) {
|
||||
if (vvec[i].vv_size != prdt[nr_prds].vp_size) {
|
||||
dprintf(V_ERR, ("%s: non-contiguous memory from %d\n",
|
||||
ahci_portname(ps), endpt));
|
||||
return EINVAL;
|
||||
}
|
||||
if (phys & 1) {
|
||||
|
||||
if (prdt[nr_prds].vp_addr & 1) {
|
||||
dprintf(V_ERR, ("%s: bad physical address from %d\n",
|
||||
ahci_portname(ps), endpt));
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
assert(nr_prds < NR_PRDS);
|
||||
prdt[nr_prds].prd_phys = phys;
|
||||
prdt[nr_prds].prd_size = bytes;
|
||||
nr_prds++;
|
||||
|
||||
size -= bytes;
|
||||
}
|
||||
|
||||
if (trail > 0) {
|
||||
assert(nr_prds < NR_PRDS);
|
||||
prdt[nr_prds].prd_phys = ps->pad_phys + lead;
|
||||
prdt[nr_prds].prd_size = trail;
|
||||
prdt[nr_prds].vp_addr = ps->pad_phys + lead;
|
||||
prdt[nr_prds].vp_size = trail;
|
||||
nr_prds++;
|
||||
}
|
||||
|
||||
|
@ -1154,7 +1166,8 @@ PRIVATE ssize_t port_transfer(struct port_state *ps, u64_t pos, u64_t eof,
|
|||
}
|
||||
|
||||
/* Create a vector of physical addresses and sizes for the transfer. */
|
||||
nr_prds = r = setup_prdt(ps, endpt, iovec, nr_req, size, lead, prdt);
|
||||
nr_prds = r = setup_prdt(ps, endpt, iovec, nr_req, size, lead, write,
|
||||
prdt);
|
||||
|
||||
if (r < 0) return r;
|
||||
|
||||
|
|
|
@ -247,13 +247,10 @@ typedef struct {
|
|||
u8_t cf_ctl; /* Control */
|
||||
} cmd_fis_t;
|
||||
|
||||
/* Physical Region Descriptor (PRD). For internal use only;
|
||||
/* Physical Region Descriptor (PRD). For internal and sys_vumap() use only;
|
||||
* the contents of this structure are later converted to an actual PRD.
|
||||
*/
|
||||
typedef struct {
|
||||
phys_bytes prd_phys;
|
||||
vir_bytes prd_size;
|
||||
} prd_t;
|
||||
typedef struct vumap_phys prd_t;
|
||||
|
||||
/* These are from at_wini, as this driver is a drop-in replacement for at_wini.
|
||||
* Practically speaking this is already the upper limit with 256 minor device
|
||||
|
|
|
@ -339,6 +339,7 @@ service ahci
|
|||
{
|
||||
system
|
||||
UMAP # 14
|
||||
VUMAP # 18
|
||||
IRQCTL # 19
|
||||
;
|
||||
pci class
|
||||
|
|
Loading…
Reference in a new issue