diff options
author | John W. Linville <linville@tuxdriver.com> | 2010-07-27 11:59:19 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-07-27 11:59:19 -0400 |
commit | 800f65bba8d2030b3fef62850e203f9f176625a8 (patch) | |
tree | 6507c4fe7a0826c253b4afb29375ab306a0fd9c8 /drivers/net/benet | |
parent | 06b3cda0c12986f5bba578b918b188d731c4e191 (diff) | |
parent | b3190df628617c7a4f188a9465aeabe1f5761933 (diff) | |
download | blackbird-op-linux-800f65bba8d2030b3fef62850e203f9f176625a8.tar.gz blackbird-op-linux-800f65bba8d2030b3fef62850e203f9f176625a8.zip |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/holtmann/bluetooth-next-2.6
Conflicts:
drivers/net/wireless/iwlwifi/iwl-commands.h
Diffstat (limited to 'drivers/net/benet')
-rw-r--r-- | drivers/net/benet/be.h | 15 | ||||
-rw-r--r-- | drivers/net/benet/be_cmds.c | 80 | ||||
-rw-r--r-- | drivers/net/benet/be_cmds.h | 27 | ||||
-rw-r--r-- | drivers/net/benet/be_ethtool.c | 55 | ||||
-rw-r--r-- | drivers/net/benet/be_hw.h | 2 | ||||
-rw-r--r-- | drivers/net/benet/be_main.c | 122 |
6 files changed, 219 insertions, 82 deletions
diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index 373c1a563474..f17428caecf1 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -282,15 +282,19 @@ struct be_adapter { int link_speed; u8 port_type; u8 transceiver; + u8 autoneg; u8 generation; /* BladeEngine ASIC generation */ + u32 flash_status; + struct completion flash_compl; bool sriov_enabled; u32 vf_if_handle[BE_MAX_VF]; u32 vf_pmac_id[BE_MAX_VF]; u8 base_eq_id; + u8 is_virtfn; }; -#define be_physfn(adapter) (!adapter->pdev->is_virtfn) +#define be_physfn(adapter) (!adapter->is_virtfn) /* BladeEngine Generation numbers */ #define BE_GEN2 2 @@ -390,6 +394,15 @@ static inline u8 is_udp_pkt(struct sk_buff *skb) return val; } +static inline void be_check_sriov_fn_type(struct be_adapter *adapter) +{ + u8 data; + + pci_write_config_byte(adapter->pdev, 0xFE, 0xAA); + pci_read_config_byte(adapter->pdev, 0xFE, &data); + adapter->is_virtfn = (data != 0xAA); +} + extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, u16 num_popped); extern void be_link_status_update(struct be_adapter *adapter, bool link_up); diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index e79bf8b9af3b..344e062b7f25 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -25,6 +25,8 @@ static void be_mcc_notify(struct be_adapter *adapter) val |= mccq->id & DB_MCCQ_RING_ID_MASK; val |= 1 << DB_MCCQ_NUM_POSTED_SHIFT; + + wmb(); iowrite32(val, adapter->db + DB_MCCQ_OFFSET); } @@ -59,6 +61,13 @@ static int be_mcc_compl_process(struct be_adapter *adapter, compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) & CQE_STATUS_COMPL_MASK; + + if ((compl->tag0 == OPCODE_COMMON_WRITE_FLASHROM) && + (compl->tag1 == CMD_SUBSYSTEM_COMMON)) { + adapter->flash_status = compl_status; + complete(&adapter->flash_compl); + } + if (compl_status == MCC_STATUS_SUCCESS) { if (compl->tag0 == OPCODE_ETH_GET_STATISTICS) { struct be_cmd_resp_get_stats *resp = @@ -179,7 +188,7 @@ static int be_mcc_notify_wait(struct be_adapter *adapter) static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db) { - int cnt = 0, wait = 5; + int msecs = 0; u32 ready; do { @@ -194,15 +203,14 @@ static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db) if (ready) break; - if (cnt > 4000000) { + if (msecs > 4000) { dev_err(&adapter->pdev->dev, "mbox poll timed out\n"); return -1; } - if (cnt > 50) - wait = 200; - cnt += wait; - udelay(wait); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(msecs_to_jiffies(1)); + msecs++; } while (true); return 0; @@ -287,7 +295,7 @@ int be_cmd_POST(struct be_adapter *adapter) } else { return 0; } - } while (timeout < 20); + } while (timeout < 40); dev_err(&adapter->pdev->dev, "POST timeout; stage=0x%x\n", stage); return -1; @@ -1417,17 +1425,19 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, int status; spin_lock_bh(&adapter->mcc_lock); + adapter->flash_status = 0; wrb = wrb_from_mccq(adapter); if (!wrb) { status = -EBUSY; - goto err; + goto err_unlock; } req = cmd->va; sge = nonembedded_sgl(wrb); be_wrb_hdr_prepare(wrb, cmd->size, false, 1, OPCODE_COMMON_WRITE_FLASHROM); + wrb->tag1 = CMD_SUBSYSTEM_COMMON; be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, OPCODE_COMMON_WRITE_FLASHROM, cmd->size); @@ -1439,9 +1449,18 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, req->params.op_code = cpu_to_le32(flash_opcode); req->params.data_buf_size = cpu_to_le32(buf_size); - status = be_mcc_notify_wait(adapter); + be_mcc_notify(adapter); + spin_unlock_bh(&adapter->mcc_lock); -err: + if (!wait_for_completion_timeout(&adapter->flash_compl, + msecs_to_jiffies(12000))) + status = -1; + else + status = adapter->flash_status; + + return status; + +err_unlock: spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -1482,7 +1501,7 @@ err: return status; } -extern int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac, +int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac, struct be_dma_mem *nonemb_cmd) { struct be_mcc_wrb *wrb; @@ -1575,7 +1594,7 @@ int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num, be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL, OPCODE_LOWLEVEL_LOOPBACK_TEST, sizeof(*req)); - req->hdr.timeout = 4; + req->hdr.timeout = cpu_to_le32(4); req->pattern = cpu_to_le64(pattern); req->src_port = cpu_to_le32(port_num); @@ -1647,7 +1666,7 @@ err: return status; } -extern int be_cmd_get_seeprom_data(struct be_adapter *adapter, +int be_cmd_get_seeprom_data(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd) { struct be_mcc_wrb *wrb; @@ -1676,3 +1695,38 @@ extern int be_cmd_get_seeprom_data(struct be_adapter *adapter, spin_unlock_bh(&adapter->mcc_lock); return status; } + +int be_cmd_get_phy_info(struct be_adapter *adapter, struct be_dma_mem *cmd) +{ + struct be_mcc_wrb *wrb; + struct be_cmd_req_get_phy_info *req; + struct be_sge *sge; + int status; + + spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; + goto err; + } + + req = cmd->va; + sge = nonembedded_sgl(wrb); + + be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1, + OPCODE_COMMON_GET_PHY_DETAILS); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_GET_PHY_DETAILS, + sizeof(*req)); + + sge->pa_hi = cpu_to_le32(upper_32_bits(cmd->dma)); + sge->pa_lo = cpu_to_le32(cmd->dma & 0xFFFFFFFF); + sge->len = cpu_to_le32(cmd->size); + + status = be_mcc_notify_wait(adapter); +err: + spin_unlock_bh(&adapter->mcc_lock); + return status; +} diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h index 763dc199e337..912a0586f060 100644 --- a/drivers/net/benet/be_cmds.h +++ b/drivers/net/benet/be_cmds.h @@ -144,6 +144,7 @@ struct be_mcc_mailbox { #define OPCODE_COMMON_ENABLE_DISABLE_BEACON 69 #define OPCODE_COMMON_GET_BEACON_STATE 70 #define OPCODE_COMMON_READ_TRANSRECV_DATA 73 +#define OPCODE_COMMON_GET_PHY_DETAILS 102 #define OPCODE_ETH_ACPI_CONFIG 2 #define OPCODE_ETH_PROMISCUOUS 3 @@ -869,6 +870,30 @@ struct be_cmd_resp_seeprom_read { u8 seeprom_data[BE_READ_SEEPROM_LEN]; }; +enum { + PHY_TYPE_CX4_10GB = 0, + PHY_TYPE_XFP_10GB, + PHY_TYPE_SFP_1GB, + PHY_TYPE_SFP_PLUS_10GB, + PHY_TYPE_KR_10GB, + PHY_TYPE_KX4_10GB, + PHY_TYPE_BASET_10GB, + PHY_TYPE_BASET_1GB, + PHY_TYPE_DISABLED = 255 +}; + +struct be_cmd_req_get_phy_info { + struct be_cmd_req_hdr hdr; + u8 rsvd0[24]; +}; +struct be_cmd_resp_get_phy_info { + struct be_cmd_req_hdr hdr; + u16 phy_type; + u16 interface_type; + u32 misc_params; + u32 future_use[4]; +}; + extern int be_pci_fnum_get(struct be_adapter *adapter); extern int be_cmd_POST(struct be_adapter *adapter); extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, @@ -947,4 +972,6 @@ extern int be_cmd_get_seeprom_data(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd); extern int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num, u8 loopback_type, u8 enable); +extern int be_cmd_get_phy_info(struct be_adapter *adapter, + struct be_dma_mem *cmd); diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c index 200e98515909..c0ade242895d 100644 --- a/drivers/net/benet/be_ethtool.c +++ b/drivers/net/benet/be_ethtool.c @@ -314,10 +314,13 @@ static int be_get_sset_count(struct net_device *netdev, int stringset) static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) { struct be_adapter *adapter = netdev_priv(netdev); - u8 mac_speed = 0, connector = 0; + struct be_dma_mem phy_cmd; + struct be_cmd_resp_get_phy_info *resp; + u8 mac_speed = 0; u16 link_speed = 0; bool link_up = false; int status; + u16 intf_type; if (adapter->link_speed < 0) { status = be_cmd_link_status_query(adapter, &link_up, @@ -337,40 +340,57 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) } } - status = be_cmd_read_port_type(adapter, adapter->port_num, - &connector); + phy_cmd.size = sizeof(struct be_cmd_req_get_phy_info); + phy_cmd.va = pci_alloc_consistent(adapter->pdev, phy_cmd.size, + &phy_cmd.dma); + if (!phy_cmd.va) { + dev_err(&adapter->pdev->dev, "Memory alloc failure\n"); + return -ENOMEM; + } + status = be_cmd_get_phy_info(adapter, &phy_cmd); if (!status) { - switch (connector) { - case 7: + resp = (struct be_cmd_resp_get_phy_info *) phy_cmd.va; + intf_type = le16_to_cpu(resp->interface_type); + + switch (intf_type) { + case PHY_TYPE_XFP_10GB: + case PHY_TYPE_SFP_1GB: + case PHY_TYPE_SFP_PLUS_10GB: ecmd->port = PORT_FIBRE; - ecmd->transceiver = XCVR_EXTERNAL; - break; - case 0: - ecmd->port = PORT_TP; - ecmd->transceiver = XCVR_EXTERNAL; break; default: ecmd->port = PORT_TP; - ecmd->transceiver = XCVR_INTERNAL; break; } - } else { - ecmd->port = PORT_AUI; + + switch (intf_type) { + case PHY_TYPE_KR_10GB: + case PHY_TYPE_KX4_10GB: + ecmd->autoneg = AUTONEG_ENABLE; ecmd->transceiver = XCVR_INTERNAL; + break; + default: + ecmd->autoneg = AUTONEG_DISABLE; + ecmd->transceiver = XCVR_EXTERNAL; + break; + } } /* Save for future use */ adapter->link_speed = ecmd->speed; adapter->port_type = ecmd->port; adapter->transceiver = ecmd->transceiver; + adapter->autoneg = ecmd->autoneg; + pci_free_consistent(adapter->pdev, phy_cmd.size, + phy_cmd.va, phy_cmd.dma); } else { ecmd->speed = adapter->link_speed; ecmd->port = adapter->port_type; ecmd->transceiver = adapter->transceiver; + ecmd->autoneg = adapter->autoneg; } ecmd->duplex = DUPLEX_FULL; - ecmd->autoneg = AUTONEG_DISABLE; ecmd->phy_address = adapter->port_num; switch (ecmd->port) { case PORT_FIBRE: @@ -384,6 +404,13 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) break; } + if (ecmd->autoneg) { + ecmd->supported |= SUPPORTED_1000baseT_Full; + ecmd->supported |= SUPPORTED_Autoneg; + ecmd->advertising |= (ADVERTISED_10000baseT_Full | + ADVERTISED_1000baseT_Full); + } + return 0; } diff --git a/drivers/net/benet/be_hw.h b/drivers/net/benet/be_hw.h index 063026de4957..06839676e3c4 100644 --- a/drivers/net/benet/be_hw.h +++ b/drivers/net/benet/be_hw.h @@ -192,7 +192,7 @@ struct amap_eth_hdr_wrb { u8 event; u8 crc; u8 forward; - u8 ipsec; + u8 lso6; u8 mgmt; u8 ipcs; u8 udpcs; diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 058d7f95f5ae..e6ca92334d6d 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -89,6 +89,8 @@ static void be_rxq_notify(struct be_adapter *adapter, u16 qid, u16 posted) u32 val = 0; val |= qid & DB_RQ_RING_ID_MASK; val |= posted << DB_RQ_NUM_POSTED_SHIFT; + + wmb(); iowrite32(val, adapter->db + DB_RQ_OFFSET); } @@ -97,6 +99,8 @@ static void be_txq_notify(struct be_adapter *adapter, u16 qid, u16 posted) u32 val = 0; val |= qid & DB_TXULP_RING_ID_MASK; val |= (posted & DB_TXULP_NUM_POSTED_MASK) << DB_TXULP_NUM_POSTED_SHIFT; + + wmb(); iowrite32(val, adapter->db + DB_TXULP1_OFFSET); } @@ -373,10 +377,12 @@ static void wrb_fill_hdr(struct be_eth_hdr_wrb *hdr, struct sk_buff *skb, AMAP_SET_BITS(struct amap_eth_hdr_wrb, crc, hdr, 1); - if (skb_shinfo(skb)->gso_segs > 1 && skb_shinfo(skb)->gso_size) { + if (skb_is_gso(skb)) { AMAP_SET_BITS(struct amap_eth_hdr_wrb, lso, hdr, 1); AMAP_SET_BITS(struct amap_eth_hdr_wrb, lso_mss, hdr, skb_shinfo(skb)->gso_size); + if (skb_is_gso_v6(skb)) + AMAP_SET_BITS(struct amap_eth_hdr_wrb, lso6, hdr, 1); } else if (skb->ip_summed == CHECKSUM_PARTIAL) { if (is_tcp_pkt(skb)) AMAP_SET_BITS(struct amap_eth_hdr_wrb, tcpcs, hdr, 1); @@ -971,6 +977,7 @@ static struct be_eth_rx_compl *be_rx_compl_get(struct be_adapter *adapter) if (rxcp->dw[offsetof(struct amap_eth_rx_compl, valid) / 32] == 0) return NULL; + rmb(); be_dws_le_to_cpu(rxcp, sizeof(*rxcp)); queue_tail_inc(&adapter->rx_obj.cq); @@ -1064,6 +1071,7 @@ static struct be_eth_tx_compl *be_tx_compl_get(struct be_queue_info *tx_cq) if (txcp->dw[offsetof(struct amap_eth_tx_compl, valid) / 32] == 0) return NULL; + rmb(); be_dws_le_to_cpu(txcp, sizeof(*txcp)); txcp->dw[offsetof(struct amap_eth_tx_compl, valid) / 32] = 0; @@ -1111,6 +1119,7 @@ static inline struct be_eq_entry *event_get(struct be_eq_obj *eq_obj) if (!eqe->evt) return NULL; + rmb(); eqe->evt = le32_to_cpu(eqe->evt); queue_tail_inc(&eq_obj->q); return eqe; @@ -1622,6 +1631,7 @@ static void be_sriov_enable(struct be_adapter *adapter) { #ifdef CONFIG_PCI_IOV int status; + be_check_sriov_fn_type(adapter); if (be_physfn(adapter) && num_vfs) { status = pci_enable_sriov(adapter->pdev, num_vfs); adapter->sriov_enabled = status ? false : true; @@ -1735,6 +1745,44 @@ done: adapter->isr_registered = false; } +static int be_close(struct net_device *netdev) +{ + struct be_adapter *adapter = netdev_priv(netdev); + struct be_eq_obj *rx_eq = &adapter->rx_eq; + struct be_eq_obj *tx_eq = &adapter->tx_eq; + int vec; + + cancel_delayed_work_sync(&adapter->work); + + be_async_mcc_disable(adapter); + + netif_stop_queue(netdev); + netif_carrier_off(netdev); + adapter->link_up = false; + + be_intr_set(adapter, false); + + if (adapter->msix_enabled) { + vec = be_msix_vec_get(adapter, tx_eq->q.id); + synchronize_irq(vec); + vec = be_msix_vec_get(adapter, rx_eq->q.id); + synchronize_irq(vec); + } else { + synchronize_irq(netdev->irq); + } + be_irq_unregister(adapter); + + napi_disable(&rx_eq->napi); + napi_disable(&tx_eq->napi); + + /* Wait for all pending tx completions to arrive so that + * all tx skbs are freed. + */ + be_tx_compl_clean(adapter); + + return 0; +} + static int be_open(struct net_device *netdev) { struct be_adapter *adapter = netdev_priv(netdev); @@ -1765,27 +1813,29 @@ static int be_open(struct net_device *netdev) /* Now that interrupts are on we can process async mcc */ be_async_mcc_enable(adapter); + schedule_delayed_work(&adapter->work, msecs_to_jiffies(100)); + status = be_cmd_link_status_query(adapter, &link_up, &mac_speed, &link_speed); if (status) - goto ret_sts; + goto err; be_link_status_update(adapter, link_up); - if (be_physfn(adapter)) + if (be_physfn(adapter)) { status = be_vid_config(adapter); - if (status) - goto ret_sts; + if (status) + goto err; - if (be_physfn(adapter)) { status = be_cmd_set_flow_control(adapter, adapter->tx_fc, adapter->rx_fc); if (status) - goto ret_sts; + goto err; } - schedule_delayed_work(&adapter->work, msecs_to_jiffies(100)); -ret_sts: - return status; + return 0; +err: + be_close(adapter->netdev); + return -EIO; } static int be_setup_wol(struct be_adapter *adapter, bool enable) @@ -1861,7 +1911,7 @@ static int be_setup(struct be_adapter *adapter) goto if_destroy; } vf++; - } while (vf < num_vfs); + } } else if (!be_physfn(adapter)) { status = be_cmd_mac_addr_query(adapter, mac, MAC_ADDRESS_TYPE_NETWORK, false, adapter->if_handle); @@ -1913,43 +1963,6 @@ static int be_clear(struct be_adapter *adapter) return 0; } -static int be_close(struct net_device *netdev) -{ - struct be_adapter *adapter = netdev_priv(netdev); - struct be_eq_obj *rx_eq = &adapter->rx_eq; - struct be_eq_obj *tx_eq = &adapter->tx_eq; - int vec; - - cancel_delayed_work_sync(&adapter->work); - - be_async_mcc_disable(adapter); - - netif_stop_queue(netdev); - netif_carrier_off(netdev); - adapter->link_up = false; - - be_intr_set(adapter, false); - - if (adapter->msix_enabled) { - vec = be_msix_vec_get(adapter, tx_eq->q.id); - synchronize_irq(vec); - vec = be_msix_vec_get(adapter, rx_eq->q.id); - synchronize_irq(vec); - } else { - synchronize_irq(netdev->irq); - } - be_irq_unregister(adapter); - - napi_disable(&rx_eq->napi); - napi_disable(&tx_eq->napi); - - /* Wait for all pending tx completions to arrive so that - * all tx skbs are freed. - */ - be_tx_compl_clean(adapter); - - return 0; -} #define FW_FILE_HDR_SIGN "ServerEngines Corp. " char flash_cookie[2][16] = {"*** SE FLAS", @@ -2183,7 +2196,7 @@ static void be_netdev_init(struct net_device *netdev) netdev->features |= NETIF_F_SG | NETIF_F_HW_VLAN_RX | NETIF_F_TSO | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | NETIF_F_HW_CSUM | - NETIF_F_GRO; + NETIF_F_GRO | NETIF_F_TSO6; netdev->vlan_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_HW_CSUM; @@ -2319,6 +2332,7 @@ static int be_ctrl_init(struct be_adapter *adapter) spin_lock_init(&adapter->mcc_lock); spin_lock_init(&adapter->mcc_cq_lock); + init_completion(&adapter->flash_compl); pci_save_state(adapter->pdev); return 0; @@ -2487,10 +2501,6 @@ static int __devinit be_probe(struct pci_dev *pdev, status = be_cmd_POST(adapter); if (status) goto ctrl_clean; - - status = be_cmd_reset_function(adapter); - if (status) - goto ctrl_clean; } /* tell fw we're ready to fire cmds */ @@ -2498,6 +2508,12 @@ static int __devinit be_probe(struct pci_dev *pdev, if (status) goto ctrl_clean; + if (be_physfn(adapter)) { + status = be_cmd_reset_function(adapter); + if (status) + goto ctrl_clean; + } + status = be_stats_init(adapter); if (status) goto ctrl_clean; |