On Wed, Apr 23, 2025 at 11:24 AM Michael S. Tsirkin mst@redhat.com wrote:
some nits
On Wed, Apr 23, 2025 at 03:11:11AM +0000, Mina Almasry wrote:
@@ -189,43 +200,44 @@ net_devmem_bind_dmabuf(struct net_device *dev, unsigned int dmabuf_fd, }
binding->dev = dev;
err = xa_alloc_cyclic(&net_devmem_dmabuf_bindings, &binding->id,
binding, xa_limit_32b, &id_alloc_next,
GFP_KERNEL);
if (err < 0)
goto err_free_binding;
xa_init_flags(&binding->bound_rxqs, XA_FLAGS_ALLOC);
refcount_set(&binding->ref, 1);
binding->dmabuf = dmabuf;
given you keep iterating, don't tweak whitespace in the same patch- will make the review a tiny bit easier.
Sure.
binding->attachment = dma_buf_attach(binding->dmabuf, dev->dev.parent); if (IS_ERR(binding->attachment)) { err = PTR_ERR(binding->attachment); NL_SET_ERR_MSG(extack, "Failed to bind dmabuf to device");
goto err_free_id;
goto err_free_binding; } binding->sgt = dma_buf_map_attachment_unlocked(binding->attachment,
DMA_FROM_DEVICE);
direction); if (IS_ERR(binding->sgt)) { err = PTR_ERR(binding->sgt); NL_SET_ERR_MSG(extack, "Failed to map dmabuf attachment"); goto err_detach; }
if (direction == DMA_TO_DEVICE) {
binding->tx_vec = kvmalloc_array(dmabuf->size / PAGE_SIZE,
sizeof(struct net_iov *),
GFP_KERNEL);
if (!binding->tx_vec) {
err = -ENOMEM;
goto err_unmap;
}
}
/* For simplicity we expect to make PAGE_SIZE allocations, but the * binding can be much more flexible than that. We may be able to * allocate MTU sized chunks here. Leave that for future work... */
binding->chunk_pool =
gen_pool_create(PAGE_SHIFT, dev_to_node(&dev->dev));
binding->chunk_pool = gen_pool_create(PAGE_SHIFT,
dev_to_node(&dev->dev)); if (!binding->chunk_pool) { err = -ENOMEM;
goto err_unmap;
goto err_tx_vec; } virtual = 0;
@@ -270,24 +282,34 @@ net_devmem_bind_dmabuf(struct net_device *dev, unsigned int dmabuf_fd, niov->owner = &owner->area; page_pool_set_dma_addr_netmem(net_iov_to_netmem(niov), net_devmem_get_dma_addr(niov));
if (direction == DMA_TO_DEVICE)
binding->tx_vec[owner->area.base_virtual / PAGE_SIZE + i] = niov; } virtual += len; }
err = xa_alloc_cyclic(&net_devmem_dmabuf_bindings, &binding->id,
binding, xa_limit_32b, &id_alloc_next,
GFP_KERNEL);
if (err < 0)
goto err_free_id;
return binding;
+err_free_id:
xa_erase(&net_devmem_dmabuf_bindings, binding->id);
err_free_chunks: gen_pool_for_each_chunk(binding->chunk_pool, net_devmem_dmabuf_free_chunk_owner, NULL); gen_pool_destroy(binding->chunk_pool); +err_tx_vec:
kvfree(binding->tx_vec);
err_unmap: dma_buf_unmap_attachment_unlocked(binding->attachment, binding->sgt, DMA_FROM_DEVICE); err_detach: dma_buf_detach(dmabuf, binding->attachment); -err_free_id:
xa_erase(&net_devmem_dmabuf_bindings, binding->id);
err_free_binding: kfree(binding); err_put_dmabuf: @@ -295,6 +317,21 @@ net_devmem_bind_dmabuf(struct net_device *dev, unsigned int dmabuf_fd, return ERR_PTR(err); }
+struct net_devmem_dmabuf_binding *net_devmem_lookup_dmabuf(u32 id) +{
struct net_devmem_dmabuf_binding *binding;
rcu_read_lock();
binding = xa_load(&net_devmem_dmabuf_bindings, id);
if (binding) {
if (!net_devmem_dmabuf_binding_get(binding))
binding = NULL;
}
rcu_read_unlock();
return binding;
+}
void net_devmem_get_net_iov(struct net_iov *niov) { net_devmem_dmabuf_binding_get(net_devmem_iov_binding(niov)); @@ -305,6 +342,53 @@ void net_devmem_put_net_iov(struct net_iov *niov) net_devmem_dmabuf_binding_put(net_devmem_iov_binding(niov)); }
+struct net_devmem_dmabuf_binding *net_devmem_get_binding(struct sock *sk,
unsigned int dmabuf_id)
+{
struct net_devmem_dmabuf_binding *binding;
struct dst_entry *dst = __sk_dst_get(sk);
int err = 0;
binding = net_devmem_lookup_dmabuf(dmabuf_id);
why not initialize binding together with the declaration?
I find it stylistically much better to error check this right after it's assigned.
if (!binding || !binding->tx_vec) {
err = -EINVAL;
goto out_err;
}
/* The dma-addrs in this binding are only reachable to the corresponding
* net_device.
*/
if (!dst || !dst->dev || dst->dev->ifindex != binding->dev->ifindex) {
err = -ENODEV;
goto out_err;
}
return binding;
+out_err:
if (binding)
net_devmem_dmabuf_binding_put(binding);
return ERR_PTR(err);
+}
+struct net_iov * +net_devmem_get_niov_at(struct net_devmem_dmabuf_binding *binding,
size_t virt_addr, size_t *off, size_t *size)
+{
size_t idx;
if (virt_addr >= binding->dmabuf->size)
return NULL;
idx = virt_addr / PAGE_SIZE;
init this at where it's declared? or where it's used.
I think probably a local variable isn't warranted. Will remove.