diff options
author | Sony Chacko <sony.chacko@qlogic.com> | 2012-11-27 23:34:26 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-11-28 11:07:43 -0500 |
commit | c70001a952e561775222d28a9e2f2a0075af51f3 (patch) | |
tree | 8698785c3426bc26eeb98af21f06a19d6d687e1c /drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c | |
parent | 3a858a86922f3aeb85a352f3d1ce44c2a99b69a6 (diff) |
qlcnic: create file qlcnic_io.c for datapath routines
Physical refactoring of 82xx adapter data path routines.
Move data path code to new file qlcnic_io.c
Existing data path code has coding stye issues, the code is
moved to the new file without fixing the style issues.
There is a seperate patch to fix the style issues in qlcnic_io.c
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/qlcnic_init.c')
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c | 630 |
1 files changed, 0 insertions, 630 deletions
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c index ccbef8491d2..d8610ea56a4 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c | |||
@@ -25,10 +25,6 @@ static unsigned int crb_addr_xform[QLCNIC_MAX_CRB_XFORM]; | |||
25 | 25 | ||
26 | #define QLCNIC_ADDR_ERROR (0xffffffff) | 26 | #define QLCNIC_ADDR_ERROR (0xffffffff) |
27 | 27 | ||
28 | static void | ||
29 | qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter, | ||
30 | struct qlcnic_host_rds_ring *rds_ring); | ||
31 | |||
32 | static int | 28 | static int |
33 | qlcnic_check_fw_hearbeat(struct qlcnic_adapter *adapter); | 29 | qlcnic_check_fw_hearbeat(struct qlcnic_adapter *adapter); |
34 | 30 | ||
@@ -1332,629 +1328,3 @@ qlcnic_release_firmware(struct qlcnic_adapter *adapter) | |||
1332 | release_firmware(adapter->fw); | 1328 | release_firmware(adapter->fw); |
1333 | adapter->fw = NULL; | 1329 | adapter->fw = NULL; |
1334 | } | 1330 | } |
1335 | |||
1336 | static void | ||
1337 | qlcnic_handle_linkevent(struct qlcnic_adapter *adapter, | ||
1338 | struct qlcnic_fw_msg *msg) | ||
1339 | { | ||
1340 | u32 cable_OUI; | ||
1341 | u16 cable_len; | ||
1342 | u16 link_speed; | ||
1343 | u8 link_status, module, duplex, autoneg; | ||
1344 | u8 lb_status = 0; | ||
1345 | struct net_device *netdev = adapter->netdev; | ||
1346 | |||
1347 | adapter->has_link_events = 1; | ||
1348 | |||
1349 | cable_OUI = msg->body[1] & 0xffffffff; | ||
1350 | cable_len = (msg->body[1] >> 32) & 0xffff; | ||
1351 | link_speed = (msg->body[1] >> 48) & 0xffff; | ||
1352 | |||
1353 | link_status = msg->body[2] & 0xff; | ||
1354 | duplex = (msg->body[2] >> 16) & 0xff; | ||
1355 | autoneg = (msg->body[2] >> 24) & 0xff; | ||
1356 | lb_status = (msg->body[2] >> 32) & 0x3; | ||
1357 | |||
1358 | module = (msg->body[2] >> 8) & 0xff; | ||
1359 | if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE) | ||
1360 | dev_info(&netdev->dev, "unsupported cable: OUI 0x%x, " | ||
1361 | "length %d\n", cable_OUI, cable_len); | ||
1362 | else if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN) | ||
1363 | dev_info(&netdev->dev, "unsupported cable length %d\n", | ||
1364 | cable_len); | ||
1365 | |||
1366 | if (!link_status && (lb_status == QLCNIC_ILB_MODE || | ||
1367 | lb_status == QLCNIC_ELB_MODE)) | ||
1368 | adapter->ahw->loopback_state |= QLCNIC_LINKEVENT; | ||
1369 | |||
1370 | qlcnic_advert_link_change(adapter, link_status); | ||
1371 | |||
1372 | if (duplex == LINKEVENT_FULL_DUPLEX) | ||
1373 | adapter->link_duplex = DUPLEX_FULL; | ||
1374 | else | ||
1375 | adapter->link_duplex = DUPLEX_HALF; | ||
1376 | |||
1377 | adapter->module_type = module; | ||
1378 | adapter->link_autoneg = autoneg; | ||
1379 | |||
1380 | if (link_status) { | ||
1381 | adapter->link_speed = link_speed; | ||
1382 | } else { | ||
1383 | adapter->link_speed = SPEED_UNKNOWN; | ||
1384 | adapter->link_duplex = DUPLEX_UNKNOWN; | ||
1385 | } | ||
1386 | } | ||
1387 | |||
1388 | static void | ||
1389 | qlcnic_handle_fw_message(int desc_cnt, int index, | ||
1390 | struct qlcnic_host_sds_ring *sds_ring) | ||
1391 | { | ||
1392 | struct qlcnic_fw_msg msg; | ||
1393 | struct status_desc *desc; | ||
1394 | struct qlcnic_adapter *adapter; | ||
1395 | struct device *dev; | ||
1396 | int i = 0, opcode, ret; | ||
1397 | |||
1398 | while (desc_cnt > 0 && i < 8) { | ||
1399 | desc = &sds_ring->desc_head[index]; | ||
1400 | msg.words[i++] = le64_to_cpu(desc->status_desc_data[0]); | ||
1401 | msg.words[i++] = le64_to_cpu(desc->status_desc_data[1]); | ||
1402 | |||
1403 | index = get_next_index(index, sds_ring->num_desc); | ||
1404 | desc_cnt--; | ||
1405 | } | ||
1406 | |||
1407 | adapter = sds_ring->adapter; | ||
1408 | dev = &adapter->pdev->dev; | ||
1409 | opcode = qlcnic_get_nic_msg_opcode(msg.body[0]); | ||
1410 | |||
1411 | switch (opcode) { | ||
1412 | case QLCNIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE: | ||
1413 | qlcnic_handle_linkevent(adapter, &msg); | ||
1414 | break; | ||
1415 | case QLCNIC_C2H_OPCODE_CONFIG_LOOPBACK: | ||
1416 | ret = (u32)(msg.body[1]); | ||
1417 | switch (ret) { | ||
1418 | case 0: | ||
1419 | adapter->ahw->loopback_state |= QLCNIC_LB_RESPONSE; | ||
1420 | break; | ||
1421 | case 1: | ||
1422 | dev_info(dev, "loopback already in progress\n"); | ||
1423 | adapter->diag_cnt = -QLCNIC_TEST_IN_PROGRESS; | ||
1424 | break; | ||
1425 | case 2: | ||
1426 | dev_info(dev, "loopback cable is not connected\n"); | ||
1427 | adapter->diag_cnt = -QLCNIC_LB_CABLE_NOT_CONN; | ||
1428 | break; | ||
1429 | default: | ||
1430 | dev_info(dev, "loopback configure request failed," | ||
1431 | " ret %x\n", ret); | ||
1432 | adapter->diag_cnt = -QLCNIC_UNDEFINED_ERROR; | ||
1433 | break; | ||
1434 | } | ||
1435 | break; | ||
1436 | default: | ||
1437 | break; | ||
1438 | } | ||
1439 | } | ||
1440 | |||
1441 | static int | ||
1442 | qlcnic_alloc_rx_skb(struct qlcnic_adapter *adapter, | ||
1443 | struct qlcnic_host_rds_ring *rds_ring, | ||
1444 | struct qlcnic_rx_buffer *buffer) | ||
1445 | { | ||
1446 | struct sk_buff *skb; | ||
1447 | dma_addr_t dma; | ||
1448 | struct pci_dev *pdev = adapter->pdev; | ||
1449 | |||
1450 | skb = netdev_alloc_skb(adapter->netdev, rds_ring->skb_size); | ||
1451 | if (!skb) { | ||
1452 | adapter->stats.skb_alloc_failure++; | ||
1453 | return -ENOMEM; | ||
1454 | } | ||
1455 | |||
1456 | skb_reserve(skb, NET_IP_ALIGN); | ||
1457 | |||
1458 | dma = pci_map_single(pdev, skb->data, | ||
1459 | rds_ring->dma_size, PCI_DMA_FROMDEVICE); | ||
1460 | |||
1461 | if (pci_dma_mapping_error(pdev, dma)) { | ||
1462 | adapter->stats.rx_dma_map_error++; | ||
1463 | dev_kfree_skb_any(skb); | ||
1464 | return -ENOMEM; | ||
1465 | } | ||
1466 | |||
1467 | buffer->skb = skb; | ||
1468 | buffer->dma = dma; | ||
1469 | |||
1470 | return 0; | ||
1471 | } | ||
1472 | |||
1473 | static struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *adapter, | ||
1474 | struct qlcnic_host_rds_ring *rds_ring, u16 index, u16 cksum) | ||
1475 | { | ||
1476 | struct qlcnic_rx_buffer *buffer; | ||
1477 | struct sk_buff *skb; | ||
1478 | |||
1479 | buffer = &rds_ring->rx_buf_arr[index]; | ||
1480 | |||
1481 | if (unlikely(buffer->skb == NULL)) { | ||
1482 | WARN_ON(1); | ||
1483 | return NULL; | ||
1484 | } | ||
1485 | |||
1486 | pci_unmap_single(adapter->pdev, buffer->dma, rds_ring->dma_size, | ||
1487 | PCI_DMA_FROMDEVICE); | ||
1488 | |||
1489 | skb = buffer->skb; | ||
1490 | |||
1491 | if (likely((adapter->netdev->features & NETIF_F_RXCSUM) && | ||
1492 | (cksum == STATUS_CKSUM_OK || cksum == STATUS_CKSUM_LOOP))) { | ||
1493 | adapter->stats.csummed++; | ||
1494 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
1495 | } else { | ||
1496 | skb_checksum_none_assert(skb); | ||
1497 | } | ||
1498 | |||
1499 | buffer->skb = NULL; | ||
1500 | |||
1501 | return skb; | ||
1502 | } | ||
1503 | |||
1504 | static inline int | ||
1505 | qlcnic_check_rx_tagging(struct qlcnic_adapter *adapter, struct sk_buff *skb, | ||
1506 | u16 *vlan_tag) | ||
1507 | { | ||
1508 | struct ethhdr *eth_hdr; | ||
1509 | |||
1510 | if (!__vlan_get_tag(skb, vlan_tag)) { | ||
1511 | eth_hdr = (struct ethhdr *) skb->data; | ||
1512 | memmove(skb->data + VLAN_HLEN, eth_hdr, ETH_ALEN * 2); | ||
1513 | skb_pull(skb, VLAN_HLEN); | ||
1514 | } | ||
1515 | if (!adapter->pvid) | ||
1516 | return 0; | ||
1517 | |||
1518 | if (*vlan_tag == adapter->pvid) { | ||
1519 | /* Outer vlan tag. Packet should follow non-vlan path */ | ||
1520 | *vlan_tag = 0xffff; | ||
1521 | return 0; | ||
1522 | } | ||
1523 | if (adapter->flags & QLCNIC_TAGGING_ENABLED) | ||
1524 | return 0; | ||
1525 | |||
1526 | return -EINVAL; | ||
1527 | } | ||
1528 | |||
1529 | static struct qlcnic_rx_buffer * | ||
1530 | qlcnic_process_rcv(struct qlcnic_adapter *adapter, | ||
1531 | struct qlcnic_host_sds_ring *sds_ring, | ||
1532 | int ring, u64 sts_data0) | ||
1533 | { | ||
1534 | struct net_device *netdev = adapter->netdev; | ||
1535 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; | ||
1536 | struct qlcnic_rx_buffer *buffer; | ||
1537 | struct sk_buff *skb; | ||
1538 | struct qlcnic_host_rds_ring *rds_ring; | ||
1539 | int index, length, cksum, pkt_offset; | ||
1540 | u16 vid = 0xffff; | ||
1541 | |||
1542 | if (unlikely(ring >= adapter->max_rds_rings)) | ||
1543 | return NULL; | ||
1544 | |||
1545 | rds_ring = &recv_ctx->rds_rings[ring]; | ||
1546 | |||
1547 | index = qlcnic_get_sts_refhandle(sts_data0); | ||
1548 | if (unlikely(index >= rds_ring->num_desc)) | ||
1549 | return NULL; | ||
1550 | |||
1551 | buffer = &rds_ring->rx_buf_arr[index]; | ||
1552 | |||
1553 | length = qlcnic_get_sts_totallength(sts_data0); | ||
1554 | cksum = qlcnic_get_sts_status(sts_data0); | ||
1555 | pkt_offset = qlcnic_get_sts_pkt_offset(sts_data0); | ||
1556 | |||
1557 | skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum); | ||
1558 | if (!skb) | ||
1559 | return buffer; | ||
1560 | |||
1561 | if (length > rds_ring->skb_size) | ||
1562 | skb_put(skb, rds_ring->skb_size); | ||
1563 | else | ||
1564 | skb_put(skb, length); | ||
1565 | |||
1566 | if (pkt_offset) | ||
1567 | skb_pull(skb, pkt_offset); | ||
1568 | |||
1569 | if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) { | ||
1570 | adapter->stats.rxdropped++; | ||
1571 | dev_kfree_skb(skb); | ||
1572 | return buffer; | ||
1573 | } | ||
1574 | |||
1575 | skb->protocol = eth_type_trans(skb, netdev); | ||
1576 | |||
1577 | if (vid != 0xffff) | ||
1578 | __vlan_hwaccel_put_tag(skb, vid); | ||
1579 | |||
1580 | napi_gro_receive(&sds_ring->napi, skb); | ||
1581 | |||
1582 | adapter->stats.rx_pkts++; | ||
1583 | adapter->stats.rxbytes += length; | ||
1584 | |||
1585 | return buffer; | ||
1586 | } | ||
1587 | |||
1588 | #define QLC_TCP_HDR_SIZE 20 | ||
1589 | #define QLC_TCP_TS_OPTION_SIZE 12 | ||
1590 | #define QLC_TCP_TS_HDR_SIZE (QLC_TCP_HDR_SIZE + QLC_TCP_TS_OPTION_SIZE) | ||
1591 | |||
1592 | static struct qlcnic_rx_buffer * | ||
1593 | qlcnic_process_lro(struct qlcnic_adapter *adapter, | ||
1594 | int ring, u64 sts_data0, u64 sts_data1) | ||
1595 | { | ||
1596 | struct net_device *netdev = adapter->netdev; | ||
1597 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; | ||
1598 | struct qlcnic_rx_buffer *buffer; | ||
1599 | struct sk_buff *skb; | ||
1600 | struct qlcnic_host_rds_ring *rds_ring; | ||
1601 | struct iphdr *iph; | ||
1602 | struct tcphdr *th; | ||
1603 | bool push, timestamp; | ||
1604 | int l2_hdr_offset, l4_hdr_offset; | ||
1605 | int index; | ||
1606 | u16 lro_length, length, data_offset; | ||
1607 | u32 seq_number; | ||
1608 | u16 vid = 0xffff; | ||
1609 | |||
1610 | if (unlikely(ring > adapter->max_rds_rings)) | ||
1611 | return NULL; | ||
1612 | |||
1613 | rds_ring = &recv_ctx->rds_rings[ring]; | ||
1614 | |||
1615 | index = qlcnic_get_lro_sts_refhandle(sts_data0); | ||
1616 | if (unlikely(index > rds_ring->num_desc)) | ||
1617 | return NULL; | ||
1618 | |||
1619 | buffer = &rds_ring->rx_buf_arr[index]; | ||
1620 | |||
1621 | timestamp = qlcnic_get_lro_sts_timestamp(sts_data0); | ||
1622 | lro_length = qlcnic_get_lro_sts_length(sts_data0); | ||
1623 | l2_hdr_offset = qlcnic_get_lro_sts_l2_hdr_offset(sts_data0); | ||
1624 | l4_hdr_offset = qlcnic_get_lro_sts_l4_hdr_offset(sts_data0); | ||
1625 | push = qlcnic_get_lro_sts_push_flag(sts_data0); | ||
1626 | seq_number = qlcnic_get_lro_sts_seq_number(sts_data1); | ||
1627 | |||
1628 | skb = qlcnic_process_rxbuf(adapter, rds_ring, index, STATUS_CKSUM_OK); | ||
1629 | if (!skb) | ||
1630 | return buffer; | ||
1631 | |||
1632 | if (timestamp) | ||
1633 | data_offset = l4_hdr_offset + QLC_TCP_TS_HDR_SIZE; | ||
1634 | else | ||
1635 | data_offset = l4_hdr_offset + QLC_TCP_HDR_SIZE; | ||
1636 | |||
1637 | skb_put(skb, lro_length + data_offset); | ||
1638 | |||
1639 | skb_pull(skb, l2_hdr_offset); | ||
1640 | |||
1641 | if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) { | ||
1642 | adapter->stats.rxdropped++; | ||
1643 | dev_kfree_skb(skb); | ||
1644 | return buffer; | ||
1645 | } | ||
1646 | |||
1647 | skb->protocol = eth_type_trans(skb, netdev); | ||
1648 | |||
1649 | iph = (struct iphdr *)skb->data; | ||
1650 | th = (struct tcphdr *)(skb->data + (iph->ihl << 2)); | ||
1651 | |||
1652 | length = (iph->ihl << 2) + (th->doff << 2) + lro_length; | ||
1653 | iph->tot_len = htons(length); | ||
1654 | iph->check = 0; | ||
1655 | iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); | ||
1656 | th->psh = push; | ||
1657 | th->seq = htonl(seq_number); | ||
1658 | |||
1659 | length = skb->len; | ||
1660 | |||
1661 | if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP) | ||
1662 | skb_shinfo(skb)->gso_size = qlcnic_get_lro_sts_mss(sts_data1); | ||
1663 | |||
1664 | if (vid != 0xffff) | ||
1665 | __vlan_hwaccel_put_tag(skb, vid); | ||
1666 | netif_receive_skb(skb); | ||
1667 | |||
1668 | adapter->stats.lro_pkts++; | ||
1669 | adapter->stats.lrobytes += length; | ||
1670 | |||
1671 | return buffer; | ||
1672 | } | ||
1673 | |||
1674 | int | ||
1675 | qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max) | ||
1676 | { | ||
1677 | struct qlcnic_adapter *adapter = sds_ring->adapter; | ||
1678 | struct list_head *cur; | ||
1679 | struct status_desc *desc; | ||
1680 | struct qlcnic_rx_buffer *rxbuf; | ||
1681 | u64 sts_data0, sts_data1; | ||
1682 | |||
1683 | int count = 0; | ||
1684 | int opcode, ring, desc_cnt; | ||
1685 | u32 consumer = sds_ring->consumer; | ||
1686 | |||
1687 | while (count < max) { | ||
1688 | desc = &sds_ring->desc_head[consumer]; | ||
1689 | sts_data0 = le64_to_cpu(desc->status_desc_data[0]); | ||
1690 | |||
1691 | if (!(sts_data0 & STATUS_OWNER_HOST)) | ||
1692 | break; | ||
1693 | |||
1694 | desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0); | ||
1695 | opcode = qlcnic_get_sts_opcode(sts_data0); | ||
1696 | |||
1697 | switch (opcode) { | ||
1698 | case QLCNIC_RXPKT_DESC: | ||
1699 | case QLCNIC_OLD_RXPKT_DESC: | ||
1700 | case QLCNIC_SYN_OFFLOAD: | ||
1701 | ring = qlcnic_get_sts_type(sts_data0); | ||
1702 | rxbuf = qlcnic_process_rcv(adapter, sds_ring, | ||
1703 | ring, sts_data0); | ||
1704 | break; | ||
1705 | case QLCNIC_LRO_DESC: | ||
1706 | ring = qlcnic_get_lro_sts_type(sts_data0); | ||
1707 | sts_data1 = le64_to_cpu(desc->status_desc_data[1]); | ||
1708 | rxbuf = qlcnic_process_lro(adapter, ring, sts_data0, | ||
1709 | sts_data1); | ||
1710 | break; | ||
1711 | case QLCNIC_RESPONSE_DESC: | ||
1712 | qlcnic_handle_fw_message(desc_cnt, consumer, sds_ring); | ||
1713 | default: | ||
1714 | goto skip; | ||
1715 | } | ||
1716 | |||
1717 | WARN_ON(desc_cnt > 1); | ||
1718 | |||
1719 | if (likely(rxbuf)) | ||
1720 | list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]); | ||
1721 | else | ||
1722 | adapter->stats.null_rxbuf++; | ||
1723 | |||
1724 | skip: | ||
1725 | for (; desc_cnt > 0; desc_cnt--) { | ||
1726 | desc = &sds_ring->desc_head[consumer]; | ||
1727 | desc->status_desc_data[0] = | ||
1728 | cpu_to_le64(STATUS_OWNER_PHANTOM); | ||
1729 | consumer = get_next_index(consumer, sds_ring->num_desc); | ||
1730 | } | ||
1731 | count++; | ||
1732 | } | ||
1733 | |||
1734 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { | ||
1735 | struct qlcnic_host_rds_ring *rds_ring = | ||
1736 | &adapter->recv_ctx->rds_rings[ring]; | ||
1737 | |||
1738 | if (!list_empty(&sds_ring->free_list[ring])) { | ||
1739 | list_for_each(cur, &sds_ring->free_list[ring]) { | ||
1740 | rxbuf = list_entry(cur, | ||
1741 | struct qlcnic_rx_buffer, list); | ||
1742 | qlcnic_alloc_rx_skb(adapter, rds_ring, rxbuf); | ||
1743 | } | ||
1744 | spin_lock(&rds_ring->lock); | ||
1745 | list_splice_tail_init(&sds_ring->free_list[ring], | ||
1746 | &rds_ring->free_list); | ||
1747 | spin_unlock(&rds_ring->lock); | ||
1748 | } | ||
1749 | |||
1750 | qlcnic_post_rx_buffers_nodb(adapter, rds_ring); | ||
1751 | } | ||
1752 | |||
1753 | if (count) { | ||
1754 | sds_ring->consumer = consumer; | ||
1755 | writel(consumer, sds_ring->crb_sts_consumer); | ||
1756 | } | ||
1757 | |||
1758 | return count; | ||
1759 | } | ||
1760 | |||
1761 | void | ||
1762 | qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter, | ||
1763 | struct qlcnic_host_rds_ring *rds_ring) | ||
1764 | { | ||
1765 | struct rcv_desc *pdesc; | ||
1766 | struct qlcnic_rx_buffer *buffer; | ||
1767 | int count = 0; | ||
1768 | u32 producer; | ||
1769 | struct list_head *head; | ||
1770 | |||
1771 | producer = rds_ring->producer; | ||
1772 | |||
1773 | head = &rds_ring->free_list; | ||
1774 | while (!list_empty(head)) { | ||
1775 | |||
1776 | buffer = list_entry(head->next, struct qlcnic_rx_buffer, list); | ||
1777 | |||
1778 | if (!buffer->skb) { | ||
1779 | if (qlcnic_alloc_rx_skb(adapter, rds_ring, buffer)) | ||
1780 | break; | ||
1781 | } | ||
1782 | |||
1783 | count++; | ||
1784 | list_del(&buffer->list); | ||
1785 | |||
1786 | /* make a rcv descriptor */ | ||
1787 | pdesc = &rds_ring->desc_head[producer]; | ||
1788 | pdesc->addr_buffer = cpu_to_le64(buffer->dma); | ||
1789 | pdesc->reference_handle = cpu_to_le16(buffer->ref_handle); | ||
1790 | pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size); | ||
1791 | |||
1792 | producer = get_next_index(producer, rds_ring->num_desc); | ||
1793 | } | ||
1794 | |||
1795 | if (count) { | ||
1796 | rds_ring->producer = producer; | ||
1797 | writel((producer-1) & (rds_ring->num_desc-1), | ||
1798 | rds_ring->crb_rcv_producer); | ||
1799 | } | ||
1800 | } | ||
1801 | |||
1802 | static void | ||
1803 | qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter, | ||
1804 | struct qlcnic_host_rds_ring *rds_ring) | ||
1805 | { | ||
1806 | struct rcv_desc *pdesc; | ||
1807 | struct qlcnic_rx_buffer *buffer; | ||
1808 | int count = 0; | ||
1809 | uint32_t producer; | ||
1810 | struct list_head *head; | ||
1811 | |||
1812 | if (!spin_trylock(&rds_ring->lock)) | ||
1813 | return; | ||
1814 | |||
1815 | producer = rds_ring->producer; | ||
1816 | |||
1817 | head = &rds_ring->free_list; | ||
1818 | while (!list_empty(head)) { | ||
1819 | |||
1820 | buffer = list_entry(head->next, struct qlcnic_rx_buffer, list); | ||
1821 | |||
1822 | if (!buffer->skb) { | ||
1823 | if (qlcnic_alloc_rx_skb(adapter, rds_ring, buffer)) | ||
1824 | break; | ||
1825 | } | ||
1826 | |||
1827 | count++; | ||
1828 | list_del(&buffer->list); | ||
1829 | |||
1830 | /* make a rcv descriptor */ | ||
1831 | pdesc = &rds_ring->desc_head[producer]; | ||
1832 | pdesc->reference_handle = cpu_to_le16(buffer->ref_handle); | ||
1833 | pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size); | ||
1834 | pdesc->addr_buffer = cpu_to_le64(buffer->dma); | ||
1835 | |||
1836 | producer = get_next_index(producer, rds_ring->num_desc); | ||
1837 | } | ||
1838 | |||
1839 | if (count) { | ||
1840 | rds_ring->producer = producer; | ||
1841 | writel((producer - 1) & (rds_ring->num_desc - 1), | ||
1842 | rds_ring->crb_rcv_producer); | ||
1843 | } | ||
1844 | spin_unlock(&rds_ring->lock); | ||
1845 | } | ||
1846 | |||
1847 | static void dump_skb(struct sk_buff *skb, struct qlcnic_adapter *adapter) | ||
1848 | { | ||
1849 | int i; | ||
1850 | unsigned char *data = skb->data; | ||
1851 | |||
1852 | printk(KERN_INFO "\n"); | ||
1853 | for (i = 0; i < skb->len; i++) { | ||
1854 | QLCDB(adapter, DRV, "%02x ", data[i]); | ||
1855 | if ((i & 0x0f) == 8) | ||
1856 | printk(KERN_INFO "\n"); | ||
1857 | } | ||
1858 | } | ||
1859 | |||
1860 | static void qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter, int ring, | ||
1861 | u64 sts_data0) | ||
1862 | { | ||
1863 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; | ||
1864 | struct sk_buff *skb; | ||
1865 | struct qlcnic_host_rds_ring *rds_ring; | ||
1866 | int index, length, cksum, pkt_offset; | ||
1867 | |||
1868 | if (unlikely(ring >= adapter->max_rds_rings)) | ||
1869 | return; | ||
1870 | |||
1871 | rds_ring = &recv_ctx->rds_rings[ring]; | ||
1872 | |||
1873 | index = qlcnic_get_sts_refhandle(sts_data0); | ||
1874 | length = qlcnic_get_sts_totallength(sts_data0); | ||
1875 | if (unlikely(index >= rds_ring->num_desc)) | ||
1876 | return; | ||
1877 | |||
1878 | cksum = qlcnic_get_sts_status(sts_data0); | ||
1879 | pkt_offset = qlcnic_get_sts_pkt_offset(sts_data0); | ||
1880 | |||
1881 | skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum); | ||
1882 | if (!skb) | ||
1883 | return; | ||
1884 | |||
1885 | if (length > rds_ring->skb_size) | ||
1886 | skb_put(skb, rds_ring->skb_size); | ||
1887 | else | ||
1888 | skb_put(skb, length); | ||
1889 | |||
1890 | if (pkt_offset) | ||
1891 | skb_pull(skb, pkt_offset); | ||
1892 | |||
1893 | if (!qlcnic_check_loopback_buff(skb->data, adapter->mac_addr)) | ||
1894 | adapter->diag_cnt++; | ||
1895 | else | ||
1896 | dump_skb(skb, adapter); | ||
1897 | |||
1898 | dev_kfree_skb_any(skb); | ||
1899 | adapter->stats.rx_pkts++; | ||
1900 | adapter->stats.rxbytes += length; | ||
1901 | |||
1902 | return; | ||
1903 | } | ||
1904 | |||
1905 | void | ||
1906 | qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring) | ||
1907 | { | ||
1908 | struct qlcnic_adapter *adapter = sds_ring->adapter; | ||
1909 | struct status_desc *desc; | ||
1910 | u64 sts_data0; | ||
1911 | int ring, opcode, desc_cnt; | ||
1912 | |||
1913 | u32 consumer = sds_ring->consumer; | ||
1914 | |||
1915 | desc = &sds_ring->desc_head[consumer]; | ||
1916 | sts_data0 = le64_to_cpu(desc->status_desc_data[0]); | ||
1917 | |||
1918 | if (!(sts_data0 & STATUS_OWNER_HOST)) | ||
1919 | return; | ||
1920 | |||
1921 | desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0); | ||
1922 | opcode = qlcnic_get_sts_opcode(sts_data0); | ||
1923 | switch (opcode) { | ||
1924 | case QLCNIC_RESPONSE_DESC: | ||
1925 | qlcnic_handle_fw_message(desc_cnt, consumer, sds_ring); | ||
1926 | break; | ||
1927 | default: | ||
1928 | ring = qlcnic_get_sts_type(sts_data0); | ||
1929 | qlcnic_process_rcv_diag(adapter, ring, sts_data0); | ||
1930 | break; | ||
1931 | } | ||
1932 | |||
1933 | for (; desc_cnt > 0; desc_cnt--) { | ||
1934 | desc = &sds_ring->desc_head[consumer]; | ||
1935 | desc->status_desc_data[0] = cpu_to_le64(STATUS_OWNER_PHANTOM); | ||
1936 | consumer = get_next_index(consumer, sds_ring->num_desc); | ||
1937 | } | ||
1938 | |||
1939 | sds_ring->consumer = consumer; | ||
1940 | writel(consumer, sds_ring->crb_sts_consumer); | ||
1941 | } | ||
1942 | |||
1943 | void qlcnic_fetch_mac(u32 off1, u32 off2, u8 alt_mac, u8 *mac) | ||
1944 | { | ||
1945 | u32 mac_low, mac_high; | ||
1946 | int i; | ||
1947 | |||
1948 | mac_low = off1; | ||
1949 | mac_high = off2; | ||
1950 | |||
1951 | if (alt_mac) { | ||
1952 | mac_low |= (mac_low >> 16) | (mac_high << 16); | ||
1953 | mac_high >>= 16; | ||
1954 | } | ||
1955 | |||
1956 | for (i = 0; i < 2; i++) | ||
1957 | mac[i] = (u8)(mac_high >> ((1 - i) * 8)); | ||
1958 | for (i = 2; i < 6; i++) | ||
1959 | mac[i] = (u8)(mac_low >> ((5 - i) * 8)); | ||
1960 | } | ||