Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 3 additions & 62 deletions drivers/hv/channel.c
Original file line number Diff line number Diff line change
Expand Up @@ -1077,68 +1077,10 @@ int vmbus_sendpacket(struct vmbus_channel *channel, void *buffer,
EXPORT_SYMBOL(vmbus_sendpacket);

/*
* vmbus_sendpacket_pagebuffer - Send a range of single-page buffer
* packets using a GPADL Direct packet type. This interface allows you
* to control notifying the host. This will be useful for sending
* batched data. Also the sender can control the send flags
* explicitly.
*/
int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
struct hv_page_buffer pagebuffers[],
u32 pagecount, void *buffer, u32 bufferlen,
u64 requestid)
{
int i;
struct vmbus_channel_packet_page_buffer desc;
u32 descsize;
u32 packetlen;
u32 packetlen_aligned;
struct kvec bufferlist[3];
u64 aligned_data = 0;

if (pagecount > MAX_PAGE_BUFFER_COUNT)
return -EINVAL;

/*
* Adjust the size down since vmbus_channel_packet_page_buffer is the
* largest size we support
*/
descsize = sizeof(struct vmbus_channel_packet_page_buffer) -
((MAX_PAGE_BUFFER_COUNT - pagecount) *
sizeof(struct hv_page_buffer));
packetlen = descsize + bufferlen;
packetlen_aligned = ALIGN(packetlen, sizeof(u64));

/* Setup the descriptor */
desc.type = VM_PKT_DATA_USING_GPA_DIRECT;
desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
desc.dataoffset8 = descsize >> 3; /* in 8-bytes granularity */
desc.length8 = (u16)(packetlen_aligned >> 3);
desc.transactionid = VMBUS_RQST_ERROR; /* will be updated in hv_ringbuffer_write() */
desc.reserved = 0;
desc.rangecount = pagecount;

for (i = 0; i < pagecount; i++) {
desc.range[i].len = pagebuffers[i].len;
desc.range[i].offset = pagebuffers[i].offset;
desc.range[i].pfn = pagebuffers[i].pfn;
}

bufferlist[0].iov_base = &desc;
bufferlist[0].iov_len = descsize;
bufferlist[1].iov_base = buffer;
bufferlist[1].iov_len = bufferlen;
bufferlist[2].iov_base = &aligned_data;
bufferlist[2].iov_len = (packetlen_aligned - packetlen);

return hv_ringbuffer_write(channel, bufferlist, 3, requestid, NULL);
}
EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer);

/*
* vmbus_sendpacket_multipagebuffer - Send a multi-page buffer packet
* vmbus_sendpacket_mpb_desc - Send one or more multi-page buffer packets
* using a GPADL Direct packet type.
* The buffer includes the vmbus descriptor.
* The desc argument must include space for the VMBus descriptor. The
* rangecount field must already be set.
*/
int vmbus_sendpacket_mpb_desc(struct vmbus_channel *channel,
struct vmbus_packet_mpb_array *desc,
Expand All @@ -1160,7 +1102,6 @@ int vmbus_sendpacket_mpb_desc(struct vmbus_channel *channel,
desc->length8 = (u16)(packetlen_aligned >> 3);
desc->transactionid = VMBUS_RQST_ERROR; /* will be updated in hv_ringbuffer_write() */
desc->reserved = 0;
desc->rangecount = 1;

bufferlist[0].iov_base = desc;
bufferlist[0].iov_len = desc_size;
Expand Down
54 changes: 48 additions & 6 deletions drivers/infiniband/hw/mana/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,38 @@ static const struct ib_device_ops mana_ib_dev_ops = {
ib_ind_table),
};

static int mana_ib_netdev_event(struct notifier_block *this,
unsigned long event, void *ptr)
{
struct mana_ib_dev *dev = container_of(this, struct mana_ib_dev, nb);
struct net_device *event_dev = netdev_notifier_info_to_dev(ptr);
struct gdma_context *gc = dev->gdma_dev->gdma_context;
struct mana_context *mc = gc->mana.driver_data;
struct net_device *ndev;

/* Only process events from our parent device */
if (event_dev != mc->ports[0])
return NOTIFY_DONE;

switch (event) {
case NETDEV_CHANGEUPPER:
ndev = mana_get_primary_netdev(mc, 0, &dev->dev_tracker);
/*
* RDMA core will setup GID based on updated netdev.
* It's not possible to race with the core as rtnl lock is being
* held.
*/
ib_device_set_netdev(&dev->ib_dev, ndev, 1);

/* mana_get_primary_netdev() returns ndev with refcount held */
netdev_put(ndev, &dev->dev_tracker);

return NOTIFY_OK;
default:
return NOTIFY_DONE;
}
}

static int mana_ib_probe(struct auxiliary_device *adev,
const struct auxiliary_device_id *id)
{
Expand Down Expand Up @@ -84,18 +116,17 @@ static int mana_ib_probe(struct auxiliary_device *adev,
dev->ib_dev.num_comp_vectors = mdev->gdma_context->max_num_queues;
dev->ib_dev.dev.parent = mdev->gdma_context->dev;

rcu_read_lock(); /* required to get primary netdev */
ndev = mana_get_primary_netdev_rcu(mc, 0);
ndev = mana_get_primary_netdev(mc, 0, &dev->dev_tracker);
if (!ndev) {
rcu_read_unlock();
ret = -ENODEV;
ibdev_err(&dev->ib_dev, "Failed to get netdev for IB port 1");
goto free_ib_device;
}
ether_addr_copy(mac_addr, ndev->dev_addr);
addrconf_addr_eui48((u8 *)&dev->ib_dev.node_guid, ndev->dev_addr);
ret = ib_device_set_netdev(&dev->ib_dev, ndev, 1);
rcu_read_unlock();
/* mana_get_primary_netdev() returns ndev with refcount held */
netdev_put(ndev, &dev->dev_tracker);
if (ret) {
ibdev_err(&dev->ib_dev, "Failed to set ib netdev, ret %d", ret);
goto free_ib_device;
Expand All @@ -109,17 +140,25 @@ static int mana_ib_probe(struct auxiliary_device *adev,
}
dev->gdma_dev = &mdev->gdma_context->mana_ib;

dev->nb.notifier_call = mana_ib_netdev_event;
ret = register_netdevice_notifier(&dev->nb);
if (ret) {
ibdev_err(&dev->ib_dev, "Failed to register net notifier, %d",
ret);
goto deregister_device;
}

ret = mana_ib_gd_query_adapter_caps(dev);
if (ret) {
ibdev_err(&dev->ib_dev, "Failed to query device caps, ret %d",
ret);
goto deregister_device;
goto deregister_net_notifier;
}

ret = mana_ib_create_eqs(dev);
if (ret) {
ibdev_err(&dev->ib_dev, "Failed to create EQs, ret %d", ret);
goto deregister_device;
goto deregister_net_notifier;
}

ret = mana_ib_gd_create_rnic_adapter(dev);
Expand Down Expand Up @@ -148,6 +187,8 @@ static int mana_ib_probe(struct auxiliary_device *adev,
mana_ib_gd_destroy_rnic_adapter(dev);
destroy_eqs:
mana_ib_destroy_eqs(dev);
deregister_net_notifier:
unregister_netdevice_notifier(&dev->nb);
deregister_device:
mana_gd_deregister_device(dev->gdma_dev);
free_ib_device:
Expand All @@ -163,6 +204,7 @@ static void mana_ib_remove(struct auxiliary_device *adev)
xa_destroy(&dev->qp_table_wq);
mana_ib_gd_destroy_rnic_adapter(dev);
mana_ib_destroy_eqs(dev);
unregister_netdevice_notifier(&dev->nb);
mana_gd_deregister_device(dev->gdma_dev);
ib_dealloc_device(&dev->ib_dev);
}
Expand Down
2 changes: 2 additions & 0 deletions drivers/infiniband/hw/mana/mana_ib.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ struct mana_ib_dev {
struct gdma_queue **eqs;
struct xarray qp_table_wq;
struct mana_ib_adapter_caps adapter_caps;
netdevice_tracker dev_tracker;
struct notifier_block nb;
};

struct mana_ib_wq {
Expand Down
64 changes: 52 additions & 12 deletions drivers/net/ethernet/microsoft/mana/gdma_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,10 @@ static int mana_gd_detect_devices(struct pci_dev *pdev)
struct gdma_list_devices_resp resp = {};
struct gdma_general_req req = {};
struct gdma_dev_id dev;
u32 i, max_num_devs;
int found_dev = 0;
u16 dev_type;
int err;
u32 i;

mana_gd_init_req_hdr(&req.hdr, GDMA_LIST_DEVICES, sizeof(req),
sizeof(resp));
Expand All @@ -148,12 +149,17 @@ static int mana_gd_detect_devices(struct pci_dev *pdev)
return err ? err : -EPROTO;
}

max_num_devs = min_t(u32, MAX_NUM_GDMA_DEVICES, resp.num_of_devs);

for (i = 0; i < max_num_devs; i++) {
for (i = 0; i < GDMA_DEV_LIST_SIZE &&
found_dev < resp.num_of_devs; i++) {
dev = resp.devs[i];
dev_type = dev.type;

/* Skip empty devices */
if (dev.as_uint32 == 0)
continue;

found_dev++;

/* HWC is already detected in mana_hwc_create_channel(). */
if (dev_type == GDMA_DEVICE_HWC)
continue;
Expand Down Expand Up @@ -666,8 +672,11 @@ int mana_gd_create_hwc_queue(struct gdma_dev *gd,

gmi = &queue->mem_info;
err = mana_gd_alloc_memory(gc, spec->queue_size, gmi);
if (err)
if (err) {
dev_err(gc->dev, "GDMA queue type: %d, size: %u, gdma memory allocation err: %d\n",
spec->type, spec->queue_size, err);
goto free_q;
}

queue->head = 0;
queue->tail = 0;
Expand All @@ -688,6 +697,8 @@ int mana_gd_create_hwc_queue(struct gdma_dev *gd,
*queue_ptr = queue;
return 0;
out:
dev_err(gc->dev, "Failed to create queue type %d of size %u, err: %d\n",
spec->type, spec->queue_size, err);
mana_gd_free_memory(gmi);
free_q:
kfree(queue);
Expand Down Expand Up @@ -770,7 +781,13 @@ static int mana_gd_create_dma_region(struct gdma_dev *gd,
}

gmi->dma_region_handle = resp.dma_region_handle;
dev_dbg(gc->dev, "Created DMA region handle 0x%llx\n",
gmi->dma_region_handle);
out:
if (err)
dev_dbg(gc->dev,
"Failed to create DMA region of length: %u, page_type: %d, status: 0x%x, err: %d\n",
length, req->gdma_page_type, resp.hdr.status, err);
kfree(req);
return err;
}
Expand All @@ -793,8 +810,11 @@ int mana_gd_create_mana_eq(struct gdma_dev *gd,

gmi = &queue->mem_info;
err = mana_gd_alloc_memory(gc, spec->queue_size, gmi);
if (err)
if (err) {
dev_err(gc->dev, "GDMA queue type: %d, size: %u, gdma memory allocation err: %d\n",
spec->type, spec->queue_size, err);
goto free_q;
}

err = mana_gd_create_dma_region(gd, gmi);
if (err)
Expand All @@ -815,6 +835,8 @@ int mana_gd_create_mana_eq(struct gdma_dev *gd,
*queue_ptr = queue;
return 0;
out:
dev_err(gc->dev, "Failed to create queue type %d of size: %u, err: %d\n",
spec->type, spec->queue_size, err);
mana_gd_free_memory(gmi);
free_q:
kfree(queue);
Expand All @@ -841,8 +863,11 @@ int mana_gd_create_mana_wq_cq(struct gdma_dev *gd,

gmi = &queue->mem_info;
err = mana_gd_alloc_memory(gc, spec->queue_size, gmi);
if (err)
if (err) {
dev_err(gc->dev, "GDMA queue type: %d, size: %u, memory allocation err: %d\n",
spec->type, spec->queue_size, err);
goto free_q;
}

err = mana_gd_create_dma_region(gd, gmi);
if (err)
Expand All @@ -862,6 +887,8 @@ int mana_gd_create_mana_wq_cq(struct gdma_dev *gd,
*queue_ptr = queue;
return 0;
out:
dev_err(gc->dev, "Failed to create queue type %d of size: %u, err: %d\n",
spec->type, spec->queue_size, err);
mana_gd_free_memory(gmi);
free_q:
kfree(queue);
Expand Down Expand Up @@ -1157,8 +1184,11 @@ int mana_gd_post_and_ring(struct gdma_queue *queue,
int err;

err = mana_gd_post_work_request(queue, wqe_req, wqe_info);
if (err)
if (err) {
dev_err(gc->dev, "Failed to post work req from queue type %d of size %u (err=%d)\n",
queue->type, queue->queue_size, err);
return err;
}

mana_gd_wq_ring_doorbell(gc, queue);

Expand Down Expand Up @@ -1435,8 +1465,10 @@ static int mana_gd_setup(struct pci_dev *pdev)
mana_smc_init(&gc->shm_channel, gc->dev, gc->shm_base);

err = mana_gd_setup_irqs(pdev);
if (err)
if (err) {
dev_err(gc->dev, "Failed to setup IRQs: %d\n", err);
return err;
}

err = mana_hwc_create_channel(gc);
if (err)
Expand All @@ -1454,12 +1486,14 @@ static int mana_gd_setup(struct pci_dev *pdev)
if (err)
goto destroy_hwc;

dev_dbg(&pdev->dev, "mana gdma setup successful\n");
return 0;

destroy_hwc:
mana_hwc_destroy_channel(gc);
remove_irq:
mana_gd_remove_irqs(pdev);
dev_err(&pdev->dev, "%s failed (error %d)\n", __func__, err);
return err;
}

Expand All @@ -1470,6 +1504,7 @@ static void mana_gd_cleanup(struct pci_dev *pdev)
mana_hwc_destroy_channel(gc);

mana_gd_remove_irqs(pdev);
dev_dbg(&pdev->dev, "mana gdma cleanup successful\n");
}

static bool mana_is_pf(unsigned short dev_id)
Expand All @@ -1488,8 +1523,10 @@ static int mana_gd_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
BUILD_BUG_ON(2 * MAX_PORTS_IN_MANA_DEV * GDMA_EQE_SIZE > EQ_SIZE);

err = pci_enable_device(pdev);
if (err)
if (err) {
dev_err(&pdev->dev, "Failed to enable pci device (err=%d)\n", err);
return -ENXIO;
}

pci_set_master(pdev);

Expand All @@ -1498,9 +1535,10 @@ static int mana_gd_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto disable_dev;

err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
if (err)
if (err) {
dev_err(&pdev->dev, "DMA set mask failed: %d\n", err);
goto release_region;

}
dma_set_max_seg_size(&pdev->dev, UINT_MAX);

err = -ENOMEM;
Expand Down Expand Up @@ -1578,6 +1616,8 @@ static void mana_gd_remove(struct pci_dev *pdev)

pci_release_regions(pdev);
pci_disable_device(pdev);

dev_dbg(&pdev->dev, "mana gdma remove successful\n");
}

/* The 'state' parameter is not used. */
Expand Down
Loading