diff options
author | Ron Mercer <ron.mercer@qlogic.com> | 2009-02-26 05:08:35 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-02-27 01:28:09 -0500 |
commit | b0c2aadfa4d2194615ba8f5630be7ae686b9ed01 (patch) | |
tree | 4843831c1cf39df7aefb7fb5733753b9921805f2 /drivers/net | |
parent | 125844eaff0e9600c92a753995564fd93c807f3c (diff) |
qlge: Prepare to add new device.
This organizes a few calls into a function table to enable adding new
devices.
Signed-off-by: Ron Mercer <ron.mercer@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/qlge/qlge.h | 17 | ||||
-rw-r--r-- | drivers/net/qlge/qlge_main.c | 80 |
2 files changed, 78 insertions, 19 deletions
diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index 2103fe6ff3a5..7bf18c6d7bc0 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h | |||
@@ -28,7 +28,7 @@ | |||
28 | } while (0) | 28 | } while (0) |
29 | 29 | ||
30 | #define QLGE_VENDOR_ID 0x1077 | 30 | #define QLGE_VENDOR_ID 0x1077 |
31 | #define QLGE_DEVICE_ID 0x8012 | 31 | #define QLGE_DEVICE_ID_8012 0x8012 |
32 | 32 | ||
33 | #define MAX_CPUS 8 | 33 | #define MAX_CPUS 8 |
34 | #define MAX_TX_RINGS MAX_CPUS | 34 | #define MAX_TX_RINGS MAX_CPUS |
@@ -798,7 +798,7 @@ struct mbox_params { | |||
798 | int out_count; | 798 | int out_count; |
799 | }; | 799 | }; |
800 | 800 | ||
801 | struct flash_params { | 801 | struct flash_params_8012 { |
802 | u8 dev_id_str[4]; | 802 | u8 dev_id_str[4]; |
803 | __le16 size; | 803 | __le16 size; |
804 | __le16 csum; | 804 | __le16 csum; |
@@ -808,6 +808,9 @@ struct flash_params { | |||
808 | __le16 res; | 808 | __le16 res; |
809 | }; | 809 | }; |
810 | 810 | ||
811 | union flash_params { | ||
812 | struct flash_params_8012 flash_params_8012; | ||
813 | }; | ||
811 | 814 | ||
812 | /* | 815 | /* |
813 | * doorbell space for the rx ring context | 816 | * doorbell space for the rx ring context |
@@ -1367,6 +1370,12 @@ enum { | |||
1367 | CFG_DEFAULT_MAX_FRAME_SIZE = 0x00002580, | 1370 | CFG_DEFAULT_MAX_FRAME_SIZE = 0x00002580, |
1368 | }; | 1371 | }; |
1369 | 1372 | ||
1373 | struct nic_operations { | ||
1374 | |||
1375 | int (*get_flash) (struct ql_adapter *); | ||
1376 | int (*port_initialize) (struct ql_adapter *); | ||
1377 | }; | ||
1378 | |||
1370 | /* | 1379 | /* |
1371 | * The main Adapter structure definition. | 1380 | * The main Adapter structure definition. |
1372 | * This structure has all fields relevant to the hardware. | 1381 | * This structure has all fields relevant to the hardware. |
@@ -1444,7 +1453,7 @@ struct ql_adapter { | |||
1444 | u32 port_init; | 1453 | u32 port_init; |
1445 | u32 link_status; | 1454 | u32 link_status; |
1446 | 1455 | ||
1447 | struct flash_params flash; | 1456 | union flash_params flash; |
1448 | 1457 | ||
1449 | struct net_device_stats stats; | 1458 | struct net_device_stats stats; |
1450 | struct workqueue_struct *q_workqueue; | 1459 | struct workqueue_struct *q_workqueue; |
@@ -1452,6 +1461,8 @@ struct ql_adapter { | |||
1452 | struct delayed_work asic_reset_work; | 1461 | struct delayed_work asic_reset_work; |
1453 | struct delayed_work mpi_reset_work; | 1462 | struct delayed_work mpi_reset_work; |
1454 | struct delayed_work mpi_work; | 1463 | struct delayed_work mpi_work; |
1464 | struct nic_operations *nic_ops; | ||
1465 | u16 device_id; | ||
1455 | }; | 1466 | }; |
1456 | 1467 | ||
1457 | /* | 1468 | /* |
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index b144b6becfea..d1d8f05d5a11 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c | |||
@@ -75,7 +75,7 @@ module_param(irq_type, int, MSIX_IRQ); | |||
75 | MODULE_PARM_DESC(irq_type, "0 = MSI-X, 1 = MSI, 2 = Legacy."); | 75 | MODULE_PARM_DESC(irq_type, "0 = MSI-X, 1 = MSI, 2 = Legacy."); |
76 | 76 | ||
77 | static struct pci_device_id qlge_pci_tbl[] __devinitdata = { | 77 | static struct pci_device_id qlge_pci_tbl[] __devinitdata = { |
78 | {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QLGE_DEVICE_ID)}, | 78 | {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QLGE_DEVICE_ID_8012)}, |
79 | /* required last entry */ | 79 | /* required last entry */ |
80 | {0,} | 80 | {0,} |
81 | }; | 81 | }; |
@@ -623,6 +623,28 @@ static void ql_enable_all_completion_interrupts(struct ql_adapter *qdev) | |||
623 | 623 | ||
624 | } | 624 | } |
625 | 625 | ||
626 | static int ql_validate_flash(struct ql_adapter *qdev, u32 size, const char *str) | ||
627 | { | ||
628 | int status, i; | ||
629 | u16 csum = 0; | ||
630 | __le16 *flash = (__le16 *)&qdev->flash; | ||
631 | |||
632 | status = strncmp((char *)&qdev->flash, str, 4); | ||
633 | if (status) { | ||
634 | QPRINTK(qdev, IFUP, ERR, "Invalid flash signature.\n"); | ||
635 | return status; | ||
636 | } | ||
637 | |||
638 | for (i = 0; i < size; i++) | ||
639 | csum += le16_to_cpu(*flash++); | ||
640 | |||
641 | if (csum) | ||
642 | QPRINTK(qdev, IFUP, ERR, | ||
643 | "Invalid flash checksum, csum = 0x%.04x.\n", csum); | ||
644 | |||
645 | return csum; | ||
646 | } | ||
647 | |||
626 | static int ql_read_flash_word(struct ql_adapter *qdev, int offset, __le32 *data) | 648 | static int ql_read_flash_word(struct ql_adapter *qdev, int offset, __le32 *data) |
627 | { | 649 | { |
628 | int status = 0; | 650 | int status = 0; |
@@ -647,23 +669,24 @@ exit: | |||
647 | return status; | 669 | return status; |
648 | } | 670 | } |
649 | 671 | ||
650 | static int ql_get_flash_params(struct ql_adapter *qdev) | 672 | static int ql_get_8012_flash_params(struct ql_adapter *qdev) |
651 | { | 673 | { |
652 | int i; | 674 | int i; |
653 | int status; | 675 | int status; |
654 | __le32 *p = (__le32 *)&qdev->flash; | 676 | __le32 *p = (__le32 *)&qdev->flash; |
655 | u32 offset = 0; | 677 | u32 offset = 0; |
678 | u32 size = sizeof(struct flash_params_8012) / sizeof(u32); | ||
656 | 679 | ||
657 | /* Second function's parameters follow the first | 680 | /* Second function's parameters follow the first |
658 | * function's. | 681 | * function's. |
659 | */ | 682 | */ |
660 | if (qdev->func) | 683 | if (qdev->func) |
661 | offset = sizeof(qdev->flash) / sizeof(u32); | 684 | offset = size; |
662 | 685 | ||
663 | if (ql_sem_spinlock(qdev, SEM_FLASH_MASK)) | 686 | if (ql_sem_spinlock(qdev, SEM_FLASH_MASK)) |
664 | return -ETIMEDOUT; | 687 | return -ETIMEDOUT; |
665 | 688 | ||
666 | for (i = 0; i < sizeof(qdev->flash) / sizeof(u32); i++, p++) { | 689 | for (i = 0; i < size; i++, p++) { |
667 | status = ql_read_flash_word(qdev, i+offset, p); | 690 | status = ql_read_flash_word(qdev, i+offset, p); |
668 | if (status) { | 691 | if (status) { |
669 | QPRINTK(qdev, IFUP, ERR, "Error reading flash.\n"); | 692 | QPRINTK(qdev, IFUP, ERR, "Error reading flash.\n"); |
@@ -671,6 +694,25 @@ static int ql_get_flash_params(struct ql_adapter *qdev) | |||
671 | } | 694 | } |
672 | 695 | ||
673 | } | 696 | } |
697 | |||
698 | status = ql_validate_flash(qdev, | ||
699 | sizeof(struct flash_params_8012) / sizeof(u16), | ||
700 | "8012"); | ||
701 | if (status) { | ||
702 | QPRINTK(qdev, IFUP, ERR, "Invalid flash.\n"); | ||
703 | status = -EINVAL; | ||
704 | goto exit; | ||
705 | } | ||
706 | |||
707 | if (!is_valid_ether_addr(qdev->flash.flash_params_8012.mac_addr)) { | ||
708 | status = -EINVAL; | ||
709 | goto exit; | ||
710 | } | ||
711 | |||
712 | memcpy(qdev->ndev->dev_addr, | ||
713 | qdev->flash.flash_params_8012.mac_addr, | ||
714 | qdev->ndev->addr_len); | ||
715 | |||
674 | exit: | 716 | exit: |
675 | ql_sem_unlock(qdev, SEM_FLASH_MASK); | 717 | ql_sem_unlock(qdev, SEM_FLASH_MASK); |
676 | return status; | 718 | return status; |
@@ -747,7 +789,7 @@ exit: | |||
747 | * This functionality may be done in the MPI firmware at a | 789 | * This functionality may be done in the MPI firmware at a |
748 | * later date. | 790 | * later date. |
749 | */ | 791 | */ |
750 | static int ql_port_initialize(struct ql_adapter *qdev) | 792 | static int ql_8012_port_initialize(struct ql_adapter *qdev) |
751 | { | 793 | { |
752 | int status = 0; | 794 | int status = 0; |
753 | u32 data; | 795 | u32 data; |
@@ -2994,11 +3036,12 @@ static int ql_adapter_initialize(struct ql_adapter *qdev) | |||
2994 | } | 3036 | } |
2995 | } | 3037 | } |
2996 | 3038 | ||
2997 | status = ql_port_initialize(qdev); | 3039 | /* Initialize the port and set the max framesize. */ |
2998 | if (status) { | 3040 | status = qdev->nic_ops->port_initialize(qdev); |
2999 | QPRINTK(qdev, IFUP, ERR, "Failed to start port.\n"); | 3041 | if (status) { |
3000 | return status; | 3042 | QPRINTK(qdev, IFUP, ERR, "Failed to start port.\n"); |
3001 | } | 3043 | return status; |
3044 | } | ||
3002 | 3045 | ||
3003 | /* Set up the MAC address and frame routing filter. */ | 3046 | /* Set up the MAC address and frame routing filter. */ |
3004 | status = ql_cam_route_initialize(qdev); | 3047 | status = ql_cam_route_initialize(qdev); |
@@ -3509,6 +3552,12 @@ static void ql_asic_reset_work(struct work_struct *work) | |||
3509 | ql_cycle_adapter(qdev); | 3552 | ql_cycle_adapter(qdev); |
3510 | } | 3553 | } |
3511 | 3554 | ||
3555 | static struct nic_operations qla8012_nic_ops = { | ||
3556 | .get_flash = ql_get_8012_flash_params, | ||
3557 | .port_initialize = ql_8012_port_initialize, | ||
3558 | }; | ||
3559 | |||
3560 | |||
3512 | static void ql_get_board_info(struct ql_adapter *qdev) | 3561 | static void ql_get_board_info(struct ql_adapter *qdev) |
3513 | { | 3562 | { |
3514 | qdev->func = | 3563 | qdev->func = |
@@ -3527,6 +3576,9 @@ static void ql_get_board_info(struct ql_adapter *qdev) | |||
3527 | qdev->mailbox_out = PROC_ADDR_MPI_RISC | PROC_ADDR_FUNC0_MBO; | 3576 | qdev->mailbox_out = PROC_ADDR_MPI_RISC | PROC_ADDR_FUNC0_MBO; |
3528 | } | 3577 | } |
3529 | qdev->chip_rev_id = ql_read32(qdev, REV_ID); | 3578 | qdev->chip_rev_id = ql_read32(qdev, REV_ID); |
3579 | qdev->device_id = qdev->pdev->device; | ||
3580 | if (qdev->device_id == QLGE_DEVICE_ID_8012) | ||
3581 | qdev->nic_ops = &qla8012_nic_ops; | ||
3530 | } | 3582 | } |
3531 | 3583 | ||
3532 | static void ql_release_all(struct pci_dev *pdev) | 3584 | static void ql_release_all(struct pci_dev *pdev) |
@@ -3619,24 +3671,20 @@ static int __devinit ql_init_device(struct pci_dev *pdev, | |||
3619 | goto err_out; | 3671 | goto err_out; |
3620 | } | 3672 | } |
3621 | 3673 | ||
3622 | ql_get_board_info(qdev); | ||
3623 | qdev->ndev = ndev; | 3674 | qdev->ndev = ndev; |
3624 | qdev->pdev = pdev; | 3675 | qdev->pdev = pdev; |
3676 | ql_get_board_info(qdev); | ||
3625 | qdev->msg_enable = netif_msg_init(debug, default_msg); | 3677 | qdev->msg_enable = netif_msg_init(debug, default_msg); |
3626 | spin_lock_init(&qdev->hw_lock); | 3678 | spin_lock_init(&qdev->hw_lock); |
3627 | spin_lock_init(&qdev->stats_lock); | 3679 | spin_lock_init(&qdev->stats_lock); |
3628 | 3680 | ||
3629 | /* make sure the EEPROM is good */ | 3681 | /* make sure the EEPROM is good */ |
3630 | err = ql_get_flash_params(qdev); | 3682 | err = qdev->nic_ops->get_flash(qdev); |
3631 | if (err) { | 3683 | if (err) { |
3632 | dev_err(&pdev->dev, "Invalid FLASH.\n"); | 3684 | dev_err(&pdev->dev, "Invalid FLASH.\n"); |
3633 | goto err_out; | 3685 | goto err_out; |
3634 | } | 3686 | } |
3635 | 3687 | ||
3636 | if (!is_valid_ether_addr(qdev->flash.mac_addr)) | ||
3637 | goto err_out; | ||
3638 | |||
3639 | memcpy(ndev->dev_addr, qdev->flash.mac_addr, ndev->addr_len); | ||
3640 | memcpy(ndev->perm_addr, ndev->dev_addr, ndev->addr_len); | 3688 | memcpy(ndev->perm_addr, ndev->dev_addr, ndev->addr_len); |
3641 | 3689 | ||
3642 | /* Set up the default ring sizes. */ | 3690 | /* Set up the default ring sizes. */ |