mirror of
https://github.com/torvalds/linux.git
synced 2026-05-26 08:02:27 +02:00
hinic3: Interrupt request configuration
Configure interrupt request initialization. It allows driver to receive packets and management information from HW. Co-developed-by: Xin Guo <guoxin09@huawei.com> Signed-off-by: Xin Guo <guoxin09@huawei.com> Co-developed-by: Zhu Yikai <zhuyikai1@h-partners.com> Signed-off-by: Zhu Yikai <zhuyikai1@h-partners.com> Signed-off-by: Fan Gong <gongfan1@huawei.com> Link: https://patch.msgid.link/37615d5d87ced741e522cd966948d11ec87e4ad6.1755673097.git.zhuyikai1@h-partners.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
a8255ea56a
commit
a5a90346bb
|
|
@ -8,6 +8,37 @@
|
|||
#include "hinic3_hwif.h"
|
||||
#include "hinic3_mbox.h"
|
||||
|
||||
int hinic3_set_interrupt_cfg_direct(struct hinic3_hwdev *hwdev,
|
||||
const struct hinic3_interrupt_info *info)
|
||||
{
|
||||
struct comm_cmd_cfg_msix_ctrl_reg msix_cfg = {};
|
||||
struct mgmt_msg_params msg_params = {};
|
||||
int err;
|
||||
|
||||
msix_cfg.func_id = hinic3_global_func_id(hwdev);
|
||||
msix_cfg.msix_index = info->msix_index;
|
||||
msix_cfg.opcode = MGMT_MSG_CMD_OP_SET;
|
||||
|
||||
msix_cfg.lli_credit_cnt = info->lli_credit_limit;
|
||||
msix_cfg.lli_timer_cnt = info->lli_timer_cfg;
|
||||
msix_cfg.pending_cnt = info->pending_limit;
|
||||
msix_cfg.coalesce_timer_cnt = info->coalesc_timer_cfg;
|
||||
msix_cfg.resend_timer_cnt = info->resend_timer_cfg;
|
||||
|
||||
mgmt_msg_params_init_default(&msg_params, &msix_cfg, sizeof(msix_cfg));
|
||||
|
||||
err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_COMM,
|
||||
COMM_CMD_CFG_MSIX_CTRL_REG, &msg_params);
|
||||
if (err || msix_cfg.head.status) {
|
||||
dev_err(hwdev->dev,
|
||||
"Failed to set interrupt config, err: %d, status: 0x%x\n",
|
||||
err, msix_cfg.head.status);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hinic3_func_reset(struct hinic3_hwdev *hwdev, u16 func_id, u64 reset_flag)
|
||||
{
|
||||
struct comm_cmd_func_reset func_reset = {};
|
||||
|
|
|
|||
|
|
@ -8,6 +8,19 @@
|
|||
|
||||
struct hinic3_hwdev;
|
||||
|
||||
struct hinic3_interrupt_info {
|
||||
u32 lli_set;
|
||||
u32 interrupt_coalesc_set;
|
||||
u16 msix_index;
|
||||
u8 lli_credit_limit;
|
||||
u8 lli_timer_cfg;
|
||||
u8 pending_limit;
|
||||
u8 coalesc_timer_cfg;
|
||||
u8 resend_timer_cfg;
|
||||
};
|
||||
|
||||
int hinic3_set_interrupt_cfg_direct(struct hinic3_hwdev *hwdev,
|
||||
const struct hinic3_interrupt_info *info);
|
||||
int hinic3_func_reset(struct hinic3_hwdev *hwdev, u16 func_id, u64 reset_flag);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ static int hinic3_poll(struct napi_struct *napi, int budget)
|
|||
return work_done;
|
||||
}
|
||||
|
||||
void qp_add_napi(struct hinic3_irq_cfg *irq_cfg)
|
||||
static void qp_add_napi(struct hinic3_irq_cfg *irq_cfg)
|
||||
{
|
||||
struct hinic3_nic_dev *nic_dev = netdev_priv(irq_cfg->netdev);
|
||||
|
||||
|
|
@ -50,7 +50,7 @@ void qp_add_napi(struct hinic3_irq_cfg *irq_cfg)
|
|||
napi_enable(&irq_cfg->napi);
|
||||
}
|
||||
|
||||
void qp_del_napi(struct hinic3_irq_cfg *irq_cfg)
|
||||
static void qp_del_napi(struct hinic3_irq_cfg *irq_cfg)
|
||||
{
|
||||
napi_disable(&irq_cfg->napi);
|
||||
netif_queue_set_napi(irq_cfg->netdev, irq_cfg->irq_id,
|
||||
|
|
@ -60,3 +60,135 @@ void qp_del_napi(struct hinic3_irq_cfg *irq_cfg)
|
|||
netif_stop_subqueue(irq_cfg->netdev, irq_cfg->irq_id);
|
||||
netif_napi_del(&irq_cfg->napi);
|
||||
}
|
||||
|
||||
static irqreturn_t qp_irq(int irq, void *data)
|
||||
{
|
||||
struct hinic3_irq_cfg *irq_cfg = data;
|
||||
struct hinic3_nic_dev *nic_dev;
|
||||
|
||||
nic_dev = netdev_priv(irq_cfg->netdev);
|
||||
hinic3_msix_intr_clear_resend_bit(nic_dev->hwdev,
|
||||
irq_cfg->msix_entry_idx, 1);
|
||||
|
||||
napi_schedule(&irq_cfg->napi);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int hinic3_request_irq(struct hinic3_irq_cfg *irq_cfg, u16 q_id)
|
||||
{
|
||||
struct hinic3_interrupt_info info = {};
|
||||
struct hinic3_nic_dev *nic_dev;
|
||||
struct net_device *netdev;
|
||||
int err;
|
||||
|
||||
netdev = irq_cfg->netdev;
|
||||
nic_dev = netdev_priv(netdev);
|
||||
qp_add_napi(irq_cfg);
|
||||
|
||||
info.msix_index = irq_cfg->msix_entry_idx;
|
||||
info.interrupt_coalesc_set = 1;
|
||||
info.pending_limit = nic_dev->intr_coalesce[q_id].pending_limit;
|
||||
info.coalesc_timer_cfg =
|
||||
nic_dev->intr_coalesce[q_id].coalesce_timer_cfg;
|
||||
info.resend_timer_cfg = nic_dev->intr_coalesce[q_id].resend_timer_cfg;
|
||||
err = hinic3_set_interrupt_cfg_direct(nic_dev->hwdev, &info);
|
||||
if (err) {
|
||||
netdev_err(netdev, "Failed to set RX interrupt coalescing attribute.\n");
|
||||
qp_del_napi(irq_cfg);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = request_irq(irq_cfg->irq_id, qp_irq, 0, irq_cfg->irq_name,
|
||||
irq_cfg);
|
||||
if (err) {
|
||||
qp_del_napi(irq_cfg);
|
||||
return err;
|
||||
}
|
||||
|
||||
irq_set_affinity_hint(irq_cfg->irq_id, &irq_cfg->affinity_mask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hinic3_release_irq(struct hinic3_irq_cfg *irq_cfg)
|
||||
{
|
||||
irq_set_affinity_hint(irq_cfg->irq_id, NULL);
|
||||
free_irq(irq_cfg->irq_id, irq_cfg);
|
||||
}
|
||||
|
||||
int hinic3_qps_irq_init(struct net_device *netdev)
|
||||
{
|
||||
struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
|
||||
struct pci_dev *pdev = nic_dev->pdev;
|
||||
struct hinic3_irq_cfg *irq_cfg;
|
||||
struct msix_entry *msix_entry;
|
||||
u32 local_cpu;
|
||||
u16 q_id;
|
||||
int err;
|
||||
|
||||
for (q_id = 0; q_id < nic_dev->q_params.num_qps; q_id++) {
|
||||
msix_entry = &nic_dev->qps_msix_entries[q_id];
|
||||
irq_cfg = &nic_dev->q_params.irq_cfg[q_id];
|
||||
|
||||
irq_cfg->irq_id = msix_entry->vector;
|
||||
irq_cfg->msix_entry_idx = msix_entry->entry;
|
||||
irq_cfg->netdev = netdev;
|
||||
irq_cfg->txq = &nic_dev->txqs[q_id];
|
||||
irq_cfg->rxq = &nic_dev->rxqs[q_id];
|
||||
nic_dev->rxqs[q_id].irq_cfg = irq_cfg;
|
||||
|
||||
local_cpu = cpumask_local_spread(q_id, dev_to_node(&pdev->dev));
|
||||
cpumask_set_cpu(local_cpu, &irq_cfg->affinity_mask);
|
||||
|
||||
snprintf(irq_cfg->irq_name, sizeof(irq_cfg->irq_name),
|
||||
"%s_qp%u", netdev->name, q_id);
|
||||
|
||||
err = hinic3_request_irq(irq_cfg, q_id);
|
||||
if (err) {
|
||||
netdev_err(netdev, "Failed to request Rx irq\n");
|
||||
goto err_release_irqs;
|
||||
}
|
||||
|
||||
hinic3_set_msix_auto_mask_state(nic_dev->hwdev,
|
||||
irq_cfg->msix_entry_idx,
|
||||
HINIC3_SET_MSIX_AUTO_MASK);
|
||||
hinic3_set_msix_state(nic_dev->hwdev, irq_cfg->msix_entry_idx,
|
||||
HINIC3_MSIX_ENABLE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_release_irqs:
|
||||
while (q_id > 0) {
|
||||
q_id--;
|
||||
irq_cfg = &nic_dev->q_params.irq_cfg[q_id];
|
||||
qp_del_napi(irq_cfg);
|
||||
hinic3_set_msix_state(nic_dev->hwdev, irq_cfg->msix_entry_idx,
|
||||
HINIC3_MSIX_DISABLE);
|
||||
hinic3_set_msix_auto_mask_state(nic_dev->hwdev,
|
||||
irq_cfg->msix_entry_idx,
|
||||
HINIC3_CLR_MSIX_AUTO_MASK);
|
||||
hinic3_release_irq(irq_cfg);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void hinic3_qps_irq_uninit(struct net_device *netdev)
|
||||
{
|
||||
struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
|
||||
struct hinic3_irq_cfg *irq_cfg;
|
||||
u16 q_id;
|
||||
|
||||
for (q_id = 0; q_id < nic_dev->q_params.num_qps; q_id++) {
|
||||
irq_cfg = &nic_dev->q_params.irq_cfg[q_id];
|
||||
qp_del_napi(irq_cfg);
|
||||
hinic3_set_msix_state(nic_dev->hwdev, irq_cfg->msix_entry_idx,
|
||||
HINIC3_MSIX_DISABLE);
|
||||
hinic3_set_msix_auto_mask_state(nic_dev->hwdev,
|
||||
irq_cfg->msix_entry_idx,
|
||||
HINIC3_CLR_MSIX_AUTO_MASK);
|
||||
hinic3_release_irq(irq_cfg);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,8 +85,4 @@ void hinic3_set_netdev_ops(struct net_device *netdev);
|
|||
int hinic3_qps_irq_init(struct net_device *netdev);
|
||||
void hinic3_qps_irq_uninit(struct net_device *netdev);
|
||||
|
||||
/* Temporary prototypes. Functions become static in later submission. */
|
||||
void qp_add_napi(struct hinic3_irq_cfg *irq_cfg);
|
||||
void qp_del_napi(struct hinic3_irq_cfg *irq_cfg);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user