diff options
Diffstat (limited to 'drivers/net/qlge/qlge_main.c')
-rw-r--r-- | drivers/net/qlge/qlge_main.c | 1189 |
1 files changed, 797 insertions, 392 deletions
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 894a7c84fae..c26ec5d740f 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -73,7 +73,19 @@ static int qlge_irq_type = MSIX_IRQ; module_param(qlge_irq_type, int, MSIX_IRQ); MODULE_PARM_DESC(qlge_irq_type, "0 = MSI-X, 1 = MSI, 2 = Legacy."); -static struct pci_device_id qlge_pci_tbl[] __devinitdata = { +static int qlge_mpi_coredump; +module_param(qlge_mpi_coredump, int, 0); +MODULE_PARM_DESC(qlge_mpi_coredump, + "Option to enable MPI firmware dump. " + "Default is OFF - Do Not allocate memory. "); + +static int qlge_force_coredump; +module_param(qlge_force_coredump, int, 0); +MODULE_PARM_DESC(qlge_force_coredump, + "Option to allow force of firmware core dump. " + "Default is OFF - Do not allow."); + +static DEFINE_PCI_DEVICE_TABLE(qlge_pci_tbl) = { {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QLGE_DEVICE_ID_8012)}, {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QLGE_DEVICE_ID_8000)}, /* required last entry */ @@ -116,7 +128,7 @@ static int ql_sem_trylock(struct ql_adapter *qdev, u32 sem_mask) sem_bits = SEM_SET << SEM_PROC_REG_SHIFT; break; default: - QPRINTK(qdev, PROBE, ALERT, "Bad Semaphore mask!.\n"); + netif_alert(qdev, probe, qdev->ndev, "bad Semaphore mask!.\n"); return -EINVAL; } @@ -156,17 +168,17 @@ int ql_wait_reg_rdy(struct ql_adapter *qdev, u32 reg, u32 bit, u32 err_bit) /* check for errors */ if (temp & err_bit) { - QPRINTK(qdev, PROBE, ALERT, - "register 0x%.08x access error, value = 0x%.08x!.\n", - reg, temp); + netif_alert(qdev, probe, qdev->ndev, + "register 0x%.08x access error, value = 0x%.08x!.\n", + reg, temp); return -EIO; } else if (temp & bit) return 0; udelay(UDELAY_DELAY); count--; } - QPRINTK(qdev, PROBE, ALERT, - "Timed out waiting for reg %x to come ready.\n", reg); + netif_alert(qdev, probe, qdev->ndev, + "Timed out waiting for reg %x to come ready.\n", reg); return -ETIMEDOUT; } @@ -209,7 +221,7 @@ int ql_write_cfg(struct ql_adapter *qdev, void *ptr, int size, u32 bit, map = pci_map_single(qdev->pdev, ptr, size, direction); if (pci_dma_mapping_error(qdev->pdev, map)) { - QPRINTK(qdev, IFUP, ERR, "Couldn't map DMA area.\n"); + netif_err(qdev, ifup, qdev->ndev, "Couldn't map DMA area.\n"); return -ENOMEM; } @@ -219,8 +231,8 @@ int ql_write_cfg(struct ql_adapter *qdev, void *ptr, int size, u32 bit, status = ql_wait_cfg(qdev, bit); if (status) { - QPRINTK(qdev, IFUP, ERR, - "Timed out waiting for CFG to come ready.\n"); + netif_err(qdev, ifup, qdev->ndev, + "Timed out waiting for CFG to come ready.\n"); goto exit; } @@ -301,8 +313,8 @@ int ql_get_mac_addr_reg(struct ql_adapter *qdev, u32 type, u16 index, case MAC_ADDR_TYPE_VLAN: case MAC_ADDR_TYPE_MULTI_FLTR: default: - QPRINTK(qdev, IFUP, CRIT, - "Address type %d not yet supported.\n", type); + netif_crit(qdev, ifup, qdev->ndev, + "Address type %d not yet supported.\n", type); status = -EPERM; } exit: @@ -359,12 +371,11 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type, (addr[2] << 24) | (addr[3] << 16) | (addr[4] << 8) | (addr[5]); - QPRINTK(qdev, IFUP, DEBUG, - "Adding %s address %pM" - " at index %d in the CAM.\n", - ((type == - MAC_ADDR_TYPE_MULTI_MAC) ? "MULTICAST" : - "UNICAST"), addr, index); + netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev, + "Adding %s address %pM at index %d in the CAM.\n", + type == MAC_ADDR_TYPE_MULTI_MAC ? + "MULTICAST" : "UNICAST", + addr, index); status = ql_wait_reg_rdy(qdev, @@ -414,9 +425,11 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type, * addressing. It's either MAC_ADDR_E on or off. * That's bit-27 we're talking about. */ - QPRINTK(qdev, IFUP, INFO, "%s VLAN ID %d %s the CAM.\n", - (enable_bit ? "Adding" : "Removing"), - index, (enable_bit ? "to" : "from")); + netif_info(qdev, ifup, qdev->ndev, + "%s VLAN ID %d %s the CAM.\n", + enable_bit ? "Adding" : "Removing", + index, + enable_bit ? "to" : "from"); status = ql_wait_reg_rdy(qdev, @@ -431,8 +444,8 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type, } case MAC_ADDR_TYPE_MULTI_FLTR: default: - QPRINTK(qdev, IFUP, CRIT, - "Address type %d not yet supported.\n", type); + netif_crit(qdev, ifup, qdev->ndev, + "Address type %d not yet supported.\n", type); status = -EPERM; } exit: @@ -450,17 +463,14 @@ static int ql_set_mac_addr(struct ql_adapter *qdev, int set) char *addr; if (set) { - addr = &qdev->ndev->dev_addr[0]; - QPRINTK(qdev, IFUP, DEBUG, - "Set Mac addr %02x:%02x:%02x:%02x:%02x:%02x\n", - addr[0], addr[1], addr[2], addr[3], - addr[4], addr[5]); + addr = &qdev->current_mac_addr[0]; + netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev, + "Set Mac addr %pM\n", addr); } else { memset(zero_mac_addr, 0, ETH_ALEN); addr = &zero_mac_addr[0]; - QPRINTK(qdev, IFUP, DEBUG, - "Clearing MAC address on %s\n", - qdev->ndev->name); + netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev, + "Clearing MAC address\n"); } status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK); if (status) @@ -469,23 +479,21 @@ static int ql_set_mac_addr(struct ql_adapter *qdev, int set) MAC_ADDR_TYPE_CAM_MAC, qdev->func * MAX_CQ); ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK); if (status) - QPRINTK(qdev, IFUP, ERR, "Failed to init mac " - "address.\n"); + netif_err(qdev, ifup, qdev->ndev, + "Failed to init mac address.\n"); return status; } void ql_link_on(struct ql_adapter *qdev) { - QPRINTK(qdev, LINK, ERR, "%s: Link is up.\n", - qdev->ndev->name); + netif_err(qdev, link, qdev->ndev, "Link is up.\n"); netif_carrier_on(qdev->ndev); ql_set_mac_addr(qdev, 1); } void ql_link_off(struct ql_adapter *qdev) { - QPRINTK(qdev, LINK, ERR, "%s: Link is down.\n", - qdev->ndev->name); + netif_err(qdev, link, qdev->ndev, "Link is down.\n"); netif_carrier_off(qdev->ndev); ql_set_mac_addr(qdev, 0); } @@ -522,27 +530,27 @@ static int ql_set_routing_reg(struct ql_adapter *qdev, u32 index, u32 mask, int status = -EINVAL; /* Return error if no mask match. */ u32 value = 0; - QPRINTK(qdev, IFUP, DEBUG, - "%s %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s mask %s the routing reg.\n", - (enable ? "Adding" : "Removing"), - ((index == RT_IDX_ALL_ERR_SLOT) ? "MAC ERROR/ALL ERROR" : ""), - ((index == RT_IDX_IP_CSUM_ERR_SLOT) ? "IP CSUM ERROR" : ""), - ((index == - RT_IDX_TCP_UDP_CSUM_ERR_SLOT) ? "TCP/UDP CSUM ERROR" : ""), - ((index == RT_IDX_BCAST_SLOT) ? "BROADCAST" : ""), - ((index == RT_IDX_MCAST_MATCH_SLOT) ? "MULTICAST MATCH" : ""), - ((index == RT_IDX_ALLMULTI_SLOT) ? "ALL MULTICAST MATCH" : ""), - ((index == RT_IDX_UNUSED6_SLOT) ? "UNUSED6" : ""), - ((index == RT_IDX_UNUSED7_SLOT) ? "UNUSED7" : ""), - ((index == RT_IDX_RSS_MATCH_SLOT) ? "RSS ALL/IPV4 MATCH" : ""), - ((index == RT_IDX_RSS_IPV6_SLOT) ? "RSS IPV6" : ""), - ((index == RT_IDX_RSS_TCP4_SLOT) ? "RSS TCP4" : ""), - ((index == RT_IDX_RSS_TCP6_SLOT) ? "RSS TCP6" : ""), - ((index == RT_IDX_CAM_HIT_SLOT) ? "CAM HIT" : ""), - ((index == RT_IDX_UNUSED013) ? "UNUSED13" : ""), - ((index == RT_IDX_UNUSED014) ? "UNUSED14" : ""), - ((index == RT_IDX_PROMISCUOUS_SLOT) ? "PROMISCUOUS" : ""), - (enable ? "to" : "from")); + netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev, + "%s %s mask %s the routing reg.\n", + enable ? "Adding" : "Removing", + index == RT_IDX_ALL_ERR_SLOT ? "MAC ERROR/ALL ERROR" : + index == RT_IDX_IP_CSUM_ERR_SLOT ? "IP CSUM ERROR" : + index == RT_IDX_TCP_UDP_CSUM_ERR_SLOT ? "TCP/UDP CSUM ERROR" : + index == RT_IDX_BCAST_SLOT ? "BROADCAST" : + index == RT_IDX_MCAST_MATCH_SLOT ? "MULTICAST MATCH" : + index == RT_IDX_ALLMULTI_SLOT ? "ALL MULTICAST MATCH" : + index == RT_IDX_UNUSED6_SLOT ? "UNUSED6" : + index == RT_IDX_UNUSED7_SLOT ? "UNUSED7" : + index == RT_IDX_RSS_MATCH_SLOT ? "RSS ALL/IPV4 MATCH" : + index == RT_IDX_RSS_IPV6_SLOT ? "RSS IPV6" : + index == RT_IDX_RSS_TCP4_SLOT ? "RSS TCP4" : + index == RT_IDX_RSS_TCP6_SLOT ? "RSS TCP6" : + index == RT_IDX_CAM_HIT_SLOT ? "CAM HIT" : + index == RT_IDX_UNUSED013 ? "UNUSED13" : + index == RT_IDX_UNUSED014 ? "UNUSED14" : + index == RT_IDX_PROMISCUOUS_SLOT ? "PROMISCUOUS" : + "(Bad index != RT_IDX)", + enable ? "to" : "from"); switch (mask) { case RT_IDX_CAM_HIT: @@ -602,8 +610,8 @@ static int ql_set_routing_reg(struct ql_adapter *qdev, u32 index, u32 mask, break; } default: - QPRINTK(qdev, IFUP, ERR, "Mask type %d not yet supported.\n", - mask); + netif_err(qdev, ifup, qdev->ndev, + "Mask type %d not yet supported.\n", mask); status = -EPERM; goto exit; } @@ -709,7 +717,7 @@ static int ql_validate_flash(struct ql_adapter *qdev, u32 size, const char *str) status = strncmp((char *)&qdev->flash, str, 4); if (status) { - QPRINTK(qdev, IFUP, ERR, "Invalid flash signature.\n"); + netif_err(qdev, ifup, qdev->ndev, "Invalid flash signature.\n"); return status; } @@ -717,8 +725,8 @@ static int ql_validate_flash(struct ql_adapter *qdev, u32 size, const char *str) csum += le16_to_cpu(*flash++); if (csum) - QPRINTK(qdev, IFUP, ERR, - "Invalid flash checksum, csum = 0x%.04x.\n", csum); + netif_err(qdev, ifup, qdev->ndev, + "Invalid flash checksum, csum = 0x%.04x.\n", csum); return csum; } @@ -770,7 +778,8 @@ static int ql_get_8000_flash_params(struct ql_adapter *qdev) for (i = 0; i < size; i++, p++) { status = ql_read_flash_word(qdev, i+offset, p); if (status) { - QPRINTK(qdev, IFUP, ERR, "Error reading flash.\n"); + netif_err(qdev, ifup, qdev->ndev, + "Error reading flash.\n"); goto exit; } } @@ -779,7 +788,7 @@ static int ql_get_8000_flash_params(struct ql_adapter *qdev) sizeof(struct flash_params_8000) / sizeof(u16), "8000"); if (status) { - QPRINTK(qdev, IFUP, ERR, "Invalid flash.\n"); + netif_err(qdev, ifup, qdev->ndev, "Invalid flash.\n"); status = -EINVAL; goto exit; } @@ -797,7 +806,7 @@ static int ql_get_8000_flash_params(struct ql_adapter *qdev) qdev->ndev->addr_len); if (!is_valid_ether_addr(mac_addr)) { - QPRINTK(qdev, IFUP, ERR, "Invalid MAC address.\n"); + netif_err(qdev, ifup, qdev->ndev, "Invalid MAC address.\n"); status = -EINVAL; goto exit; } @@ -831,7 +840,8 @@ static int ql_get_8012_flash_params(struct ql_adapter *qdev) for (i = 0; i < size; i++, p++) { status = ql_read_flash_word(qdev, i+offset, p); if (status) { - QPRINTK(qdev, IFUP, ERR, "Error reading flash.\n"); + netif_err(qdev, ifup, qdev->ndev, + "Error reading flash.\n"); goto exit; } @@ -841,7 +851,7 @@ static int ql_get_8012_flash_params(struct ql_adapter *qdev) sizeof(struct flash_params_8012) / sizeof(u16), "8012"); if (status) { - QPRINTK(qdev, IFUP, ERR, "Invalid flash.\n"); + netif_err(qdev, ifup, qdev->ndev, "Invalid flash.\n"); status = -EINVAL; goto exit; } @@ -959,17 +969,17 @@ static int ql_8012_port_initialize(struct ql_adapter *qdev) /* Another function has the semaphore, so * wait for the port init bit to come ready. */ - QPRINTK(qdev, LINK, INFO, - "Another function has the semaphore, so wait for the port init bit to come ready.\n"); + netif_info(qdev, link, qdev->ndev, + "Another function has the semaphore, so wait for the port init bit to come ready.\n"); status = ql_wait_reg_rdy(qdev, STS, qdev->port_init, 0); if (status) { - QPRINTK(qdev, LINK, CRIT, - "Port initialize timed out.\n"); + netif_crit(qdev, link, qdev->ndev, + "Port initialize timed out.\n"); } return status; } - QPRINTK(qdev, LINK, INFO, "Got xgmac semaphore!.\n"); + netif_info(qdev, link, qdev->ndev, "Got xgmac semaphore!.\n"); /* Set the core reset. */ status = ql_read_xgmac_reg(qdev, GLOBAL_CFG, &data); if (status) @@ -1099,8 +1109,8 @@ static int ql_get_next_chunk(struct ql_adapter *qdev, struct rx_ring *rx_ring, GFP_ATOMIC, qdev->lbq_buf_order); if (unlikely(!rx_ring->pg_chunk.page)) { - QPRINTK(qdev, DRV, ERR, - "page allocation failed.\n"); + netif_err(qdev, drv, qdev->ndev, + "page allocation failed.\n"); return -ENOMEM; } rx_ring->pg_chunk.offset = 0; @@ -1110,8 +1120,8 @@ static int ql_get_next_chunk(struct ql_adapter *qdev, struct rx_ring *rx_ring, if (pci_dma_mapping_error(qdev->pdev, map)) { __free_pages(rx_ring->pg_chunk.page, qdev->lbq_buf_order); - QPRINTK(qdev, DRV, ERR, - "PCI mapping failed.\n"); + netif_err(qdev, drv, qdev->ndev, + "PCI mapping failed.\n"); return -ENOMEM; } rx_ring->pg_chunk.map = map; @@ -1148,15 +1158,15 @@ static void ql_update_lbq(struct ql_adapter *qdev, struct rx_ring *rx_ring) while (rx_ring->lbq_free_cnt > 32) { for (i = 0; i < 16; i++) { - QPRINTK(qdev, RX_STATUS, DEBUG, - "lbq: try cleaning clean_idx = %d.\n", - clean_idx); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "lbq: try cleaning clean_idx = %d.\n", + clean_idx); lbq_desc = &rx_ring->lbq[clean_idx]; if (ql_get_next_chunk(qdev, rx_ring, lbq_desc)) { - QPRINTK(qdev, IFUP, ERR, - "Could not get a page chunk.\n"); - return; - } + netif_err(qdev, ifup, qdev->ndev, + "Could not get a page chunk.\n"); + return; + } map = lbq_desc->p.pg_chunk.map + lbq_desc->p.pg_chunk.offset; @@ -1181,9 +1191,9 @@ static void ql_update_lbq(struct ql_adapter *qdev, struct rx_ring *rx_ring) } if (start_idx != clean_idx) { - QPRINTK(qdev, RX_STATUS, DEBUG, - "lbq: updating prod idx = %d.\n", - rx_ring->lbq_prod_idx); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "lbq: updating prod idx = %d.\n", + rx_ring->lbq_prod_idx); ql_write_db_reg(rx_ring->lbq_prod_idx, rx_ring->lbq_prod_idx_db_reg); } @@ -1201,19 +1211,20 @@ static void ql_update_sbq(struct ql_adapter *qdev, struct rx_ring *rx_ring) while (rx_ring->sbq_free_cnt > 16) { for (i = 0; i < 16; i++) { sbq_desc = &rx_ring->sbq[clean_idx]; - QPRINTK(qdev, RX_STATUS, DEBUG, - "sbq: try cleaning clean_idx = %d.\n", - clean_idx); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "sbq: try cleaning clean_idx = %d.\n", + clean_idx); if (sbq_desc->p.skb == NULL) { - QPRINTK(qdev, RX_STATUS, DEBUG, - "sbq: getting new skb for index %d.\n", - sbq_desc->index); + netif_printk(qdev, rx_status, KERN_DEBUG, + qdev->ndev, + "sbq: getting new skb for index %d.\n", + sbq_desc->index); sbq_desc->p.skb = netdev_alloc_skb(qdev->ndev, SMALL_BUFFER_SIZE); if (sbq_desc->p.skb == NULL) { - QPRINTK(qdev, PROBE, ERR, - "Couldn't get an skb.\n"); + netif_err(qdev, probe, qdev->ndev, + "Couldn't get an skb.\n"); rx_ring->sbq_clean_idx = clean_idx; return; } @@ -1223,7 +1234,8 @@ static void ql_update_sbq(struct ql_adapter *qdev, struct rx_ring *rx_ring) rx_ring->sbq_buf_size, PCI_DMA_FROMDEVICE); if (pci_dma_mapping_error(qdev->pdev, map)) { - QPRINTK(qdev, IFUP, ERR, "PCI mapping failed.\n"); + netif_err(qdev, ifup, qdev->ndev, + "PCI mapping failed.\n"); rx_ring->sbq_clean_idx = clean_idx; dev_kfree_skb_any(sbq_desc->p.skb); sbq_desc->p.skb = NULL; @@ -1247,9 +1259,9 @@ static void ql_update_sbq(struct ql_adapter *qdev, struct rx_ring *rx_ring) } if (start_idx != clean_idx) { - QPRINTK(qdev, RX_STATUS, DEBUG, - "sbq: updating prod idx = %d.\n", - rx_ring->sbq_prod_idx); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "sbq: updating prod idx = %d.\n", + rx_ring->sbq_prod_idx); ql_write_db_reg(rx_ring->sbq_prod_idx, rx_ring->sbq_prod_idx_db_reg); } @@ -1281,8 +1293,9 @@ static void ql_unmap_send(struct ql_adapter *qdev, * then its an OAL. */ if (i == 7) { - QPRINTK(qdev, TX_DONE, DEBUG, - "unmapping OAL area.\n"); + netif_printk(qdev, tx_done, KERN_DEBUG, + qdev->ndev, + "unmapping OAL area.\n"); } pci_unmap_single(qdev->pdev, pci_unmap_addr(&tx_ring_desc->map[i], @@ -1291,8 +1304,8 @@ static void ql_unmap_send(struct ql_adapter *qdev, maplen), PCI_DMA_TODEVICE); } else { - QPRINTK(qdev, TX_DONE, DEBUG, "unmapping frag %d.\n", - i); + netif_printk(qdev, tx_done, KERN_DEBUG, qdev->ndev, + "unmapping frag %d.\n", i); pci_unmap_page(qdev->pdev, pci_unmap_addr(&tx_ring_desc->map[i], mapaddr), @@ -1317,7 +1330,8 @@ static int ql_map_send(struct ql_adapter *qdev, int frag_cnt = skb_shinfo(skb)->nr_frags; if (frag_cnt) { - QPRINTK(qdev, TX_QUEUED, DEBUG, "frag_cnt = %d.\n", frag_cnt); + netif_printk(qdev, tx_queued, KERN_DEBUG, qdev->ndev, + "frag_cnt = %d.\n", frag_cnt); } /* * Map the skb buffer first. @@ -1326,8 +1340,8 @@ static int ql_map_send(struct ql_adapter *qdev, err = pci_dma_mapping_error(qdev->pdev, map); if (err) { - QPRINTK(qdev, TX_QUEUED, ERR, - "PCI mapping failed with error: %d\n", err); + netif_err(qdev, tx_queued, qdev->ndev, + "PCI mapping failed with error: %d\n", err); return NETDEV_TX_BUSY; } @@ -1373,9 +1387,9 @@ static int ql_map_send(struct ql_adapter *qdev, PCI_DMA_TODEVICE); err = pci_dma_mapping_error(qdev->pdev, map); if (err) { - QPRINTK(qdev, TX_QUEUED, ERR, - "PCI mapping outbound address list with error: %d\n", - err); + netif_err(qdev, tx_queued, qdev->ndev, + "PCI mapping outbound address list with error: %d\n", + err); goto map_error; } @@ -1403,9 +1417,9 @@ static int ql_map_send(struct ql_adapter *qdev, err = pci_dma_mapping_error(qdev->pdev, map); if (err) { - QPRINTK(qdev, TX_QUEUED, ERR, - "PCI mapping frags failed with error: %d.\n", - err); + netif_err(qdev, tx_queued, qdev->ndev, + "PCI mapping frags failed with error: %d.\n", + err); goto map_error; } @@ -1433,6 +1447,260 @@ map_error: return NETDEV_TX_BUSY; } +/* Process an inbound completion from an rx ring. */ +static void ql_process_mac_rx_gro_page(struct ql_adapter *qdev, + struct rx_ring *rx_ring, + struct ib_mac_iocb_rsp *ib_mac_rsp, + u32 length, + u16 vlan_id) +{ + struct sk_buff *skb; + struct bq_desc *lbq_desc = ql_get_curr_lchunk(qdev, rx_ring); + struct skb_frag_struct *rx_frag; + int nr_frags; + struct napi_struct *napi = &rx_ring->napi; + + napi->dev = qdev->ndev; + + skb = napi_get_frags(napi); + if (!skb) { + netif_err(qdev, drv, qdev->ndev, + "Couldn't get an skb, exiting.\n"); + rx_ring->rx_dropped++; + put_page(lbq_desc->p.pg_chunk.page); + return; + } + prefetch(lbq_desc->p.pg_chunk.va); + rx_frag = skb_shinfo(skb)->frags; + nr_frags = skb_shinfo(skb)->nr_frags; + rx_frag += nr_frags; + rx_frag->page = lbq_desc->p.pg_chunk.page; + rx_frag->page_offset = lbq_desc->p.pg_chunk.offset; + rx_frag->size = length; + + skb->len += length; + skb->data_len += length; + skb->truesize += length; + skb_shinfo(skb)->nr_frags++; + + rx_ring->rx_packets++; + rx_ring->rx_bytes += length; + skb->ip_summed = CHECKSUM_UNNECESSARY; + skb_record_rx_queue(skb, rx_ring->cq_id); + if (qdev->vlgrp && (vlan_id != 0xffff)) + vlan_gro_frags(&rx_ring->napi, qdev->vlgrp, vlan_id); + else + napi_gro_frags(napi); +} + +/* Process an inbound completion from an rx ring. */ +static void ql_process_mac_rx_page(struct ql_adapter *qdev, + struct rx_ring *rx_ring, + struct ib_mac_iocb_rsp *ib_mac_rsp, + u32 length, + u16 vlan_id) +{ + struct net_device *ndev = qdev->ndev; + struct sk_buff *skb = NULL; + void *addr; + struct bq_desc *lbq_desc = ql_get_curr_lchunk(qdev, rx_ring); + struct napi_struct *napi = &rx_ring->napi; + + skb = netdev_alloc_skb(ndev, length); + if (!skb) { + netif_err(qdev, drv, qdev->ndev, + "Couldn't get an skb, need to unwind!.\n"); + rx_ring->rx_dropped++; + put_page(lbq_desc->p.pg_chunk.page); + return; + } + + addr = lbq_desc->p.pg_chunk.va; + prefetch(addr); + + + /* Frame error, so drop the packet. */ + if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) { + netif_err(qdev, drv, qdev->ndev, + "Receive error, flags2 = 0x%x\n", ib_mac_rsp->flags2); + rx_ring->rx_errors++; + goto err_out; + } + + /* The max framesize filter on this chip is set higher than + * MTU since FCoE uses 2k frames. + */ + if (skb->len > ndev->mtu + ETH_HLEN) { + netif_err(qdev, drv, qdev->ndev, + "Segment too small, dropping.\n"); + rx_ring->rx_dropped++; + goto err_out; + } + memcpy(skb_put(skb, ETH_HLEN), addr, ETH_HLEN); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "%d bytes of headers and data in large. Chain page to new skb and pull tail.\n", + length); + skb_fill_page_desc(skb, 0, lbq_desc->p.pg_chunk.page, + lbq_desc->p.pg_chunk.offset+ETH_HLEN, + length-ETH_HLEN); + skb->len += length-ETH_HLEN; + skb->data_len += length-ETH_HLEN; + skb->truesize += length-ETH_HLEN; + + rx_ring->rx_packets++; + rx_ring->rx_bytes += skb->len; + skb->protocol = eth_type_trans(skb, ndev); + skb->ip_summed = CHECKSUM_NONE; + + if (qdev->rx_csum && + !(ib_mac_rsp->flags1 & IB_MAC_CSUM_ERR_MASK)) { + /* TCP frame. */ + if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_T) { + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "TCP checksum done!\n"); + skb->ip_summed = CHECKSUM_UNNECESSARY; + } else if ((ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_U) && + (ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_V4)) { + /* Unfragmented ipv4 UDP frame. */ + struct iphdr *iph = (struct iphdr *) skb->data; + if (!(iph->frag_off & + cpu_to_be16(IP_MF|IP_OFFSET))) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + netif_printk(qdev, rx_status, KERN_DEBUG, + qdev->ndev, + "TCP checksum done!\n"); + } + } + } + + skb_record_rx_queue(skb, rx_ring->cq_id); + if (skb->ip_summed == CHECKSUM_UNNECESSARY) { + if (qdev->vlgrp && (vlan_id != 0xffff)) + vlan_gro_receive(napi, qdev->vlgrp, vlan_id, skb); + else + napi_gro_receive(napi, skb); + } else { + if (qdev->vlgrp && (vlan_id != 0xffff)) + vlan_hwaccel_receive_skb(skb, qdev->vlgrp, vlan_id); + else + netif_receive_skb(skb); + } + return; +err_out: + dev_kfree_skb_any(skb); + put_page(lbq_desc->p.pg_chunk.page); +} + +/* Process an inbound completion from an rx ring. */ +static void ql_process_mac_rx_skb(struct ql_adapter *qdev, + struct rx_ring *rx_ring, + struct ib_mac_iocb_rsp *ib_mac_rsp, + u32 length, + u16 vlan_id) +{ + struct net_device *ndev = qdev->ndev; + struct sk_buff *skb = NULL; + struct sk_buff *new_skb = NULL; + struct bq_desc *sbq_desc = ql_get_curr_sbuf(rx_ring); + + skb = sbq_desc->p.skb; + /* Allocate new_skb and copy */ + new_skb = netdev_alloc_skb(qdev->ndev, length + NET_IP_ALIGN); + if (new_skb == NULL) { + netif_err(qdev, probe, qdev->ndev, + "No skb available, drop the packet.\n"); + rx_ring->rx_dropped++; + return; + } + skb_reserve(new_skb, NET_IP_ALIGN); + memcpy(skb_put(new_skb, length), skb->data, length); + skb = new_skb; + + /* Frame error, so drop the packet. */ + if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) { + netif_err(qdev, drv, qdev->ndev, + "Receive error, flags2 = 0x%x\n", ib_mac_rsp->flags2); + dev_kfree_skb_any(skb); + rx_ring->rx_errors++; + return; + } + + /* loopback self test for ethtool */ + if (test_bit(QL_SELFTEST, &qdev->flags)) { + ql_check_lb_frame(qdev, skb); + dev_kfree_skb_any(skb); + return; + } + + /* The max framesize filter on this chip is set higher than + * MTU since FCoE uses 2k frames. + */ + if (skb->len > ndev->mtu + ETH_HLEN) { + dev_kfree_skb_any(skb); + rx_ring->rx_dropped++; + return; + } + + prefetch(skb->data); + skb->dev = ndev; + if (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) { + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "%s Multicast.\n", + (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) == + IB_MAC_IOCB_RSP_M_HASH ? "Hash" : + (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) == + IB_MAC_IOCB_RSP_M_REG ? "Registered" : + (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) == + IB_MAC_IOCB_RSP_M_PROM ? "Promiscuous" : ""); + } + if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_P) + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "Promiscuous Packet.\n"); + + rx_ring->rx_packets++; + rx_ring->rx_bytes += skb->len; + skb->protocol = eth_type_trans(skb, ndev); + skb->ip_summed = CHECKSUM_NONE; + + /* If rx checksum is on, and there are no + * csum or frame errors. + */ + if (qdev->rx_csum && + !(ib_mac_rsp->flags1 & IB_MAC_CSUM_ERR_MASK)) { + /* TCP frame. */ + if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_T) { + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "TCP checksum done!\n"); + skb->ip_summed = CHECKSUM_UNNECESSARY; + } else if ((ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_U) && + (ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_V4)) { + /* Unfragmented ipv4 UDP frame. */ + struct iphdr *iph = (struct iphdr *) skb->data; + if (!(iph->frag_off & + cpu_to_be16(IP_MF|IP_OFFSET))) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + netif_printk(qdev, rx_status, KERN_DEBUG, + qdev->ndev, + "TCP checksum done!\n"); + } + } + } + + skb_record_rx_queue(skb, rx_ring->cq_id); + if (skb->ip_summed == CHECKSUM_UNNECESSARY) { + if (qdev->vlgrp && (vlan_id != 0xffff)) + vlan_gro_receive(&rx_ring->napi, qdev->vlgrp, + vlan_id, skb); + else + napi_gro_receive(&rx_ring->napi, skb); + } else { + if (qdev->vlgrp && (vlan_id != 0xffff)) + vlan_hwaccel_receive_skb(skb, qdev->vlgrp, vlan_id); + else + netif_receive_skb(skb); + } +} + static void ql_realign_skb(struct sk_buff *skb, int len) { void *temp_addr = skb->data; @@ -1467,7 +1735,8 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev, */ if (ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HV && ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HS) { - QPRINTK(qdev, RX_STATUS, DEBUG, "Header of %d bytes in small buffer.\n", hdr_len); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "Header of %d bytes in small buffer.\n", hdr_len); /* * Headers fit nicely into a small buffer. */ @@ -1486,15 +1755,16 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev, * Handle the data buffer(s). */ if (unlikely(!length)) { /* Is there data too? */ - QPRINTK(qdev, RX_STATUS, DEBUG, - "No Data buffer in this packet.\n"); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "No Data buffer in this packet.\n"); return skb; } if (ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_DS) { if (ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HS) { - QPRINTK(qdev, RX_STATUS, DEBUG, - "Headers in small, data of %d bytes in small, combine them.\n", length); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "Headers in small, data of %d bytes in small, combine them.\n", + length); /* * Data is less than small buffer size so it's * stuffed in a small buffer. @@ -1520,8 +1790,9 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev, maplen), PCI_DMA_FROMDEVICE); } else { - QPRINTK(qdev, RX_STATUS, DEBUG, - "%d bytes in a single small buffer.\n", length); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "%d bytes in a single small buffer.\n", + length); sbq_desc = ql_get_curr_sbuf(rx_ring); skb = sbq_desc->p.skb; ql_realign_skb(skb, length); @@ -1536,18 +1807,18 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev, } } else if (ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_DL) { if (ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HS) { - QPRINTK(qdev, RX_STATUS, DEBUG, - "Header in small, %d bytes in large. Chain large to small!\n", length); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "Header in small, %d bytes in large. Chain large to small!\n", + length); /* * The data is in a single large buffer. We * chain it to the header buffer's skb and let * it rip. */ lbq_desc = ql_get_curr_lchunk(qdev, rx_ring); - QPRINTK(qdev, RX_STATUS, DEBUG, - "Chaining page at offset = %d," - "for %d bytes to skb.\n", - lbq_desc->p.pg_chunk.offset, length); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "Chaining page at offset = %d, for %d bytes to skb.\n", + lbq_desc->p.pg_chunk.offset, length); skb_fill_page_desc(skb, 0, lbq_desc->p.pg_chunk.page, lbq_desc->p.pg_chunk.offset, length); @@ -1563,8 +1834,8 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev, lbq_desc = ql_get_curr_lchunk(qdev, rx_ring); skb = netdev_alloc_skb(qdev->ndev, length); if (skb == NULL) { - QPRINTK(qdev, PROBE, DEBUG, - "No skb available, drop the packet.\n"); + netif_printk(qdev, probe, KERN_DEBUG, qdev->ndev, + "No skb available, drop the packet.\n"); return NULL; } pci_unmap_page(qdev->pdev, @@ -1573,8 +1844,9 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev, pci_unmap_len(lbq_desc, maplen), PCI_DMA_FROMDEVICE); skb_reserve(skb, NET_IP_ALIGN); - QPRINTK(qdev, RX_STATUS, DEBUG, - "%d bytes of headers and data in large. Chain page to new skb and pull tail.\n", length); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "%d bytes of headers and data in large. Chain page to new skb and pull tail.\n", + length); skb_fill_page_desc(skb, 0, lbq_desc->p.pg_chunk.page, lbq_desc->p.pg_chunk.offset, @@ -1615,8 +1887,9 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev, * a local buffer and use it to find the * pages to chain. */ - QPRINTK(qdev, RX_STATUS, DEBUG, - "%d bytes of headers & data in chain of large.\n", length); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "%d bytes of headers & data in chain of large.\n", + length); skb = sbq_desc->p.skb; sbq_desc->p.skb = NULL; skb_reserve(skb, NET_IP_ALIGN); @@ -1626,9 +1899,9 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev, size = (length < rx_ring->lbq_buf_size) ? length : rx_ring->lbq_buf_size; - QPRINTK(qdev, RX_STATUS, DEBUG, - "Adding page %d to skb for %d bytes.\n", - i, size); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "Adding page %d to skb for %d bytes.\n", + i, size); skb_fill_page_desc(skb, i, lbq_desc->p.pg_chunk.page, lbq_desc->p.pg_chunk.offset, @@ -1646,29 +1919,28 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev, } /* Process an inbound completion from an rx ring. */ -static void ql_process_mac_rx_intr(struct ql_adapter *qdev, +static void ql_process_mac_split_rx_intr(struct ql_adapter *qdev, struct rx_ring *rx_ring, - struct ib_mac_iocb_rsp *ib_mac_rsp) + struct ib_mac_iocb_rsp *ib_mac_rsp, + u16 vlan_id) { struct net_device *ndev = qdev->ndev; struct sk_buff *skb = NULL; - u16 vlan_id = (le16_to_cpu(ib_mac_rsp->vlan_id) & - IB_MAC_IOCB_RSP_VLAN_MASK) QL_DUMP_IB_MAC_RSP(ib_mac_rsp); skb = ql_build_rx_skb(qdev, rx_ring, ib_mac_rsp); if (unlikely(!skb)) { - QPRINTK(qdev, RX_STATUS, DEBUG, - "No skb available, drop packet.\n"); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "No skb available, drop packet.\n"); rx_ring->rx_dropped++; return; } /* Frame error, so drop the packet. */ if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) { - QPRINTK(qdev, DRV, ERR, "Receive error, flags2 = 0x%x\n", - ib_mac_rsp->flags2); + netif_err(qdev, drv, qdev->ndev, + "Receive error, flags2 = 0x%x\n", ib_mac_rsp->flags2); dev_kfree_skb_any(skb); rx_ring->rx_errors++; return; @@ -1693,17 +1965,18 @@ static void ql_process_mac_rx_intr(struct ql_adapter *qdev, prefetch(skb->data); skb->dev = ndev; if (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) { - QPRINTK(qdev, RX_STATUS, DEBUG, "%s%s%s Multicast.\n", - (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) == - IB_MAC_IOCB_RSP_M_HASH ? "Hash" : "", - (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) == - IB_MAC_IOCB_RSP_M_REG ? "Registered" : "", - (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) == - IB_MAC_IOCB_RSP_M_PROM ? "Promiscuous" : ""); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, "%s Multicast.\n", + (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) == + IB_MAC_IOCB_RSP_M_HASH ? "Hash" : + (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) == + IB_MAC_IOCB_RSP_M_REG ? "Registered" : + (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) == + IB_MAC_IOCB_RSP_M_PROM ? "Promiscuous" : ""); rx_ring->rx_multicast++; } if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_P) { - QPRINTK(qdev, RX_STATUS, DEBUG, "Promiscuous Packet.\n"); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "Promiscuous Packet.\n"); } skb->protocol = eth_type_trans(skb, ndev); @@ -1716,8 +1989,8 @@ static void ql_process_mac_rx_intr(struct ql_adapter *qdev, !(ib_mac_rsp->flags1 & IB_MAC_CSUM_ERR_MASK)) { /* TCP frame. */ if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_T) { - QPRINTK(qdev, RX_STATUS, DEBUG, - "TCP checksum done!\n"); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "TCP checksum done!\n"); skb->ip_summed = CHECKSUM_UNNECESSARY; } else if ((ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_U) && (ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_V4)) { @@ -1726,8 +1999,8 @@ static void ql_process_mac_rx_intr(struct ql_adapter *qdev, if (!(iph->frag_off & cpu_to_be16(IP_MF|IP_OFFSET))) { skb->ip_summed = CHECKSUM_UNNECESSARY; - QPRINTK(qdev, RX_STATUS, DEBUG, - "TCP checksum done!\n"); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "TCP checksum done!\n"); } } } @@ -1753,6 +2026,56 @@ static void ql_process_mac_rx_intr(struct ql_adapter *qdev, } } +/* Process an inbound completion from an rx ring. */ +static unsigned long ql_process_mac_rx_intr(struct ql_adapter *qdev, + struct rx_ring *rx_ring, + struct ib_mac_iocb_rsp *ib_mac_rsp) +{ + u32 length = le32_to_cpu(ib_mac_rsp->data_len); + u16 vlan_id = (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V) ? + ((le16_to_cpu(ib_mac_rsp->vlan_id) & + IB_MAC_IOCB_RSP_VLAN_MASK)) : 0xffff; + + QL_DUMP_IB_MAC_RSP(ib_mac_rsp); + + if (ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HV) { + /* The data and headers are split into + * separate buffers. + */ + ql_process_mac_split_rx_intr(qdev, rx_ring, ib_mac_rsp, + vlan_id); + } else if (ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_DS) { + /* The data fit in a single small buffer. + * Allocate a new skb, copy the data and + * return the buffer to the free pool. + */ + ql_process_mac_rx_skb(qdev, rx_ring, ib_mac_rsp, + length, vlan_id); + } else if ((ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_DL) && + !(ib_mac_rsp->flags1 & IB_MAC_CSUM_ERR_MASK) && + (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_T)) { + /* TCP packet in a page chunk that's been checksummed. + * Tack it on to our GRO skb and let it go. + */ + ql_process_mac_rx_gro_page(qdev, rx_ring, ib_mac_rsp, + length, vlan_id); + } else if (ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_DL) { + /* Non-TCP packet in a page chunk. Allocate an + * skb, tack it on frags, and send it up. + */ + ql_process_mac_rx_page(qdev, rx_ring, ib_mac_rsp, + length, vlan_id); + } else { + /* Non-TCP/UDP large frames that span multiple buffers + * can be processed corrrectly by the split frame logic. |