diff options
Diffstat (limited to 'drivers/net/qla3xxx.c')
-rwxr-xr-x | drivers/net/qla3xxx.c | 486 |
1 files changed, 375 insertions, 111 deletions
diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c index d3f65dab306..d8766c0e825 100755 --- a/drivers/net/qla3xxx.c +++ b/drivers/net/qla3xxx.c @@ -39,7 +39,7 @@ #define DRV_NAME "qla3xxx" #define DRV_STRING "QLogic ISP3XXX Network Driver" -#define DRV_VERSION "v2.03.00-k3" +#define DRV_VERSION "v2.03.00-k4" #define PFX DRV_NAME " " static const char ql3xxx_driver_name[] = DRV_NAME; @@ -72,6 +72,30 @@ static struct pci_device_id ql3xxx_pci_tbl[] __devinitdata = { MODULE_DEVICE_TABLE(pci, ql3xxx_pci_tbl); /* + * These are the known PHY's which are used + */ +typedef enum { + PHY_TYPE_UNKNOWN = 0, + PHY_VITESSE_VSC8211, + PHY_AGERE_ET1011C, + MAX_PHY_DEV_TYPES +} PHY_DEVICE_et; + +typedef struct { + PHY_DEVICE_et phyDevice; + u32 phyIdOUI; + u16 phyIdModel; + char *name; +} PHY_DEVICE_INFO_t; + +static const PHY_DEVICE_INFO_t PHY_DEVICES[] = + {{PHY_TYPE_UNKNOWN, 0x000000, 0x0, "PHY_TYPE_UNKNOWN"}, + {PHY_VITESSE_VSC8211, 0x0003f1, 0xb, "PHY_VITESSE_VSC8211"}, + {PHY_AGERE_ET1011C, 0x00a0bc, 0x1, "PHY_AGERE_ET1011C"}, +}; + + +/* * Caller must take hw_lock. */ static int ql_sem_spinlock(struct ql3_adapter *qdev, @@ -662,7 +686,7 @@ static u8 ql_mii_disable_scan_mode(struct ql3_adapter *qdev) } static int ql_mii_write_reg_ex(struct ql3_adapter *qdev, - u16 regAddr, u16 value, u32 mac_index) + u16 regAddr, u16 value, u32 phyAddr) { struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; @@ -680,7 +704,7 @@ static int ql_mii_write_reg_ex(struct ql3_adapter *qdev, } ql_write_page0_reg(qdev, &port_regs->macMIIMgmtAddrReg, - PHYAddr[mac_index] | regAddr); + phyAddr | regAddr); ql_write_page0_reg(qdev, &port_regs->macMIIMgmtDataReg, value); @@ -701,7 +725,7 @@ static int ql_mii_write_reg_ex(struct ql3_adapter *qdev, } static int ql_mii_read_reg_ex(struct ql3_adapter *qdev, u16 regAddr, - u16 * value, u32 mac_index) + u16 * value, u32 phyAddr) { struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; @@ -720,7 +744,7 @@ static int ql_mii_read_reg_ex(struct ql3_adapter *qdev, u16 regAddr, } ql_write_page0_reg(qdev, &port_regs->macMIIMgmtAddrReg, - PHYAddr[mac_index] | regAddr); + phyAddr | regAddr); ql_write_page0_reg(qdev, &port_regs->macMIIMgmtControlReg, (MAC_MII_CONTROL_RC << 16)); @@ -850,28 +874,31 @@ static void ql_petbi_start_neg(struct ql3_adapter *qdev) } -static void ql_petbi_reset_ex(struct ql3_adapter *qdev, u32 mac_index) +static void ql_petbi_reset_ex(struct ql3_adapter *qdev) { ql_mii_write_reg_ex(qdev, PETBI_CONTROL_REG, PETBI_CTRL_SOFT_RESET, - mac_index); + PHYAddr[qdev->mac_index]); } -static void ql_petbi_start_neg_ex(struct ql3_adapter *qdev, u32 mac_index) +static void ql_petbi_start_neg_ex(struct ql3_adapter *qdev) { u16 reg; /* Enable Auto-negotiation sense */ - ql_mii_read_reg_ex(qdev, PETBI_TBI_CTRL, ®, mac_index); + ql_mii_read_reg_ex(qdev, PETBI_TBI_CTRL, ®, + PHYAddr[qdev->mac_index]); reg |= PETBI_TBI_AUTO_SENSE; - ql_mii_write_reg_ex(qdev, PETBI_TBI_CTRL, reg, mac_index); + ql_mii_write_reg_ex(qdev, PETBI_TBI_CTRL, reg, + PHYAddr[qdev->mac_index]); ql_mii_write_reg_ex(qdev, PETBI_NEG_ADVER, - PETBI_NEG_PAUSE | PETBI_NEG_DUPLEX, mac_index); + PETBI_NEG_PAUSE | PETBI_NEG_DUPLEX, + PHYAddr[qdev->mac_index]); ql_mii_write_reg_ex(qdev, PETBI_CONTROL_REG, PETBI_CTRL_AUTO_NEG | PETBI_CTRL_RESTART_NEG | PETBI_CTRL_FULL_DUPLEX | PETBI_CTRL_SPEED_1000, - mac_index); + PHYAddr[qdev->mac_index]); } static void ql_petbi_init(struct ql3_adapter *qdev) @@ -880,10 +907,10 @@ static void ql_petbi_init(struct ql3_adapter *qdev) ql_petbi_start_neg(qdev); } -static void ql_petbi_init_ex(struct ql3_adapter *qdev, u32 mac_index) +static void ql_petbi_init_ex(struct ql3_adapter *qdev) { - ql_petbi_reset_ex(qdev, mac_index); - ql_petbi_start_neg_ex(qdev, mac_index); + ql_petbi_reset_ex(qdev); + ql_petbi_start_neg_ex(qdev); } static int ql_is_petbi_neg_pause(struct ql3_adapter *qdev) @@ -896,33 +923,128 @@ static int ql_is_petbi_neg_pause(struct ql3_adapter *qdev) return (reg & PETBI_NEG_PAUSE_MASK) == PETBI_NEG_PAUSE; } +static void phyAgereSpecificInit(struct ql3_adapter *qdev, u32 miiAddr) +{ + printk(KERN_INFO "%s: enabling Agere specific PHY\n", qdev->ndev->name); + /* power down device bit 11 = 1 */ + ql_mii_write_reg_ex(qdev, 0x00, 0x1940, miiAddr); + /* enable diagnostic mode bit 2 = 1 */ + ql_mii_write_reg_ex(qdev, 0x12, 0x840e, miiAddr); + /* 1000MB amplitude adjust (see Agere errata) */ + ql_mii_write_reg_ex(qdev, 0x10, 0x8805, miiAddr); + /* 1000MB amplitude adjust (see Agere errata) */ + ql_mii_write_reg_ex(qdev, 0x11, 0xf03e, miiAddr); + /* 100MB amplitude adjust (see Agere errata) */ + ql_mii_write_reg_ex(qdev, 0x10, 0x8806, miiAddr); + /* 100MB amplitude adjust (see Agere errata) */ + ql_mii_write_reg_ex(qdev, 0x11, 0x003e, miiAddr); + /* 10MB amplitude adjust (see Agere errata) */ + ql_mii_write_reg_ex(qdev, 0x10, 0x8807, miiAddr); + /* 10MB amplitude adjust (see Agere errata) */ + ql_mii_write_reg_ex(qdev, 0x11, 0x1f00, miiAddr); + /* point to hidden reg 0x2806 */ + ql_mii_write_reg_ex(qdev, 0x10, 0x2806, miiAddr); + /* Write new PHYAD w/bit 5 set */ + ql_mii_write_reg_ex(qdev, 0x11, 0x0020 | (PHYAddr[qdev->mac_index] >> 8), miiAddr); + /* + * Disable diagnostic mode bit 2 = 0 + * Power up device bit 11 = 0 + * Link up (on) and activity (blink) + */ + ql_mii_write_reg(qdev, 0x12, 0x840a); + ql_mii_write_reg(qdev, 0x00, 0x1140); + ql_mii_write_reg(qdev, 0x1c, 0xfaf0); +} + +static PHY_DEVICE_et getPhyType (struct ql3_adapter *qdev, + u16 phyIdReg0, u16 phyIdReg1) +{ + PHY_DEVICE_et result = PHY_TYPE_UNKNOWN; + u32 oui; + u16 model; + int i; + + if (phyIdReg0 == 0xffff) { + return result; + } + + if (phyIdReg1 == 0xffff) { + return result; + } + + /* oui is split between two registers */ + oui = (phyIdReg0 << 6) | ((phyIdReg1 & PHY_OUI_1_MASK) >> 10); + + model = (phyIdReg1 & PHY_MODEL_MASK) >> 4; + + /* Scan table for this PHY */ + for(i = 0; i < MAX_PHY_DEV_TYPES; i++) { + if ((oui == PHY_DEVICES[i].phyIdOUI) && (model == PHY_DEVICES[i].phyIdModel)) + { + result = PHY_DEVICES[i].phyDevice; + + printk(KERN_INFO "%s: Phy: %s\n", + qdev->ndev->name, PHY_DEVICES[i].name); + + break; + } + } + + return result; +} + static int ql_phy_get_speed(struct ql3_adapter *qdev) { u16 reg; + switch(qdev->phyType) { + case PHY_AGERE_ET1011C: + { + if (ql_mii_read_reg(qdev, 0x1A, ®) < 0) + return 0; + + reg = (reg >> 8) & 3; + break; + } + default: if (ql_mii_read_reg(qdev, AUX_CONTROL_STATUS, ®) < 0) return 0; reg = (((reg & 0x18) >> 3) & 3); + } - if (reg == 2) + switch(reg) { + case 2: return SPEED_1000; - else if (reg == 1) + case 1: return SPEED_100; - else if (reg == 0) + case 0: return SPEED_10; - else + default: return -1; + } } static int ql_is_full_dup(struct ql3_adapter *qdev) { u16 reg; - if (ql_mii_read_reg(qdev, AUX_CONTROL_STATUS, ®) < 0) - return 0; - - return (reg & PHY_AUX_DUPLEX_STAT) != 0; + switch(qdev->phyType) { + case PHY_AGERE_ET1011C: + { + if (ql_mii_read_reg(qdev, 0x1A, ®)) + return 0; + + return ((reg & 0x0080) && (reg & 0x1000)) != 0; + } + case PHY_VITESSE_VSC8211: + default: + { + if (ql_mii_read_reg(qdev, AUX_CONTROL_STATUS, ®) < 0) + return 0; + return (reg & PHY_AUX_DUPLEX_STAT) != 0; + } + } } static int ql_is_phy_neg_pause(struct ql3_adapter *qdev) @@ -935,6 +1057,73 @@ static int ql_is_phy_neg_pause(struct ql3_adapter *qdev) return (reg & PHY_NEG_PAUSE) != 0; } +static int PHY_Setup(struct ql3_adapter *qdev) +{ + u16 reg1; + u16 reg2; + bool agereAddrChangeNeeded = false; + u32 miiAddr = 0; + int err; + + /* Determine the PHY we are using by reading the ID's */ + err = ql_mii_read_reg(qdev, PHY_ID_0_REG, ®1); + if(err != 0) { + printk(KERN_ERR "%s: Could not read from reg PHY_ID_0_REG\n", + qdev->ndev->name); + return err; + } + + err = ql_mii_read_reg(qdev, PHY_ID_1_REG, ®2); + if(err != 0) { + printk(KERN_ERR "%s: Could not read from reg PHY_ID_0_REG\n", + qdev->ndev->name); + return err; + } + + /* Check if we have a Agere PHY */ + if ((reg1 == 0xffff) || (reg2 == 0xffff)) { + + /* Determine which MII address we should be using + determined by the index of the card */ + if (qdev->mac_index == 0) { + miiAddr = MII_AGERE_ADDR_1; + } else { + miiAddr = MII_AGERE_ADDR_2; + } + + err =ql_mii_read_reg_ex(qdev, PHY_ID_0_REG, ®1, miiAddr); + if(err != 0) { + printk(KERN_ERR "%s: Could not read from reg PHY_ID_0_REG after Agere detected\n", + qdev->ndev->name); + return err; + } + + err = ql_mii_read_reg_ex(qdev, PHY_ID_1_REG, ®2, miiAddr); + if(err != 0) { + printk(KERN_ERR "%s: Could not read from reg PHY_ID_0_REG after Agere detected\n", + qdev->ndev->name); + return err; + } + + /* We need to remember to initialize the Agere PHY */ + agereAddrChangeNeeded = true; + } + + /* Determine the particular PHY we have on board to apply + PHY specific initializations */ + qdev->phyType = getPhyType(qdev, reg1, reg2); + + if ((qdev->phyType == PHY_AGERE_ET1011C) && agereAddrChangeNeeded) { + /* need this here so address gets changed */ + phyAgereSpecificInit(qdev, miiAddr); + } else if (qdev->phyType == PHY_TYPE_UNKNOWN) { + printk(KERN_ERR "%s: PHY is unknown\n", qdev->ndev->name); + return -EIO; + } + + return 0; +} + /* * Caller holds hw_lock. */ @@ -1205,15 +1394,14 @@ static int ql_link_down_detect_clear(struct ql3_adapter *qdev) /* * Caller holds hw_lock. */ -static int ql_this_adapter_controls_port(struct ql3_adapter *qdev, - u32 mac_index) +static int ql_this_adapter_controls_port(struct ql3_adapter *qdev) { struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; u32 bitToCheck = 0; u32 temp; - switch (mac_index) { + switch (qdev->mac_index) { case 0: bitToCheck = PORT_STATUS_F1_ENABLED; break; @@ -1238,27 +1426,96 @@ static int ql_this_adapter_controls_port(struct ql3_adapter *qdev, } } -static void ql_phy_reset_ex(struct ql3_adapter *qdev, u32 mac_index) +static void ql_phy_reset_ex(struct ql3_adapter *qdev) { - ql_mii_write_reg_ex(qdev, CONTROL_REG, PHY_CTRL_SOFT_RESET, mac_index); + ql_mii_write_reg_ex(qdev, CONTROL_REG, PHY_CTRL_SOFT_RESET, + PHYAddr[qdev->mac_index]); } -static void ql_phy_start_neg_ex(struct ql3_adapter *qdev, u32 mac_index) +static void ql_phy_start_neg_ex(struct ql3_adapter *qdev) { u16 reg; + u16 portConfiguration; + + if(qdev->phyType == PHY_AGERE_ET1011C) { + /* turn off external loopback */ + ql_mii_write_reg(qdev, 0x13, 0x0000); + } - ql_mii_write_reg_ex(qdev, PHY_NEG_ADVER, - PHY_NEG_PAUSE | PHY_NEG_ADV_SPEED | 1, mac_index); + if(qdev->mac_index == 0) + portConfiguration = qdev->nvram_data.macCfg_port0.portConfiguration; + else + portConfiguration = qdev->nvram_data.macCfg_port1.portConfiguration; + + /* Some HBA's in the field are set to 0 and they need to + be reinterpreted with a default value */ + if(portConfiguration == 0) + portConfiguration = PORT_CONFIG_DEFAULT; + + /* Set the 1000 advertisements */ + ql_mii_read_reg_ex(qdev, PHY_GIG_CONTROL, ®, + PHYAddr[qdev->mac_index]); + reg &= ~PHY_GIG_ALL_PARAMS; + + if(portConfiguration & + PORT_CONFIG_FULL_DUPLEX_ENABLED & + PORT_CONFIG_1000MB_SPEED) { + reg |= PHY_GIG_ADV_1000F; + } + + if(portConfiguration & + PORT_CONFIG_HALF_DUPLEX_ENABLED & + PORT_CONFIG_1000MB_SPEED) { + reg |= PHY_GIG_ADV_1000H; + } - ql_mii_read_reg_ex(qdev, CONTROL_REG, ®, mac_index); - ql_mii_write_reg_ex(qdev, CONTROL_REG, reg | PHY_CTRL_RESTART_NEG, - mac_index); + ql_mii_write_reg_ex(qdev, PHY_GIG_CONTROL, reg, + PHYAddr[qdev->mac_index]); + + /* Set the 10/100 & pause negotiation advertisements */ + ql_mii_read_reg_ex(qdev, PHY_NEG_ADVER, ®, + PHYAddr[qdev->mac_index]); + reg &= ~PHY_NEG_ALL_PARAMS; + + if(portConfiguration & PORT_CONFIG_SYM_PAUSE_ENABLED) + reg |= PHY_NEG_ASY_PAUSE | PHY_NEG_SYM_PAUSE; + + if(portConfiguration & PORT_CONFIG_FULL_DUPLEX_ENABLED) { + if(portConfiguration & PORT_CONFIG_100MB_SPEED) + reg |= PHY_NEG_ADV_100F; + + if(portConfiguration & PORT_CONFIG_10MB_SPEED) + reg |= PHY_NEG_ADV_10F; + } + + if(portConfiguration & PORT_CONFIG_HALF_DUPLEX_ENABLED) { + if(portConfiguration & PORT_CONFIG_100MB_SPEED) + reg |= PHY_NEG_ADV_100H; + + if(portConfiguration & PORT_CONFIG_10MB_SPEED) + reg |= PHY_NEG_ADV_10H; + } + + if(portConfiguration & + PORT_CONFIG_1000MB_SPEED) { + reg |= 1; + } + + ql_mii_write_reg_ex(qdev, PHY_NEG_ADVER, reg, + PHYAddr[qdev->mac_index]); + + ql_mii_read_reg_ex(qdev, CONTROL_REG, ®, PHYAddr[qdev->mac_index]); + + ql_mii_write_reg_ex(qdev, CONTROL_REG, + reg | PHY_CTRL_RESTART_NEG | PHY_CTRL_AUTO_NEG, + PHYAddr[qdev->mac_index]); } -static void ql_phy_init_ex(struct ql3_adapter *qdev, u32 mac_index) +static void ql_phy_init_ex(struct ql3_adapter *qdev) { - ql_phy_reset_ex(qdev, mac_index); - ql_phy_start_neg_ex(qdev, mac_index); + ql_phy_reset_ex(qdev); + PHY_Setup(qdev); + ql_phy_start_neg_ex(qdev); } /* @@ -1295,14 +1552,17 @@ static int ql_port_start(struct ql3_adapter *qdev) { if(ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK, (QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) * - 2) << 7)) + 2) << 7)) { + printk(KERN_ERR "%s: Could not get hw lock for GIO\n", + qdev->ndev->name); return -1; + } if (ql_is_fiber(qdev)) { ql_petbi_init(qdev); } else { /* Copper port */ - ql_phy_init_ex(qdev, qdev->mac_index); + ql_phy_init_ex(qdev); } ql_sem_unlock(qdev, QL_PHY_GIO_SEM_MASK); @@ -1453,7 +1713,7 @@ static void ql_link_state_machine(struct ql3_adapter *qdev) */ static void ql_get_phy_owner(struct ql3_adapter *qdev) { - if (ql_this_adapter_controls_port(qdev, qdev->mac_index)) + if (ql_this_adapter_controls_port(qdev)) set_bit(QL_LINK_MASTER,&qdev->flags); else clear_bit(QL_LINK_MASTER,&qdev->flags); @@ -1467,11 +1727,11 @@ static void ql_init_scan_mode(struct ql3_adapter *qdev) ql_mii_enable_scan_mode(qdev); if (test_bit(QL_LINK_OPTICAL,&qdev->flags)) { - if (ql_this_adapter_controls_port(qdev, qdev->mac_index)) - ql_petbi_init_ex(qdev, qdev->mac_index); + if (ql_this_adapter_controls_port(qdev)) + ql_petbi_init_ex(qdev); } else { - if (ql_this_adapter_controls_port(qdev, qdev->mac_index)) - ql_phy_init_ex(qdev, qdev->mac_index); + if (ql_this_adapter_controls_port(qdev)) + ql_phy_init_ex(qdev); } } @@ -1624,6 +1884,23 @@ static void ql_set_msglevel(struct net_device *ndev, u32 value) qdev->msg_enable = value; } +static void ql_get_pauseparam(struct net_device *ndev, + struct ethtool_pauseparam *pause) +{ + struct ql3_adapter *qdev = netdev_priv(ndev); + struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; + + u32 reg; + if(qdev->mac_index == 0) + reg = ql_read_page0_reg(qdev, &port_regs->mac0ConfigReg); + else + reg = ql_read_page0_reg(qdev, &port_regs->mac1ConfigReg); + + pause->autoneg = ql_get_auto_cfg_status(qdev); + pause->rx_pause = (reg & MAC_CONFIG_REG_RF) >> 2; + pause->tx_pause = (reg & MAC_CONFIG_REG_TF) >> 1; +} + static const struct ethtool_ops ql3xxx_ethtool_ops = { .get_settings = ql_get_settings, .get_drvinfo = ql_get_drvinfo, @@ -1631,6 +1908,7 @@ static const struct ethtool_ops ql3xxx_ethtool_ops = { .get_link = ethtool_op_get_link, .get_msglevel = ql_get_msglevel, .set_msglevel = ql_set_msglevel, + .get_pauseparam = ql_get_pauseparam, }; static int ql_populate_free_queue(struct ql3_adapter *qdev) @@ -1691,6 +1969,27 @@ static int ql_populate_free_queue(struct ql3_adapter *qdev) /* * Caller holds hw_lock. */ +static void ql_update_small_bufq_prod_index(struct ql3_adapter *qdev) +{ + struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; + if (qdev->small_buf_release_cnt >= 16) { + while (qdev->small_buf_release_cnt >= 16) { + qdev->small_buf_q_producer_index++; + + if (qdev->small_buf_q_producer_index == + NUM_SBUFQ_ENTRIES) + qdev->small_buf_q_producer_index = 0; + qdev->small_buf_release_cnt -= 8; + } + wmb(); + writel(qdev->small_buf_q_producer_index, + &port_regs->CommonRegs.rxSmallQProducerIndex); + } +} + +/* + * Caller holds hw_lock. + */ static void ql_update_lrg_bufq_prod_index(struct ql3_adapter *qdev) { struct bufq_addr_element *lrg_buf_q_ele; @@ -1732,13 +2031,10 @@ static void ql_update_lrg_bufq_prod_index(struct ql3_adapter *qdev) lrg_buf_q_ele = qdev->lrg_buf_q_virt_addr; } } - + wmb(); qdev->lrg_buf_next_free = lrg_buf_q_ele; - - ql_write_common_reg(qdev, - &port_regs->CommonRegs. - rxLargeQProducerIndex, - qdev->lrg_buf_q_producer_index); + writel(qdev->lrg_buf_q_producer_index, + &port_regs->CommonRegs.rxLargeQProducerIndex); } } @@ -1797,14 +2093,14 @@ invalid_seg_count: atomic_inc(&qdev->tx_count); } -void ql_get_sbuf(struct ql3_adapter *qdev) +static void ql_get_sbuf(struct ql3_adapter *qdev) { if (++qdev->small_buf_index == NUM_SMALL_BUFFERS) qdev->small_buf_index = 0; qdev->small_buf_release_cnt++; } -struct ql_rcv_buf_cb *ql_get_lbuf(struct ql3_adapter *qdev) +static struct ql_rcv_buf_cb *ql_get_lbuf(struct ql3_adapter *qdev) { struct ql_rcv_buf_cb *lrg_buf_cb = NULL; lrg_buf_cb = &qdev->lrg_buf[qdev->lrg_buf_index]; @@ -1855,7 +2151,6 @@ static void ql_process_mac_rx_intr(struct ql3_adapter *qdev, pci_unmap_len(lrg_buf_cb2, maplen), PCI_DMA_FROMDEVICE); prefetch(skb->data); - skb->dev = qdev->ndev; skb->ip_summed = CHECKSUM_NONE; skb->protocol = eth_type_trans(skb, qdev->ndev); @@ -1910,24 +2205,25 @@ static void ql_process_macip_rx_intr(struct ql3_adapter *qdev, * Copy the ethhdr from first buffer to second. This * is necessary for 3022 IP completions. */ - memcpy(skb_push(skb2, size), skb1->data + VLAN_ID_LEN, size); + skb_copy_from_linear_data_offset(skb1, VLAN_ID_LEN, + skb_push(skb2, size), size); } else { u16 checksum = le16_to_cpu(ib_ip_rsp_ptr->checksum); if (checksum & (IB_IP_IOCB_RSP_3032_ICE | - IB_IP_IOCB_RSP_3032_CE | - IB_IP_IOCB_RSP_3032_NUC)) { + IB_IP_IOCB_RSP_3032_CE)) { printk(KERN_ERR "%s: Bad checksum for this %s packet, checksum = %x.\n", __func__, ((checksum & IB_IP_IOCB_RSP_3032_TCP) ? "TCP" : "UDP"),checksum); - } else if (checksum & IB_IP_IOCB_RSP_3032_TCP) { + } else if ((checksum & IB_IP_IOCB_RSP_3032_TCP) || + (checksum & IB_IP_IOCB_RSP_3032_UDP && + !(checksum & IB_IP_IOCB_RSP_3032_NUC))) { skb2->ip_summed = CHECKSUM_UNNECESSARY; - } + } } - skb2->dev = qdev->ndev; skb2->protocol = eth_type_trans(skb2, qdev->ndev); netif_receive_skb(skb2); @@ -1944,16 +2240,12 @@ static void ql_process_macip_rx_intr(struct ql3_adapter *qdev, static int ql_tx_rx_clean(struct ql3_adapter *qdev, int *tx_cleaned, int *rx_cleaned, int work_to_do) { - struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; struct net_rsp_iocb *net_rsp; struct net_device *ndev = qdev->ndev; - unsigned long hw_flags; int work_done = 0; - u32 rsp_producer_index = le32_to_cpu(*(qdev->prsp_producer_index)); - /* While there are entries in the completion queue. */ - while ((rsp_producer_index != + while ((le32_to_cpu(*(qdev->prsp_producer_index)) != qdev->rsp_consumer_index) && (work_done < work_to_do)) { net_rsp = qdev->rsp_current; @@ -2009,33 +2301,7 @@ static int ql_tx_rx_clean(struct ql3_adapter *qdev, work_done = *tx_cleaned + *rx_cleaned; } - if(work_done) { - spin_lock_irqsave(&qdev->hw_lock, hw_flags); - - ql_update_lrg_bufq_prod_index(qdev); - - if (qdev->small_buf_release_cnt >= 16) { - while (qdev->small_buf_release_cnt >= 16) { - qdev->small_buf_q_producer_index++; - - if (qdev->small_buf_q_producer_index == - NUM_SBUFQ_ENTRIES) - qdev->small_buf_q_producer_index = 0; - qdev->small_buf_release_cnt -= 8; - } - - wmb(); - ql_write_common_reg(qdev, - &port_regs->CommonRegs. - rxSmallQProducerIndex, - qdev->small_buf_q_producer_index); - - } - - spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); - } - - return *tx_cleaned + *rx_cleaned; + return work_done; } static int ql_poll(struct net_device *ndev, int *budget) @@ -2059,9 +2325,10 @@ quit_polling: netif_rx_complete(ndev); spin_lock_irqsave(&qdev->hw_lock, hw_flags); - ql_write_common_reg(qdev, - &port_regs->CommonRegs.rspQConsumerIndex, - qdev->rsp_consumer_index); + ql_update_small_bufq_prod_index(qdev); + ql_update_lrg_bufq_prod_index(qdev); + writel(qdev->rsp_consumer_index, + &port_regs->CommonRegs.rspQConsumerIndex); spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); ql_enable_interrupts(qdev); @@ -2217,12 +2484,7 @@ static int ql_send_map(struct ql3_adapter *qdev, int seg_cnt, seg = 0; int frag_cnt = (int)skb_shinfo(skb)->nr_frags; - seg_cnt = tx_cb->seg_count = ql_get_seg_count(qdev, - (skb_shinfo(skb)->nr_frags)); - if(seg_cnt == -1) { - printk(KERN_ERR PFX"%s: invalid segment count!\n",__func__); - return NETDEV_TX_BUSY; - } + seg_cnt = tx_cb->seg_count; /* * Map the skb buffer first. */ @@ -2278,7 +2540,7 @@ static int ql_send_map(struct ql3_adapter *qdev, pci_unmap_addr_set(&tx_cb->map[seg], mapaddr, map); pci_unmap_len_set(&tx_cb->map[seg], maplen, - len); + sizeof(struct oal)); oal_entry = (struct oal_entry *)oal; oal++; seg++; @@ -2380,6 +2642,7 @@ static int ql3xxx_send(struct sk_buff *skb, struct net_device *ndev) } mac_iocb_ptr = tx_cb->queue_entry; + memset((void *)mac_iocb_ptr, 0, sizeof(struct ob_mac_iocb_req)); mac_iocb_ptr->opcode = qdev->mac_ob_opcode; mac_iocb_ptr->flags = OB_MAC_IOCB_REQ_X; mac_iocb_ptr->flags |= qdev->mb_bit_mask; @@ -3054,15 +3317,6 @@ static int ql_adapter_initialize(struct ql3_adapter *qdev) goto out; } - if (qdev->mac_index) - ql_write_page0_reg(qdev, - &port_regs->mac1MaxFrameLengthReg, - qdev->max_frame_size); - else - ql_write_page0_reg(qdev, - &port_regs->mac0MaxFrameLengthReg, - qdev->max_frame_size); - value = qdev->nvram_data.tcpMaxWindowSize; ql_write_page0_reg(qdev, &port_regs->tcpMaxWindow, value); @@ -3082,6 +3336,14 @@ static int ql_adapter_initialize(struct ql3_adapter *qdev) ql_sem_unlock(qdev, QL_FLASH_SEM_MASK); } + if (qdev->mac_index) + ql_write_page0_reg(qdev, + &port_regs->mac1MaxFrameLengthReg, + qdev->max_frame_size); + else + ql_write_page0_reg(qdev, + &port_regs->mac0MaxFrameLengthReg, + qdev->max_frame_size); if(ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK, (QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) * @@ -3090,6 +3352,7 @@ static int ql_adapter_initialize(struct ql3_adapter *qdev) goto out; } + PHY_Setup(qdev); ql_init_scan_mode(qdev); ql_get_phy_owner(qdev); @@ -3152,7 +3415,8 @@ static int ql_adapter_initialize(struct ql3_adapter *qdev) if (qdev->device_id == QL3032_DEVICE_ID) { value = (QL3032_PORT_CONTROL_EF | QL3032_PORT_CONTROL_KIE | - QL3032_PORT_CONTROL_EIv6 | QL3032_PORT_CONTROL_EIv4); + QL3032_PORT_CONTROL_EIv6 | QL3032_PORT_CONTROL_EIv4 | + QL3032_PORT_CONTROL_ET); ql_write_page0_reg(qdev, &port_regs->functionControl, ((value << 16) | value)); } else { |