mirror of
https://github.com/torvalds/linux.git
synced 2024-11-12 07:01:57 +00:00
enic: driver/firmware API updates
Add driver/firmware compatibility check. Update firmware notify cmd to honor notify area size. Add new version of init cmd. Add link_down_cnt to notify area to track link down count. Signed-off-by: Scott Feldman <scofeldm@cisco.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
86ca9db794
commit
27372bf5fa
@ -43,6 +43,7 @@ struct vnic_dev {
|
|||||||
struct vnic_devcmd_notify *notify;
|
struct vnic_devcmd_notify *notify;
|
||||||
struct vnic_devcmd_notify notify_copy;
|
struct vnic_devcmd_notify notify_copy;
|
||||||
dma_addr_t notify_pa;
|
dma_addr_t notify_pa;
|
||||||
|
u32 notify_sz;
|
||||||
u32 *linkstatus;
|
u32 *linkstatus;
|
||||||
dma_addr_t linkstatus_pa;
|
dma_addr_t linkstatus_pa;
|
||||||
struct vnic_stats *stats;
|
struct vnic_stats *stats;
|
||||||
@ -235,14 +236,6 @@ int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
|
|||||||
struct vnic_devcmd __iomem *devcmd = vdev->devcmd;
|
struct vnic_devcmd __iomem *devcmd = vdev->devcmd;
|
||||||
int delay;
|
int delay;
|
||||||
u32 status;
|
u32 status;
|
||||||
int dev_cmd_err[] = {
|
|
||||||
/* convert from fw's version of error.h to host's version */
|
|
||||||
0, /* ERR_SUCCESS */
|
|
||||||
EINVAL, /* ERR_EINVAL */
|
|
||||||
EFAULT, /* ERR_EFAULT */
|
|
||||||
EPERM, /* ERR_EPERM */
|
|
||||||
EBUSY, /* ERR_EBUSY */
|
|
||||||
};
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
status = ioread32(&devcmd->status);
|
status = ioread32(&devcmd->status);
|
||||||
@ -270,10 +263,12 @@ int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
|
|||||||
if (!(status & STAT_BUSY)) {
|
if (!(status & STAT_BUSY)) {
|
||||||
|
|
||||||
if (status & STAT_ERROR) {
|
if (status & STAT_ERROR) {
|
||||||
err = dev_cmd_err[(int)readq(&devcmd->args[0])];
|
err = (int)readq(&devcmd->args[0]);
|
||||||
printk(KERN_ERR "Error %d devcmd %d\n",
|
if (err != ERR_ECMDUNKNOWN ||
|
||||||
err, _CMD_N(cmd));
|
cmd != CMD_CAPABILITY)
|
||||||
return -err;
|
printk(KERN_ERR "Error %d devcmd %d\n",
|
||||||
|
err, _CMD_N(cmd));
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_CMD_DIR(cmd) & _CMD_DIR_READ) {
|
if (_CMD_DIR(cmd) & _CMD_DIR_READ) {
|
||||||
@ -290,6 +285,17 @@ int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
|
|||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int vnic_dev_capable(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd)
|
||||||
|
{
|
||||||
|
u64 a0 = (u32)cmd, a1 = 0;
|
||||||
|
int wait = 1000;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = vnic_dev_cmd(vdev, CMD_CAPABILITY, &a0, &a1, wait);
|
||||||
|
|
||||||
|
return !(err || a0);
|
||||||
|
}
|
||||||
|
|
||||||
int vnic_dev_fw_info(struct vnic_dev *vdev,
|
int vnic_dev_fw_info(struct vnic_dev *vdev,
|
||||||
struct vnic_devcmd_fw_info **fw_info)
|
struct vnic_devcmd_fw_info **fw_info)
|
||||||
{
|
{
|
||||||
@ -511,6 +517,7 @@ int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr)
|
|||||||
{
|
{
|
||||||
u64 a0, a1;
|
u64 a0, a1;
|
||||||
int wait = 1000;
|
int wait = 1000;
|
||||||
|
int r;
|
||||||
|
|
||||||
if (!vdev->notify) {
|
if (!vdev->notify) {
|
||||||
vdev->notify = pci_alloc_consistent(vdev->pdev,
|
vdev->notify = pci_alloc_consistent(vdev->pdev,
|
||||||
@ -518,13 +525,16 @@ int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr)
|
|||||||
&vdev->notify_pa);
|
&vdev->notify_pa);
|
||||||
if (!vdev->notify)
|
if (!vdev->notify)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
memset(vdev->notify, 0, sizeof(struct vnic_devcmd_notify));
|
||||||
}
|
}
|
||||||
|
|
||||||
a0 = vdev->notify_pa;
|
a0 = vdev->notify_pa;
|
||||||
a1 = ((u64)intr << 32) & 0x0000ffff00000000ULL;
|
a1 = ((u64)intr << 32) & 0x0000ffff00000000ULL;
|
||||||
a1 += sizeof(struct vnic_devcmd_notify);
|
a1 += sizeof(struct vnic_devcmd_notify);
|
||||||
|
|
||||||
return vnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait);
|
r = vnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait);
|
||||||
|
vdev->notify_sz = (r == 0) ? (u32)a1 : 0;
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vnic_dev_notify_unset(struct vnic_dev *vdev)
|
void vnic_dev_notify_unset(struct vnic_dev *vdev)
|
||||||
@ -537,22 +547,22 @@ void vnic_dev_notify_unset(struct vnic_dev *vdev)
|
|||||||
a1 += sizeof(struct vnic_devcmd_notify);
|
a1 += sizeof(struct vnic_devcmd_notify);
|
||||||
|
|
||||||
vnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait);
|
vnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait);
|
||||||
|
vdev->notify_sz = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vnic_dev_notify_ready(struct vnic_dev *vdev)
|
static int vnic_dev_notify_ready(struct vnic_dev *vdev)
|
||||||
{
|
{
|
||||||
u32 *words;
|
u32 *words;
|
||||||
unsigned int nwords = sizeof(struct vnic_devcmd_notify) / 4;
|
unsigned int nwords = vdev->notify_sz / 4;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
u32 csum;
|
u32 csum;
|
||||||
|
|
||||||
if (!vdev->notify)
|
if (!vdev->notify || !vdev->notify_sz)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
csum = 0;
|
csum = 0;
|
||||||
memcpy(&vdev->notify_copy, vdev->notify,
|
memcpy(&vdev->notify_copy, vdev->notify, vdev->notify_sz);
|
||||||
sizeof(struct vnic_devcmd_notify));
|
|
||||||
words = (u32 *)&vdev->notify_copy;
|
words = (u32 *)&vdev->notify_copy;
|
||||||
for (i = 1; i < nwords; i++)
|
for (i = 1; i < nwords; i++)
|
||||||
csum += words[i];
|
csum += words[i];
|
||||||
@ -565,7 +575,20 @@ int vnic_dev_init(struct vnic_dev *vdev, int arg)
|
|||||||
{
|
{
|
||||||
u64 a0 = (u32)arg, a1 = 0;
|
u64 a0 = (u32)arg, a1 = 0;
|
||||||
int wait = 1000;
|
int wait = 1000;
|
||||||
return vnic_dev_cmd(vdev, CMD_INIT, &a0, &a1, wait);
|
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_link_status(struct vnic_dev *vdev)
|
int vnic_dev_link_status(struct vnic_dev *vdev)
|
||||||
@ -666,3 +689,4 @@ err_out:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -168,7 +168,8 @@ enum vnic_devcmd_cmd {
|
|||||||
CMD_CLOSE = _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 25),
|
CMD_CLOSE = _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 25),
|
||||||
|
|
||||||
/* initialize virtual link: (u32)a0=flags (see CMD_INITF_*) */
|
/* initialize virtual link: (u32)a0=flags (see CMD_INITF_*) */
|
||||||
CMD_INIT = _CMDCNW(_CMD_DIR_READ, _CMD_VTYPE_ALL, 26),
|
/***** Replaced by CMD_INIT *****/
|
||||||
|
CMD_INIT_v1 = _CMDCNW(_CMD_DIR_READ, _CMD_VTYPE_ALL, 26),
|
||||||
|
|
||||||
/* variant of CMD_INIT, with provisioning info
|
/* variant of CMD_INIT, with provisioning info
|
||||||
* (u64)a0=paddr of vnic_devcmd_provinfo
|
* (u64)a0=paddr of vnic_devcmd_provinfo
|
||||||
@ -198,6 +199,14 @@ enum vnic_devcmd_cmd {
|
|||||||
|
|
||||||
/* undo initialize of virtual link */
|
/* undo initialize of virtual link */
|
||||||
CMD_DEINIT = _CMDCNW(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 34),
|
CMD_DEINIT = _CMDCNW(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 34),
|
||||||
|
|
||||||
|
/* initialize virtual link: (u32)a0=flags (see CMD_INITF_*) */
|
||||||
|
CMD_INIT = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 35),
|
||||||
|
|
||||||
|
/* check fw capability of a cmd:
|
||||||
|
* in: (u32)a0=cmd
|
||||||
|
* out: (u32)a0=errno, 0:valid cmd, a1=supported VNIC_STF_* bits */
|
||||||
|
CMD_CAPABILITY = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 36),
|
||||||
};
|
};
|
||||||
|
|
||||||
/* flags for CMD_OPEN */
|
/* flags for CMD_OPEN */
|
||||||
@ -249,8 +258,16 @@ struct vnic_devcmd_notify {
|
|||||||
u32 uif; /* uplink interface */
|
u32 uif; /* uplink interface */
|
||||||
u32 status; /* status bits (see VNIC_STF_*) */
|
u32 status; /* status bits (see VNIC_STF_*) */
|
||||||
u32 error; /* error code (see ERR_*) for first ERR */
|
u32 error; /* error code (see ERR_*) for first ERR */
|
||||||
|
u32 link_down_cnt; /* running count of link down transitions */
|
||||||
};
|
};
|
||||||
#define VNIC_STF_FATAL_ERR 0x0001 /* fatal fw error */
|
#define VNIC_STF_FATAL_ERR 0x0001 /* fatal fw error */
|
||||||
|
#define VNIC_STF_STD_PAUSE 0x0002 /* standard link-level pause on */
|
||||||
|
#define VNIC_STF_PFC_PAUSE 0x0004 /* priority flow control pause on */
|
||||||
|
/* all supported status flags */
|
||||||
|
#define VNIC_STF_ALL (VNIC_STF_FATAL_ERR |\
|
||||||
|
VNIC_STF_STD_PAUSE |\
|
||||||
|
VNIC_STF_PFC_PAUSE |\
|
||||||
|
0)
|
||||||
|
|
||||||
struct vnic_devcmd_provinfo {
|
struct vnic_devcmd_provinfo {
|
||||||
u8 oui[3];
|
u8 oui[3];
|
||||||
|
Loading…
Reference in New Issue
Block a user