static void efx_ef10_sriov_free_vf_vports(struct efx_nic *efx) { struct efx_ef10_nic_data *nic_data = efx->nic_data; int i; if (!nic_data->vf) return; for (i = 0; i < efx->vf_count; i++) { struct ef10_vf *vf = nic_data->vf + i; #if !defined(EFX_USE_KCOMPAT) || defined(EFX_HAVE_PCI_DEV_FLAGS_ASSIGNED) /* If VF is assigned, do not free the vport */ if (vf->pci_dev && vf->pci_dev->dev_flags & PCI_DEV_FLAGS_ASSIGNED) continue; #endif if (vf->vport_assigned) { efx_ef10_evb_port_assign(efx, EVB_PORT_ID_NULL, i); vf->vport_assigned = 0; } if (!is_zero_ether_addr(vf->mac)) { efx_ef10_vport_del_mac(efx, vf->vport_id, vf->mac); eth_zero_addr(vf->mac); } if (vf->vport_id) { efx_ef10_vport_free(efx, vf->vport_id); vf->vport_id = 0; } vf->efx = NULL; } }
/* * This function resets the connection state. * * The function is invoked after receiving a disconnect event from firmware, * and performs the following actions - * - Set media status to disconnected * - Clean up Tx and Rx packets * - Resets SNR/NF/RSSI value in driver * - Resets security configurations in driver * - Enables auto data rate * - Saves the previous SSID and BSSID so that they can * be used for re-association, if required * - Erases current SSID and BSSID information * - Sends a disconnect event to upper layers/applications. */ void mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason_code, bool from_ap) { struct mwifiex_adapter *adapter = priv->adapter; if (!priv->media_connected) return; mwifiex_dbg(adapter, INFO, "info: handles disconnect event\n"); priv->media_connected = false; priv->scan_block = false; priv->port_open = false; if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) && ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info)) { mwifiex_disable_all_tdls_links(priv); if (priv->adapter->auto_tdls) mwifiex_clean_auto_tdls(priv); } /* Free Tx and Rx packets, report disconnect to upper layer */ mwifiex_clean_txrx(priv); /* Reset SNR/NF/RSSI values */ priv->data_rssi_last = 0; priv->data_nf_last = 0; priv->data_rssi_avg = 0; priv->data_nf_avg = 0; priv->bcn_rssi_last = 0; priv->bcn_nf_last = 0; priv->bcn_rssi_avg = 0; priv->bcn_nf_avg = 0; priv->rxpd_rate = 0; priv->rxpd_htinfo = 0; priv->sec_info.wpa_enabled = false; priv->sec_info.wpa2_enabled = false; priv->wpa_ie_len = 0; priv->sec_info.wapi_enabled = false; priv->wapi_ie_len = 0; priv->sec_info.wapi_key_on = false; priv->sec_info.encryption_mode = 0; /* Enable auto data rate */ priv->is_data_rate_auto = true; priv->data_rate = 0; priv->assoc_resp_ht_param = 0; priv->ht_param_present = false; if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA || GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) && priv->hist_data) mwifiex_hist_data_reset(priv); if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { priv->adhoc_state = ADHOC_IDLE; priv->adhoc_is_link_sensed = false; } /* * Memorize the previous SSID and BSSID so * it could be used for re-assoc */ mwifiex_dbg(adapter, INFO, "info: previous SSID=%s, SSID len=%u\n", priv->prev_ssid.ssid, priv->prev_ssid.ssid_len); mwifiex_dbg(adapter, INFO, "info: current SSID=%s, SSID len=%u\n", priv->curr_bss_params.bss_descriptor.ssid.ssid, priv->curr_bss_params.bss_descriptor.ssid.ssid_len); memcpy(&priv->prev_ssid, &priv->curr_bss_params.bss_descriptor.ssid, sizeof(struct cfg80211_ssid)); memcpy(priv->prev_bssid, priv->curr_bss_params.bss_descriptor.mac_address, ETH_ALEN); /* Need to erase the current SSID and BSSID info */ memset(&priv->curr_bss_params, 0x00, sizeof(priv->curr_bss_params)); adapter->tx_lock_flag = false; adapter->pps_uapsd_mode = false; if (test_bit(MWIFIEX_IS_CMD_TIMEDOUT, &adapter->work_flags) && adapter->curr_cmd) return; priv->media_connected = false; mwifiex_dbg(adapter, MSG, "info: successfully disconnected from %pM: reason code %d\n", priv->cfg_bssid, reason_code); if (priv->bss_mode == NL80211_IFTYPE_STATION || priv->bss_mode == NL80211_IFTYPE_P2P_CLIENT) { cfg80211_disconnected(priv->netdev, reason_code, NULL, 0, !from_ap, GFP_KERNEL); } eth_zero_addr(priv->cfg_bssid); mwifiex_stop_net_dev_queue(priv->netdev, adapter); if (netif_carrier_ok(priv->netdev)) netif_carrier_off(priv->netdev); if (!ISSUPP_FIRMWARE_SUPPLICANT(priv->adapter->fw_cap_info)) return; mwifiex_send_cmd(priv, HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG, HostCmd_ACT_GEN_REMOVE, 0, NULL, false); }
static int rtl_op_set_key( struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct ieee80211_key_conf *key ) { struct rtl_priv *rtlpriv = rtl_priv( hw ); struct rtl_mac *mac = rtl_mac( rtl_priv( hw ) ); u8 key_type = NO_ENCRYPTION; u8 key_idx; bool group_key = false; bool wep_only = false; int err = 0; u8 mac_addr[ETH_ALEN]; u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; if ( rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec ) { RT_TRACE( rtlpriv, COMP_ERR, DBG_WARNING, "not open hw encryption\n" ); return -ENOSPC; /*User disabled HW-crypto */ } /* To support IBSS, use sw-crypto for GTK */ if ( ( ( vif->type == NL80211_IFTYPE_ADHOC ) || ( vif->type == NL80211_IFTYPE_MESH_POINT ) ) && !( key->flags & IEEE80211_KEY_FLAG_PAIRWISE ) ) return -ENOSPC; RT_TRACE( rtlpriv, COMP_SEC, DBG_DMESG, "%s hardware based encryption for keyidx: %d, mac: %pM\n", cmd == SET_KEY ? "Using" : "Disabling", key->keyidx, sta ? sta->addr : bcast_addr ); rtlpriv->sec.being_setkey = true; rtl_ips_nic_on( hw ); mutex_lock( &rtlpriv->locks.conf_mutex ); /* <1> get encryption alg */ switch ( key->cipher ) { case WLAN_CIPHER_SUITE_WEP40: key_type = WEP40_ENCRYPTION; RT_TRACE( rtlpriv, COMP_SEC, DBG_DMESG, "alg:WEP40\n" ); break; case WLAN_CIPHER_SUITE_WEP104: RT_TRACE( rtlpriv, COMP_SEC, DBG_DMESG, "alg:WEP104\n" ); key_type = WEP104_ENCRYPTION; break; case WLAN_CIPHER_SUITE_TKIP: key_type = TKIP_ENCRYPTION; RT_TRACE( rtlpriv, COMP_SEC, DBG_DMESG, "alg:TKIP\n" ); break; case WLAN_CIPHER_SUITE_CCMP: key_type = AESCCMP_ENCRYPTION; RT_TRACE( rtlpriv, COMP_SEC, DBG_DMESG, "alg:CCMP\n" ); break; case WLAN_CIPHER_SUITE_AES_CMAC: /*HW doesn't support CMAC encryption, use software CMAC */ key_type = AESCMAC_ENCRYPTION; RT_TRACE( rtlpriv, COMP_SEC, DBG_DMESG, "alg:CMAC\n" ); RT_TRACE( rtlpriv, COMP_SEC, DBG_DMESG, "HW don't support CMAC encryption, use software CMAC\n" ); err = -EOPNOTSUPP; goto out_unlock; default: RT_TRACE( rtlpriv, COMP_ERR, DBG_EMERG, "alg_err:%x!!!!\n", key->cipher ); goto out_unlock; } if ( key_type == WEP40_ENCRYPTION || key_type == WEP104_ENCRYPTION || mac->opmode == NL80211_IFTYPE_ADHOC ) rtlpriv->sec.use_defaultkey = true; /* <2> get key_idx */ key_idx = ( u8 ) ( key->keyidx ); if ( key_idx > 3 ) goto out_unlock; /* <3> if pairwise key enable_hw_sec */ group_key = !( key->flags & IEEE80211_KEY_FLAG_PAIRWISE ); /* wep always be group key, but there are two conditions: * 1 ) wep only: is just for wep enc, in this condition * rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION * will be true & enable_hw_sec will be set when wep * key setting. * 2 ) wep( group ) + AES( pairwise ): some AP like cisco * may use it, in this condition enable_hw_sec will not * be set when wep key setting */ /* we must reset sec_info after lingked before set key, * or some flag will be wrong*/ if ( vif->type == NL80211_IFTYPE_AP || vif->type == NL80211_IFTYPE_MESH_POINT ) { if ( !group_key || key_type == WEP40_ENCRYPTION || key_type == WEP104_ENCRYPTION ) { if ( group_key ) wep_only = true; rtlpriv->cfg->ops->enable_hw_sec( hw ); } } else { if ( ( !group_key ) || ( mac->opmode == NL80211_IFTYPE_ADHOC ) || rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION ) { if ( rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION && ( key_type == WEP40_ENCRYPTION || key_type == WEP104_ENCRYPTION ) ) wep_only = true; rtlpriv->sec.pairwise_enc_algorithm = key_type; RT_TRACE( rtlpriv, COMP_SEC, DBG_DMESG, "set enable_hw_sec, key_type:%x(OPEN:0 WEP40:1 TKIP:2 AES:4 WEP104:5)\n", key_type ); rtlpriv->cfg->ops->enable_hw_sec( hw ); } } /* <4> set key based on cmd */ switch ( cmd ) { case SET_KEY: if ( wep_only ) { RT_TRACE( rtlpriv, COMP_SEC, DBG_DMESG, "set WEP(group/pairwise) key\n" ); /* Pairwise key with an assigned MAC address. */ rtlpriv->sec.pairwise_enc_algorithm = key_type; rtlpriv->sec.group_enc_algorithm = key_type; /*set local buf about wep key. */ memcpy( rtlpriv->sec.key_buf[key_idx], key->key, key->keylen ); rtlpriv->sec.key_len[key_idx] = key->keylen; eth_zero_addr( mac_addr ); } else if ( group_key ) { /* group key */ RT_TRACE( rtlpriv, COMP_SEC, DBG_DMESG, "set group key\n" ); /* group key */ rtlpriv->sec.group_enc_algorithm = key_type; /*set local buf about group key. */ memcpy( rtlpriv->sec.key_buf[key_idx], key->key, key->keylen ); rtlpriv->sec.key_len[key_idx] = key->keylen; memcpy( mac_addr, bcast_addr, ETH_ALEN ); } else { /* pairwise key */ RT_TRACE( rtlpriv, COMP_SEC, DBG_DMESG, "set pairwise key\n" ); if ( !sta ) { RT_ASSERT( false, "pairwise key without mac_addr\n" ); err = -EOPNOTSUPP; goto out_unlock; } /* Pairwise key with an assigned MAC address. */ rtlpriv->sec.pairwise_enc_algorithm = key_type; /*set local buf about pairwise key. */ memcpy( rtlpriv->sec.key_buf[PAIRWISE_KEYIDX], key->key, key->keylen ); rtlpriv->sec.key_len[PAIRWISE_KEYIDX] = key->keylen; rtlpriv->sec.pairwise_key = rtlpriv->sec.key_buf[PAIRWISE_KEYIDX]; memcpy( mac_addr, sta->addr, ETH_ALEN ); } rtlpriv->cfg->ops->set_key( hw, key_idx, mac_addr, group_key, key_type, wep_only, false ); /* <5> tell mac80211 do something: */ /*must use sw generate IV, or can not work !!!!. */ key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; key->hw_key_idx = key_idx; if ( key_type == TKIP_ENCRYPTION ) key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; /*use software CCMP encryption for management frames ( MFP ) */ if ( key_type == AESCCMP_ENCRYPTION ) key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; break; case DISABLE_KEY: RT_TRACE( rtlpriv, COMP_SEC, DBG_DMESG, "disable key delete one entry\n" ); /*set local buf about wep key. */ if ( vif->type == NL80211_IFTYPE_AP || vif->type == NL80211_IFTYPE_MESH_POINT ) { if ( sta ) rtl_cam_del_entry( hw, sta->addr ); } memset( rtlpriv->sec.key_buf[key_idx], 0, key->keylen ); rtlpriv->sec.key_len[key_idx] = 0; eth_zero_addr( mac_addr ); /* *mac80211 will delete entrys one by one, *so don't use rtl_cam_reset_all_entry *or clear all entry here. */ rtl_cam_delete_one_entry( hw, mac_addr, key_idx ); rtl_cam_reset_sec_info( hw ); break; default: RT_TRACE( rtlpriv, COMP_ERR, DBG_EMERG, "cmd_err:%x!!!!\n", cmd ); } out_unlock: mutex_unlock( &rtlpriv->locks.conf_mutex ); rtlpriv->sec.being_setkey = false; return err; }
static int qtnf_connect(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_connect_params *sme) { struct qtnf_vif *vif = qtnf_netdev_get_priv(dev); struct qtnf_wmac *mac = wiphy_priv(wiphy); struct cfg80211_chan_def chandef; struct qtnf_bss_config *bss_cfg; int ret; if (vif->wdev.iftype != NL80211_IFTYPE_STATION) return -EOPNOTSUPP; if (vif->sta_state != QTNF_STA_DISCONNECTED) return -EBUSY; bss_cfg = &vif->bss_cfg; memset(bss_cfg, 0, sizeof(*bss_cfg)); if (sme->channel) { /* FIXME: need to set proper nl80211_channel_type value */ cfg80211_chandef_create(&chandef, sme->channel, NL80211_CHAN_HT20); /* fall-back to minimal safe chandef description */ if (!cfg80211_chandef_valid(&chandef)) cfg80211_chandef_create(&chandef, sme->channel, NL80211_CHAN_HT20); memcpy(&mac->chandef, &chandef, sizeof(mac->chandef)); } bss_cfg->ssid_len = sme->ssid_len; memcpy(&bss_cfg->ssid, sme->ssid, bss_cfg->ssid_len); bss_cfg->auth_type = sme->auth_type; bss_cfg->privacy = sme->privacy; bss_cfg->mfp = sme->mfp; if ((sme->bg_scan_period > 0) && (sme->bg_scan_period <= QTNF_MAX_BG_SCAN_PERIOD)) bss_cfg->bg_scan_period = sme->bg_scan_period; else if (sme->bg_scan_period == -1) bss_cfg->bg_scan_period = QTNF_DEFAULT_BG_SCAN_PERIOD; else bss_cfg->bg_scan_period = 0; /* disabled */ bss_cfg->connect_flags = 0; if (sme->flags & ASSOC_REQ_DISABLE_HT) bss_cfg->connect_flags |= QLINK_STA_CONNECT_DISABLE_HT; if (sme->flags & ASSOC_REQ_DISABLE_VHT) bss_cfg->connect_flags |= QLINK_STA_CONNECT_DISABLE_VHT; if (sme->flags & ASSOC_REQ_USE_RRM) bss_cfg->connect_flags |= QLINK_STA_CONNECT_USE_RRM; memcpy(&bss_cfg->crypto, &sme->crypto, sizeof(bss_cfg->crypto)); if (sme->bssid) ether_addr_copy(bss_cfg->bssid, sme->bssid); else eth_zero_addr(bss_cfg->bssid); ret = qtnf_cmd_send_connect(vif, sme); if (ret) { pr_err("VIF%u.%u: failed to connect\n", vif->mac->macid, vif->vifid); return ret; } vif->sta_state = QTNF_STA_CONNECTING; return 0; }
static struct wireless_dev *qtnf_add_virtual_intf(struct wiphy *wiphy, const char *name, unsigned char name_assign_t, enum nl80211_iftype type, struct vif_params *params) { struct qtnf_wmac *mac; struct qtnf_vif *vif; u8 *mac_addr = NULL; mac = wiphy_priv(wiphy); if (!mac) return ERR_PTR(-EFAULT); switch (type) { case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_AP: vif = qtnf_mac_get_free_vif(mac); if (!vif) { pr_err("MAC%u: no free VIF available\n", mac->macid); return ERR_PTR(-EFAULT); } eth_zero_addr(vif->mac_addr); vif->bss_priority = QTNF_DEF_BSS_PRIORITY; vif->wdev.wiphy = wiphy; vif->wdev.iftype = type; vif->sta_state = QTNF_STA_DISCONNECTED; break; default: pr_err("MAC%u: unsupported IF type %d\n", mac->macid, type); return ERR_PTR(-ENOTSUPP); } if (params) mac_addr = params->macaddr; if (qtnf_cmd_send_add_intf(vif, type, mac_addr)) { pr_err("VIF%u.%u: failed to add VIF\n", mac->macid, vif->vifid); goto err_cmd; } if (!is_valid_ether_addr(vif->mac_addr)) { pr_err("VIF%u.%u: FW reported bad MAC: %pM\n", mac->macid, vif->vifid, vif->mac_addr); goto err_mac; } if (qtnf_core_net_attach(mac, vif, name, name_assign_t, type)) { pr_err("VIF%u.%u: failed to attach netdev\n", mac->macid, vif->vifid); goto err_net; } vif->wdev.netdev = vif->netdev; return &vif->wdev; err_net: vif->netdev = NULL; err_mac: qtnf_cmd_send_del_intf(vif); err_cmd: vif->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED; return ERR_PTR(-EFAULT); }
static int vl600_rx_fixup(struct usbnet *dev, struct sk_buff *skb) { struct vl600_frame_hdr *frame; struct vl600_pkt_hdr *packet; struct ethhdr *ethhdr; int packet_len, count; struct sk_buff *buf = skb; struct sk_buff *clone; struct vl600_state *s = dev->driver_priv; /* Frame lengths are generally 4B multiplies but every couple of * hours there's an odd number of bytes sized yet correct frame, * so don't require this. */ /* Allow a packet (or multiple packets batched together) to be * split across many frames. We don't allow a new batch to * begin in the same frame another one is ending however, and no * leading or trailing pad bytes. */ if (s->current_rx_buf) { frame = (struct vl600_frame_hdr *) s->current_rx_buf->data; if (skb->len + s->current_rx_buf->len > le32_to_cpup(&frame->len)) { netif_err(dev, ifup, dev->net, "Fragment too long\n"); dev->net->stats.rx_length_errors++; goto error; } buf = s->current_rx_buf; memcpy(skb_put(buf, skb->len), skb->data, skb->len); } else if (skb->len < 4) { netif_err(dev, ifup, dev->net, "Frame too short\n"); dev->net->stats.rx_length_errors++; goto error; } frame = (struct vl600_frame_hdr *) buf->data; /* Yes, check that frame->magic == 0x53544448 (or 0x44544d48), * otherwise we may run out of memory w/a bad packet */ if (ntohl(frame->magic) != 0x53544448 && ntohl(frame->magic) != 0x44544d48) goto error; if (buf->len < sizeof(*frame) || buf->len != le32_to_cpup(&frame->len)) { /* Save this fragment for later assembly */ if (s->current_rx_buf) return 0; s->current_rx_buf = skb_copy_expand(skb, 0, le32_to_cpup(&frame->len), GFP_ATOMIC); if (!s->current_rx_buf) { netif_err(dev, ifup, dev->net, "Reserving %i bytes " "for packet assembly failed.\n", le32_to_cpup(&frame->len)); dev->net->stats.rx_errors++; } return 0; } count = le32_to_cpup(&frame->pkt_cnt); skb_pull(buf, sizeof(*frame)); while (count--) { if (buf->len < sizeof(*packet)) { netif_err(dev, ifup, dev->net, "Packet too short\n"); goto error; } packet = (struct vl600_pkt_hdr *) buf->data; packet_len = sizeof(*packet) + le32_to_cpup(&packet->len); if (packet_len > buf->len) { netif_err(dev, ifup, dev->net, "Bad packet length stored in header\n"); goto error; } /* Packet header is same size as the ethernet header * (sizeof(*packet) == sizeof(*ethhdr)), additionally * the h_proto field is in the same place so we just leave it * alone and fill in the remaining fields. */ ethhdr = (struct ethhdr *) skb->data; if (be16_to_cpup(ðhdr->h_proto) == ETH_P_ARP && buf->len > 0x26) { /* Copy the addresses from packet contents */ memcpy(ethhdr->h_source, &buf->data[sizeof(*ethhdr) + 0x8], ETH_ALEN); memcpy(ethhdr->h_dest, &buf->data[sizeof(*ethhdr) + 0x12], ETH_ALEN); } else { eth_zero_addr(ethhdr->h_source); memcpy(ethhdr->h_dest, dev->net->dev_addr, ETH_ALEN); /* Inbound IPv6 packets have an IPv4 ethertype (0x800) * for some reason. Peek at the L3 header to check * for IPv6 packets, and set the ethertype to IPv6 * (0x86dd) so Linux can understand it. */ if ((buf->data[sizeof(*ethhdr)] & 0xf0) == 0x60) ethhdr->h_proto = htons(ETH_P_IPV6); } if (count) { /* Not the last packet in this batch */ clone = skb_clone(buf, GFP_ATOMIC); if (!clone) goto error; skb_trim(clone, packet_len); usbnet_skb_return(dev, clone); skb_pull(buf, (packet_len + 3) & ~3); } else { skb_trim(buf, packet_len); if (s->current_rx_buf) { usbnet_skb_return(dev, buf); s->current_rx_buf = NULL; return 0; } return 1; } } error: if (s->current_rx_buf) { dev_kfree_skb_any(s->current_rx_buf); s->current_rx_buf = NULL; } dev->net->stats.rx_errors++; return 0; }
static struct sk_buff *mlx5e_test_get_udp_skb(struct mlx5e_priv *priv) { struct sk_buff *skb = NULL; struct mlx5ehdr *mlxh; struct ethhdr *ethh; struct udphdr *udph; struct iphdr *iph; int datalen, iplen; datalen = MLX5E_TEST_PKT_SIZE - (sizeof(*ethh) + sizeof(*iph) + sizeof(*udph)); skb = netdev_alloc_skb(priv->netdev, MLX5E_TEST_PKT_SIZE); if (!skb) { netdev_err(priv->netdev, "\tFailed to alloc loopback skb\n"); return NULL; } prefetchw(skb->data); skb_reserve(skb, NET_IP_ALIGN); /* Reserve for ethernet and IP header */ ethh = skb_push(skb, ETH_HLEN); skb_reset_mac_header(skb); skb_set_network_header(skb, skb->len); iph = skb_put(skb, sizeof(struct iphdr)); skb_set_transport_header(skb, skb->len); udph = skb_put(skb, sizeof(struct udphdr)); /* Fill ETH header */ ether_addr_copy(ethh->h_dest, priv->netdev->dev_addr); eth_zero_addr(ethh->h_source); ethh->h_proto = htons(ETH_P_IP); /* Fill UDP header */ udph->source = htons(9); udph->dest = htons(9); /* Discard Protocol */ udph->len = htons(datalen + sizeof(struct udphdr)); udph->check = 0; /* Fill IP header */ iph->ihl = 5; iph->ttl = 32; iph->version = 4; iph->protocol = IPPROTO_UDP; iplen = sizeof(struct iphdr) + sizeof(struct udphdr) + datalen; iph->tot_len = htons(iplen); iph->frag_off = 0; iph->saddr = 0; iph->daddr = 0; iph->tos = 0; iph->id = 0; ip_send_check(iph); /* Fill test header and data */ mlxh = skb_put(skb, sizeof(*mlxh)); mlxh->version = 0; mlxh->magic = cpu_to_be64(MLX5E_TEST_MAGIC); strlcpy(mlxh->text, mlx5e_test_text, sizeof(mlxh->text)); datalen -= sizeof(*mlxh); skb_put_zero(skb, datalen); skb->csum = 0; skb->ip_summed = CHECKSUM_PARTIAL; udp4_hwcsum(skb, iph->saddr, iph->daddr); skb->protocol = htons(ETH_P_IP); skb->pkt_type = PACKET_HOST; skb->dev = priv->netdev; return skb; }
int efx_ef10_sriov_set_vf_vlan(struct efx_nic *efx, int vf_i, u16 vlan, u8 qos) { struct efx_ef10_nic_data *nic_data = efx->nic_data; struct ef10_vf *vf; u16 old_vlan, new_vlan; int rc = 0, rc2 = 0; if (vf_i >= efx->vf_count) return -EINVAL; if (qos != 0) return -EINVAL; vf = nic_data->vf + vf_i; new_vlan = (vlan == 0) ? EFX_EF10_NO_VLAN : vlan; if (new_vlan == vf->vlan) return 0; if (vf->efx) { efx_device_detach_sync(vf->efx); efx_net_stop(vf->efx->net_dev); down_write(&vf->efx->filter_sem); vf->efx->type->filter_table_remove(vf->efx); rc = efx_ef10_vadaptor_free(vf->efx, EVB_PORT_ID_ASSIGNED); if (rc) goto restore_filters; } if (vf->vport_assigned) { rc = efx_ef10_evb_port_assign(efx, EVB_PORT_ID_NULL, vf_i); if (rc) { netif_warn(efx, drv, efx->net_dev, "Failed to change vlan on VF %d.\n", vf_i); netif_warn(efx, drv, efx->net_dev, "This is likely because the VF is bound to a driver in a VM.\n"); netif_warn(efx, drv, efx->net_dev, "Please unload the driver in the VM.\n"); goto restore_vadaptor; } vf->vport_assigned = 0; } if (!is_zero_ether_addr(vf->mac)) { rc = efx_ef10_vport_del_mac(efx, vf->vport_id, vf->mac); if (rc) goto restore_evb_port; } if (vf->vport_id) { rc = efx_ef10_vport_free(efx, vf->vport_id); if (rc) goto restore_mac; vf->vport_id = 0; } /* Do the actual vlan change */ old_vlan = vf->vlan; vf->vlan = new_vlan; /* Restore everything in reverse order */ rc = efx_ef10_vport_alloc(efx, EVB_PORT_ID_ASSIGNED, MC_CMD_VPORT_ALLOC_IN_VPORT_TYPE_NORMAL, vf->vlan, &vf->vport_id); if (rc) goto reset_nic; restore_mac: if (!is_zero_ether_addr(vf->mac)) { rc2 = efx_ef10_vport_add_mac(efx, vf->vport_id, vf->mac); if (rc2) { eth_zero_addr(vf->mac); goto reset_nic; } } restore_evb_port: rc2 = efx_ef10_evb_port_assign(efx, vf->vport_id, vf_i); if (rc2) goto reset_nic; else vf->vport_assigned = 1; restore_vadaptor: if (vf->efx) { rc2 = efx_ef10_vadaptor_alloc(vf->efx, EVB_PORT_ID_ASSIGNED); if (rc2) goto reset_nic; } restore_filters: if (vf->efx) { rc2 = vf->efx->type->filter_table_probe(vf->efx); if (rc2) goto reset_nic; rc2 = efx_net_open(vf->efx->net_dev); if (rc2) goto reset_nic; up_write(&vf->efx->filter_sem); netif_device_attach(vf->efx->net_dev); } return rc; reset_nic: if (vf->efx) { up_write(&vf->efx->filter_sem); netif_err(efx, drv, efx->net_dev, "Failed to restore the VF - scheduling reset.\n"); efx_schedule_reset(vf->efx, RESET_TYPE_DATAPATH); } else { netif_err(efx, drv, efx->net_dev, "Failed to restore the VF and cannot reset the VF " "- VF is not functional.\n"); netif_err(efx, drv, efx->net_dev, "Please reload the driver attached to the VF.\n"); } return rc ? rc : rc2; }
int efx_ef10_sriov_set_vf_mac(struct efx_nic *efx, int vf_i, u8 *mac) { struct efx_ef10_nic_data *nic_data = efx->nic_data; struct ef10_vf *vf; int rc; if (nic_data->vf == NULL) return -EOPNOTSUPP; if (vf_i >= efx->vf_count) return -EINVAL; vf = nic_data->vf + vf_i; if (vf->efx) { efx_device_detach_sync(vf->efx); efx_net_stop(vf->efx->net_dev); down_write(&vf->efx->filter_sem); vf->efx->type->filter_table_remove(vf->efx); rc = efx_ef10_vadaptor_free(vf->efx, EVB_PORT_ID_ASSIGNED); if (rc) { up_write(&vf->efx->filter_sem); return rc; } } rc = efx_ef10_evb_port_assign(efx, EVB_PORT_ID_NULL, vf_i); if (rc) return rc; if (!is_zero_ether_addr(vf->mac)) { rc = efx_ef10_vport_del_vf_mac(efx, vf->vport_id, vf->mac); if (rc) return rc; } if (!is_zero_ether_addr(mac)) { rc = efx_ef10_vport_add_mac(efx, vf->vport_id, mac); if (rc) { eth_zero_addr(vf->mac); goto fail; } if (vf->efx) ether_addr_copy(vf->efx->net_dev->dev_addr, mac); } ether_addr_copy(vf->mac, mac); rc = efx_ef10_evb_port_assign(efx, vf->vport_id, vf_i); if (rc) goto fail; if (vf->efx) { /* VF cannot use the vport_id that the PF created */ rc = efx_ef10_vadaptor_alloc(vf->efx, EVB_PORT_ID_ASSIGNED); if (rc) { up_write(&vf->efx->filter_sem); return rc; } vf->efx->type->filter_table_probe(vf->efx); up_write(&vf->efx->filter_sem); efx_net_open(vf->efx->net_dev); netif_device_attach(vf->efx->net_dev); } return 0; fail: memset(vf->mac, 0, ETH_ALEN); return rc; }
/* On top of the default firmware vswitch setup, create a VEB vswitch and * expansion vport for use by this function. */ int efx_ef10_vswitching_probe_pf(struct efx_nic *efx) { #ifdef CONFIG_SFC_SRIOV struct efx_ef10_nic_data *nic_data = efx->nic_data; struct net_device *net_dev = efx->net_dev; int rc; #if !defined(EFX_USE_KCOMPAT) || defined(EFX_HAVE_SRIOV_GET_TOTALVFS) if (pci_sriov_get_totalvfs(efx->pci_dev) <= 0 && !enable_vswitch) { #else if (efx->max_vfs <= 0 && !enable_vswitch) { #endif /* vswitch not needed as we have no VFs */ efx_ef10_vadaptor_alloc(efx, nic_data->vport_id); return 0; } rc = efx_ef10_vswitch_alloc(efx, EVB_PORT_ID_ASSIGNED, MC_CMD_VSWITCH_ALLOC_IN_VSWITCH_TYPE_VEB); if (rc) goto fail1; rc = efx_ef10_vport_alloc(efx, EVB_PORT_ID_ASSIGNED, MC_CMD_VPORT_ALLOC_IN_VPORT_TYPE_NORMAL, EFX_EF10_NO_VLAN, &nic_data->vport_id); if (rc) goto fail2; efx->ef10_resources.vport_id = nic_data->vport_id; rc = efx_ef10_vport_add_mac(efx, nic_data->vport_id, net_dev->dev_addr); if (rc) goto fail3; ether_addr_copy(nic_data->vport_mac, net_dev->dev_addr); rc = efx_ef10_vadaptor_alloc(efx, nic_data->vport_id); if (rc) goto fail4; return 0; fail4: efx_ef10_vport_del_mac(efx, nic_data->vport_id, nic_data->vport_mac); eth_zero_addr(nic_data->vport_mac); fail3: efx_ef10_vport_free(efx, nic_data->vport_id); nic_data->vport_id = EVB_PORT_ID_ASSIGNED; fail2: efx_ef10_vswitch_free(efx, EVB_PORT_ID_ASSIGNED); fail1: return rc; #else return 0; #endif } int efx_ef10_vswitching_probe_vf(struct efx_nic *efx) { #ifdef CONFIG_SFC_SRIOV struct efx_ef10_nic_data *nic_data = efx->nic_data; return efx_ef10_vadaptor_alloc(efx, nic_data->vport_id); #else return 0; #endif } int efx_ef10_vswitching_restore_pf(struct efx_nic *efx) { #ifdef CONFIG_SFC_SRIOV struct efx_ef10_nic_data *nic_data = efx->nic_data; int rc; if (!nic_data->must_probe_vswitching) return 0; rc = efx_ef10_vswitching_probe_pf(efx); if (rc) goto fail; rc = efx_ef10_sriov_restore_vf_vswitching(efx); if (rc) goto fail; nic_data->must_probe_vswitching = false; fail: return rc; #else return 0; #endif } int efx_ef10_vswitching_restore_vf(struct efx_nic *efx) { #ifdef CONFIG_SFC_SRIOV struct efx_ef10_nic_data *nic_data = efx->nic_data; int rc; if (!nic_data->must_probe_vswitching) return 0; rc = efx_ef10_vadaptor_free(efx, EVB_PORT_ID_ASSIGNED); if (rc) return rc; nic_data->must_probe_vswitching = false; #endif return 0; } void efx_ef10_vswitching_remove_pf(struct efx_nic *efx) { #ifdef CONFIG_SFC_SRIOV struct efx_ef10_nic_data *nic_data = efx->nic_data; efx_ef10_sriov_free_vf_vswitching(efx); efx_ef10_vadaptor_free(efx, nic_data->vport_id); if (nic_data->vport_id == EVB_PORT_ID_ASSIGNED) return; /* No vswitch was ever created */ if (!is_zero_ether_addr(nic_data->vport_mac)) { efx_ef10_vport_del_mac(efx, nic_data->vport_id, efx->net_dev->dev_addr); eth_zero_addr(nic_data->vport_mac); } efx_ef10_vport_free(efx, nic_data->vport_id); nic_data->vport_id = EVB_PORT_ID_ASSIGNED; #if !defined(EFX_USE_KCOMPAT) || defined(EFX_HAVE_PCI_DEV_FLAGS_ASSIGNED) /* Only free the vswitch if no VFs are assigned */ if (!pci_vfs_assigned(efx->pci_dev)) #endif efx_ef10_vswitch_free(efx, nic_data->vport_id); #endif } void efx_ef10_vswitching_remove_vf(struct efx_nic *efx) { #ifdef CONFIG_SFC_SRIOV efx_ef10_vadaptor_free(efx, EVB_PORT_ID_ASSIGNED); #endif }