Skip to content

Commit

Permalink
Merge branch 'mana-misc'
Browse files Browse the repository at this point in the history
Dexuan Cui says:

====================
net: mana: some misc patches

Patch 1 is a small fix.

Patch 2 reports OS info to the PF driver.
Before the patch, the req fields were all zeros.

Patch 3 fixes and cleans up the error handling of HWC creation failure.

Patch 4 adds the callbacks for hibernation/kexec. It's based on patch 3.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Nov 1, 2021
2 parents 986d2e3 + 635096a commit c6e03db
Show file tree
Hide file tree
Showing 4 changed files with 208 additions and 97 deletions.
155 changes: 117 additions & 38 deletions drivers/net/ethernet/microsoft/mana/gdma_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

#include <linux/module.h>
#include <linux/pci.h>
#include <linux/utsname.h>
#include <linux/version.h>

#include "mana.h"

Expand Down Expand Up @@ -848,6 +850,15 @@ int mana_gd_verify_vf_version(struct pci_dev *pdev)
req.gd_drv_cap_flags3 = GDMA_DRV_CAP_FLAGS3;
req.gd_drv_cap_flags4 = GDMA_DRV_CAP_FLAGS4;

req.drv_ver = 0; /* Unused*/
req.os_type = 0x10; /* Linux */
req.os_ver_major = LINUX_VERSION_MAJOR;
req.os_ver_minor = LINUX_VERSION_PATCHLEVEL;
req.os_ver_build = LINUX_VERSION_SUBLEVEL;
strscpy(req.os_ver_str1, utsname()->sysname, sizeof(req.os_ver_str1));
strscpy(req.os_ver_str2, utsname()->release, sizeof(req.os_ver_str2));
strscpy(req.os_ver_str3, utsname()->version, sizeof(req.os_ver_str3));

err = mana_gd_send_request(gc, sizeof(req), &req, sizeof(resp), &resp);
if (err || resp.hdr.status) {
dev_err(gc->dev, "VfVerifyVersionOutput: %d, status=0x%x\n",
Expand Down Expand Up @@ -1247,6 +1258,52 @@ static void mana_gd_remove_irqs(struct pci_dev *pdev)
gc->irq_contexts = NULL;
}

static int mana_gd_setup(struct pci_dev *pdev)
{
struct gdma_context *gc = pci_get_drvdata(pdev);
int err;

mana_gd_init_registers(pdev);
mana_smc_init(&gc->shm_channel, gc->dev, gc->shm_base);

err = mana_gd_setup_irqs(pdev);
if (err)
return err;

err = mana_hwc_create_channel(gc);
if (err)
goto remove_irq;

err = mana_gd_verify_vf_version(pdev);
if (err)
goto destroy_hwc;

err = mana_gd_query_max_resources(pdev);
if (err)
goto destroy_hwc;

err = mana_gd_detect_devices(pdev);
if (err)
goto destroy_hwc;

return 0;

destroy_hwc:
mana_hwc_destroy_channel(gc);
remove_irq:
mana_gd_remove_irqs(pdev);
return err;
}

static void mana_gd_cleanup(struct pci_dev *pdev)
{
struct gdma_context *gc = pci_get_drvdata(pdev);

mana_hwc_destroy_channel(gc);

mana_gd_remove_irqs(pdev);
}

static int mana_gd_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct gdma_context *gc;
Expand Down Expand Up @@ -1276,56 +1333,33 @@ static int mana_gd_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (!gc)
goto release_region;

mutex_init(&gc->eq_test_event_mutex);
pci_set_drvdata(pdev, gc);

bar0_va = pci_iomap(pdev, bar, 0);
if (!bar0_va)
goto free_gc;

gc->bar0_va = bar0_va;
gc->dev = &pdev->dev;

pci_set_drvdata(pdev, gc);

mana_gd_init_registers(pdev);

mana_smc_init(&gc->shm_channel, gc->dev, gc->shm_base);

err = mana_gd_setup_irqs(pdev);
err = mana_gd_setup(pdev);
if (err)
goto unmap_bar;

mutex_init(&gc->eq_test_event_mutex);

err = mana_hwc_create_channel(gc);
if (err)
goto remove_irq;

err = mana_gd_verify_vf_version(pdev);
if (err)
goto remove_irq;

err = mana_gd_query_max_resources(pdev);
if (err)
goto remove_irq;

err = mana_gd_detect_devices(pdev);
err = mana_probe(&gc->mana, false);
if (err)
goto remove_irq;

err = mana_probe(&gc->mana);
if (err)
goto clean_up_gdma;
goto cleanup_gd;

return 0;

clean_up_gdma:
mana_hwc_destroy_channel(gc);
vfree(gc->cq_table);
gc->cq_table = NULL;
remove_irq:
mana_gd_remove_irqs(pdev);
cleanup_gd:
mana_gd_cleanup(pdev);
unmap_bar:
pci_iounmap(pdev, bar0_va);
free_gc:
pci_set_drvdata(pdev, NULL);
vfree(gc);
release_region:
pci_release_regions(pdev);
Expand All @@ -1340,13 +1374,9 @@ static void mana_gd_remove(struct pci_dev *pdev)
{
struct gdma_context *gc = pci_get_drvdata(pdev);

mana_remove(&gc->mana);
mana_remove(&gc->mana, false);

mana_hwc_destroy_channel(gc);
vfree(gc->cq_table);
gc->cq_table = NULL;

mana_gd_remove_irqs(pdev);
mana_gd_cleanup(pdev);

pci_iounmap(pdev, gc->bar0_va);

Expand All @@ -1357,6 +1387,52 @@ static void mana_gd_remove(struct pci_dev *pdev)
pci_disable_device(pdev);
}

/* The 'state' parameter is not used. */
static int mana_gd_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct gdma_context *gc = pci_get_drvdata(pdev);

mana_remove(&gc->mana, true);

mana_gd_cleanup(pdev);

return 0;
}

/* In case the NIC hardware stops working, the suspend and resume callbacks will
* fail -- if this happens, it's safer to just report an error than try to undo
* what has been done.
*/
static int mana_gd_resume(struct pci_dev *pdev)
{
struct gdma_context *gc = pci_get_drvdata(pdev);
int err;

err = mana_gd_setup(pdev);
if (err)
return err;

err = mana_probe(&gc->mana, true);
if (err)
return err;

return 0;
}

/* Quiesce the device for kexec. This is also called upon reboot/shutdown. */
static void mana_gd_shutdown(struct pci_dev *pdev)
{
struct gdma_context *gc = pci_get_drvdata(pdev);

dev_info(&pdev->dev, "Shutdown was calledd\n");

mana_remove(&gc->mana, true);

mana_gd_cleanup(pdev);

pci_disable_device(pdev);
}

#ifndef PCI_VENDOR_ID_MICROSOFT
#define PCI_VENDOR_ID_MICROSOFT 0x1414
#endif
Expand All @@ -1371,6 +1447,9 @@ static struct pci_driver mana_driver = {
.id_table = mana_id_table,
.probe = mana_gd_probe,
.remove = mana_gd_remove,
.suspend = mana_gd_suspend,
.resume = mana_gd_resume,
.shutdown = mana_gd_shutdown,
};

module_pci_driver(mana_driver);
Expand Down
71 changes: 31 additions & 40 deletions drivers/net/ethernet/microsoft/mana/hw_channel.c
Original file line number Diff line number Diff line change
Expand Up @@ -309,9 +309,6 @@ static void mana_hwc_comp_event(void *ctx, struct gdma_queue *q_self)

static void mana_hwc_destroy_cq(struct gdma_context *gc, struct hwc_cq *hwc_cq)
{
if (!hwc_cq)
return;

kfree(hwc_cq->comp_buf);

if (hwc_cq->gdma_cq)
Expand Down Expand Up @@ -446,9 +443,6 @@ static void mana_hwc_dealloc_dma_buf(struct hw_channel_context *hwc,
static void mana_hwc_destroy_wq(struct hw_channel_context *hwc,
struct hwc_wq *hwc_wq)
{
if (!hwc_wq)
return;

mana_hwc_dealloc_dma_buf(hwc, hwc_wq->msg_buf);

if (hwc_wq->gdma_wq)
Expand Down Expand Up @@ -621,6 +615,7 @@ static int mana_hwc_establish_channel(struct gdma_context *gc, u16 *q_depth,
*max_req_msg_size = hwc->hwc_init_max_req_msg_size;
*max_resp_msg_size = hwc->hwc_init_max_resp_msg_size;

/* Both were set in mana_hwc_init_event_handler(). */
if (WARN_ON(cq->id >= gc->max_num_cqs))
return -EPROTO;

Expand All @@ -636,9 +631,6 @@ static int mana_hwc_establish_channel(struct gdma_context *gc, u16 *q_depth,
static int mana_hwc_init_queues(struct hw_channel_context *hwc, u16 q_depth,
u32 max_req_msg_size, u32 max_resp_msg_size)
{
struct hwc_wq *hwc_rxq = NULL;
struct hwc_wq *hwc_txq = NULL;
struct hwc_cq *hwc_cq = NULL;
int err;

err = mana_hwc_init_inflight_msg(hwc, q_depth);
Expand All @@ -651,44 +643,32 @@ static int mana_hwc_init_queues(struct hw_channel_context *hwc, u16 q_depth,
err = mana_hwc_create_cq(hwc, q_depth * 2,
mana_hwc_init_event_handler, hwc,
mana_hwc_rx_event_handler, hwc,
mana_hwc_tx_event_handler, hwc, &hwc_cq);
mana_hwc_tx_event_handler, hwc, &hwc->cq);
if (err) {
dev_err(hwc->dev, "Failed to create HWC CQ: %d\n", err);
goto out;
}
hwc->cq = hwc_cq;

err = mana_hwc_create_wq(hwc, GDMA_RQ, q_depth, max_req_msg_size,
hwc_cq, &hwc_rxq);
hwc->cq, &hwc->rxq);
if (err) {
dev_err(hwc->dev, "Failed to create HWC RQ: %d\n", err);
goto out;
}
hwc->rxq = hwc_rxq;

err = mana_hwc_create_wq(hwc, GDMA_SQ, q_depth, max_resp_msg_size,
hwc_cq, &hwc_txq);
hwc->cq, &hwc->txq);
if (err) {
dev_err(hwc->dev, "Failed to create HWC SQ: %d\n", err);
goto out;
}
hwc->txq = hwc_txq;

hwc->num_inflight_msg = q_depth;
hwc->max_req_msg_size = max_req_msg_size;

return 0;
out:
if (hwc_txq)
mana_hwc_destroy_wq(hwc, hwc_txq);

if (hwc_rxq)
mana_hwc_destroy_wq(hwc, hwc_rxq);

if (hwc_cq)
mana_hwc_destroy_cq(hwc->gdma_dev->gdma_context, hwc_cq);

mana_gd_free_res_map(&hwc->inflight_msg_res);
/* mana_hwc_create_channel() will do the cleanup.*/
return err;
}

Expand Down Expand Up @@ -716,6 +696,9 @@ int mana_hwc_create_channel(struct gdma_context *gc)
gd->pdid = INVALID_PDID;
gd->doorbell = INVALID_DOORBELL;

/* mana_hwc_init_queues() only creates the required data structures,
* and doesn't touch the HWC device.
*/
err = mana_hwc_init_queues(hwc, HW_CHANNEL_VF_BOOTSTRAP_QUEUE_DEPTH,
HW_CHANNEL_MAX_REQUEST_SIZE,
HW_CHANNEL_MAX_RESPONSE_SIZE);
Expand All @@ -741,42 +724,50 @@ int mana_hwc_create_channel(struct gdma_context *gc)

return 0;
out:
kfree(hwc);
mana_hwc_destroy_channel(gc);
return err;
}

void mana_hwc_destroy_channel(struct gdma_context *gc)
{
struct hw_channel_context *hwc = gc->hwc.driver_data;
struct hwc_caller_ctx *ctx;

mana_smc_teardown_hwc(&gc->shm_channel, false);
if (!hwc)
return;

/* gc->max_num_cqs is set in mana_hwc_init_event_handler(). If it's
* non-zero, the HWC worked and we should tear down the HWC here.
*/
if (gc->max_num_cqs > 0) {
mana_smc_teardown_hwc(&gc->shm_channel, false);
gc->max_num_cqs = 0;
}

ctx = hwc->caller_ctx;
kfree(ctx);
kfree(hwc->caller_ctx);
hwc->caller_ctx = NULL;

mana_hwc_destroy_wq(hwc, hwc->txq);
hwc->txq = NULL;
if (hwc->txq)
mana_hwc_destroy_wq(hwc, hwc->txq);

mana_hwc_destroy_wq(hwc, hwc->rxq);
hwc->rxq = NULL;
if (hwc->rxq)
mana_hwc_destroy_wq(hwc, hwc->rxq);

mana_hwc_destroy_cq(hwc->gdma_dev->gdma_context, hwc->cq);
hwc->cq = NULL;
if (hwc->cq)
mana_hwc_destroy_cq(hwc->gdma_dev->gdma_context, hwc->cq);

mana_gd_free_res_map(&hwc->inflight_msg_res);

hwc->num_inflight_msg = 0;

if (hwc->gdma_dev->pdid != INVALID_PDID) {
hwc->gdma_dev->doorbell = INVALID_DOORBELL;
hwc->gdma_dev->pdid = INVALID_PDID;
}
hwc->gdma_dev->doorbell = INVALID_DOORBELL;
hwc->gdma_dev->pdid = INVALID_PDID;

kfree(hwc);
gc->hwc.driver_data = NULL;
gc->hwc.gdma_context = NULL;

vfree(gc->cq_table);
gc->cq_table = NULL;
}

int mana_hwc_send_request(struct hw_channel_context *hwc, u32 req_len,
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/ethernet/microsoft/mana/mana.h
Original file line number Diff line number Diff line change
Expand Up @@ -374,8 +374,8 @@ int mana_alloc_queues(struct net_device *ndev);
int mana_attach(struct net_device *ndev);
int mana_detach(struct net_device *ndev, bool from_close);

int mana_probe(struct gdma_dev *gd);
void mana_remove(struct gdma_dev *gd);
int mana_probe(struct gdma_dev *gd, bool resuming);
void mana_remove(struct gdma_dev *gd, bool suspending);

extern const struct ethtool_ops mana_ethtool_ops;

Expand Down
Loading

0 comments on commit c6e03db

Please sign in to comment.