diff options
Diffstat (limited to 'usr/src/uts/sun4v/io/vldc.c')
-rw-r--r-- | usr/src/uts/sun4v/io/vldc.c | 156 |
1 files changed, 90 insertions, 66 deletions
diff --git a/usr/src/uts/sun4v/io/vldc.c b/usr/src/uts/sun4v/io/vldc.c index 6c366c5c59..6b9d48a76c 100644 --- a/usr/src/uts/sun4v/io/vldc.c +++ b/usr/src/uts/sun4v/io/vldc.c @@ -408,6 +408,7 @@ i_vldc_mdeg_register(vldc_t *vldcp) bcopy(nameprop, name, namesz); VLDC_SET_MDEG_PROP_NAME(pspecp, name); + ddi_prop_free(nameprop); /* copy in the instance property */ VLDC_SET_MDEG_PROP_INST(pspecp, inst); @@ -728,6 +729,9 @@ i_vldc_close_port(vldc_t *vldcp, uint_t portno) kmem_free(vport->send_buf, vport->mtu); kmem_free(vport->recv_buf, vport->mtu); + if (strcmp(vport->minorp->sname, VLDC_HVCTL_SVCNAME) == 0) + kmem_free(vport->cookie_buf, vldc_max_cookie); + vport->status = VLDC_PORT_CLOSED; return (rv); @@ -910,6 +914,9 @@ vldc_open(dev_t *devp, int flag, int otyp, cred_t *cred) vport->recv_buf = kmem_alloc(vport->mtu, KM_SLEEP); vport->send_buf = kmem_alloc(vport->mtu, KM_SLEEP); + if (strcmp(vport->minorp->sname, VLDC_HVCTL_SVCNAME) == 0) + vport->cookie_buf = kmem_alloc(vldc_max_cookie, KM_SLEEP); + vport->is_stream = B_FALSE; /* assume not a stream */ vport->hanged_up = B_FALSE; @@ -1057,50 +1064,57 @@ i_vldc_ioctl_read_cookie(vldc_port_t *vport, int vldc_instance, void *arg, int mode) { vldc_data_t copy_info; - caddr_t buf; - uint64_t len; + uint64_t len, balance, copy_size; + caddr_t src_addr, dst_addr; int rv; if (ddi_copyin(arg, ©_info, sizeof (copy_info), mode) == -1) { return (EFAULT); } - len = copy_info.length; - if (len > vldc_max_cookie) { - return (EINVAL); - } + len = balance = copy_info.length; + src_addr = (caddr_t)copy_info.src_addr; + dst_addr = (caddr_t)copy_info.dst_addr; + while (balance > 0) { - /* allocate a temporary buffer */ - buf = kmem_alloc(len, KM_SLEEP); + /* get the max amount to the copied */ + copy_size = MIN(balance, vldc_max_cookie); - mutex_enter(&vport->minorp->lock); + mutex_enter(&vport->minorp->lock); - D2("i_vldc_ioctl_read_cookie: vldc@%d:%d reading from 0x%lx " - "size 0x%lx to 0x%lx\n", vldc_instance, vport->number, - copy_info.dst_addr, copy_info.length, copy_info.src_addr); + D2("i_vldc_ioctl_read_cookie: vldc@%d:%d reading from 0x%p " + "size 0x%lx to 0x%p\n", vldc_instance, vport->number, + dst_addr, copy_size, src_addr); - /* read from the HV into the temporary buffer */ - rv = ldc_mem_rdwr_pa(vport->ldc_handle, buf, &len, - (caddr_t)copy_info.dst_addr, LDC_COPY_IN); - if (rv != 0) { - DWARN("i_vldc_ioctl_read_cookie: vldc@%d:%d cannot read " - "address 0x%lx, rv=%d\n", vldc_instance, vport->number, - copy_info.dst_addr, rv); - mutex_exit(&vport->minorp->lock); - kmem_free(buf, copy_info.length); - return (EFAULT); - } + /* read from the HV into the temporary buffer */ + rv = ldc_mem_rdwr_pa(vport->ldc_handle, vport->cookie_buf, + ©_size, dst_addr, LDC_COPY_IN); + if (rv != 0) { + DWARN("i_vldc_ioctl_read_cookie: vldc@%d:%d cannot " + "read address 0x%p, rv=%d\n", + vldc_instance, vport->number, dst_addr, rv); + mutex_exit(&vport->minorp->lock); + return (EFAULT); + } - D2("i_vldc_ioctl_read_cookie: vldc@%d:%d read succeeded\n", - vldc_instance, vport->number); + D2("i_vldc_ioctl_read_cookie: vldc@%d:%d read succeeded\n", + vldc_instance, vport->number); - mutex_exit(&vport->minorp->lock); + mutex_exit(&vport->minorp->lock); - /* copy data from temporary buffer out to the caller and free buffer */ - rv = ddi_copyout(buf, (caddr_t)copy_info.src_addr, len, mode); - kmem_free(buf, copy_info.length); - if (rv != 0) { - return (EFAULT); + /* + * copy data from temporary buffer out to the + * caller and free buffer + */ + rv = ddi_copyout(vport->cookie_buf, src_addr, copy_size, mode); + if (rv != 0) { + return (EFAULT); + } + + /* adjust len, source and dest */ + balance -= copy_size; + src_addr += copy_size; + dst_addr += copy_size; } /* set the structure to reflect outcome */ @@ -1118,54 +1132,58 @@ i_vldc_ioctl_write_cookie(vldc_port_t *vport, int vldc_instance, void *arg, int mode) { vldc_data_t copy_info; - caddr_t buf; - uint64_t len; + uint64_t len, balance, copy_size; + caddr_t src_addr, dst_addr; int rv; - if (ddi_copyin((caddr_t)arg, ©_info, - sizeof (copy_info), mode) != 0) { + if (ddi_copyin(arg, ©_info, sizeof (copy_info), mode) != 0) { return (EFAULT); } - len = copy_info.length; - if (len > vldc_max_cookie) { - return (EINVAL); - } - D2("i_vldc_ioctl_write_cookie: vldc@%d:%d writing 0x%lx size 0x%lx " "to 0x%lx\n", vldc_instance, vport->number, copy_info.src_addr, copy_info.length, copy_info.dst_addr); - /* allocate a temporary buffer */ - buf = kmem_alloc(len, KM_SLEEP); + len = balance = copy_info.length; + src_addr = (caddr_t)copy_info.src_addr; + dst_addr = (caddr_t)copy_info.dst_addr; + while (balance > 0) { - /* copy into the temporary buffer the data to be written to the HV */ - if (ddi_copyin((caddr_t)copy_info.src_addr, buf, - copy_info.length, mode) != 0) { - kmem_free(buf, copy_info.length); - return (EFAULT); - } + /* get the max amount to the copied */ + copy_size = MIN(balance, vldc_max_cookie); - mutex_enter(&vport->minorp->lock); + /* + * copy into the temporary buffer the data + * to be written to the HV + */ + if (ddi_copyin((caddr_t)src_addr, vport->cookie_buf, + copy_size, mode) != 0) { + return (EFAULT); + } - /* write the data from the temporary buffer to the HV */ - rv = ldc_mem_rdwr_pa(vport->ldc_handle, buf, &len, - (caddr_t)copy_info.dst_addr, LDC_COPY_OUT); - if (rv != 0) { - DWARN("i_vldc_ioctl_write_cookie: vldc@%d:%d failed to write at" - " address 0x%lx\n, rv=%d", vldc_instance, vport->number, - copy_info.dst_addr, rv); - mutex_exit(&vport->minorp->lock); - kmem_free(buf, copy_info.length); - return (EFAULT); - } + mutex_enter(&vport->minorp->lock); + + /* write the data from the temporary buffer to the HV */ + rv = ldc_mem_rdwr_pa(vport->ldc_handle, vport->cookie_buf, + ©_size, dst_addr, LDC_COPY_OUT); + if (rv != 0) { + DWARN("i_vldc_ioctl_write_cookie: vldc@%d:%d " + "failed to write at address 0x%p\n, rv=%d", + vldc_instance, vport->number, dst_addr, rv); + mutex_exit(&vport->minorp->lock); + return (EFAULT); + } - D2("i_vldc_ioctl_write_cookie: vldc@%d:%d write succeeded\n", - vldc_instance, vport->number); + D2("i_vldc_ioctl_write_cookie: vldc@%d:%d write succeeded\n", + vldc_instance, vport->number); - mutex_exit(&vport->minorp->lock); + mutex_exit(&vport->minorp->lock); - kmem_free(buf, copy_info.length); + /* adjust len, source and dest */ + balance -= copy_size; + src_addr += copy_size; + dst_addr += copy_size; + } /* set the structure to reflect outcome */ copy_info.length = len; @@ -1315,13 +1333,19 @@ vldc_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, break; case VLDC_IOCTL_READ_COOKIE: - + if (strcmp(vport->minorp->sname, VLDC_HVCTL_SVCNAME)) { + rv = EINVAL; + break; + } rv = i_vldc_ioctl_read_cookie(vport, instance, (void *)arg, mode); break; case VLDC_IOCTL_WRITE_COOKIE: - + if (strcmp(vport->minorp->sname, VLDC_HVCTL_SVCNAME)) { + rv = EINVAL; + break; + } rv = i_vldc_ioctl_write_cookie(vport, instance, (void *)arg, mode); break; |