mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-01 06:33:07 +00:00
Merge branch 'ionic-FLR-support'
Shannon Nelson says: ==================== ionic: add FLR support Add support for handing and recovering from a PCI FLR event. This patchset first moves some code around to make it usable from multiple paths, then adds the PCI error handler callbacks for reset_prepare and reset_done. Example test: echo 1 > /sys/bus/pci/devices/0000:2a:00.0/reset v4: - don't remove ionic_dev_teardown() in ionic_probe() in patch 2/4 - remove clear_bit() change from patch 3/4 v3: Link: https://lore.kernel.org/netdev/20230717170001.30539-1-shannon.nelson@amd.com/ - removed first patch, it is already merged into net v2: Link: https://lore.kernel.org/netdev/20230713192936.45152-1-shannon.nelson@amd.com/ - removed redundant pci_save/restore_state() calls ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
5322a27c0d
3 changed files with 190 additions and 97 deletions
|
@ -213,6 +213,85 @@ static int ionic_sriov_configure(struct pci_dev *pdev, int num_vfs)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void ionic_clear_pci(struct ionic *ionic)
|
||||
{
|
||||
ionic_unmap_bars(ionic);
|
||||
pci_release_regions(ionic->pdev);
|
||||
pci_disable_device(ionic->pdev);
|
||||
}
|
||||
|
||||
static int ionic_setup_one(struct ionic *ionic)
|
||||
{
|
||||
struct pci_dev *pdev = ionic->pdev;
|
||||
struct device *dev = ionic->dev;
|
||||
int err;
|
||||
|
||||
ionic_debugfs_add_dev(ionic);
|
||||
|
||||
/* Setup PCI device */
|
||||
err = pci_enable_device_mem(pdev);
|
||||
if (err) {
|
||||
dev_err(dev, "Cannot enable PCI device: %d, aborting\n", err);
|
||||
goto err_out_debugfs_del_dev;
|
||||
}
|
||||
|
||||
err = pci_request_regions(pdev, IONIC_DRV_NAME);
|
||||
if (err) {
|
||||
dev_err(dev, "Cannot request PCI regions: %d, aborting\n", err);
|
||||
goto err_out_clear_pci;
|
||||
}
|
||||
pcie_print_link_status(pdev);
|
||||
|
||||
err = ionic_map_bars(ionic);
|
||||
if (err)
|
||||
goto err_out_clear_pci;
|
||||
|
||||
/* Configure the device */
|
||||
err = ionic_setup(ionic);
|
||||
if (err) {
|
||||
dev_err(dev, "Cannot setup device: %d, aborting\n", err);
|
||||
goto err_out_clear_pci;
|
||||
}
|
||||
pci_set_master(pdev);
|
||||
|
||||
err = ionic_identify(ionic);
|
||||
if (err) {
|
||||
dev_err(dev, "Cannot identify device: %d, aborting\n", err);
|
||||
goto err_out_teardown;
|
||||
}
|
||||
ionic_debugfs_add_ident(ionic);
|
||||
|
||||
err = ionic_init(ionic);
|
||||
if (err) {
|
||||
dev_err(dev, "Cannot init device: %d, aborting\n", err);
|
||||
goto err_out_teardown;
|
||||
}
|
||||
|
||||
/* Configure the port */
|
||||
err = ionic_port_identify(ionic);
|
||||
if (err) {
|
||||
dev_err(dev, "Cannot identify port: %d, aborting\n", err);
|
||||
goto err_out_teardown;
|
||||
}
|
||||
|
||||
err = ionic_port_init(ionic);
|
||||
if (err) {
|
||||
dev_err(dev, "Cannot init port: %d, aborting\n", err);
|
||||
goto err_out_teardown;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_out_teardown:
|
||||
ionic_dev_teardown(ionic);
|
||||
err_out_clear_pci:
|
||||
ionic_clear_pci(ionic);
|
||||
err_out_debugfs_del_dev:
|
||||
ionic_debugfs_del_dev(ionic);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ionic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
|
@ -234,69 +313,18 @@ static int ionic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
if (err) {
|
||||
dev_err(dev, "Unable to obtain 64-bit DMA for consistent allocations, aborting. err=%d\n",
|
||||
err);
|
||||
goto err_out_clear_drvdata;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
ionic_debugfs_add_dev(ionic);
|
||||
|
||||
/* Setup PCI device */
|
||||
err = pci_enable_device_mem(pdev);
|
||||
if (err) {
|
||||
dev_err(dev, "Cannot enable PCI device: %d, aborting\n", err);
|
||||
goto err_out_debugfs_del_dev;
|
||||
}
|
||||
|
||||
err = pci_request_regions(pdev, IONIC_DRV_NAME);
|
||||
if (err) {
|
||||
dev_err(dev, "Cannot request PCI regions: %d, aborting\n", err);
|
||||
goto err_out_pci_disable_device;
|
||||
}
|
||||
|
||||
pcie_print_link_status(pdev);
|
||||
|
||||
err = ionic_map_bars(ionic);
|
||||
err = ionic_setup_one(ionic);
|
||||
if (err)
|
||||
goto err_out_pci_release_regions;
|
||||
|
||||
/* Configure the device */
|
||||
err = ionic_setup(ionic);
|
||||
if (err) {
|
||||
dev_err(dev, "Cannot setup device: %d, aborting\n", err);
|
||||
goto err_out_unmap_bars;
|
||||
}
|
||||
pci_set_master(pdev);
|
||||
|
||||
err = ionic_identify(ionic);
|
||||
if (err) {
|
||||
dev_err(dev, "Cannot identify device: %d, aborting\n", err);
|
||||
goto err_out_teardown;
|
||||
}
|
||||
ionic_debugfs_add_ident(ionic);
|
||||
|
||||
err = ionic_init(ionic);
|
||||
if (err) {
|
||||
dev_err(dev, "Cannot init device: %d, aborting\n", err);
|
||||
goto err_out_teardown;
|
||||
}
|
||||
|
||||
/* Configure the ports */
|
||||
err = ionic_port_identify(ionic);
|
||||
if (err) {
|
||||
dev_err(dev, "Cannot identify port: %d, aborting\n", err);
|
||||
goto err_out_reset;
|
||||
}
|
||||
|
||||
err = ionic_port_init(ionic);
|
||||
if (err) {
|
||||
dev_err(dev, "Cannot init port: %d, aborting\n", err);
|
||||
goto err_out_reset;
|
||||
}
|
||||
goto err_out;
|
||||
|
||||
/* Allocate and init the LIF */
|
||||
err = ionic_lif_size(ionic);
|
||||
if (err) {
|
||||
dev_err(dev, "Cannot size LIF: %d, aborting\n", err);
|
||||
goto err_out_port_reset;
|
||||
goto err_out_pci;
|
||||
}
|
||||
|
||||
err = ionic_lif_alloc(ionic);
|
||||
|
@ -347,21 +375,10 @@ static int ionic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
ionic->lif = NULL;
|
||||
err_out_free_irqs:
|
||||
ionic_bus_free_irq_vectors(ionic);
|
||||
err_out_port_reset:
|
||||
ionic_port_reset(ionic);
|
||||
err_out_reset:
|
||||
ionic_reset(ionic);
|
||||
err_out_teardown:
|
||||
err_out_pci:
|
||||
ionic_dev_teardown(ionic);
|
||||
err_out_unmap_bars:
|
||||
ionic_unmap_bars(ionic);
|
||||
err_out_pci_release_regions:
|
||||
pci_release_regions(pdev);
|
||||
err_out_pci_disable_device:
|
||||
pci_disable_device(pdev);
|
||||
err_out_debugfs_del_dev:
|
||||
ionic_debugfs_del_dev(ionic);
|
||||
err_out_clear_drvdata:
|
||||
ionic_clear_pci(ionic);
|
||||
err_out:
|
||||
mutex_destroy(&ionic->dev_cmd_lock);
|
||||
ionic_devlink_free(ionic);
|
||||
|
||||
|
@ -386,20 +403,71 @@ static void ionic_remove(struct pci_dev *pdev)
|
|||
ionic_port_reset(ionic);
|
||||
ionic_reset(ionic);
|
||||
ionic_dev_teardown(ionic);
|
||||
ionic_unmap_bars(ionic);
|
||||
pci_release_regions(pdev);
|
||||
pci_disable_device(pdev);
|
||||
ionic_clear_pci(ionic);
|
||||
ionic_debugfs_del_dev(ionic);
|
||||
mutex_destroy(&ionic->dev_cmd_lock);
|
||||
ionic_devlink_free(ionic);
|
||||
}
|
||||
|
||||
static void ionic_reset_prepare(struct pci_dev *pdev)
|
||||
{
|
||||
struct ionic *ionic = pci_get_drvdata(pdev);
|
||||
struct ionic_lif *lif = ionic->lif;
|
||||
|
||||
dev_dbg(ionic->dev, "%s: device stopping\n", __func__);
|
||||
|
||||
del_timer_sync(&ionic->watchdog_timer);
|
||||
cancel_work_sync(&lif->deferred.work);
|
||||
|
||||
mutex_lock(&lif->queue_lock);
|
||||
ionic_stop_queues_reconfig(lif);
|
||||
ionic_txrx_free(lif);
|
||||
ionic_lif_deinit(lif);
|
||||
ionic_qcqs_free(lif);
|
||||
mutex_unlock(&lif->queue_lock);
|
||||
|
||||
ionic_dev_teardown(ionic);
|
||||
ionic_clear_pci(ionic);
|
||||
ionic_debugfs_del_dev(ionic);
|
||||
}
|
||||
|
||||
static void ionic_reset_done(struct pci_dev *pdev)
|
||||
{
|
||||
struct ionic *ionic = pci_get_drvdata(pdev);
|
||||
struct ionic_lif *lif = ionic->lif;
|
||||
int err;
|
||||
|
||||
err = ionic_setup_one(ionic);
|
||||
if (err)
|
||||
goto err_out;
|
||||
|
||||
ionic_debugfs_add_sizes(ionic);
|
||||
ionic_debugfs_add_lif(ionic->lif);
|
||||
|
||||
err = ionic_restart_lif(lif);
|
||||
if (err)
|
||||
goto err_out;
|
||||
|
||||
mod_timer(&ionic->watchdog_timer, jiffies + 1);
|
||||
|
||||
err_out:
|
||||
dev_dbg(ionic->dev, "%s: device recovery %s\n",
|
||||
__func__, err ? "failed" : "done");
|
||||
}
|
||||
|
||||
static const struct pci_error_handlers ionic_err_handler = {
|
||||
/* FLR handling */
|
||||
.reset_prepare = ionic_reset_prepare,
|
||||
.reset_done = ionic_reset_done,
|
||||
};
|
||||
|
||||
static struct pci_driver ionic_driver = {
|
||||
.name = IONIC_DRV_NAME,
|
||||
.id_table = ionic_id_table,
|
||||
.probe = ionic_probe,
|
||||
.remove = ionic_remove,
|
||||
.sriov_configure = ionic_sriov_configure,
|
||||
.err_handler = &ionic_err_handler
|
||||
};
|
||||
|
||||
int ionic_bus_register_driver(void)
|
||||
|
|
|
@ -434,7 +434,7 @@ static void ionic_qcq_free(struct ionic_lif *lif, struct ionic_qcq *qcq)
|
|||
}
|
||||
}
|
||||
|
||||
static void ionic_qcqs_free(struct ionic_lif *lif)
|
||||
void ionic_qcqs_free(struct ionic_lif *lif)
|
||||
{
|
||||
struct device *dev = lif->ionic->dev;
|
||||
struct ionic_qcq *adminqcq;
|
||||
|
@ -1754,7 +1754,7 @@ static int ionic_set_mac_address(struct net_device *netdev, void *sa)
|
|||
return ionic_lif_addr_add(netdev_priv(netdev), mac);
|
||||
}
|
||||
|
||||
static void ionic_stop_queues_reconfig(struct ionic_lif *lif)
|
||||
void ionic_stop_queues_reconfig(struct ionic_lif *lif)
|
||||
{
|
||||
/* Stop and clean the queues before reconfiguration */
|
||||
netif_device_detach(lif->netdev);
|
||||
|
@ -2009,7 +2009,7 @@ static void ionic_txrx_deinit(struct ionic_lif *lif)
|
|||
}
|
||||
}
|
||||
|
||||
static void ionic_txrx_free(struct ionic_lif *lif)
|
||||
void ionic_txrx_free(struct ionic_lif *lif)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
|
@ -3266,27 +3266,11 @@ static void ionic_lif_handle_fw_down(struct ionic_lif *lif)
|
|||
dev_info(ionic->dev, "FW Down: LIFs stopped\n");
|
||||
}
|
||||
|
||||
static void ionic_lif_handle_fw_up(struct ionic_lif *lif)
|
||||
int ionic_restart_lif(struct ionic_lif *lif)
|
||||
{
|
||||
struct ionic *ionic = lif->ionic;
|
||||
int err;
|
||||
|
||||
if (!test_bit(IONIC_LIF_F_FW_RESET, lif->state))
|
||||
return;
|
||||
|
||||
dev_info(ionic->dev, "FW Up: restarting LIFs\n");
|
||||
|
||||
ionic_init_devinfo(ionic);
|
||||
err = ionic_identify(ionic);
|
||||
if (err)
|
||||
goto err_out;
|
||||
err = ionic_port_identify(ionic);
|
||||
if (err)
|
||||
goto err_out;
|
||||
err = ionic_port_init(ionic);
|
||||
if (err)
|
||||
goto err_out;
|
||||
|
||||
mutex_lock(&lif->queue_lock);
|
||||
|
||||
if (test_and_clear_bit(IONIC_LIF_F_BROKEN, lif->state))
|
||||
|
@ -3322,12 +3306,8 @@ static void ionic_lif_handle_fw_up(struct ionic_lif *lif)
|
|||
clear_bit(IONIC_LIF_F_FW_RESET, lif->state);
|
||||
ionic_link_status_check_request(lif, CAN_SLEEP);
|
||||
netif_device_attach(lif->netdev);
|
||||
dev_info(ionic->dev, "FW Up: LIFs restarted\n");
|
||||
|
||||
/* restore the hardware timestamping queues */
|
||||
ionic_lif_hwstamp_replay(lif);
|
||||
|
||||
return;
|
||||
return 0;
|
||||
|
||||
err_txrx_free:
|
||||
ionic_txrx_free(lif);
|
||||
|
@ -3337,6 +3317,46 @@ static void ionic_lif_handle_fw_up(struct ionic_lif *lif)
|
|||
ionic_qcqs_free(lif);
|
||||
err_unlock:
|
||||
mutex_unlock(&lif->queue_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void ionic_lif_handle_fw_up(struct ionic_lif *lif)
|
||||
{
|
||||
struct ionic *ionic = lif->ionic;
|
||||
int err;
|
||||
|
||||
if (!test_bit(IONIC_LIF_F_FW_RESET, lif->state))
|
||||
return;
|
||||
|
||||
dev_info(ionic->dev, "FW Up: restarting LIFs\n");
|
||||
|
||||
/* This is a little different from what happens at
|
||||
* probe time because the LIF already exists so we
|
||||
* just need to reanimate it.
|
||||
*/
|
||||
ionic_init_devinfo(ionic);
|
||||
err = ionic_identify(ionic);
|
||||
if (err)
|
||||
goto err_out;
|
||||
err = ionic_port_identify(ionic);
|
||||
if (err)
|
||||
goto err_out;
|
||||
err = ionic_port_init(ionic);
|
||||
if (err)
|
||||
goto err_out;
|
||||
|
||||
err = ionic_restart_lif(lif);
|
||||
if (err)
|
||||
goto err_out;
|
||||
|
||||
dev_info(ionic->dev, "FW Up: LIFs restarted\n");
|
||||
|
||||
/* restore the hardware timestamping queues */
|
||||
ionic_lif_hwstamp_replay(lif);
|
||||
|
||||
return;
|
||||
|
||||
err_out:
|
||||
dev_err(ionic->dev, "FW Up: LIFs restart failed - err %d\n", err);
|
||||
}
|
||||
|
|
|
@ -325,6 +325,11 @@ void ionic_lif_deinit(struct ionic_lif *lif);
|
|||
int ionic_lif_addr_add(struct ionic_lif *lif, const u8 *addr);
|
||||
int ionic_lif_addr_del(struct ionic_lif *lif, const u8 *addr);
|
||||
|
||||
void ionic_stop_queues_reconfig(struct ionic_lif *lif);
|
||||
void ionic_txrx_free(struct ionic_lif *lif);
|
||||
void ionic_qcqs_free(struct ionic_lif *lif);
|
||||
int ionic_restart_lif(struct ionic_lif *lif);
|
||||
|
||||
int ionic_lif_register(struct ionic_lif *lif);
|
||||
void ionic_lif_unregister(struct ionic_lif *lif);
|
||||
int ionic_lif_identify(struct ionic *ionic, u8 lif_type,
|
||||
|
|
Loading…
Reference in a new issue