Skip to content

Commit

Permalink
Merge branch 'hns3-add-code-optimization-for-VF-reset-and-some-new-re…
Browse files Browse the repository at this point in the history
…set-feature'

Huazhong Tan says:

====================
hns3: add code optimization for VF reset and some new reset feature

Currently hardware supports below reset:
1. VF reset: triggered by sending cmd to IMP(Integrated Management
   Processor). Only reset specific VF function and do not affect
   other PF or VF.
2. PF reset: triggered by sending cmd to IMP. Only reset specific PF
   and it's VF.
3. PF FLR: triggered by PCIe subsystem. Only reset specific PF and
   it's VF.
4. VF FLR: triggered by PCIe subsystem. Only reset specific VF function
   and do not affect other PF or VF.
5. Core reset: triggered by writing to register. Reset most hardware
   unit, such as SSU, which affects all the PF and VF.
6. Global reset: triggered by writing to register. Reset all hardware
   unit, which affects all the PF and VF.
7. IMP reset: triggered by IMU(Intelligent Management Unit) when
   IMP is not longer feeding IMU's watchdog. IMU will reload the IMP
   firmware and IMP will perform global reset after firmware reloading,
   which affects all the PF and VF.

Current driver only support PF/VF reset, incomplete core and global
reset(lacking the vf reset handling). So this patchset adds complete
reset support in hns3 driver.

Also, this patchset contains some optimization related to reset.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Nov 10, 2018
2 parents 40c4b1e + 6ff3cf0 commit 70e7983
Show file tree
Hide file tree
Showing 12 changed files with 638 additions and 164 deletions.
6 changes: 6 additions & 0 deletions drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,12 @@ struct hclge_mbx_pf_to_vf_cmd {
u16 msg[8];
};

struct hclge_vf_rst_cmd {
u8 dest_vfid;
u8 vf_rst;
u8 rsv[22];
};

/* used by VF to store the received Async responses from PF */
struct hclgevf_mbx_arq_ring {
#define HCLGE_MBX_MAX_ARQ_MSG_SIZE 8
Expand Down
11 changes: 10 additions & 1 deletion drivers/net/ethernet/hisilicon/hns3/hnae3.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,14 +124,22 @@ enum hnae3_reset_notify_type {

enum hnae3_reset_type {
HNAE3_VF_RESET,
HNAE3_VF_FUNC_RESET,
HNAE3_VF_PF_FUNC_RESET,
HNAE3_VF_FULL_RESET,
HNAE3_FLR_RESET,
HNAE3_FUNC_RESET,
HNAE3_CORE_RESET,
HNAE3_GLOBAL_RESET,
HNAE3_IMP_RESET,
HNAE3_NONE_RESET,
};

enum hnae3_flr_state {
HNAE3_FLR_DOWN,
HNAE3_FLR_DONE,
};

struct hnae3_vector_info {
u8 __iomem *io_addr;
int vector;
Expand Down Expand Up @@ -297,7 +305,8 @@ struct hnae3_ae_dev {
struct hnae3_ae_ops {
int (*init_ae_dev)(struct hnae3_ae_dev *ae_dev);
void (*uninit_ae_dev)(struct hnae3_ae_dev *ae_dev);

void (*flr_prepare)(struct hnae3_ae_dev *ae_dev);
void (*flr_done)(struct hnae3_ae_dev *ae_dev);
int (*init_client_instance)(struct hnae3_client *client,
struct hnae3_ae_dev *ae_dev);
void (*uninit_client_instance)(struct hnae3_client *client,
Expand Down
66 changes: 55 additions & 11 deletions drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
Original file line number Diff line number Diff line change
Expand Up @@ -415,9 +415,6 @@ static void hns3_nic_net_down(struct net_device *netdev)
const struct hnae3_ae_ops *ops;
int i;

if (test_and_set_bit(HNS3_NIC_STATE_DOWN, &priv->state))
return;

/* disable vectors */
for (i = 0; i < priv->vector_num; i++)
hns3_vector_disable(&priv->tqp_vector[i]);
Expand All @@ -439,6 +436,11 @@ static void hns3_nic_net_down(struct net_device *netdev)

static int hns3_nic_net_stop(struct net_device *netdev)
{
struct hns3_nic_priv *priv = netdev_priv(netdev);

if (test_and_set_bit(HNS3_NIC_STATE_DOWN, &priv->state))
return 0;

netif_tx_stop_all_queues(netdev);
netif_carrier_off(netdev);

Expand Down Expand Up @@ -1849,9 +1851,29 @@ static pci_ers_result_t hns3_slot_reset(struct pci_dev *pdev)
return PCI_ERS_RESULT_DISCONNECT;
}

static void hns3_reset_prepare(struct pci_dev *pdev)
{
struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev);

dev_info(&pdev->dev, "hns3 flr prepare\n");
if (ae_dev && ae_dev->ops && ae_dev->ops->flr_prepare)
ae_dev->ops->flr_prepare(ae_dev);
}

static void hns3_reset_done(struct pci_dev *pdev)
{
struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev);

dev_info(&pdev->dev, "hns3 flr done\n");
if (ae_dev && ae_dev->ops && ae_dev->ops->flr_done)
ae_dev->ops->flr_done(ae_dev);
}

static const struct pci_error_handlers hns3_err_handler = {
.error_detected = hns3_error_detected,
.slot_reset = hns3_slot_reset,
.reset_prepare = hns3_reset_prepare,
.reset_done = hns3_reset_done,
};

static struct pci_driver hns3_driver = {
Expand Down Expand Up @@ -2699,6 +2721,7 @@ static void hns3_update_new_int_gl(struct hns3_enet_tqp_vector *tqp_vector)

static int hns3_nic_common_poll(struct napi_struct *napi, int budget)
{
struct hns3_nic_priv *priv = netdev_priv(napi->dev);
struct hns3_enet_ring *ring;
int rx_pkt_total = 0;

Expand All @@ -2707,6 +2730,11 @@ static int hns3_nic_common_poll(struct napi_struct *napi, int budget)
bool clean_complete = true;
int rx_budget;

if (unlikely(test_bit(HNS3_NIC_STATE_DOWN, &priv->state))) {
napi_complete(napi);
return 0;
}

/* Since the actual Tx work is minimal, we can give the Tx a larger
* budget and be more aggressive about cleaning up the Tx descriptors.
*/
Expand All @@ -2731,9 +2759,11 @@ static int hns3_nic_common_poll(struct napi_struct *napi, int budget)
if (!clean_complete)
return budget;

napi_complete(napi);
hns3_update_new_int_gl(tqp_vector);
hns3_mask_vector_irq(tqp_vector, 1);
if (likely(!test_bit(HNS3_NIC_STATE_DOWN, &priv->state)) &&
napi_complete(napi)) {
hns3_update_new_int_gl(tqp_vector);
hns3_mask_vector_irq(tqp_vector, 1);
}

return rx_pkt_total;
}
Expand Down Expand Up @@ -3818,20 +3848,30 @@ static int hns3_reset_notify_init_enet(struct hnae3_handle *handle)
/* Carrier off reporting is important to ethtool even BEFORE open */
netif_carrier_off(netdev);

ret = hns3_nic_alloc_vector_data(priv);
if (ret)
return ret;

hns3_restore_coal(priv);

ret = hns3_nic_init_vector_data(priv);
if (ret)
return ret;
goto err_dealloc_vector;

ret = hns3_init_all_ring(priv);
if (ret) {
hns3_nic_uninit_vector_data(priv);
priv->ring_data = NULL;
}
if (ret)
goto err_uninit_vector;

set_bit(HNS3_NIC_STATE_INITED, &priv->state);

return ret;

err_uninit_vector:
hns3_nic_uninit_vector_data(priv);
priv->ring_data = NULL;
err_dealloc_vector:
hns3_nic_dealloc_vector_data(priv);

return ret;
}

Expand All @@ -3856,6 +3896,10 @@ static int hns3_reset_notify_uninit_enet(struct hnae3_handle *handle)

hns3_store_coal(priv);

ret = hns3_nic_dealloc_vector_data(priv);
if (ret)
netdev_err(netdev, "dealloc vector error\n");

ret = hns3_uninit_all_ring(priv);
if (ret)
netdev_err(netdev, "uninit ring error\n");
Expand Down
6 changes: 5 additions & 1 deletion drivers/net/ethernet/hisilicon/hns3/hns3_enet.h
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,11 @@ static inline void hns3_write_reg(void __iomem *base, u32 reg, u32 value)

static inline bool hns3_dev_ongoing_func_reset(struct hnae3_ae_dev *ae_dev)
{
return (ae_dev && (ae_dev->reset_type == HNAE3_FUNC_RESET));
return (ae_dev && (ae_dev->reset_type == HNAE3_FUNC_RESET ||
ae_dev->reset_type == HNAE3_FLR_RESET ||
ae_dev->reset_type == HNAE3_VF_FUNC_RESET ||
ae_dev->reset_type == HNAE3_VF_FULL_RESET ||
ae_dev->reset_type == HNAE3_VF_PF_FUNC_RESET));
}

#define hns3_read_dev(a, reg) \
Expand Down
11 changes: 10 additions & 1 deletion drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -350,11 +350,20 @@ int hclge_cmd_init(struct hclge_dev *hdev)
hdev->hw.cmq.crq.next_to_use = 0;

hclge_cmd_init_regs(&hdev->hw);
clear_bit(HCLGE_STATE_CMD_DISABLE, &hdev->state);

spin_unlock_bh(&hdev->hw.cmq.crq.lock);
spin_unlock_bh(&hdev->hw.cmq.csq.lock);

clear_bit(HCLGE_STATE_CMD_DISABLE, &hdev->state);

/* Check if there is new reset pending, because the higher level
* reset may happen when lower level reset is being processed.
*/
if ((hclge_is_reset_pending(hdev))) {
set_bit(HCLGE_STATE_CMD_DISABLE, &hdev->state);
return -EBUSY;
}

ret = hclge_cmd_query_firmware_version(&hdev->hw, &version);
if (ret) {
dev_err(&hdev->pdev->dev,
Expand Down
Loading

0 comments on commit 70e7983

Please sign in to comment.