Merge 26a0ba5d16 ("Input: drv260x - sleep between polling GO bit") into android13-5.15-lts
Steps on the way to 5.15.121 Change-Id: I86e12f6d1961f47f208c0d1ea240ffad750d66a6 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
@@ -302,6 +302,9 @@ void dcn30_smu_set_display_refresh_from_mall(struct clk_mgr_internal *clk_mgr, b
|
||||
/* bits 8:7 for cache timer scale, bits 6:1 for cache timer delay, bit 0 = 1 for enable, = 0 for disable */
|
||||
uint32_t param = (cache_timer_scale << 7) | (cache_timer_delay << 1) | (enable ? 1 : 0);
|
||||
|
||||
smu_print("SMU Set display refresh from mall: enable = %d, cache_timer_delay = %d, cache_timer_scale = %d\n",
|
||||
enable, cache_timer_delay, cache_timer_scale);
|
||||
|
||||
dcn30_smu_send_msg_with_param(clk_mgr,
|
||||
DALSMC_MSG_SetDisplayRefreshFromMall, param, NULL);
|
||||
}
|
||||
|
||||
@@ -2111,9 +2111,6 @@ static enum surface_update_type det_surface_update(const struct dc *dc,
|
||||
enum surface_update_type overall_type = UPDATE_TYPE_FAST;
|
||||
union surface_update_flags *update_flags = &u->surface->update_flags;
|
||||
|
||||
if (u->flip_addr)
|
||||
update_flags->bits.addr_update = 1;
|
||||
|
||||
if (!is_surface_in_context(context, u->surface) || u->surface->force_full_update) {
|
||||
update_flags->raw = 0xFFFFFFFF;
|
||||
return UPDATE_TYPE_FULL;
|
||||
|
||||
@@ -5520,6 +5520,7 @@ static int ci_parse_power_table(struct radeon_device *rdev)
|
||||
u8 frev, crev;
|
||||
u8 *power_state_offset;
|
||||
struct ci_ps *ps;
|
||||
int ret;
|
||||
|
||||
if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
|
||||
&frev, &crev, &data_offset))
|
||||
@@ -5549,11 +5550,15 @@ static int ci_parse_power_table(struct radeon_device *rdev)
|
||||
non_clock_array_index = power_state->v2.nonClockInfoIndex;
|
||||
non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
|
||||
&non_clock_info_array->nonClockInfo[non_clock_array_index];
|
||||
if (!rdev->pm.power_state[i].clock_info)
|
||||
return -EINVAL;
|
||||
if (!rdev->pm.power_state[i].clock_info) {
|
||||
ret = -EINVAL;
|
||||
goto err_free_ps;
|
||||
}
|
||||
ps = kzalloc(sizeof(struct ci_ps), GFP_KERNEL);
|
||||
if (ps == NULL)
|
||||
return -ENOMEM;
|
||||
if (ps == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto err_free_ps;
|
||||
}
|
||||
rdev->pm.dpm.ps[i].ps_priv = ps;
|
||||
ci_parse_pplib_non_clock_info(rdev, &rdev->pm.dpm.ps[i],
|
||||
non_clock_info,
|
||||
@@ -5593,6 +5598,12 @@ static int ci_parse_power_table(struct radeon_device *rdev)
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_ps:
|
||||
for (i = 0; i < rdev->pm.dpm.num_ps; i++)
|
||||
kfree(rdev->pm.dpm.ps[i].ps_priv);
|
||||
kfree(rdev->pm.dpm.ps);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ci_get_vbios_boot_values(struct radeon_device *rdev,
|
||||
@@ -5681,25 +5692,26 @@ int ci_dpm_init(struct radeon_device *rdev)
|
||||
|
||||
ret = ci_get_vbios_boot_values(rdev, &pi->vbios_boot_state);
|
||||
if (ret) {
|
||||
ci_dpm_fini(rdev);
|
||||
kfree(rdev->pm.dpm.priv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = r600_get_platform_caps(rdev);
|
||||
if (ret) {
|
||||
ci_dpm_fini(rdev);
|
||||
kfree(rdev->pm.dpm.priv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = r600_parse_extended_power_table(rdev);
|
||||
if (ret) {
|
||||
ci_dpm_fini(rdev);
|
||||
kfree(rdev->pm.dpm.priv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ci_parse_power_table(rdev);
|
||||
if (ret) {
|
||||
ci_dpm_fini(rdev);
|
||||
kfree(rdev->pm.dpm.priv);
|
||||
r600_free_extended_power_table(rdev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -435,6 +435,7 @@ static int drv260x_init(struct drv260x_data *haptics)
|
||||
}
|
||||
|
||||
do {
|
||||
usleep_range(15000, 15500);
|
||||
error = regmap_read(haptics->regmap, DRV260X_GO, &cal_buf);
|
||||
if (error) {
|
||||
dev_err(&haptics->client->dev,
|
||||
|
||||
@@ -3900,7 +3900,7 @@ u32 bond_xmit_hash(struct bonding *bond, struct sk_buff *skb)
|
||||
return skb->hash;
|
||||
|
||||
return __bond_xmit_hash(bond, skb, skb->data, skb->protocol,
|
||||
skb_mac_offset(skb), skb_network_offset(skb),
|
||||
0, skb_network_offset(skb),
|
||||
skb_headlen(skb));
|
||||
}
|
||||
|
||||
|
||||
@@ -228,6 +228,10 @@ struct igc_adapter {
|
||||
struct ptp_clock *ptp_clock;
|
||||
struct ptp_clock_info ptp_caps;
|
||||
struct work_struct ptp_tx_work;
|
||||
/* Access to ptp_tx_skb and ptp_tx_start are protected by the
|
||||
* ptp_tx_lock.
|
||||
*/
|
||||
spinlock_t ptp_tx_lock;
|
||||
struct sk_buff *ptp_tx_skb;
|
||||
struct hwtstamp_config tstamp_config;
|
||||
unsigned long ptp_tx_start;
|
||||
@@ -430,7 +434,6 @@ enum igc_state_t {
|
||||
__IGC_TESTING,
|
||||
__IGC_RESETTING,
|
||||
__IGC_DOWN,
|
||||
__IGC_PTP_TX_IN_PROGRESS,
|
||||
};
|
||||
|
||||
enum igc_tx_flags {
|
||||
|
||||
@@ -1576,9 +1576,10 @@ done:
|
||||
* the other timer registers before skipping the
|
||||
* timestamping request.
|
||||
*/
|
||||
if (adapter->tstamp_config.tx_type == HWTSTAMP_TX_ON &&
|
||||
!test_and_set_bit_lock(__IGC_PTP_TX_IN_PROGRESS,
|
||||
&adapter->state)) {
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&adapter->ptp_tx_lock, flags);
|
||||
if (adapter->tstamp_config.tx_type == HWTSTAMP_TX_ON && !adapter->ptp_tx_skb) {
|
||||
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
|
||||
tx_flags |= IGC_TX_FLAGS_TSTAMP;
|
||||
|
||||
@@ -1587,6 +1588,8 @@ done:
|
||||
} else {
|
||||
adapter->tx_hwtstamp_skipped++;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&adapter->ptp_tx_lock, flags);
|
||||
}
|
||||
|
||||
if (skb_vlan_tag_present(skb)) {
|
||||
|
||||
@@ -608,6 +608,7 @@ static int igc_ptp_set_timestamp_mode(struct igc_adapter *adapter,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Requires adapter->ptp_tx_lock held by caller. */
|
||||
static void igc_ptp_tx_timeout(struct igc_adapter *adapter)
|
||||
{
|
||||
struct igc_hw *hw = &adapter->hw;
|
||||
@@ -615,7 +616,6 @@ static void igc_ptp_tx_timeout(struct igc_adapter *adapter)
|
||||
dev_kfree_skb_any(adapter->ptp_tx_skb);
|
||||
adapter->ptp_tx_skb = NULL;
|
||||
adapter->tx_hwtstamp_timeouts++;
|
||||
clear_bit_unlock(__IGC_PTP_TX_IN_PROGRESS, &adapter->state);
|
||||
/* Clear the tx valid bit in TSYNCTXCTL register to enable interrupt. */
|
||||
rd32(IGC_TXSTMPH);
|
||||
netdev_warn(adapter->netdev, "Tx timestamp timeout\n");
|
||||
@@ -623,20 +623,20 @@ static void igc_ptp_tx_timeout(struct igc_adapter *adapter)
|
||||
|
||||
void igc_ptp_tx_hang(struct igc_adapter *adapter)
|
||||
{
|
||||
bool timeout = time_is_before_jiffies(adapter->ptp_tx_start +
|
||||
IGC_PTP_TX_TIMEOUT);
|
||||
unsigned long flags;
|
||||
|
||||
if (!test_bit(__IGC_PTP_TX_IN_PROGRESS, &adapter->state))
|
||||
return;
|
||||
spin_lock_irqsave(&adapter->ptp_tx_lock, flags);
|
||||
|
||||
/* If we haven't received a timestamp within the timeout, it is
|
||||
* reasonable to assume that it will never occur, so we can unlock the
|
||||
* timestamp bit when this occurs.
|
||||
*/
|
||||
if (timeout) {
|
||||
cancel_work_sync(&adapter->ptp_tx_work);
|
||||
igc_ptp_tx_timeout(adapter);
|
||||
}
|
||||
if (!adapter->ptp_tx_skb)
|
||||
goto unlock;
|
||||
|
||||
if (time_is_after_jiffies(adapter->ptp_tx_start + IGC_PTP_TX_TIMEOUT))
|
||||
goto unlock;
|
||||
|
||||
igc_ptp_tx_timeout(adapter);
|
||||
|
||||
unlock:
|
||||
spin_unlock_irqrestore(&adapter->ptp_tx_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -646,6 +646,8 @@ void igc_ptp_tx_hang(struct igc_adapter *adapter)
|
||||
* If we were asked to do hardware stamping and such a time stamp is
|
||||
* available, then it must have been for this skb here because we only
|
||||
* allow only one such packet into the queue.
|
||||
*
|
||||
* Context: Expects adapter->ptp_tx_lock to be held by caller.
|
||||
*/
|
||||
static void igc_ptp_tx_hwtstamp(struct igc_adapter *adapter)
|
||||
{
|
||||
@@ -681,13 +683,7 @@ static void igc_ptp_tx_hwtstamp(struct igc_adapter *adapter)
|
||||
shhwtstamps.hwtstamp =
|
||||
ktime_add_ns(shhwtstamps.hwtstamp, adjust);
|
||||
|
||||
/* Clear the lock early before calling skb_tstamp_tx so that
|
||||
* applications are not woken up before the lock bit is clear. We use
|
||||
* a copy of the skb pointer to ensure other threads can't change it
|
||||
* while we're notifying the stack.
|
||||
*/
|
||||
adapter->ptp_tx_skb = NULL;
|
||||
clear_bit_unlock(__IGC_PTP_TX_IN_PROGRESS, &adapter->state);
|
||||
|
||||
/* Notify the stack and free the skb after we've unlocked */
|
||||
skb_tstamp_tx(skb, &shhwtstamps);
|
||||
@@ -698,24 +694,33 @@ static void igc_ptp_tx_hwtstamp(struct igc_adapter *adapter)
|
||||
* igc_ptp_tx_work
|
||||
* @work: pointer to work struct
|
||||
*
|
||||
* This work function polls the TSYNCTXCTL valid bit to determine when a
|
||||
* timestamp has been taken for the current stored skb.
|
||||
* This work function checks the TSYNCTXCTL valid bit to determine when
|
||||
* a timestamp has been taken for the current stored skb.
|
||||
*/
|
||||
static void igc_ptp_tx_work(struct work_struct *work)
|
||||
{
|
||||
struct igc_adapter *adapter = container_of(work, struct igc_adapter,
|
||||
ptp_tx_work);
|
||||
struct igc_hw *hw = &adapter->hw;
|
||||
unsigned long flags;
|
||||
u32 tsynctxctl;
|
||||
|
||||
if (!test_bit(__IGC_PTP_TX_IN_PROGRESS, &adapter->state))
|
||||
return;
|
||||
spin_lock_irqsave(&adapter->ptp_tx_lock, flags);
|
||||
|
||||
if (!adapter->ptp_tx_skb)
|
||||
goto unlock;
|
||||
|
||||
tsynctxctl = rd32(IGC_TSYNCTXCTL);
|
||||
if (WARN_ON_ONCE(!(tsynctxctl & IGC_TSYNCTXCTL_TXTT_0)))
|
||||
return;
|
||||
tsynctxctl &= IGC_TSYNCTXCTL_TXTT_0;
|
||||
if (!tsynctxctl) {
|
||||
WARN_ONCE(1, "Received a TSTAMP interrupt but no TSTAMP is ready.\n");
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
igc_ptp_tx_hwtstamp(adapter);
|
||||
|
||||
unlock:
|
||||
spin_unlock_irqrestore(&adapter->ptp_tx_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -964,6 +969,7 @@ void igc_ptp_init(struct igc_adapter *adapter)
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_init(&adapter->ptp_tx_lock);
|
||||
spin_lock_init(&adapter->tmreg_lock);
|
||||
INIT_WORK(&adapter->ptp_tx_work, igc_ptp_tx_work);
|
||||
|
||||
@@ -1028,7 +1034,6 @@ void igc_ptp_suspend(struct igc_adapter *adapter)
|
||||
cancel_work_sync(&adapter->ptp_tx_work);
|
||||
dev_kfree_skb_any(adapter->ptp_tx_skb);
|
||||
adapter->ptp_tx_skb = NULL;
|
||||
clear_bit_unlock(__IGC_PTP_TX_IN_PROGRESS, &adapter->state);
|
||||
|
||||
if (pci_device_is_present(adapter->pdev)) {
|
||||
igc_ptp_time_save(adapter);
|
||||
|
||||
@@ -1297,8 +1297,10 @@ static void efx_ef10_fini_nic(struct efx_nic *efx)
|
||||
{
|
||||
struct efx_ef10_nic_data *nic_data = efx->nic_data;
|
||||
|
||||
spin_lock_bh(&efx->stats_lock);
|
||||
kfree(nic_data->mc_stats);
|
||||
nic_data->mc_stats = NULL;
|
||||
spin_unlock_bh(&efx->stats_lock);
|
||||
}
|
||||
|
||||
static int efx_ef10_init_nic(struct efx_nic *efx)
|
||||
@@ -1852,9 +1854,14 @@ static size_t efx_ef10_update_stats_pf(struct efx_nic *efx, u64 *full_stats,
|
||||
|
||||
efx_ef10_get_stat_mask(efx, mask);
|
||||
|
||||
efx_nic_copy_stats(efx, nic_data->mc_stats);
|
||||
efx_nic_update_stats(efx_ef10_stat_desc, EF10_STAT_COUNT,
|
||||
mask, stats, nic_data->mc_stats, false);
|
||||
/* If NIC was fini'd (probably resetting), then we can't read
|
||||
* updated stats right now.
|
||||
*/
|
||||
if (nic_data->mc_stats) {
|
||||
efx_nic_copy_stats(efx, nic_data->mc_stats);
|
||||
efx_nic_update_stats(efx_ef10_stat_desc, EF10_STAT_COUNT,
|
||||
mask, stats, nic_data->mc_stats, false);
|
||||
}
|
||||
|
||||
/* Update derived statistics */
|
||||
efx_nic_fix_nodesc_drop_stat(efx,
|
||||
|
||||
@@ -7318,12 +7318,6 @@ int stmmac_dvr_remove(struct device *dev)
|
||||
netif_carrier_off(ndev);
|
||||
unregister_netdev(ndev);
|
||||
|
||||
/* Serdes power down needs to happen after VLAN filter
|
||||
* is deleted that is triggered by unregister_netdev().
|
||||
*/
|
||||
if (priv->plat->serdes_powerdown)
|
||||
priv->plat->serdes_powerdown(ndev, priv->plat->bsp_priv);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
stmmac_exit_fs(ndev);
|
||||
#endif
|
||||
|
||||
@@ -2075,6 +2075,11 @@ static int axienet_probe(struct platform_device *pdev)
|
||||
goto cleanup_clk;
|
||||
}
|
||||
|
||||
/* Reset core now that clocks are enabled, prior to accessing MDIO */
|
||||
ret = __axienet_device_reset(lp);
|
||||
if (ret)
|
||||
goto cleanup_clk;
|
||||
|
||||
/* Autodetect the need for 64-bit DMA pointers.
|
||||
* When the IP is configured for a bus width bigger than 32 bits,
|
||||
* writing the MSB registers is mandatory, even if they are all 0.
|
||||
@@ -2122,11 +2127,6 @@ static int axienet_probe(struct platform_device *pdev)
|
||||
lp->coalesce_count_rx = XAXIDMA_DFT_RX_THRESHOLD;
|
||||
lp->coalesce_count_tx = XAXIDMA_DFT_TX_THRESHOLD;
|
||||
|
||||
/* Reset core now that clocks are enabled, prior to accessing MDIO */
|
||||
ret = __axienet_device_reset(lp);
|
||||
if (ret)
|
||||
goto cleanup_clk;
|
||||
|
||||
ret = axienet_mdio_setup(lp);
|
||||
if (ret)
|
||||
dev_warn(&pdev->dev,
|
||||
|
||||
@@ -298,7 +298,9 @@ static void __gtp_encap_destroy(struct sock *sk)
|
||||
gtp->sk1u = NULL;
|
||||
udp_sk(sk)->encap_type = 0;
|
||||
rcu_assign_sk_user_data(sk, NULL);
|
||||
release_sock(sk);
|
||||
sock_put(sk);
|
||||
return;
|
||||
}
|
||||
release_sock(sk);
|
||||
}
|
||||
|
||||
@@ -586,7 +586,8 @@ static int ipvlan_xmit_mode_l3(struct sk_buff *skb, struct net_device *dev)
|
||||
consume_skb(skb);
|
||||
return NET_XMIT_DROP;
|
||||
}
|
||||
return ipvlan_rcv_frame(addr, &skb, true);
|
||||
ipvlan_rcv_frame(addr, &skb, true);
|
||||
return NET_XMIT_SUCCESS;
|
||||
}
|
||||
}
|
||||
out:
|
||||
@@ -612,7 +613,8 @@ static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev)
|
||||
consume_skb(skb);
|
||||
return NET_XMIT_DROP;
|
||||
}
|
||||
return ipvlan_rcv_frame(addr, &skb, true);
|
||||
ipvlan_rcv_frame(addr, &skb, true);
|
||||
return NET_XMIT_SUCCESS;
|
||||
}
|
||||
}
|
||||
skb = skb_share_check(skb, GFP_ATOMIC);
|
||||
@@ -624,7 +626,8 @@ static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev)
|
||||
* the skb for the main-dev. At the RX side we just return
|
||||
* RX_PASS for it to be processed further on the stack.
|
||||
*/
|
||||
return dev_forward_skb(ipvlan->phy_dev, skb);
|
||||
dev_forward_skb(ipvlan->phy_dev, skb);
|
||||
return NET_XMIT_SUCCESS;
|
||||
|
||||
} else if (is_multicast_ether_addr(eth->h_dest)) {
|
||||
skb_reset_mac_header(skb);
|
||||
|
||||
@@ -69,17 +69,18 @@
|
||||
* Error Status Indicator (ESI) 1
|
||||
* Data length code (DLC) 4
|
||||
* Data field 0...512
|
||||
* Stuff Bit Count (SBC) 0...16: 4 20...64:5
|
||||
* Stuff Bit Count (SBC) 4
|
||||
* CRC 0...16: 17 20...64:21
|
||||
* CRC delimiter (CD) 1
|
||||
* Fixed Stuff bits (FSB) 0...16: 6 20...64:7
|
||||
* ACK slot (AS) 1
|
||||
* ACK delimiter (AD) 1
|
||||
* End-of-frame (EOF) 7
|
||||
* Inter frame spacing 3
|
||||
*
|
||||
* assuming CRC21, rounded up and ignoring bitstuffing
|
||||
* assuming CRC21, rounded up and ignoring dynamic bitstuffing
|
||||
*/
|
||||
#define CANFD_FRAME_OVERHEAD_SFF DIV_ROUND_UP(61, 8)
|
||||
#define CANFD_FRAME_OVERHEAD_SFF DIV_ROUND_UP(67, 8)
|
||||
|
||||
/*
|
||||
* Size of a CAN-FD Extended Frame
|
||||
@@ -98,17 +99,18 @@
|
||||
* Error Status Indicator (ESI) 1
|
||||
* Data length code (DLC) 4
|
||||
* Data field 0...512
|
||||
* Stuff Bit Count (SBC) 0...16: 4 20...64:5
|
||||
* Stuff Bit Count (SBC) 4
|
||||
* CRC 0...16: 17 20...64:21
|
||||
* CRC delimiter (CD) 1
|
||||
* Fixed Stuff bits (FSB) 0...16: 6 20...64:7
|
||||
* ACK slot (AS) 1
|
||||
* ACK delimiter (AD) 1
|
||||
* End-of-frame (EOF) 7
|
||||
* Inter frame spacing 3
|
||||
*
|
||||
* assuming CRC21, rounded up and ignoring bitstuffing
|
||||
* assuming CRC21, rounded up and ignoring dynamic bitstuffing
|
||||
*/
|
||||
#define CANFD_FRAME_OVERHEAD_EFF DIV_ROUND_UP(80, 8)
|
||||
#define CANFD_FRAME_OVERHEAD_EFF DIV_ROUND_UP(86, 8)
|
||||
|
||||
/*
|
||||
* Maximum size of a Classical CAN frame
|
||||
|
||||
@@ -5236,6 +5236,15 @@ static inline bool netif_is_l3_slave(const struct net_device *dev)
|
||||
return dev->priv_flags & IFF_L3MDEV_SLAVE;
|
||||
}
|
||||
|
||||
static inline int dev_sdif(const struct net_device *dev)
|
||||
{
|
||||
#ifdef CONFIG_NET_L3_MASTER_DEV
|
||||
if (netif_is_l3_slave(dev))
|
||||
return dev->ifindex;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool netif_is_bridge_master(const struct net_device *dev)
|
||||
{
|
||||
return dev->priv_flags & IFF_EBRIDGE;
|
||||
|
||||
@@ -2012,6 +2012,7 @@ static inline void sock_graft(struct sock *sk, struct socket *parent)
|
||||
}
|
||||
|
||||
kuid_t sock_i_uid(struct sock *sk);
|
||||
unsigned long __sock_i_ino(struct sock *sk);
|
||||
unsigned long sock_i_ino(struct sock *sk);
|
||||
|
||||
static inline kuid_t sock_net_uid(const struct net *net, const struct sock *sk)
|
||||
|
||||
@@ -60,10 +60,12 @@ static unsigned int bm_find(struct ts_config *conf, struct ts_state *state)
|
||||
struct ts_bm *bm = ts_config_priv(conf);
|
||||
unsigned int i, text_len, consumed = state->offset;
|
||||
const u8 *text;
|
||||
int shift = bm->patlen - 1, bs;
|
||||
int bs;
|
||||
const u8 icase = conf->flags & TS_IGNORECASE;
|
||||
|
||||
for (;;) {
|
||||
int shift = bm->patlen - 1;
|
||||
|
||||
text_len = conf->get_next_block(consumed, &text, conf, state);
|
||||
|
||||
if (unlikely(text_len == 0))
|
||||
|
||||
@@ -6174,12 +6174,11 @@ static struct sock *sk_lookup(struct net *net, struct bpf_sock_tuple *tuple,
|
||||
static struct sock *
|
||||
__bpf_skc_lookup(struct sk_buff *skb, struct bpf_sock_tuple *tuple, u32 len,
|
||||
struct net *caller_net, u32 ifindex, u8 proto, u64 netns_id,
|
||||
u64 flags)
|
||||
u64 flags, int sdif)
|
||||
{
|
||||
struct sock *sk = NULL;
|
||||
u8 family = AF_UNSPEC;
|
||||
struct net *net;
|
||||
int sdif;
|
||||
u8 family;
|
||||
|
||||
if (len == sizeof(tuple->ipv4))
|
||||
family = AF_INET;
|
||||
@@ -6188,14 +6187,15 @@ __bpf_skc_lookup(struct sk_buff *skb, struct bpf_sock_tuple *tuple, u32 len,
|
||||
else
|
||||
return NULL;
|
||||
|
||||
if (unlikely(family == AF_UNSPEC || flags ||
|
||||
!((s32)netns_id < 0 || netns_id <= S32_MAX)))
|
||||
if (unlikely(flags || !((s32)netns_id < 0 || netns_id <= S32_MAX)))
|
||||
goto out;
|
||||
|
||||
if (family == AF_INET)
|
||||
sdif = inet_sdif(skb);
|
||||
else
|
||||
sdif = inet6_sdif(skb);
|
||||
if (sdif < 0) {
|
||||
if (family == AF_INET)
|
||||
sdif = inet_sdif(skb);
|
||||
else
|
||||
sdif = inet6_sdif(skb);
|
||||
}
|
||||
|
||||
if ((s32)netns_id < 0) {
|
||||
net = caller_net;
|
||||
@@ -6215,10 +6215,11 @@ out:
|
||||
static struct sock *
|
||||
__bpf_sk_lookup(struct sk_buff *skb, struct bpf_sock_tuple *tuple, u32 len,
|
||||
struct net *caller_net, u32 ifindex, u8 proto, u64 netns_id,
|
||||
u64 flags)
|
||||
u64 flags, int sdif)
|
||||
{
|
||||
struct sock *sk = __bpf_skc_lookup(skb, tuple, len, caller_net,
|
||||
ifindex, proto, netns_id, flags);
|
||||
ifindex, proto, netns_id, flags,
|
||||
sdif);
|
||||
|
||||
if (sk) {
|
||||
struct sock *sk2 = sk_to_full_sk(sk);
|
||||
@@ -6258,7 +6259,7 @@ bpf_skc_lookup(struct sk_buff *skb, struct bpf_sock_tuple *tuple, u32 len,
|
||||
}
|
||||
|
||||
return __bpf_skc_lookup(skb, tuple, len, caller_net, ifindex, proto,
|
||||
netns_id, flags);
|
||||
netns_id, flags, -1);
|
||||
}
|
||||
|
||||
static struct sock *
|
||||
@@ -6347,6 +6348,78 @@ static const struct bpf_func_proto bpf_sk_lookup_udp_proto = {
|
||||
.arg5_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
BPF_CALL_5(bpf_tc_skc_lookup_tcp, struct sk_buff *, skb,
|
||||
struct bpf_sock_tuple *, tuple, u32, len, u64, netns_id, u64, flags)
|
||||
{
|
||||
struct net_device *dev = skb->dev;
|
||||
int ifindex = dev->ifindex, sdif = dev_sdif(dev);
|
||||
struct net *caller_net = dev_net(dev);
|
||||
|
||||
return (unsigned long)__bpf_skc_lookup(skb, tuple, len, caller_net,
|
||||
ifindex, IPPROTO_TCP, netns_id,
|
||||
flags, sdif);
|
||||
}
|
||||
|
||||
static const struct bpf_func_proto bpf_tc_skc_lookup_tcp_proto = {
|
||||
.func = bpf_tc_skc_lookup_tcp,
|
||||
.gpl_only = false,
|
||||
.pkt_access = true,
|
||||
.ret_type = RET_PTR_TO_SOCK_COMMON_OR_NULL,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg3_type = ARG_CONST_SIZE,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
.arg5_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
BPF_CALL_5(bpf_tc_sk_lookup_tcp, struct sk_buff *, skb,
|
||||
struct bpf_sock_tuple *, tuple, u32, len, u64, netns_id, u64, flags)
|
||||
{
|
||||
struct net_device *dev = skb->dev;
|
||||
int ifindex = dev->ifindex, sdif = dev_sdif(dev);
|
||||
struct net *caller_net = dev_net(dev);
|
||||
|
||||
return (unsigned long)__bpf_sk_lookup(skb, tuple, len, caller_net,
|
||||
ifindex, IPPROTO_TCP, netns_id,
|
||||
flags, sdif);
|
||||
}
|
||||
|
||||
static const struct bpf_func_proto bpf_tc_sk_lookup_tcp_proto = {
|
||||
.func = bpf_tc_sk_lookup_tcp,
|
||||
.gpl_only = false,
|
||||
.pkt_access = true,
|
||||
.ret_type = RET_PTR_TO_SOCKET_OR_NULL,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg3_type = ARG_CONST_SIZE,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
.arg5_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
BPF_CALL_5(bpf_tc_sk_lookup_udp, struct sk_buff *, skb,
|
||||
struct bpf_sock_tuple *, tuple, u32, len, u64, netns_id, u64, flags)
|
||||
{
|
||||
struct net_device *dev = skb->dev;
|
||||
int ifindex = dev->ifindex, sdif = dev_sdif(dev);
|
||||
struct net *caller_net = dev_net(dev);
|
||||
|
||||
return (unsigned long)__bpf_sk_lookup(skb, tuple, len, caller_net,
|
||||
ifindex, IPPROTO_UDP, netns_id,
|
||||
flags, sdif);
|
||||
}
|
||||
|
||||
static const struct bpf_func_proto bpf_tc_sk_lookup_udp_proto = {
|
||||
.func = bpf_tc_sk_lookup_udp,
|
||||
.gpl_only = false,
|
||||
.pkt_access = true,
|
||||
.ret_type = RET_PTR_TO_SOCKET_OR_NULL,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg3_type = ARG_CONST_SIZE,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
.arg5_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
BPF_CALL_1(bpf_sk_release, struct sock *, sk)
|
||||
{
|
||||
if (sk && sk_is_refcounted(sk))
|
||||
@@ -6364,12 +6437,13 @@ static const struct bpf_func_proto bpf_sk_release_proto = {
|
||||
BPF_CALL_5(bpf_xdp_sk_lookup_udp, struct xdp_buff *, ctx,
|
||||
struct bpf_sock_tuple *, tuple, u32, len, u32, netns_id, u64, flags)
|
||||
{
|
||||
struct net *caller_net = dev_net(ctx->rxq->dev);
|
||||
int ifindex = ctx->rxq->dev->ifindex;
|
||||
struct net_device *dev = ctx->rxq->dev;
|
||||
int ifindex = dev->ifindex, sdif = dev_sdif(dev);
|
||||
struct net *caller_net = dev_net(dev);
|
||||
|
||||
return (unsigned long)__bpf_sk_lookup(NULL, tuple, len, caller_net,
|
||||
ifindex, IPPROTO_UDP, netns_id,
|
||||
flags);
|
||||
flags, sdif);
|
||||
}
|
||||
|
||||
static const struct bpf_func_proto bpf_xdp_sk_lookup_udp_proto = {
|
||||
@@ -6387,12 +6461,13 @@ static const struct bpf_func_proto bpf_xdp_sk_lookup_udp_proto = {
|
||||
BPF_CALL_5(bpf_xdp_skc_lookup_tcp, struct xdp_buff *, ctx,
|
||||
struct bpf_sock_tuple *, tuple, u32, len, u32, netns_id, u64, flags)
|
||||
{
|
||||
struct net *caller_net = dev_net(ctx->rxq->dev);
|
||||
int ifindex = ctx->rxq->dev->ifindex;
|
||||
struct net_device *dev = ctx->rxq->dev;
|
||||
int ifindex = dev->ifindex, sdif = dev_sdif(dev);
|
||||
struct net *caller_net = dev_net(dev);
|
||||
|
||||
return (unsigned long)__bpf_skc_lookup(NULL, tuple, len, caller_net,
|
||||
ifindex, IPPROTO_TCP, netns_id,
|
||||
flags);
|
||||
flags, sdif);
|
||||
}
|
||||
|
||||
static const struct bpf_func_proto bpf_xdp_skc_lookup_tcp_proto = {
|
||||
@@ -6410,12 +6485,13 @@ static const struct bpf_func_proto bpf_xdp_skc_lookup_tcp_proto = {
|
||||
BPF_CALL_5(bpf_xdp_sk_lookup_tcp, struct xdp_buff *, ctx,
|
||||
struct bpf_sock_tuple *, tuple, u32, len, u32, netns_id, u64, flags)
|
||||
{
|
||||
struct net *caller_net = dev_net(ctx->rxq->dev);
|
||||
int ifindex = ctx->rxq->dev->ifindex;
|
||||
struct net_device *dev = ctx->rxq->dev;
|
||||
int ifindex = dev->ifindex, sdif = dev_sdif(dev);
|
||||
struct net *caller_net = dev_net(dev);
|
||||
|
||||
return (unsigned long)__bpf_sk_lookup(NULL, tuple, len, caller_net,
|
||||
ifindex, IPPROTO_TCP, netns_id,
|
||||
flags);
|
||||
flags, sdif);
|
||||
}
|
||||
|
||||
static const struct bpf_func_proto bpf_xdp_sk_lookup_tcp_proto = {
|
||||
@@ -6435,7 +6511,8 @@ BPF_CALL_5(bpf_sock_addr_skc_lookup_tcp, struct bpf_sock_addr_kern *, ctx,
|
||||
{
|
||||
return (unsigned long)__bpf_skc_lookup(NULL, tuple, len,
|
||||
sock_net(ctx->sk), 0,
|
||||
IPPROTO_TCP, netns_id, flags);
|
||||
IPPROTO_TCP, netns_id, flags,
|
||||
-1);
|
||||
}
|
||||
|
||||
static const struct bpf_func_proto bpf_sock_addr_skc_lookup_tcp_proto = {
|
||||
@@ -6454,7 +6531,7 @@ BPF_CALL_5(bpf_sock_addr_sk_lookup_tcp, struct bpf_sock_addr_kern *, ctx,
|
||||
{
|
||||
return (unsigned long)__bpf_sk_lookup(NULL, tuple, len,
|
||||
sock_net(ctx->sk), 0, IPPROTO_TCP,
|
||||
netns_id, flags);
|
||||
netns_id, flags, -1);
|
||||
}
|
||||
|
||||
static const struct bpf_func_proto bpf_sock_addr_sk_lookup_tcp_proto = {
|
||||
@@ -6473,7 +6550,7 @@ BPF_CALL_5(bpf_sock_addr_sk_lookup_udp, struct bpf_sock_addr_kern *, ctx,
|
||||
{
|
||||
return (unsigned long)__bpf_sk_lookup(NULL, tuple, len,
|
||||
sock_net(ctx->sk), 0, IPPROTO_UDP,
|
||||
netns_id, flags);
|
||||
netns_id, flags, -1);
|
||||
}
|
||||
|
||||
static const struct bpf_func_proto bpf_sock_addr_sk_lookup_udp_proto = {
|
||||
@@ -7476,9 +7553,9 @@ tc_cls_act_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
|
||||
#endif
|
||||
#ifdef CONFIG_INET
|
||||
case BPF_FUNC_sk_lookup_tcp:
|
||||
return &bpf_sk_lookup_tcp_proto;
|
||||
return &bpf_tc_sk_lookup_tcp_proto;
|
||||
case BPF_FUNC_sk_lookup_udp:
|
||||
return &bpf_sk_lookup_udp_proto;
|
||||
return &bpf_tc_sk_lookup_udp_proto;
|
||||
case BPF_FUNC_sk_release:
|
||||
return &bpf_sk_release_proto;
|
||||
case BPF_FUNC_tcp_sock:
|
||||
@@ -7486,7 +7563,7 @@ tc_cls_act_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
|
||||
case BPF_FUNC_get_listener_sock:
|
||||
return &bpf_get_listener_sock_proto;
|
||||
case BPF_FUNC_skc_lookup_tcp:
|
||||
return &bpf_skc_lookup_tcp_proto;
|
||||
return &bpf_tc_skc_lookup_tcp_proto;
|
||||
case BPF_FUNC_tcp_check_syncookie:
|
||||
return &bpf_tcp_check_syncookie_proto;
|
||||
case BPF_FUNC_skb_ecn_set_ce:
|
||||
|
||||
@@ -3911,7 +3911,7 @@ static int nlmsg_populate_fdb_fill(struct sk_buff *skb,
|
||||
ndm->ndm_ifindex = dev->ifindex;
|
||||
ndm->ndm_state = ndm_state;
|
||||
|
||||
if (nla_put(skb, NDA_LLADDR, ETH_ALEN, addr))
|
||||
if (nla_put(skb, NDA_LLADDR, dev->addr_len, addr))
|
||||
goto nla_put_failure;
|
||||
if (vid)
|
||||
if (nla_put(skb, NDA_VLAN, sizeof(u16), &vid))
|
||||
@@ -3925,10 +3925,10 @@ nla_put_failure:
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static inline size_t rtnl_fdb_nlmsg_size(void)
|
||||
static inline size_t rtnl_fdb_nlmsg_size(const struct net_device *dev)
|
||||
{
|
||||
return NLMSG_ALIGN(sizeof(struct ndmsg)) +
|
||||
nla_total_size(ETH_ALEN) + /* NDA_LLADDR */
|
||||
nla_total_size(dev->addr_len) + /* NDA_LLADDR */
|
||||
nla_total_size(sizeof(u16)) + /* NDA_VLAN */
|
||||
0;
|
||||
}
|
||||
@@ -3940,7 +3940,7 @@ static void rtnl_fdb_notify(struct net_device *dev, u8 *addr, u16 vid, int type,
|
||||
struct sk_buff *skb;
|
||||
int err = -ENOBUFS;
|
||||
|
||||
skb = nlmsg_new(rtnl_fdb_nlmsg_size(), GFP_ATOMIC);
|
||||
skb = nlmsg_new(rtnl_fdb_nlmsg_size(dev), GFP_ATOMIC);
|
||||
if (!skb)
|
||||
goto errout;
|
||||
|
||||
|
||||
@@ -2330,13 +2330,24 @@ kuid_t sock_i_uid(struct sock *sk)
|
||||
}
|
||||
EXPORT_SYMBOL(sock_i_uid);
|
||||
|
||||
unsigned long __sock_i_ino(struct sock *sk)
|
||||
{
|
||||
unsigned long ino;
|
||||
|
||||
read_lock(&sk->sk_callback_lock);
|
||||
ino = sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_ino : 0;
|
||||
read_unlock(&sk->sk_callback_lock);
|
||||
return ino;
|
||||
}
|
||||
EXPORT_SYMBOL(__sock_i_ino);
|
||||
|
||||
unsigned long sock_i_ino(struct sock *sk)
|
||||
{
|
||||
unsigned long ino;
|
||||
|
||||
read_lock_bh(&sk->sk_callback_lock);
|
||||
ino = sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_ino : 0;
|
||||
read_unlock_bh(&sk->sk_callback_lock);
|
||||
local_bh_disable();
|
||||
ino = __sock_i_ino(sk);
|
||||
local_bh_enable();
|
||||
return ino;
|
||||
}
|
||||
EXPORT_SYMBOL(sock_i_ino);
|
||||
|
||||
@@ -432,9 +432,19 @@ static bool dccp_error(const struct dccp_hdr *dh,
|
||||
struct sk_buff *skb, unsigned int dataoff,
|
||||
const struct nf_hook_state *state)
|
||||
{
|
||||
static const unsigned long require_seq48 = 1 << DCCP_PKT_REQUEST |
|
||||
1 << DCCP_PKT_RESPONSE |
|
||||
1 << DCCP_PKT_CLOSEREQ |
|
||||
1 << DCCP_PKT_CLOSE |
|
||||
1 << DCCP_PKT_RESET |
|
||||
1 << DCCP_PKT_SYNC |
|
||||
1 << DCCP_PKT_SYNCACK;
|
||||
unsigned int dccp_len = skb->len - dataoff;
|
||||
unsigned int cscov;
|
||||
const char *msg;
|
||||
u8 type;
|
||||
|
||||
BUILD_BUG_ON(DCCP_PKT_INVALID >= BITS_PER_LONG);
|
||||
|
||||
if (dh->dccph_doff * 4 < sizeof(struct dccp_hdr) ||
|
||||
dh->dccph_doff * 4 > dccp_len) {
|
||||
@@ -459,34 +469,70 @@ static bool dccp_error(const struct dccp_hdr *dh,
|
||||
goto out_invalid;
|
||||
}
|
||||
|
||||
if (dh->dccph_type >= DCCP_PKT_INVALID) {
|
||||
type = dh->dccph_type;
|
||||
if (type >= DCCP_PKT_INVALID) {
|
||||
msg = "nf_ct_dccp: reserved packet type ";
|
||||
goto out_invalid;
|
||||
}
|
||||
|
||||
if (test_bit(type, &require_seq48) && !dh->dccph_x) {
|
||||
msg = "nf_ct_dccp: type lacks 48bit sequence numbers";
|
||||
goto out_invalid;
|
||||
}
|
||||
|
||||
return false;
|
||||
out_invalid:
|
||||
nf_l4proto_log_invalid(skb, state, IPPROTO_DCCP, "%s", msg);
|
||||
return true;
|
||||
}
|
||||
|
||||
struct nf_conntrack_dccp_buf {
|
||||
struct dccp_hdr dh; /* generic header part */
|
||||
struct dccp_hdr_ext ext; /* optional depending dh->dccph_x */
|
||||
union { /* depends on header type */
|
||||
struct dccp_hdr_ack_bits ack;
|
||||
struct dccp_hdr_request req;
|
||||
struct dccp_hdr_response response;
|
||||
struct dccp_hdr_reset rst;
|
||||
} u;
|
||||
};
|
||||
|
||||
static struct dccp_hdr *
|
||||
dccp_header_pointer(const struct sk_buff *skb, int offset, const struct dccp_hdr *dh,
|
||||
struct nf_conntrack_dccp_buf *buf)
|
||||
{
|
||||
unsigned int hdrlen = __dccp_hdr_len(dh);
|
||||
|
||||
if (hdrlen > sizeof(*buf))
|
||||
return NULL;
|
||||
|
||||
return skb_header_pointer(skb, offset, hdrlen, buf);
|
||||
}
|
||||
|
||||
int nf_conntrack_dccp_packet(struct nf_conn *ct, struct sk_buff *skb,
|
||||
unsigned int dataoff,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
const struct nf_hook_state *state)
|
||||
{
|
||||
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
|
||||
struct dccp_hdr _dh, *dh;
|
||||
struct nf_conntrack_dccp_buf _dh;
|
||||
u_int8_t type, old_state, new_state;
|
||||
enum ct_dccp_roles role;
|
||||
unsigned int *timeouts;
|
||||
struct dccp_hdr *dh;
|
||||
|
||||
dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh);
|
||||
dh = skb_header_pointer(skb, dataoff, sizeof(*dh), &_dh.dh);
|
||||
if (!dh)
|
||||
return NF_DROP;
|
||||
|
||||
if (dccp_error(dh, skb, dataoff, state))
|
||||
return -NF_ACCEPT;
|
||||
|
||||
/* pull again, including possible 48 bit sequences and subtype header */
|
||||
dh = dccp_header_pointer(skb, dataoff, dh, &_dh);
|
||||
if (!dh)
|
||||
return NF_DROP;
|
||||
|
||||
type = dh->dccph_type;
|
||||
if (!nf_ct_is_confirmed(ct) && !dccp_new(ct, skb, dh, state))
|
||||
return -NF_ACCEPT;
|
||||
|
||||
@@ -611,7 +611,7 @@ int ct_sip_parse_numerical_param(const struct nf_conn *ct, const char *dptr,
|
||||
start += strlen(name);
|
||||
*val = simple_strtoul(start, &end, 0);
|
||||
if (start == end)
|
||||
return 0;
|
||||
return -1;
|
||||
if (matchoff && matchlen) {
|
||||
*matchoff = start - dptr;
|
||||
*matchlen = end - start;
|
||||
|
||||
@@ -1610,6 +1610,7 @@ out:
|
||||
int netlink_set_err(struct sock *ssk, u32 portid, u32 group, int code)
|
||||
{
|
||||
struct netlink_set_err_data info;
|
||||
unsigned long flags;
|
||||
struct sock *sk;
|
||||
int ret = 0;
|
||||
|
||||
@@ -1619,12 +1620,12 @@ int netlink_set_err(struct sock *ssk, u32 portid, u32 group, int code)
|
||||
/* sk->sk_err wants a positive error value */
|
||||
info.code = -code;
|
||||
|
||||
read_lock(&nl_table_lock);
|
||||
read_lock_irqsave(&nl_table_lock, flags);
|
||||
|
||||
sk_for_each_bound(sk, &nl_table[ssk->sk_protocol].mc_list)
|
||||
ret += do_one_set_err(sk, &info);
|
||||
|
||||
read_unlock(&nl_table_lock);
|
||||
read_unlock_irqrestore(&nl_table_lock, flags);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(netlink_set_err);
|
||||
|
||||
@@ -94,6 +94,7 @@ static int __netlink_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
|
||||
struct net *net = sock_net(skb->sk);
|
||||
struct netlink_diag_req *req;
|
||||
struct netlink_sock *nlsk;
|
||||
unsigned long flags;
|
||||
struct sock *sk;
|
||||
int num = 2;
|
||||
int ret = 0;
|
||||
@@ -152,7 +153,7 @@ static int __netlink_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
|
||||
num++;
|
||||
|
||||
mc_list:
|
||||
read_lock(&nl_table_lock);
|
||||
read_lock_irqsave(&nl_table_lock, flags);
|
||||
sk_for_each_bound(sk, &tbl->mc_list) {
|
||||
if (sk_hashed(sk))
|
||||
continue;
|
||||
@@ -167,13 +168,13 @@ mc_list:
|
||||
NETLINK_CB(cb->skb).portid,
|
||||
cb->nlh->nlmsg_seq,
|
||||
NLM_F_MULTI,
|
||||
sock_i_ino(sk)) < 0) {
|
||||
__sock_i_ino(sk)) < 0) {
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
num++;
|
||||
}
|
||||
read_unlock(&nl_table_lock);
|
||||
read_unlock_irqrestore(&nl_table_lock, flags);
|
||||
|
||||
done:
|
||||
cb->args[0] = num;
|
||||
|
||||
@@ -202,7 +202,6 @@ void nfc_llcp_sock_link(struct llcp_sock_list *l, struct sock *s);
|
||||
void nfc_llcp_sock_unlink(struct llcp_sock_list *l, struct sock *s);
|
||||
void nfc_llcp_socket_remote_param_init(struct nfc_llcp_sock *sock);
|
||||
struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev);
|
||||
struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local);
|
||||
int nfc_llcp_local_put(struct nfc_llcp_local *local);
|
||||
u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local,
|
||||
struct nfc_llcp_sock *sock);
|
||||
|
||||
@@ -361,6 +361,7 @@ int nfc_llcp_send_symm(struct nfc_dev *dev)
|
||||
struct sk_buff *skb;
|
||||
struct nfc_llcp_local *local;
|
||||
u16 size = 0;
|
||||
int err;
|
||||
|
||||
pr_debug("Sending SYMM\n");
|
||||
|
||||
@@ -372,8 +373,10 @@ int nfc_llcp_send_symm(struct nfc_dev *dev)
|
||||
size += dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE;
|
||||
|
||||
skb = alloc_skb(size, GFP_KERNEL);
|
||||
if (skb == NULL)
|
||||
return -ENOMEM;
|
||||
if (skb == NULL) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE);
|
||||
|
||||
@@ -383,8 +386,11 @@ int nfc_llcp_send_symm(struct nfc_dev *dev)
|
||||
|
||||
nfc_llcp_send_to_raw_sock(local, skb, NFC_DIRECTION_TX);
|
||||
|
||||
return nfc_data_exchange(dev, local->target_idx, skb,
|
||||
err = nfc_data_exchange(dev, local->target_idx, skb,
|
||||
nfc_llcp_recv, local);
|
||||
out:
|
||||
nfc_llcp_local_put(local);
|
||||
return err;
|
||||
}
|
||||
|
||||
int nfc_llcp_send_connect(struct nfc_llcp_sock *sock)
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
static u8 llcp_magic[3] = {0x46, 0x66, 0x6d};
|
||||
|
||||
static LIST_HEAD(llcp_devices);
|
||||
/* Protects llcp_devices list */
|
||||
static DEFINE_SPINLOCK(llcp_devices_lock);
|
||||
|
||||
static void nfc_llcp_rx_skb(struct nfc_llcp_local *local, struct sk_buff *skb);
|
||||
|
||||
@@ -143,7 +145,7 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool device,
|
||||
write_unlock(&local->raw_sockets.lock);
|
||||
}
|
||||
|
||||
struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local)
|
||||
static struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local)
|
||||
{
|
||||
kref_get(&local->ref);
|
||||
|
||||
@@ -171,7 +173,6 @@ static void local_release(struct kref *ref)
|
||||
|
||||
local = container_of(ref, struct nfc_llcp_local, ref);
|
||||
|
||||
list_del(&local->list);
|
||||
local_cleanup(local);
|
||||
kfree(local);
|
||||
}
|
||||
@@ -284,12 +285,33 @@ static void nfc_llcp_sdreq_timer(struct timer_list *t)
|
||||
struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev)
|
||||
{
|
||||
struct nfc_llcp_local *local;
|
||||
struct nfc_llcp_local *res = NULL;
|
||||
|
||||
spin_lock(&llcp_devices_lock);
|
||||
list_for_each_entry(local, &llcp_devices, list)
|
||||
if (local->dev == dev)
|
||||
return local;
|
||||
if (local->dev == dev) {
|
||||
res = nfc_llcp_local_get(local);
|
||||
break;
|
||||
}
|
||||
spin_unlock(&llcp_devices_lock);
|
||||
|
||||
pr_debug("No device found\n");
|
||||
return res;
|
||||
}
|
||||
|
||||
static struct nfc_llcp_local *nfc_llcp_remove_local(struct nfc_dev *dev)
|
||||
{
|
||||
struct nfc_llcp_local *local, *tmp;
|
||||
|
||||
spin_lock(&llcp_devices_lock);
|
||||
list_for_each_entry_safe(local, tmp, &llcp_devices, list)
|
||||
if (local->dev == dev) {
|
||||
list_del(&local->list);
|
||||
spin_unlock(&llcp_devices_lock);
|
||||
return local;
|
||||
}
|
||||
spin_unlock(&llcp_devices_lock);
|
||||
|
||||
pr_warn("Shutting down device not found\n");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -610,12 +632,15 @@ u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len)
|
||||
|
||||
*general_bytes_len = local->gb_len;
|
||||
|
||||
nfc_llcp_local_put(local);
|
||||
|
||||
return local->gb;
|
||||
}
|
||||
|
||||
int nfc_llcp_set_remote_gb(struct nfc_dev *dev, const u8 *gb, u8 gb_len)
|
||||
{
|
||||
struct nfc_llcp_local *local;
|
||||
int err;
|
||||
|
||||
if (gb_len < 3 || gb_len > NFC_MAX_GT_LEN)
|
||||
return -EINVAL;
|
||||
@@ -632,12 +657,16 @@ int nfc_llcp_set_remote_gb(struct nfc_dev *dev, const u8 *gb, u8 gb_len)
|
||||
|
||||
if (memcmp(local->remote_gb, llcp_magic, 3)) {
|
||||
pr_err("MAC does not support LLCP\n");
|
||||
return -EINVAL;
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
return nfc_llcp_parse_gb_tlv(local,
|
||||
err = nfc_llcp_parse_gb_tlv(local,
|
||||
&local->remote_gb[3],
|
||||
local->remote_gb_len - 3);
|
||||
out:
|
||||
nfc_llcp_local_put(local);
|
||||
return err;
|
||||
}
|
||||
|
||||
static u8 nfc_llcp_dsap(const struct sk_buff *pdu)
|
||||
@@ -1527,6 +1556,8 @@ int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb)
|
||||
|
||||
__nfc_llcp_recv(local, skb);
|
||||
|
||||
nfc_llcp_local_put(local);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1543,6 +1574,8 @@ void nfc_llcp_mac_is_down(struct nfc_dev *dev)
|
||||
|
||||
/* Close and purge all existing sockets */
|
||||
nfc_llcp_socket_release(local, true, 0);
|
||||
|
||||
nfc_llcp_local_put(local);
|
||||
}
|
||||
|
||||
void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx,
|
||||
@@ -1568,6 +1601,8 @@ void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx,
|
||||
mod_timer(&local->link_timer,
|
||||
jiffies + msecs_to_jiffies(local->remote_lto));
|
||||
}
|
||||
|
||||
nfc_llcp_local_put(local);
|
||||
}
|
||||
|
||||
int nfc_llcp_register_device(struct nfc_dev *ndev)
|
||||
@@ -1618,7 +1653,7 @@ int nfc_llcp_register_device(struct nfc_dev *ndev)
|
||||
|
||||
void nfc_llcp_unregister_device(struct nfc_dev *dev)
|
||||
{
|
||||
struct nfc_llcp_local *local = nfc_llcp_find_local(dev);
|
||||
struct nfc_llcp_local *local = nfc_llcp_remove_local(dev);
|
||||
|
||||
if (local == NULL) {
|
||||
pr_debug("No such device\n");
|
||||
|
||||
@@ -99,7 +99,7 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
|
||||
}
|
||||
|
||||
llcp_sock->dev = dev;
|
||||
llcp_sock->local = nfc_llcp_local_get(local);
|
||||
llcp_sock->local = local;
|
||||
llcp_sock->nfc_protocol = llcp_addr.nfc_protocol;
|
||||
llcp_sock->service_name_len = min_t(unsigned int,
|
||||
llcp_addr.service_name_len,
|
||||
@@ -181,7 +181,7 @@ static int llcp_raw_sock_bind(struct socket *sock, struct sockaddr *addr,
|
||||
}
|
||||
|
||||
llcp_sock->dev = dev;
|
||||
llcp_sock->local = nfc_llcp_local_get(local);
|
||||
llcp_sock->local = local;
|
||||
llcp_sock->nfc_protocol = llcp_addr.nfc_protocol;
|
||||
|
||||
nfc_llcp_sock_link(&local->raw_sockets, sk);
|
||||
@@ -698,24 +698,22 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
|
||||
if (dev->dep_link_up == false) {
|
||||
ret = -ENOLINK;
|
||||
device_unlock(&dev->dev);
|
||||
goto put_dev;
|
||||
goto sock_llcp_put_local;
|
||||
}
|
||||
device_unlock(&dev->dev);
|
||||
|
||||
if (local->rf_mode == NFC_RF_INITIATOR &&
|
||||
addr->target_idx != local->target_idx) {
|
||||
ret = -ENOLINK;
|
||||
goto put_dev;
|
||||
goto sock_llcp_put_local;
|
||||
}
|
||||
|
||||
llcp_sock->dev = dev;
|
||||
llcp_sock->local = nfc_llcp_local_get(local);
|
||||
llcp_sock->local = local;
|
||||
llcp_sock->ssap = nfc_llcp_get_local_ssap(local);
|
||||
if (llcp_sock->ssap == LLCP_SAP_MAX) {
|
||||
nfc_llcp_local_put(llcp_sock->local);
|
||||
llcp_sock->local = NULL;
|
||||
ret = -ENOMEM;
|
||||
goto put_dev;
|
||||
goto sock_llcp_nullify;
|
||||
}
|
||||
|
||||
llcp_sock->reserved_ssap = llcp_sock->ssap;
|
||||
@@ -760,8 +758,13 @@ sock_unlink:
|
||||
|
||||
sock_llcp_release:
|
||||
nfc_llcp_put_ssap(local, llcp_sock->ssap);
|
||||
nfc_llcp_local_put(llcp_sock->local);
|
||||
|
||||
sock_llcp_nullify:
|
||||
llcp_sock->local = NULL;
|
||||
llcp_sock->dev = NULL;
|
||||
|
||||
sock_llcp_put_local:
|
||||
nfc_llcp_local_put(local);
|
||||
|
||||
put_dev:
|
||||
nfc_put_device(dev);
|
||||
|
||||
@@ -1039,11 +1039,14 @@ static int nfc_genl_llc_get_params(struct sk_buff *skb, struct genl_info *info)
|
||||
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||
if (!msg) {
|
||||
rc = -ENOMEM;
|
||||
goto exit;
|
||||
goto put_local;
|
||||
}
|
||||
|
||||
rc = nfc_genl_send_params(msg, local, info->snd_portid, info->snd_seq);
|
||||
|
||||
put_local:
|
||||
nfc_llcp_local_put(local);
|
||||
|
||||
exit:
|
||||
device_unlock(&dev->dev);
|
||||
|
||||
@@ -1105,7 +1108,7 @@ static int nfc_genl_llc_set_params(struct sk_buff *skb, struct genl_info *info)
|
||||
if (info->attrs[NFC_ATTR_LLC_PARAM_LTO]) {
|
||||
if (dev->dep_link_up) {
|
||||
rc = -EINPROGRESS;
|
||||
goto exit;
|
||||
goto put_local;
|
||||
}
|
||||
|
||||
local->lto = nla_get_u8(info->attrs[NFC_ATTR_LLC_PARAM_LTO]);
|
||||
@@ -1117,6 +1120,9 @@ static int nfc_genl_llc_set_params(struct sk_buff *skb, struct genl_info *info)
|
||||
if (info->attrs[NFC_ATTR_LLC_PARAM_MIUX])
|
||||
local->miux = cpu_to_be16(miux);
|
||||
|
||||
put_local:
|
||||
nfc_llcp_local_put(local);
|
||||
|
||||
exit:
|
||||
device_unlock(&dev->dev);
|
||||
|
||||
@@ -1172,7 +1178,7 @@ static int nfc_genl_llc_sdreq(struct sk_buff *skb, struct genl_info *info)
|
||||
|
||||
if (rc != 0) {
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
goto put_local;
|
||||
}
|
||||
|
||||
if (!sdp_attrs[NFC_SDP_ATTR_URI])
|
||||
@@ -1191,7 +1197,7 @@ static int nfc_genl_llc_sdreq(struct sk_buff *skb, struct genl_info *info)
|
||||
sdreq = nfc_llcp_build_sdreq_tlv(tid, uri, uri_len);
|
||||
if (sdreq == NULL) {
|
||||
rc = -ENOMEM;
|
||||
goto exit;
|
||||
goto put_local;
|
||||
}
|
||||
|
||||
tlvs_len += sdreq->tlv_len;
|
||||
@@ -1201,10 +1207,14 @@ static int nfc_genl_llc_sdreq(struct sk_buff *skb, struct genl_info *info)
|
||||
|
||||
if (hlist_empty(&sdreq_list)) {
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
goto put_local;
|
||||
}
|
||||
|
||||
rc = nfc_llcp_send_snl_sdreq(local, &sdreq_list, tlvs_len);
|
||||
|
||||
put_local:
|
||||
nfc_llcp_local_put(local);
|
||||
|
||||
exit:
|
||||
device_unlock(&dev->dev);
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ int nfc_llcp_set_remote_gb(struct nfc_dev *dev, const u8 *gb, u8 gb_len);
|
||||
u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len);
|
||||
int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb);
|
||||
struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev);
|
||||
int nfc_llcp_local_put(struct nfc_llcp_local *local);
|
||||
int __init nfc_llcp_init(void);
|
||||
void nfc_llcp_exit(void);
|
||||
void nfc_llcp_free_sdp_tlv(struct nfc_llcp_sdp_tlv *sdp);
|
||||
|
||||
@@ -835,6 +835,7 @@ EOF
|
||||
fi
|
||||
|
||||
# clean up any leftovers
|
||||
echo 0 > /sys/bus/netdevsim/del_device
|
||||
$probed && rmmod netdevsim
|
||||
|
||||
if [ $ret -ne 0 ]; then
|
||||
|
||||
Reference in New Issue
Block a user