diff options
author | David S. Miller <davem@davemloft.net> | 2009-10-12 02:15:47 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-10-12 02:15:47 -0400 |
commit | 7fe13c5733790ef582769a54693fa6a5abf3c032 (patch) | |
tree | 567eb4394b642ddc81ff05521329d75d1cf47b88 /drivers/net/qlge | |
parent | 8aa0f64ac3835a6daf84d0b0e07c4c01d7d8eddc (diff) | |
parent | 10c435f18b8cb78a5870c08d52955594f5ec9c31 (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Diffstat (limited to 'drivers/net/qlge')
-rw-r--r-- | drivers/net/qlge/qlge.h | 10 | ||||
-rw-r--r-- | drivers/net/qlge/qlge_main.c | 97 | ||||
-rw-r--r-- | drivers/net/qlge/qlge_mpi.c | 93 |
3 files changed, 177 insertions, 23 deletions
diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index 9e53ca9c3b43..f6bd22495f55 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h | |||
@@ -803,6 +803,12 @@ enum { | |||
803 | MB_CMD_SET_PORT_CFG = 0x00000122, | 803 | MB_CMD_SET_PORT_CFG = 0x00000122, |
804 | MB_CMD_GET_PORT_CFG = 0x00000123, | 804 | MB_CMD_GET_PORT_CFG = 0x00000123, |
805 | MB_CMD_GET_LINK_STS = 0x00000124, | 805 | MB_CMD_GET_LINK_STS = 0x00000124, |
806 | MB_CMD_SET_MGMNT_TFK_CTL = 0x00000160, /* Set Mgmnt Traffic Control */ | ||
807 | MB_SET_MPI_TFK_STOP = (1 << 0), | ||
808 | MB_SET_MPI_TFK_RESUME = (1 << 1), | ||
809 | MB_CMD_GET_MGMNT_TFK_CTL = 0x00000161, /* Get Mgmnt Traffic Control */ | ||
810 | MB_GET_MPI_TFK_STOPPED = (1 << 0), | ||
811 | MB_GET_MPI_TFK_FIFO_EMPTY = (1 << 1), | ||
806 | 812 | ||
807 | /* Mailbox Command Status. */ | 813 | /* Mailbox Command Status. */ |
808 | MB_CMD_STS_GOOD = 0x00004000, /* Success. */ | 814 | MB_CMD_STS_GOOD = 0x00004000, /* Success. */ |
@@ -1168,7 +1174,7 @@ struct ricb { | |||
1168 | #define RSS_RI6 0x40 | 1174 | #define RSS_RI6 0x40 |
1169 | #define RSS_RT6 0x80 | 1175 | #define RSS_RT6 0x80 |
1170 | __le16 mask; | 1176 | __le16 mask; |
1171 | __le32 hash_cq_id[256]; | 1177 | u8 hash_cq_id[1024]; |
1172 | __le32 ipv6_hash_key[10]; | 1178 | __le32 ipv6_hash_key[10]; |
1173 | __le32 ipv4_hash_key[4]; | 1179 | __le32 ipv4_hash_key[4]; |
1174 | } __attribute((packed)); | 1180 | } __attribute((packed)); |
@@ -1605,6 +1611,8 @@ int ql_read_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 *data); | |||
1605 | int ql_mb_about_fw(struct ql_adapter *qdev); | 1611 | int ql_mb_about_fw(struct ql_adapter *qdev); |
1606 | void ql_link_on(struct ql_adapter *qdev); | 1612 | void ql_link_on(struct ql_adapter *qdev); |
1607 | void ql_link_off(struct ql_adapter *qdev); | 1613 | void ql_link_off(struct ql_adapter *qdev); |
1614 | int ql_mb_set_mgmnt_traffic_ctl(struct ql_adapter *qdev, u32 control); | ||
1615 | int ql_wait_fifo_empty(struct ql_adapter *qdev); | ||
1608 | 1616 | ||
1609 | #if 1 | 1617 | #if 1 |
1610 | #define QL_ALL_DUMP | 1618 | #define QL_ALL_DUMP |
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index fde5af0d5b46..cd093db29ada 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c | |||
@@ -320,6 +320,37 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type, | |||
320 | 320 | ||
321 | switch (type) { | 321 | switch (type) { |
322 | case MAC_ADDR_TYPE_MULTI_MAC: | 322 | case MAC_ADDR_TYPE_MULTI_MAC: |
323 | { | ||
324 | u32 upper = (addr[0] << 8) | addr[1]; | ||
325 | u32 lower = (addr[2] << 24) | (addr[3] << 16) | | ||
326 | (addr[4] << 8) | (addr[5]); | ||
327 | |||
328 | status = | ||
329 | ql_wait_reg_rdy(qdev, | ||
330 | MAC_ADDR_IDX, MAC_ADDR_MW, 0); | ||
331 | if (status) | ||
332 | goto exit; | ||
333 | ql_write32(qdev, MAC_ADDR_IDX, (offset++) | | ||
334 | (index << MAC_ADDR_IDX_SHIFT) | | ||
335 | type | MAC_ADDR_E); | ||
336 | ql_write32(qdev, MAC_ADDR_DATA, lower); | ||
337 | status = | ||
338 | ql_wait_reg_rdy(qdev, | ||
339 | MAC_ADDR_IDX, MAC_ADDR_MW, 0); | ||
340 | if (status) | ||
341 | goto exit; | ||
342 | ql_write32(qdev, MAC_ADDR_IDX, (offset++) | | ||
343 | (index << MAC_ADDR_IDX_SHIFT) | | ||
344 | type | MAC_ADDR_E); | ||
345 | |||
346 | ql_write32(qdev, MAC_ADDR_DATA, upper); | ||
347 | status = | ||
348 | ql_wait_reg_rdy(qdev, | ||
349 | MAC_ADDR_IDX, MAC_ADDR_MW, 0); | ||
350 | if (status) | ||
351 | goto exit; | ||
352 | break; | ||
353 | } | ||
323 | case MAC_ADDR_TYPE_CAM_MAC: | 354 | case MAC_ADDR_TYPE_CAM_MAC: |
324 | { | 355 | { |
325 | u32 cam_output; | 356 | u32 cam_output; |
@@ -365,16 +396,14 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type, | |||
365 | and possibly the function id. Right now we hardcode | 396 | and possibly the function id. Right now we hardcode |
366 | the route field to NIC core. | 397 | the route field to NIC core. |
367 | */ | 398 | */ |
368 | if (type == MAC_ADDR_TYPE_CAM_MAC) { | 399 | cam_output = (CAM_OUT_ROUTE_NIC | |
369 | cam_output = (CAM_OUT_ROUTE_NIC | | 400 | (qdev-> |
370 | (qdev-> | 401 | func << CAM_OUT_FUNC_SHIFT) | |
371 | func << CAM_OUT_FUNC_SHIFT) | | 402 | (0 << CAM_OUT_CQ_ID_SHIFT)); |
372 | (0 << CAM_OUT_CQ_ID_SHIFT)); | 403 | if (qdev->vlgrp) |
373 | if (qdev->vlgrp) | 404 | cam_output |= CAM_OUT_RV; |
374 | cam_output |= CAM_OUT_RV; | 405 | /* route to NIC core */ |
375 | /* route to NIC core */ | 406 | ql_write32(qdev, MAC_ADDR_DATA, cam_output); |
376 | ql_write32(qdev, MAC_ADDR_DATA, cam_output); | ||
377 | } | ||
378 | break; | 407 | break; |
379 | } | 408 | } |
380 | case MAC_ADDR_TYPE_VLAN: | 409 | case MAC_ADDR_TYPE_VLAN: |
@@ -546,14 +575,14 @@ static int ql_set_routing_reg(struct ql_adapter *qdev, u32 index, u32 mask, | |||
546 | } | 575 | } |
547 | case RT_IDX_MCAST: /* Pass up All Multicast frames. */ | 576 | case RT_IDX_MCAST: /* Pass up All Multicast frames. */ |
548 | { | 577 | { |
549 | value = RT_IDX_DST_CAM_Q | /* dest */ | 578 | value = RT_IDX_DST_DFLT_Q | /* dest */ |
550 | RT_IDX_TYPE_NICQ | /* type */ | 579 | RT_IDX_TYPE_NICQ | /* type */ |
551 | (RT_IDX_ALLMULTI_SLOT << RT_IDX_IDX_SHIFT);/* index */ | 580 | (RT_IDX_ALLMULTI_SLOT << RT_IDX_IDX_SHIFT);/* index */ |
552 | break; | 581 | break; |
553 | } | 582 | } |
554 | case RT_IDX_MCAST_MATCH: /* Pass up matched Multicast frames. */ | 583 | case RT_IDX_MCAST_MATCH: /* Pass up matched Multicast frames. */ |
555 | { | 584 | { |
556 | value = RT_IDX_DST_CAM_Q | /* dest */ | 585 | value = RT_IDX_DST_DFLT_Q | /* dest */ |
557 | RT_IDX_TYPE_NICQ | /* type */ | 586 | RT_IDX_TYPE_NICQ | /* type */ |
558 | (RT_IDX_MCAST_MATCH_SLOT << RT_IDX_IDX_SHIFT);/* index */ | 587 | (RT_IDX_MCAST_MATCH_SLOT << RT_IDX_IDX_SHIFT);/* index */ |
559 | break; | 588 | break; |
@@ -3078,6 +3107,12 @@ err_irq: | |||
3078 | 3107 | ||
3079 | static int ql_start_rss(struct ql_adapter *qdev) | 3108 | static int ql_start_rss(struct ql_adapter *qdev) |
3080 | { | 3109 | { |
3110 | u8 init_hash_seed[] = {0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2, | ||
3111 | 0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, | ||
3112 | 0xb0, 0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, | ||
3113 | 0x30, 0xb4, 0x77, 0xcb, 0x2d, 0xa3, 0x80, | ||
3114 | 0x30, 0xf2, 0x0c, 0x6a, 0x42, 0xb7, 0x3b, | ||
3115 | 0xbe, 0xac, 0x01, 0xfa}; | ||
3081 | struct ricb *ricb = &qdev->ricb; | 3116 | struct ricb *ricb = &qdev->ricb; |
3082 | int status = 0; | 3117 | int status = 0; |
3083 | int i; | 3118 | int i; |
@@ -3087,21 +3122,17 @@ static int ql_start_rss(struct ql_adapter *qdev) | |||
3087 | 3122 | ||
3088 | ricb->base_cq = RSS_L4K; | 3123 | ricb->base_cq = RSS_L4K; |
3089 | ricb->flags = | 3124 | ricb->flags = |
3090 | (RSS_L6K | RSS_LI | RSS_LB | RSS_LM | RSS_RI4 | RSS_RI6 | RSS_RT4 | | 3125 | (RSS_L6K | RSS_LI | RSS_LB | RSS_LM | RSS_RT4 | RSS_RT6); |
3091 | RSS_RT6); | 3126 | ricb->mask = cpu_to_le16((u16)(0x3ff)); |
3092 | ricb->mask = cpu_to_le16(qdev->rss_ring_count - 1); | ||
3093 | 3127 | ||
3094 | /* | 3128 | /* |
3095 | * Fill out the Indirection Table. | 3129 | * Fill out the Indirection Table. |
3096 | */ | 3130 | */ |
3097 | for (i = 0; i < 256; i++) | 3131 | for (i = 0; i < 1024; i++) |
3098 | hash_id[i] = i & (qdev->rss_ring_count - 1); | 3132 | hash_id[i] = (i & (qdev->rss_ring_count - 1)); |
3099 | 3133 | ||
3100 | /* | 3134 | memcpy((void *)&ricb->ipv6_hash_key[0], init_hash_seed, 40); |
3101 | * Random values for the IPv6 and IPv4 Hash Keys. | 3135 | memcpy((void *)&ricb->ipv4_hash_key[0], init_hash_seed, 16); |
3102 | */ | ||
3103 | get_random_bytes((void *)&ricb->ipv6_hash_key[0], 40); | ||
3104 | get_random_bytes((void *)&ricb->ipv4_hash_key[0], 16); | ||
3105 | 3136 | ||
3106 | QPRINTK(qdev, IFUP, DEBUG, "Initializing RSS.\n"); | 3137 | QPRINTK(qdev, IFUP, DEBUG, "Initializing RSS.\n"); |
3107 | 3138 | ||
@@ -3240,6 +3271,13 @@ static int ql_adapter_initialize(struct ql_adapter *qdev) | |||
3240 | ql_write32(qdev, SPLT_HDR, SPLT_HDR_EP | | 3271 | ql_write32(qdev, SPLT_HDR, SPLT_HDR_EP | |
3241 | min(SMALL_BUFFER_SIZE, MAX_SPLIT_SIZE)); | 3272 | min(SMALL_BUFFER_SIZE, MAX_SPLIT_SIZE)); |
3242 | 3273 | ||
3274 | /* Set RX packet routing to use port/pci function on which the | ||
3275 | * packet arrived on in addition to usual frame routing. | ||
3276 | * This is helpful on bonding where both interfaces can have | ||
3277 | * the same MAC address. | ||
3278 | */ | ||
3279 | ql_write32(qdev, RST_FO, RST_FO_RR_MASK | RST_FO_RR_RCV_FUNC_CQ); | ||
3280 | |||
3243 | /* Start up the rx queues. */ | 3281 | /* Start up the rx queues. */ |
3244 | for (i = 0; i < qdev->rx_ring_count; i++) { | 3282 | for (i = 0; i < qdev->rx_ring_count; i++) { |
3245 | status = ql_start_rx_ring(qdev, &qdev->rx_ring[i]); | 3283 | status = ql_start_rx_ring(qdev, &qdev->rx_ring[i]); |
@@ -3312,6 +3350,13 @@ static int ql_adapter_reset(struct ql_adapter *qdev) | |||
3312 | 3350 | ||
3313 | end_jiffies = jiffies + | 3351 | end_jiffies = jiffies + |
3314 | max((unsigned long)1, usecs_to_jiffies(30)); | 3352 | max((unsigned long)1, usecs_to_jiffies(30)); |
3353 | |||
3354 | /* Stop management traffic. */ | ||
3355 | ql_mb_set_mgmnt_traffic_ctl(qdev, MB_SET_MPI_TFK_STOP); | ||
3356 | |||
3357 | /* Wait for the NIC and MGMNT FIFOs to empty. */ | ||
3358 | ql_wait_fifo_empty(qdev); | ||
3359 | |||
3315 | ql_write32(qdev, RST_FO, (RST_FO_FR << 16) | RST_FO_FR); | 3360 | ql_write32(qdev, RST_FO, (RST_FO_FR << 16) | RST_FO_FR); |
3316 | 3361 | ||
3317 | do { | 3362 | do { |
@@ -3327,6 +3372,8 @@ static int ql_adapter_reset(struct ql_adapter *qdev) | |||
3327 | status = -ETIMEDOUT; | 3372 | status = -ETIMEDOUT; |
3328 | } | 3373 | } |
3329 | 3374 | ||
3375 | /* Resume management traffic. */ | ||
3376 | ql_mb_set_mgmnt_traffic_ctl(qdev, MB_SET_MPI_TFK_RESUME); | ||
3330 | return status; | 3377 | return status; |
3331 | } | 3378 | } |
3332 | 3379 | ||
@@ -3704,6 +3751,12 @@ static void ql_asic_reset_work(struct work_struct *work) | |||
3704 | status = ql_adapter_up(qdev); | 3751 | status = ql_adapter_up(qdev); |
3705 | if (status) | 3752 | if (status) |
3706 | goto error; | 3753 | goto error; |
3754 | |||
3755 | /* Restore rx mode. */ | ||
3756 | clear_bit(QL_ALLMULTI, &qdev->flags); | ||
3757 | clear_bit(QL_PROMISCUOUS, &qdev->flags); | ||
3758 | qlge_set_multicast_list(qdev->ndev); | ||
3759 | |||
3707 | rtnl_unlock(); | 3760 | rtnl_unlock(); |
3708 | return; | 3761 | return; |
3709 | error: | 3762 | error: |
diff --git a/drivers/net/qlge/qlge_mpi.c b/drivers/net/qlge/qlge_mpi.c index c2e43073047e..99e58e3f8e22 100644 --- a/drivers/net/qlge/qlge_mpi.c +++ b/drivers/net/qlge/qlge_mpi.c | |||
@@ -768,6 +768,95 @@ static int ql_idc_wait(struct ql_adapter *qdev) | |||
768 | return status; | 768 | return status; |
769 | } | 769 | } |
770 | 770 | ||
771 | int ql_mb_set_mgmnt_traffic_ctl(struct ql_adapter *qdev, u32 control) | ||
772 | { | ||
773 | struct mbox_params mbc; | ||
774 | struct mbox_params *mbcp = &mbc; | ||
775 | int status; | ||
776 | |||
777 | memset(mbcp, 0, sizeof(struct mbox_params)); | ||
778 | |||
779 | mbcp->in_count = 1; | ||
780 | mbcp->out_count = 2; | ||
781 | |||
782 | mbcp->mbox_in[0] = MB_CMD_SET_MGMNT_TFK_CTL; | ||
783 | mbcp->mbox_in[1] = control; | ||
784 | |||
785 | status = ql_mailbox_command(qdev, mbcp); | ||
786 | if (status) | ||
787 | return status; | ||
788 | |||
789 | if (mbcp->mbox_out[0] == MB_CMD_STS_GOOD) | ||
790 | return status; | ||
791 | |||
792 | if (mbcp->mbox_out[0] == MB_CMD_STS_INVLD_CMD) { | ||
793 | QPRINTK(qdev, DRV, ERR, | ||
794 | "Command not supported by firmware.\n"); | ||
795 | status = -EINVAL; | ||
796 | } else if (mbcp->mbox_out[0] == MB_CMD_STS_ERR) { | ||
797 | /* This indicates that the firmware is | ||
798 | * already in the state we are trying to | ||
799 | * change it to. | ||
800 | */ | ||
801 | QPRINTK(qdev, DRV, ERR, | ||
802 | "Command parameters make no change.\n"); | ||
803 | } | ||
804 | return status; | ||
805 | } | ||
806 | |||
807 | /* Returns a negative error code or the mailbox command status. */ | ||
808 | static int ql_mb_get_mgmnt_traffic_ctl(struct ql_adapter *qdev, u32 *control) | ||
809 | { | ||
810 | struct mbox_params mbc; | ||
811 | struct mbox_params *mbcp = &mbc; | ||
812 | int status; | ||
813 | |||
814 | memset(mbcp, 0, sizeof(struct mbox_params)); | ||
815 | *control = 0; | ||
816 | |||
817 | mbcp->in_count = 1; | ||
818 | mbcp->out_count = 1; | ||
819 | |||
820 | mbcp->mbox_in[0] = MB_CMD_GET_MGMNT_TFK_CTL; | ||
821 | |||
822 | status = ql_mailbox_command(qdev, mbcp); | ||
823 | if (status) | ||
824 | return status; | ||
825 | |||
826 | if (mbcp->mbox_out[0] == MB_CMD_STS_GOOD) { | ||
827 | *control = mbcp->mbox_in[1]; | ||
828 | return status; | ||
829 | } | ||
830 | |||
831 | if (mbcp->mbox_out[0] == MB_CMD_STS_INVLD_CMD) { | ||
832 | QPRINTK(qdev, DRV, ERR, | ||
833 | "Command not supported by firmware.\n"); | ||
834 | status = -EINVAL; | ||
835 | } else if (mbcp->mbox_out[0] == MB_CMD_STS_ERR) { | ||
836 | QPRINTK(qdev, DRV, ERR, | ||
837 | "Failed to get MPI traffic control.\n"); | ||
838 | status = -EIO; | ||
839 | } | ||
840 | return status; | ||
841 | } | ||
842 | |||
843 | int ql_wait_fifo_empty(struct ql_adapter *qdev) | ||
844 | { | ||
845 | int count = 5; | ||
846 | u32 mgmnt_fifo_empty; | ||
847 | u32 nic_fifo_empty; | ||
848 | |||
849 | do { | ||
850 | nic_fifo_empty = ql_read32(qdev, STS) & STS_NFE; | ||
851 | ql_mb_get_mgmnt_traffic_ctl(qdev, &mgmnt_fifo_empty); | ||
852 | mgmnt_fifo_empty &= MB_GET_MPI_TFK_FIFO_EMPTY; | ||
853 | if (nic_fifo_empty && mgmnt_fifo_empty) | ||
854 | return 0; | ||
855 | msleep(100); | ||
856 | } while (count-- > 0); | ||
857 | return -ETIMEDOUT; | ||
858 | } | ||
859 | |||
771 | /* API called in work thread context to set new TX/RX | 860 | /* API called in work thread context to set new TX/RX |
772 | * maximum frame size values to match MTU. | 861 | * maximum frame size values to match MTU. |
773 | */ | 862 | */ |
@@ -876,6 +965,8 @@ void ql_mpi_work(struct work_struct *work) | |||
876 | int err = 0; | 965 | int err = 0; |
877 | 966 | ||
878 | rtnl_lock(); | 967 | rtnl_lock(); |
968 | /* Begin polled mode for MPI */ | ||
969 | ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16)); | ||
879 | 970 | ||
880 | while (ql_read32(qdev, STS) & STS_PI) { | 971 | while (ql_read32(qdev, STS) & STS_PI) { |
881 | memset(mbcp, 0, sizeof(struct mbox_params)); | 972 | memset(mbcp, 0, sizeof(struct mbox_params)); |
@@ -888,6 +979,8 @@ void ql_mpi_work(struct work_struct *work) | |||
888 | break; | 979 | break; |
889 | } | 980 | } |
890 | 981 | ||
982 | /* End polled mode for MPI */ | ||
983 | ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16) | INTR_MASK_PI); | ||
891 | rtnl_unlock(); | 984 | rtnl_unlock(); |
892 | ql_enable_completion_interrupt(qdev, 0); | 985 | ql_enable_completion_interrupt(qdev, 0); |
893 | } | 986 | } |