aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorScott Feldman <scofeldm@cisco.com>2008-11-22 00:28:18 -0500
committerDavid S. Miller <davem@davemloft.net>2008-11-22 00:28:18 -0500
commit27372bf5fa5ffc0fee3ddb486a0da942295fd8e0 (patch)
tree34a4e6f41057ff12f01a86d891c81023c3d45a8e /drivers
parent86ca9db794a285f18f31ed15601696b238ccb57a (diff)
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/enic/vnic_dev.c60
-rw-r--r--drivers/net/enic/vnic_devcmd.h19
2 files changed, 60 insertions, 19 deletions
diff --git a/drivers/net/enic/vnic_dev.c b/drivers/net/enic/vnic_dev.c
index 9afd33c7188d..08a37b01bf37 100644
--- a/drivers/net/enic/vnic_dev.c
+++ b/drivers/net/enic/vnic_dev.c
@@ -43,6 +43,7 @@ struct vnic_dev {
43 struct vnic_devcmd_notify *notify; 43 struct vnic_devcmd_notify *notify;
44 struct vnic_devcmd_notify notify_copy; 44 struct vnic_devcmd_notify notify_copy;
45 dma_addr_t notify_pa; 45 dma_addr_t notify_pa;
46 u32 notify_sz;
46 u32 *linkstatus; 47 u32 *linkstatus;
47 dma_addr_t linkstatus_pa; 48 dma_addr_t linkstatus_pa;
48 struct vnic_stats *stats; 49 struct vnic_stats *stats;
@@ -235,14 +236,6 @@ int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
235 struct vnic_devcmd __iomem *devcmd = vdev->devcmd; 236 struct vnic_devcmd __iomem *devcmd = vdev->devcmd;
236 int delay; 237 int delay;
237 u32 status; 238 u32 status;
238 int dev_cmd_err[] = {
239 /* convert from fw's version of error.h to host's version */
240 0, /* ERR_SUCCESS */
241 EINVAL, /* ERR_EINVAL */
242 EFAULT, /* ERR_EFAULT */
243 EPERM, /* ERR_EPERM */
244 EBUSY, /* ERR_EBUSY */
245 };
246 int err; 239 int err;
247 240
248 status = ioread32(&devcmd->status); 241 status = ioread32(&devcmd->status);
@@ -270,10 +263,12 @@ int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
270 if (!(status & STAT_BUSY)) { 263 if (!(status & STAT_BUSY)) {
271 264
272 if (status & STAT_ERROR) { 265 if (status & STAT_ERROR) {
273 err = dev_cmd_err[(int)readq(&devcmd->args[0])]; 266 err = (int)readq(&devcmd->args[0]);
274 printk(KERN_ERR "Error %d devcmd %d\n", 267 if (err != ERR_ECMDUNKNOWN ||
275 err, _CMD_N(cmd)); 268 cmd != CMD_CAPABILITY)
276 return -err; 269 printk(KERN_ERR "Error %d devcmd %d\n",
270 err, _CMD_N(cmd));
271 return err;
277 } 272 }
278 273
279 if (_CMD_DIR(cmd) & _CMD_DIR_READ) { 274 if (_CMD_DIR(cmd) & _CMD_DIR_READ) {
@@ -290,6 +285,17 @@ int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
290 return -ETIMEDOUT; 285 return -ETIMEDOUT;
291} 286}
292 287
288int vnic_dev_capable(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd)
289{
290 u64 a0 = (u32)cmd, a1 = 0;
291 int wait = 1000;
292 int err;
293
294 err = vnic_dev_cmd(vdev, CMD_CAPABILITY, &a0, &a1, wait);
295
296 return !(err || a0);
297}
298
293int vnic_dev_fw_info(struct vnic_dev *vdev, 299int vnic_dev_fw_info(struct vnic_dev *vdev,
294 struct vnic_devcmd_fw_info **fw_info) 300 struct vnic_devcmd_fw_info **fw_info)
295{ 301{
@@ -511,6 +517,7 @@ int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr)
511{ 517{
512 u64 a0, a1; 518 u64 a0, a1;
513 int wait = 1000; 519 int wait = 1000;
520 int r;
514 521
515 if (!vdev->notify) { 522 if (!vdev->notify) {
516 vdev->notify = pci_alloc_consistent(vdev->pdev, 523 vdev->notify = pci_alloc_consistent(vdev->pdev,
@@ -518,13 +525,16 @@ int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr)
518 &vdev->notify_pa); 525 &vdev->notify_pa);
519 if (!vdev->notify) 526 if (!vdev->notify)
520 return -ENOMEM; 527 return -ENOMEM;
528 memset(vdev->notify, 0, sizeof(struct vnic_devcmd_notify));
521 } 529 }
522 530
523 a0 = vdev->notify_pa; 531 a0 = vdev->notify_pa;
524 a1 = ((u64)intr << 32) & 0x0000ffff00000000ULL; 532 a1 = ((u64)intr << 32) & 0x0000ffff00000000ULL;
525 a1 += sizeof(struct vnic_devcmd_notify); 533 a1 += sizeof(struct vnic_devcmd_notify);
526 534
527 return vnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait); 535 r = vnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait);
536 vdev->notify_sz = (r == 0) ? (u32)a1 : 0;
537 return r;
528} 538}
529 539
530void vnic_dev_notify_unset(struct vnic_dev *vdev) 540void vnic_dev_notify_unset(struct vnic_dev *vdev)
@@ -537,22 +547,22 @@ void vnic_dev_notify_unset(struct vnic_dev *vdev)
537 a1 += sizeof(struct vnic_devcmd_notify); 547 a1 += sizeof(struct vnic_devcmd_notify);
538 548
539 vnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait); 549 vnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait);
550 vdev->notify_sz = 0;
540} 551}
541 552
542static int vnic_dev_notify_ready(struct vnic_dev *vdev) 553static int vnic_dev_notify_ready(struct vnic_dev *vdev)
543{ 554{
544 u32 *words; 555 u32 *words;
545 unsigned int nwords = sizeof(struct vnic_devcmd_notify) / 4; 556 unsigned int nwords = vdev->notify_sz / 4;
546 unsigned int i; 557 unsigned int i;
547 u32 csum; 558 u32 csum;
548 559
549 if (!vdev->notify) 560 if (!vdev->notify || !vdev->notify_sz)
550 return 0; 561 return 0;
551 562
552 do { 563 do {
553 csum = 0; 564 csum = 0;
554 memcpy(&vdev->notify_copy, vdev->notify, 565 memcpy(&vdev->notify_copy, vdev->notify, vdev->notify_sz);
555 sizeof(struct vnic_devcmd_notify));
556 words = (u32 *)&vdev->notify_copy; 566 words = (u32 *)&vdev->notify_copy;
557 for (i = 1; i < nwords; i++) 567 for (i = 1; i < nwords; i++)
558 csum += words[i]; 568 csum += words[i];
@@ -565,7 +575,20 @@ int vnic_dev_init(struct vnic_dev *vdev, int arg)
565{ 575{
566 u64 a0 = (u32)arg, a1 = 0; 576 u64 a0 = (u32)arg, a1 = 0;
567 int wait = 1000; 577 int wait = 1000;
568 return vnic_dev_cmd(vdev, CMD_INIT, &a0, &a1, wait); 578 int r = 0;
579
580 if (vnic_dev_capable(vdev, CMD_INIT))
581 r = vnic_dev_cmd(vdev, CMD_INIT, &a0, &a1, wait);
582 else {
583 vnic_dev_cmd(vdev, CMD_INIT_v1, &a0, &a1, wait);
584 if (a0 & CMD_INITF_DEFAULT_MAC) {
585 // Emulate these for old CMD_INIT_v1 which
586 // didn't pass a0 so no CMD_INITF_*.
587 vnic_dev_cmd(vdev, CMD_MAC_ADDR, &a0, &a1, wait);
588 vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait);
589 }
590 }
591 return r;
569} 592}
570 593
571int vnic_dev_link_status(struct vnic_dev *vdev) 594int vnic_dev_link_status(struct vnic_dev *vdev)
@@ -666,3 +689,4 @@ err_out:
666 return NULL; 689 return NULL;
667} 690}
668 691
692
diff --git a/drivers/net/enic/vnic_devcmd.h b/drivers/net/enic/vnic_devcmd.h
index d8617a3373b1..8062c75154e6 100644
--- a/drivers/net/enic/vnic_devcmd.h
+++ b/drivers/net/enic/vnic_devcmd.h
@@ -168,7 +168,8 @@ enum vnic_devcmd_cmd {
168 CMD_CLOSE = _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 25), 168 CMD_CLOSE = _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 25),
169 169
170 /* initialize virtual link: (u32)a0=flags (see CMD_INITF_*) */ 170 /* initialize virtual link: (u32)a0=flags (see CMD_INITF_*) */
171 CMD_INIT = _CMDCNW(_CMD_DIR_READ, _CMD_VTYPE_ALL, 26), 171/***** Replaced by CMD_INIT *****/
172 CMD_INIT_v1 = _CMDCNW(_CMD_DIR_READ, _CMD_VTYPE_ALL, 26),
172 173
173 /* variant of CMD_INIT, with provisioning info 174 /* variant of CMD_INIT, with provisioning info
174 * (u64)a0=paddr of vnic_devcmd_provinfo 175 * (u64)a0=paddr of vnic_devcmd_provinfo
@@ -198,6 +199,14 @@ enum vnic_devcmd_cmd {
198 199
199 /* undo initialize of virtual link */ 200 /* undo initialize of virtual link */
200 CMD_DEINIT = _CMDCNW(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 34), 201 CMD_DEINIT = _CMDCNW(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 34),
202
203 /* initialize virtual link: (u32)a0=flags (see CMD_INITF_*) */
204 CMD_INIT = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 35),
205
206 /* check fw capability of a cmd:
207 * in: (u32)a0=cmd
208 * out: (u32)a0=errno, 0:valid cmd, a1=supported VNIC_STF_* bits */
209 CMD_CAPABILITY = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 36),
201}; 210};
202 211
203/* flags for CMD_OPEN */ 212/* flags for CMD_OPEN */
@@ -249,8 +258,16 @@ struct vnic_devcmd_notify {
249 u32 uif; /* uplink interface */ 258 u32 uif; /* uplink interface */
250 u32 status; /* status bits (see VNIC_STF_*) */ 259 u32 status; /* status bits (see VNIC_STF_*) */
251 u32 error; /* error code (see ERR_*) for first ERR */ 260 u32 error; /* error code (see ERR_*) for first ERR */
261 u32 link_down_cnt; /* running count of link down transitions */
252}; 262};
253#define VNIC_STF_FATAL_ERR 0x0001 /* fatal fw error */ 263#define VNIC_STF_FATAL_ERR 0x0001 /* fatal fw error */
264#define VNIC_STF_STD_PAUSE 0x0002 /* standard link-level pause on */
265#define VNIC_STF_PFC_PAUSE 0x0004 /* priority flow control pause on */
266/* all supported status flags */
267#define VNIC_STF_ALL (VNIC_STF_FATAL_ERR |\
268 VNIC_STF_STD_PAUSE |\
269 VNIC_STF_PFC_PAUSE |\
270 0)
254 271
255struct vnic_devcmd_provinfo { 272struct vnic_devcmd_provinfo {
256 u8 oui[3]; 273 u8 oui[3];