diff options
Diffstat (limited to 'drivers/net/ethernet/emulex/benet/be_main.c')
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_main.c | 585 |
1 files changed, 342 insertions, 243 deletions
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index dc19bc5dec7..34a26e42f19 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -134,7 +134,7 @@ static void be_queue_free(struct be_adapter *adapter, struct be_queue_info *q) } static int be_queue_alloc(struct be_adapter *adapter, struct be_queue_info *q, - u16 len, u16 entry_size) + u16 len, u16 entry_size) { struct be_dma_mem *mem = &q->dma_mem; @@ -154,7 +154,7 @@ static void be_reg_intr_set(struct be_adapter *adapter, bool enable) u32 reg, enabled; pci_read_config_dword(adapter->pdev, PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET, - ®); + ®); enabled = reg & MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; if (!enabled && enable) @@ -165,7 +165,7 @@ static void be_reg_intr_set(struct be_adapter *adapter, bool enable) return; pci_write_config_dword(adapter->pdev, - PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET, reg); + PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET, reg); } static void be_intr_set(struct be_adapter *adapter, bool enable) @@ -206,12 +206,11 @@ static void be_txq_notify(struct be_adapter *adapter, struct be_tx_obj *txo, } static void be_eq_notify(struct be_adapter *adapter, u16 qid, - bool arm, bool clear_int, u16 num_popped) + bool arm, bool clear_int, u16 num_popped) { u32 val = 0; val |= qid & DB_EQ_RING_ID_MASK; - val |= ((qid & DB_EQ_RING_ID_EXT_MASK) << - DB_EQ_RING_ID_EXT_MASK_SHIFT); + val |= ((qid & DB_EQ_RING_ID_EXT_MASK) << DB_EQ_RING_ID_EXT_MASK_SHIFT); if (adapter->eeh_error) return; @@ -477,7 +476,7 @@ static void populate_be_v2_stats(struct be_adapter *adapter) drvs->rx_drops_no_tpre_descr = rxf_stats->rx_drops_no_tpre_descr; drvs->rx_drops_too_many_frags = rxf_stats->rx_drops_too_many_frags; adapter->drv_stats.eth_red_drops = pmem_sts->eth_red_drops; - if (be_roce_supported(adapter)) { + if (be_roce_supported(adapter)) { drvs->rx_roce_bytes_lsd = port_stats->roce_bytes_received_lsd; drvs->rx_roce_bytes_msd = port_stats->roce_bytes_received_msd; drvs->rx_roce_frames = port_stats->roce_frames_received; @@ -491,8 +490,7 @@ static void populate_lancer_stats(struct be_adapter *adapter) { struct be_drv_stats *drvs = &adapter->drv_stats; - struct lancer_pport_stats *pport_stats = - pport_stats_from_cmd(adapter); + struct lancer_pport_stats *pport_stats = pport_stats_from_cmd(adapter); be_dws_le_to_cpu(pport_stats, sizeof(*pport_stats)); drvs->rx_pause_frames = pport_stats->rx_pause_frames_lo; @@ -539,8 +537,7 @@ static void accumulate_16bit_val(u32 *acc, u16 val) } static void populate_erx_stats(struct be_adapter *adapter, - struct be_rx_obj *rxo, - u32 erx_stat) + struct be_rx_obj *rxo, u32 erx_stat) { if (!BEx_chip(adapter)) rx_stats(rxo)->rx_drops_no_frags = erx_stat; @@ -579,7 +576,7 @@ void be_parse_stats(struct be_adapter *adapter) } static struct rtnl_link_stats64 *be_get_stats64(struct net_device *netdev, - struct rtnl_link_stats64 *stats) + struct rtnl_link_stats64 *stats) { struct be_adapter *adapter = netdev_priv(netdev); struct be_drv_stats *drvs = &adapter->drv_stats; @@ -660,7 +657,8 @@ void be_link_status_update(struct be_adapter *adapter, u8 link_status) } static void be_tx_stats_update(struct be_tx_obj *txo, - u32 wrb_cnt, u32 copied, u32 gso_segs, bool stopped) + u32 wrb_cnt, u32 copied, u32 gso_segs, + bool stopped) { struct be_tx_stats *stats = tx_stats(txo); @@ -676,7 +674,7 @@ static void be_tx_stats_update(struct be_tx_obj *txo, /* Determine number of WRB entries needed to xmit data in an skb */ static u32 wrb_cnt_for_skb(struct be_adapter *adapter, struct sk_buff *skb, - bool *dummy) + bool *dummy) { int cnt = (skb->len > skb->data_len); @@ -704,7 +702,7 @@ static inline void wrb_fill(struct be_eth_wrb *wrb, u64 addr, int len) } static inline u16 be_get_tx_vlan_tag(struct be_adapter *adapter, - struct sk_buff *skb) + struct sk_buff *skb) { u8 vlan_prio; u16 vlan_tag; @@ -733,7 +731,8 @@ static u16 skb_ip_proto(struct sk_buff *skb) } static void wrb_fill_hdr(struct be_adapter *adapter, struct be_eth_hdr_wrb *hdr, - struct sk_buff *skb, u32 wrb_cnt, u32 len, bool skip_hw_vlan) + struct sk_buff *skb, u32 wrb_cnt, u32 len, + bool skip_hw_vlan) { u16 vlan_tag, proto; @@ -774,7 +773,7 @@ static void wrb_fill_hdr(struct be_adapter *adapter, struct be_eth_hdr_wrb *hdr, } static void unmap_tx_frag(struct device *dev, struct be_eth_wrb *wrb, - bool unmap_single) + bool unmap_single) { dma_addr_t dma; @@ -791,8 +790,8 @@ static void unmap_tx_frag(struct device *dev, struct be_eth_wrb *wrb, } static int make_tx_wrbs(struct be_adapter *adapter, struct be_queue_info *txq, - struct sk_buff *skb, u32 wrb_cnt, bool dummy_wrb, - bool skip_hw_vlan) + struct sk_buff *skb, u32 wrb_cnt, bool dummy_wrb, + bool skip_hw_vlan) { dma_addr_t busaddr; int i, copied = 0; @@ -821,8 +820,7 @@ static int make_tx_wrbs(struct be_adapter *adapter, struct be_queue_info *txq, } for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - const struct skb_frag_struct *frag = - &skb_shinfo(skb)->frags[i]; + const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i]; busaddr = skb_frag_dma_map(dev, frag, 0, skb_frag_size(frag), DMA_TO_DEVICE); if (dma_mapping_error(dev, busaddr)) @@ -927,8 +925,7 @@ static int be_vlan_tag_tx_chk(struct be_adapter *adapter, struct sk_buff *skb) return vlan_tx_tag_present(skb) || adapter->pvid || adapter->qnq_vid; } -static int be_ipv6_tx_stall_chk(struct be_adapter *adapter, - struct sk_buff *skb) +static int be_ipv6_tx_stall_chk(struct be_adapter *adapter, struct sk_buff *skb) { return BE3_chip(adapter) && be_ipv6_exthdr_check(skb); } @@ -959,7 +956,7 @@ static struct sk_buff *be_lancer_xmit_workarounds(struct be_adapter *adapter, */ if (be_pvid_tagging_enabled(adapter) && veh->h_vlan_proto == htons(ETH_P_8021Q)) - *skip_hw_vlan = true; + *skip_hw_vlan = true; /* HW has a bug wherein it will calculate CSUM for VLAN * pkts even though it is disabled. @@ -1077,16 +1074,15 @@ static int be_change_mtu(struct net_device *netdev, int new_mtu) { struct be_adapter *adapter = netdev_priv(netdev); if (new_mtu < BE_MIN_MTU || - new_mtu > (BE_MAX_JUMBO_FRAME_SIZE - - (ETH_HLEN + ETH_FCS_LEN))) { + new_mtu > (BE_MAX_JUMBO_FRAME_SIZE - (ETH_HLEN + ETH_FCS_LEN))) { dev_info(&adapter->pdev->dev, - "MTU must be between %d and %d bytes\n", - BE_MIN_MTU, - (BE_MAX_JUMBO_FRAME_SIZE - (ETH_HLEN + ETH_FCS_LEN))); + "MTU must be between %d and %d bytes\n", + BE_MIN_MTU, + (BE_MAX_JUMBO_FRAME_SIZE - (ETH_HLEN + ETH_FCS_LEN))); return -EINVAL; } dev_info(&adapter->pdev->dev, "MTU changed from %d to %d bytes\n", - netdev->mtu, new_mtu); + netdev->mtu, new_mtu); netdev->mtu = new_mtu; return 0; } @@ -1098,7 +1094,7 @@ static int be_change_mtu(struct net_device *netdev, int new_mtu) static int be_vid_config(struct be_adapter *adapter) { u16 vids[BE_NUM_VLANS_SUPPORTED]; - u16 num = 0, i; + u16 num = 0, i = 0; int status = 0; /* No need to further configure vids if in promiscuous mode */ @@ -1109,16 +1105,14 @@ static int be_vid_config(struct be_adapter *adapter) goto set_vlan_promisc; /* Construct VLAN Table to give to HW */ - for (i = 0; i < VLAN_N_VID; i++) - if (adapter->vlan_tag[i]) - vids[num++] = cpu_to_le16(i); - - status = be_cmd_vlan_config(adapter, adapter->if_handle, - vids, num, 0); + for_each_set_bit(i, adapter->vids, VLAN_N_VID) + vids[num++] = cpu_to_le16(i); + status = be_cmd_vlan_config(adapter, adapter->if_handle, vids, num); if (status) { /* Set to VLAN promisc mode as setting VLAN filter failed */ - if (status == MCC_ADDL_STS_INSUFFICIENT_RESOURCES) + if (addl_status(status) == + MCC_ADDL_STATUS_INSUFFICIENT_RESOURCES) goto set_vlan_promisc; dev_err(&adapter->pdev->dev, "Setting HW VLAN filtering failed.\n"); @@ -1160,16 +1154,16 @@ static int be_vlan_add_vid(struct net_device *netdev, __be16 proto, u16 vid) if (lancer_chip(adapter) && vid == 0) return status; - if (adapter->vlan_tag[vid]) + if (test_bit(vid, adapter->vids)) return status; - adapter->vlan_tag[vid] = 1; + set_bit(vid, adapter->vids); adapter->vlans_added++; status = be_vid_config(adapter); if (status) { adapter->vlans_added--; - adapter->vlan_tag[vid] = 0; + clear_bit(vid, adapter->vids); } return status; @@ -1184,12 +1178,12 @@ static int be_vlan_rem_vid(struct net_device *netdev, __be16 proto, u16 vid) if (lancer_chip(adapter) && vid == 0) goto ret; - adapter->vlan_tag[vid] = 0; + clear_bit(vid, adapter->vids); status = be_vid_config(adapter); if (!status) adapter->vlans_added--; else - adapter->vlan_tag[vid] = 1; + set_bit(vid, adapter->vids); ret: return status; } @@ -1197,7 +1191,7 @@ ret: static void be_clear_promisc(struct be_adapter *adapter) { adapter->promiscuous = false; - adapter->flags &= ~BE_FLAGS_VLAN_PROMISC; + adapter->flags &= ~(BE_FLAGS_VLAN_PROMISC | BE_FLAGS_MCAST_PROMISC); be_cmd_rx_filter(adapter, IFF_PROMISC, OFF); } @@ -1222,10 +1216,8 @@ static void be_set_rx_mode(struct net_device *netdev) /* Enable multicast promisc if num configured exceeds what we support */ if (netdev->flags & IFF_ALLMULTI || - netdev_mc_count(netdev) > be_max_mc(adapter)) { - be_cmd_rx_filter(adapter, IFF_ALLMULTI, ON); - goto done; - } + netdev_mc_count(netdev) > be_max_mc(adapter)) + goto set_mcast_promisc; if (netdev_uc_count(netdev) != adapter->uc_macs) { struct netdev_hw_addr *ha; @@ -1251,13 +1243,22 @@ static void be_set_rx_mode(struct net_device *netdev) } status = be_cmd_rx_filter(adapter, IFF_MULTICAST, ON); - - /* Set to MCAST promisc mode if setting MULTICAST address fails */ - if (status) { - dev_info(&adapter->pdev->dev, "Exhausted multicast HW filters.\n"); - dev_info(&adapter->pdev->dev, "Disabling HW multicast filtering.\n"); - be_cmd_rx_filter(adapter, IFF_ALLMULTI, ON); + if (!status) { + if (adapter->flags & BE_FLAGS_MCAST_PROMISC) + adapter->flags &= ~BE_FLAGS_MCAST_PROMISC; + goto done; } + +set_mcast_promisc: + if (adapter->flags & BE_FLAGS_MCAST_PROMISC) + return; + + /* Set to MCAST promisc mode if setting MULTICAST address fails + * or if num configured exceeds what we support + */ + status = be_cmd_rx_filter(adapter, IFF_ALLMULTI, ON); + if (!status) + adapter->flags |= BE_FLAGS_MCAST_PROMISC; done: return; } @@ -1287,7 +1288,7 @@ static int be_set_vf_mac(struct net_device *netdev, int vf, u8 *mac) if (status) dev_err(&adapter->pdev->dev, "MAC %pM set on VF %d Failed\n", - mac, vf); + mac, vf); else memcpy(vf_cfg->mac_addr, mac, ETH_ALEN); @@ -1295,7 +1296,7 @@ static int be_set_vf_mac(struct net_device *netdev, int vf, u8 *mac) } static int be_get_vf_config(struct net_device *netdev, int vf, - struct ifla_vf_info *vi) + struct ifla_vf_info *vi) { struct be_adapter *adapter = netdev_priv(netdev); struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf]; @@ -1307,7 +1308,8 @@ static int be_get_vf_config(struct net_device *netdev, int vf, return -EINVAL; vi->vf = vf; - vi->tx_rate = vf_cfg->tx_rate; + vi->max_tx_rate = vf_cfg->tx_rate; + vi->min_tx_rate = 0; vi->vlan = vf_cfg->vlan_tag & VLAN_VID_MASK; vi->qos = vf_cfg->vlan_tag >> VLAN_PRIO_SHIFT; memcpy(&vi->mac, vf_cfg->mac_addr, ETH_ALEN); @@ -1316,8 +1318,7 @@ static int be_get_vf_config(struct net_device *netdev, int vf, return 0; } -static int be_set_vf_vlan(struct net_device *netdev, - int vf, u16 vlan, u8 qos) +static int be_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos) { struct be_adapter *adapter = netdev_priv(netdev); struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf]; @@ -1348,11 +1349,14 @@ static int be_set_vf_vlan(struct net_device *netdev, return status; } -static int be_set_vf_tx_rate(struct net_device *netdev, - int vf, int rate) +static int be_set_vf_tx_rate(struct net_device *netdev, int vf, + int min_tx_rate, int max_tx_rate) { struct be_adapter *adapter = netdev_priv(netdev); - int status = 0; + struct device *dev = &adapter->pdev->dev; + int percent_rate, status = 0; + u16 link_speed = 0; + u8 link_status; if (!sriov_enabled(adapter)) return -EPERM; @@ -1360,18 +1364,50 @@ static int be_set_vf_tx_rate(struct net_device *netdev, if (vf >= adapter->num_vfs) return -EINVAL; - if (rate < 100 || rate > 10000) { - dev_err(&adapter->pdev->dev, - "tx rate must be between 100 and 10000 Mbps\n"); + if (min_tx_rate) return -EINVAL; + + if (!max_tx_rate) + goto config_qos; + + status = be_cmd_link_status_query(adapter, &link_speed, + &link_status, 0); + if (status) + goto err; + + if (!link_status) { + dev_err(dev, "TX-rate setting not allowed when link is down\n"); + status = -EPERM; + goto err; + } + + if (max_tx_rate < 100 || max_tx_rate > link_speed) { + dev_err(dev, "TX-rate must be between 100 and %d Mbps\n", + link_speed); + status = -EINVAL; + goto err; + } + + /* On Skyhawk the QOS setting must be done only as a % value */ + percent_rate = link_speed / 100; + if (skyhawk_chip(adapter) && (max_tx_rate % percent_rate)) { + dev_err(dev, "TX-rate must be a multiple of %d Mbps\n", + percent_rate); + status = -EINVAL; + goto err; } - status = be_cmd_config_qos(adapter, rate / 10, vf + 1); +config_qos: + status = be_cmd_config_qos(adapter, max_tx_rate, link_speed, vf + 1); if (status) - dev_err(&adapter->pdev->dev, - "tx rate %d on VF %d failed\n", rate, vf); - else - adapter->vf_cfg[vf].tx_rate = rate; + goto err; + + adapter->vf_cfg[vf].tx_rate = max_tx_rate; + return 0; + +err: + dev_err(dev, "TX-rate setting of %dMbps on VF%d failed\n", + max_tx_rate, vf); return status; } static int be_set_vf_link_state(struct net_device *netdev, int vf, @@ -1469,7 +1505,7 @@ modify_eqd: } static void be_rx_stats_update(struct be_rx_obj *rxo, - struct be_rx_compl_info *rxcp) + struct be_rx_compl_info *rxcp) { struct be_rx_stats *stats = rx_stats(rxo); @@ -1566,7 +1602,8 @@ static void skb_fill_rx_data(struct be_rx_obj *rxo, struct sk_buff *skb, skb_frag_set_page(skb, 0, page_info->page); skb_shinfo(skb)->frags[0].page_offset = page_info->page_offset + hdr_len; - skb_frag_size_set(&skb_shinfo(skb)->frags[0], curr_frag_len - hdr_len); + skb_frag_size_set(&skb_shinfo(skb)->frags[0], + curr_frag_len - hdr_len); skb->data_len = curr_frag_len - hdr_len; skb->truesize += rx_frag_size; skb->tail += hdr_len; @@ -1725,8 +1762,8 @@ static void be_parse_rx_compl_v1(struct be_eth_rx_compl *compl, if (rxcp->vlanf) { rxcp->qnq = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, qnq, compl); - rxcp->vlan_tag = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, vlan_tag, - compl); + rxcp->vlan_tag = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, + vlan_tag, compl); } rxcp->port = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, port, compl); rxcp->tunneled = @@ -1757,8 +1794,8 @@ static void be_parse_rx_compl_v0(struct be_eth_rx_compl *compl, if (rxcp->vlanf) { rxcp->qnq = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, qnq, compl); - rxcp->vlan_tag = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, vlan_tag, - compl); + rxcp->vlan_tag = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, + vlan_tag, compl); } rxcp->port = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, port, compl); rxcp->ip_frag = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, @@ -1799,7 +1836,7 @@ static struct be_rx_compl_info *be_rx_compl_get(struct be_rx_obj *rxo) rxcp->vlan_tag = swab16(rxcp->vlan_tag); if (adapter->pvid == (rxcp->vlan_tag & VLAN_VID_MASK) && - !adapter->vlan_tag[rxcp->vlan_tag]) + !test_bit(rxcp->vlan_tag, adapter->vids)) rxcp->vlanf = 0; } @@ -1915,7 +1952,7 @@ static struct be_eth_tx_compl *be_tx_compl_get(struct be_queue_info *tx_cq) } static u16 be_tx_compl_process(struct be_adapter *adapter, - struct be_tx_obj *txo, u16 last_index) + struct be_tx_obj *txo, u16 last_index) { struct be_queue_info *txq = &txo->q; struct be_eth_wrb *wrb; @@ -2122,7 +2159,7 @@ static int be_evt_queues_create(struct be_adapter *adapter) eq = &eqo->q; rc = be_queue_alloc(adapter, eq, EVNT_Q_LEN, - sizeof(struct be_eq_entry)); + sizeof(struct be_eq_entry)); if (rc) return rc; @@ -2155,7 +2192,7 @@ static int be_mcc_queues_create(struct be_adapter *adapter) cq = &adapter->mcc_obj.cq; if (be_queue_alloc(adapter, cq, MCC_CQ_LEN, - sizeof(struct be_mcc_compl))) + sizeof(struct be_mcc_compl))) goto err; /* Use the default EQ for MCC completions */ @@ -2275,7 +2312,7 @@ static int be_rx_cqs_create(struct be_adapter *adapter) rxo->adapter = adapter; cq = &rxo->cq; rc = be_queue_alloc(adapter, cq, RX_CQ_LEN, - sizeof(struct be_eth_rx_compl)); + sizeof(struct be_eth_rx_compl)); if (rc) return rc; @@ -2339,7 +2376,7 @@ static inline bool do_gro(struct be_rx_compl_info *rxcp) } static int be_process_rx(struct be_rx_obj *rxo, struct napi_struct *napi, - int budget, int polling) + int budget, int polling) { struct be_adapter *adapter = rxo->adapter; struct be_queue_info *rx_cq = &rxo->cq; @@ -2365,7 +2402,7 @@ static int be_process_rx(struct be_rx_obj *rxo, struct napi_struct *napi, * promiscuous mode on some skews */ if (unlikely(rxcp->port != adapter->port_num && - !lancer_chip(adapter))) { + !lancer_chip(adapter))) { be_rx_compl_discard(rxo, rxcp); goto loop_continue; } @@ -2405,8 +2442,9 @@ static bool be_process_tx(struct be_adapter *adapter, struct be_tx_obj *txo, if (!txcp) break; num_wrbs += be_tx_compl_process(adapter, txo, - AMAP_GET_BITS(struct amap_eth_tx_compl, - wrb_index, txcp)); + AMAP_GET_BITS(struct + amap_eth_tx_compl, + wrb_index, txcp)); } if (work_done) { @@ -2416,7 +2454,7 @@ static bool be_process_tx(struct be_adapter *adapter, struct be_tx_obj *txo, /* As Tx wrbs have been freed up, wake up netdev queue * if it was stopped due to lack of tx wrbs. */ if (__netif_subqueue_stopped(adapter->netdev, idx) && - atomic_read(&txo->q.used) < txo->q.len / 2) { + atomic_read(&txo->q.used) < txo->q.len / 2) { netif_wake_subqueue(adapter->netdev, idx); } @@ -2510,9 +2548,9 @@ void be_detect_error(struct be_adapter *adapter) sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET); if (sliport_status & SLIPORT_STATUS_ERR_MASK) { sliport_err1 = ioread32(adapter->db + - SLIPORT_ERROR1_OFFSET); + SLIPORT_ERROR1_OFFSET); sliport_err2 = ioread32(adapter->db + - SLIPORT_ERROR2_OFFSET); + SLIPORT_ERROR2_OFFSET); adapter->hw_error = true; /* Do not log error messages if its a FW reset */ if (sliport_err1 == SLIPORT_ERROR_FW_RESET1 && @@ -2531,13 +2569,13 @@ void be_detect_error(struct be_adapter *adapter) } } else { pci_read_config_dword(adapter->pdev, - PCICFG_UE_STATUS_LOW, &ue_lo); + PCICFG_UE_STATUS_LOW, &ue_lo); pci_read_config_dword(adapter->pdev, - PCICFG_UE_STATUS_HIGH, &ue_hi); + PCICFG_UE_STATUS_HIGH, &ue_hi); pci_read_config_dword(adapter->pdev, - PCICFG_UE_STATUS_LOW_MASK, &ue_lo_mask); + PCICFG_UE_STATUS_LOW_MASK, &ue_lo_mask); pci_read_config_dword(adapter->pdev, - PCICFG_UE_STATUS_HI_MASK, &ue_hi_mask); + PCICFG_UE_STATUS_HI_MASK, &ue_hi_mask); ue_lo = (ue_lo & ~ue_lo_mask); ue_hi = (ue_hi & ~ue_hi_mask); @@ -2624,7 +2662,7 @@ fail: } static inline int be_msix_vec_get(struct be_adapter *adapter, - struct be_eq_obj *eqo) + struct be_eq_obj *eqo) { return adapter->msix_entries[eqo->msix_idx].vector; } @@ -2648,7 +2686,7 @@ err_msix: for (i--, eqo = &adapter->eq_obj[i]; i >= 0; i--, eqo--) free_irq(be_msix_vec_get(adapter, eqo), eqo); dev_warn(&adapter->pdev->dev, "MSIX Request IRQ failed - err %d\n", - status); + status); be_msix_disable(adapter); return status; } @@ -2774,7 +2812,8 @@ static int be_rx_qs_create(struct be_adapter *adapter) { struct be_rx_obj *rxo; int rc, i, j; - u8 rsstable[128]; + u8 rss_hkey[RSS_HASH_KEY_LEN]; + struct rss_info *rss = &adapter->rss_info; for_all_rx_queues(adapter, rxo, i) { rc = be_queue_alloc(adapter, &rxo->q, RX_Q_LEN, @@ -2799,31 +2838,36 @@ static int be_rx_qs_create(struct be_adapter *adapter) } if (be_multi_rxq(adapter)) { - for (j = 0; j < 128; j += adapter->num_rx_qs - 1) { + for (j = 0; j < RSS_INDIR_TABLE_LEN; + j += adapter->num_rx_qs - 1) { for_all_rss_queues(adapter, rxo, i) { - if ((j + i) >= 128) + if ((j + i) >= RSS_INDIR_TABLE_LEN) break; - rsstable[j + i] = rxo->rss_id; + rss->rsstable[j + i] = rxo->rss_id; + rss->rss_queue[j + i] = i; } } - adapter->rss_flags = RSS_ENABLE_TCP_IPV4 | RSS_ENABLE_IPV4 | - RSS_ENABLE_TCP_IPV6 | RSS_ENABLE_IPV6; + rss->rss_flags = RSS_ENABLE_TCP_IPV4 | RSS_ENABLE_IPV4 | + RSS_ENABLE_TCP_IPV6 | RSS_ENABLE_IPV6; if (!BEx_chip(adapter)) - adapter->rss_flags |= RSS_ENABLE_UDP_IPV4 | - RSS_ENABLE_UDP_IPV6; + rss->rss_flags |= RSS_ENABLE_UDP_IPV4 | + RSS_ENABLE_UDP_IPV6; } else { /* Disable RSS, if only default RX Q is created */ - adapter->rss_flags = RSS_ENABLE_NONE; + rss->rss_flags = RSS_ENABLE_NONE; } - rc = be_cmd_rss_config(adapter, rsstable, adapter->rss_flags, - 128); + get_random_bytes(rss_hkey, RSS_HASH_KEY_LEN); + rc = be_cmd_rss_config(adapter, rss->rsstable, rss->rss_flags, + 128, rss_hkey); if (rc) { - adapter->rss_flags = RSS_ENABLE_NONE; + rss->rss_flags = RSS_ENABLE_NONE; return rc; } + memcpy(rss->rss_hkey, rss_hkey, RSS_HASH_KEY_LEN); + /* First time posting */ for_all_rx_queues(adapter, rxo, i) be_post_rx_frags(rxo, GFP_KERNEL); @@ -2896,7 +2940,8 @@ static int be_setup_wol(struct be_adapter *adapter, bool enable) if (enable) { status = pci_write_config_dword(adapter->pdev, - PCICFG_PM_CONTROL_OFFSET, PCICFG_PM_CONTROL_MASK); + PCICFG_PM_CONTROL_OFFSET, + PCICFG_PM_CONTROL_MASK); if (status) { dev_err(&adapter->pdev->dev, "Could not enable Wake-on-lan\n"); @@ -2905,7 +2950,8 @@ static int be_setup_wol(struct be_adapter *adapter, bool enable) return status; } status = be_cmd_enable_magic_wol(adapter, - adapter->netdev->dev_addr, &cmd); + adapter->netdev->dev_addr, + &cmd); pci_enable_wake(adapter->pdev, PCI_D3hot, 1); pci_enable_wake(adapter->pdev, PCI_D3cold, 1); } else { @@ -2944,7 +2990,8 @@ static int be_vf_eth_addr_config(struct be_adapter *adapter) if (status) dev_err(&adapter->pdev->dev, - "Mac address assignment failed for VF %d\n", vf); + "Mac address assignment failed for VF %d\n", + vf); else memcpy(vf_cfg->mac_addr, mac, ETH_ALEN); @@ -3086,9 +3133,11 @@ static int be_vfs_if_create(struct be_adapter *adapter) /* If a FW profile exists, then cap_flags are updated */ en_flags = cap_flags & (BE_IF_FLAGS_UNTAGGED | - BE_IF_FLAGS_BROADCAST | BE_IF_FLAGS_MULTICAST); - status = be_cmd_if_create(adapter, cap_flags, en_flags, - &vf_cfg->if_handle, vf + 1); + BE_IF_FLAGS_BROADCAST | + BE_IF_FLAGS_MULTICAST); + status = + be_cmd_if_create(adapter, cap_flags, en_flags, + &vf_cfg->if_handle, vf + 1); if (status) goto err; } @@ -3119,7 +3168,6 @@ static int be_vf_setup(struct be_adapter *adapter) struct be_vf_cfg *vf_cfg; int status, old_vfs, vf; u32 privileges; - u16 lnk_speed; old_vfs = pci_num_vf(adapter->pdev); if (old_vfs) { @@ -3175,16 +3223,9 @@ static int be_vf_setup(struct be_adapter *adapter) vf); } - /* BE3 FW, by default, caps VF TX-rate to 100mbps. - * Allow full available bandwidth - */ - if (BE3_chip(adapter) && !old_vfs) - be_cmd_config_qos(adapter, 1000, vf + 1); - - status = be_cmd_link_status_query(adapter, &lnk_speed, - NULL, vf + 1); - if (!status) - vf_cfg->tx_rate = lnk_speed; + /* Allow full available bandwidth */ + if (!old_vfs) + be_cmd_config_qos(adapter, 0, 0, vf + 1); if (!old_vfs) { be_cmd_enable_vf(adapter, vf + 1); @@ -3213,9 +3254,9 @@ err: static u8 be_convert_mc_type(u32 function_mode) { - if (function_mode & VNIC_MODE && function_mode & FLEX10_MODE) + if (function_mode & VNIC_MODE && function_mode & QNQ_MODE) return vNIC1; - else if (function_mode & FLEX10_MODE) + else if (function_mode & QNQ_MODE) return FLEX10; else if (function_mode & VNIC_MODE) return vNIC2; @@ -3590,35 +3631,7 @@ static void be_netpoll(struct net_device *netdev) } #endif -#define FW_FILE_HDR_SIGN "ServerEngines Corp. " -static char flash_cookie[2][16] = {"*** SE FLAS", "H DIRECTORY *** "}; - -static bool be_flash_redboot(struct be_adapter *adapter, - const u8 *p, u32 img_start, int image_size, - int hdr_size) -{ - u32 crc_offset; - u8 flashed_crc[4]; - int status; - - crc_offset = hdr_size + img_start + image_size - 4; - - p += crc_offset; - - status = be_cmd_get_flash_crc(adapter, flashed_crc, - (image_size - 4)); - if (status) { - dev_err(&adapter->pdev->dev, - "could not get crc from flash, not flashing redboot\n"); - return false; - } - - /*update redboot only if crc does not match*/ - if (!memcmp(flashed_crc, p, 4)) - return false; - else - return true; -} +static char flash_cookie[2][16] = {"*** SE FLAS", "H DIRECTORY *** "}; static bool phy_flashing_required(struct be_adapter *adapter) { @@ -3649,8 +3662,8 @@ static bool is_comp_in_ufi(struct be_adapter *adapter, } static struct flash_section_info *get_fsec_info(struct be_adapter *adapter, - int header_size, - const struct firmware *fw) + int header_size, + const struct firmware *fw) { struct flash_section_info *fsec = NULL; const u8 *p = fw->data; @@ -3665,12 +3678,35 @@ static struct flash_section_info *get_fsec_info(struct be_adapter *adapter, return NULL; } +static int be_check_flash_crc(struct be_adapter *adapter, const u8 *p, + u32 img_offset, u32 img_size, int hdr_size, + u16 img_optype, bool *crc_match) +{ + u32 crc_offset; + int status; + u8 crc[4]; + + status = be_cmd_get_flash_crc(adapter, crc, img_optype, img_size - 4); + if (status) + return status; + + crc_offset = hdr_size + img_offset + img_size - 4; + + /* Skip flashing, if crc of flashed region matches */ + if (!memcmp(crc, p + crc_offset, 4)) + *crc_match = true; + else + *crc_match = false; + + return status; +} + static int be_flash(struct be_adapter *adapter, const u8 *img, - struct be_dma_mem *flash_cmd, int optype, int img_size) + struct be_dma_mem *flash_cmd, int optype, int img_size) { - u32 total_bytes = 0, flash_op, num_bytes = 0; - int status = 0; struct be_cmd_write_flashrom *req = flash_cmd->va; + u32 total_bytes, flash_op, num_bytes; + int status; total_bytes = img_size; while (total_bytes) { @@ -3693,32 +3729,28 @@ static int be_flash(struct be_adapter *adapter, const u8 *img, memcpy(req->data_buf, img, num_bytes); img += num_bytes; status = be_cmd_write_flashrom(adapter, flash_cmd, optype, - flash_op, num_bytes); - if (status) { - if (status == ILLEGAL_IOCTL_REQ && - optype == OPTYPE_PHY_FW) - break; - dev_err(&adapter->pdev->dev, - "cmd to write to flash rom failed.\n"); + flash_op, num_bytes); + if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST && + optype == OPTYPE_PHY_FW) + break; + else if (status) return status; - } } return 0; } /* For BE2, BE3 and BE3-R */ static int be_flash_BEx(struct be_adapter *adapter, - const struct firmware *fw, - struct be_dma_mem *flash_cmd, - int num_of_images) - + const struct firmware *fw, + struct be_dma_mem *flash_cmd, int num_of_images) { - int status = 0, i, filehdr_size = 0; int img_hdrs_size = (num_of_images * sizeof(struct image_hdr)); - const u8 *p = fw->data; - const struct flash_comp *pflashcomp; - int num_comp, redboot; + struct device *dev = &adapter->pdev->dev; struct flash_section_info *fsec = NULL; + int status, i, filehdr_size, num_comp; + const struct flash_comp *pflashcomp; + bool crc_match; + const u8 *p; struct flash_comp gen3_flash_types[] = { { FLASH_iSCSI_PRIMARY_IMAGE_START_g3, OPTYPE_ISCSI_ACTIVE, @@ -3775,8 +3807,7 @@ static int be_flash_BEx(struct be_adapter *adapter, /* Get flash section info*/ fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw); if (!fsec) { - dev_err(&adapter->pdev->dev, - "Invalid Cookie. UFI corrupted ?\n"); + dev_err(dev, "Invalid Cookie. FW image may be corrupted\n"); return -1; } for (i = 0; i < num_comp; i++) { @@ -3792,23 +3823,32 @@ static int be_flash_BEx(struct be_adapter *adapter, continue; if (pflashcomp[i].optype == OPTYPE_REDBOOT) { - redboot = be_flash_redboot(adapter, fw->data, - pflashcomp[i].offset, pflashcomp[i].size, - filehdr_size + img_hdrs_size); - if (!redboot) + status = be_check_flash_crc(adapter, fw->data, + pflashcomp[i].offset, + pflashcomp[i].size, + filehdr_size + + img_hdrs_size, + OPTYPE_REDBOOT, &crc_match); + if (status) { + dev_err(dev, + "Could not get CRC for 0x%x region\n", + pflashcomp[i].optype); + continue; + } + + if (crc_match) continue; } - p = fw->data; - p += filehdr_size + pflashcomp[i].offset + img_hdrs_size; + p = fw->data + filehdr_size + pflashcomp[i].offset + + img_hdrs_size; if (p + pflashcomp[i].size > fw->data + fw->size) return -1; status = be_flash(adapter, p, flash_cmd, pflashcomp[i].optype, - pflashcomp[i].size); + pflashcomp[i].size); if (status) { - dev_err(&adapter->pdev->dev, - "Flashing section type %d failed.\n", + dev_err(dev, "Flashing section type 0x%x failed\n", pflashcomp[i].img_type); return status; } @@ -3816,80 +3856,142 @@ static int be_flash_BEx(struct be_adapter *adapter, return 0; } +static u16 be_get_img_optype(struct flash_section_entry fsec_entry) +{ + u32 img_type = le32_to_cpu(fsec_entry.type); + u16 img_optype = le16_to_cpu(fsec_entry.optype); + + if (img_optype != 0xFFFF) + return img_optype; + + switch (img_type) { + case IMAGE_FIRMWARE_iSCSI: + img_optype = OPTYPE_ISCSI_ACTIVE; + break; + case IMAGE_BOOT_CODE: + img_optype = OPTYPE_REDBOOT; + break; + case IMAGE_OPTION_ROM_ISCSI: + img_optype = OPTYPE_BIOS; + break; + case IMAGE_OPTION_ROM_PXE: + img_optype = OPTYPE_PXE_BIOS; + break; + case IMAGE_OPTION_ROM_FCoE: + img_optype = OPTYPE_FCOE_BIOS; + break; + case IMAGE_FIRMWARE_BACKUP_iSCSI: + img_optype = OPTYPE_ISCSI_BACKUP; + break; + case IMAGE_NCSI: + img_optype = OPTYPE_NCSI_FW; + break; + case IMAGE_FLASHISM_JUMPVECTOR: + img_optype = OPTYPE_FLASHISM_JUMPVECTOR; + break; + case IMAGE_FIRMWARE_PHY: + img_optype = OPTYPE_SH_PHY_FW; + break; + case IMAGE_REDBOOT_DIR: + img_optype = OPTYPE_REDBOOT_DIR; + break; + case IMAGE_REDBOOT_CONFIG: + img_optype = OPTYPE_REDBOOT_CONFIG; + break; + case IMAGE_UFI_DIR: + img_optype = OPTYPE_UFI_DIR; + break; + default: + break; + } + + return img_optype; +} + static int be_flash_skyhawk(struct be_adapter *adapter, - const struct firmware *fw, - struct be_dma_mem *flash_cmd, int num_of_images) + const struct firmware *fw, + struct be_dma_mem *flash_cmd, int num_of_images) { - int status = 0, i, filehdr_size = 0; - int img_offset, img_size, img_optype, redboot; int img_hdrs_size = num_of_images * sizeof(struct image_hdr); - const u8 *p = fw->data; + struct device *dev = &adapter->pdev->dev; struct flash_section_info *fsec = NULL; + u32 img_offset, img_size, img_type; + int status, i, filehdr_size; + bool crc_match, old_fw_img; + u16 img_optype; + const u8 *p; filehdr_size = sizeof(struct flash_file_hdr_g3); fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw); if (!fsec) { - dev_err(&adapter->pdev->dev, - "Invalid Cookie. UFI corrupted ?\n"); + dev_err(dev, "Invalid Cookie. FW image may be corrupted\n"); return -1; } for (i = 0; i < le32_to_cpu(fsec->fsec_hdr.num_images); i++) { img_offset = le32_to_cpu(fsec->fsec_entry[i].offset); img_size = le32_to_cpu(fsec->fsec_entry[i].pad_size); + img_type = le32_to_cpu(fsec->fsec_entry[i].type); + img_optype = be_get_img_optype(fsec->fsec_entry[i]); + old_fw_img = fsec->fsec_entry[i].optype == 0xFFFF; - switch (le32_to_cpu(fsec->fsec_entry[i].type)) { - case IMAGE_FIRMWARE_iSCSI: - img_optype = OPTYPE_ISCSI_ACTIVE; - break; - case IMAGE_BOOT_CODE: - img_optype = OPTYPE_REDBOOT; - break; - case IMAGE_OPTION_ROM_ISCSI: - img_optype = OPTYPE_BIOS; - break; - case IMAGE_OPTION_ROM_PXE: - img_optype = OPTYPE_PXE_BIOS; - break; - case IMAGE_OPTION_ROM_FCoE: - img_optype = OPTYPE_FCOE_BIOS; - break; - case IMAGE_FIRMWARE_BACKUP_iSCSI: - img_optype = OPTYPE_ISCSI_BACKUP; - break; - case IMAGE_NCSI: - img_optype = OPTYPE_NCSI_FW; - break; - default: + if (img_optype == 0xFFFF) continue; + /* Don't bother verifying CRC if an old FW image is being + * flashed + */ + if (old_fw_img) + goto flash; + + status = be_check_flash_crc(adapter, fw->data, img_offset, + img_size, filehdr_size + + img_hdrs_size, img_optype, + &crc_match); + /* The current FW image on the card does not recognize the new + * FLASH op_type. The FW download is partially complete. + * Reboot the server now to enable FW image to recognize the + * new FLASH op_type. To complete the remaining process, + * download the same FW again after the reboot. + */ + if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST || + base_status(status) == MCC_STATUS_ILLEGAL_FIELD) { + dev_err(dev, "Flash incomplete. Reset the server\n"); + dev_err(dev, "Download FW image again after reset\n"); + return -EAGAIN; + } else if (status) { + dev_err(dev, "Could not get CRC for 0x%x region\n", + img_optype); + return -EFAULT; } - if (img_optype == OPTYPE_REDBOOT) { - redboot = be_flash_redboot(adapter, fw->data, - img_offset, img_size, - filehdr_size + img_hdrs_size); - if (!redboot) - continue; - } + if (crc_match) + continue; - p = fw->data; - p += filehdr_size + img_offset + img_hdrs_size; +flash: + p = fw->data + filehdr_size + img_offset + img_hdrs_size; if (p + img_size > fw->data + fw->size) return -1; status = be_flash(adapter, p, flash_cmd, img_optype, img_size); - if (status) { - dev_err(&adapter->pdev->dev, - "Flashing section type %d failed.\n", - fsec->fsec_entry[i].type); - return status; + /* For old FW images ignore ILLEGAL_FIELD error or errors on + * UFI_DIR region + */ + if (old_fw_img && + (base_status(status) == MCC_STATUS_ILLEGAL_FIELD || + (img_optype == OPTYPE_UFI_DIR && + base_status(status) == MCC_STATUS_FAILED))) { + continue; + } else if (status) { + dev_err(dev, "Flashing section type 0x%x failed\n", + img_type); + return -EFAULT; } } return 0; } static int lancer_fw_download(struct be_adapter *adapter, - const struct firmware *fw) + const struct firmware *fw) { #define LANCER_FW_DOWNLOAD_CHUNK (32 * 1024) #define LANCER_FW_DOWNLOAD_LOCATION "/prg" @@ -3955,7 +4057,7 @@ static int lancer_fw_download(struct be_adapter *adapter, } dma_free_coherent(&adapter->pdev->dev, flash_cmd.size, flash_cmd.va, - flash_cmd.dma); + flash_cmd.dma); if (status) { dev_err(&adapter->pdev->dev, "Firmware load error. " @@ -3976,9 +4078,8 @@ static int lancer_fw_download(struct be_adapter *adapter, goto lancer_fw_exit; } } else if (change_status != LANCER_NO_RESET_NEEDED) { - dev_err(&adapter->pdev->dev, - "System reboot required for new FW" - " to be active\n"); + dev_err(&adapter->pdev->dev, + "System reboot required for new FW to be active\n"); } dev_info(&adapter->pdev->dev, "Firmware flashed successfully\n"); @@ -4042,7 +4143,7 @@ static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw) switch (ufi_type) { case UFI_TYPE4: status = be_flash_skyhawk(adapter, fw, - &flash_cmd, num_imgs); + &flash_cmd, num_imgs); break; case UFI_TYPE3R: status = be_flash_BEx(adapter, fw, &flash_cmd, @@ -4112,8 +4213,7 @@ fw_exit: return status; } -static int be_ndo_bridge_setlink(struct net_device *dev, - struct nlmsghdr *nlh) +static int be_ndo_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh) { struct be_adapter *adapter = netdev_priv(dev); struct nlattr *attr, *br_spec; @@ -4155,8 +4255,7 @@ err: } static int be_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq, - struct net_device *dev, - u32 filter_mask) + struct net_device *dev, u32 filter_mask) { struct be_adapter *adapter = netdev_priv(dev); int status = 0; @@ -4254,7 +4353,7 @@ static const struct net_device_ops be_netdev_ops = { .ndo_vlan_rx_kill_vid = be_vlan_rem_vid, .ndo_set_vf_mac = be_set_vf_mac, .ndo_set_vf_vlan = be_set_vf_vlan, - .ndo_set_vf_tx_rate = be_set_vf_tx_rate, + .ndo_set_vf_rate = be_set_vf_tx_rate, .ndo_get_vf_config = be_get_vf_config, .ndo_set_vf_link_state = be_set_vf_link_state, #ifdef CONFIG_NET_POLL_CONTROLLER @@ -4301,7 +4400,7 @@ static void be_netdev_init(struct net_device *netdev) netdev->netdev_ops = &be_netdev_ops; - SET_ETHTOOL_OPS(netdev, &be_ethtool_ops); + netdev->ethtool_ops = &be_ethtool_ops; } static void be_unmap_pci_bars(struct be_adapter *adapter) @@ -4870,7 +4969,7 @@ static void be_shutdown(struct pci_dev *pdev) } static pci_ers_result_t be_eeh_err_detected(struct pci_dev *pdev, - pci_channel_state_t state) + pci_channel_state_t state) { struct be_adapter *adapter = pci_get_drvdata(pdev); struct net_device *netdev = adapter->netdev; |