diff options
author | Sony Chacko <sony.chacko@qlogic.com> | 2012-12-31 22:20:20 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-01-02 05:43:26 -0500 |
commit | 4be41e92f7c613d6c08686374ad0fdeaaa2a7280 (patch) | |
tree | ee5a37cf0fb67dacaf9d741c3cf47e16f6e55268 /drivers/net/ethernet/qlogic/qlcnic | |
parent | 7f9664525f9cb507de9198a395a111371413f230 (diff) |
qlcnic: 83xx data path routines
Add 83xx adapter data path routines
Update few 82xx adapter data path routines
Modify datapath resource allocation routines
Signed-off-by: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
Signed-off-by: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Signed-off-by: Sritej Velaga <sritej.velaga@qlogic.com>
Signed-off-by: Sony Chacko <sony.chacko@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/qlogic/qlcnic')
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 13 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 5 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h | 8 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c | 71 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c | 38 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c | 592 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 82 |
7 files changed, 676 insertions, 133 deletions
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index 2b7adda619bb..31cf1b1cdf6c 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | |||
@@ -431,6 +431,7 @@ struct qlcnic_adapter_stats { | |||
431 | u64 rx_dma_map_error; | 431 | u64 rx_dma_map_error; |
432 | u64 tx_dma_map_error; | 432 | u64 tx_dma_map_error; |
433 | u64 spurious_intr; | 433 | u64 spurious_intr; |
434 | u64 mac_filter_limit_overrun; | ||
434 | }; | 435 | }; |
435 | 436 | ||
436 | /* | 437 | /* |
@@ -469,6 +470,7 @@ struct qlcnic_host_sds_ring { | |||
469 | } ____cacheline_internodealigned_in_smp; | 470 | } ____cacheline_internodealigned_in_smp; |
470 | 471 | ||
471 | struct qlcnic_host_tx_ring { | 472 | struct qlcnic_host_tx_ring { |
473 | int irq; | ||
472 | void __iomem *crb_intr_mask; | 474 | void __iomem *crb_intr_mask; |
473 | char name[IFNAMSIZ+4]; | 475 | char name[IFNAMSIZ+4]; |
474 | u16 ctx_id; | 476 | u16 ctx_id; |
@@ -477,6 +479,8 @@ struct qlcnic_host_tx_ring { | |||
477 | u32 num_desc; | 479 | u32 num_desc; |
478 | void __iomem *crb_cmd_producer; | 480 | void __iomem *crb_cmd_producer; |
479 | struct cmd_desc_type0 *desc_head; | 481 | struct cmd_desc_type0 *desc_head; |
482 | struct qlcnic_adapter *adapter; | ||
483 | struct napi_struct napi; | ||
480 | struct qlcnic_cmd_buffer *cmd_buf_arr; | 484 | struct qlcnic_cmd_buffer *cmd_buf_arr; |
481 | __le32 *hw_consumer; | 485 | __le32 *hw_consumer; |
482 | 486 | ||
@@ -1402,7 +1406,7 @@ void qlcnic_release_tx_buffers(struct qlcnic_adapter *adapter); | |||
1402 | int qlcnic_check_fw_status(struct qlcnic_adapter *adapter); | 1406 | int qlcnic_check_fw_status(struct qlcnic_adapter *adapter); |
1403 | void qlcnic_watchdog_task(struct work_struct *work); | 1407 | void qlcnic_watchdog_task(struct work_struct *work); |
1404 | void qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter, | 1408 | void qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter, |
1405 | struct qlcnic_host_rds_ring *rds_ring); | 1409 | struct qlcnic_host_rds_ring *rds_ring, u8 ring_id); |
1406 | int qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max); | 1410 | int qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max); |
1407 | void qlcnic_set_multi(struct net_device *netdev); | 1411 | void qlcnic_set_multi(struct net_device *netdev); |
1408 | void qlcnic_free_mac_list(struct qlcnic_adapter *adapter); | 1412 | void qlcnic_free_mac_list(struct qlcnic_adapter *adapter); |
@@ -1443,7 +1447,6 @@ int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, u8, u8, u8); | |||
1443 | int qlcnic_get_mac_stats(struct qlcnic_adapter *, struct qlcnic_mac_statistics *); | 1447 | int qlcnic_get_mac_stats(struct qlcnic_adapter *, struct qlcnic_mac_statistics *); |
1444 | 1448 | ||
1445 | void qlcnic_free_mbx_args(struct qlcnic_cmd_args *cmd); | 1449 | void qlcnic_free_mbx_args(struct qlcnic_cmd_args *cmd); |
1446 | void qlcnic_napi_del(struct qlcnic_adapter *); | ||
1447 | 1450 | ||
1448 | int qlcnic_alloc_sds_rings(struct qlcnic_recv_context *, int); | 1451 | int qlcnic_alloc_sds_rings(struct qlcnic_recv_context *, int); |
1449 | void qlcnic_free_sds_rings(struct qlcnic_recv_context *); | 1452 | void qlcnic_free_sds_rings(struct qlcnic_recv_context *); |
@@ -1495,6 +1498,7 @@ struct qlcnic_nic_template { | |||
1495 | void (*request_reset) (struct qlcnic_adapter *, u32); | 1498 | void (*request_reset) (struct qlcnic_adapter *, u32); |
1496 | void (*cancel_idc_work) (struct qlcnic_adapter *); | 1499 | void (*cancel_idc_work) (struct qlcnic_adapter *); |
1497 | int (*napi_add)(struct qlcnic_adapter *, struct net_device *); | 1500 | int (*napi_add)(struct qlcnic_adapter *, struct net_device *); |
1501 | void (*napi_del)(struct qlcnic_adapter *); | ||
1498 | void (*config_ipaddr)(struct qlcnic_adapter *, __be32, int); | 1502 | void (*config_ipaddr)(struct qlcnic_adapter *, __be32, int); |
1499 | irqreturn_t (*clear_legacy_intr)(struct qlcnic_adapter *); | 1503 | irqreturn_t (*clear_legacy_intr)(struct qlcnic_adapter *); |
1500 | }; | 1504 | }; |
@@ -1670,6 +1674,11 @@ static inline int qlcnic_napi_add(struct qlcnic_adapter *adapter, | |||
1670 | return adapter->nic_ops->napi_add(adapter, netdev); | 1674 | return adapter->nic_ops->napi_add(adapter, netdev); |
1671 | } | 1675 | } |
1672 | 1676 | ||
1677 | static inline void qlcnic_napi_del(struct qlcnic_adapter *adapter) | ||
1678 | { | ||
1679 | adapter->nic_ops->napi_del(adapter); | ||
1680 | } | ||
1681 | |||
1673 | static inline void qlcnic_napi_enable(struct qlcnic_adapter *adapter) | 1682 | static inline void qlcnic_napi_enable(struct qlcnic_adapter *adapter) |
1674 | { | 1683 | { |
1675 | adapter->ahw->hw_ops->napi_enable(adapter); | 1684 | adapter->ahw->hw_ops->napi_enable(adapter); |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c index 454cd9f2e545..b2b024c9f3ea 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | |||
@@ -242,6 +242,7 @@ static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = { | |||
242 | .get_func_no = qlcnic_83xx_get_func_no, | 242 | .get_func_no = qlcnic_83xx_get_func_no, |
243 | .api_lock = qlcnic_83xx_cam_lock, | 243 | .api_lock = qlcnic_83xx_cam_lock, |
244 | .api_unlock = qlcnic_83xx_cam_unlock, | 244 | .api_unlock = qlcnic_83xx_cam_unlock, |
245 | .process_lb_rcv_ring_diag = qlcnic_83xx_process_rcv_ring_diag, | ||
245 | .create_rx_ctx = qlcnic_83xx_create_rx_ctx, | 246 | .create_rx_ctx = qlcnic_83xx_create_rx_ctx, |
246 | .create_tx_ctx = qlcnic_83xx_create_tx_ctx, | 247 | .create_tx_ctx = qlcnic_83xx_create_tx_ctx, |
247 | .setup_link_event = qlcnic_83xx_setup_link_event, | 248 | .setup_link_event = qlcnic_83xx_setup_link_event, |
@@ -249,6 +250,8 @@ static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = { | |||
249 | .get_pci_info = qlcnic_83xx_get_pci_info, | 250 | .get_pci_info = qlcnic_83xx_get_pci_info, |
250 | .set_nic_info = qlcnic_83xx_set_nic_info, | 251 | .set_nic_info = qlcnic_83xx_set_nic_info, |
251 | .change_macvlan = qlcnic_83xx_sre_macaddr_change, | 252 | .change_macvlan = qlcnic_83xx_sre_macaddr_change, |
253 | .napi_enable = qlcnic_83xx_napi_enable, | ||
254 | .napi_disable = qlcnic_83xx_napi_disable, | ||
252 | .config_intr_coal = qlcnic_83xx_config_intr_coal, | 255 | .config_intr_coal = qlcnic_83xx_config_intr_coal, |
253 | .config_rss = qlcnic_83xx_config_rss, | 256 | .config_rss = qlcnic_83xx_config_rss, |
254 | .config_hw_lro = qlcnic_83xx_config_hw_lro, | 257 | .config_hw_lro = qlcnic_83xx_config_hw_lro, |
@@ -262,6 +265,8 @@ static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = { | |||
262 | static struct qlcnic_nic_template qlcnic_83xx_ops = { | 265 | static struct qlcnic_nic_template qlcnic_83xx_ops = { |
263 | .config_bridged_mode = qlcnic_config_bridged_mode, | 266 | .config_bridged_mode = qlcnic_config_bridged_mode, |
264 | .config_led = qlcnic_config_led, | 267 | .config_led = qlcnic_config_led, |
268 | .napi_add = qlcnic_83xx_napi_add, | ||
269 | .napi_del = qlcnic_83xx_napi_del, | ||
265 | .config_ipaddr = qlcnic_83xx_config_ipaddr, | 270 | .config_ipaddr = qlcnic_83xx_config_ipaddr, |
266 | .clear_legacy_intr = qlcnic_83xx_clear_legacy_intr, | 271 | .clear_legacy_intr = qlcnic_83xx_clear_legacy_intr, |
267 | }; | 272 | }; |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h index 9d707be27ca2..e2cfc86f925a 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h | |||
@@ -193,8 +193,7 @@ void qlcnic_83xx_write_crb(struct qlcnic_adapter *, char *, loff_t, size_t); | |||
193 | void qlcnic_83xx_read_crb(struct qlcnic_adapter *, char *, loff_t, size_t); | 193 | void qlcnic_83xx_read_crb(struct qlcnic_adapter *, char *, loff_t, size_t); |
194 | int qlcnic_83xx_rd_reg_indirect(struct qlcnic_adapter *, ulong); | 194 | int qlcnic_83xx_rd_reg_indirect(struct qlcnic_adapter *, ulong); |
195 | int qlcnic_83xx_wrt_reg_indirect(struct qlcnic_adapter *, ulong, u32); | 195 | int qlcnic_83xx_wrt_reg_indirect(struct qlcnic_adapter *, ulong, u32); |
196 | void qlcnic_83xx_process_rcv_diag(struct qlcnic_adapter *, | 196 | void qlcnic_83xx_process_rcv_diag(struct qlcnic_adapter *, int, u64 []); |
197 | struct qlcnic_host_sds_ring *, int, u64 []); | ||
198 | int qlcnic_83xx_nic_set_promisc(struct qlcnic_adapter *, u32); | 197 | int qlcnic_83xx_nic_set_promisc(struct qlcnic_adapter *, u32); |
199 | int qlcnic_83xx_set_lb_mode(struct qlcnic_adapter *, u8); | 198 | int qlcnic_83xx_set_lb_mode(struct qlcnic_adapter *, u8); |
200 | int qlcnic_83xx_clear_lb_mode(struct qlcnic_adapter *, u8); | 199 | int qlcnic_83xx_clear_lb_mode(struct qlcnic_adapter *, u8); |
@@ -206,6 +205,11 @@ int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *, struct qlcnic_pci_info *); | |||
206 | int qlcnic_83xx_set_nic_info(struct qlcnic_adapter *, struct qlcnic_info *); | 205 | int qlcnic_83xx_set_nic_info(struct qlcnic_adapter *, struct qlcnic_info *); |
207 | void qlcnic_83xx_register_nic_idc_func(struct qlcnic_adapter *, int); | 206 | void qlcnic_83xx_register_nic_idc_func(struct qlcnic_adapter *, int); |
208 | 207 | ||
208 | int qlcnic_83xx_napi_add(struct qlcnic_adapter *, struct net_device *); | ||
209 | void qlcnic_83xx_napi_del(struct qlcnic_adapter *); | ||
210 | void qlcnic_83xx_napi_enable(struct qlcnic_adapter *); | ||
211 | void qlcnic_83xx_napi_disable(struct qlcnic_adapter *); | ||
212 | |||
209 | void qlcnic_ind_wr(struct qlcnic_adapter *, u32, u32); | 213 | void qlcnic_ind_wr(struct qlcnic_adapter *, u32, u32); |
210 | int qlcnic_ind_rd(struct qlcnic_adapter *, u32); | 214 | int qlcnic_ind_rd(struct qlcnic_adapter *, u32); |
211 | void qlcnic_83xx_get_stats(struct qlcnic_adapter *, | 215 | void qlcnic_83xx_get_stats(struct qlcnic_adapter *, |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c index 7ebd8612d4cb..3098a14c67f0 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c | |||
@@ -498,36 +498,42 @@ qlcnic_fw_cmd_set_port(struct qlcnic_adapter *adapter, u32 config) | |||
498 | int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter) | 498 | int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter) |
499 | { | 499 | { |
500 | void *addr; | 500 | void *addr; |
501 | int err; | 501 | int err, ring; |
502 | int ring; | ||
503 | struct qlcnic_recv_context *recv_ctx; | 502 | struct qlcnic_recv_context *recv_ctx; |
504 | struct qlcnic_host_rds_ring *rds_ring; | 503 | struct qlcnic_host_rds_ring *rds_ring; |
505 | struct qlcnic_host_sds_ring *sds_ring; | 504 | struct qlcnic_host_sds_ring *sds_ring; |
506 | struct qlcnic_host_tx_ring *tx_ring; | 505 | struct qlcnic_host_tx_ring *tx_ring; |
506 | __le32 *ptr; | ||
507 | 507 | ||
508 | struct pci_dev *pdev = adapter->pdev; | 508 | struct pci_dev *pdev = adapter->pdev; |
509 | 509 | ||
510 | recv_ctx = adapter->recv_ctx; | 510 | recv_ctx = adapter->recv_ctx; |
511 | tx_ring = adapter->tx_ring; | ||
512 | 511 | ||
513 | tx_ring->hw_consumer = (__le32 *) dma_alloc_coherent(&pdev->dev, | 512 | for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) { |
514 | sizeof(u32), &tx_ring->hw_cons_phys_addr, GFP_KERNEL); | 513 | tx_ring = &adapter->tx_ring[ring]; |
515 | if (tx_ring->hw_consumer == NULL) { | 514 | ptr = (__le32 *)dma_alloc_coherent(&pdev->dev, sizeof(u32), |
516 | dev_err(&pdev->dev, "failed to allocate tx consumer\n"); | 515 | &tx_ring->hw_cons_phys_addr, |
517 | return -ENOMEM; | 516 | GFP_KERNEL); |
518 | } | ||
519 | 517 | ||
520 | /* cmd desc ring */ | 518 | if (ptr == NULL) { |
521 | addr = dma_alloc_coherent(&pdev->dev, TX_DESC_RINGSIZE(tx_ring), | 519 | dev_err(&pdev->dev, "failed to allocate tx consumer\n"); |
522 | &tx_ring->phys_addr, GFP_KERNEL); | 520 | return -ENOMEM; |
521 | } | ||
522 | tx_ring->hw_consumer = ptr; | ||
523 | /* cmd desc ring */ | ||
524 | addr = dma_alloc_coherent(&pdev->dev, TX_DESC_RINGSIZE(tx_ring), | ||
525 | &tx_ring->phys_addr, | ||
526 | GFP_KERNEL); | ||
523 | 527 | ||
524 | if (addr == NULL) { | 528 | if (addr == NULL) { |
525 | dev_err(&pdev->dev, "failed to allocate tx desc ring\n"); | 529 | dev_err(&pdev->dev, |
526 | err = -ENOMEM; | 530 | "failed to allocate tx desc ring\n"); |
527 | goto err_out_free; | 531 | err = -ENOMEM; |
528 | } | 532 | goto err_out_free; |
533 | } | ||
529 | 534 | ||
530 | tx_ring->desc_head = addr; | 535 | tx_ring->desc_head = addr; |
536 | } | ||
531 | 537 | ||
532 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { | 538 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { |
533 | rds_ring = &recv_ctx->rds_rings[ring]; | 539 | rds_ring = &recv_ctx->rds_rings[ring]; |
@@ -624,20 +630,23 @@ void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter) | |||
624 | 630 | ||
625 | recv_ctx = adapter->recv_ctx; | 631 | recv_ctx = adapter->recv_ctx; |
626 | 632 | ||
627 | tx_ring = adapter->tx_ring; | 633 | for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) { |
628 | if (tx_ring->hw_consumer != NULL) { | 634 | tx_ring = &adapter->tx_ring[ring]; |
629 | dma_free_coherent(&adapter->pdev->dev, | 635 | if (tx_ring->hw_consumer != NULL) { |
630 | sizeof(u32), | 636 | dma_free_coherent(&adapter->pdev->dev, sizeof(u32), |
631 | tx_ring->hw_consumer, | 637 | tx_ring->hw_consumer, |
632 | tx_ring->hw_cons_phys_addr); | 638 | tx_ring->hw_cons_phys_addr); |
633 | tx_ring->hw_consumer = NULL; | ||
634 | } | ||
635 | 639 | ||
636 | if (tx_ring->desc_head != NULL) { | 640 | tx_ring->hw_consumer = NULL; |
637 | dma_free_coherent(&adapter->pdev->dev, | 641 | } |
638 | TX_DESC_RINGSIZE(tx_ring), | 642 | |
639 | tx_ring->desc_head, tx_ring->phys_addr); | 643 | if (tx_ring->desc_head != NULL) { |
640 | tx_ring->desc_head = NULL; | 644 | dma_free_coherent(&adapter->pdev->dev, |
645 | TX_DESC_RINGSIZE(tx_ring), | ||
646 | tx_ring->desc_head, | ||
647 | tx_ring->phys_addr); | ||
648 | tx_ring->desc_head = NULL; | ||
649 | } | ||
641 | } | 650 | } |
642 | 651 | ||
643 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { | 652 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c index 4b41f9b43124..aa71ebaefdc0 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c | |||
@@ -163,13 +163,12 @@ void qlcnic_free_sw_resources(struct qlcnic_adapter *adapter) | |||
163 | { | 163 | { |
164 | struct qlcnic_recv_context *recv_ctx; | 164 | struct qlcnic_recv_context *recv_ctx; |
165 | struct qlcnic_host_rds_ring *rds_ring; | 165 | struct qlcnic_host_rds_ring *rds_ring; |
166 | struct qlcnic_host_tx_ring *tx_ring; | ||
167 | int ring; | 166 | int ring; |
168 | 167 | ||
169 | recv_ctx = adapter->recv_ctx; | 168 | recv_ctx = adapter->recv_ctx; |
170 | 169 | ||
171 | if (recv_ctx->rds_rings == NULL) | 170 | if (recv_ctx->rds_rings == NULL) |
172 | goto skip_rds; | 171 | return; |
173 | 172 | ||
174 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { | 173 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { |
175 | rds_ring = &recv_ctx->rds_rings[ring]; | 174 | rds_ring = &recv_ctx->rds_rings[ring]; |
@@ -177,16 +176,6 @@ void qlcnic_free_sw_resources(struct qlcnic_adapter *adapter) | |||
177 | rds_ring->rx_buf_arr = NULL; | 176 | rds_ring->rx_buf_arr = NULL; |
178 | } | 177 | } |
179 | kfree(recv_ctx->rds_rings); | 178 | kfree(recv_ctx->rds_rings); |
180 | |||
181 | skip_rds: | ||
182 | if (adapter->tx_ring == NULL) | ||
183 | return; | ||
184 | |||
185 | tx_ring = adapter->tx_ring; | ||
186 | vfree(tx_ring->cmd_buf_arr); | ||
187 | tx_ring->cmd_buf_arr = NULL; | ||
188 | kfree(adapter->tx_ring); | ||
189 | adapter->tx_ring = NULL; | ||
190 | } | 179 | } |
191 | 180 | ||
192 | int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter) | 181 | int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter) |
@@ -194,31 +183,11 @@ int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter) | |||
194 | struct qlcnic_recv_context *recv_ctx; | 183 | struct qlcnic_recv_context *recv_ctx; |
195 | struct qlcnic_host_rds_ring *rds_ring; | 184 | struct qlcnic_host_rds_ring *rds_ring; |
196 | struct qlcnic_host_sds_ring *sds_ring; | 185 | struct qlcnic_host_sds_ring *sds_ring; |
197 | struct qlcnic_host_tx_ring *tx_ring; | ||
198 | struct qlcnic_rx_buffer *rx_buf; | 186 | struct qlcnic_rx_buffer *rx_buf; |
199 | int ring, i, size; | 187 | int ring, i, size; |
200 | 188 | ||
201 | struct qlcnic_cmd_buffer *cmd_buf_arr; | ||
202 | struct net_device *netdev = adapter->netdev; | 189 | struct net_device *netdev = adapter->netdev; |
203 | 190 | ||
204 | size = sizeof(struct qlcnic_host_tx_ring); | ||
205 | tx_ring = kzalloc(size, GFP_KERNEL); | ||
206 | if (tx_ring == NULL) { | ||
207 | dev_err(&netdev->dev, "failed to allocate tx ring struct\n"); | ||
208 | return -ENOMEM; | ||
209 | } | ||
210 | adapter->tx_ring = tx_ring; | ||
211 | |||
212 | tx_ring->num_desc = adapter->num_txd; | ||
213 | tx_ring->txq = netdev_get_tx_queue(netdev, 0); | ||
214 | |||
215 | cmd_buf_arr = vzalloc(TX_BUFF_RINGSIZE(tx_ring)); | ||
216 | if (cmd_buf_arr == NULL) { | ||
217 | dev_err(&netdev->dev, "failed to allocate cmd buffer ring\n"); | ||
218 | goto err_out; | ||
219 | } | ||
220 | tx_ring->cmd_buf_arr = cmd_buf_arr; | ||
221 | |||
222 | recv_ctx = adapter->recv_ctx; | 191 | recv_ctx = adapter->recv_ctx; |
223 | 192 | ||
224 | size = adapter->max_rds_rings * sizeof(struct qlcnic_host_rds_ring); | 193 | size = adapter->max_rds_rings * sizeof(struct qlcnic_host_rds_ring); |
@@ -253,10 +222,11 @@ int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter) | |||
253 | } | 222 | } |
254 | rds_ring->rx_buf_arr = vzalloc(RCV_BUFF_RINGSIZE(rds_ring)); | 223 | rds_ring->rx_buf_arr = vzalloc(RCV_BUFF_RINGSIZE(rds_ring)); |
255 | if (rds_ring->rx_buf_arr == NULL) { | 224 | if (rds_ring->rx_buf_arr == NULL) { |
256 | dev_err(&netdev->dev, "Failed to allocate " | 225 | dev_err(&netdev->dev, |
257 | "rx buffer ring %d\n", ring); | 226 | "Failed to allocate rx buffer ring %d\n", ring); |
258 | goto err_out; | 227 | goto err_out; |
259 | } | 228 | } |
229 | |||
260 | INIT_LIST_HEAD(&rds_ring->free_list); | 230 | INIT_LIST_HEAD(&rds_ring->free_list); |
261 | /* | 231 | /* |
262 | * Now go through all of them, set reference handles | 232 | * Now go through all of them, set reference handles |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c index d678e6d763e1..383ecd20d9b5 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c | |||
@@ -5,9 +5,6 @@ | |||
5 | 5 | ||
6 | #include "qlcnic.h" | 6 | #include "qlcnic.h" |
7 | 7 | ||
8 | #define QLCNIC_MAC_HASH(MAC)\ | ||
9 | ((((MAC) & 0x70000) >> 0x10) | (((MAC) & 0x70000000000ULL) >> 0x25)) | ||
10 | |||
11 | #define TX_ETHER_PKT 0x01 | 8 | #define TX_ETHER_PKT 0x01 |
12 | #define TX_TCP_PKT 0x02 | 9 | #define TX_TCP_PKT 0x02 |
13 | #define TX_UDP_PKT 0x03 | 10 | #define TX_UDP_PKT 0x03 |
@@ -91,10 +88,61 @@ | |||
91 | #define QLCNIC_RESPONSE_DESC 0x05 | 88 | #define QLCNIC_RESPONSE_DESC 0x05 |
92 | #define QLCNIC_LRO_DESC 0x12 | 89 | #define QLCNIC_LRO_DESC 0x12 |
93 | 90 | ||
91 | #define QLCNIC_TX_POLL_BUDGET 128 | ||
92 | #define QLCNIC_TCP_HDR_SIZE 20 | ||
93 | #define QLCNIC_TCP_TS_OPTION_SIZE 12 | ||
94 | #define QLCNIC_FETCH_RING_ID(handle) ((handle) >> 63) | ||
95 | #define QLCNIC_DESC_OWNER_FW cpu_to_le64(STATUS_OWNER_PHANTOM) | ||
96 | |||
97 | #define QLCNIC_TCP_TS_HDR_SIZE (QLCNIC_TCP_HDR_SIZE + QLCNIC_TCP_TS_OPTION_SIZE) | ||
98 | |||
94 | /* for status field in status_desc */ | 99 | /* for status field in status_desc */ |
95 | #define STATUS_CKSUM_LOOP 0 | 100 | #define STATUS_CKSUM_LOOP 0 |
96 | #define STATUS_CKSUM_OK 2 | 101 | #define STATUS_CKSUM_OK 2 |
97 | 102 | ||
103 | #define qlcnic_83xx_pktln(sts) ((sts >> 32) & 0x3FFF) | ||
104 | #define qlcnic_83xx_hndl(sts) ((sts >> 48) & 0x7FFF) | ||
105 | #define qlcnic_83xx_csum_status(sts) ((sts >> 39) & 7) | ||
106 | #define qlcnic_83xx_opcode(sts) ((sts >> 42) & 0xF) | ||
107 | #define qlcnic_83xx_vlan_tag(sts) (((sts) >> 48) & 0xFFFF) | ||
108 | #define qlcnic_83xx_lro_pktln(sts) (((sts) >> 32) & 0x3FFF) | ||
109 | #define qlcnic_83xx_l2_hdr_off(sts) (((sts) >> 16) & 0xFF) | ||
110 | #define qlcnic_83xx_l4_hdr_off(sts) (((sts) >> 24) & 0xFF) | ||
111 | #define qlcnic_83xx_pkt_cnt(sts) (((sts) >> 16) & 0x7) | ||
112 | #define qlcnic_83xx_is_tstamp(sts) (((sts) >> 40) & 1) | ||
113 | #define qlcnic_83xx_is_psh_bit(sts) (((sts) >> 41) & 1) | ||
114 | #define qlcnic_83xx_is_ip_align(sts) (((sts) >> 46) & 1) | ||
115 | #define qlcnic_83xx_has_vlan_tag(sts) (((sts) >> 47) & 1) | ||
116 | |||
117 | struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *, | ||
118 | struct qlcnic_host_rds_ring *, u16, u16); | ||
119 | |||
120 | inline void qlcnic_83xx_enable_tx_intr(struct qlcnic_adapter *adapter, | ||
121 | struct qlcnic_host_tx_ring *tx_ring) | ||
122 | { | ||
123 | writel(0, tx_ring->crb_intr_mask); | ||
124 | } | ||
125 | |||
126 | inline void qlcnic_83xx_disable_tx_intr(struct qlcnic_adapter *adapter, | ||
127 | struct qlcnic_host_tx_ring *tx_ring) | ||
128 | { | ||
129 | writel(1, tx_ring->crb_intr_mask); | ||
130 | } | ||
131 | |||
132 | static inline u8 qlcnic_mac_hash(u64 mac) | ||
133 | { | ||
134 | return (u8)((mac & 0xff) ^ ((mac >> 40) & 0xff)); | ||
135 | } | ||
136 | |||
137 | static inline u32 qlcnic_get_ref_handle(struct qlcnic_adapter *adapter, | ||
138 | u16 handle, u8 ring_id) | ||
139 | { | ||
140 | if (adapter->pdev->device == PCI_DEVICE_ID_QLOGIC_QLE834X) | ||
141 | return handle | (ring_id << 15); | ||
142 | else | ||
143 | return handle; | ||
144 | } | ||
145 | |||
98 | void qlcnic_82xx_change_filter(struct qlcnic_adapter *adapter, u64 *uaddr, | 146 | void qlcnic_82xx_change_filter(struct qlcnic_adapter *adapter, u64 *uaddr, |
99 | __le16 vlan_id) | 147 | __le16 vlan_id) |
100 | { | 148 | { |
@@ -128,29 +176,33 @@ void qlcnic_82xx_change_filter(struct qlcnic_adapter *adapter, u64 *uaddr, | |||
128 | } | 176 | } |
129 | 177 | ||
130 | static void qlcnic_send_filter(struct qlcnic_adapter *adapter, | 178 | static void qlcnic_send_filter(struct qlcnic_adapter *adapter, |
131 | struct qlcnic_host_tx_ring *tx_ring, | ||
132 | struct cmd_desc_type0 *first_desc, | 179 | struct cmd_desc_type0 *first_desc, |
133 | struct sk_buff *skb) | 180 | struct sk_buff *skb) |
134 | { | 181 | { |
135 | struct qlcnic_filter *fil, *tmp_fil; | 182 | struct qlcnic_filter *fil, *tmp_fil; |
136 | struct hlist_node *tmp_hnode, *n; | 183 | struct hlist_node *tmp_hnode, *n; |
137 | struct hlist_head *head; | 184 | struct hlist_head *head; |
185 | struct net_device *netdev = adapter->netdev; | ||
138 | struct ethhdr *phdr = (struct ethhdr *)(skb->data); | 186 | struct ethhdr *phdr = (struct ethhdr *)(skb->data); |
139 | u64 src_addr = 0; | 187 | u64 src_addr = 0; |
140 | __le16 vlan_id = 0; | 188 | __le16 vlan_id = 0; |
141 | u8 hindex; | 189 | u8 hindex; |
142 | 190 | ||
143 | if (!compare_ether_addr(phdr->h_source, adapter->mac_addr)) | 191 | if (ether_addr_equal(phdr->h_source, adapter->mac_addr)) |
144 | return; | 192 | return; |
145 | 193 | ||
146 | if (adapter->fhash.fnum >= adapter->fhash.fmax) | 194 | if (adapter->fhash.fnum >= adapter->fhash.fmax) { |
195 | adapter->stats.mac_filter_limit_overrun++; | ||
196 | netdev_info(netdev, "Can not add more than %d mac addresses\n", | ||
197 | adapter->fhash.fmax); | ||
147 | return; | 198 | return; |
199 | } | ||
148 | 200 | ||
149 | /* Only NPAR capable devices support vlan based learning */ | 201 | /* Only NPAR capable devices support vlan based learning */ |
150 | if (adapter->flags & QLCNIC_ESWITCH_ENABLED) | 202 | if (adapter->flags & QLCNIC_ESWITCH_ENABLED) |
151 | vlan_id = first_desc->vlan_TCI; | 203 | vlan_id = first_desc->vlan_TCI; |
152 | memcpy(&src_addr, phdr->h_source, ETH_ALEN); | 204 | memcpy(&src_addr, phdr->h_source, ETH_ALEN); |
153 | hindex = QLCNIC_MAC_HASH(src_addr) & (QLCNIC_LB_MAX_FILTERS - 1); | 205 | hindex = qlcnic_mac_hash(src_addr) & (adapter->fhash.fbucket_size - 1); |
154 | head = &(adapter->fhash.fhead[hindex]); | 206 | head = &(adapter->fhash.fhead[hindex]); |
155 | 207 | ||
156 | hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode) { | 208 | hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode) { |
@@ -470,7 +522,7 @@ netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
470 | goto unwind_buff; | 522 | goto unwind_buff; |
471 | 523 | ||
472 | if (adapter->mac_learn) | 524 | if (adapter->mac_learn) |
473 | qlcnic_send_filter(adapter, tx_ring, first_desc, skb); | 525 | qlcnic_send_filter(adapter, first_desc, skb); |
474 | 526 | ||
475 | adapter->stats.txbytes += skb->len; | 527 | adapter->stats.txbytes += skb->len; |
476 | adapter->stats.xmitcalled++; | 528 | adapter->stats.xmitcalled++; |
@@ -523,8 +575,8 @@ static int qlcnic_alloc_rx_skb(struct qlcnic_adapter *adapter, | |||
523 | } | 575 | } |
524 | 576 | ||
525 | skb_reserve(skb, NET_IP_ALIGN); | 577 | skb_reserve(skb, NET_IP_ALIGN); |
526 | dma = pci_map_single(pdev, skb->data, rds_ring->dma_size, | 578 | dma = pci_map_single(pdev, skb->data, |
527 | PCI_DMA_FROMDEVICE); | 579 | rds_ring->dma_size, PCI_DMA_FROMDEVICE); |
528 | 580 | ||
529 | if (pci_dma_mapping_error(pdev, dma)) { | 581 | if (pci_dma_mapping_error(pdev, dma)) { |
530 | adapter->stats.rx_dma_map_error++; | 582 | adapter->stats.rx_dma_map_error++; |
@@ -539,12 +591,13 @@ static int qlcnic_alloc_rx_skb(struct qlcnic_adapter *adapter, | |||
539 | } | 591 | } |
540 | 592 | ||
541 | static void qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter, | 593 | static void qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter, |
542 | struct qlcnic_host_rds_ring *rds_ring) | 594 | struct qlcnic_host_rds_ring *rds_ring, |
595 | u8 ring_id) | ||
543 | { | 596 | { |
544 | struct rcv_desc *pdesc; | 597 | struct rcv_desc *pdesc; |
545 | struct qlcnic_rx_buffer *buffer; | 598 | struct qlcnic_rx_buffer *buffer; |
546 | int count = 0; | 599 | int count = 0; |
547 | uint32_t producer; | 600 | uint32_t producer, handle; |
548 | struct list_head *head; | 601 | struct list_head *head; |
549 | 602 | ||
550 | if (!spin_trylock(&rds_ring->lock)) | 603 | if (!spin_trylock(&rds_ring->lock)) |
@@ -552,7 +605,6 @@ static void qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter, | |||
552 | 605 | ||
553 | producer = rds_ring->producer; | 606 | producer = rds_ring->producer; |
554 | head = &rds_ring->free_list; | 607 | head = &rds_ring->free_list; |
555 | |||
556 | while (!list_empty(head)) { | 608 | while (!list_empty(head)) { |
557 | buffer = list_entry(head->next, struct qlcnic_rx_buffer, list); | 609 | buffer = list_entry(head->next, struct qlcnic_rx_buffer, list); |
558 | 610 | ||
@@ -560,28 +612,29 @@ static void qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter, | |||
560 | if (qlcnic_alloc_rx_skb(adapter, rds_ring, buffer)) | 612 | if (qlcnic_alloc_rx_skb(adapter, rds_ring, buffer)) |
561 | break; | 613 | break; |
562 | } | 614 | } |
563 | |||
564 | count++; | 615 | count++; |
565 | list_del(&buffer->list); | 616 | list_del(&buffer->list); |
566 | 617 | ||
567 | /* make a rcv descriptor */ | 618 | /* make a rcv descriptor */ |
568 | pdesc = &rds_ring->desc_head[producer]; | 619 | pdesc = &rds_ring->desc_head[producer]; |
569 | pdesc->reference_handle = cpu_to_le16(buffer->ref_handle); | 620 | handle = qlcnic_get_ref_handle(adapter, |
621 | buffer->ref_handle, ring_id); | ||
622 | pdesc->reference_handle = cpu_to_le16(handle); | ||
570 | pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size); | 623 | pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size); |
571 | pdesc->addr_buffer = cpu_to_le64(buffer->dma); | 624 | pdesc->addr_buffer = cpu_to_le64(buffer->dma); |
572 | producer = get_next_index(producer, rds_ring->num_desc); | 625 | producer = get_next_index(producer, rds_ring->num_desc); |
573 | } | 626 | } |
574 | |||
575 | if (count) { | 627 | if (count) { |
576 | rds_ring->producer = producer; | 628 | rds_ring->producer = producer; |
577 | writel((producer - 1) & (rds_ring->num_desc - 1), | 629 | writel((producer - 1) & (rds_ring->num_desc - 1), |
578 | rds_ring->crb_rcv_producer); | 630 | rds_ring->crb_rcv_producer); |
579 | } | 631 | } |
580 | |||
581 | spin_unlock(&rds_ring->lock); | 632 | spin_unlock(&rds_ring->lock); |
582 | } | 633 | } |
583 | 634 | ||
584 | static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter) | 635 | static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter, |
636 | struct qlcnic_host_tx_ring *tx_ring, | ||
637 | int budget) | ||
585 | { | 638 | { |
586 | u32 sw_consumer, hw_consumer; | 639 | u32 sw_consumer, hw_consumer; |
587 | int i, done, count = 0; | 640 | int i, done, count = 0; |
@@ -589,7 +642,6 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter) | |||
589 | struct pci_dev *pdev = adapter->pdev; | 642 | struct pci_dev *pdev = adapter->pdev; |
590 | struct net_device *netdev = adapter->netdev; | 643 | struct net_device *netdev = adapter->netdev; |
591 | struct qlcnic_skb_frag *frag; | 644 | struct qlcnic_skb_frag *frag; |
592 | struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring; | ||
593 | 645 | ||
594 | if (!spin_trylock(&adapter->tx_clean_lock)) | 646 | if (!spin_trylock(&adapter->tx_clean_lock)) |
595 | return 1; | 647 | return 1; |
@@ -610,22 +662,19 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter) | |||
610 | PCI_DMA_TODEVICE); | 662 | PCI_DMA_TODEVICE); |
611 | frag->dma = 0ULL; | 663 | frag->dma = 0ULL; |
612 | } | 664 | } |
613 | |||
614 | adapter->stats.xmitfinished++; | 665 | adapter->stats.xmitfinished++; |
615 | dev_kfree_skb_any(buffer->skb); | 666 | dev_kfree_skb_any(buffer->skb); |
616 | buffer->skb = NULL; | 667 | buffer->skb = NULL; |
617 | } | 668 | } |
618 | 669 | ||
619 | sw_consumer = get_next_index(sw_consumer, tx_ring->num_desc); | 670 | sw_consumer = get_next_index(sw_consumer, tx_ring->num_desc); |
620 | if (++count >= MAX_STATUS_HANDLE) | 671 | if (++count >= budget) |
621 | break; | 672 | break; |
622 | } | 673 | } |
623 | 674 | ||
624 | if (count && netif_running(netdev)) { | 675 | if (count && netif_running(netdev)) { |
625 | tx_ring->sw_consumer = sw_consumer; | 676 | tx_ring->sw_consumer = sw_consumer; |
626 | |||
627 | smp_mb(); | 677 | smp_mb(); |
628 | |||
629 | if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) { | 678 | if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) { |
630 | if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) { | 679 | if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) { |
631 | netif_wake_queue(netdev); | 680 | netif_wake_queue(netdev); |
@@ -649,7 +698,6 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter) | |||
649 | */ | 698 | */ |
650 | hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer)); | 699 | hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer)); |
651 | done = (sw_consumer == hw_consumer); | 700 | done = (sw_consumer == hw_consumer); |
652 | |||
653 | spin_unlock(&adapter->tx_clean_lock); | 701 | spin_unlock(&adapter->tx_clean_lock); |
654 | 702 | ||
655 | return done; | 703 | return done; |
@@ -657,16 +705,15 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter) | |||
657 | 705 | ||
658 | static int qlcnic_poll(struct napi_struct *napi, int budget) | 706 | static int qlcnic_poll(struct napi_struct *napi, int budget) |
659 | { | 707 | { |
708 | int tx_complete, work_done; | ||
660 | struct qlcnic_host_sds_ring *sds_ring; | 709 | struct qlcnic_host_sds_ring *sds_ring; |
661 | struct qlcnic_adapter *adapter; | 710 | struct qlcnic_adapter *adapter; |
662 | int tx_complete, work_done; | ||
663 | 711 | ||
664 | sds_ring = container_of(napi, struct qlcnic_host_sds_ring, napi); | 712 | sds_ring = container_of(napi, struct qlcnic_host_sds_ring, napi); |
665 | adapter = sds_ring->adapter; | 713 | adapter = sds_ring->adapter; |
666 | 714 | tx_complete = qlcnic_process_cmd_ring(adapter, adapter->tx_ring, | |
667 | tx_complete = qlcnic_process_cmd_ring(adapter); | 715 | budget); |
668 | work_done = qlcnic_process_rcv_ring(sds_ring, budget); | 716 | work_done = qlcnic_process_rcv_ring(sds_ring, budget); |
669 | |||
670 | if ((work_done < budget) && tx_complete) { | 717 | if ((work_done < budget) && tx_complete) { |
671 | napi_complete(&sds_ring->napi); | 718 | napi_complete(&sds_ring->napi); |
672 | if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) | 719 | if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) |
@@ -799,26 +846,23 @@ static void qlcnic_handle_fw_message(int desc_cnt, int index, | |||
799 | } | 846 | } |
800 | } | 847 | } |
801 | 848 | ||
802 | static struct sk_buff * | 849 | struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *adapter, |
803 | qlcnic_process_rxbuf(struct qlcnic_adapter *adapter, | 850 | struct qlcnic_host_rds_ring *ring, |
804 | struct qlcnic_host_rds_ring *rds_ring, u16 index, | 851 | u16 index, u16 cksum) |
805 | u16 cksum) | ||
806 | { | 852 | { |
807 | struct qlcnic_rx_buffer *buffer; | 853 | struct qlcnic_rx_buffer *buffer; |
808 | struct sk_buff *skb; | 854 | struct sk_buff *skb; |
809 | 855 | ||
810 | buffer = &rds_ring->rx_buf_arr[index]; | 856 | buffer = &ring->rx_buf_arr[index]; |
811 | |||
812 | if (unlikely(buffer->skb == NULL)) { | 857 | if (unlikely(buffer->skb == NULL)) { |
813 | WARN_ON(1); | 858 | WARN_ON(1); |
814 | return NULL; | 859 | return NULL; |
815 | } | 860 | } |
816 | 861 | ||
817 | pci_unmap_single(adapter->pdev, buffer->dma, rds_ring->dma_size, | 862 | pci_unmap_single(adapter->pdev, buffer->dma, ring->dma_size, |
818 | PCI_DMA_FROMDEVICE); | 863 | PCI_DMA_FROMDEVICE); |
819 | 864 | ||
820 | skb = buffer->skb; | 865 | skb = buffer->skb; |
821 | |||
822 | if (likely((adapter->netdev->features & NETIF_F_RXCSUM) && | 866 | if (likely((adapter->netdev->features & NETIF_F_RXCSUM) && |
823 | (cksum == STATUS_CKSUM_OK || cksum == STATUS_CKSUM_LOOP))) { | 867 | (cksum == STATUS_CKSUM_OK || cksum == STATUS_CKSUM_LOOP))) { |
824 | adapter->stats.csummed++; | 868 | adapter->stats.csummed++; |
@@ -827,6 +871,7 @@ qlcnic_process_rxbuf(struct qlcnic_adapter *adapter, | |||
827 | skb_checksum_none_assert(skb); | 871 | skb_checksum_none_assert(skb); |
828 | } | 872 | } |
829 | 873 | ||
874 | |||
830 | buffer->skb = NULL; | 875 | buffer->skb = NULL; |
831 | 876 | ||
832 | return skb; | 877 | return skb; |
@@ -1001,9 +1046,9 @@ int qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max) | |||
1001 | struct list_head *cur; | 1046 | struct list_head *cur; |
1002 | struct status_desc *desc; | 1047 | struct status_desc *desc; |
1003 | struct qlcnic_rx_buffer *rxbuf; | 1048 | struct qlcnic_rx_buffer *rxbuf; |
1049 | int opcode, desc_cnt, count = 0; | ||
1004 | u64 sts_data0, sts_data1; | 1050 | u64 sts_data0, sts_data1; |
1005 | __le64 owner_phantom = cpu_to_le64(STATUS_OWNER_PHANTOM); | 1051 | u8 ring; |
1006 | int opcode, ring, desc_cnt, count = 0; | ||
1007 | u32 consumer = sds_ring->consumer; | 1052 | u32 consumer = sds_ring->consumer; |
1008 | 1053 | ||
1009 | while (count < max) { | 1054 | while (count < max) { |
@@ -1015,7 +1060,6 @@ int qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max) | |||
1015 | 1060 | ||
1016 | desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0); | 1061 | desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0); |
1017 | opcode = qlcnic_get_sts_opcode(sts_data0); | 1062 | opcode = qlcnic_get_sts_opcode(sts_data0); |
1018 | |||
1019 | switch (opcode) { | 1063 | switch (opcode) { |
1020 | case QLCNIC_RXPKT_DESC: | 1064 | case QLCNIC_RXPKT_DESC: |
1021 | case QLCNIC_OLD_RXPKT_DESC: | 1065 | case QLCNIC_OLD_RXPKT_DESC: |
@@ -1035,18 +1079,16 @@ int qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max) | |||
1035 | default: | 1079 | default: |
1036 | goto skip; | 1080 | goto skip; |
1037 | } | 1081 | } |
1038 | |||
1039 | WARN_ON(desc_cnt > 1); | 1082 | WARN_ON(desc_cnt > 1); |
1040 | 1083 | ||
1041 | if (likely(rxbuf)) | 1084 | if (likely(rxbuf)) |
1042 | list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]); | 1085 | list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]); |
1043 | else | 1086 | else |
1044 | adapter->stats.null_rxbuf++; | 1087 | adapter->stats.null_rxbuf++; |
1045 | |||
1046 | skip: | 1088 | skip: |
1047 | for (; desc_cnt > 0; desc_cnt--) { | 1089 | for (; desc_cnt > 0; desc_cnt--) { |
1048 | desc = &sds_ring->desc_head[consumer]; | 1090 | desc = &sds_ring->desc_head[consumer]; |
1049 | desc->status_desc_data[0] = owner_phantom; | 1091 | desc->status_desc_data[0] = QLCNIC_DESC_OWNER_FW; |
1050 | consumer = get_next_index(consumer, sds_ring->num_desc); | 1092 | consumer = get_next_index(consumer, sds_ring->num_desc); |
1051 | } | 1093 | } |
1052 | count++; | 1094 | count++; |
@@ -1054,7 +1096,6 @@ skip: | |||
1054 | 1096 | ||
1055 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { | 1097 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { |
1056 | rds_ring = &adapter->recv_ctx->rds_rings[ring]; | 1098 | rds_ring = &adapter->recv_ctx->rds_rings[ring]; |
1057 | |||
1058 | if (!list_empty(&sds_ring->free_list[ring])) { | 1099 | if (!list_empty(&sds_ring->free_list[ring])) { |
1059 | list_for_each(cur, &sds_ring->free_list[ring]) { | 1100 | list_for_each(cur, &sds_ring->free_list[ring]) { |
1060 | rxbuf = list_entry(cur, struct qlcnic_rx_buffer, | 1101 | rxbuf = list_entry(cur, struct qlcnic_rx_buffer, |
@@ -1067,7 +1108,7 @@ skip: | |||
1067 | spin_unlock(&rds_ring->lock); | 1108 | spin_unlock(&rds_ring->lock); |
1068 | } | 1109 | } |
1069 | 1110 | ||
1070 | qlcnic_post_rx_buffers_nodb(adapter, rds_ring); | 1111 | qlcnic_post_rx_buffers_nodb(adapter, rds_ring, ring); |
1071 | } | 1112 | } |
1072 | 1113 | ||
1073 | if (count) { | 1114 | if (count) { |
@@ -1079,12 +1120,12 @@ skip: | |||
1079 | } | 1120 | } |
1080 | 1121 | ||
1081 | void qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter, | 1122 | void qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter, |
1082 | struct qlcnic_host_rds_ring *rds_ring) | 1123 | struct qlcnic_host_rds_ring *rds_ring, u8 ring_id) |
1083 | { | 1124 | { |
1084 | struct rcv_desc *pdesc; | 1125 | struct rcv_desc *pdesc; |
1085 | struct qlcnic_rx_buffer *buffer; | 1126 | struct qlcnic_rx_buffer *buffer; |
1086 | int count = 0; | 1127 | int count = 0; |
1087 | u32 producer; | 1128 | u32 producer, handle; |
1088 | struct list_head *head; | 1129 | struct list_head *head; |
1089 | 1130 | ||
1090 | producer = rds_ring->producer; | 1131 | producer = rds_ring->producer; |
@@ -1105,7 +1146,9 @@ void qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter, | |||
1105 | /* make a rcv descriptor */ | 1146 | /* make a rcv descriptor */ |
1106 | pdesc = &rds_ring->desc_head[producer]; | 1147 | pdesc = &rds_ring->desc_head[producer]; |
1107 | pdesc->addr_buffer = cpu_to_le64(buffer->dma); | 1148 | pdesc->addr_buffer = cpu_to_le64(buffer->dma); |
1108 | pdesc->reference_handle = cpu_to_le16(buffer->ref_handle); | 1149 | handle = qlcnic_get_ref_handle(adapter, buffer->ref_handle, |
1150 | ring_id); | ||
1151 | pdesc->reference_handle = cpu_to_le16(handle); | ||
1109 | pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size); | 1152 | pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size); |
1110 | producer = get_next_index(producer, rds_ring->num_desc); | 1153 | producer = get_next_index(producer, rds_ring->num_desc); |
1111 | } | 1154 | } |
@@ -1226,8 +1269,7 @@ int qlcnic_82xx_napi_add(struct qlcnic_adapter *adapter, | |||
1226 | 1269 | ||
1227 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { | 1270 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { |
1228 | sds_ring = &recv_ctx->sds_rings[ring]; | 1271 | sds_ring = &recv_ctx->sds_rings[ring]; |
1229 | 1272 | if (ring == adapter->max_sds_rings - 1) | |
1230 | if (ring == max_sds_rings - 1) | ||
1231 | netif_napi_add(netdev, &sds_ring->napi, qlcnic_poll, | 1273 | netif_napi_add(netdev, &sds_ring->napi, qlcnic_poll, |
1232 | QLCNIC_NETDEV_WEIGHT / max_sds_rings); | 1274 | QLCNIC_NETDEV_WEIGHT / max_sds_rings); |
1233 | else | 1275 | else |
@@ -1235,10 +1277,15 @@ int qlcnic_82xx_napi_add(struct qlcnic_adapter *adapter, | |||
1235 | QLCNIC_NETDEV_WEIGHT*2); | 1277 | QLCNIC_NETDEV_WEIGHT*2); |
1236 | } | 1278 | } |
1237 | 1279 | ||
1280 | if (qlcnic_alloc_tx_rings(adapter, netdev)) { | ||
1281 | qlcnic_free_sds_rings(recv_ctx); | ||
1282 | return -ENOMEM; | ||
1283 | } | ||
1284 | |||
1238 | return 0; | 1285 | return 0; |
1239 | } | 1286 | } |
1240 | 1287 | ||
1241 | void qlcnic_napi_del(struct qlcnic_adapter *adapter) | 1288 | void qlcnic_82xx_napi_del(struct qlcnic_adapter *adapter) |
1242 | { | 1289 | { |
1243 | int ring; | 1290 | int ring; |
1244 | struct qlcnic_host_sds_ring *sds_ring; | 1291 | struct qlcnic_host_sds_ring *sds_ring; |
@@ -1250,6 +1297,7 @@ void qlcnic_napi_del(struct qlcnic_adapter *adapter) | |||
1250 | } | 1297 | } |
1251 | 1298 | ||
1252 | qlcnic_free_sds_rings(adapter->recv_ctx); | 1299 | qlcnic_free_sds_rings(adapter->recv_ctx); |
1300 | qlcnic_free_tx_rings(adapter); | ||
1253 | } | 1301 | } |
1254 | 1302 | ||
1255 | void qlcnic_82xx_napi_enable(struct qlcnic_adapter *adapter) | 1303 | void qlcnic_82xx_napi_enable(struct qlcnic_adapter *adapter) |
@@ -1284,3 +1332,447 @@ void qlcnic_82xx_napi_disable(struct qlcnic_adapter *adapter) | |||
1284 | napi_disable(&sds_ring->napi); | 1332 | napi_disable(&sds_ring->napi); |
1285 | } | 1333 | } |
1286 | } | 1334 | } |
1335 | |||
1336 | static struct qlcnic_rx_buffer * | ||
1337 | qlcnic_83xx_process_rcv(struct qlcnic_adapter *adapter, | ||
1338 | struct qlcnic_host_sds_ring *sds_ring, | ||
1339 | u8 ring, u64 sts_data[]) | ||
1340 | { | ||
1341 | struct net_device *netdev = adapter->netdev; | ||
1342 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; | ||
1343 | struct qlcnic_rx_buffer *buffer; | ||
1344 | struct sk_buff *skb; | ||
1345 | struct qlcnic_host_rds_ring *rds_ring; | ||
1346 | int index, length, cksum; | ||
1347 | u16 vid = 0xffff; | ||
1348 | |||
1349 | if (unlikely(ring >= adapter->max_rds_rings)) | ||
1350 | return NULL; | ||
1351 | |||
1352 | rds_ring = &recv_ctx->rds_rings[ring]; | ||
1353 | |||
1354 | index = qlcnic_83xx_hndl(sts_data[0]); | ||
1355 | if (unlikely(index >= rds_ring->num_desc)) | ||
1356 | return NULL; | ||
1357 | |||
1358 | buffer = &rds_ring->rx_buf_arr[index]; | ||
1359 | length = qlcnic_83xx_pktln(sts_data[0]); | ||
1360 | cksum = qlcnic_83xx_csum_status(sts_data[1]); | ||
1361 | skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum); | ||
1362 | if (!skb) | ||
1363 | return buffer; | ||
1364 | |||
1365 | if (length > rds_ring->skb_size) | ||
1366 | skb_put(skb, rds_ring->skb_size); | ||
1367 | else | ||
1368 | skb_put(skb, length); | ||
1369 | |||
1370 | if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) { | ||
1371 | adapter->stats.rxdropped++; | ||
1372 | dev_kfree_skb(skb); | ||
1373 | return buffer; | ||
1374 | } | ||
1375 | |||
1376 | skb->protocol = eth_type_trans(skb, netdev); | ||
1377 | |||
1378 | if (vid != 0xffff) | ||
1379 | __vlan_hwaccel_put_tag(skb, vid); | ||
1380 | |||
1381 | napi_gro_receive(&sds_ring->napi, skb); | ||
1382 | |||
1383 | adapter->stats.rx_pkts++; | ||
1384 | adapter->stats.rxbytes += length; | ||
1385 | |||
1386 | return buffer; | ||
1387 | } | ||
1388 | |||
1389 | static struct qlcnic_rx_buffer * | ||
1390 | qlcnic_83xx_process_lro(struct qlcnic_adapter *adapter, | ||
1391 | u8 ring, u64 sts_data[]) | ||
1392 | { | ||
1393 | struct net_device *netdev = adapter->netdev; | ||
1394 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; | ||
1395 | struct qlcnic_rx_buffer *buffer; | ||
1396 | struct sk_buff *skb; | ||
1397 | struct qlcnic_host_rds_ring *rds_ring; | ||
1398 | struct iphdr *iph; | ||
1399 | struct ipv6hdr *ipv6h; | ||
1400 | struct tcphdr *th; | ||
1401 | bool push; | ||
1402 | int l2_hdr_offset, l4_hdr_offset; | ||
1403 | int index; | ||
1404 | u16 lro_length, length, data_offset; | ||
1405 | u16 vid = 0xffff; | ||
1406 | |||
1407 | if (unlikely(ring > adapter->max_rds_rings)) | ||
1408 | return NULL; | ||
1409 | |||
1410 | rds_ring = &recv_ctx->rds_rings[ring]; | ||
1411 | |||
1412 | index = qlcnic_83xx_hndl(sts_data[0]); | ||
1413 | if (unlikely(index > rds_ring->num_desc)) | ||
1414 | return NULL; | ||
1415 | |||
1416 | buffer = &rds_ring->rx_buf_arr[index]; | ||
1417 | |||
1418 | lro_length = qlcnic_83xx_lro_pktln(sts_data[0]); | ||
1419 | l2_hdr_offset = qlcnic_83xx_l2_hdr_off(sts_data[1]); | ||
1420 | l4_hdr_offset = qlcnic_83xx_l4_hdr_off(sts_data[1]); | ||
1421 | push = qlcnic_83xx_is_psh_bit(sts_data[1]); | ||
1422 | |||
1423 | skb = qlcnic_process_rxbuf(adapter, rds_ring, index, STATUS_CKSUM_OK); | ||
1424 | if (!skb) | ||
1425 | return buffer; | ||
1426 | if (qlcnic_83xx_is_tstamp(sts_data[1])) | ||
1427 | data_offset = l4_hdr_offset + QLCNIC_TCP_TS_HDR_SIZE; | ||
1428 | else | ||
1429 | data_offset = l4_hdr_offset + QLCNIC_TCP_HDR_SIZE; | ||
1430 | |||
1431 | skb_put(skb, lro_length + data_offset); | ||
1432 | skb_pull(skb, l2_hdr_offset); | ||
1433 | |||
1434 | if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) { | ||
1435 | adapter->stats.rxdropped++; | ||
1436 | dev_kfree_skb(skb); | ||
1437 | return buffer; | ||
1438 | } | ||
1439 | |||
1440 | skb->protocol = eth_type_trans(skb, netdev); | ||
1441 | if (ntohs(skb->protocol) == ETH_P_IPV6) { | ||
1442 | ipv6h = (struct ipv6hdr *)skb->data; | ||
1443 | th = (struct tcphdr *)(skb->data + sizeof(struct ipv6hdr)); | ||
1444 | |||
1445 | length = (th->doff << 2) + lro_length; | ||
1446 | ipv6h->payload_len = htons(length); | ||
1447 | } else { | ||
1448 | iph = (struct iphdr *)skb->data; | ||
1449 | th = (struct tcphdr *)(skb->data + (iph->ihl << 2)); | ||
1450 | length = (iph->ihl << 2) + (th->doff << 2) + lro_length; | ||
1451 | iph->tot_len = htons(length); | ||
1452 | iph->check = 0; | ||
1453 | iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); | ||
1454 | } | ||
1455 | |||
1456 | th->psh = push; | ||
1457 | length = skb->len; | ||
1458 | |||
1459 | if (vid != 0xffff) | ||
1460 | __vlan_hwaccel_put_tag(skb, vid); | ||
1461 | |||
1462 | netif_receive_skb(skb); | ||
1463 | |||
1464 | adapter->stats.lro_pkts++; | ||
1465 | adapter->stats.lrobytes += length; | ||
1466 | return buffer; | ||
1467 | } | ||
1468 | |||
1469 | static int qlcnic_83xx_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, | ||
1470 | int max) | ||
1471 | { | ||
1472 | struct qlcnic_host_rds_ring *rds_ring; | ||
1473 | struct qlcnic_adapter *adapter = sds_ring->adapter; | ||
1474 | struct list_head *cur; | ||
1475 | struct status_desc *desc; | ||
1476 | struct qlcnic_rx_buffer *rxbuf = NULL; | ||
1477 | u8 ring; | ||
1478 | u64 sts_data[2]; | ||
1479 | int count = 0, opcode; | ||
1480 | u32 consumer = sds_ring->consumer; | ||
1481 | |||
1482 | while (count < max) { | ||
1483 | desc = &sds_ring->desc_head[consumer]; | ||
1484 | sts_data[1] = le64_to_cpu(desc->status_desc_data[1]); | ||
1485 | opcode = qlcnic_83xx_opcode(sts_data[1]); | ||
1486 | if (!opcode) | ||
1487 | break; | ||
1488 | sts_data[0] = le64_to_cpu(desc->status_desc_data[0]); | ||
1489 | ring = QLCNIC_FETCH_RING_ID(sts_data[0]); | ||
1490 | |||
1491 | switch (opcode) { | ||
1492 | case QLC_83XX_REG_DESC: | ||
1493 | rxbuf = qlcnic_83xx_process_rcv(adapter, sds_ring, | ||
1494 | ring, sts_data); | ||
1495 | break; | ||
1496 | case QLC_83XX_LRO_DESC: | ||
1497 | rxbuf = qlcnic_83xx_process_lro(adapter, ring, | ||
1498 | sts_data); | ||
1499 | break; | ||
1500 | default: | ||
1501 | dev_info(&adapter->pdev->dev, | ||
1502 | "Unkonwn opcode: 0x%x\n", opcode); | ||
1503 | goto skip; | ||
1504 | } | ||
1505 | |||
1506 | if (likely(rxbuf)) | ||
1507 | list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]); | ||
1508 | else | ||
1509 | adapter->stats.null_rxbuf++; | ||
1510 | skip: | ||
1511 | desc = &sds_ring->desc_head[consumer]; | ||
1512 | /* Reset the descriptor */ | ||
1513 | desc->status_desc_data[1] = 0; | ||
1514 | consumer = get_next_index(consumer, sds_ring->num_desc); | ||
1515 | count++; | ||
1516 | } | ||
1517 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { | ||
1518 | rds_ring = &adapter->recv_ctx->rds_rings[ring]; | ||
1519 | if (!list_empty(&sds_ring->free_list[ring])) { | ||
1520 | list_for_each(cur, &sds_ring->free_list[ring]) { | ||
1521 | rxbuf = list_entry(cur, struct qlcnic_rx_buffer, | ||
1522 | list); | ||
1523 | qlcnic_alloc_rx_skb(adapter, rds_ring, rxbuf); | ||
1524 | } | ||
1525 | spin_lock(&rds_ring->lock); | ||
1526 | list_splice_tail_init(&sds_ring->free_list[ring], | ||
1527 | &rds_ring->free_list); | ||
1528 | spin_unlock(&rds_ring->lock); | ||
1529 | } | ||
1530 | qlcnic_post_rx_buffers_nodb(adapter, rds_ring, ring); | ||
1531 | } | ||
1532 | if (count) { | ||
1533 | sds_ring->consumer = consumer; | ||
1534 | writel(consumer, sds_ring->crb_sts_consumer); | ||
1535 | } | ||
1536 | return count; | ||
1537 | } | ||
1538 | |||
1539 | static int qlcnic_83xx_poll(struct napi_struct *napi, int budget) | ||
1540 | { | ||
1541 | int tx_complete; | ||
1542 | int work_done; | ||
1543 | struct qlcnic_host_sds_ring *sds_ring; | ||
1544 | struct qlcnic_adapter *adapter; | ||
1545 | struct qlcnic_host_tx_ring *tx_ring; | ||
1546 | |||
1547 | sds_ring = container_of(napi, struct qlcnic_host_sds_ring, napi); | ||
1548 | adapter = sds_ring->adapter; | ||
1549 | /* tx ring count = 1 */ | ||
1550 | tx_ring = adapter->tx_ring; | ||
1551 | |||
1552 | if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) | ||
1553 | qlcnic_83xx_process_aen(adapter); | ||
1554 | |||
1555 | tx_complete = qlcnic_process_cmd_ring(adapter, tx_ring, budget); | ||
1556 | work_done = qlcnic_83xx_process_rcv_ring(sds_ring, budget); | ||
1557 | if ((work_done < budget) && tx_complete) { | ||
1558 | napi_complete(&sds_ring->napi); | ||
1559 | if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) | ||
1560 | qlcnic_83xx_enable_intr(adapter, sds_ring); | ||
1561 | } | ||
1562 | |||
1563 | return work_done; | ||
1564 | } | ||
1565 | |||
1566 | static int qlcnic_83xx_msix_tx_poll(struct napi_struct *napi, int budget) | ||
1567 | { | ||
1568 | int work_done; | ||
1569 | struct qlcnic_host_tx_ring *tx_ring; | ||
1570 | struct qlcnic_adapter *adapter; | ||
1571 | |||
1572 | budget = QLCNIC_TX_POLL_BUDGET; | ||
1573 | tx_ring = container_of(napi, struct qlcnic_host_tx_ring, napi); | ||
1574 | adapter = tx_ring->adapter; | ||
1575 | work_done = qlcnic_process_cmd_ring(adapter, tx_ring, budget); | ||
1576 | if (work_done) { | ||
1577 | napi_complete(&tx_ring->napi); | ||
1578 | if (test_bit(__QLCNIC_DEV_UP , &adapter->state)) | ||
1579 | qlcnic_83xx_enable_tx_intr(adapter, tx_ring); | ||
1580 | } | ||
1581 | |||
1582 | return work_done; | ||
1583 | } | ||
1584 | |||
1585 | static int qlcnic_83xx_rx_poll(struct napi_struct *napi, int budget) | ||
1586 | { | ||
1587 | int work_done; | ||
1588 | struct qlcnic_host_sds_ring *sds_ring; | ||
1589 | struct qlcnic_adapter *adapter; | ||
1590 | |||
1591 | sds_ring = container_of(napi, struct qlcnic_host_sds_ring, napi); | ||
1592 | adapter = sds_ring->adapter; | ||
1593 | work_done = qlcnic_83xx_process_rcv_ring(sds_ring, budget); | ||
1594 | if (work_done < budget) { | ||
1595 | napi_complete(&sds_ring->napi); | ||
1596 | if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) | ||
1597 | qlcnic_83xx_enable_intr(adapter, sds_ring); | ||
1598 | } | ||
1599 | |||
1600 | return work_done; | ||
1601 | } | ||
1602 | |||
1603 | void qlcnic_83xx_napi_enable(struct qlcnic_adapter *adapter) | ||
1604 | { | ||
1605 | int ring; | ||
1606 | struct qlcnic_host_sds_ring *sds_ring; | ||
1607 | struct qlcnic_host_tx_ring *tx_ring; | ||
1608 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; | ||
1609 | |||
1610 | if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) | ||
1611 | return; | ||
1612 | |||
1613 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { | ||
1614 | sds_ring = &recv_ctx->sds_rings[ring]; | ||
1615 | napi_enable(&sds_ring->napi); | ||
1616 | qlcnic_83xx_enable_intr(adapter, sds_ring); | ||
1617 | } | ||
1618 | |||
1619 | if (adapter->flags & QLCNIC_MSIX_ENABLED) { | ||
1620 | for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) { | ||
1621 | tx_ring = &adapter->tx_ring[ring]; | ||
1622 | napi_enable(&tx_ring->napi); | ||
1623 | qlcnic_83xx_enable_tx_intr(adapter, tx_ring); | ||
1624 | } | ||
1625 | } | ||
1626 | } | ||
1627 | |||
1628 | void qlcnic_83xx_napi_disable(struct qlcnic_adapter *adapter) | ||
1629 | { | ||
1630 | int ring; | ||
1631 | struct qlcnic_host_sds_ring *sds_ring; | ||
1632 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; | ||
1633 | struct qlcnic_host_tx_ring *tx_ring; | ||
1634 | |||
1635 | if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) | ||
1636 | return; | ||
1637 | |||
1638 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { | ||
1639 | sds_ring = &recv_ctx->sds_rings[ring]; | ||
1640 | writel(1, sds_ring->crb_intr_mask); | ||
1641 | napi_synchronize(&sds_ring->napi); | ||
1642 | napi_disable(&sds_ring->napi); | ||
1643 | } | ||
1644 | |||
1645 | if (adapter->flags & QLCNIC_MSIX_ENABLED) { | ||
1646 | for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) { | ||
1647 | tx_ring = &adapter->tx_ring[ring]; | ||
1648 | qlcnic_83xx_disable_tx_intr(adapter, tx_ring); | ||
1649 | napi_synchronize(&tx_ring->napi); | ||
1650 | napi_disable(&tx_ring->napi); | ||
1651 | } | ||
1652 | } | ||
1653 | } | ||
1654 | |||
1655 | int qlcnic_83xx_napi_add(struct qlcnic_adapter *adapter, | ||
1656 | struct net_device *netdev) | ||
1657 | { | ||
1658 | int ring, max_sds_rings; | ||
1659 | struct qlcnic_host_sds_ring *sds_ring; | ||
1660 | struct qlcnic_host_tx_ring *tx_ring; | ||
1661 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; | ||
1662 | |||
1663 | if (qlcnic_alloc_sds_rings(recv_ctx, adapter->max_sds_rings)) | ||
1664 | return -ENOMEM; | ||
1665 | |||
1666 | max_sds_rings = adapter->max_sds_rings; | ||
1667 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { | ||
1668 | sds_ring = &recv_ctx->sds_rings[ring]; | ||
1669 | if (adapter->flags & QLCNIC_MSIX_ENABLED) | ||
1670 | netif_napi_add(netdev, &sds_ring->napi, | ||
1671 | qlcnic_83xx_rx_poll, | ||
1672 | QLCNIC_NETDEV_WEIGHT * 2); | ||
1673 | else | ||
1674 | netif_napi_add(netdev, &sds_ring->napi, | ||
1675 | qlcnic_83xx_poll, | ||
1676 | QLCNIC_NETDEV_WEIGHT / max_sds_rings); | ||
1677 | } | ||
1678 | |||
1679 | if (qlcnic_alloc_tx_rings(adapter, netdev)) { | ||
1680 | qlcnic_free_sds_rings(recv_ctx); | ||
1681 | return -ENOMEM; | ||
1682 | } | ||
1683 | |||
1684 | if (adapter->flags & QLCNIC_MSIX_ENABLED) { | ||
1685 | for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) { | ||
1686 | tx_ring = &adapter->tx_ring[ring]; | ||
1687 | netif_napi_add(netdev, &tx_ring->napi, | ||
1688 | qlcnic_83xx_msix_tx_poll, | ||
1689 | QLCNIC_NETDEV_WEIGHT); | ||
1690 | } | ||
1691 | } | ||
1692 | |||
1693 | return 0; | ||
1694 | } | ||
1695 | |||
1696 | void qlcnic_83xx_napi_del(struct qlcnic_adapter *adapter) | ||
1697 | { | ||
1698 | int ring; | ||
1699 | struct qlcnic_host_sds_ring *sds_ring; | ||
1700 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; | ||
1701 | struct qlcnic_host_tx_ring *tx_ring; | ||
1702 | |||
1703 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { | ||
1704 | sds_ring = &recv_ctx->sds_rings[ring]; | ||
1705 | netif_napi_del(&sds_ring->napi); | ||
1706 | } | ||
1707 | |||
1708 | qlcnic_free_sds_rings(adapter->recv_ctx); | ||
1709 | |||
1710 | if ((adapter->flags & QLCNIC_MSIX_ENABLED)) { | ||
1711 | for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) { | ||
1712 | tx_ring = &adapter->tx_ring[ring]; | ||
1713 | netif_napi_del(&tx_ring->napi); | ||
1714 | } | ||
1715 | } | ||
1716 | |||
1717 | qlcnic_free_tx_rings(adapter); | ||
1718 | } | ||
1719 | |||
1720 | void qlcnic_83xx_process_rcv_diag(struct qlcnic_adapter *adapter, | ||
1721 | int ring, u64 sts_data[]) | ||
1722 | { | ||
1723 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; | ||
1724 | struct sk_buff *skb; | ||
1725 | struct qlcnic_host_rds_ring *rds_ring; | ||
1726 | int index, length; | ||
1727 | |||
1728 | if (unlikely(ring >= adapter->max_rds_rings)) | ||
1729 | return; | ||
1730 | |||
1731 | rds_ring = &recv_ctx->rds_rings[ring]; | ||
1732 | index = qlcnic_83xx_hndl(sts_data[0]); | ||
1733 | if (unlikely(index >= rds_ring->num_desc)) | ||
1734 | return; | ||
1735 | |||
1736 | length = qlcnic_83xx_pktln(sts_data[0]); | ||
1737 | |||
1738 | skb = qlcnic_process_rxbuf(adapter, rds_ring, index, STATUS_CKSUM_OK); | ||
1739 | if (!skb) | ||
1740 | return; | ||
1741 | |||
1742 | if (length > rds_ring->skb_size) | ||
1743 | skb_put(skb, rds_ring->skb_size); | ||
1744 | else | ||
1745 | skb_put(skb, length); | ||
1746 | |||
1747 | if (!qlcnic_check_loopback_buff(skb->data, adapter->mac_addr)) | ||
1748 | adapter->ahw->diag_cnt++; | ||
1749 | else | ||
1750 | dump_skb(skb, adapter); | ||
1751 | |||
1752 | dev_kfree_skb_any(skb); | ||
1753 | return; | ||
1754 | } | ||
1755 | |||
1756 | void qlcnic_83xx_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring) | ||
1757 | { | ||
1758 | struct qlcnic_adapter *adapter = sds_ring->adapter; | ||
1759 | struct status_desc *desc; | ||
1760 | u64 sts_data[2]; | ||
1761 | int ring, opcode; | ||
1762 | u32 consumer = sds_ring->consumer; | ||
1763 | |||
1764 | desc = &sds_ring->desc_head[consumer]; | ||
1765 | sts_data[0] = le64_to_cpu(desc->status_desc_data[0]); | ||
1766 | sts_data[1] = le64_to_cpu(desc->status_desc_data[1]); | ||
1767 | opcode = qlcnic_83xx_opcode(sts_data[1]); | ||
1768 | if (!opcode) | ||
1769 | return; | ||
1770 | |||
1771 | ring = QLCNIC_FETCH_RING_ID(qlcnic_83xx_hndl(sts_data[0])); | ||
1772 | qlcnic_83xx_process_rcv_diag(adapter, ring, sts_data); | ||
1773 | desc = &sds_ring->desc_head[consumer]; | ||
1774 | desc->status_desc_data[0] = cpu_to_le64(STATUS_OWNER_PHANTOM); | ||
1775 | consumer = get_next_index(consumer, sds_ring->num_desc); | ||
1776 | sds_ring->consumer = consumer; | ||
1777 | writel(consumer, sds_ring->crb_sts_consumer); | ||
1778 | } | ||
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 9498b39770bb..ae289abfeb2f 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | |||
@@ -303,6 +303,7 @@ static struct qlcnic_nic_template qlcnic_ops = { | |||
303 | .request_reset = qlcnic_82xx_dev_request_reset, | 303 | .request_reset = qlcnic_82xx_dev_request_reset, |
304 | .cancel_idc_work = qlcnic_82xx_cancel_idc_work, | 304 | .cancel_idc_work = qlcnic_82xx_cancel_idc_work, |
305 | .napi_add = qlcnic_82xx_napi_add, | 305 | .napi_add = qlcnic_82xx_napi_add, |
306 | .napi_del = qlcnic_82xx_napi_del, | ||
306 | .config_ipaddr = qlcnic_82xx_config_ipaddr, | 307 | .config_ipaddr = qlcnic_82xx_config_ipaddr, |
307 | .clear_legacy_intr = qlcnic_82xx_clear_legacy_intr, | 308 | .clear_legacy_intr = qlcnic_82xx_clear_legacy_intr, |
308 | }; | 309 | }; |
@@ -1201,7 +1202,7 @@ __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev) | |||
1201 | 1202 | ||
1202 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { | 1203 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { |
1203 | rds_ring = &adapter->recv_ctx->rds_rings[ring]; | 1204 | rds_ring = &adapter->recv_ctx->rds_rings[ring]; |
1204 | qlcnic_post_rx_buffers(adapter, rds_ring); | 1205 | qlcnic_post_rx_buffers(adapter, rds_ring, ring); |
1205 | } | 1206 | } |
1206 | 1207 | ||
1207 | qlcnic_set_multi(netdev); | 1208 | qlcnic_set_multi(netdev); |
@@ -1380,21 +1381,11 @@ out: | |||
1380 | static int qlcnic_alloc_adapter_resources(struct qlcnic_adapter *adapter) | 1381 | static int qlcnic_alloc_adapter_resources(struct qlcnic_adapter *adapter) |
1381 | { | 1382 | { |
1382 | int err = 0; | 1383 | int err = 0; |
1383 | adapter->ahw = kzalloc(sizeof(struct qlcnic_hardware_context), | ||
1384 | GFP_KERNEL); | ||
1385 | if (!adapter->ahw) { | ||
1386 | dev_err(&adapter->pdev->dev, | ||
1387 | "Failed to allocate recv ctx resources for adapter\n"); | ||
1388 | err = -ENOMEM; | ||
1389 | goto err_out; | ||
1390 | } | ||
1391 | adapter->recv_ctx = kzalloc(sizeof(struct qlcnic_recv_context), | 1384 | adapter->recv_ctx = kzalloc(sizeof(struct qlcnic_recv_context), |
1392 | GFP_KERNEL); | 1385 | GFP_KERNEL); |
1393 | if (!adapter->recv_ctx) { | 1386 | if (!adapter->recv_ctx) { |
1394 | dev_err(&adapter->pdev->dev, | 1387 | dev_err(&adapter->pdev->dev, |
1395 | "Failed to allocate recv ctx resources for adapter\n"); | 1388 | "Failed to allocate recv ctx resources for adapter\n"); |
1396 | kfree(adapter->ahw); | ||
1397 | adapter->ahw = NULL; | ||
1398 | err = -ENOMEM; | 1389 | err = -ENOMEM; |
1399 | goto err_out; | 1390 | goto err_out; |
1400 | } | 1391 | } |
@@ -1402,6 +1393,8 @@ static int qlcnic_alloc_adapter_resources(struct qlcnic_adapter *adapter) | |||
1402 | adapter->ahw->coal.flag = QLCNIC_INTR_DEFAULT; | 1393 | adapter->ahw->coal.flag = QLCNIC_INTR_DEFAULT; |
1403 | adapter->ahw->coal.rx_time_us = QLCNIC_DEFAULT_INTR_COALESCE_RX_TIME_US; | 1394 | adapter->ahw->coal.rx_time_us = QLCNIC_DEFAULT_INTR_COALESCE_RX_TIME_US; |
1404 | adapter->ahw->coal.rx_packets = QLCNIC_DEFAULT_INTR_COALESCE_RX_PACKETS; | 1395 | adapter->ahw->coal.rx_packets = QLCNIC_DEFAULT_INTR_COALESCE_RX_PACKETS; |
1396 | /* clear stats */ | ||
1397 | memset(&adapter->stats, 0, sizeof(adapter->stats)); | ||
1405 | err_out: | 1398 | err_out: |
1406 | return err; | 1399 | return err; |
1407 | } | 1400 | } |
@@ -1415,8 +1408,8 @@ static void qlcnic_free_adapter_resources(struct qlcnic_adapter *adapter) | |||
1415 | vfree(adapter->ahw->fw_dump.tmpl_hdr); | 1408 | vfree(adapter->ahw->fw_dump.tmpl_hdr); |
1416 | adapter->ahw->fw_dump.tmpl_hdr = NULL; | 1409 | adapter->ahw->fw_dump.tmpl_hdr = NULL; |
1417 | } | 1410 | } |
1418 | kfree(adapter->ahw); | 1411 | |
1419 | adapter->ahw = NULL; | 1412 | adapter->ahw->fw_dump.tmpl_hdr = NULL; |
1420 | } | 1413 | } |
1421 | 1414 | ||
1422 | int qlcnic_diag_alloc_res(struct net_device *netdev, int test) | 1415 | int qlcnic_diag_alloc_res(struct net_device *netdev, int test) |
@@ -1436,6 +1429,7 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test) | |||
1436 | 1429 | ||
1437 | adapter->max_sds_rings = 1; | 1430 | adapter->max_sds_rings = 1; |
1438 | adapter->ahw->diag_test = test; | 1431 | adapter->ahw->diag_test = test; |
1432 | adapter->ahw->linkup = 0; | ||
1439 | 1433 | ||
1440 | ret = qlcnic_attach(adapter); | 1434 | ret = qlcnic_attach(adapter); |
1441 | if (ret) { | 1435 | if (ret) { |
@@ -1452,7 +1446,7 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test) | |||
1452 | 1446 | ||
1453 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { | 1447 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { |
1454 | rds_ring = &adapter->recv_ctx->rds_rings[ring]; | 1448 | rds_ring = &adapter->recv_ctx->rds_rings[ring]; |
1455 | qlcnic_post_rx_buffers(adapter, rds_ring); | 1449 | qlcnic_post_rx_buffers(adapter, rds_ring, ring); |
1456 | } | 1450 | } |
1457 | 1451 | ||
1458 | if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) { | 1452 | if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) { |
@@ -1601,6 +1595,66 @@ qlcnic_alloc_msix_entries(struct qlcnic_adapter *adapter, u16 count) | |||
1601 | return -ENOMEM; | 1595 | return -ENOMEM; |
1602 | } | 1596 | } |
1603 | 1597 | ||
1598 | void qlcnic_free_tx_rings(struct qlcnic_adapter *adapter) | ||
1599 | { | ||
1600 | int ring; | ||
1601 | struct qlcnic_host_tx_ring *tx_ring; | ||
1602 | |||
1603 | for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) { | ||
1604 | tx_ring = &adapter->tx_ring[ring]; | ||
1605 | if (tx_ring && tx_ring->cmd_buf_arr != NULL) { | ||
1606 | vfree(tx_ring->cmd_buf_arr); | ||
1607 | tx_ring->cmd_buf_arr = NULL; | ||
1608 | } | ||
1609 | } | ||
1610 | if (adapter->tx_ring != NULL) | ||
1611 | kfree(adapter->tx_ring); | ||
1612 | } | ||
1613 | |||
1614 | int qlcnic_alloc_tx_rings(struct qlcnic_adapter *adapter, | ||
1615 | struct net_device *netdev) | ||
1616 | { | ||
1617 | int ring, size, vector, index; | ||
1618 | struct qlcnic_host_tx_ring *tx_ring; | ||
1619 | struct qlcnic_cmd_buffer *cmd_buf_arr; | ||
1620 | |||
1621 | size = adapter->max_drv_tx_rings * sizeof(struct qlcnic_host_tx_ring); | ||
1622 | tx_ring = kzalloc(size, GFP_KERNEL); | ||
1623 | if (tx_ring == NULL) { | ||
1624 | dev_err(&netdev->dev, "failed to allocate tx rings\n"); | ||
1625 | return -ENOMEM; | ||
1626 | } | ||
1627 | adapter->tx_ring = tx_ring; | ||
1628 | |||
1629 | for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) { | ||
1630 | tx_ring = &adapter->tx_ring[ring]; | ||
1631 | tx_ring->num_desc = adapter->num_txd; | ||
1632 | tx_ring->txq = netdev_get_tx_queue(netdev, ring); | ||
1633 | cmd_buf_arr = vzalloc(TX_BUFF_RINGSIZE(tx_ring)); | ||
1634 | if (cmd_buf_arr == NULL) { | ||
1635 | dev_err(&netdev->dev, | ||
1636 | "failed to allocate cmd buffer ring\n"); | ||
1637 | qlcnic_free_tx_rings(adapter); | ||
1638 | return -ENOMEM; | ||
1639 | } | ||
1640 | memset(cmd_buf_arr, 0, TX_BUFF_RINGSIZE(tx_ring)); | ||
1641 | tx_ring->cmd_buf_arr = cmd_buf_arr; | ||
1642 | } | ||
1643 | |||
1644 | if (qlcnic_83xx_check(adapter)) { | ||
1645 | for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) { | ||
1646 | tx_ring = &adapter->tx_ring[ring]; | ||
1647 | tx_ring->adapter = adapter; | ||
1648 | if (adapter->flags & QLCNIC_MSIX_ENABLED) { | ||
1649 | index = adapter->max_sds_rings + ring; | ||
1650 | vector = adapter->msix_entries[index].vector; | ||
1651 | tx_ring->irq = vector; | ||
1652 | } | ||
1653 | } | ||
1654 | } | ||
1655 | return 0; | ||
1656 | } | ||
1657 | |||
1604 | static int __devinit | 1658 | static int __devinit |
1605 | qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 1659 | qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
1606 | { | 1660 | { |