int vnic_dev_intr_coal_timer_info(struct vnic_dev *vdev) { int wait = 1000; int err; memset(vdev->args, 0, sizeof(vdev->args)); if (vnic_dev_capable(vdev, CMD_INTR_COAL_CONVERT)) err = _vnic_dev_cmd(vdev, CMD_INTR_COAL_CONVERT, wait); else err = ERR_ECMDUNKNOWN; /* Use defaults when firmware doesn't support the devcmd at all or * supports it for only specific hardware */ if ((err == ERR_ECMDUNKNOWN) || (!err && !(vdev->args[0] && vdev->args[1] && vdev->args[2]))) { pr_warning("Using default conversion factor for " "interrupt coalesce timer\n"); vnic_dev_intr_coal_timer_info_default(vdev); return 0; } if (!err) { vdev->intr_coal_timer_info.mul = (u32) vdev->args[0]; vdev->intr_coal_timer_info.div = (u32) vdev->args[1]; vdev->intr_coal_timer_info.max_usec = (u32) vdev->args[2]; } return err; }
int vnic_dev_fw_info(struct vnic_dev *vdev, struct vnic_devcmd_fw_info **fw_info) { u64 a0, a1 = 0; int wait = 1000; int err = 0; if (!vdev->fw_info) { vdev->fw_info = pci_zalloc_consistent(vdev->pdev, sizeof(struct vnic_devcmd_fw_info), &vdev->fw_info_pa); if (!vdev->fw_info) return -ENOMEM; a0 = vdev->fw_info_pa; a1 = sizeof(struct vnic_devcmd_fw_info); /* only get fw_info once and cache it */ if (vnic_dev_capable(vdev, CMD_MCPU_FW_INFO)) err = vnic_dev_cmd(vdev, CMD_MCPU_FW_INFO, &a0, &a1, wait); else err = vnic_dev_cmd(vdev, CMD_MCPU_FW_INFO_OLD, &a0, &a1, wait); } *fw_info = vdev->fw_info; return err; }
struct vnic_dev *vnic_dev_register(struct vnic_dev *vdev, void *priv, struct pci_dev *pdev, struct vnic_dev_bar *bar) { if (!vdev) { vdev = kzalloc(sizeof(struct vnic_dev), GFP_ATOMIC); if (!vdev) return NULL; } vdev->priv = priv; vdev->pdev = pdev; if (vnic_dev_discover_res(vdev, bar)) goto err_out; vdev->devcmd = vnic_dev_get_res(vdev, RES_TYPE_DEVCMD, 0); if (!vdev->devcmd) goto err_out; vdev->cap_flags = 0; if (vnic_dev_capable(vdev, CMD_INIT)) vdev->cap_flags |= VNIC_DEV_CAP_INIT; return vdev; err_out: vnic_dev_unregister(vdev); return NULL; }
int vnic_dev_enable_wait(struct vnic_dev *vdev) { u64 a0 = 0, a1 = 0; int wait = 1000; if (vnic_dev_capable(vdev, CMD_ENABLE_WAIT)) return vnic_dev_cmd(vdev, CMD_ENABLE_WAIT, &a0, &a1, wait); else return vnic_dev_cmd(vdev, CMD_ENABLE, &a0, &a1, wait); }
int vnic_dev_set_ig_vlan_rewrite_mode(struct vnic_dev *vdev, u8 ig_vlan_rewrite_mode) { u64 a0 = ig_vlan_rewrite_mode, a1 = 0; int wait = 1000; if (vnic_dev_capable(vdev, CMD_IG_VLAN_REWRITE_MODE)) return vnic_dev_cmd(vdev, CMD_IG_VLAN_REWRITE_MODE, &a0, &a1, wait); else return 0; }
int vnic_dev_hang_reset(struct vnic_dev *vdev, int arg) { u64 a0 = (u32)arg, a1 = 0; int wait = 1000; int err; if (vnic_dev_capable(vdev, CMD_HANG_RESET)) { return vnic_dev_cmd(vdev, CMD_HANG_RESET, &a0, &a1, wait); } else { err = vnic_dev_soft_reset(vdev, arg); if (err) return err; return vnic_dev_init(vdev, 0); } }
int vnic_dev_init(struct vnic_dev *vdev, int arg) { u64 a0 = (u32)arg, a1 = 0; int wait = 1000; int r = 0; if (vnic_dev_capable(vdev, CMD_INIT)) r = vnic_dev_cmd(vdev, CMD_INIT, &a0, &a1, wait); else { vnic_dev_cmd(vdev, CMD_INIT_v1, &a0, &a1, wait); if (a0 & CMD_INITF_DEFAULT_MAC) { vnic_dev_cmd(vdev, CMD_GET_MAC_ADDR, &a0, &a1, wait); vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait); } } return r; }
int vnic_dev_init(struct vnic_dev *vdev, int arg) { u64 a0 = (u32)arg, a1 = 0; int wait = 1000; int r = 0; if (vnic_dev_capable(vdev, CMD_INIT)) r = vnic_dev_cmd(vdev, CMD_INIT, &a0, &a1, wait); else { vnic_dev_cmd(vdev, CMD_INIT_v1, &a0, &a1, wait); if (a0 & CMD_INITF_DEFAULT_MAC) { // Emulate these for old CMD_INIT_v1 which // didn't pass a0 so no CMD_INITF_*. vnic_dev_cmd(vdev, CMD_MAC_ADDR, &a0, &a1, wait); vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait); } } return r; }
int vnic_dev_hang_reset_done(struct vnic_dev *vdev, int *done) { u64 a0 = 0, a1 = 0; int wait = 1000; int err; *done = 0; if (vnic_dev_capable(vdev, CMD_HANG_RESET_STATUS)) { err = vnic_dev_cmd(vdev, CMD_HANG_RESET_STATUS, &a0, &a1, wait); if (err) return err; } else { return vnic_dev_soft_reset_done(vdev, done); } *done = (a0 == 0); return 0; }