mutex_lock(&adapter->vector_lock);
min_vec = adapter->num_msix_entries - adapter->num_avail_msix;
stack = &adapter->vector_stack;
stack->size = adapter->num_msix_entries; /* set the base and top to point at start of the 'free pool' to *distributetheunusedvectorson-demandbasis
*/
stack->base = min_vec;
stack->top = min_vec;
stack->vec_idx = kcalloc(stack->size, sizeof(u16), GFP_KERNEL); if (!stack->vec_idx) {
mutex_unlock(&adapter->vector_lock);
return -ENOMEM;
}
for (i = 0; i < stack->size; i++)
stack->vec_idx[i] = i;
if (stack->top == stack->size) {
dev_err(&adapter->pdev->dev, "No interrupt vectors are available to distribute!\n");
return -EINVAL;
}
return stack->vec_idx[stack->top++];
}
/** *idpf_vector_stash-Storethevectorindexesontothestack *@adapter:privatedatastruct *@q_vector_idxs:vectorindexarray *@vec_info:inforelatedtothenumberofvectors * *Thisfunctionisano-opiftherearenovectorsindexestobestashed
*/ staticvoid idpf_vector_stash(struct idpf_adapter *adapter, u16 *q_vector_idxs, struct idpf_vector_info *vec_info)
{ int i, base = 0;
u16 vec_idx;
lockdep_assert_held(&adapter->vector_lock);
if (!vec_info->num_curr_vecs) return;
/* For default vports, no need to stash vector allocated from the *defaultpoolontothestack
*/ if (vec_info->default_vport)
base = IDPF_MIN_Q_VEC;
for (i = vec_info->num_curr_vecs - 1; i >= base ; i--) {
vec_idx = q_vector_idxs[i];
idpf_vector_lifo_push(adapter, vec_idx);
adapter->num_avail_msix++;
}
}
/* Stash interrupt vector indexes onto the stack if required */
idpf_vector_stash(adapter, q_vector_idxs, vec_info);
if (!num_req_vecs) goto rel_lock;
if (vec_info->default_vport) { /* As IDPF_MIN_Q_VEC per default vport is put aside in the *defaultpoolofthestack,usethemfordefaultvports
*/
j = vec_info->index * IDPF_MIN_Q_VEC + IDPF_MBX_Q_VEC; for (i = 0; i < IDPF_MIN_Q_VEC; i++) {
q_vector_idxs[num_alloc_vecs++] = stack->vec_idx[j++];
num_req_vecs--;
}
}
/* Find if stack has enough vector to allocate */
max_vecs = min(adapter->num_avail_msix, num_req_vecs);
if (idpf_is_rdma_cap_ena(adapter)) { if (actual_vecs < total_vecs) {
dev_warn(&adapter->pdev->dev, "Warning: %d vectors requested, only %d available. Defaulting to minimum (%d) for RDMA and remaining for LAN.\n",
total_vecs, actual_vecs, IDPF_MIN_RDMA_VEC);
num_rdma_vecs = IDPF_MIN_RDMA_VEC;
}
for (vector = 0; vector < num_lan_vecs; vector++) {
adapter->msix_entries[vector].entry = vecids[vector];
adapter->msix_entries[vector].vector =
pci_irq_vector(adapter->pdev, vector);
} for (i = 0; i < num_rdma_vecs; vector++, i++) {
adapter->rdma_msix_entries[i].entry = vecids[vector];
adapter->rdma_msix_entries[i].vector =
pci_irq_vector(adapter->pdev, vector);
}
/* 'num_avail_msix' is used to distribute excess vectors to the vports *afterconsideringtheminimumvectorsrequiredpereachdefault *vport
*/
adapter->num_avail_msix = num_lan_vecs - min_lan_vecs;
adapter->num_msix_entries = num_lan_vecs; if (idpf_is_rdma_cap_ena(adapter))
adapter->num_rdma_msix_entries = num_rdma_vecs;
/* Fill MSIX vector lifo stack with vector indexes */
err = idpf_init_vector_stack(adapter); if (err) goto free_vecids;
err = idpf_mb_intr_init(adapter); if (err) goto deinit_vec_stack;
idpf_mb_irq_enable(adapter);
kfree(vecids);
if (!idpf_is_cap_ena(adapter, IDPF_OTHER_CAPS,
VIRTCHNL2_CAP_MACFILTER)) {
dev_err(&adapter->pdev->dev, "MAC address is not provided and capability is not set\n");
dev_info(&adapter->pdev->dev, "Invalid MAC address %pM, using random %pM\n",
vport->default_mac_addr, netdev->dev_addr);
ether_addr_copy(vport->default_mac_addr, netdev->dev_addr);
idpf_send_disable_vport_msg(vport);
idpf_send_disable_queues_msg(vport);
idpf_send_map_unmap_queue_vector_msg(vport, false); /* Normally we ask for queues in create_vport, but if the number of *initiallyrequestedqueueshavechanged,forexampleviaethtool *setchannels,wedodeletequeuesandthenaddthequeuesback *insteadofdeletingandreallocatingthevport.
*/ if (test_and_clear_bit(IDPF_VPORT_DEL_QUEUES, vport->flags))
idpf_send_delete_queues_msg(vport);
/* Release all max queues allocated to the adapter's pool */
max_q.max_rxq = vport_config->max_q.max_rxq;
max_q.max_txq = vport_config->max_q.max_txq;
max_q.max_bufq = vport_config->max_q.max_bufq;
max_q.max_complq = vport_config->max_q.max_complq;
idpf_vport_dealloc_max_qs(adapter, &max_q);
/* Release all the allocated vectors on the stack */
vec_info.num_req_vecs = 0;
vec_info.num_curr_vecs = vport->num_q_vectors;
vec_info.default_vport = vport->default_vport;
if (!test_bit(IDPF_HR_RESET_IN_PROG, adapter->flags))
idpf_decfg_netdev(vport); if (test_bit(IDPF_REMOVE_IN_PROG, adapter->flags))
idpf_del_all_mac_filters(vport);
if (adapter->netdevs[i]) { struct idpf_netdev_priv *np = netdev_priv(adapter->netdevs[i]);
switch (val) { case ETHTOOL_TCP_DATA_SPLIT_UNKNOWN: /* Default is to enable */ case ETHTOOL_TCP_DATA_SPLIT_ENABLED:
__set_bit(__IDPF_USER_FLAG_HSPLIT, config->user_flags); returntrue; case ETHTOOL_TCP_DATA_SPLIT_DISABLED:
__clear_bit(__IDPF_USER_FLAG_HSPLIT, config->user_flags); returntrue; default: returnfalse;
}
}
vport->q_vector_idxs = kcalloc(num_max_q, sizeof(u16), GFP_KERNEL); if (!vport->q_vector_idxs) goto free_vport;
idpf_vport_init(vport, max_q);
/* This alloc is done separate from the LUT because it's not strictly *dependentonhowmanyqueueswehave.Ifwechangenumberofqueues *andsoftresetwe'llneedanewLUTbutthekeycanremainthesame *foraslongasthevportexists.
*/
rss_data = &adapter->vport_config[idx]->user_config.rss_data;
rss_data->rss_key = kzalloc(rss_data->rss_key_size, GFP_KERNEL); if (!rss_data->rss_key) goto free_vector_idxs;
err = idpf_check_supported_desc_ids(vport); if (err) {
dev_err(&pdev->dev, "failed to get required descriptor ids\n"); goto cfg_netdev_err;
}
if (idpf_cfg_netdev(vport)) goto cfg_netdev_err;
err = idpf_send_get_rx_ptype_msg(vport); if (err) goto handle_err;
/* Once state is put into DOWN, driver is ready for dev_open */
np = netdev_priv(vport->netdev);
np->state = __IDPF_VPORT_DOWN; if (test_and_clear_bit(IDPF_VPORT_UP_REQUESTED, vport_config->flags))
idpf_vport_open(vport, true);
/* Spawn and return 'idpf_init_task' work queue until all the *defaultvportsarecreated
*/ if (adapter->num_alloc_vports < num_default_vports) {
queue_delayed_work(adapter->init_wq, &adapter->init_task,
msecs_to_jiffies(5 * (adapter->pdev->devfn & 0x07)));
return;
}
for (index = 0; index < adapter->max_vports; index++) { struct net_device *netdev = adapter->netdevs[index]; struct idpf_vport_config *vport_config;
vport_config = adapter->vport_config[index];
if (!netdev ||
test_bit(IDPF_VPORT_REG_NETDEV, vport_config->flags)) continue;
err = register_netdev(netdev); if (err) {
dev_err(&pdev->dev, "failed to register netdev for vport %d: %pe\n",
index, ERR_PTR(err)); continue;
}
set_bit(IDPF_VPORT_REG_NETDEV, vport_config->flags);
}
/* As all the required vports are created, clear the reset flag *unconditionallyhereincasewewereinresetandthelinkwasdown.
*/
clear_bit(IDPF_HR_RESET_IN_PROG, adapter->flags); /* Start the statistics task now */
queue_delayed_work(adapter->stats_wq, &adapter->stats_task,
msecs_to_jiffies(10 * (pdev->devfn & 0x07)));
return;
handle_err:
idpf_decfg_netdev(vport);
cfg_netdev_err:
idpf_vport_rel(vport);
adapter->vports[index] = NULL;
unwind_vports: if (default_vport) { for (index = 0; index < adapter->max_vports; index++) { if (adapter->vports[index])
idpf_vport_dealloc(adapter->vports[index]);
}
}
clear_bit(IDPF_HR_RESET_IN_PROG, adapter->flags);
}
/** *idpf_sriov_ena-EnableorchangenumberofVFs *@adapter:privatedatastruct *@num_vfs:numberofVFstoallocate
*/ staticint idpf_sriov_ena(struct idpf_adapter *adapter, int num_vfs)
{ struct device *dev = &adapter->pdev->dev; int err;
err = idpf_send_set_sriov_vfs_msg(adapter, num_vfs); if (err) {
dev_err(dev, "Failed to allocate VFs: %d\n", err);
return err;
}
err = pci_enable_sriov(adapter->pdev, num_vfs); if (err) {
idpf_send_set_sriov_vfs_msg(adapter, 0);
dev_err(dev, "Failed to enable SR-IOV: %d\n", err);
return err;
}
adapter->num_vfs = num_vfs;
return num_vfs;
}
/** *idpf_sriov_configure-ConfiguretherequestedVFs *@pdev:pointertoapci_devstructure *@num_vfs:numberofvfstoallocate * *EnableorchangethenumberofVFs.Calledwhentheuserupdatesthenumber *ofVFsinsysfs.
**/ int idpf_sriov_configure(struct pci_dev *pdev, int num_vfs)
{ struct idpf_adapter *adapter = pci_get_drvdata(pdev);
if (!idpf_is_cap_ena(adapter, IDPF_OTHER_CAPS, VIRTCHNL2_CAP_SRIOV)) {
dev_info(&pdev->dev, "SR-IOV is not supported on this device\n");
return -EOPNOTSUPP;
}
if (num_vfs) return idpf_sriov_ena(adapter, num_vfs);
if (pci_vfs_assigned(pdev)) {
dev_warn(&pdev->dev, "Unable to free VFs because some are assigned to VMs\n");
/* Wait until the init_task is done else this thread might release *theresourcesfirstandtheotherthreadmightendupinabadstate
*/
cancel_delayed_work_sync(&adapter->init_task);
if (!adapter->vports) return;
cancel_delayed_work_sync(&adapter->stats_task);
for (i = 0; i < adapter->max_vports; i++) { if (adapter->vports[i])
idpf_vport_dealloc(adapter->vports[i]);
}
}
for (i = 0; i < 2000; i++) {
u32 reg_val = readl(reset_reg->rstat);
/* 0xFFFFFFFF might be read if other side hasn't cleared the *registerforusyetand0xFFFFFFFFisnotavalidvaluefor *theregister,sotreatthatasinvalid.
*/ if (reg_val != 0xFFFFFFFF && (reg_val & reset_reg->rstat_m)) return0;
usleep_range(5000, 10000);
}
dev_warn(&adapter->pdev->dev, "Device reset timeout!\n"); /* Clear the reset flag unconditionally here since the reset *technicallyisn'tinprogressanymorefromthedriver'sperspective
*/
clear_bit(IDPF_HR_RESET_IN_PROG, adapter->flags);
/* Wait for reset to complete */
err = idpf_check_reset_complete(&adapter->hw, &adapter->reset_reg); if (err) {
dev_err(dev, "The driver was unable to contact the device's firmware. Check that the FW is running. Driver state= 0x%x\n",
adapter->state); goto unlock_mutex;
}
/* Reset is complete and so start building the driver resources again */
err = idpf_init_dflt_mbx(adapter); if (err) {
dev_err(dev, "Failed to initialize default mailbox: %d\n", err); goto unlock_mutex;
}
/* Initialize the state machine, also allocate memory and request *resources
*/
err = idpf_vc_core_init(adapter); if (err) {
cancel_delayed_work_sync(&adapter->mbx_task);
idpf_deinit_dflt_mbx(adapter); goto unlock_mutex;
}
/* Wait till all the vports are initialized to release the reset lock, *elseuserspacecallbacksmayaccessuninitializedvports
*/ while (test_bit(IDPF_HR_RESET_IN_PROG, adapter->flags))
msleep(100);
/* If the system is low on memory, we can end up in bad state if we *freeallthememoryforqueueresourcesandtrytoallocatethem *again.Instead,wecanpre-allocatethenewresourcesbeforedoing *anythingandbailingiftheallocfails. * *Makeacloneoftheexistingvporttomimicitscurrent *configuration,thenmodifythenewstructurewithanyrequested *changes.Oncetheallocationofthenewresourcesisdone,stopthe *existingvportandcopytheconfigurationtothemainvport.Ifan *erroroccurred,theexistingvportwillbeuntouched. *
*/
new_vport = kzalloc(sizeof(*vport), GFP_KERNEL); if (!new_vport) return -ENOMEM;
/* This purposely avoids copying the end of the struct because it *containswait_queuesandmutexesandotherstuffwedon'twantto *messwith.Nothingbelowshouldusethosevariablesfromnew_vport *andshouldinsteadalwaysrefertotheminvportiftheyneedto.
*/
memcpy(new_vport, vport, offsetof(struct idpf_vport, link_up));
/* Adjust resource parameters prior to reallocating resources */ switch (reset_cause) { case IDPF_SR_Q_CHANGE:
err = idpf_vport_adjust_qs(new_vport); if (err) goto free_vport; break; case IDPF_SR_Q_DESC_CHANGE: /* Update queue parameters before allocating resources */
idpf_vport_calc_num_q_desc(new_vport); break; case IDPF_SR_MTU_CHANGE:
idpf_idc_vdev_mtu_event(vport->vdev_info,
IIDC_RDMA_EVENT_BEFORE_MTU_CHANGE); break; case IDPF_SR_RSC_CHANGE: break; default:
dev_err(&adapter->pdev->dev, "Unhandled soft reset cause\n");
err = -EINVAL; goto free_vport;
}
idpf_deinit_rss(vport); /* We're passing in vport here because we need its wait_queue *tosendamessageanditshouldbegettingallthevport *configdataoutoftheadapterbutweneedtobecarefulnot *toaddcodetoadd_queuestochangethevportconfigwithin *vportitselfasitwillbewipedwithamemcpylater.
*/
err = idpf_send_add_queues_msg(vport, new_vport->num_txq,
new_vport->num_complq,
new_vport->num_rxq,
new_vport->num_bufq); if (err)
goto err_reset;
/* Same comment as above regarding avoiding copying the wait_queues and
* mutexes applies here. We do not want to mess with those if possible.
*/
memcpy(vport, new_vport, offsetof(struct idpf_vport, link_up));
if (reset_cause == IDPF_SR_Q_CHANGE)
idpf_vport_alloc_vec_indexes(vport);
err = idpf_set_real_num_queues(vport); if (err)
goto err_open;
if (current_state == __IDPF_VPORT_UP)
err = idpf_vport_open(vport, false);
err_open: if (current_state == __IDPF_VPORT_UP)
idpf_vport_open(vport, false);
free_vport:
kfree(new_vport);
if (reset_cause == IDPF_SR_MTU_CHANGE)
idpf_idc_vdev_mtu_event(vport->vdev_info,
IIDC_RDMA_EVENT_AFTER_MTU_CHANGE);
return err;
}
/**
* idpf_addr_sync - Callback for dev_(mc|uc)_sync to add address
* @netdev: the netdevice
* @addr: address to add
*
* Called by __dev_(mc|uc)_sync when an address needs to be added. We call
* __dev_(uc|mc)_sync from .set_rx_mode. Kernel takes addr_list_lock spinlock
* meaning we cannot sleep in this context. Due to this, we have to add the
* filter and send the virtchnl message asynchronously without waiting for the
* response from the other side. We won't know whether or not the operation
* actually succeeded until we get the message back. Returns 0 on success,
* negative on failure.
*/
static int idpf_addr_sync(struct net_device *netdev, const u8 *addr)
{
struct idpf_netdev_priv *np = netdev_priv(netdev);
/**
* idpf_addr_unsync - Callback for dev_(mc|uc)_sync to remove address
* @netdev: the netdevice
* @addr: address to add
*
* Called by __dev_(mc|uc)_sync when an address needs to be added. We call
* __dev_(uc|mc)_sync from .set_rx_mode. Kernel takes addr_list_lock spinlock
* meaning we cannot sleep in this context. Due to this we have to delete the
* filter and send the virtchnl message asynchronously without waiting for the
* return from the other side. We won't know whether or not the operation
* actually succeeded until we get the message back. Returns 0 on success,
* negative on failure.
*/
static int idpf_addr_unsync(struct net_device *netdev, const u8 *addr)
{
struct idpf_netdev_priv *np = netdev_priv(netdev);
/* Under some circumstances, we might receive a request to delete
* our own device address from our uc list. Because we store the
* device address in the VSI's MAC filter list, we need to ignore
* such requests and not delete our device address from this list.
*/ if (ether_addr_equal(addr, netdev->dev_addr))
return 0;
idpf_del_mac_filter(np->vport, np, addr, true);
return 0;
}
/**
* idpf_set_rx_mode - NDO callback to set the netdev filters
* @netdev: network interface device structure
*
* Stack takes addr_list_lock spinlock before calling our .set_rx_mode. We
* cannot sleep in this context.
*/
static void idpf_set_rx_mode(struct net_device *netdev)
{
struct idpf_netdev_priv *np = netdev_priv(netdev);
struct idpf_vport_user_config_data *config_data;
struct idpf_adapter *adapter;
bool changed = false;
struct device *dev;
int err;
err = idpf_set_promiscuous(adapter, config_data, np->vport_id); if (err)
dev_err(dev, "Failed to set promiscuous mode: %d\n", err);
}
/**
* idpf_vport_manage_rss_lut - disable/enable RSS
* @vport: the vport being changed
*
* In the event of disable request for RSS, this function will zero out RSS
* LUT, while in the event of enable request for RSS, it will reconfigure RSS
* LUT with the default LUT configuration.
*/
static int idpf_vport_manage_rss_lut(struct idpf_vport *vport)
{
bool ena = idpf_is_feature_ena(vport, NETIF_F_RXHASH);
struct idpf_rss_data *rss_data;
u16 idx = vport->idx;
int lut_size;
if (ena) {
/* This will contain the default or user configured LUT */
memcpy(rss_data->rss_lut, rss_data->cached_lut, lut_size);
} else {
/* Save a copy of the current LUT to be restored later if
* requested.
*/
memcpy(rss_data->cached_lut, rss_data->rss_lut, lut_size);
/* Zero out the current LUT to disable */
memset(rss_data->rss_lut, 0, lut_size);
}
return idpf_config_rss(vport);
}
/**
* idpf_set_features - set the netdev feature flags
* @netdev: ptr to the netdev being adjusted
* @features: the feature set that the stack is suggesting
*/
static int idpf_set_features(struct net_device *netdev,
netdev_features_t features)
{
netdev_features_t changed = netdev->features ^ features;
struct idpf_adapter *adapter;
struct idpf_vport *vport;
int err = 0;
/**
* idpf_open - Called when a network interface becomes active
* @netdev: network interface device structure
*
* The open entry point is called when a network interface is made
* active by the system (IFF_UP). At this point all resources needed
* for transmit and receive operations are allocated, the interrupt
* handler is registered with the OS, the netdev watchdog is enabled,
* and the stack is notified that the interface is ready.
*
* Returns 0 on success, negative value on failure
*/
static int idpf_open(struct net_device *netdev)
{
struct idpf_vport *vport;
int err;
err = idpf_set_real_num_queues(vport); if (err)
goto unlock;
err = idpf_vport_open(vport, false);
unlock:
idpf_vport_ctrl_unlock(netdev);
return err;
}
/**
* idpf_change_mtu - NDO callback to change the MTU
* @netdev: network interface device structure
* @new_mtu: new value for maximum frame size
*
* Returns 0 on success, negative on failure
*/
static int idpf_change_mtu(struct net_device *netdev, int new_mtu)
{
struct idpf_vport *vport;
int err;
/**
* idpf_chk_tso_segment - Check skb is not using too many buffers
* @skb: send buffer
* @max_bufs: maximum number of buffers
*
* For TSO we need to count the TSO header and segment payload separately. As
* such we need to check cases where we have max_bufs-1 fragments or more as we
* can potentially require max_bufs+1 DMA transactions, 1for the TSO header, 1
* for the segment payload in the first descriptor, and another max_buf-1for
* the fragments.
*
* Returns true if the packet needs to be software segmented by core stack.
*/
static bool idpf_chk_tso_segment(const struct sk_buff *skb,
unsigned int max_bufs)
{
const struct skb_shared_info *shinfo = skb_shinfo(skb);
const skb_frag_t *frag, *stale;
int nr_frags, sum;
/* no need to check if number of frags is less than max_bufs - 1 */
nr_frags = shinfo->nr_frags; if (nr_frags < (max_bufs - 1))
return false;
/* We need to walk through the list and validate that each group
* of max_bufs-2 fragments totals at least gso_size.
*/
nr_frags -= max_bufs - 2;
frag = &shinfo->frags[0];
/* Initialize size to the negative value of gso_size minus 1. We use
* this as the worst case scenario in which the frag ahead of us only
* provides one byte which is why we are limited to max_bufs-2
* descriptors for a single transmit as the header and previous
* fragment are already consuming 2 descriptors.
*/
sum = 1 - shinfo->gso_size;
/* Add size of frags 0 through 4 to create our initial sum */
sum += skb_frag_size(frag++);
sum += skb_frag_size(frag++);
sum += skb_frag_size(frag++);
sum += skb_frag_size(frag++);
sum += skb_frag_size(frag++);
/* Walk through fragments adding latest fragment, testing it, and
* then removing stale fragments from the sum.
*/ for (stale = &shinfo->frags[0];; stale++) {
int stale_size = skb_frag_size(stale);
sum += skb_frag_size(frag++);
/* The stale fragment may present us with a smaller
* descriptor than the actual fragment size. To account
* for that we need to remove all the data on the front and
* figure out what the remainder would be in the last
* descriptor associated with the fragment.
*/ if (stale_size > IDPF_TX_MAX_DESC_DATA) {
int align_pad = -(skb_frag_off(stale)) &
(IDPF_TX_MAX_READ_REQ_SIZE - 1);
sum -= align_pad;
stale_size -= align_pad;
do {
sum -= IDPF_TX_MAX_DESC_DATA_ALIGNED;
stale_size -= IDPF_TX_MAX_DESC_DATA_ALIGNED;
} while (stale_size > IDPF_TX_MAX_DESC_DATA);
}
/* if sum is negative we failed to make sufficient progress */ if (sum < 0)
return true;
if (!nr_frags--)
break;
sum -= stale_size;
}
return false;
}
/**
* idpf_features_check - Validate packet conforms to limits
* @skb: skb buffer
* @netdev: This port's netdev
* @features: Offload features that the stack believes apply
*/
static netdev_features_t idpf_features_check(struct sk_buff *skb,
struct net_device *netdev,
netdev_features_t features)
{
struct idpf_netdev_priv *np = netdev_priv(netdev);
u16 max_tx_hdr_size = np->max_tx_hdr_size;
size_t len;
/* No point in doing any of this if neither checksum nor GSO are
* being requested for this frame. We can rule out both by just
* checking for CHECKSUM_PARTIAL
*/ if (skb->ip_summed != CHECKSUM_PARTIAL)
return features;
if (skb_is_gso(skb)) {
/* We cannot support GSO if the MSS is going to be less than
* 88 bytes. If it is then we need to drop support for GSO.
*/ if (skb_shinfo(skb)->gso_size < IDPF_TX_TSO_MIN_MSS)
features &= ~NETIF_F_GSO_MASK; elseif (idpf_chk_tso_segment(skb, np->tx_max_bufs))
features &= ~NETIF_F_GSO_MASK;
}
/* Ensure MACLEN is <= 126 bytes (63 words) and not an odd size */
len = skb_network_offset(skb); if (unlikely(len & ~(126)))
goto unsupported;
len = skb_network_header_len(skb); if (unlikely(len > max_tx_hdr_size))
goto unsupported;
if (!skb->encapsulation)
return features;
/* L4TUNLEN can support 127 words */
len = skb_inner_network_header(skb) - skb_transport_header(skb); if (unlikely(len & ~(127 * 2)))
goto unsupported;
/* IPLEN can support at most 127 dwords */
len = skb_inner_network_header_len(skb); if (unlikely(len > max_tx_hdr_size))
goto unsupported;
/* No need to validate L4LEN as TCP is the only protocol with a
* a flexible value and we support all possible values supported
* by TCP, which is at most 15 dwords
*/
return features;
unsupported:
return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
}
/**
* idpf_set_mac - NDO callback to set port mac address
* @netdev: network interface device structure
* @p: pointer to an address structure
*
* Returns 0 on success, negative on failure
**/
static int idpf_set_mac(struct net_device *netdev, void *p)
{
struct idpf_netdev_priv *np = netdev_priv(netdev);
struct idpf_vport_config *vport_config;
struct sockaddr *addr = p;
u8 old_mac_addr[ETH_ALEN];
struct idpf_vport *vport;
int err = 0;
if (!idpf_is_cap_ena(vport->adapter, IDPF_OTHER_CAPS,
VIRTCHNL2_CAP_MACFILTER)) {
dev_info(&vport->adapter->pdev->dev, "Setting MAC address is not supported\n");
err = -EOPNOTSUPP;
goto unlock_mutex;
}
if (!is_valid_ether_addr(addr->sa_data)) {
dev_info(&vport->adapter->pdev->dev, "Invalid MAC address: %pM\n",
addr->sa_data);
err = -EADDRNOTAVAIL;
goto unlock_mutex;
}
if (ether_addr_equal(netdev->dev_addr, addr->sa_data))
goto unlock_mutex;
if (is_valid_ether_addr(old_mac_addr))
__idpf_del_mac_filter(vport_config, old_mac_addr);
eth_hw_addr_set(netdev, addr->sa_data);
unlock_mutex:
idpf_vport_ctrl_unlock(netdev);
return err;
}
/**
* idpf_alloc_dma_mem - Allocate dma memory
* @hw: pointer to hw struct
* @mem: pointer to dma_mem struct
* @size: size of the memory to allocate
*/
void *idpf_alloc_dma_mem(struct idpf_hw *hw, struct idpf_dma_mem *mem, u64 size)
{
struct idpf_adapter *adapter = hw->back;
size_t sz = ALIGN(size, 4096);
/* The control queue resources are freed under a spinlock, contiguous
* pages will avoid IOMMU remapping and the use vmap (and vunmap in
* dma_free_*() path.
*/
mem->va = dma_alloc_attrs(&adapter->pdev->dev, sz, &mem->pa,
GFP_KERNEL, DMA_ATTR_FORCE_CONTIGUOUS);
mem->size = sz;
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.95Bemerkung:
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.