diff options
Diffstat (limited to 'drivers/net')
438 files changed, 23194 insertions, 14256 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index f9009be3f307..b6d64f546574 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -145,6 +145,24 @@ config MACVTAP To compile this driver as a module, choose M here: the module will be called macvtap. + +config IPVLAN + tristate "IP-VLAN support" + ---help--- + This allows one to create virtual devices off of a main interface + and packets will be delivered based on the dest L3 (IPv6/IPv4 addr) + on packets. All interfaces (including the main interface) share L2 + making it transparent to the connected L2 switch. + + Ipvlan devices can be added using the "ip" command from the + iproute2 package starting with the iproute2-X.Y.ZZ release: + + "ip link add link <main-dev> [ NAME ] type ipvlan" + + To compile this driver as a module, choose M here: the module + will be called ipvlan. + + config VXLAN tristate "Virtual eXtensible Local Area Network (VXLAN)" depends on INET diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 61aefdd1e173..e25fdd7d905e 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -6,6 +6,7 @@ # Networking Core Drivers # obj-$(CONFIG_BONDING) += bonding/ +obj-$(CONFIG_IPVLAN) += ipvlan/ obj-$(CONFIG_DUMMY) += dummy.o obj-$(CONFIG_EQUALIZER) += eql.o obj-$(CONFIG_IFB) += ifb.o diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index 2110215f3528..8baa87df1738 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -29,8 +29,8 @@ #include <linux/if_bonding.h> #include <linux/pkt_sched.h> #include <net/net_namespace.h> -#include "bonding.h" -#include "bond_3ad.h" +#include <net/bonding.h> +#include <net/bond_3ad.h> /* General definitions */ #define AD_SHORT_TIMEOUT 1 @@ -79,15 +79,21 @@ * -------------------------------------------------------------- * 16 6 1 0 */ -#define AD_DUPLEX_KEY_BITS 0x1 -#define AD_SPEED_KEY_BITS 0x3E -#define AD_USER_KEY_BITS 0xFFC0 - -#define AD_LINK_SPEED_BITMASK_1MBPS 0x1 -#define AD_LINK_SPEED_BITMASK_10MBPS 0x2 -#define AD_LINK_SPEED_BITMASK_100MBPS 0x4 -#define AD_LINK_SPEED_BITMASK_1000MBPS 0x8 -#define AD_LINK_SPEED_BITMASK_10000MBPS 0x10 +#define AD_DUPLEX_KEY_MASKS 0x1 +#define AD_SPEED_KEY_MASKS 0x3E +#define AD_USER_KEY_MASKS 0xFFC0 + +enum ad_link_speed_type { + AD_LINK_SPEED_1MBPS = 1, + AD_LINK_SPEED_10MBPS, + AD_LINK_SPEED_100MBPS, + AD_LINK_SPEED_1000MBPS, + AD_LINK_SPEED_2500MBPS, + AD_LINK_SPEED_10000MBPS, + AD_LINK_SPEED_20000MBPS, + AD_LINK_SPEED_40000MBPS, + AD_LINK_SPEED_56000MBPS +}; /* compare MAC addresses */ #define MAC_ADDRESS_EQUAL(A, B) \ @@ -240,12 +246,16 @@ static inline int __check_agg_selection_timer(struct port *port) * __get_link_speed - get a port's speed * @port: the port we're looking at * - * Return @port's speed in 802.3ad bitmask format. i.e. one of: + * Return @port's speed in 802.3ad enum format. i.e. one of: * 0, - * %AD_LINK_SPEED_BITMASK_10MBPS, - * %AD_LINK_SPEED_BITMASK_100MBPS, - * %AD_LINK_SPEED_BITMASK_1000MBPS, - * %AD_LINK_SPEED_BITMASK_10000MBPS + * %AD_LINK_SPEED_10MBPS, + * %AD_LINK_SPEED_100MBPS, + * %AD_LINK_SPEED_1000MBPS, + * %AD_LINK_SPEED_2500MBPS, + * %AD_LINK_SPEED_10000MBPS + * %AD_LINK_SPEED_20000MBPS + * %AD_LINK_SPEED_40000MBPS + * %AD_LINK_SPEED_56000MBPS */ static u16 __get_link_speed(struct port *port) { @@ -262,19 +272,35 @@ static u16 __get_link_speed(struct port *port) else { switch (slave->speed) { case SPEED_10: - speed = AD_LINK_SPEED_BITMASK_10MBPS; + speed = AD_LINK_SPEED_10MBPS; break; case SPEED_100: - speed = AD_LINK_SPEED_BITMASK_100MBPS; + speed = AD_LINK_SPEED_100MBPS; break; case SPEED_1000: - speed = AD_LINK_SPEED_BITMASK_1000MBPS; + speed = AD_LINK_SPEED_1000MBPS; + break; + + case SPEED_2500: + speed = AD_LINK_SPEED_2500MBPS; break; case SPEED_10000: - speed = AD_LINK_SPEED_BITMASK_10000MBPS; + speed = AD_LINK_SPEED_10000MBPS; + break; + + case SPEED_20000: + speed = AD_LINK_SPEED_20000MBPS; + break; + + case SPEED_40000: + speed = AD_LINK_SPEED_40000MBPS; + break; + + case SPEED_56000: + speed = AD_LINK_SPEED_56000MBPS; break; default: @@ -625,21 +651,33 @@ static u32 __get_agg_bandwidth(struct aggregator *aggregator) if (aggregator->num_of_ports) { switch (__get_link_speed(aggregator->lag_ports)) { - case AD_LINK_SPEED_BITMASK_1MBPS: + case AD_LINK_SPEED_1MBPS: bandwidth = aggregator->num_of_ports; break; - case AD_LINK_SPEED_BITMASK_10MBPS: + case AD_LINK_SPEED_10MBPS: bandwidth = aggregator->num_of_ports * 10; break; - case AD_LINK_SPEED_BITMASK_100MBPS: + case AD_LINK_SPEED_100MBPS: bandwidth = aggregator->num_of_ports * 100; break; - case AD_LINK_SPEED_BITMASK_1000MBPS: + case AD_LINK_SPEED_1000MBPS: bandwidth = aggregator->num_of_ports * 1000; break; - case AD_LINK_SPEED_BITMASK_10000MBPS: + case AD_LINK_SPEED_2500MBPS: + bandwidth = aggregator->num_of_ports * 2500; + break; + case AD_LINK_SPEED_10000MBPS: bandwidth = aggregator->num_of_ports * 10000; break; + case AD_LINK_SPEED_20000MBPS: + bandwidth = aggregator->num_of_ports * 20000; + break; + case AD_LINK_SPEED_40000MBPS: + bandwidth = aggregator->num_of_ports * 40000; + break; + case AD_LINK_SPEED_56000MBPS: + bandwidth = aggregator->num_of_ports * 56000; + break; default: bandwidth = 0; /* to silence the compiler */ } @@ -1011,7 +1049,7 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port) port->sm_rx_state); switch (port->sm_rx_state) { case AD_RX_INITIALIZE: - if (!(port->actor_oper_port_key & AD_DUPLEX_KEY_BITS)) + if (!(port->actor_oper_port_key & AD_DUPLEX_KEY_MASKS)) port->sm_vars &= ~AD_PORT_LACP_ENABLED; else port->sm_vars |= AD_PORT_LACP_ENABLED; @@ -1318,7 +1356,7 @@ static void ad_port_selection_logic(struct port *port, bool *update_slave_arr) /* update the new aggregator's parameters * if port was responsed from the end-user */ - if (port->actor_oper_port_key & AD_DUPLEX_KEY_BITS) + if (port->actor_oper_port_key & AD_DUPLEX_KEY_MASKS) /* if port is full duplex */ port->aggregator->is_individual = false; else @@ -1846,7 +1884,7 @@ void bond_3ad_bind_slave(struct slave *slave) /* if the port is not full duplex, then the port should be not * lacp Enabled */ - if (!(port->actor_oper_port_key & AD_DUPLEX_KEY_BITS)) + if (!(port->actor_oper_port_key & AD_DUPLEX_KEY_MASKS)) port->sm_vars &= ~AD_PORT_LACP_ENABLED; /* actor system is the bond's system */ port->actor_system = BOND_AD_INFO(bond).system.sys_mac_addr; @@ -2214,7 +2252,7 @@ void bond_3ad_adapter_speed_changed(struct slave *slave) spin_lock_bh(&slave->bond->mode_lock); - port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS; + port->actor_admin_port_key &= ~AD_SPEED_KEY_MASKS; port->actor_oper_port_key = port->actor_admin_port_key |= (__get_link_speed(port) << 1); netdev_dbg(slave->bond->dev, "Port %d changed speed\n", port->actor_port_number); @@ -2247,7 +2285,7 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave) spin_lock_bh(&slave->bond->mode_lock); - port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS; + port->actor_admin_port_key &= ~AD_DUPLEX_KEY_MASKS; port->actor_oper_port_key = port->actor_admin_port_key |= __get_duplex(port); netdev_dbg(slave->bond->dev, "Port %d changed duplex\n", port->actor_port_number); @@ -2289,18 +2327,18 @@ void bond_3ad_handle_link_change(struct slave *slave, char link) */ if (link == BOND_LINK_UP) { port->is_enabled = true; - port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS; + port->actor_admin_port_key &= ~AD_DUPLEX_KEY_MASKS; port->actor_oper_port_key = port->actor_admin_port_key |= __get_duplex(port); - port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS; + port->actor_admin_port_key &= ~AD_SPEED_KEY_MASKS; port->actor_oper_port_key = port->actor_admin_port_key |= (__get_link_speed(port) << 1); } else { /* link has failed */ port->is_enabled = false; - port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS; + port->actor_admin_port_key &= ~AD_DUPLEX_KEY_MASKS; port->actor_oper_port_key = (port->actor_admin_port_key &= - ~AD_SPEED_KEY_BITS); + ~AD_SPEED_KEY_MASKS); } netdev_dbg(slave->bond->dev, "Port %d changed link status to %s\n", port->actor_port_number, diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h deleted file mode 100644 index c5f14ac63f3e..000000000000 --- a/drivers/net/bonding/bond_3ad.h +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - */ - -#ifndef __BOND_3AD_H__ -#define __BOND_3AD_H__ - -#include <asm/byteorder.h> -#include <linux/skbuff.h> -#include <linux/netdevice.h> -#include <linux/if_ether.h> - -/* General definitions */ -#define PKT_TYPE_LACPDU cpu_to_be16(ETH_P_SLOW) -#define AD_TIMER_INTERVAL 100 /*msec*/ - -#define MULTICAST_LACPDU_ADDR {0x01, 0x80, 0xC2, 0x00, 0x00, 0x02} - -#define AD_LACP_SLOW 0 -#define AD_LACP_FAST 1 - -typedef struct mac_addr { - u8 mac_addr_value[ETH_ALEN]; -} __packed mac_addr_t; - -enum { - BOND_AD_STABLE = 0, - BOND_AD_BANDWIDTH = 1, - BOND_AD_COUNT = 2, -}; - -/* rx machine states(43.4.11 in the 802.3ad standard) */ -typedef enum { - AD_RX_DUMMY, - AD_RX_INITIALIZE, /* rx Machine */ - AD_RX_PORT_DISABLED, /* rx Machine */ - AD_RX_LACP_DISABLED, /* rx Machine */ - AD_RX_EXPIRED, /* rx Machine */ - AD_RX_DEFAULTED, /* rx Machine */ - AD_RX_CURRENT /* rx Machine */ -} rx_states_t; - -/* periodic machine states(43.4.12 in the 802.3ad standard) */ -typedef enum { - AD_PERIODIC_DUMMY, - AD_NO_PERIODIC, /* periodic machine */ - AD_FAST_PERIODIC, /* periodic machine */ - AD_SLOW_PERIODIC, /* periodic machine */ - AD_PERIODIC_TX /* periodic machine */ -} periodic_states_t; - -/* mux machine states(43.4.13 in the 802.3ad standard) */ -typedef enum { - AD_MUX_DUMMY, - AD_MUX_DETACHED, /* mux machine */ - AD_MUX_WAITING, /* mux machine */ - AD_MUX_ATTACHED, /* mux machine */ - AD_MUX_COLLECTING_DISTRIBUTING /* mux machine */ -} mux_states_t; - -/* tx machine states(43.4.15 in the 802.3ad standard) */ -typedef enum { - AD_TX_DUMMY, - AD_TRANSMIT /* tx Machine */ -} tx_states_t; - -/* rx indication types */ -typedef enum { - AD_TYPE_LACPDU = 1, /* type lacpdu */ - AD_TYPE_MARKER /* type marker */ -} pdu_type_t; - -/* rx marker indication types */ -typedef enum { - AD_MARKER_INFORMATION_SUBTYPE = 1, /* marker imformation subtype */ - AD_MARKER_RESPONSE_SUBTYPE /* marker response subtype */ -} bond_marker_subtype_t; - -/* timers types(43.4.9 in the 802.3ad standard) */ -typedef enum { - AD_CURRENT_WHILE_TIMER, - AD_ACTOR_CHURN_TIMER, - AD_PERIODIC_TIMER, - AD_PARTNER_CHURN_TIMER, - AD_WAIT_WHILE_TIMER -} ad_timers_t; - -#pragma pack(1) - -/* Link Aggregation Control Protocol(LACP) data unit structure(43.4.2.2 in the 802.3ad standard) */ -typedef struct lacpdu { - u8 subtype; /* = LACP(= 0x01) */ - u8 version_number; - u8 tlv_type_actor_info; /* = actor information(type/length/value) */ - u8 actor_information_length; /* = 20 */ - __be16 actor_system_priority; - struct mac_addr actor_system; - __be16 actor_key; - __be16 actor_port_priority; - __be16 actor_port; - u8 actor_state; - u8 reserved_3_1[3]; /* = 0 */ - u8 tlv_type_partner_info; /* = partner information */ - u8 partner_information_length; /* = 20 */ - __be16 partner_system_priority; - struct mac_addr partner_system; - __be16 partner_key; - __be16 partner_port_priority; - __be16 partner_port; - u8 partner_state; - u8 reserved_3_2[3]; /* = 0 */ - u8 tlv_type_collector_info; /* = collector information */ - u8 collector_information_length;/* = 16 */ - __be16 collector_max_delay; - u8 reserved_12[12]; - u8 tlv_type_terminator; /* = terminator */ - u8 terminator_length; /* = 0 */ - u8 reserved_50[50]; /* = 0 */ -} __packed lacpdu_t; - -typedef struct lacpdu_header { - struct ethhdr hdr; - struct lacpdu lacpdu; -} __packed lacpdu_header_t; - -/* Marker Protocol Data Unit(PDU) structure(43.5.3.2 in the 802.3ad standard) */ -typedef struct bond_marker { - u8 subtype; /* = 0x02 (marker PDU) */ - u8 version_number; /* = 0x01 */ - u8 tlv_type; /* = 0x01 (marker information) */ - /* = 0x02 (marker response information) */ - u8 marker_length; /* = 0x16 */ - u16 requester_port; /* The number assigned to the port by the requester */ - struct mac_addr requester_system; /* The requester's system id */ - u32 requester_transaction_id; /* The transaction id allocated by the requester, */ - u16 pad; /* = 0 */ - u8 tlv_type_terminator; /* = 0x00 */ - u8 terminator_length; /* = 0x00 */ - u8 reserved_90[90]; /* = 0 */ -} __packed bond_marker_t; - -typedef struct bond_marker_header { - struct ethhdr hdr; - struct bond_marker marker; -} __packed bond_marker_header_t; - -#pragma pack() - -struct slave; -struct bonding; -struct ad_info; -struct port; - -#ifdef __ia64__ -#pragma pack(8) -#endif - -/* aggregator structure(43.4.5 in the 802.3ad standard) */ -typedef struct aggregator { - struct mac_addr aggregator_mac_address; - u16 aggregator_identifier; - bool is_individual; - u16 actor_admin_aggregator_key; - u16 actor_oper_aggregator_key; - struct mac_addr partner_system; - u16 partner_system_priority; - u16 partner_oper_aggregator_key; - u16 receive_state; /* BOOLEAN */ - u16 transmit_state; /* BOOLEAN */ - struct port *lag_ports; - /* ****** PRIVATE PARAMETERS ****** */ - struct slave *slave; /* pointer to the bond slave that this aggregator belongs to */ - u16 is_active; /* BOOLEAN. Indicates if this aggregator is active */ - u16 num_of_ports; -} aggregator_t; - -struct port_params { - struct mac_addr system; - u16 system_priority; - u16 key; - u16 port_number; - u16 port_priority; - u16 port_state; -}; - -/* port structure(43.4.6 in the 802.3ad standard) */ -typedef struct port { - u16 actor_port_number; - u16 actor_port_priority; - struct mac_addr actor_system; /* This parameter is added here although it is not specified in the standard, just for simplification */ - u16 actor_system_priority; /* This parameter is added here although it is not specified in the standard, just for simplification */ - u16 actor_port_aggregator_identifier; - bool ntt; - u16 actor_admin_port_key; - u16 actor_oper_port_key; - u8 actor_admin_port_state; - u8 actor_oper_port_state; - - struct port_params partner_admin; - struct port_params partner_oper; - - bool is_enabled; - - /* ****** PRIVATE PARAMETERS ****** */ - u16 sm_vars; /* all state machines variables for this port */ - rx_states_t sm_rx_state; /* state machine rx state */ - u16 sm_rx_timer_counter; /* state machine rx timer counter */ - periodic_states_t sm_periodic_state; /* state machine periodic state */ - u16 sm_periodic_timer_counter; /* state machine periodic timer counter */ - mux_states_t sm_mux_state; /* state machine mux state */ - u16 sm_mux_timer_counter; /* state machine mux timer counter */ - tx_states_t sm_tx_state; /* state machine tx state */ - u16 sm_tx_timer_counter; /* state machine tx timer counter(allways on - enter to transmit state 3 time per second) */ - struct slave *slave; /* pointer to the bond slave that this port belongs to */ - struct aggregator *aggregator; /* pointer to an aggregator that this port related to */ - struct port *next_port_in_aggregator; /* Next port on the linked list of the parent aggregator */ - u32 transaction_id; /* continuous number for identification of Marker PDU's; */ - struct lacpdu lacpdu; /* the lacpdu that will be sent for this port */ -} port_t; - -/* system structure */ -struct ad_system { - u16 sys_priority; - struct mac_addr sys_mac_addr; -}; - -#ifdef __ia64__ -#pragma pack() -#endif - -/* ========== AD Exported structures to the main bonding code ========== */ -#define BOND_AD_INFO(bond) ((bond)->ad_info) -#define SLAVE_AD_INFO(slave) ((slave)->ad_info) - -struct ad_bond_info { - struct ad_system system; /* 802.3ad system structure */ - u32 agg_select_timer; /* Timer to select aggregator after all adapter's hand shakes */ - u16 aggregator_identifier; -}; - -struct ad_slave_info { - struct aggregator aggregator; /* 802.3ad aggregator structure */ - struct port port; /* 802.3ad port structure */ - u16 id; -}; - -/* ========== AD Exported functions to the main bonding code ========== */ -void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution); -void bond_3ad_bind_slave(struct slave *slave); -void bond_3ad_unbind_slave(struct slave *slave); -void bond_3ad_state_machine_handler(struct work_struct *); -void bond_3ad_initiate_agg_selection(struct bonding *bond, int timeout); -void bond_3ad_adapter_speed_changed(struct slave *slave); -void bond_3ad_adapter_duplex_changed(struct slave *slave); -void bond_3ad_handle_link_change(struct slave *slave, char link); -int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info); -int __bond_3ad_get_active_agg_info(struct bonding *bond, - struct ad_info *ad_info); -int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev); -int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond, - struct slave *slave); -int bond_3ad_set_carrier(struct bonding *bond); -void bond_3ad_update_lacp_rate(struct bonding *bond); -#endif /* __BOND_3AD_H__ */ - diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index d2eadab787c5..bb9e9fc45e1b 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -37,8 +37,8 @@ #include <net/arp.h> #include <net/ipv6.h> #include <asm/byteorder.h> -#include "bonding.h" -#include "bond_alb.h" +#include <net/bonding.h> +#include <net/bond_alb.h> @@ -475,12 +475,8 @@ static void rlb_update_client(struct rlb_client_info *client_info) skb->dev = client_info->slave->dev; if (client_info->vlan_id) { - skb = vlan_put_tag(skb, htons(ETH_P_8021Q), client_info->vlan_id); - if (!skb) { - netdev_err(client_info->slave->bond->dev, - "failed to insert VLAN tag\n"); - continue; - } + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), + client_info->vlan_id); } arp_xmit(skb); @@ -951,13 +947,8 @@ static void alb_send_lp_vid(struct slave *slave, u8 mac_addr[], skb->priority = TC_PRIO_CONTROL; skb->dev = slave->dev; - if (vid) { - skb = vlan_put_tag(skb, vlan_proto, vid); - if (!skb) { - netdev_err(slave->bond->dev, "failed to insert VLAN tag\n"); - return; - } - } + if (vid) + __vlan_hwaccel_put_tag(skb, vlan_proto, vid); dev_queue_xmit(skb); } @@ -1326,7 +1317,7 @@ static int bond_do_alb_xmit(struct sk_buff *skb, struct bonding *bond, } /* no suitable interface, frame not sent */ - dev_kfree_skb_any(skb); + bond_tx_drop(bond->dev, skb); out: return NETDEV_TX_OK; } diff --git a/drivers/net/bonding/bond_alb.h b/drivers/net/bonding/bond_alb.h deleted file mode 100644 index 1ad473b4ade5..000000000000 --- a/drivers/net/bonding/bond_alb.h +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see <http://www.gnu.org/licenses/>. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - */ - -#ifndef __BOND_ALB_H__ -#define __BOND_ALB_H__ - -#include <linux/if_ether.h> - -struct bonding; -struct slave; - -#define BOND_ALB_INFO(bond) ((bond)->alb_info) -#define SLAVE_TLB_INFO(slave) ((slave)->tlb_info) - -#define ALB_TIMER_TICKS_PER_SEC 10 /* should be a divisor of HZ */ -#define BOND_TLB_REBALANCE_INTERVAL 10 /* In seconds, periodic re-balancing. - * Used for division - never set - * to zero !!! - */ -#define BOND_ALB_DEFAULT_LP_INTERVAL 1 -#define BOND_ALB_LP_INTERVAL(bond) (bond->params.lp_interval) /* In seconds, periodic send of - * learning packets to the switch - */ - -#define BOND_TLB_REBALANCE_TICKS (BOND_TLB_REBALANCE_INTERVAL \ - * ALB_TIMER_TICKS_PER_SEC) - -#define BOND_ALB_LP_TICKS(bond) (BOND_ALB_LP_INTERVAL(bond) \ - * ALB_TIMER_TICKS_PER_SEC) - -#define TLB_HASH_TABLE_SIZE 256 /* The size of the clients hash table. - * Note that this value MUST NOT be smaller - * because the key hash table is BYTE wide ! - */ - - -#define TLB_NULL_INDEX 0xffffffff - -/* rlb defs */ -#define RLB_HASH_TABLE_SIZE 256 -#define RLB_NULL_INDEX 0xffffffff -#define RLB_UPDATE_DELAY (2*ALB_TIMER_TICKS_PER_SEC) /* 2 seconds */ -#define RLB_ARP_BURST_SIZE 2 -#define RLB_UPDATE_RETRY 3 /* 3-ticks - must be smaller than the rlb - * rebalance interval (5 min). - */ -/* RLB_PROMISC_TIMEOUT = 10 sec equals the time that the current slave is - * promiscuous after failover - */ -#define RLB_PROMISC_TIMEOUT (10*ALB_TIMER_TICKS_PER_SEC) - - -struct tlb_client_info { - struct slave *tx_slave; /* A pointer to slave used for transmiting - * packets to a Client that the Hash function - * gave this entry index. - */ - u32 tx_bytes; /* Each Client accumulates the BytesTx that - * were transmitted to it, and after each - * CallBack the LoadHistory is divided - * by the balance interval - */ - u32 load_history; /* This field contains the amount of Bytes - * that were transmitted to this client by - * the server on the previous balance - * interval in Bps. - */ - u32 next; /* The next Hash table entry index, assigned - * to use the same adapter for transmit. - */ - u32 prev; /* The previous Hash table entry index, - * assigned to use the same - */ -}; - -/* ------------------------------------------------------------------------- - * struct rlb_client_info contains all info related to a specific rx client - * connection. This is the Clients Hash Table entry struct. - * Note that this is not a proper hash table; if a new client's IP address - * hash collides with an existing client entry, the old entry is replaced. - * - * There is a linked list (linked by the used_next and used_prev members) - * linking all the used entries of the hash table. This allows updating - * all the clients without walking over all the unused elements of the table. - * - * There are also linked lists of entries with identical hash(ip_src). These - * allow cleaning up the table from ip_src<->mac_src associations that have - * become outdated and would cause sending out invalid ARP updates to the - * network. These are linked by the (src_next and src_prev members). - * ------------------------------------------------------------------------- - */ -struct rlb_client_info { - __be32 ip_src; /* the server IP address */ - __be32 ip_dst; /* the client IP address */ - u8 mac_src[ETH_ALEN]; /* the server MAC address */ - u8 mac_dst[ETH_ALEN]; /* the client MAC address */ - - /* list of used hash table entries, starting at rx_hashtbl_used_head */ - u32 used_next; - u32 used_prev; - - /* ip_src based hashing */ - u32 src_next; /* next entry with same hash(ip_src) */ - u32 src_prev; /* prev entry with same hash(ip_src) */ - u32 src_first; /* first entry with hash(ip_src) == this entry's index */ - - u8 assigned; /* checking whether this entry is assigned */ - u8 ntt; /* flag - need to transmit client info */ - struct slave *slave; /* the slave assigned to this client */ - unsigned short vlan_id; /* VLAN tag associated with IP address */ -}; - -struct tlb_slave_info { - u32 head; /* Index to the head of the bi-directional clients - * hash table entries list. The entries in the list - * are the entries that were assigned to use this - * slave for transmit. - */ - u32 load; /* Each slave sums the loadHistory of all clients - * assigned to it - */ -}; - -struct alb_bond_info { - struct tlb_client_info *tx_hashtbl; /* Dynamically allocated */ - u32 unbalanced_load; - int tx_rebalance_counter; - int lp_counter; - /* -------- rlb parameters -------- */ - int rlb_enabled; - struct rlb_client_info *rx_hashtbl; /* Receive hash table */ - u32 rx_hashtbl_used_head; - u8 rx_ntt; /* flag - need to transmit - * to all rx clients - */ - struct slave *rx_slave;/* last slave to xmit from */ - u8 primary_is_promisc; /* boolean */ - u32 rlb_promisc_timeout_counter;/* counts primary - * promiscuity time - */ - u32 rlb_update_delay_counter; - u32 rlb_update_retry_counter;/* counter of retries - * of client update - */ - u8 rlb_rebalance; /* flag - indicates that the - * rx traffic should be - * rebalanced - */ -}; - -int bond_alb_initialize(struct bonding *bond, int rlb_enabled); -void bond_alb_deinitialize(struct bonding *bond); -int bond_alb_init_slave(struct bonding *bond, struct slave *slave); -void bond_alb_deinit_slave(struct bonding *bond, struct slave *slave); -void bond_alb_handle_link_change(struct bonding *bond, struct slave *slave, char link); -void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave); -int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev); -int bond_tlb_xmit(struct sk_buff *skb, struct net_device *bond_dev); -void bond_alb_monitor(struct work_struct *); -int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr); -void bond_alb_clear_vlan(struct bonding *bond, unsigned short vlan_id); -#endif /* __BOND_ALB_H__ */ - diff --git a/drivers/net/bonding/bond_debugfs.c b/drivers/net/bonding/bond_debugfs.c index 8f99082f90eb..e52e25a977fa 100644 --- a/drivers/net/bonding/bond_debugfs.c +++ b/drivers/net/bonding/bond_debugfs.c @@ -3,8 +3,8 @@ #include <linux/device.h> #include <linux/netdevice.h> -#include "bonding.h" -#include "bond_alb.h" +#include <net/bonding.h> +#include <net/bond_alb.h> #if defined(CONFIG_DEBUG_FS) && !defined(CONFIG_NET_NS) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index a5115fb7cf33..184c434ae305 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -77,9 +77,9 @@ #include <net/pkt_sched.h> #include <linux/rculist.h> #include <net/flow_keys.h> -#include "bonding.h" -#include "bond_3ad.h" -#include "bond_alb.h" +#include <net/bonding.h> +#include <net/bond_3ad.h> +#include <net/bond_alb.h> /*---------------------------- Module parameters ----------------------------*/ @@ -1526,6 +1526,9 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) } #endif + if (!(bond_dev->features & NETIF_F_LRO)) + dev_disable_lro(slave_dev); + res = netdev_rx_handler_register(slave_dev, bond_handle_frame, new_slave); if (res) { @@ -2143,8 +2146,8 @@ static void bond_arp_send(struct net_device *slave_dev, int arp_op, netdev_dbg(slave_dev, "inner tag: proto %X vid %X\n", ntohs(outer_tag->vlan_proto), tags->vlan_id); - skb = __vlan_put_tag(skb, tags->vlan_proto, - tags->vlan_id); + skb = vlan_insert_tag_set_proto(skb, tags->vlan_proto, + tags->vlan_id); if (!skb) { net_err_ratelimited("failed to insert inner VLAN tag\n"); return; @@ -2156,12 +2159,8 @@ static void bond_arp_send(struct net_device *slave_dev, int arp_op, if (outer_tag->vlan_id) { netdev_dbg(slave_dev, "outer tag: proto %X vid %X\n", ntohs(outer_tag->vlan_proto), outer_tag->vlan_id); - skb = vlan_put_tag(skb, outer_tag->vlan_proto, - outer_tag->vlan_id); - if (!skb) { - net_err_ratelimited("failed to insert outer VLAN tag\n"); - return; - } + __vlan_hwaccel_put_tag(skb, outer_tag->vlan_proto, + outer_tag->vlan_id); } xmit: @@ -3523,7 +3522,7 @@ static void bond_xmit_slave_id(struct bonding *bond, struct sk_buff *skb, int sl } } /* no slave that can tx has been found */ - dev_kfree_skb_any(skb); + bond_tx_drop(bond->dev, skb); } /** @@ -3585,7 +3584,7 @@ static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev slave_id = bond_rr_gen_slave_id(bond); bond_xmit_slave_id(bond, skb, slave_id % slave_cnt); } else { - dev_kfree_skb_any(skb); + bond_tx_drop(bond_dev, skb); } } @@ -3604,7 +3603,7 @@ static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *bond_d if (slave) bond_dev_queue_xmit(bond, skb, slave->dev); else - dev_kfree_skb_any(skb); + bond_tx_drop(bond_dev, skb); return NETDEV_TX_OK; } @@ -3748,8 +3747,7 @@ int bond_3ad_xor_xmit(struct sk_buff *skb, struct net_device *dev) slave = slaves->arr[bond_xmit_hash(bond, skb) % count]; bond_dev_queue_xmit(bond, skb, slave->dev); } else { - dev_kfree_skb_any(skb); - atomic_long_inc(&dev->tx_dropped); + bond_tx_drop(dev, skb); } return NETDEV_TX_OK; @@ -3779,7 +3777,7 @@ static int bond_xmit_broadcast(struct sk_buff *skb, struct net_device *bond_dev) if (slave && bond_slave_is_up(slave) && slave->link == BOND_LINK_UP) bond_dev_queue_xmit(bond, skb, slave->dev); else - dev_kfree_skb_any(skb); + bond_tx_drop(bond_dev, skb); return NETDEV_TX_OK; } @@ -3859,7 +3857,7 @@ static netdev_tx_t __bond_start_xmit(struct sk_buff *skb, struct net_device *dev /* Should never happen, mode already checked */ netdev_err(dev, "Unknown bonding mode %d\n", BOND_MODE(bond)); WARN_ON_ONCE(1); - dev_kfree_skb_any(skb); + bond_tx_drop(dev, skb); return NETDEV_TX_OK; } } @@ -3879,7 +3877,7 @@ static netdev_tx_t bond_start_xmit(struct sk_buff *skb, struct net_device *dev) if (bond_has_slaves(bond)) ret = __bond_start_xmit(skb, dev); else - dev_kfree_skb_any(skb); + bond_tx_drop(dev, skb); rcu_read_unlock(); return ret; diff --git a/drivers/net/bonding/bond_netlink.c b/drivers/net/bonding/bond_netlink.c index c13d83e15ace..3e6eebd5be50 100644 --- a/drivers/net/bonding/bond_netlink.c +++ b/drivers/net/bonding/bond_netlink.c @@ -17,7 +17,7 @@ #include <linux/if_ether.h> #include <net/netlink.h> #include <net/rtnetlink.h> -#include "bonding.h" +#include <net/bonding.h> static size_t bond_get_slave_size(const struct net_device *bond_dev, const struct net_device *slave_dev) diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c index b62697f4a3de..1a61cc9b3402 100644 --- a/drivers/net/bonding/bond_options.c +++ b/drivers/net/bonding/bond_options.c @@ -16,7 +16,7 @@ #include <linux/rcupdate.h> #include <linux/ctype.h> #include <linux/inet.h> -#include "bonding.h" +#include <net/bonding.h> static int bond_option_active_slave_set(struct bonding *bond, const struct bond_opt_value *newval); diff --git a/drivers/net/bonding/bond_options.h b/drivers/net/bonding/bond_options.h deleted file mode 100644 index 17ded5b29176..000000000000 --- a/drivers/net/bonding/bond_options.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * drivers/net/bond/bond_options.h - bonding options - * Copyright (c) 2013 Nikolay Aleksandrov <nikolay@redhat.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#ifndef _BOND_OPTIONS_H -#define _BOND_OPTIONS_H - -#define BOND_OPT_MAX_NAMELEN 32 -#define BOND_OPT_VALID(opt) ((opt) < BOND_OPT_LAST) -#define BOND_MODE_ALL_EX(x) (~(x)) - -/* Option flags: - * BOND_OPTFLAG_NOSLAVES - check if the bond device is empty before setting - * BOND_OPTFLAG_IFDOWN - check if the bond device is down before setting - * BOND_OPTFLAG_RAWVAL - the option parses the value itself - */ -enum { - BOND_OPTFLAG_NOSLAVES = BIT(0), - BOND_OPTFLAG_IFDOWN = BIT(1), - BOND_OPTFLAG_RAWVAL = BIT(2) -}; - -/* Value type flags: - * BOND_VALFLAG_DEFAULT - mark the value as default - * BOND_VALFLAG_(MIN|MAX) - mark the value as min/max - */ -enum { - BOND_VALFLAG_DEFAULT = BIT(0), - BOND_VALFLAG_MIN = BIT(1), - BOND_VALFLAG_MAX = BIT(2) -}; - -/* Option IDs, their bit positions correspond to their IDs */ -enum { - BOND_OPT_MODE, - BOND_OPT_PACKETS_PER_SLAVE, - BOND_OPT_XMIT_HASH, - BOND_OPT_ARP_VALIDATE, - BOND_OPT_ARP_ALL_TARGETS, - BOND_OPT_FAIL_OVER_MAC, - BOND_OPT_ARP_INTERVAL, - BOND_OPT_ARP_TARGETS, - BOND_OPT_DOWNDELAY, - BOND_OPT_UPDELAY, - BOND_OPT_LACP_RATE, - BOND_OPT_MINLINKS, - BOND_OPT_AD_SELECT, - BOND_OPT_NUM_PEER_NOTIF, - BOND_OPT_MIIMON, - BOND_OPT_PRIMARY, - BOND_OPT_PRIMARY_RESELECT, - BOND_OPT_USE_CARRIER, - BOND_OPT_ACTIVE_SLAVE, - BOND_OPT_QUEUE_ID, - BOND_OPT_ALL_SLAVES_ACTIVE, - BOND_OPT_RESEND_IGMP, - BOND_OPT_LP_INTERVAL, - BOND_OPT_SLAVES, - BOND_OPT_TLB_DYNAMIC_LB, - BOND_OPT_LAST -}; - -/* This structure is used for storing option values and for passing option - * values when changing an option. The logic when used as an arg is as follows: - * - if string != NULL -> parse it, if the opt is RAW type then return it, else - * return the parse result - * - if string == NULL -> parse value - */ -struct bond_opt_value { - char *string; - u64 value; - u32 flags; -}; - -struct bonding; - -struct bond_option { - int id; - const char *name; - const char *desc; - u32 flags; - - /* unsuppmodes is used to denote modes in which the option isn't - * supported. - */ - unsigned long unsuppmodes; - /* supported values which this option can have, can be a subset of - * BOND_OPTVAL_RANGE's value range - */ - const struct bond_opt_value *values; - - int (*set)(struct bonding *bond, const struct bond_opt_value *val); -}; - -int __bond_opt_set(struct bonding *bond, unsigned int option, - struct bond_opt_value *val); -int bond_opt_tryset_rtnl(struct bonding *bond, unsigned int option, char *buf); - -const struct bond_opt_value *bond_opt_parse(const struct bond_option *opt, - struct bond_opt_value *val); -const struct bond_option *bond_opt_get(unsigned int option); -const struct bond_option *bond_opt_get_by_name(const char *name); -const struct bond_opt_value *bond_opt_get_val(unsigned int option, u64 val); - -/* This helper is used to initialize a bond_opt_value structure for parameter - * passing. There should be either a valid string or value, but not both. - * When value is ULLONG_MAX then string will be used. - */ -static inline void __bond_opt_init(struct bond_opt_value *optval, - char *string, u64 value) -{ - memset(optval, 0, sizeof(*optval)); - optval->value = ULLONG_MAX; - if (value == ULLONG_MAX) - optval->string = string; - else - optval->value = value; -} -#define bond_opt_initval(optval, value) __bond_opt_init(optval, NULL, value) -#define bond_opt_initstr(optval, str) __bond_opt_init(optval, str, ULLONG_MAX) - -void bond_option_arp_ip_targets_clear(struct bonding *bond); - -#endif /* _BOND_OPTIONS_H */ diff --git a/drivers/net/bonding/bond_procfs.c b/drivers/net/bonding/bond_procfs.c index a3948f8d1e53..976f5ad2a0f2 100644 --- a/drivers/net/bonding/bond_procfs.c +++ b/drivers/net/bonding/bond_procfs.c @@ -2,7 +2,7 @@ #include <linux/export.h> #include <net/net_namespace.h> #include <net/netns/generic.h> -#include "bonding.h" +#include <net/bonding.h> static void *bond_info_seq_start(struct seq_file *seq, loff_t *pos) diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 8ffbafd500fd..7e9e151d4d61 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -40,7 +40,7 @@ #include <net/netns/generic.h> #include <linux/nsproxy.h> -#include "bonding.h" +#include <net/bonding.h> #define to_dev(obj) container_of(obj, struct device, kobj) #define to_bond(cd) ((struct bonding *)(netdev_priv(to_net_dev(cd)))) diff --git a/drivers/net/bonding/bond_sysfs_slave.c b/drivers/net/bonding/bond_sysfs_slave.c index b01b0ce4d1be..23618a831612 100644 --- a/drivers/net/bonding/bond_sysfs_slave.c +++ b/drivers/net/bonding/bond_sysfs_slave.c @@ -12,7 +12,7 @@ #include <linux/kernel.h> #include <linux/netdevice.h> -#include "bonding.h" +#include <net/bonding.h> struct slave_attribute { struct attribute attr; diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h deleted file mode 100644 index 10920f0686e2..000000000000 --- a/drivers/net/bonding/bonding.h +++ /dev/null @@ -1,648 +0,0 @@ -/* - * Bond several ethernet interfaces into a Cisco, running 'Etherchannel'. - * - * Portions are (c) Copyright 1995 Simon "Guru Aleph-Null" Janes - * NCM: Network and Communications Management, Inc. - * - * BUT, I'm the one who modified it for ethernet, so: - * (c) Copyright 1999, Thomas Davis, tadavis@lbl.gov - * - * This software may be used and distributed according to the terms - * of the GNU Public License, incorporated herein by reference. - * - */ - -#ifndef _LINUX_BONDING_H -#define _LINUX_BONDING_H - -#include <linux/timer.h> -#include <linux/proc_fs.h> -#include <linux/if_bonding.h> -#include <linux/cpumask.h> -#include <linux/in6.h> -#include <linux/netpoll.h> -#include <linux/inetdevice.h> -#include <linux/etherdevice.h> -#include <linux/reciprocal_div.h> -#include <linux/if_link.h> - -#include "bond_3ad.h" -#include "bond_alb.h" -#include "bond_options.h" - -#define DRV_VERSION "3.7.1" -#define DRV_RELDATE "April 27, 2011" -#define DRV_NAME "bonding" -#define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" - -#define bond_version DRV_DESCRIPTION ": v" DRV_VERSION " (" DRV_RELDATE ")\n" - -#define BOND_MAX_ARP_TARGETS 16 - -#define BOND_DEFAULT_MIIMON 100 - -/* - * Less bad way to call ioctl from within the kernel; this needs to be - * done some other way to get the call out of interrupt context. - * Needs "ioctl" variable to be supplied by calling context. - */ -#define IOCTL(dev, arg, cmd) ({ \ - int res = 0; \ - mm_segment_t fs = get_fs(); \ - set_fs(get_ds()); \ - res = ioctl(dev, arg, cmd); \ - set_fs(fs); \ - res; }) - -#define BOND_MODE(bond) ((bond)->params.mode) - -/* slave list primitives */ -#define bond_slave_list(bond) (&(bond)->dev->adj_list.lower) - -#define bond_has_slaves(bond) !list_empty(bond_slave_list(bond)) - -/* IMPORTANT: bond_first/last_slave can return NULL in case of an empty list */ -#define bond_first_slave(bond) \ - (bond_has_slaves(bond) ? \ - netdev_adjacent_get_private(bond_slave_list(bond)->next) : \ - NULL) -#define bond_last_slave(bond) \ - (bond_has_slaves(bond) ? \ - netdev_adjacent_get_private(bond_slave_list(bond)->prev) : \ - NULL) - -/* Caller must have rcu_read_lock */ -#define bond_first_slave_rcu(bond) \ - netdev_lower_get_first_private_rcu(bond->dev) - -#define bond_is_first_slave(bond, pos) (pos == bond_first_slave(bond)) -#define bond_is_last_slave(bond, pos) (pos == bond_last_slave(bond)) - -/** - * bond_for_each_slave - iterate over all slaves - * @bond: the bond holding this list - * @pos: current slave - * @iter: list_head * iterator - * - * Caller must hold RTNL - */ -#define bond_for_each_slave(bond, pos, iter) \ - netdev_for_each_lower_private((bond)->dev, pos, iter) - -/* Caller must have rcu_read_lock */ -#define bond_for_each_slave_rcu(bond, pos, iter) \ - netdev_for_each_lower_private_rcu((bond)->dev, pos, iter) - -#ifdef CONFIG_NET_POLL_CONTROLLER -extern atomic_t netpoll_block_tx; - -static inline void block_netpoll_tx(void) -{ - atomic_inc(&netpoll_block_tx); -} - -static inline void unblock_netpoll_tx(void) -{ - atomic_dec(&netpoll_block_tx); -} - -static inline int is_netpoll_tx_blocked(struct net_device *dev) -{ - if (unlikely(netpoll_tx_running(dev))) - return atomic_read(&netpoll_block_tx); - return 0; -} -#else -#define block_netpoll_tx() -#define unblock_netpoll_tx() -#define is_netpoll_tx_blocked(dev) (0) -#endif - -struct bond_params { - int mode; - int xmit_policy; - int miimon; - u8 num_peer_notif; - int arp_interval; - int arp_validate; - int arp_all_targets; - int use_carrier; - int fail_over_mac; - int updelay; - int downdelay; - int lacp_fast; - unsigned int min_links; - int ad_select; - char primary[IFNAMSIZ]; - int primary_reselect; - __be32 arp_targets[BOND_MAX_ARP_TARGETS]; - int tx_queues; - int all_slaves_active; - int resend_igmp; - int lp_interval; - int packets_per_slave; - int tlb_dynamic_lb; - struct reciprocal_value reciprocal_packets_per_slave; -}; - -struct bond_parm_tbl { - char *modename; - int mode; -}; - -struct slave { - struct net_device *dev; /* first - useful for panic debug */ - struct bonding *bond; /* our master */ - int delay; - /* all three in jiffies */ - unsigned long last_link_up; - unsigned long last_rx; - unsigned long target_last_arp_rx[BOND_MAX_ARP_TARGETS]; - s8 link; /* one of BOND_LINK_XXXX */ - s8 new_link; - u8 backup:1, /* indicates backup slave. Value corresponds with - BOND_STATE_ACTIVE and BOND_STATE_BACKUP */ - inactive:1, /* indicates inactive slave */ - should_notify:1; /* indicateds whether the state changed */ - u8 duplex; - u32 original_mtu; - u32 link_failure_count; - u32 speed; - u16 queue_id; - u8 perm_hwaddr[ETH_ALEN]; - struct ad_slave_info *ad_info; - struct tlb_slave_info tlb_info; -#ifdef CONFIG_NET_POLL_CONTROLLER - struct netpoll *np; -#endif - struct kobject kobj; - struct rtnl_link_stats64 slave_stats; -}; - -struct bond_up_slave { - unsigned int count; - struct rcu_head rcu; - struct slave *arr[0]; -}; - -/* - * Link pseudo-state only used internally by monitors - */ -#define BOND_LINK_NOCHANGE -1 - -/* - * Here are the locking policies for the two bonding locks: - * Get rcu_read_lock when reading or RTNL when writing slave list. - */ -struct bonding { - struct net_device *dev; /* first - useful for panic debug */ - struct slave __rcu *curr_active_slave; - struct slave __rcu *current_arp_slave; - struct slave __rcu *primary_slave; - struct bond_up_slave __rcu *slave_arr; /* Array of usable slaves */ - bool force_primary; - s32 slave_cnt; /* never change this value outside the attach/detach wrappers */ - int (*recv_probe)(const struct sk_buff *, struct bonding *, - struct slave *); - /* mode_lock is used for mode-specific locking needs, currently used by: - * 3ad mode (4) - protect against running bond_3ad_unbind_slave() and - * bond_3ad_state_machine_handler() concurrently and also - * the access to the state machine shared variables. - * TLB mode (5) - to sync the use and modifications of its hash table - * ALB mode (6) - to sync the use and modifications of its hash table - */ - spinlock_t mode_lock; - u8 send_peer_notif; - u8 igmp_retrans; -#ifdef CONFIG_PROC_FS - struct proc_dir_entry *proc_entry; - char proc_file_name[IFNAMSIZ]; -#endif /* CONFIG_PROC_FS */ - struct list_head bond_list; - u32 rr_tx_counter; - struct ad_bond_info ad_info; - struct alb_bond_info alb_info; - struct bond_params params; - struct workqueue_struct *wq; - struct delayed_work mii_work; - struct delayed_work arp_work; - struct delayed_work alb_work; - struct delayed_work ad_work; - struct delayed_work mcast_work; - struct delayed_work slave_arr_work; -#ifdef CONFIG_DEBUG_FS - /* debugging support via debugfs */ - struct dentry *debug_dir; -#endif /* CONFIG_DEBUG_FS */ - struct rtnl_link_stats64 bond_stats; -}; - -#define bond_slave_get_rcu(dev) \ - ((struct slave *) rcu_dereference(dev->rx_handler_data)) - -#define bond_slave_get_rtnl(dev) \ - ((struct slave *) rtnl_dereference(dev->rx_handler_data)) - -struct bond_vlan_tag { - __be16 vlan_proto; - unsigned short vlan_id; -}; - -/** - * Returns NULL if the net_device does not belong to any of the bond's slaves - * - * Caller must hold bond lock for read - */ -static inline struct slave *bond_get_slave_by_dev(struct bonding *bond, - struct net_device *slave_dev) -{ - return netdev_lower_dev_get_private(bond->dev, slave_dev); -} - -static inline struct bonding *bond_get_bond_by_slave(struct slave *slave) -{ - return slave->bond; -} - -static inline bool bond_should_override_tx_queue(struct bonding *bond) -{ - return BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP || - BOND_MODE(bond) == BOND_MODE_ROUNDROBIN; -} - -static inline bool bond_is_lb(const struct bonding *bond) -{ - return BOND_MODE(bond) == BOND_MODE_TLB || - BOND_MODE(bond) == BOND_MODE_ALB; -} - -static inline bool bond_is_nondyn_tlb(const struct bonding *bond) -{ - return (BOND_MODE(bond) == BOND_MODE_TLB) && - (bond->params.tlb_dynamic_lb == 0); -} - -static inline bool bond_mode_uses_xmit_hash(const struct bonding *bond) -{ - return (BOND_MODE(bond) == BOND_MODE_8023AD || - BOND_MODE(bond) == BOND_MODE_XOR || - bond_is_nondyn_tlb(bond)); -} - -static inline bool bond_mode_uses_arp(int mode) -{ - return mode != BOND_MODE_8023AD && mode != BOND_MODE_TLB && - mode != BOND_MODE_ALB; -} - -static inline bool bond_mode_uses_primary(int mode) -{ - return mode == BOND_MODE_ACTIVEBACKUP || mode == BOND_MODE_TLB || - mode == BOND_MODE_ALB; -} - -static inline bool bond_uses_primary(struct bonding *bond) -{ - return bond_mode_uses_primary(BOND_MODE(bond)); -} - -static inline bool bond_slave_is_up(struct slave *slave) -{ - return netif_running(slave->dev) && netif_carrier_ok(slave->dev); -} - -static inline void bond_set_active_slave(struct slave *slave) -{ - if (slave->backup) { - slave->backup = 0; - rtmsg_ifinfo(RTM_NEWLINK, slave->dev, 0, GFP_ATOMIC); - } -} - -static inline void bond_set_backup_slave(struct slave *slave) -{ - if (!slave->backup) { - slave->backup = 1; - rtmsg_ifinfo(RTM_NEWLINK, slave->dev, 0, GFP_ATOMIC); - } -} - -static inline void bond_set_slave_state(struct slave *slave, - int slave_state, bool notify) -{ - if (slave->backup == slave_state) - return; - - slave->backup = slave_state; - if (notify) { - rtmsg_ifinfo(RTM_NEWLINK, slave->dev, 0, GFP_ATOMIC); - slave->should_notify = 0; - } else { - if (slave->should_notify) - slave->should_notify = 0; - else - slave->should_notify = 1; - } -} - -static inline void bond_slave_state_change(struct bonding *bond) -{ - struct list_head *iter; - struct slave *tmp; - - bond_for_each_slave(bond, tmp, iter) { - if (tmp->link == BOND_LINK_UP) - bond_set_active_slave(tmp); - else if (tmp->link == BOND_LINK_DOWN) - bond_set_backup_slave(tmp); - } -} - -static inline void bond_slave_state_notify(struct bonding *bond) -{ - struct list_head *iter; - struct slave *tmp; - - bond_for_each_slave(bond, tmp, iter) { - if (tmp->should_notify) { - rtmsg_ifinfo(RTM_NEWLINK, tmp->dev, 0, GFP_ATOMIC); - tmp->should_notify = 0; - } - } -} - -static inline int bond_slave_state(struct slave *slave) -{ - return slave->backup; -} - -static inline bool bond_is_active_slave(struct slave *slave) -{ - return !bond_slave_state(slave); -} - -static inline bool bond_slave_can_tx(struct slave *slave) -{ - return bond_slave_is_up(slave) && slave->link == BOND_LINK_UP && - bond_is_active_slave(slave); -} - -#define BOND_PRI_RESELECT_ALWAYS 0 -#define BOND_PRI_RESELECT_BETTER 1 -#define BOND_PRI_RESELECT_FAILURE 2 - -#define BOND_FOM_NONE 0 -#define BOND_FOM_ACTIVE 1 -#define BOND_FOM_FOLLOW 2 - -#define BOND_ARP_TARGETS_ANY 0 -#define BOND_ARP_TARGETS_ALL 1 - -#define BOND_ARP_VALIDATE_NONE 0 -#define BOND_ARP_VALIDATE_ACTIVE (1 << BOND_STATE_ACTIVE) -#define BOND_ARP_VALIDATE_BACKUP (1 << BOND_STATE_BACKUP) -#define BOND_ARP_VALIDATE_ALL (BOND_ARP_VALIDATE_ACTIVE | \ - BOND_ARP_VALIDATE_BACKUP) -#define BOND_ARP_FILTER (BOND_ARP_VALIDATE_ALL + 1) -#define BOND_ARP_FILTER_ACTIVE (BOND_ARP_VALIDATE_ACTIVE | \ - BOND_ARP_FILTER) -#define BOND_ARP_FILTER_BACKUP (BOND_ARP_VALIDATE_BACKUP | \ - BOND_ARP_FILTER) - -#define BOND_SLAVE_NOTIFY_NOW true -#define BOND_SLAVE_NOTIFY_LATER false - -static inline int slave_do_arp_validate(struct bonding *bond, - struct slave *slave) -{ - return bond->params.arp_validate & (1 << bond_slave_state(slave)); -} - -static inline int slave_do_arp_validate_only(struct bonding *bond) -{ - return bond->params.arp_validate & BOND_ARP_FILTER; -} - -static inline int bond_is_ip_target_ok(__be32 addr) -{ - return !ipv4_is_lbcast(addr) && !ipv4_is_zeronet(addr); -} - -/* Get the oldest arp which we've received on this slave for bond's - * arp_targets. - */ -static inline unsigned long slave_oldest_target_arp_rx(struct bonding *bond, - struct slave *slave) -{ - int i = 1; - unsigned long ret = slave->target_last_arp_rx[0]; - - for (; (i < BOND_MAX_ARP_TARGETS) && bond->params.arp_targets[i]; i++) - if (time_before(slave->target_last_arp_rx[i], ret)) - ret = slave->target_last_arp_rx[i]; - - return ret; -} - -static inline unsigned long slave_last_rx(struct bonding *bond, - struct slave *slave) -{ - if (bond->params.arp_all_targets == BOND_ARP_TARGETS_ALL) - return slave_oldest_target_arp_rx(bond, slave); - - return slave->last_rx; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static inline void bond_netpoll_send_skb(const struct slave *slave, - struct sk_buff *skb) -{ - struct netpoll *np = slave->np; - - if (np) - netpoll_send_skb(np, skb); -} -#else -static inline void bond_netpoll_send_skb(const struct slave *slave, - struct sk_buff *skb) -{ -} -#endif - -static inline void bond_set_slave_inactive_flags(struct slave *slave, - bool notify) -{ - if (!bond_is_lb(slave->bond)) - bond_set_slave_state(slave, BOND_STATE_BACKUP, notify); - if (!slave->bond->params.all_slaves_active) - slave->inactive = 1; -} - -static inline void bond_set_slave_active_flags(struct slave *slave, - bool notify) -{ - bond_set_slave_state(slave, BOND_STATE_ACTIVE, notify); - slave->inactive = 0; -} - -static inline bool bond_is_slave_inactive(struct slave *slave) -{ - return slave->inactive; -} - -static inline __be32 bond_confirm_addr(struct net_device *dev, __be32 dst, __be32 local) -{ - struct in_device *in_dev; - __be32 addr = 0; - - rcu_read_lock(); - in_dev = __in_dev_get_rcu(dev); - - if (in_dev) - addr = inet_confirm_addr(dev_net(dev), in_dev, dst, local, - RT_SCOPE_HOST); - rcu_read_unlock(); - return addr; -} - -struct bond_net { - struct net *net; /* Associated network namespace */ - struct list_head dev_list; -#ifdef CONFIG_PROC_FS - struct proc_dir_entry *proc_dir; -#endif - struct class_attribute class_attr_bonding_masters; -}; - -int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond, struct slave *slave); -void bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev); -int bond_create(struct net *net, const char *name); -int bond_create_sysfs(struct bond_net *net); -void bond_destroy_sysfs(struct bond_net *net); -void bond_prepare_sysfs_group(struct bonding *bond); -int bond_sysfs_slave_add(struct slave *slave); -void bond_sysfs_slave_del(struct slave *slave); -int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev); -int bond_release(struct net_device *bond_dev, struct net_device *slave_dev); -u32 bond_xmit_hash(struct bonding *bond, struct sk_buff *skb); -void bond_select_active_slave(struct bonding *bond); -void bond_change_active_slave(struct bonding *bond, struct slave *new_active); -void bond_create_debugfs(void); -void bond_destroy_debugfs(void); -void bond_debug_register(struct bonding *bond); -void bond_debug_unregister(struct bonding *bond); -void bond_debug_reregister(struct bonding *bond); -const char *bond_mode_name(int mode); -void bond_setup(struct net_device *bond_dev); -unsigned int bond_get_num_tx_queues(void); -int bond_netlink_init(void); -void bond_netlink_fini(void); -struct net_device *bond_option_active_slave_get_rcu(struct bonding *bond); -const char *bond_slave_link_status(s8 link); -struct bond_vlan_tag *bond_verify_device_path(struct net_device *start_dev, - struct net_device *end_dev, - int level); -int bond_update_slave_arr(struct bonding *bond, struct slave *skipslave); -void bond_slave_arr_work_rearm(struct bonding *bond, unsigned long delay); - -#ifdef CONFIG_PROC_FS -void bond_create_proc_entry(struct bonding *bond); -void bond_remove_proc_entry(struct bonding *bond); -void bond_create_proc_dir(struct bond_net *bn); -void bond_destroy_proc_dir(struct bond_net *bn); -#else -static inline void bond_create_proc_entry(struct bonding *bond) -{ -} - -static inline void bond_remove_proc_entry(struct bonding *bond) -{ -} - -static inline void bond_create_proc_dir(struct bond_net *bn) -{ -} - -static inline void bond_destroy_proc_dir(struct bond_net *bn) -{ -} -#endif - -static inline struct slave *bond_slave_has_mac(struct bonding *bond, - const u8 *mac) -{ - struct list_head *iter; - struct slave *tmp; - - bond_for_each_slave(bond, tmp, iter) - if (ether_addr_equal_64bits(mac, tmp->dev->dev_addr)) - return tmp; - - return NULL; -} - -/* Caller must hold rcu_read_lock() for read */ -static inline struct slave *bond_slave_has_mac_rcu(struct bonding *bond, - const u8 *mac) -{ - struct list_head *iter; - struct slave *tmp; - - bond_for_each_slave_rcu(bond, tmp, iter) - if (ether_addr_equal_64bits(mac, tmp->dev->dev_addr)) - return tmp; - - return NULL; -} - -/* Caller must hold rcu_read_lock() for read */ -static inline bool bond_slave_has_mac_rx(struct bonding *bond, const u8 *mac) -{ - struct list_head *iter; - struct slave *tmp; - struct netdev_hw_addr *ha; - - bond_for_each_slave_rcu(bond, tmp, iter) - if (ether_addr_equal_64bits(mac, tmp->dev->dev_addr)) - return true; - - if (netdev_uc_empty(bond->dev)) - return false; - - netdev_for_each_uc_addr(ha, bond->dev) - if (ether_addr_equal_64bits(mac, ha->addr)) - return true; - - return false; -} - -/* Check if the ip is present in arp ip list, or first free slot if ip == 0 - * Returns -1 if not found, index if found - */ -static inline int bond_get_targets_ip(__be32 *targets, __be32 ip) -{ - int i; - - for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) - if (targets[i] == ip) - return i; - else if (targets[i] == 0) - break; - - return -1; -} - -/* exported from bond_main.c */ -extern int bond_net_id; -extern const struct bond_parm_tbl bond_lacp_tbl[]; -extern const struct bond_parm_tbl xmit_hashtype_tbl[]; -extern const struct bond_parm_tbl arp_validate_tbl[]; -extern const struct bond_parm_tbl arp_all_targets_tbl[]; -extern const struct bond_parm_tbl fail_over_mac_tbl[]; -extern const struct bond_parm_tbl pri_reselect_tbl[]; -extern struct bond_parm_tbl ad_select_tbl[]; - -/* exported from bond_netlink.c */ -extern struct rtnl_link_ops bond_link_ops; - -#endif /* _LINUX_BONDING_H */ diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index 8e78bb48f5a4..f94a9fa60488 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c @@ -35,6 +35,7 @@ #include <linux/list.h> #include <linux/io.h> #include <linux/pm_runtime.h> +#include <linux/pinctrl/consumer.h> #include <linux/can.h> #include <linux/can/dev.h> @@ -603,6 +604,8 @@ static int c_can_start(struct net_device *dev) priv->can.state = CAN_STATE_ERROR_ACTIVE; + /* activate pins */ + pinctrl_pm_select_default_state(dev->dev.parent); return 0; } @@ -611,6 +614,9 @@ static void c_can_stop(struct net_device *dev) struct c_can_priv *priv = netdev_priv(dev); c_can_irq_control(priv, false); + + /* deactivate pins */ + pinctrl_pm_select_sleep_state(dev->dev.parent); priv->can.state = CAN_STATE_STOPPED; } @@ -1244,6 +1250,13 @@ int register_c_can_dev(struct net_device *dev) struct c_can_priv *priv = netdev_priv(dev); int err; + /* Deactivate pins to prevent DRA7 DCAN IP from being + * stuck in transition when module is disabled. + * Pins are activated in c_can_start() and deactivated + * in c_can_stop() + */ + pinctrl_pm_select_sleep_state(dev->dev.parent); + c_can_pm_runtime_enable(priv); dev->flags |= IFF_ECHO; /* we support local echo */ diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h index 99ad1aa576b0..8acdc7fa4792 100644 --- a/drivers/net/can/c_can/c_can.h +++ b/drivers/net/can/c_can/c_can.h @@ -169,6 +169,28 @@ enum c_can_dev_id { BOSCH_D_CAN, }; +struct raminit_bits { + u8 start; + u8 done; +}; + +struct c_can_driver_data { + enum c_can_dev_id id; + + /* RAMINIT register description. Optional. */ + const struct raminit_bits *raminit_bits; /* Array of START/DONE bit positions */ + u8 raminit_num; /* Number of CAN instances on the SoC */ + bool raminit_pulse; /* If set, sets and clears START bit (pulse) */ +}; + +/* Out of band RAMINIT register access via syscon regmap */ +struct c_can_raminit { + struct regmap *syscon; /* for raminit ctrl. reg. access */ + unsigned int reg; /* register index within syscon */ + struct raminit_bits bits; + bool needs_pulse; +}; + /* c_can private data structure */ struct c_can_priv { struct can_priv can; /* must be the first member */ @@ -186,8 +208,7 @@ struct c_can_priv { const u16 *regs; void *priv; /* for board-specific data */ enum c_can_dev_id type; - u32 __iomem *raminit_ctrlreg; - int instance; + struct c_can_raminit raminit_sys; /* RAMINIT via syscon regmap */ void (*raminit) (const struct c_can_priv *priv, bool enable); u32 comm_rcv_high; u32 rxmasked; diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c index fb279d6ae484..a4535d2142a7 100644 --- a/drivers/net/can/c_can/c_can_platform.c +++ b/drivers/net/can/c_can/c_can_platform.c @@ -32,14 +32,13 @@ #include <linux/clk.h> #include <linux/of.h> #include <linux/of_device.h> +#include <linux/mfd/syscon.h> +#include <linux/regmap.h> #include <linux/can/dev.h> #include "c_can.h" -#define CAN_RAMINIT_START_MASK(i) (0x001 << (i)) -#define CAN_RAMINIT_DONE_MASK(i) (0x100 << (i)) -#define CAN_RAMINIT_ALL_MASK(i) (0x101 << (i)) #define DCAN_RAM_INIT_BIT (1 << 3) static DEFINE_SPINLOCK(raminit_lock); /* @@ -72,39 +71,63 @@ static void c_can_plat_write_reg_aligned_to_32bit(const struct c_can_priv *priv, writew(val, priv->base + 2 * priv->regs[index]); } -static void c_can_hw_raminit_wait_ti(const struct c_can_priv *priv, u32 mask, - u32 val) +static void c_can_hw_raminit_wait_syscon(const struct c_can_priv *priv, + u32 mask, u32 val) { + const struct c_can_raminit *raminit = &priv->raminit_sys; + int timeout = 0; + u32 ctrl = 0; + /* We look only at the bits of our instance. */ val &= mask; - while ((readl(priv->raminit_ctrlreg) & mask) != val) + do { udelay(1); + timeout++; + + regmap_read(raminit->syscon, raminit->reg, &ctrl); + if (timeout == 1000) { + dev_err(&priv->dev->dev, "%s: time out\n", __func__); + break; + } + } while ((ctrl & mask) != val); } -static void c_can_hw_raminit_ti(const struct c_can_priv *priv, bool enable) +static void c_can_hw_raminit_syscon(const struct c_can_priv *priv, bool enable) { - u32 mask = CAN_RAMINIT_ALL_MASK(priv->instance); - u32 ctrl; + const struct c_can_raminit *raminit = &priv->raminit_sys; + u32 ctrl = 0; + u32 mask; spin_lock(&raminit_lock); - ctrl = readl(priv->raminit_ctrlreg); + mask = 1 << raminit->bits.start | 1 << raminit->bits.done; + regmap_read(raminit->syscon, raminit->reg, &ctrl); + /* We clear the done and start bit first. The start bit is * looking at the 0 -> transition, but is not self clearing; * And we clear the init done bit as well. + * NOTE: DONE must be written with 1 to clear it. */ - ctrl &= ~CAN_RAMINIT_START_MASK(priv->instance); - ctrl |= CAN_RAMINIT_DONE_MASK(priv->instance); - writel(ctrl, priv->raminit_ctrlreg); - ctrl &= ~CAN_RAMINIT_DONE_MASK(priv->instance); - c_can_hw_raminit_wait_ti(priv, mask, ctrl); + ctrl &= ~(1 << raminit->bits.start); + ctrl |= 1 << raminit->bits.done; + regmap_write(raminit->syscon, raminit->reg, ctrl); + + ctrl &= ~(1 << raminit->bits.done); + c_can_hw_raminit_wait_syscon(priv, mask, ctrl); if (enable) { /* Set start bit and wait for the done bit. */ - ctrl |= CAN_RAMINIT_START_MASK(priv->instance); - writel(ctrl, priv->raminit_ctrlreg); - ctrl |= CAN_RAMINIT_DONE_MASK(priv->instance); - c_can_hw_raminit_wait_ti(priv, mask, ctrl); + ctrl |= 1 << raminit->bits.start; + regmap_write(raminit->syscon, raminit->reg, ctrl); + + /* clear START bit if start pulse is needed */ + if (raminit->needs_pulse) { + ctrl &= ~(1 << raminit->bits.start); + regmap_write(raminit->syscon, raminit->reg, ctrl); + } + + ctrl |= 1 << raminit->bits.done; + c_can_hw_raminit_wait_syscon(priv, mask, ctrl); } spin_unlock(&raminit_lock); } @@ -159,26 +182,60 @@ static void c_can_hw_raminit(const struct c_can_priv *priv, bool enable) } } +static const struct c_can_driver_data c_can_drvdata = { + .id = BOSCH_C_CAN, +}; + +static const struct c_can_driver_data d_can_drvdata = { + .id = BOSCH_D_CAN, +}; + +static const struct raminit_bits dra7_raminit_bits[] = { + [0] = { .start = 3, .done = 1, }, + [1] = { .start = 5, .done = 2, }, +}; + +static const struct c_can_driver_data dra7_dcan_drvdata = { + .id = BOSCH_D_CAN, + .raminit_num = ARRAY_SIZE(dra7_raminit_bits), + .raminit_bits = dra7_raminit_bits, + .raminit_pulse = true, +}; + +static const struct raminit_bits am3352_raminit_bits[] = { + [0] = { .start = 0, .done = 8, }, + [1] = { .start = 1, .done = 9, }, +}; + +static const struct c_can_driver_data am3352_dcan_drvdata = { + .id = BOSCH_D_CAN, + .raminit_num = ARRAY_SIZE(am3352_raminit_bits), + .raminit_bits = am3352_raminit_bits, +}; + static struct platform_device_id c_can_id_table[] = { - [BOSCH_C_CAN_PLATFORM] = { + { .name = KBUILD_MODNAME, - .driver_data = BOSCH_C_CAN, + .driver_data = (kernel_ulong_t)&c_can_drvdata, }, - [BOSCH_C_CAN] = { + { .name = "c_can", - .driver_data = BOSCH_C_CAN, + .driver_data = (kernel_ulong_t)&c_can_drvdata, }, - [BOSCH_D_CAN] = { + { .name = "d_can", - .driver_data = BOSCH_D_CAN, - }, { - } + .driver_data = (kernel_ulong_t)&d_can_drvdata, + }, + { /* sentinel */ }, }; MODULE_DEVICE_TABLE(platform, c_can_id_table); static const struct of_device_id c_can_of_table[] = { - { .compatible = "bosch,c_can", .data = &c_can_id_table[BOSCH_C_CAN] }, - { .compatible = "bosch,d_can", .data = &c_can_id_table[BOSCH_D_CAN] }, + { .compatible = "bosch,c_can", .data = &c_can_drvdata }, + { .compatible = "bosch,d_can", .data = &d_can_drvdata }, + { .compatible = "ti,dra7-d_can", .data = &dra7_dcan_drvdata }, + { .compatible = "ti,am3352-d_can", .data = &am3352_dcan_drvdata }, + { .compatible = "ti,am4372-d_can", .data = &am3352_dcan_drvdata }, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, c_can_of_table); @@ -190,21 +247,20 @@ static int c_can_plat_probe(struct platform_device *pdev) struct net_device *dev; struct c_can_priv *priv; const struct of_device_id *match; - const struct platform_device_id *id; - struct resource *mem, *res; + struct resource *mem; int irq; struct clk *clk; - - if (pdev->dev.of_node) { - match = of_match_device(c_can_of_table, &pdev->dev); - if (!match) { - dev_err(&pdev->dev, "Failed to find matching dt id\n"); - ret = -EINVAL; - goto exit; - } - id = match->data; + const struct c_can_driver_data *drvdata; + struct device_node *np = pdev->dev.of_node; + + match = of_match_device(c_can_of_table, &pdev->dev); + if (match) { + drvdata = match->data; + } else if (pdev->id_entry->driver_data) { + drvdata = (struct c_can_driver_data *) + platform_get_device_id(pdev)->driver_data; } else { - id = platform_get_device_id(pdev); + return -ENODEV; } /* get the appropriate clk */ @@ -236,7 +292,7 @@ static int c_can_plat_probe(struct platform_device *pdev) } priv = netdev_priv(dev); - switch (id->driver_data) { + switch (drvdata->id) { case BOSCH_C_CAN: priv->regs = reg_map_c_can; switch (mem->flags & IORESOURCE_MEM_TYPE_MASK) { @@ -263,27 +319,50 @@ static int c_can_plat_probe(struct platform_device *pdev) priv->read_reg32 = d_can_plat_read_reg32; priv->write_reg32 = d_can_plat_write_reg32; - if (pdev->dev.of_node) - priv->instance = of_alias_get_id(pdev->dev.of_node, "d_can"); - else - priv->instance = pdev->id; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - /* Not all D_CAN modules have a separate register for the D_CAN - * RAM initialization. Use default RAM init bit in D_CAN module - * if not specified in DT. + /* Check if we need custom RAMINIT via syscon. Mostly for TI + * platforms. Only supported with DT boot. */ - if (!res) { + if (np && of_property_read_bool(np, "syscon-raminit")) { + u32 id; + struct c_can_raminit *raminit = &priv->raminit_sys; + + ret = -EINVAL; + raminit->syscon = syscon_regmap_lookup_by_phandle(np, + "syscon-raminit"); + if (IS_ERR(raminit->syscon)) { + /* can fail with -EPROBE_DEFER */ + ret = PTR_ERR(raminit->syscon); + free_c_can_dev(dev); + return ret; + } + + if (of_property_read_u32_index(np, "syscon-raminit", 1, + &raminit->reg)) { + dev_err(&pdev->dev, + "couldn't get the RAMINIT reg. offset!\n"); + goto exit_free_device; + } + + if (of_property_read_u32_index(np, "syscon-raminit", 2, + &id)) { + dev_err(&pdev->dev, + "couldn't get the CAN instance ID\n"); + goto exit_free_device; + } + + if (id >= drvdata->raminit_num) { + dev_err(&pdev->dev, + "Invalid CAN instance ID\n"); + goto exit_free_device; + } + + raminit->bits = drvdata->raminit_bits[id]; + raminit->needs_pulse = drvdata->raminit_pulse; + + priv->raminit = c_can_hw_raminit_syscon; + } else { priv->raminit = c_can_hw_raminit; - break; } - - priv->raminit_ctrlreg = devm_ioremap(&pdev->dev, res->start, - resource_size(res)); - if (!priv->raminit_ctrlreg || priv->instance < 0) - dev_info(&pdev->dev, "control memory is not used for raminit\n"); - else - priv->raminit = c_can_hw_raminit_ti; break; default: ret = -EINVAL; @@ -295,7 +374,7 @@ static int c_can_plat_probe(struct platform_device *pdev) priv->device = &pdev->dev; priv->can.clock.freq = clk_get_rate(clk); priv->priv = clk; - priv->type = id->driver_data; + priv->type = drvdata->id; platform_set_drvdata(pdev, dev); SET_NETDEV_DEV(dev, &pdev->dev); diff --git a/drivers/net/dsa/Kconfig b/drivers/net/dsa/Kconfig index 9234d808cbb3..7cf8f4ac281f 100644 --- a/drivers/net/dsa/Kconfig +++ b/drivers/net/dsa/Kconfig @@ -37,13 +37,22 @@ config NET_DSA_MV88E6123_61_65 ethernet switch chips. config NET_DSA_MV88E6171 - tristate "Marvell 88E6171 ethernet switch chip support" + tristate "Marvell 88E6171/6172 ethernet switch chip support" select NET_DSA select NET_DSA_MV88E6XXX select NET_DSA_TAG_EDSA ---help--- - This enables support for the Marvell 88E6171 ethernet switch - chip. + This enables support for the Marvell 88E6171/6172 ethernet switch + chips. + +config NET_DSA_MV88E6352 + tristate "Marvell 88E6176/88E6352 ethernet switch chip support" + select NET_DSA + select NET_DSA_MV88E6XXX + select NET_DSA_TAG_EDSA + ---help--- + This enables support for the Marvell 88E6176 and 88E6352 ethernet + switch chips. config NET_DSA_BCM_SF2 tristate "Broadcom Starfighter 2 Ethernet switch support" diff --git a/drivers/net/dsa/Makefile b/drivers/net/dsa/Makefile index 23a90de9830e..e2d51c4b9382 100644 --- a/drivers/net/dsa/Makefile +++ b/drivers/net/dsa/Makefile @@ -7,6 +7,9 @@ endif ifdef CONFIG_NET_DSA_MV88E6131 mv88e6xxx_drv-y += mv88e6131.o endif +ifdef CONFIG_NET_DSA_MV88E6352 +mv88e6xxx_drv-y += mv88e6352.o +endif ifdef CONFIG_NET_DSA_MV88E6171 mv88e6xxx_drv-y += mv88e6171.o endif diff --git a/drivers/net/dsa/mv88e6060.c b/drivers/net/dsa/mv88e6060.c index 05b0ca3bf71d..c29aebe1e62b 100644 --- a/drivers/net/dsa/mv88e6060.c +++ b/drivers/net/dsa/mv88e6060.c @@ -69,8 +69,11 @@ static char *mv88e6060_probe(struct device *host_dev, int sw_addr) ret = mdiobus_read(bus, sw_addr + REG_PORT(0), 0x03); if (ret >= 0) { - ret &= 0xfff0; if (ret == 0x0600) + return "Marvell 88E6060 (A0)"; + if (ret == 0x0601 || ret == 0x0602) + return "Marvell 88E6060 (B0)"; + if ((ret & 0xfff0) == 0x0600) return "Marvell 88E6060"; } diff --git a/drivers/net/dsa/mv88e6123_61_65.c b/drivers/net/dsa/mv88e6123_61_65.c index a332c53ff955..e9c736e1cef3 100644 --- a/drivers/net/dsa/mv88e6123_61_65.c +++ b/drivers/net/dsa/mv88e6123_61_65.c @@ -299,6 +299,7 @@ static int mv88e6123_61_65_setup(struct dsa_switch *ds) mutex_init(&ps->smi_mutex); mutex_init(&ps->stats_mutex); + mutex_init(&ps->phy_mutex); ret = mv88e6123_61_65_switch_reset(ds); if (ret < 0) @@ -329,16 +330,28 @@ static int mv88e6123_61_65_port_to_phy_addr(int port) static int mv88e6123_61_65_phy_read(struct dsa_switch *ds, int port, int regnum) { + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int addr = mv88e6123_61_65_port_to_phy_addr(port); - return mv88e6xxx_phy_read(ds, addr, regnum); + int ret; + + mutex_lock(&ps->phy_mutex); + ret = mv88e6xxx_phy_read(ds, addr, regnum); + mutex_unlock(&ps->phy_mutex); + return ret; } static int mv88e6123_61_65_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val) { + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int addr = mv88e6123_61_65_port_to_phy_addr(port); - return mv88e6xxx_phy_write(ds, addr, regnum, val); + int ret; + + mutex_lock(&ps->phy_mutex); + ret = mv88e6xxx_phy_write(ds, addr, regnum, val); + mutex_unlock(&ps->phy_mutex); + return ret; } static struct mv88e6xxx_hw_stat mv88e6123_61_65_hw_stats[] = { @@ -372,6 +385,9 @@ static struct mv88e6xxx_hw_stat mv88e6123_61_65_hw_stats[] = { { "hist_256_511bytes", 4, 0x0b, }, { "hist_512_1023bytes", 4, 0x0c, }, { "hist_1024_max_bytes", 4, 0x0d, }, + { "sw_in_discards", 4, 0x110, }, + { "sw_in_filtered", 2, 0x112, }, + { "sw_out_filtered", 2, 0x113, }, }; static void @@ -406,6 +422,11 @@ struct dsa_switch_driver mv88e6123_61_65_switch_driver = { .get_strings = mv88e6123_61_65_get_strings, .get_ethtool_stats = mv88e6123_61_65_get_ethtool_stats, .get_sset_count = mv88e6123_61_65_get_sset_count, +#ifdef CONFIG_NET_DSA_HWMON + .get_temp = mv88e6xxx_get_temp, +#endif + .get_regs_len = mv88e6xxx_get_regs_len, + .get_regs = mv88e6xxx_get_regs, }; MODULE_ALIAS("platform:mv88e6123"); diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c index 244c735014fa..1230f52aa70e 100644 --- a/drivers/net/dsa/mv88e6131.c +++ b/drivers/net/dsa/mv88e6131.c @@ -21,6 +21,7 @@ #define ID_6085 0x04a0 #define ID_6095 0x0950 #define ID_6131 0x1060 +#define ID_6131_B2 0x1066 static char *mv88e6131_probe(struct device *host_dev, int sw_addr) { @@ -32,12 +33,15 @@ static char *mv88e6131_probe(struct device *host_dev, int sw_addr) ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), 0x03); if (ret >= 0) { - ret &= 0xfff0; - if (ret == ID_6085) + int ret_masked = ret & 0xfff0; + + if (ret_masked == ID_6085) return "Marvell 88E6085"; - if (ret == ID_6095) + if (ret_masked == ID_6095) return "Marvell 88E6095/88E6095F"; - if (ret == ID_6131) + if (ret == ID_6131_B2) + return "Marvell 88E6131 (B2)"; + if (ret_masked == ID_6131) return "Marvell 88E6131"; } diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c index 78d8e876f3aa..aa33d16f2e22 100644 --- a/drivers/net/dsa/mv88e6171.c +++ b/drivers/net/dsa/mv88e6171.c @@ -1,4 +1,4 @@ -/* net/dsa/mv88e6171.c - Marvell 88e6171 switch chip support +/* net/dsa/mv88e6171.c - Marvell 88e6171/8826172 switch chip support * Copyright (c) 2008-2009 Marvell Semiconductor * Copyright (c) 2014 Claudio Leite <leitec@staticky.com> * @@ -29,6 +29,8 @@ static char *mv88e6171_probe(struct device *host_dev, int sw_addr) if (ret >= 0) { if ((ret & 0xfff0) == 0x1710) return "Marvell 88E6171"; + if ((ret & 0xfff0) == 0x1720) + return "Marvell 88E6172"; } return NULL; @@ -314,6 +316,8 @@ static int mv88e6171_setup(struct dsa_switch *ds) return ret; } + mutex_init(&ps->phy_mutex); + return 0; } @@ -327,18 +331,28 @@ static int mv88e6171_port_to_phy_addr(int port) static int mv88e6171_phy_read(struct dsa_switch *ds, int port, int regnum) { + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int addr = mv88e6171_port_to_phy_addr(port); + int ret; - return mv88e6xxx_phy_read(ds, addr, regnum); + mutex_lock(&ps->phy_mutex); + ret = mv88e6xxx_phy_read(ds, addr, regnum); + mutex_unlock(&ps->phy_mutex); + return ret; } static int mv88e6171_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val) { + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int addr = mv88e6171_port_to_phy_addr(port); + int ret; - return mv88e6xxx_phy_write(ds, addr, regnum, val); + mutex_lock(&ps->phy_mutex); + ret = mv88e6xxx_phy_write(ds, addr, regnum, val); + mutex_unlock(&ps->phy_mutex); + return ret; } static struct mv88e6xxx_hw_stat mv88e6171_hw_stats[] = { @@ -406,6 +420,12 @@ struct dsa_switch_driver mv88e6171_switch_driver = { .get_strings = mv88e6171_get_strings, .get_ethtool_stats = mv88e6171_get_ethtool_stats, .get_sset_count = mv88e6171_get_sset_count, +#ifdef CONFIG_NET_DSA_HWMON + .get_temp = mv88e6xxx_get_temp, +#endif + .get_regs_len = mv88e6xxx_get_regs_len, + .get_regs = mv88e6xxx_get_regs, }; MODULE_ALIAS("platform:mv88e6171"); +MODULE_ALIAS("platform:mv88e6172"); diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c new file mode 100644 index 000000000000..258d9ef5ef25 --- /dev/null +++ b/drivers/net/dsa/mv88e6352.c @@ -0,0 +1,788 @@ +/* + * net/dsa/mv88e6352.c - Marvell 88e6352 switch chip support + * + * Copyright (c) 2014 Guenter Roeck + * + * Derived from mv88e6123_61_65.c + * Copyright (c) 2008-2009 Marvell Semiconductor + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include <linux/delay.h> +#include <linux/jiffies.h> +#include <linux/list.h> +#include <linux/module.h> +#include <linux/netdevice.h> +#include <linux/platform_device.h> +#include <linux/phy.h> +#include <net/dsa.h> +#include "mv88e6xxx.h" + +static int mv88e6352_wait(struct dsa_switch *ds, int reg, u16 mask) +{ + unsigned long timeout = jiffies + HZ / 10; + + while (time_before(jiffies, timeout)) { + int ret; + + ret = REG_READ(REG_GLOBAL2, reg); + if (ret < 0) + return ret; + + if (!(ret & mask)) + return 0; + + usleep_range(1000, 2000); + } + return -ETIMEDOUT; +} + +static inline int mv88e6352_phy_wait(struct dsa_switch *ds) +{ + return mv88e6352_wait(ds, 0x18, 0x8000); +} + +static inline int mv88e6352_eeprom_load_wait(struct dsa_switch *ds) +{ + return mv88e6352_wait(ds, 0x14, 0x0800); +} + +static inline int mv88e6352_eeprom_busy_wait(struct dsa_switch *ds) +{ + return mv88e6352_wait(ds, 0x14, 0x8000); +} + +static int __mv88e6352_phy_read(struct dsa_switch *ds, int addr, int regnum) +{ + int ret; + + REG_WRITE(REG_GLOBAL2, 0x18, 0x9800 | (addr << 5) | regnum); + + ret = mv88e6352_phy_wait(ds); + if (ret < 0) + return ret; + + return REG_READ(REG_GLOBAL2, 0x19); +} + +static int __mv88e6352_phy_write(struct dsa_switch *ds, int addr, int regnum, + u16 val) +{ + REG_WRITE(REG_GLOBAL2, 0x19, val); + REG_WRITE(REG_GLOBAL2, 0x18, 0x9400 | (addr << 5) | regnum); + + return mv88e6352_phy_wait(ds); +} + +static char *mv88e6352_probe(struct device *host_dev, int sw_addr) +{ + struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev); + int ret; + + if (bus == NULL) + return NULL; + + ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), 0x03); + if (ret >= 0) { + if ((ret & 0xfff0) == 0x1760) + return "Marvell 88E6176"; + if (ret == 0x3521) + return "Marvell 88E6352 (A0)"; + if (ret == 0x3522) + return "Marvell 88E6352 (A1)"; + if ((ret & 0xfff0) == 0x3520) + return "Marvell 88E6352"; + } + + return NULL; +} + +static int mv88e6352_switch_reset(struct dsa_switch *ds) +{ + unsigned long timeout; + int ret; + int i; + + /* Set all ports to the disabled state. */ + for (i = 0; i < 7; i++) { + ret = REG_READ(REG_PORT(i), 0x04); + REG_WRITE(REG_PORT(i), 0x04, ret & 0xfffc); + } + + /* Wait for transmit queues to drain. */ + usleep_range(2000, 4000); + + /* Reset the switch. Keep PPU active (bit 14, undocumented). + * The PPU needs to be active to support indirect phy register + * accesses through global registers 0x18 and 0x19. + */ + REG_WRITE(REG_GLOBAL, 0x04, 0xc000); + + /* Wait up to one second for reset to complete. */ + timeout = jiffies + 1 * HZ; + while (time_before(jiffies, timeout)) { + ret = REG_READ(REG_GLOBAL, 0x00); + if ((ret & 0x8800) == 0x8800) + break; + usleep_range(1000, 2000); + } + if (time_after(jiffies, timeout)) + return -ETIMEDOUT; + + return 0; +} + +static int mv88e6352_setup_global(struct dsa_switch *ds) +{ + int ret; + int i; + + /* Discard packets with excessive collisions, + * mask all interrupt sources, enable PPU (bit 14, undocumented). + */ + REG_WRITE(REG_GLOBAL, 0x04, 0x6000); + + /* Set the default address aging time to 5 minutes, and + * enable address learn messages to be sent to all message + * ports. + */ + REG_WRITE(REG_GLOBAL, 0x0a, 0x0148); + + /* Configure the priority mapping registers. */ + ret = mv88e6xxx_config_prio(ds); + if (ret < 0) + return ret; + + /* Configure the upstream port, and configure the upstream + * port as the port to which ingress and egress monitor frames + * are to be sent. + */ + REG_WRITE(REG_GLOBAL, 0x1a, (dsa_upstream_port(ds) * 0x1110)); + + /* Disable remote management for now, and set the switch's + * DSA device number. + */ + REG_WRITE(REG_GLOBAL, 0x1c, ds->index & 0x1f); + + /* Send all frames with destination addresses matching + * 01:80:c2:00:00:2x to the CPU port. + */ + REG_WRITE(REG_GLOBAL2, 0x02, 0xffff); + + /* Send all frames with destination addresses matching + * 01:80:c2:00:00:0x to the CPU port. + */ + REG_WRITE(REG_GLOBAL2, 0x03, 0xffff); + + /* Disable the loopback filter, disable flow control + * messages, disable flood broadcast override, disable + * removing of provider tags, disable ATU age violation + * interrupts, disable tag flow control, force flow + * control priority to the highest, and send all special + * multicast frames to the CPU at the highest priority. + */ + REG_WRITE(REG_GLOBAL2, 0x05, 0x00ff); + + /* Program the DSA routing table. */ + for (i = 0; i < 32; i++) { + int nexthop = 0x1f; + + if (i != ds->index && i < ds->dst->pd->nr_chips) + nexthop = ds->pd->rtable[i] & 0x1f; + + REG_WRITE(REG_GLOBAL2, 0x06, 0x8000 | (i << 8) | nexthop); + } + + /* Clear all trunk masks. */ + for (i = 0; i < 8; i++) + REG_WRITE(REG_GLOBAL2, 0x07, 0x8000 | (i << 12) | 0x7f); + + /* Clear all trunk mappings. */ + for (i = 0; i < 16; i++) + REG_WRITE(REG_GLOBAL2, 0x08, 0x8000 | (i << 11)); + + /* Disable ingress rate limiting by resetting all ingress + * rate limit registers to their initial state. + */ + for (i = 0; i < 7; i++) + REG_WRITE(REG_GLOBAL2, 0x09, 0x9000 | (i << 8)); + + /* Initialise cross-chip port VLAN table to reset defaults. */ + REG_WRITE(REG_GLOBAL2, 0x0b, 0x9000); + + /* Clear the priority override table. */ + for (i = 0; i < 16; i++) + REG_WRITE(REG_GLOBAL2, 0x0f, 0x8000 | (i << 8)); + + /* @@@ initialise AVB (22/23) watchdog (27) sdet (29) registers */ + + return 0; +} + +static int mv88e6352_setup_port(struct dsa_switch *ds, int p) +{ + int addr = REG_PORT(p); + u16 val; + + /* MAC Forcing register: don't force link, speed, duplex + * or flow control state to any particular values on physical + * ports, but force the CPU port and all DSA ports to 1000 Mb/s + * full duplex. + */ + if (dsa_is_cpu_port(ds, p) || ds->dsa_port_mask & (1 << p)) + REG_WRITE(addr, 0x01, 0x003e); + else + REG_WRITE(addr, 0x01, 0x0003); + + /* Do not limit the period of time that this port can be + * paused for by the remote end or the period of time that + * this port can pause the remote end. + */ + REG_WRITE(addr, 0x02, 0x0000); + + /* Port Control: disable Drop-on-Unlock, disable Drop-on-Lock, + * disable Header mode, enable IGMP/MLD snooping, disable VLAN + * tunneling, determine priority by looking at 802.1p and IP + * priority fields (IP prio has precedence), and set STP state + * to Forwarding. + * + * If this is the CPU link, use DSA or EDSA tagging depending + * on which tagging mode was configured. + * + * If this is a link to another switch, use DSA tagging mode. + * + * If this is the upstream port for this switch, enable + * forwarding of unknown unicasts and multicasts. + */ + val = 0x0433; + if (dsa_is_cpu_port(ds, p)) { + if (ds->dst->tag_protocol == DSA_TAG_PROTO_EDSA) + val |= 0x3300; + else + val |= 0x0100; + } + if (ds->dsa_port_mask & (1 << p)) + val |= 0x0100; + if (p == dsa_upstream_port(ds)) + val |= 0x000c; + REG_WRITE(addr, 0x04, val); + + /* Port Control 1: disable trunking. Also, if this is the + * CPU port, enable learn messages to be sent to this port. + */ + REG_WRITE(addr, 0x05, dsa_is_cpu_port(ds, p) ? 0x8000 : 0x0000); + + /* Port based VLAN map: give each port its own address + * database, allow the CPU port to talk to each of the 'real' + * ports, and allow each of the 'real' ports to only talk to + * the upstream port. + */ + val = (p & 0xf) << 12; + if (dsa_is_cpu_port(ds, p)) + val |= ds->phys_port_mask; + else + val |= 1 << dsa_upstream_port(ds); + REG_WRITE(addr, 0x06, val); + + /* Default VLAN ID and priority: don't set a default VLAN + * ID, and set the default packet priority to zero. + */ + REG_WRITE(addr, 0x07, 0x0000); + + /* Port Control 2: don't force a good FCS, set the maximum + * frame size to 10240 bytes, don't let the switch add or + * strip 802.1q tags, don't discard tagged or untagged frames + * on this port, do a destination address lookup on all + * received packets as usual, disable ARP mirroring and don't + * send a copy of all transmitted/received frames on this port + * to the CPU. + */ + REG_WRITE(addr, 0x08, 0x2080); + + /* Egress rate control: disable egress rate control. */ + REG_WRITE(addr, 0x09, 0x0001); + + /* Egress rate control 2: disable egress rate control. */ + REG_WRITE(addr, 0x0a, 0x0000); + + /* Port Association Vector: when learning source addresses + * of packets, add the address to the address database using + * a port bitmap that has only the bit for this port set and + * the other bits clear. + */ + REG_WRITE(addr, 0x0b, 1 << p); + + /* Port ATU control: disable limiting the number of address + * database entries that this port is allowed to use. + */ + REG_WRITE(addr, 0x0c, 0x0000); + + /* Priority Override: disable DA, SA and VTU priority override. */ + REG_WRITE(addr, 0x0d, 0x0000); + + /* Port Ethertype: use the Ethertype DSA Ethertype value. */ + REG_WRITE(addr, 0x0f, ETH_P_EDSA); + + /* Tag Remap: use an identity 802.1p prio -> switch prio + * mapping. + */ + REG_WRITE(addr, 0x18, 0x3210); + + /* Tag Remap 2: use an identity 802.1p prio -> switch prio + * mapping. + */ + REG_WRITE(addr, 0x19, 0x7654); + + return 0; +} + +#ifdef CONFIG_NET_DSA_HWMON + +static int mv88e6352_phy_page_read(struct dsa_switch *ds, + int port, int page, int reg) +{ + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); + int ret; + + mutex_lock(&ps->phy_mutex); + ret = __mv88e6352_phy_write(ds, port, 0x16, page); + if (ret < 0) + goto error; + ret = __mv88e6352_phy_read(ds, port, reg); +error: + __mv88e6352_phy_write(ds, port, 0x16, 0x0); + mutex_unlock(&ps->phy_mutex); + return ret; +} + +static int mv88e6352_phy_page_write(struct dsa_switch *ds, + int port, int page, int reg, int val) +{ + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); + int ret; + + mutex_lock(&ps->phy_mutex); + ret = __mv88e6352_phy_write(ds, port, 0x16, page); + if (ret < 0) + goto error; + + ret = __mv88e6352_phy_write(ds, port, reg, val); +error: + __mv88e6352_phy_write(ds, port, 0x16, 0x0); + mutex_unlock(&ps->phy_mutex); + return ret; +} + +static int mv88e6352_get_temp(struct dsa_switch *ds, int *temp) +{ + int ret; + + *temp = 0; + + ret = mv88e6352_phy_page_read(ds, 0, 6, 27); + if (ret < 0) + return ret; + + *temp = (ret & 0xff) - 25; + + return 0; +} + +static int mv88e6352_get_temp_limit(struct dsa_switch *ds, int *temp) +{ + int ret; + + *temp = 0; + + ret = mv88e6352_phy_page_read(ds, 0, 6, 26); + if (ret < 0) + return ret; + + *temp = (((ret >> 8) & 0x1f) * 5) - 25; + + return 0; +} + +static int mv88e6352_set_temp_limit(struct dsa_switch *ds, int temp) +{ + int ret; + + ret = mv88e6352_phy_page_read(ds, 0, 6, 26); + if (ret < 0) + return ret; + temp = clamp_val(DIV_ROUND_CLOSEST(temp, 5) + 5, 0, 0x1f); + return mv88e6352_phy_page_write(ds, 0, 6, 26, + (ret & 0xe0ff) | (temp << 8)); +} + +static int mv88e6352_get_temp_alarm(struct dsa_switch *ds, bool *alarm) +{ + int ret; + + *alarm = false; + + ret = mv88e6352_phy_page_read(ds, 0, 6, 26); + if (ret < 0) + return ret; + + *alarm = !!(ret & 0x40); + + return 0; +} +#endif /* CONFIG_NET_DSA_HWMON */ + +static int mv88e6352_setup(struct dsa_switch *ds) +{ + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); + int ret; + int i; + + mutex_init(&ps->smi_mutex); + mutex_init(&ps->stats_mutex); + mutex_init(&ps->phy_mutex); + mutex_init(&ps->eeprom_mutex); + + ps->id = REG_READ(REG_PORT(0), 0x03) & 0xfff0; + + ret = mv88e6352_switch_reset(ds); + if (ret < 0) + return ret; + + /* @@@ initialise vtu and atu */ + + ret = mv88e6352_setup_global(ds); + if (ret < 0) + return ret; + + for (i = 0; i < 7; i++) { + ret = mv88e6352_setup_port(ds, i); + if (ret < 0) + return ret; + } + + return 0; +} + +static int mv88e6352_port_to_phy_addr(int port) +{ + if (port >= 0 && port <= 4) + return port; + return -EINVAL; +} + +static int +mv88e6352_phy_read(struct dsa_switch *ds, int port, int regnum) +{ + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); + int addr = mv88e6352_port_to_phy_addr(port); + int ret; + + if (addr < 0) + return addr; + + mutex_lock(&ps->phy_mutex); + ret = __mv88e6352_phy_read(ds, addr, regnum); + mutex_unlock(&ps->phy_mutex); + + return ret; +} + +static int +mv88e6352_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val) +{ + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); + int addr = mv88e6352_port_to_phy_addr(port); + int ret; + + if (addr < 0) + return addr; + + mutex_lock(&ps->phy_mutex); + ret = __mv88e6352_phy_write(ds, addr, regnum, val); + mutex_unlock(&ps->phy_mutex); + + return ret; +} + +static struct mv88e6xxx_hw_stat mv88e6352_hw_stats[] = { + { "in_good_octets", 8, 0x00, }, + { "in_bad_octets", 4, 0x02, }, + { "in_unicast", 4, 0x04, }, + { "in_broadcasts", 4, 0x06, }, + { "in_multicasts", 4, 0x07, }, + { "in_pause", 4, 0x16, }, + { "in_undersize", 4, 0x18, }, + { "in_fragments", 4, 0x19, }, + { "in_oversize", 4, 0x1a, }, + { "in_jabber", 4, 0x1b, }, + { "in_rx_error", 4, 0x1c, }, + { "in_fcs_error", 4, 0x1d, }, + { "out_octets", 8, 0x0e, }, + { "out_unicast", 4, 0x10, }, + { "out_broadcasts", 4, 0x13, }, + { "out_multicasts", 4, 0x12, }, + { "out_pause", 4, 0x15, }, + { "excessive", 4, 0x11, }, + { "collisions", 4, 0x1e, }, + { "deferred", 4, 0x05, }, + { "single", 4, 0x14, }, + { "multiple", 4, 0x17, }, + { "out_fcs_error", 4, 0x03, }, + { "late", 4, 0x1f, }, + { "hist_64bytes", 4, 0x08, }, + { "hist_65_127bytes", 4, 0x09, }, + { "hist_128_255bytes", 4, 0x0a, }, + { "hist_256_511bytes", 4, 0x0b, }, + { "hist_512_1023bytes", 4, 0x0c, }, + { "hist_1024_max_bytes", 4, 0x0d, }, + { "sw_in_discards", 4, 0x110, }, + { "sw_in_filtered", 2, 0x112, }, + { "sw_out_filtered", 2, 0x113, }, +}; + +static int mv88e6352_read_eeprom_word(struct dsa_switch *ds, int addr) +{ + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); + int ret; + + mutex_lock(&ps->eeprom_mutex); + + ret = mv88e6xxx_reg_write(ds, REG_GLOBAL2, 0x14, + 0xc000 | (addr & 0xff)); + if (ret < 0) + goto error; + + ret = mv88e6352_eeprom_busy_wait(ds); + if (ret < 0) + goto error; + + ret = mv88e6xxx_reg_read(ds, REG_GLOBAL2, 0x15); +error: + mutex_unlock(&ps->eeprom_mutex); + return ret; +} + +static int mv88e6352_get_eeprom(struct dsa_switch *ds, + struct ethtool_eeprom *eeprom, u8 *data) +{ + int offset; + int len; + int ret; + + offset = eeprom->offset; + len = eeprom->len; + eeprom->len = 0; + + eeprom->magic = 0xc3ec4951; + + ret = mv88e6352_eeprom_load_wait(ds); + if (ret < 0) + return ret; + + if (offset & 1) { + int word; + + word = mv88e6352_read_eeprom_word(ds, offset >> 1); + if (word < 0) + return word; + + *data++ = (word >> 8) & 0xff; + + offset++; + len--; + eeprom->len++; + } + + while (len >= 2) { + int word; + + word = mv88e6352_read_eeprom_word(ds, offset >> 1); + if (word < 0) + return word; + + *data++ = word & 0xff; + *data++ = (word >> 8) & 0xff; + + offset += 2; + len -= 2; + eeprom->len += 2; + } + + if (len) { + int word; + + word = mv88e6352_read_eeprom_word(ds, offset >> 1); + if (word < 0) + return word; + + *data++ = word & 0xff; + + offset++; + len--; + eeprom->len++; + } + + return 0; +} + +static int mv88e6352_eeprom_is_readonly(struct dsa_switch *ds) +{ + int ret; + + ret = mv88e6xxx_reg_read(ds, REG_GLOBAL2, 0x14); + if (ret < 0) + return ret; + + if (!(ret & 0x0400)) + return -EROFS; + + return 0; +} + +static int mv88e6352_write_eeprom_word(struct dsa_switch *ds, int addr, + u16 data) +{ + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); + int ret; + + mutex_lock(&ps->eeprom_mutex); + + ret = mv88e6xxx_reg_write(ds, REG_GLOBAL2, 0x15, data); + if (ret < 0) + goto error; + + ret = mv88e6xxx_reg_write(ds, REG_GLOBAL2, 0x14, + 0xb000 | (addr & 0xff)); + if (ret < 0) + goto error; + + ret = mv88e6352_eeprom_busy_wait(ds); +error: + mutex_unlock(&ps->eeprom_mutex); + return ret; +} + +static int mv88e6352_set_eeprom(struct dsa_switch *ds, + struct ethtool_eeprom *eeprom, u8 *data) +{ + int offset; + int ret; + int len; + + if (eeprom->magic != 0xc3ec4951) + return -EINVAL; + + ret = mv88e6352_eeprom_is_readonly(ds); + if (ret) + return ret; + + offset = eeprom->offset; + len = eeprom->len; + eeprom->len = 0; + + ret = mv88e6352_eeprom_load_wait(ds); + if (ret < 0) + return ret; + + if (offset & 1) { + int word; + + word = mv88e6352_read_eeprom_word(ds, offset >> 1); + if (word < 0) + return word; + + word = (*data++ << 8) | (word & 0xff); + + ret = mv88e6352_write_eeprom_word(ds, offset >> 1, word); + if (ret < 0) + return ret; + + offset++; + len--; + eeprom->len++; + } + + while (len >= 2) { + int word; + + word = *data++; + word |= *data++ << 8; + + ret = mv88e6352_write_eeprom_word(ds, offset >> 1, word); + if (ret < 0) + return ret; + + offset += 2; + len -= 2; + eeprom->len += 2; + } + + if (len) { + int word; + + word = mv88e6352_read_eeprom_word(ds, offset >> 1); + if (word < 0) + return word; + + word = (word & 0xff00) | *data++; + + ret = mv88e6352_write_eeprom_word(ds, offset >> 1, word); + if (ret < 0) + return ret; + + offset++; + len--; + eeprom->len++; + } + + return 0; +} + +static void +mv88e6352_get_strings(struct dsa_switch *ds, int port, uint8_t *data) +{ + mv88e6xxx_get_strings(ds, ARRAY_SIZE(mv88e6352_hw_stats), + mv88e6352_hw_stats, port, data); +} + +static void +mv88e6352_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data) +{ + mv88e6xxx_get_ethtool_stats(ds, ARRAY_SIZE(mv88e6352_hw_stats), + mv88e6352_hw_stats, port, data); +} + +static int mv88e6352_get_sset_count(struct dsa_switch *ds) +{ + return ARRAY_SIZE(mv88e6352_hw_stats); +} + +struct dsa_switch_driver mv88e6352_switch_driver = { + .tag_protocol = DSA_TAG_PROTO_EDSA, + .priv_size = sizeof(struct mv88e6xxx_priv_state), + .probe = mv88e6352_probe, + .setup = mv88e6352_setup, + .set_addr = mv88e6xxx_set_addr_indirect, + .phy_read = mv88e6352_phy_read, + .phy_write = mv88e6352_phy_write, + .poll_link = mv88e6xxx_poll_link, + .get_strings = mv88e6352_get_strings, + .get_ethtool_stats = mv88e6352_get_ethtool_stats, + .get_sset_count = mv88e6352_get_sset_count, +#ifdef CONFIG_NET_DSA_HWMON + .get_temp = mv88e6352_get_temp, + .get_temp_limit = mv88e6352_get_temp_limit, + .set_temp_limit = mv88e6352_set_temp_limit, + .get_temp_alarm = mv88e6352_get_temp_alarm, +#endif + .get_eeprom = mv88e6352_get_eeprom, + .set_eeprom = mv88e6352_set_eeprom, + .get_regs_len = mv88e6xxx_get_regs_len, + .get_regs = mv88e6xxx_get_regs, +}; + +MODULE_ALIAS("platform:mv88e6352"); diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index a6c90cf5634d..cd6807c6b4ed 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -485,20 +485,108 @@ void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, for (i = 0; i < nr_stats; i++) { struct mv88e6xxx_hw_stat *s = stats + i; u32 low; - u32 high; - + u32 high = 0; + + if (s->reg >= 0x100) { + int ret; + + ret = mv88e6xxx_reg_read(ds, REG_PORT(port), + s->reg - 0x100); + if (ret < 0) + goto error; + low = ret; + if (s->sizeof_stat == 4) { + ret = mv88e6xxx_reg_read(ds, REG_PORT(port), + s->reg - 0x100 + 1); + if (ret < 0) + goto error; + high = ret; + } + data[i] = (((u64)high) << 16) | low; + continue; + } mv88e6xxx_stats_read(ds, s->reg, &low); if (s->sizeof_stat == 8) mv88e6xxx_stats_read(ds, s->reg + 1, &high); - else - high = 0; data[i] = (((u64)high) << 32) | low; } - +error: mutex_unlock(&ps->stats_mutex); } +int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port) +{ + return 32 * sizeof(u16); +} + +void mv88e6xxx_get_regs(struct dsa_switch *ds, int port, + struct ethtool_regs *regs, void *_p) +{ + u16 *p = _p; + int i; + + regs->version = 0; + + memset(p, 0xff, 32 * sizeof(u16)); + + for (i = 0; i < 32; i++) { + int ret; + + ret = mv88e6xxx_reg_read(ds, REG_PORT(port), i); + if (ret >= 0) + p[i] = ret; + } +} + +#ifdef CONFIG_NET_DSA_HWMON + +int mv88e6xxx_get_temp(struct dsa_switch *ds, int *temp) +{ + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); + int ret; + int val; + + *temp = 0; + + mutex_lock(&ps->phy_mutex); + + ret = mv88e6xxx_phy_write(ds, 0x0, 0x16, 0x6); + if (ret < 0) + goto error; + + /* Enable temperature sensor */ + ret = mv88e6xxx_phy_read(ds, 0x0, 0x1a); + if (ret < 0) + goto error; + + ret = mv88e6xxx_phy_write(ds, 0x0, 0x1a, ret | (1 << 5)); + if (ret < 0) + goto error; + + /* Wait for temperature to stabilize */ + usleep_range(10000, 12000); + + val = mv88e6xxx_phy_read(ds, 0x0, 0x1a); + if (val < 0) { + ret = val; + goto error; + } + + /* Disable temperature sensor */ + ret = mv88e6xxx_phy_write(ds, 0x0, 0x1a, ret & ~(1 << 5)); + if (ret < 0) + goto error; + + *temp = ((val & 0x1f) - 5) * 5; + +error: + mv88e6xxx_phy_write(ds, 0x0, 0x16, 0x0); + mutex_unlock(&ps->phy_mutex); + return ret; +} +#endif /* CONFIG_NET_DSA_HWMON */ + static int __init mv88e6xxx_init(void) { #if IS_ENABLED(CONFIG_NET_DSA_MV88E6131) @@ -507,6 +595,9 @@ static int __init mv88e6xxx_init(void) #if IS_ENABLED(CONFIG_NET_DSA_MV88E6123_61_65) register_switch_driver(&mv88e6123_61_65_switch_driver); #endif +#if IS_ENABLED(CONFIG_NET_DSA_MV88E6352) + register_switch_driver(&mv88e6352_switch_driver); +#endif #if IS_ENABLED(CONFIG_NET_DSA_MV88E6171) register_switch_driver(&mv88e6171_switch_driver); #endif diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h index 5e5145ad9525..03e397efde36 100644 --- a/drivers/net/dsa/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx.h @@ -37,6 +37,17 @@ struct mv88e6xxx_priv_state { */ struct mutex stats_mutex; + /* This mutex serializes phy access for chips with + * indirect phy addressing. It is unused for chips + * with direct phy access. + */ + struct mutex phy_mutex; + + /* This mutex serializes eeprom access for chips with + * eeprom support. + */ + struct mutex eeprom_mutex; + int id; /* switch product id */ }; @@ -67,9 +78,14 @@ void mv88e6xxx_get_strings(struct dsa_switch *ds, void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int nr_stats, struct mv88e6xxx_hw_stat *stats, int port, uint64_t *data); +int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port); +void mv88e6xxx_get_regs(struct dsa_switch *ds, int port, + struct ethtool_regs *regs, void *_p); +int mv88e6xxx_get_temp(struct dsa_switch *ds, int *temp); extern struct dsa_switch_driver mv88e6131_switch_driver; extern struct dsa_switch_driver mv88e6123_61_65_switch_driver; +extern struct dsa_switch_driver mv88e6352_switch_driver; extern struct dsa_switch_driver mv88e6171_switch_driver; #define REG_READ(addr, reg) \ diff --git a/drivers/net/ethernet/3com/typhoon.c b/drivers/net/ethernet/3com/typhoon.c index 48775b88bac7..dede43f4ce09 100644 --- a/drivers/net/ethernet/3com/typhoon.c +++ b/drivers/net/ethernet/3com/typhoon.c @@ -1285,7 +1285,7 @@ typhoon_request_firmware(struct typhoon *tp) return err; } - image_data = (u8 *) typhoon_fw->data; + image_data = typhoon_fw->data; remaining = typhoon_fw->size; if (remaining < sizeof(struct typhoon_file_header)) goto invalid_fw; @@ -1343,7 +1343,7 @@ typhoon_download_firmware(struct typhoon *tp) int i; int err; - image_data = (u8 *) typhoon_fw->data; + image_data = typhoon_fw->data; fHdr = (struct typhoon_file_header *) image_data; /* Cannot just map the firmware image using pci_map_single() as diff --git a/drivers/net/ethernet/amd/Kconfig b/drivers/net/ethernet/amd/Kconfig index 8319c99331b0..7a5e4aa5415e 100644 --- a/drivers/net/ethernet/amd/Kconfig +++ b/drivers/net/ethernet/amd/Kconfig @@ -179,7 +179,7 @@ config SUNLANCE config AMD_XGBE tristate "AMD 10GbE Ethernet driver" - depends on OF_NET + depends on OF_NET && HAS_IOMEM select PHYLIB select AMD_XGBE_PHY select BITREVERSE diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h index caade30820d5..75b08c63d39f 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h @@ -125,9 +125,6 @@ #define DMA_AXIAWCR 0x3018 #define DMA_DSR0 0x3020 #define DMA_DSR1 0x3024 -#define DMA_DSR2 0x3028 -#define DMA_DSR3 0x302c -#define DMA_DSR4 0x3030 /* DMA register entry bit positions and sizes */ #define DMA_AXIARCR_DRC_INDEX 0 @@ -158,10 +155,6 @@ #define DMA_AXIAWCR_TDC_WIDTH 4 #define DMA_AXIAWCR_TDD_INDEX 28 #define DMA_AXIAWCR_TDD_WIDTH 2 -#define DMA_DSR0_RPS_INDEX 8 -#define DMA_DSR0_RPS_WIDTH 4 -#define DMA_DSR0_TPS_INDEX 12 -#define DMA_DSR0_TPS_WIDTH 4 #define DMA_ISR_MACIS_INDEX 17 #define DMA_ISR_MACIS_WIDTH 1 #define DMA_ISR_MTLIS_INDEX 16 @@ -175,6 +168,20 @@ #define DMA_SBMR_UNDEF_INDEX 0 #define DMA_SBMR_UNDEF_WIDTH 1 +/* DMA register values */ +#define DMA_DSR_RPS_WIDTH 4 +#define DMA_DSR_TPS_WIDTH 4 +#define DMA_DSR_Q_WIDTH (DMA_DSR_RPS_WIDTH + DMA_DSR_TPS_WIDTH) +#define DMA_DSR0_RPS_START 8 +#define DMA_DSR0_TPS_START 12 +#define DMA_DSRX_FIRST_QUEUE 3 +#define DMA_DSRX_INC 4 +#define DMA_DSRX_QPR 4 +#define DMA_DSRX_RPS_START 0 +#define DMA_DSRX_TPS_START 4 +#define DMA_TPS_STOPPED 0x00 +#define DMA_TPS_SUSPENDED 0x06 + /* DMA channel register offsets * Multiple channels can be active. The first channel has registers * that begin at 0x3100. Each subsequent channel has registers that @@ -207,6 +214,8 @@ /* DMA channel register entry bit positions and sizes */ #define DMA_CH_CR_PBLX8_INDEX 16 #define DMA_CH_CR_PBLX8_WIDTH 1 +#define DMA_CH_CR_SPH_INDEX 24 +#define DMA_CH_CR_SPH_WIDTH 1 #define DMA_CH_IER_AIE_INDEX 15 #define DMA_CH_IER_AIE_WIDTH 1 #define DMA_CH_IER_FBEE_INDEX 12 @@ -306,6 +315,9 @@ #define MAC_MACA0LR 0x0304 #define MAC_MACA1HR 0x0308 #define MAC_MACA1LR 0x030c +#define MAC_RSSCR 0x0c80 +#define MAC_RSSAR 0x0c88 +#define MAC_RSSDR 0x0c8c #define MAC_TSCR 0x0d00 #define MAC_SSIR 0x0d04 #define MAC_STSR 0x0d08 @@ -429,6 +441,8 @@ #define MAC_RCR_CST_WIDTH 1 #define MAC_RCR_DCRCC_INDEX 3 #define MAC_RCR_DCRCC_WIDTH 1 +#define MAC_RCR_HDSMS_INDEX 12 +#define MAC_RCR_HDSMS_WIDTH 3 #define MAC_RCR_IPC_INDEX 9 #define MAC_RCR_IPC_WIDTH 1 #define MAC_RCR_JE_INDEX 8 @@ -445,6 +459,24 @@ #define MAC_RFCR_UP_WIDTH 1 #define MAC_RQC0R_RXQ0EN_INDEX 0 #define MAC_RQC0R_RXQ0EN_WIDTH 2 +#define MAC_RSSAR_ADDRT_INDEX 2 +#define MAC_RSSAR_ADDRT_WIDTH 1 +#define MAC_RSSAR_CT_INDEX 1 +#define MAC_RSSAR_CT_WIDTH 1 +#define MAC_RSSAR_OB_INDEX 0 +#define MAC_RSSAR_OB_WIDTH 1 +#define MAC_RSSAR_RSSIA_INDEX 8 +#define MAC_RSSAR_RSSIA_WIDTH 8 +#define MAC_RSSCR_IP2TE_INDEX 1 +#define MAC_RSSCR_IP2TE_WIDTH 1 +#define MAC_RSSCR_RSSE_INDEX 0 +#define MAC_RSSCR_RSSE_WIDTH 1 +#define MAC_RSSCR_TCP4TE_INDEX 2 +#define MAC_RSSCR_TCP4TE_WIDTH 1 +#define MAC_RSSCR_UDP4TE_INDEX 3 +#define MAC_RSSCR_UDP4TE_WIDTH 1 +#define MAC_RSSDR_DMCH_INDEX 0 +#define MAC_RSSDR_DMCH_WIDTH 4 #define MAC_SSIR_SNSINC_INDEX 8 #define MAC_SSIR_SNSINC_WIDTH 8 #define MAC_SSIR_SSINC_INDEX 16 @@ -844,9 +876,13 @@ #define RX_PACKET_ATTRIBUTES_CONTEXT_WIDTH 1 #define RX_PACKET_ATTRIBUTES_RX_TSTAMP_INDEX 5 #define RX_PACKET_ATTRIBUTES_RX_TSTAMP_WIDTH 1 +#define RX_PACKET_ATTRIBUTES_RSS_HASH_INDEX 6 +#define RX_PACKET_ATTRIBUTES_RSS_HASH_WIDTH 1 #define RX_NORMAL_DESC0_OVT_INDEX 0 #define RX_NORMAL_DESC0_OVT_WIDTH 16 +#define RX_NORMAL_DESC2_HL_INDEX 0 +#define RX_NORMAL_DESC2_HL_WIDTH 10 #define RX_NORMAL_DESC3_CDA_INDEX 27 #define RX_NORMAL_DESC3_CDA_WIDTH 1 #define RX_NORMAL_DESC3_CTXT_INDEX 30 @@ -855,14 +891,27 @@ #define RX_NORMAL_DESC3_ES_WIDTH 1 #define RX_NORMAL_DESC3_ETLT_INDEX 16 #define RX_NORMAL_DESC3_ETLT_WIDTH 4 +#define RX_NORMAL_DESC3_FD_INDEX 29 +#define RX_NORMAL_DESC3_FD_WIDTH 1 #define RX_NORMAL_DESC3_INTE_INDEX 30 #define RX_NORMAL_DESC3_INTE_WIDTH 1 +#define RX_NORMAL_DESC3_L34T_INDEX 20 +#define RX_NORMAL_DESC3_L34T_WIDTH 4 #define RX_NORMAL_DESC3_LD_INDEX 28 #define RX_NORMAL_DESC3_LD_WIDTH 1 #define RX_NORMAL_DESC3_OWN_INDEX 31 #define RX_NORMAL_DESC3_OWN_WIDTH 1 #define RX_NORMAL_DESC3_PL_INDEX 0 #define RX_NORMAL_DESC3_PL_WIDTH 14 +#define RX_NORMAL_DESC3_RSV_INDEX 26 +#define RX_NORMAL_DESC3_RSV_WIDTH 1 + +#define RX_DESC3_L34T_IPV4_TCP 1 +#define RX_DESC3_L34T_IPV4_UDP 2 +#define RX_DESC3_L34T_IPV4_ICMP 3 +#define RX_DESC3_L34T_IPV6_TCP 9 +#define RX_DESC3_L34T_IPV6_UDP 10 +#define RX_DESC3_L34T_IPV6_ICMP 11 #define RX_CONTEXT_DESC3_TSA_INDEX 4 #define RX_CONTEXT_DESC3_TSA_WIDTH 1 diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c index 6fc5da01437d..51b68d1299fe 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c @@ -117,7 +117,7 @@ #include "xgbe.h" #include "xgbe-common.h" -static void xgbe_unmap_skb(struct xgbe_prv_data *, struct xgbe_ring_data *); +static void xgbe_unmap_rdata(struct xgbe_prv_data *, struct xgbe_ring_data *); static void xgbe_free_ring(struct xgbe_prv_data *pdata, struct xgbe_ring *ring) @@ -131,13 +131,35 @@ static void xgbe_free_ring(struct xgbe_prv_data *pdata, if (ring->rdata) { for (i = 0; i < ring->rdesc_count; i++) { rdata = XGBE_GET_DESC_DATA(ring, i); - xgbe_unmap_skb(pdata, rdata); + xgbe_unmap_rdata(pdata, rdata); } kfree(ring->rdata); ring->rdata = NULL; } + if (ring->rx_hdr_pa.pages) { + dma_unmap_page(pdata->dev, ring->rx_hdr_pa.pages_dma, + ring->rx_hdr_pa.pages_len, DMA_FROM_DEVICE); + put_page(ring->rx_hdr_pa.pages); + + ring->rx_hdr_pa.pages = NULL; + ring->rx_hdr_pa.pages_len = 0; + ring->rx_hdr_pa.pages_offset = 0; + ring->rx_hdr_pa.pages_dma = 0; + } + + if (ring->rx_buf_pa.pages) { + dma_unmap_page(pdata->dev, ring->rx_buf_pa.pages_dma, + ring->rx_buf_pa.pages_len, DMA_FROM_DEVICE); + put_page(ring->rx_buf_pa.pages); + + ring->rx_buf_pa.pages = NULL; + ring->rx_buf_pa.pages_len = 0; + ring->rx_buf_pa.pages_offset = 0; + ring->rx_buf_pa.pages_dma = 0; + } + if (ring->rdesc) { dma_free_coherent(pdata->dev, (sizeof(struct xgbe_ring_desc) * @@ -233,6 +255,96 @@ err_ring: return ret; } +static int xgbe_alloc_pages(struct xgbe_prv_data *pdata, + struct xgbe_page_alloc *pa, gfp_t gfp, int order) +{ + struct page *pages = NULL; + dma_addr_t pages_dma; + int ret; + + /* Try to obtain pages, decreasing order if necessary */ + gfp |= __GFP_COLD | __GFP_COMP; + while (order >= 0) { + pages = alloc_pages(gfp, order); + if (pages) + break; + + order--; + } + if (!pages) + return -ENOMEM; + + /* Map the pages */ + pages_dma = dma_map_page(pdata->dev, pages, 0, + PAGE_SIZE << order, DMA_FROM_DEVICE); + ret = dma_mapping_error(pdata->dev, pages_dma); + if (ret) { + put_page(pages); + return ret; + } + + pa->pages = pages; + pa->pages_len = PAGE_SIZE << order; + pa->pages_offset = 0; + pa->pages_dma = pages_dma; + + return 0; +} + +static void xgbe_set_buffer_data(struct xgbe_buffer_data *bd, + struct xgbe_page_alloc *pa, + unsigned int len) +{ + get_page(pa->pages); + bd->pa = *pa; + + bd->dma = pa->pages_dma + pa->pages_offset; + bd->dma_len = len; + + pa->pages_offset += len; + if ((pa->pages_offset + len) > pa->pages_len) { + /* This data descriptor is responsible for unmapping page(s) */ + bd->pa_unmap = *pa; + + /* Get a new allocation next time */ + pa->pages = NULL; + pa->pages_len = 0; + pa->pages_offset = 0; + pa->pages_dma = 0; + } +} + +static int xgbe_map_rx_buffer(struct xgbe_prv_data *pdata, + struct xgbe_ring *ring, + struct xgbe_ring_data *rdata) +{ + int order, ret; + + if (!ring->rx_hdr_pa.pages) { + ret = xgbe_alloc_pages(pdata, &ring->rx_hdr_pa, GFP_ATOMIC, 0); + if (ret) + return ret; + } + + if (!ring->rx_buf_pa.pages) { + order = max_t(int, PAGE_ALLOC_COSTLY_ORDER - 1, 0); + ret = xgbe_alloc_pages(pdata, &ring->rx_buf_pa, GFP_ATOMIC, + order); + if (ret) + return ret; + } + + /* Set up the header page info */ + xgbe_set_buffer_data(&rdata->rx.hdr, &ring->rx_hdr_pa, + XGBE_SKB_ALLOC_SIZE); + + /* Set up the buffer page info */ + xgbe_set_buffer_data(&rdata->rx.buf, &ring->rx_buf_pa, + pdata->rx_buf_size); + + return 0; +} + static void xgbe_wrapper_tx_descriptor_init(struct xgbe_prv_data *pdata) { struct xgbe_hw_if *hw_if = &pdata->hw_if; @@ -266,7 +378,7 @@ static void xgbe_wrapper_tx_descriptor_init(struct xgbe_prv_data *pdata) ring->cur = 0; ring->dirty = 0; - ring->tx.queue_stopped = 0; + memset(&ring->tx, 0, sizeof(ring->tx)); hw_if->tx_desc_init(channel); } @@ -281,8 +393,7 @@ static void xgbe_wrapper_rx_descriptor_init(struct xgbe_prv_data *pdata) struct xgbe_ring *ring; struct xgbe_ring_desc *rdesc; struct xgbe_ring_data *rdata; - dma_addr_t rdesc_dma, skb_dma; - struct sk_buff *skb = NULL; + dma_addr_t rdesc_dma; unsigned int i, j; DBGPR("-->xgbe_wrapper_rx_descriptor_init\n"); @@ -302,22 +413,8 @@ static void xgbe_wrapper_rx_descriptor_init(struct xgbe_prv_data *pdata) rdata->rdesc = rdesc; rdata->rdesc_dma = rdesc_dma; - /* Allocate skb & assign to each rdesc */ - skb = dev_alloc_skb(pdata->rx_buf_size); - if (skb == NULL) - break; - skb_dma = dma_map_single(pdata->dev, skb->data, - pdata->rx_buf_size, - DMA_FROM_DEVICE); - if (dma_mapping_error(pdata->dev, skb_dma)) { - netdev_alert(pdata->netdev, - "failed to do the dma map\n"); - dev_kfree_skb_any(skb); + if (xgbe_map_rx_buffer(pdata, ring, rdata)) break; - } - rdata->skb = skb; - rdata->skb_dma = skb_dma; - rdata->skb_dma_len = pdata->rx_buf_size; rdesc++; rdesc_dma += sizeof(struct xgbe_ring_desc); @@ -325,8 +422,7 @@ static void xgbe_wrapper_rx_descriptor_init(struct xgbe_prv_data *pdata) ring->cur = 0; ring->dirty = 0; - ring->rx.realloc_index = 0; - ring->rx.realloc_threshold = 0; + memset(&ring->rx, 0, sizeof(ring->rx)); hw_if->rx_desc_init(channel); } @@ -334,8 +430,8 @@ static void xgbe_wrapper_rx_descriptor_init(struct xgbe_prv_data *pdata) DBGPR("<--xgbe_wrapper_rx_descriptor_init\n"); } -static void xgbe_unmap_skb(struct xgbe_prv_data *pdata, - struct xgbe_ring_data *rdata) +static void xgbe_unmap_rdata(struct xgbe_prv_data *pdata, + struct xgbe_ring_data *rdata) { if (rdata->skb_dma) { if (rdata->mapped_as_page) { @@ -354,8 +450,29 @@ static void xgbe_unmap_skb(struct xgbe_prv_data *pdata, rdata->skb = NULL; } - rdata->tso_header = 0; - rdata->len = 0; + if (rdata->rx.hdr.pa.pages) + put_page(rdata->rx.hdr.pa.pages); + + if (rdata->rx.hdr.pa_unmap.pages) { + dma_unmap_page(pdata->dev, rdata->rx.hdr.pa_unmap.pages_dma, + rdata->rx.hdr.pa_unmap.pages_len, + DMA_FROM_DEVICE); + put_page(rdata->rx.hdr.pa_unmap.pages); + } + + if (rdata->rx.buf.pa.pages) + put_page(rdata->rx.buf.pa.pages); + + if (rdata->rx.buf.pa_unmap.pages) { + dma_unmap_page(pdata->dev, rdata->rx.buf.pa_unmap.pages_dma, + rdata->rx.buf.pa_unmap.pages_len, + DMA_FROM_DEVICE); + put_page(rdata->rx.buf.pa_unmap.pages); + } + + memset(&rdata->tx, 0, sizeof(rdata->tx)); + memset(&rdata->rx, 0, sizeof(rdata->rx)); + rdata->interrupt = 0; rdata->mapped_as_page = 0; @@ -414,7 +531,6 @@ static int xgbe_map_tx_skb(struct xgbe_channel *channel, struct sk_buff *skb) } rdata->skb_dma = skb_dma; rdata->skb_dma_len = packet->header_len; - rdata->tso_header = 1; offset = packet->header_len; @@ -494,7 +610,7 @@ static int xgbe_map_tx_skb(struct xgbe_channel *channel, struct sk_buff *skb) err_out: while (start_index < cur_index) { rdata = XGBE_GET_DESC_DATA(ring, start_index++); - xgbe_unmap_skb(pdata, rdata); + xgbe_unmap_rdata(pdata, rdata); } DBGPR("<--xgbe_map_tx_skb: count=0\n"); @@ -502,40 +618,25 @@ err_out: return 0; } -static void xgbe_realloc_skb(struct xgbe_channel *channel) +static void xgbe_realloc_rx_buffer(struct xgbe_channel *channel) { struct xgbe_prv_data *pdata = channel->pdata; struct xgbe_hw_if *hw_if = &pdata->hw_if; struct xgbe_ring *ring = channel->rx_ring; struct xgbe_ring_data *rdata; - struct sk_buff *skb = NULL; - dma_addr_t skb_dma; int i; - DBGPR("-->xgbe_realloc_skb: rx_ring->rx.realloc_index = %u\n", + DBGPR("-->xgbe_realloc_rx_buffer: rx_ring->rx.realloc_index = %u\n", ring->rx.realloc_index); for (i = 0; i < ring->dirty; i++) { rdata = XGBE_GET_DESC_DATA(ring, ring->rx.realloc_index); /* Reset rdata values */ - xgbe_unmap_skb(pdata, rdata); + xgbe_unmap_rdata(pdata, rdata); - /* Allocate skb & assign to each rdesc */ - skb = dev_alloc_skb(pdata->rx_buf_size); - if (skb == NULL) + if (xgbe_map_rx_buffer(pdata, ring, rdata)) break; - skb_dma = dma_map_single(pdata->dev, skb->data, - pdata->rx_buf_size, DMA_FROM_DEVICE); - if (dma_mapping_error(pdata->dev, skb_dma)) { - netdev_alert(pdata->netdev, - "failed to do the dma map\n"); - dev_kfree_skb_any(skb); - break; - } - rdata->skb = skb; - rdata->skb_dma = skb_dma; - rdata->skb_dma_len = pdata->rx_buf_size; hw_if->rx_desc_reset(rdata); @@ -543,7 +644,7 @@ static void xgbe_realloc_skb(struct xgbe_channel *channel) } ring->dirty = 0; - DBGPR("<--xgbe_realloc_skb\n"); + DBGPR("<--xgbe_realloc_rx_buffer\n"); } void xgbe_init_function_ptrs_desc(struct xgbe_desc_if *desc_if) @@ -553,8 +654,8 @@ void xgbe_init_function_ptrs_desc(struct xgbe_desc_if *desc_if) desc_if->alloc_ring_resources = xgbe_alloc_ring_resources; desc_if->free_ring_resources = xgbe_free_ring_resources; desc_if->map_tx_skb = xgbe_map_tx_skb; - desc_if->realloc_skb = xgbe_realloc_skb; - desc_if->unmap_skb = xgbe_unmap_skb; + desc_if->realloc_rx_buffer = xgbe_realloc_rx_buffer; + desc_if->unmap_rdata = xgbe_unmap_rdata; desc_if->wrapper_tx_desc_init = xgbe_wrapper_tx_descriptor_init; desc_if->wrapper_rx_desc_init = xgbe_wrapper_rx_descriptor_init; diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c index 9da3a03e8c07..53f5f66ec2ee 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c @@ -335,6 +335,161 @@ static void xgbe_config_tso_mode(struct xgbe_prv_data *pdata) } } +static void xgbe_config_sph_mode(struct xgbe_prv_data *pdata) +{ + struct xgbe_channel *channel; + unsigned int i; + + channel = pdata->channel; + for (i = 0; i < pdata->channel_count; i++, channel++) { + if (!channel->rx_ring) + break; + + XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_CR, SPH, 1); + } + + XGMAC_IOWRITE_BITS(pdata, MAC_RCR, HDSMS, XGBE_SPH_HDSMS_SIZE); +} + +static int xgbe_write_rss_reg(struct xgbe_prv_data *pdata, unsigned int type, + unsigned int index, unsigned int val) +{ + unsigned int wait; + int ret = 0; + + mutex_lock(&pdata->rss_mutex); + + if (XGMAC_IOREAD_BITS(pdata, MAC_RSSAR, OB)) { + ret = -EBUSY; + goto unlock; + } + + XGMAC_IOWRITE(pdata, MAC_RSSDR, val); + + XGMAC_IOWRITE_BITS(pdata, MAC_RSSAR, RSSIA, index); + XGMAC_IOWRITE_BITS(pdata, MAC_RSSAR, ADDRT, type); + XGMAC_IOWRITE_BITS(pdata, MAC_RSSAR, CT, 0); + XGMAC_IOWRITE_BITS(pdata, MAC_RSSAR, OB, 1); + + wait = 1000; + while (wait--) { + if (!XGMAC_IOREAD_BITS(pdata, MAC_RSSAR, OB)) + goto unlock; + + usleep_range(1000, 1500); + } + + ret = -EBUSY; + +unlock: + mutex_unlock(&pdata->rss_mutex); + + return ret; +} + +static int xgbe_write_rss_hash_key(struct xgbe_prv_data *pdata) +{ + unsigned int key_regs = sizeof(pdata->rss_key) / sizeof(u32); + unsigned int *key = (unsigned int *)&pdata->rss_key; + int ret; + + while (key_regs--) { + ret = xgbe_write_rss_reg(pdata, XGBE_RSS_HASH_KEY_TYPE, + key_regs, *key++); + if (ret) + return ret; + } + + return 0; +} + +static int xgbe_write_rss_lookup_table(struct xgbe_prv_data *pdata) +{ + unsigned int i; + int ret; + + for (i = 0; i < ARRAY_SIZE(pdata->rss_table); i++) { + ret = xgbe_write_rss_reg(pdata, + XGBE_RSS_LOOKUP_TABLE_TYPE, i, + pdata->rss_table[i]); + if (ret) + return ret; + } + + return 0; +} + +static int xgbe_set_rss_hash_key(struct xgbe_prv_data *pdata, const u8 *key) +{ + memcpy(pdata->rss_key, key, sizeof(pdata->rss_key)); + + return xgbe_write_rss_hash_key(pdata); +} + +static int xgbe_set_rss_lookup_table(struct xgbe_prv_data *pdata, + const u32 *table) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(pdata->rss_table); i++) + XGMAC_SET_BITS(pdata->rss_table[i], MAC_RSSDR, DMCH, table[i]); + + return xgbe_write_rss_lookup_table(pdata); +} + +static int xgbe_enable_rss(struct xgbe_prv_data *pdata) +{ + int ret; + + if (!pdata->hw_feat.rss) + return -EOPNOTSUPP; + + /* Program the hash key */ + ret = xgbe_write_rss_hash_key(pdata); + if (ret) + return ret; + + /* Program the lookup table */ + ret = xgbe_write_rss_lookup_table(pdata); + if (ret) + return ret; + + /* Set the RSS options */ + XGMAC_IOWRITE(pdata, MAC_RSSCR, pdata->rss_options); + + /* Enable RSS */ + XGMAC_IOWRITE_BITS(pdata, MAC_RSSCR, RSSE, 1); + + return 0; +} + +static int xgbe_disable_rss(struct xgbe_prv_data *pdata) +{ + if (!pdata->hw_feat.rss) + return -EOPNOTSUPP; + + XGMAC_IOWRITE_BITS(pdata, MAC_RSSCR, RSSE, 0); + + return 0; +} + +static void xgbe_config_rss(struct xgbe_prv_data *pdata) +{ + int ret; + + if (!pdata->hw_feat.rss) + return; + + if (pdata->netdev->features & NETIF_F_RXHASH) + ret = xgbe_enable_rss(pdata); + else + ret = xgbe_disable_rss(pdata); + + if (ret) + netdev_err(pdata->netdev, + "error configuring RSS, RSS disabled\n"); +} + static int xgbe_disable_tx_flow_control(struct xgbe_prv_data *pdata) { unsigned int max_q_count, q_count; @@ -465,17 +620,21 @@ static void xgbe_enable_dma_interrupts(struct xgbe_prv_data *pdata) if (channel->tx_ring) { /* Enable the following Tx interrupts - * TIE - Transmit Interrupt Enable (unless polling) + * TIE - Transmit Interrupt Enable (unless using + * per channel interrupts) */ - XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TIE, 1); + if (!pdata->per_channel_irq) + XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TIE, 1); } if (channel->rx_ring) { /* Enable following Rx interrupts * RBUE - Receive Buffer Unavailable Enable - * RIE - Receive Interrupt Enable + * RIE - Receive Interrupt Enable (unless using + * per channel interrupts) */ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RBUE, 1); - XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RIE, 1); + if (!pdata->per_channel_irq) + XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RIE, 1); } XGMAC_DMA_IOWRITE(channel, DMA_CH_IER, dma_ch_ier); @@ -880,13 +1039,15 @@ static void xgbe_tx_desc_reset(struct xgbe_ring_data *rdata) rdesc->desc1 = 0; rdesc->desc2 = 0; rdesc->desc3 = 0; + + /* Make sure ownership is written to the descriptor */ + wmb(); } static void xgbe_tx_desc_init(struct xgbe_channel *channel) { struct xgbe_ring *ring = channel->tx_ring; struct xgbe_ring_data *rdata; - struct xgbe_ring_desc *rdesc; int i; int start_index = ring->cur; @@ -895,26 +1056,11 @@ static void xgbe_tx_desc_init(struct xgbe_channel *channel) /* Initialze all descriptors */ for (i = 0; i < ring->rdesc_count; i++) { rdata = XGBE_GET_DESC_DATA(ring, i); - rdesc = rdata->rdesc; - /* Initialize Tx descriptor - * Set buffer 1 (lo) address to zero - * Set buffer 1 (hi) address to zero - * Reset all other control bits (IC, TTSE, B2L & B1L) - * Reset all other control bits (OWN, CTXT, FD, LD, CPC, CIC, - * etc) - */ - rdesc->desc0 = 0; - rdesc->desc1 = 0; - rdesc->desc2 = 0; - rdesc->desc3 = 0; + /* Initialize Tx descriptor */ + xgbe_tx_desc_reset(rdata); } - /* Make sure everything is written to the descriptor(s) before - * telling the device about them - */ - wmb(); - /* Update the total number of Tx descriptors */ XGMAC_DMA_IOWRITE(channel, DMA_CH_TDRLR, ring->rdesc_count - 1); @@ -933,19 +1079,19 @@ static void xgbe_rx_desc_reset(struct xgbe_ring_data *rdata) struct xgbe_ring_desc *rdesc = rdata->rdesc; /* Reset the Rx descriptor - * Set buffer 1 (lo) address to dma address (lo) - * Set buffer 1 (hi) address to dma address (hi) - * Set buffer 2 (lo) address to zero - * Set buffer 2 (hi) address to zero and set control bits - * OWN and INTE + * Set buffer 1 (lo) address to header dma address (lo) + * Set buffer 1 (hi) address to header dma address (hi) + * Set buffer 2 (lo) address to buffer dma address (lo) + * Set buffer 2 (hi) address to buffer dma address (hi) and + * set control bits OWN and INTE */ - rdesc->desc0 = cpu_to_le32(lower_32_bits(rdata->skb_dma)); - rdesc->desc1 = cpu_to_le32(upper_32_bits(rdata->skb_dma)); - rdesc->desc2 = 0; + rdesc->desc0 = cpu_to_le32(lower_32_bits(rdata->rx.hdr.dma)); + rdesc->desc1 = cpu_to_le32(upper_32_bits(rdata->rx.hdr.dma)); + rdesc->desc2 = cpu_to_le32(lower_32_bits(rdata->rx.buf.dma)); + rdesc->desc3 = cpu_to_le32(upper_32_bits(rdata->rx.buf.dma)); - rdesc->desc3 = 0; - if (rdata->interrupt) - XGMAC_SET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, INTE, 1); + XGMAC_SET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, INTE, + rdata->interrupt ? 1 : 0); /* Since the Rx DMA engine is likely running, make sure everything * is written to the descriptor(s) before setting the OWN bit @@ -964,7 +1110,6 @@ static void xgbe_rx_desc_init(struct xgbe_channel *channel) struct xgbe_prv_data *pdata = channel->pdata; struct xgbe_ring *ring = channel->rx_ring; struct xgbe_ring_data *rdata; - struct xgbe_ring_desc *rdesc; unsigned int start_index = ring->cur; unsigned int rx_coalesce, rx_frames; unsigned int i; @@ -977,34 +1122,16 @@ static void xgbe_rx_desc_init(struct xgbe_channel *channel) /* Initialize all descriptors */ for (i = 0; i < ring->rdesc_count; i++) { rdata = XGBE_GET_DESC_DATA(ring, i); - rdesc = rdata->rdesc; - /* Initialize Rx descriptor - * Set buffer 1 (lo) address to dma address (lo) - * Set buffer 1 (hi) address to dma address (hi) - * Set buffer 2 (lo) address to zero - * Set buffer 2 (hi) address to zero and set control - * bits OWN and INTE appropriateley - */ - rdesc->desc0 = cpu_to_le32(lower_32_bits(rdata->skb_dma)); - rdesc->desc1 = cpu_to_le32(upper_32_bits(rdata->skb_dma)); - rdesc->desc2 = 0; - rdesc->desc3 = 0; - XGMAC_SET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, OWN, 1); - XGMAC_SET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, INTE, 1); - rdata->interrupt = 1; - if (rx_coalesce && (!rx_frames || ((i + 1) % rx_frames))) { - /* Clear interrupt on completion bit */ - XGMAC_SET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, INTE, - 0); + /* Set interrupt on completion bit as appropriate */ + if (rx_coalesce && (!rx_frames || ((i + 1) % rx_frames))) rdata->interrupt = 0; - } - } + else + rdata->interrupt = 1; - /* Make sure everything is written to the descriptors before - * telling the device about them - */ - wmb(); + /* Initialize Rx descriptor */ + xgbe_rx_desc_reset(rdata); + } /* Update the total number of Rx descriptors */ XGMAC_DMA_IOWRITE(channel, DMA_CH_RDRLR, ring->rdesc_count - 1); @@ -1198,7 +1325,30 @@ static void xgbe_config_dcb_pfc(struct xgbe_prv_data *pdata) xgbe_config_flow_control(pdata); } -static void xgbe_pre_xmit(struct xgbe_channel *channel) +static void xgbe_tx_start_xmit(struct xgbe_channel *channel, + struct xgbe_ring *ring) +{ + struct xgbe_prv_data *pdata = channel->pdata; + struct xgbe_ring_data *rdata; + + /* Issue a poll command to Tx DMA by writing address + * of next immediate free descriptor */ + rdata = XGBE_GET_DESC_DATA(ring, ring->cur); + XGMAC_DMA_IOWRITE(channel, DMA_CH_TDTR_LO, + lower_32_bits(rdata->rdesc_dma)); + + /* Start the Tx coalescing timer */ + if (pdata->tx_usecs && !channel->tx_timer_active) { + channel->tx_timer_active = 1; + hrtimer_start(&channel->tx_timer, + ktime_set(0, pdata->tx_usecs * NSEC_PER_USEC), + HRTIMER_MODE_REL); + } + + ring->tx.xmit_more = 0; +} + +static void xgbe_dev_xmit(struct xgbe_channel *channel) { struct xgbe_prv_data *pdata = channel->pdata; struct xgbe_ring *ring = channel->tx_ring; @@ -1207,11 +1357,11 @@ static void xgbe_pre_xmit(struct xgbe_channel *channel) struct xgbe_packet_data *packet = &ring->packet_data; unsigned int csum, tso, vlan; unsigned int tso_context, vlan_context; - unsigned int tx_coalesce, tx_frames; + unsigned int tx_set_ic; int start_index = ring->cur; int i; - DBGPR("-->xgbe_pre_xmit\n"); + DBGPR("-->xgbe_dev_xmit\n"); csum = XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, CSUM_ENABLE); @@ -1230,10 +1380,26 @@ static void xgbe_pre_xmit(struct xgbe_channel *channel) else vlan_context = 0; - tx_coalesce = (pdata->tx_usecs || pdata->tx_frames) ? 1 : 0; - tx_frames = pdata->tx_frames; - if (tx_coalesce && !channel->tx_timer_active) - ring->coalesce_count = 0; + /* Determine if an interrupt should be generated for this Tx: + * Interrupt: + * - Tx frame count exceeds the frame count setting + * - Addition of Tx frame count to the frame count since the + * last interrupt was set exceeds the frame count setting + * No interrupt: + * - No frame count setting specified (ethtool -C ethX tx-frames 0) + * - Addition of Tx frame count to the frame count since the + * last interrupt was set does not exceed the frame count setting + */ + ring->coalesce_count += packet->tx_packets; + if (!pdata->tx_frames) + tx_set_ic = 0; + else if (packet->tx_packets > pdata->tx_frames) + tx_set_ic = 1; + else if ((ring->coalesce_count % pdata->tx_frames) < + packet->tx_packets) + tx_set_ic = 1; + else + tx_set_ic = 0; rdata = XGBE_GET_DESC_DATA(ring, ring->cur); rdesc = rdata->rdesc; @@ -1300,13 +1466,6 @@ static void xgbe_pre_xmit(struct xgbe_channel *channel) if (XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, PTP)) XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, TTSE, 1); - /* Set IC bit based on Tx coalescing settings */ - XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, IC, 1); - if (tx_coalesce && (!tx_frames || - (++ring->coalesce_count % tx_frames))) - /* Clear IC bit */ - XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, IC, 0); - /* Mark it as First Descriptor */ XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, FD, 1); @@ -1351,13 +1510,6 @@ static void xgbe_pre_xmit(struct xgbe_channel *channel) XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, HL_B1L, rdata->skb_dma_len); - /* Set IC bit based on Tx coalescing settings */ - XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, IC, 1); - if (tx_coalesce && (!tx_frames || - (++ring->coalesce_count % tx_frames))) - /* Clear IC bit */ - XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, IC, 0); - /* Set OWN bit */ XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, OWN, 1); @@ -1373,6 +1525,14 @@ static void xgbe_pre_xmit(struct xgbe_channel *channel) /* Set LAST bit for the last descriptor */ XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, LD, 1); + /* Set IC bit based on Tx coalescing settings */ + if (tx_set_ic) + XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, IC, 1); + + /* Save the Tx info to report back during cleanup */ + rdata->tx.packets = packet->tx_packets; + rdata->tx.bytes = packet->tx_bytes; + /* In case the Tx DMA engine is running, make sure everything * is written to the descriptor(s) before setting the OWN bit * for the first descriptor @@ -1391,26 +1551,19 @@ static void xgbe_pre_xmit(struct xgbe_channel *channel) /* Make sure ownership is written to the descriptor */ wmb(); - /* Issue a poll command to Tx DMA by writing address - * of next immediate free descriptor */ ring->cur++; - rdata = XGBE_GET_DESC_DATA(ring, ring->cur); - XGMAC_DMA_IOWRITE(channel, DMA_CH_TDTR_LO, - lower_32_bits(rdata->rdesc_dma)); - - /* Start the Tx coalescing timer */ - if (tx_coalesce && !channel->tx_timer_active) { - channel->tx_timer_active = 1; - hrtimer_start(&channel->tx_timer, - ktime_set(0, pdata->tx_usecs * NSEC_PER_USEC), - HRTIMER_MODE_REL); - } + if (!packet->skb->xmit_more || + netif_xmit_stopped(netdev_get_tx_queue(pdata->netdev, + channel->queue_index))) + xgbe_tx_start_xmit(channel, ring); + else + ring->tx.xmit_more = 1; DBGPR(" %s: descriptors %u to %u written\n", channel->name, start_index & (ring->rdesc_count - 1), (ring->cur - 1) & (ring->rdesc_count - 1)); - DBGPR("<--xgbe_pre_xmit\n"); + DBGPR("<--xgbe_dev_xmit\n"); } static int xgbe_dev_read(struct xgbe_channel *channel) @@ -1420,7 +1573,7 @@ static int xgbe_dev_read(struct xgbe_channel *channel) struct xgbe_ring_desc *rdesc; struct xgbe_packet_data *packet = &ring->packet_data; struct net_device *netdev = channel->pdata->netdev; - unsigned int err, etlt; + unsigned int err, etlt, l34t; DBGPR("-->xgbe_dev_read: cur = %d\n", ring->cur); @@ -1431,6 +1584,9 @@ static int xgbe_dev_read(struct xgbe_channel *channel) if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, OWN)) return 1; + /* Make sure descriptor fields are read after reading the OWN bit */ + rmb(); + #ifdef XGMAC_ENABLE_RX_DESC_DUMP xgbe_dump_rx_desc(ring, rdesc, ring->cur); #endif @@ -1454,8 +1610,33 @@ static int xgbe_dev_read(struct xgbe_channel *channel) XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, CONTEXT_NEXT, 1); + /* Get the header length */ + if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, FD)) + rdata->rx.hdr_len = XGMAC_GET_BITS_LE(rdesc->desc2, + RX_NORMAL_DESC2, HL); + + /* Get the RSS hash */ + if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, RSV)) { + XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, + RSS_HASH, 1); + + packet->rss_hash = le32_to_cpu(rdesc->desc1); + + l34t = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, L34T); + switch (l34t) { + case RX_DESC3_L34T_IPV4_TCP: + case RX_DESC3_L34T_IPV4_UDP: + case RX_DESC3_L34T_IPV6_TCP: + case RX_DESC3_L34T_IPV6_UDP: + packet->rss_hash_type = PKT_HASH_TYPE_L4; + break; + default: + packet->rss_hash_type = PKT_HASH_TYPE_L3; + } + } + /* Get the packet length */ - rdata->len = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, PL); + rdata->rx.len = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, PL); if (!XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, LD)) { /* Not all the data has been transferred for this packet */ @@ -1478,7 +1659,8 @@ static int xgbe_dev_read(struct xgbe_channel *channel) etlt = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, ETLT); DBGPR(" err=%u, etlt=%#x\n", err, etlt); - if (!err || (err && !etlt)) { + if (!err || !etlt) { + /* No error if err is 0 or etlt is 0 */ if ((etlt == 0x09) && (netdev->features & NETIF_F_HW_VLAN_CTAG_RX)) { XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, @@ -2298,6 +2480,47 @@ static void xgbe_config_mmc(struct xgbe_prv_data *pdata) XGMAC_IOWRITE_BITS(pdata, MMC_CR, CR, 1); } +static void xgbe_prepare_tx_stop(struct xgbe_prv_data *pdata, + struct xgbe_channel *channel) +{ + unsigned int tx_dsr, tx_pos, tx_qidx; + unsigned int tx_status; + unsigned long tx_timeout; + + /* Calculate the status register to read and the position within */ + if (channel->queue_index < DMA_DSRX_FIRST_QUEUE) { + tx_dsr = DMA_DSR0; + tx_pos = (channel->queue_index * DMA_DSR_Q_WIDTH) + + DMA_DSR0_TPS_START; + } else { + tx_qidx = channel->queue_index - DMA_DSRX_FIRST_QUEUE; + + tx_dsr = DMA_DSR1 + ((tx_qidx / DMA_DSRX_QPR) * DMA_DSRX_INC); + tx_pos = ((tx_qidx % DMA_DSRX_QPR) * DMA_DSR_Q_WIDTH) + + DMA_DSRX_TPS_START; + } + + /* The Tx engine cannot be stopped if it is actively processing + * descriptors. Wait for the Tx engine to enter the stopped or + * suspended state. Don't wait forever though... + */ + tx_timeout = jiffies + (XGBE_DMA_STOP_TIMEOUT * HZ); + while (time_before(jiffies, tx_timeout)) { + tx_status = XGMAC_IOREAD(pdata, tx_dsr); + tx_status = GET_BITS(tx_status, tx_pos, DMA_DSR_TPS_WIDTH); + if ((tx_status == DMA_TPS_STOPPED) || + (tx_status == DMA_TPS_SUSPENDED)) + break; + + usleep_range(500, 1000); + } + + if (!time_before(jiffies, tx_timeout)) + netdev_info(pdata->netdev, + "timed out waiting for Tx DMA channel %u to stop\n", + channel->queue_index); +} + static void xgbe_enable_tx(struct xgbe_prv_data *pdata) { struct xgbe_channel *channel; @@ -2326,6 +2549,15 @@ static void xgbe_disable_tx(struct xgbe_prv_data *pdata) struct xgbe_channel *channel; unsigned int i; + /* Prepare for Tx DMA channel stop */ + channel = pdata->channel; + for (i = 0; i < pdata->channel_count; i++, channel++) { + if (!channel->tx_ring) + break; + + xgbe_prepare_tx_stop(pdata, channel); + } + /* Disable MAC Tx */ XGMAC_IOWRITE_BITS(pdata, MAC_TCR, TE, 0); @@ -2417,6 +2649,15 @@ static void xgbe_powerdown_tx(struct xgbe_prv_data *pdata) struct xgbe_channel *channel; unsigned int i; + /* Prepare for Tx DMA channel stop */ + channel = pdata->channel; + for (i = 0; i < pdata->channel_count; i++, channel++) { + if (!channel->tx_ring) + break; + + xgbe_prepare_tx_stop(pdata, channel); + } + /* Disable MAC Tx */ XGMAC_IOWRITE_BITS(pdata, MAC_TCR, TE, 0); @@ -2485,6 +2726,8 @@ static int xgbe_init(struct xgbe_prv_data *pdata) xgbe_config_tx_coalesce(pdata); xgbe_config_rx_buffer_size(pdata); xgbe_config_tso_mode(pdata); + xgbe_config_sph_mode(pdata); + xgbe_config_rss(pdata); desc_if->wrapper_tx_desc_init(pdata); desc_if->wrapper_rx_desc_init(pdata); xgbe_enable_dma_interrupts(pdata); @@ -2561,7 +2804,7 @@ void xgbe_init_function_ptrs_dev(struct xgbe_hw_if *hw_if) hw_if->powerup_rx = xgbe_powerup_rx; hw_if->powerdown_rx = xgbe_powerdown_rx; - hw_if->pre_xmit = xgbe_pre_xmit; + hw_if->dev_xmit = xgbe_dev_xmit; hw_if->dev_read = xgbe_dev_read; hw_if->enable_int = xgbe_enable_int; hw_if->disable_int = xgbe_disable_int; @@ -2575,6 +2818,7 @@ void xgbe_init_function_ptrs_dev(struct xgbe_hw_if *hw_if) hw_if->rx_desc_reset = xgbe_rx_desc_reset; hw_if->is_last_desc = xgbe_is_last_desc; hw_if->is_context_desc = xgbe_is_context_desc; + hw_if->tx_start_xmit = xgbe_tx_start_xmit; /* For FLOW ctrl */ hw_if->config_tx_flow_control = xgbe_config_tx_flow_control; @@ -2620,5 +2864,11 @@ void xgbe_init_function_ptrs_dev(struct xgbe_hw_if *hw_if) hw_if->config_dcb_tc = xgbe_config_dcb_tc; hw_if->config_dcb_pfc = xgbe_config_dcb_pfc; + /* For Receive Side Scaling */ + hw_if->enable_rss = xgbe_enable_rss; + hw_if->disable_rss = xgbe_disable_rss; + hw_if->set_rss_hash_key = xgbe_set_rss_hash_key; + hw_if->set_rss_lookup_table = xgbe_set_rss_lookup_table; + DBGPR("<--xgbe_init_function_ptrs\n"); } diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index 2349ea970255..02c104dc2aa4 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c @@ -114,6 +114,7 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ +#include <linux/platform_device.h> #include <linux/spinlock.h> #include <linux/tcp.h> #include <linux/if_vlan.h> @@ -126,14 +127,126 @@ #include "xgbe.h" #include "xgbe-common.h" -static int xgbe_poll(struct napi_struct *, int); +static int xgbe_one_poll(struct napi_struct *, int); +static int xgbe_all_poll(struct napi_struct *, int); static void xgbe_set_rx_mode(struct net_device *); +static int xgbe_alloc_channels(struct xgbe_prv_data *pdata) +{ + struct xgbe_channel *channel_mem, *channel; + struct xgbe_ring *tx_ring, *rx_ring; + unsigned int count, i; + int ret = -ENOMEM; + + count = max_t(unsigned int, pdata->tx_ring_count, pdata->rx_ring_count); + + channel_mem = kcalloc(count, sizeof(struct xgbe_channel), GFP_KERNEL); + if (!channel_mem) + goto err_channel; + + tx_ring = kcalloc(pdata->tx_ring_count, sizeof(struct xgbe_ring), + GFP_KERNEL); + if (!tx_ring) + goto err_tx_ring; + + rx_ring = kcalloc(pdata->rx_ring_count, sizeof(struct xgbe_ring), + GFP_KERNEL); + if (!rx_ring) + goto err_rx_ring; + + for (i = 0, channel = channel_mem; i < count; i++, channel++) { + snprintf(channel->name, sizeof(channel->name), "channel-%d", i); + channel->pdata = pdata; + channel->queue_index = i; + channel->dma_regs = pdata->xgmac_regs + DMA_CH_BASE + + (DMA_CH_INC * i); + + if (pdata->per_channel_irq) { + /* Get the DMA interrupt (offset 1) */ + ret = platform_get_irq(pdata->pdev, i + 1); + if (ret < 0) { + netdev_err(pdata->netdev, + "platform_get_irq %u failed\n", + i + 1); + goto err_irq; + } + + channel->dma_irq = ret; + } + + if (i < pdata->tx_ring_count) { + spin_lock_init(&tx_ring->lock); + channel->tx_ring = tx_ring++; + } + + if (i < pdata->rx_ring_count) { + spin_lock_init(&rx_ring->lock); + channel->rx_ring = rx_ring++; + } + + DBGPR(" %s: queue=%u, dma_regs=%p, dma_irq=%d, tx=%p, rx=%p\n", + channel->name, channel->queue_index, channel->dma_regs, + channel->dma_irq, channel->tx_ring, channel->rx_ring); + } + + pdata->channel = channel_mem; + pdata->channel_count = count; + + return 0; + +err_irq: + kfree(rx_ring); + +err_rx_ring: + kfree(tx_ring); + +err_tx_ring: + kfree(channel_mem); + +err_channel: + return ret; +} + +static void xgbe_free_channels(struct xgbe_prv_data *pdata) +{ + if (!pdata->channel) + return; + + kfree(pdata->channel->rx_ring); + kfree(pdata->channel->tx_ring); + kfree(pdata->channel); + + pdata->channel = NULL; + pdata->channel_count = 0; +} + static inline unsigned int xgbe_tx_avail_desc(struct xgbe_ring *ring) { return (ring->rdesc_count - (ring->cur - ring->dirty)); } +static int xgbe_maybe_stop_tx_queue(struct xgbe_channel *channel, + struct xgbe_ring *ring, unsigned int count) +{ + struct xgbe_prv_data *pdata = channel->pdata; + + if (count > xgbe_tx_avail_desc(ring)) { + DBGPR(" Tx queue stopped, not enough descriptors available\n"); + netif_stop_subqueue(pdata->netdev, channel->queue_index); + ring->tx.queue_stopped = 1; + + /* If we haven't notified the hardware because of xmit_more + * support, tell it now + */ + if (ring->tx.xmit_more) + pdata->hw_if.tx_start_xmit(channel, ring); + + return NETDEV_TX_BUSY; + } + + return 0; +} + static int xgbe_calc_rx_buf_size(struct net_device *netdev, unsigned int mtu) { unsigned int rx_buf_size; @@ -144,8 +257,8 @@ static int xgbe_calc_rx_buf_size(struct net_device *netdev, unsigned int mtu) } rx_buf_size = mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; - if (rx_buf_size < XGBE_RX_MIN_BUF_SIZE) - rx_buf_size = XGBE_RX_MIN_BUF_SIZE; + rx_buf_size = clamp_val(rx_buf_size, XGBE_RX_MIN_BUF_SIZE, PAGE_SIZE); + rx_buf_size = (rx_buf_size + XGBE_RX_BUF_ALIGN - 1) & ~(XGBE_RX_BUF_ALIGN - 1); @@ -213,11 +326,7 @@ static irqreturn_t xgbe_isr(int irq, void *data) if (!dma_isr) goto isr_done; - DBGPR("-->xgbe_isr\n"); - DBGPR(" DMA_ISR = %08x\n", dma_isr); - DBGPR(" DMA_DS0 = %08x\n", XGMAC_IOREAD(pdata, DMA_DSR0)); - DBGPR(" DMA_DS1 = %08x\n", XGMAC_IOREAD(pdata, DMA_DSR1)); for (i = 0; i < pdata->channel_count; i++) { if (!(dma_isr & (1 << i))) @@ -228,6 +337,10 @@ static irqreturn_t xgbe_isr(int irq, void *data) dma_ch_isr = XGMAC_DMA_IOREAD(channel, DMA_CH_SR); DBGPR(" DMA_CH%u_ISR = %08x\n", i, dma_ch_isr); + /* If we get a TI or RI interrupt that means per channel DMA + * interrupts are not enabled, so we use the private data napi + * structure, not the per channel napi structure + */ if (XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, TI) || XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, RI)) { if (napi_schedule_prep(&pdata->napi)) { @@ -270,12 +383,28 @@ static irqreturn_t xgbe_isr(int irq, void *data) DBGPR(" DMA_ISR = %08x\n", XGMAC_IOREAD(pdata, DMA_ISR)); - DBGPR("<--xgbe_isr\n"); - isr_done: return IRQ_HANDLED; } +static irqreturn_t xgbe_dma_isr(int irq, void *data) +{ + struct xgbe_channel *channel = data; + + /* Per channel DMA interrupts are enabled, so we use the per + * channel napi structure and not the private data napi structure + */ + if (napi_schedule_prep(&channel->napi)) { + /* Disable Tx and Rx interrupts */ + disable_irq(channel->dma_irq); + + /* Turn on polling */ + __napi_schedule(&channel->napi); + } + + return IRQ_HANDLED; +} + static enum hrtimer_restart xgbe_tx_timer(struct hrtimer *timer) { struct xgbe_channel *channel = container_of(timer, @@ -283,18 +412,24 @@ static enum hrtimer_restart xgbe_tx_timer(struct hrtimer *timer) tx_timer); struct xgbe_ring *ring = channel->tx_ring; struct xgbe_prv_data *pdata = channel->pdata; + struct napi_struct *napi; unsigned long flags; DBGPR("-->xgbe_tx_timer\n"); + napi = (pdata->per_channel_irq) ? &channel->napi : &pdata->napi; + spin_lock_irqsave(&ring->lock, flags); - if (napi_schedule_prep(&pdata->napi)) { + if (napi_schedule_prep(napi)) { /* Disable Tx and Rx interrupts */ - xgbe_disable_rx_tx_ints(pdata); + if (pdata->per_channel_irq) + disable_irq(channel->dma_irq); + else + xgbe_disable_rx_tx_ints(pdata); /* Turn on polling */ - __napi_schedule(&pdata->napi); + __napi_schedule(napi); } channel->tx_timer_active = 0; @@ -430,18 +565,46 @@ void xgbe_get_all_hw_features(struct xgbe_prv_data *pdata) static void xgbe_napi_enable(struct xgbe_prv_data *pdata, unsigned int add) { - if (add) - netif_napi_add(pdata->netdev, &pdata->napi, xgbe_poll, - NAPI_POLL_WEIGHT); - napi_enable(&pdata->napi); + struct xgbe_channel *channel; + unsigned int i; + + if (pdata->per_channel_irq) { + channel = pdata->channel; + for (i = 0; i < pdata->channel_count; i++, channel++) { + if (add) + netif_napi_add(pdata->netdev, &channel->napi, + xgbe_one_poll, NAPI_POLL_WEIGHT); + + napi_enable(&channel->napi); + } + } else { + if (add) + netif_napi_add(pdata->netdev, &pdata->napi, + xgbe_all_poll, NAPI_POLL_WEIGHT); + + napi_enable(&pdata->napi); + } } static void xgbe_napi_disable(struct xgbe_prv_data *pdata, unsigned int del) { - napi_disable(&pdata->napi); + struct xgbe_channel *channel; + unsigned int i; + + if (pdata->per_channel_irq) { + channel = pdata->channel; + for (i = 0; i < pdata->channel_count; i++, channel++) { + napi_disable(&channel->napi); - if (del) - netif_napi_del(&pdata->napi); + if (del) + netif_napi_del(&channel->napi); + } + } else { + napi_disable(&pdata->napi); + + if (del) + netif_napi_del(&pdata->napi); + } } void xgbe_init_tx_coalesce(struct xgbe_prv_data *pdata) @@ -472,7 +635,7 @@ void xgbe_init_rx_coalesce(struct xgbe_prv_data *pdata) DBGPR("<--xgbe_init_rx_coalesce\n"); } -static void xgbe_free_tx_skbuff(struct xgbe_prv_data *pdata) +static void xgbe_free_tx_data(struct xgbe_prv_data *pdata) { struct xgbe_desc_if *desc_if = &pdata->desc_if; struct xgbe_channel *channel; @@ -480,7 +643,7 @@ static void xgbe_free_tx_skbuff(struct xgbe_prv_data *pdata) struct xgbe_ring_data *rdata; unsigned int i, j; - DBGPR("-->xgbe_free_tx_skbuff\n"); + DBGPR("-->xgbe_free_tx_data\n"); channel = pdata->channel; for (i = 0; i < pdata->channel_count; i++, channel++) { @@ -490,14 +653,14 @@ static void xgbe_free_tx_skbuff(struct xgbe_prv_data *pdata) for (j = 0; j < ring->rdesc_count; j++) { rdata = XGBE_GET_DESC_DATA(ring, j); - desc_if->unmap_skb(pdata, rdata); + desc_if->unmap_rdata(pdata, rdata); } } - DBGPR("<--xgbe_free_tx_skbuff\n"); + DBGPR("<--xgbe_free_tx_data\n"); } -static void xgbe_free_rx_skbuff(struct xgbe_prv_data *pdata) +static void xgbe_free_rx_data(struct xgbe_prv_data *pdata) { struct xgbe_desc_if *desc_if = &pdata->desc_if; struct xgbe_channel *channel; @@ -505,7 +668,7 @@ static void xgbe_free_rx_skbuff(struct xgbe_prv_data *pdata) struct xgbe_ring_data *rdata; unsigned int i, j; - DBGPR("-->xgbe_free_rx_skbuff\n"); + DBGPR("-->xgbe_free_rx_data\n"); channel = pdata->channel; for (i = 0; i < pdata->channel_count; i++, channel++) { @@ -515,11 +678,11 @@ static void xgbe_free_rx_skbuff(struct xgbe_prv_data *pdata) for (j = 0; j < ring->rdesc_count; j++) { rdata = XGBE_GET_DESC_DATA(ring, j); - desc_if->unmap_skb(pdata, rdata); + desc_if->unmap_rdata(pdata, rdata); } } - DBGPR("<--xgbe_free_rx_skbuff\n"); + DBGPR("<--xgbe_free_rx_data\n"); } static void xgbe_adjust_link(struct net_device *netdev) @@ -735,7 +898,10 @@ static int xgbe_start(struct xgbe_prv_data *pdata) static void xgbe_stop(struct xgbe_prv_data *pdata) { struct xgbe_hw_if *hw_if = &pdata->hw_if; + struct xgbe_channel *channel; struct net_device *netdev = pdata->netdev; + struct netdev_queue *txq; + unsigned int i; DBGPR("-->xgbe_stop\n"); @@ -749,12 +915,23 @@ static void xgbe_stop(struct xgbe_prv_data *pdata) hw_if->disable_tx(pdata); hw_if->disable_rx(pdata); + channel = pdata->channel; + for (i = 0; i < pdata->channel_count; i++, channel++) { + if (!channel->tx_ring) + continue; + + txq = netdev_get_tx_queue(netdev, channel->queue_index); + netdev_tx_reset_queue(txq); + } + DBGPR("<--xgbe_stop\n"); } static void xgbe_restart_dev(struct xgbe_prv_data *pdata, unsigned int reset) { + struct xgbe_channel *channel; struct xgbe_hw_if *hw_if = &pdata->hw_if; + unsigned int i; DBGPR("-->xgbe_restart_dev\n"); @@ -763,10 +940,15 @@ static void xgbe_restart_dev(struct xgbe_prv_data *pdata, unsigned int reset) return; xgbe_stop(pdata); - synchronize_irq(pdata->irq_number); + synchronize_irq(pdata->dev_irq); + if (pdata->per_channel_irq) { + channel = pdata->channel; + for (i = 0; i < pdata->channel_count; i++, channel++) + synchronize_irq(channel->dma_irq); + } - xgbe_free_tx_skbuff(pdata); - xgbe_free_rx_skbuff(pdata); + xgbe_free_tx_data(pdata); + xgbe_free_rx_data(pdata); /* Issue software reset to device if requested */ if (reset) @@ -1008,6 +1190,12 @@ static int xgbe_prep_tso(struct sk_buff *skb, struct xgbe_packet_data *packet) packet->tcp_header_len, packet->tcp_payload_len); DBGPR(" packet->mss=%u\n", packet->mss); + /* Update the number of packets that will ultimately be transmitted + * along with the extra bytes for each extra packet + */ + packet->tx_packets = skb_shinfo(skb)->gso_segs; + packet->tx_bytes += (packet->tx_packets - 1) * packet->header_len; + return 0; } @@ -1033,17 +1221,22 @@ static void xgbe_packet_info(struct xgbe_prv_data *pdata, unsigned int len; unsigned int i; + packet->skb = skb; + context_desc = 0; packet->rdesc_count = 0; + packet->tx_packets = 1; + packet->tx_bytes = skb->len; + if (xgbe_is_tso(skb)) { - /* TSO requires an extra desriptor if mss is different */ + /* TSO requires an extra descriptor if mss is different */ if (skb_shinfo(skb)->gso_size != ring->tx.cur_mss) { context_desc = 1; packet->rdesc_count++; } - /* TSO requires an extra desriptor for TSO header */ + /* TSO requires an extra descriptor for TSO header */ packet->rdesc_count++; XGMAC_SET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, @@ -1091,6 +1284,9 @@ static int xgbe_open(struct net_device *netdev) struct xgbe_prv_data *pdata = netdev_priv(netdev); struct xgbe_hw_if *hw_if = &pdata->hw_if; struct xgbe_desc_if *desc_if = &pdata->desc_if; + struct xgbe_channel *channel = NULL; + char dma_irq_name[IFNAMSIZ + 32]; + unsigned int i = 0; int ret; DBGPR("-->xgbe_open\n"); @@ -1119,24 +1315,47 @@ static int xgbe_open(struct net_device *netdev) goto err_ptpclk; pdata->rx_buf_size = ret; + /* Allocate the channel and ring structures */ + ret = xgbe_alloc_channels(pdata); + if (ret) + goto err_ptpclk; + /* Allocate the ring descriptors and buffers */ ret = desc_if->alloc_ring_resources(pdata); if (ret) - goto err_ptpclk; + goto err_channels; /* Initialize the device restart and Tx timestamp work struct */ INIT_WORK(&pdata->restart_work, xgbe_restart); INIT_WORK(&pdata->tx_tstamp_work, xgbe_tx_tstamp); /* Request interrupts */ - ret = devm_request_irq(pdata->dev, netdev->irq, xgbe_isr, 0, + ret = devm_request_irq(pdata->dev, pdata->dev_irq, xgbe_isr, 0, netdev->name, pdata); if (ret) { netdev_alert(netdev, "error requesting irq %d\n", - pdata->irq_number); - goto err_irq; + pdata->dev_irq); + goto err_rings; + } + + if (pdata->per_channel_irq) { + channel = pdata->channel; + for (i = 0; i < pdata->channel_count; i++, channel++) { + snprintf(dma_irq_name, sizeof(dma_irq_name) - 1, + "%s-TxRx-%u", netdev_name(netdev), + channel->queue_index); + + ret = devm_request_irq(pdata->dev, channel->dma_irq, + xgbe_dma_isr, 0, dma_irq_name, + channel); + if (ret) { + netdev_alert(netdev, + "error requesting irq %d\n", + channel->dma_irq); + goto err_irq; + } + } } - pdata->irq_number = netdev->irq; ret = xgbe_start(pdata); if (ret) @@ -1149,12 +1368,21 @@ static int xgbe_open(struct net_device *netdev) err_start: hw_if->exit(pdata); - devm_free_irq(pdata->dev, pdata->irq_number, pdata); - pdata->irq_number = 0; - err_irq: + if (pdata->per_channel_irq) { + /* Using an unsigned int, 'i' will go to UINT_MAX and exit */ + for (i--, channel--; i < pdata->channel_count; i--, channel--) + devm_free_irq(pdata->dev, channel->dma_irq, channel); + } + + devm_free_irq(pdata->dev, pdata->dev_irq, pdata); + +err_rings: desc_if->free_ring_resources(pdata); +err_channels: + xgbe_free_channels(pdata); + err_ptpclk: clk_disable_unprepare(pdata->ptpclk); @@ -1172,6 +1400,8 @@ static int xgbe_close(struct net_device *netdev) struct xgbe_prv_data *pdata = netdev_priv(netdev); struct xgbe_hw_if *hw_if = &pdata->hw_if; struct xgbe_desc_if *desc_if = &pdata->desc_if; + struct xgbe_channel *channel; + unsigned int i; DBGPR("-->xgbe_close\n"); @@ -1181,15 +1411,20 @@ static int xgbe_close(struct net_device *netdev) /* Issue software reset to device */ hw_if->exit(pdata); - /* Free all the ring data */ + /* Free the ring descriptors and buffers */ desc_if->free_ring_resources(pdata); - /* Release the interrupt */ - if (pdata->irq_number != 0) { - devm_free_irq(pdata->dev, pdata->irq_number, pdata); - pdata->irq_number = 0; + /* Release the interrupts */ + devm_free_irq(pdata->dev, pdata->dev_irq, pdata); + if (pdata->per_channel_irq) { + channel = pdata->channel; + for (i = 0; i < pdata->channel_count; i++, channel++) + devm_free_irq(pdata->dev, channel->dma_irq, channel); } + /* Free the channel and ring structures */ + xgbe_free_channels(pdata); + /* Disable the clocks */ clk_disable_unprepare(pdata->ptpclk); clk_disable_unprepare(pdata->sysclk); @@ -1210,12 +1445,14 @@ static int xgbe_xmit(struct sk_buff *skb, struct net_device *netdev) struct xgbe_channel *channel; struct xgbe_ring *ring; struct xgbe_packet_data *packet; + struct netdev_queue *txq; unsigned long flags; int ret; DBGPR("-->xgbe_xmit: skb->len = %d\n", skb->len); channel = pdata->channel + skb->queue_mapping; + txq = netdev_get_tx_queue(netdev, channel->queue_index); ring = channel->tx_ring; packet = &ring->packet_data; @@ -1234,13 +1471,9 @@ static int xgbe_xmit(struct sk_buff *skb, struct net_device *netdev) xgbe_packet_info(pdata, ring, skb, packet); /* Check that there are enough descriptors available */ - if (packet->rdesc_count > xgbe_tx_avail_desc(ring)) { - DBGPR(" Tx queue stopped, not enough descriptors available\n"); - netif_stop_subqueue(netdev, channel->queue_index); - ring->tx.queue_stopped = 1; - ret = NETDEV_TX_BUSY; + ret = xgbe_maybe_stop_tx_queue(channel, ring, packet->rdesc_count); + if (ret) goto tx_netdev_return; - } ret = xgbe_prep_tso(skb, packet); if (ret) { @@ -1257,13 +1490,21 @@ static int xgbe_xmit(struct sk_buff *skb, struct net_device *netdev) xgbe_prep_tx_tstamp(pdata, skb, packet); + /* Report on the actual number of bytes (to be) sent */ + netdev_tx_sent_queue(txq, packet->tx_bytes); + /* Configure required descriptor fields for transmission */ - hw_if->pre_xmit(channel); + hw_if->dev_xmit(channel); #ifdef XGMAC_ENABLE_TX_PKT_DUMP xgbe_print_pkt(netdev, skb, true); #endif + /* Stop the queue in advance if there may not be enough descriptors */ + xgbe_maybe_stop_tx_queue(channel, ring, XGBE_TX_MAX_DESCS); + + ret = NETDEV_TX_OK; + tx_netdev_return: spin_unlock_irqrestore(&ring->lock, flags); @@ -1420,14 +1661,20 @@ static int xgbe_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, static void xgbe_poll_controller(struct net_device *netdev) { struct xgbe_prv_data *pdata = netdev_priv(netdev); + struct xgbe_channel *channel; + unsigned int i; DBGPR("-->xgbe_poll_controller\n"); - disable_irq(pdata->irq_number); - - xgbe_isr(pdata->irq_number, pdata); - - enable_irq(pdata->irq_number); + if (pdata->per_channel_irq) { + channel = pdata->channel; + for (i = 0; i < pdata->channel_count; i++, channel++) + xgbe_dma_isr(channel->dma_irq, channel); + } else { + disable_irq(pdata->dev_irq); + xgbe_isr(pdata->dev_irq, pdata); + enable_irq(pdata->dev_irq); + } DBGPR("<--xgbe_poll_controller\n"); } @@ -1465,12 +1712,21 @@ static int xgbe_set_features(struct net_device *netdev, { struct xgbe_prv_data *pdata = netdev_priv(netdev); struct xgbe_hw_if *hw_if = &pdata->hw_if; - netdev_features_t rxcsum, rxvlan, rxvlan_filter; + netdev_features_t rxhash, rxcsum, rxvlan, rxvlan_filter; + int ret = 0; + rxhash = pdata->netdev_features & NETIF_F_RXHASH; rxcsum = pdata->netdev_features & NETIF_F_RXCSUM; rxvlan = pdata->netdev_features & NETIF_F_HW_VLAN_CTAG_RX; rxvlan_filter = pdata->netdev_features & NETIF_F_HW_VLAN_CTAG_FILTER; + if ((features & NETIF_F_RXHASH) && !rxhash) + ret = hw_if->enable_rss(pdata); + else if (!(features & NETIF_F_RXHASH) && rxhash) + ret = hw_if->disable_rss(pdata); + if (ret) + return ret; + if ((features & NETIF_F_RXCSUM) && !rxcsum) hw_if->enable_rx_csum(pdata); else if (!(features & NETIF_F_RXCSUM) && rxcsum) @@ -1524,7 +1780,7 @@ static void xgbe_rx_refresh(struct xgbe_channel *channel) struct xgbe_ring *ring = channel->rx_ring; struct xgbe_ring_data *rdata; - desc_if->realloc_skb(channel); + desc_if->realloc_rx_buffer(channel); /* Update the Rx Tail Pointer Register with address of * the last cleaned entry */ @@ -1533,6 +1789,31 @@ static void xgbe_rx_refresh(struct xgbe_channel *channel) lower_32_bits(rdata->rdesc_dma)); } +static struct sk_buff *xgbe_create_skb(struct xgbe_prv_data *pdata, + struct xgbe_ring_data *rdata, + unsigned int *len) +{ + struct net_device *netdev = pdata->netdev; + struct sk_buff *skb; + u8 *packet; + unsigned int copy_len; + + skb = netdev_alloc_skb_ip_align(netdev, rdata->rx.hdr.dma_len); + if (!skb) + return NULL; + + packet = page_address(rdata->rx.hdr.pa.pages) + + rdata->rx.hdr.pa.pages_offset; + copy_len = (rdata->rx.hdr_len) ? rdata->rx.hdr_len : *len; + copy_len = min(rdata->rx.hdr.dma_len, copy_len); + skb_copy_to_linear_data(skb, packet, copy_len); + skb_put(skb, copy_len); + + *len -= copy_len; + + return skb; +} + static int xgbe_tx_poll(struct xgbe_channel *channel) { struct xgbe_prv_data *pdata = channel->pdata; @@ -1542,8 +1823,10 @@ static int xgbe_tx_poll(struct xgbe_channel *channel) struct xgbe_ring_data *rdata; struct xgbe_ring_desc *rdesc; struct net_device *netdev = pdata->netdev; + struct netdev_queue *txq; unsigned long flags; int processed = 0; + unsigned int tx_packets = 0, tx_bytes = 0; DBGPR("-->xgbe_tx_poll\n"); @@ -1551,6 +1834,8 @@ static int xgbe_tx_poll(struct xgbe_channel *channel) if (!ring) return 0; + txq = netdev_get_tx_queue(netdev, channel->queue_index); + spin_lock_irqsave(&ring->lock, flags); while ((processed < XGBE_TX_DESC_MAX_PROC) && @@ -1561,26 +1846,41 @@ static int xgbe_tx_poll(struct xgbe_channel *channel) if (!hw_if->tx_complete(rdesc)) break; + /* Make sure descriptor fields are read after reading the OWN + * bit */ + rmb(); + #ifdef XGMAC_ENABLE_TX_DESC_DUMP xgbe_dump_tx_desc(ring, ring->dirty, 1, 0); #endif + if (hw_if->is_last_desc(rdesc)) { + tx_packets += rdata->tx.packets; + tx_bytes += rdata->tx.bytes; + } + /* Free the SKB and reset the descriptor for re-use */ - desc_if->unmap_skb(pdata, rdata); + desc_if->unmap_rdata(pdata, rdata); hw_if->tx_desc_reset(rdata); processed++; ring->dirty++; } + if (!processed) + goto unlock; + + netdev_tx_completed_queue(txq, tx_packets, tx_bytes); + if ((ring->tx.queue_stopped == 1) && (xgbe_tx_avail_desc(ring) > XGBE_TX_DESC_MIN_FREE)) { ring->tx.queue_stopped = 0; - netif_wake_subqueue(netdev, channel->queue_index); + netif_tx_wake_queue(txq); } DBGPR("<--xgbe_tx_poll: processed=%d\n", processed); +unlock: spin_unlock_irqrestore(&ring->lock, flags); return processed; @@ -1594,6 +1894,7 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget) struct xgbe_ring_data *rdata; struct xgbe_packet_data *packet; struct net_device *netdev = pdata->netdev; + struct napi_struct *napi; struct sk_buff *skb; struct skb_shared_hwtstamps *hwtstamps; unsigned int incomplete, error, context_next, context; @@ -1607,6 +1908,8 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget) if (!ring) return 0; + napi = (pdata->per_channel_irq) ? &channel->napi : &pdata->napi; + rdata = XGBE_GET_DESC_DATA(ring, ring->cur); packet = &ring->packet_data; while (packet_count < budget) { @@ -1641,10 +1944,6 @@ read_again: ring->cur++; ring->dirty++; - dma_unmap_single(pdata->dev, rdata->skb_dma, - rdata->skb_dma_len, DMA_FROM_DEVICE); - rdata->skb_dma = 0; - incomplete = XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, INCOMPLETE); @@ -1667,33 +1966,40 @@ read_again: } if (!context) { - put_len = rdata->len - len; - if (skb) { - if (pskb_expand_head(skb, 0, put_len, - GFP_ATOMIC)) { - DBGPR("pskb_expand_head error\n"); - if (incomplete) { - error = 1; - goto read_again; - } - - dev_kfree_skb(skb); - goto next_packet; + put_len = rdata->rx.len - len; + len += put_len; + + if (!skb) { + dma_sync_single_for_cpu(pdata->dev, + rdata->rx.hdr.dma, + rdata->rx.hdr.dma_len, + DMA_FROM_DEVICE); + + skb = xgbe_create_skb(pdata, rdata, &put_len); + if (!skb) { + error = 1; + goto skip_data; } - memcpy(skb_tail_pointer(skb), rdata->skb->data, - put_len); - } else { - skb = rdata->skb; - rdata->skb = NULL; } - skb_put(skb, put_len); - len += put_len; + + if (put_len) { + dma_sync_single_for_cpu(pdata->dev, + rdata->rx.buf.dma, + rdata->rx.buf.dma_len, + DMA_FROM_DEVICE); + + skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, + rdata->rx.buf.pa.pages, + rdata->rx.buf.pa.pages_offset, + put_len, rdata->rx.buf.dma_len); + rdata->rx.buf.pa.pages = NULL; + } } +skip_data: if (incomplete || context_next) goto read_again; - /* Stray Context Descriptor? */ if (!skb) goto next_packet; @@ -1733,13 +2039,18 @@ read_again: hwtstamps->hwtstamp = ns_to_ktime(nsec); } + if (XGMAC_GET_BITS(packet->attributes, + RX_PACKET_ATTRIBUTES, RSS_HASH)) + skb_set_hash(skb, packet->rss_hash, + packet->rss_hash_type); + skb->dev = netdev; skb->protocol = eth_type_trans(skb, netdev); skb_record_rx_queue(skb, channel->queue_index); - skb_mark_napi_id(skb, &pdata->napi); + skb_mark_napi_id(skb, napi); netdev->last_rx = jiffies; - napi_gro_receive(&pdata->napi, skb); + napi_gro_receive(napi, skb); next_packet: packet_count++; @@ -1761,7 +2072,35 @@ next_packet: return packet_count; } -static int xgbe_poll(struct napi_struct *napi, int budget) +static int xgbe_one_poll(struct napi_struct *napi, int budget) +{ + struct xgbe_channel *channel = container_of(napi, struct xgbe_channel, + napi); + int processed = 0; + + DBGPR("-->xgbe_one_poll: budget=%d\n", budget); + + /* Cleanup Tx ring first */ + xgbe_tx_poll(channel); + + /* Process Rx ring next */ + processed = xgbe_rx_poll(channel, budget); + + /* If we processed everything, we are done */ + if (processed < budget) { + /* Turn off polling */ + napi_complete(napi); + + /* Enable Tx and Rx interrupts */ + enable_irq(channel->dma_irq); + } + + DBGPR("<--xgbe_one_poll: received = %d\n", processed); + + return processed; +} + +static int xgbe_all_poll(struct napi_struct *napi, int budget) { struct xgbe_prv_data *pdata = container_of(napi, struct xgbe_prv_data, napi); @@ -1770,7 +2109,7 @@ static int xgbe_poll(struct napi_struct *napi, int budget) int processed, last_processed; unsigned int i; - DBGPR("-->xgbe_poll: budget=%d\n", budget); + DBGPR("-->xgbe_all_poll: budget=%d\n", budget); processed = 0; ring_budget = budget / pdata->rx_ring_count; @@ -1798,7 +2137,7 @@ static int xgbe_poll(struct napi_struct *napi, int budget) xgbe_enable_rx_tx_ints(pdata); } - DBGPR("<--xgbe_poll: received = %d\n", processed); + DBGPR("<--xgbe_all_poll: received = %d\n", processed); return processed; } @@ -1812,10 +2151,10 @@ void xgbe_dump_tx_desc(struct xgbe_ring *ring, unsigned int idx, while (count--) { rdata = XGBE_GET_DESC_DATA(ring, idx); rdesc = rdata->rdesc; - DBGPR("TX_NORMAL_DESC[%d %s] = %08x:%08x:%08x:%08x\n", idx, - (flag == 1) ? "QUEUED FOR TX" : "TX BY DEVICE", - le32_to_cpu(rdesc->desc0), le32_to_cpu(rdesc->desc1), - le32_to_cpu(rdesc->desc2), le32_to_cpu(rdesc->desc3)); + pr_alert("TX_NORMAL_DESC[%d %s] = %08x:%08x:%08x:%08x\n", idx, + (flag == 1) ? "QUEUED FOR TX" : "TX BY DEVICE", + le32_to_cpu(rdesc->desc0), le32_to_cpu(rdesc->desc1), + le32_to_cpu(rdesc->desc2), le32_to_cpu(rdesc->desc3)); idx++; } } @@ -1823,9 +2162,9 @@ void xgbe_dump_tx_desc(struct xgbe_ring *ring, unsigned int idx, void xgbe_dump_rx_desc(struct xgbe_ring *ring, struct xgbe_ring_desc *desc, unsigned int idx) { - DBGPR("RX_NORMAL_DESC[%d RX BY DEVICE] = %08x:%08x:%08x:%08x\n", idx, - le32_to_cpu(desc->desc0), le32_to_cpu(desc->desc1), - le32_to_cpu(desc->desc2), le32_to_cpu(desc->desc3)); + pr_alert("RX_NORMAL_DESC[%d RX BY DEVICE] = %08x:%08x:%08x:%08x\n", idx, + le32_to_cpu(desc->desc0), le32_to_cpu(desc->desc1), + le32_to_cpu(desc->desc2), le32_to_cpu(desc->desc3)); } void xgbe_print_pkt(struct net_device *netdev, struct sk_buff *skb, bool tx_rx) diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c index 49508ec98b72..95d44538357f 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c @@ -452,9 +452,9 @@ static int xgbe_set_coalesce(struct net_device *netdev, rx_usecs); return -EINVAL; } - if (rx_frames > pdata->channel->rx_ring->rdesc_count) { + if (rx_frames > pdata->rx_desc_count) { netdev_alert(netdev, "rx-frames is limited to %d frames\n", - pdata->channel->rx_ring->rdesc_count); + pdata->rx_desc_count); return -EINVAL; } @@ -462,9 +462,9 @@ static int xgbe_set_coalesce(struct net_device *netdev, tx_frames = ec->tx_max_coalesced_frames; /* Check the bounds of values for Tx */ - if (tx_frames > pdata->channel->tx_ring->rdesc_count) { + if (tx_frames > pdata->tx_desc_count) { netdev_alert(netdev, "tx-frames is limited to %d frames\n", - pdata->channel->tx_ring->rdesc_count); + pdata->tx_desc_count); return -EINVAL; } @@ -481,6 +481,75 @@ static int xgbe_set_coalesce(struct net_device *netdev, return 0; } +static int xgbe_get_rxnfc(struct net_device *netdev, + struct ethtool_rxnfc *rxnfc, u32 *rule_locs) +{ + struct xgbe_prv_data *pdata = netdev_priv(netdev); + + switch (rxnfc->cmd) { + case ETHTOOL_GRXRINGS: + rxnfc->data = pdata->rx_ring_count; + break; + default: + return -EOPNOTSUPP; + } + + return 0; +} + +static u32 xgbe_get_rxfh_key_size(struct net_device *netdev) +{ + struct xgbe_prv_data *pdata = netdev_priv(netdev); + + return sizeof(pdata->rss_key); +} + +static u32 xgbe_get_rxfh_indir_size(struct net_device *netdev) +{ + struct xgbe_prv_data *pdata = netdev_priv(netdev); + + return ARRAY_SIZE(pdata->rss_table); +} + +static int xgbe_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key) +{ + struct xgbe_prv_data *pdata = netdev_priv(netdev); + unsigned int i; + + if (indir) { + for (i = 0; i < ARRAY_SIZE(pdata->rss_table); i++) + indir[i] = XGMAC_GET_BITS(pdata->rss_table[i], + MAC_RSSDR, DMCH); + } + + if (key) + memcpy(key, pdata->rss_key, sizeof(pdata->rss_key)); + + return 0; +} + +static int xgbe_set_rxfh(struct net_device *netdev, const u32 *indir, + const u8 *key) +{ + struct xgbe_prv_data *pdata = netdev_priv(netdev); + struct xgbe_hw_if *hw_if = &pdata->hw_if; + unsigned int ret; + + if (indir) { + ret = hw_if->set_rss_lookup_table(pdata, indir); + if (ret) + return ret; + } + + if (key) { + ret = hw_if->set_rss_hash_key(pdata, key); + if (ret) + return ret; + } + + return 0; +} + static int xgbe_get_ts_info(struct net_device *netdev, struct ethtool_ts_info *ts_info) { @@ -526,6 +595,11 @@ static const struct ethtool_ops xgbe_ethtool_ops = { .get_strings = xgbe_get_strings, .get_ethtool_stats = xgbe_get_ethtool_stats, .get_sset_count = xgbe_get_sset_count, + .get_rxnfc = xgbe_get_rxnfc, + .get_rxfh_key_size = xgbe_get_rxfh_key_size, + .get_rxfh_indir_size = xgbe_get_rxfh_indir_size, + .get_rxfh = xgbe_get_rxfh, + .set_rxfh = xgbe_set_rxfh, .get_ts_info = xgbe_get_ts_info, }; diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c index f5a8fa03921a..dbd3850b8b0a 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c @@ -133,60 +133,6 @@ MODULE_LICENSE("Dual BSD/GPL"); MODULE_VERSION(XGBE_DRV_VERSION); MODULE_DESCRIPTION(XGBE_DRV_DESC); -static struct xgbe_channel *xgbe_alloc_rings(struct xgbe_prv_data *pdata) -{ - struct xgbe_channel *channel_mem, *channel; - struct xgbe_ring *tx_ring, *rx_ring; - unsigned int count, i; - - DBGPR("-->xgbe_alloc_rings\n"); - - count = max_t(unsigned int, pdata->tx_ring_count, pdata->rx_ring_count); - - channel_mem = devm_kcalloc(pdata->dev, count, - sizeof(struct xgbe_channel), GFP_KERNEL); - if (!channel_mem) - return NULL; - - tx_ring = devm_kcalloc(pdata->dev, pdata->tx_ring_count, - sizeof(struct xgbe_ring), GFP_KERNEL); - if (!tx_ring) - return NULL; - - rx_ring = devm_kcalloc(pdata->dev, pdata->rx_ring_count, - sizeof(struct xgbe_ring), GFP_KERNEL); - if (!rx_ring) - return NULL; - - for (i = 0, channel = channel_mem; i < count; i++, channel++) { - snprintf(channel->name, sizeof(channel->name), "channel-%d", i); - channel->pdata = pdata; - channel->queue_index = i; - channel->dma_regs = pdata->xgmac_regs + DMA_CH_BASE + - (DMA_CH_INC * i); - - if (i < pdata->tx_ring_count) { - spin_lock_init(&tx_ring->lock); - channel->tx_ring = tx_ring++; - } - - if (i < pdata->rx_ring_count) { - spin_lock_init(&rx_ring->lock); - channel->rx_ring = rx_ring++; - } - - DBGPR(" %s - queue_index=%u, dma_regs=%p, tx=%p, rx=%p\n", - channel->name, channel->queue_index, channel->dma_regs, - channel->tx_ring, channel->rx_ring); - } - - pdata->channel_count = count; - - DBGPR("<--xgbe_alloc_rings\n"); - - return channel_mem; -} - static void xgbe_default_config(struct xgbe_prv_data *pdata) { DBGPR("-->xgbe_default_config\n"); @@ -224,6 +170,7 @@ static int xgbe_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct resource *res; const u8 *mac_addr; + unsigned int i; int ret; DBGPR("--> xgbe_probe\n"); @@ -244,6 +191,7 @@ static int xgbe_probe(struct platform_device *pdev) spin_lock_init(&pdata->lock); mutex_init(&pdata->xpcs_mutex); + mutex_init(&pdata->rss_mutex); spin_lock_init(&pdata->tstamp_lock); /* Set and validate the number of descriptors for a ring */ @@ -318,12 +266,18 @@ static int xgbe_probe(struct platform_device *pdev) pdata->awcache = XGBE_DMA_SYS_AWCACHE; } + /* Check for per channel interrupt support */ + if (of_property_read_bool(dev->of_node, XGBE_DMA_IRQS)) + pdata->per_channel_irq = 1; + ret = platform_get_irq(pdev, 0); if (ret < 0) { - dev_err(dev, "platform_get_irq failed\n"); + dev_err(dev, "platform_get_irq 0 failed\n"); goto err_io; } - netdev->irq = ret; + pdata->dev_irq = ret; + + netdev->irq = pdata->dev_irq; netdev->base_addr = (unsigned long)pdata->xgmac_regs; /* Set all the function pointers */ @@ -383,13 +337,16 @@ static int xgbe_probe(struct platform_device *pdev) goto err_io; } - /* Allocate the rings for the DMA channels */ - pdata->channel = xgbe_alloc_rings(pdata); - if (!pdata->channel) { - dev_err(dev, "ring allocation failed\n"); - ret = -ENOMEM; - goto err_io; - } + /* Initialize RSS hash key and lookup table */ + netdev_rss_key_fill(pdata->rss_key, sizeof(pdata->rss_key)); + + for (i = 0; i < XGBE_RSS_MAX_TABLE_SIZE; i++) + XGMAC_SET_BITS(pdata->rss_table[i], MAC_RSSDR, DMCH, + i % pdata->rx_ring_count); + + XGMAC_SET_BITS(pdata->rss_options, MAC_RSSCR, IP2TE, 1); + XGMAC_SET_BITS(pdata->rss_options, MAC_RSSCR, TCP4TE, 1); + XGMAC_SET_BITS(pdata->rss_options, MAC_RSSCR, UDP4TE, 1); /* Prepare to regsiter with MDIO */ pdata->mii_bus_id = kasprintf(GFP_KERNEL, "%s", pdev->name); @@ -421,6 +378,9 @@ static int xgbe_probe(struct platform_device *pdev) NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_FILTER; + if (pdata->hw_feat.rss) + netdev->hw_features |= NETIF_F_RXHASH; + netdev->vlan_features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h index 789957d43a13..eb3387398c6f 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe.h @@ -140,11 +140,25 @@ #define XGBE_TX_MAX_BUF_SIZE (0x3fff & ~(64 - 1)) +/* Descriptors required for maximum contigous TSO/GSO packet */ +#define XGBE_TX_MAX_SPLIT ((GSO_MAX_SIZE / XGBE_TX_MAX_BUF_SIZE) + 1) + +/* Maximum possible descriptors needed for an SKB: + * - Maximum number of SKB frags + * - Maximum descriptors for contiguous TSO/GSO packet + * - Possible context descriptor + * - Possible TSO header descriptor + */ +#define XGBE_TX_MAX_DESCS (MAX_SKB_FRAGS + XGBE_TX_MAX_SPLIT + 2) + #define XGBE_RX_MIN_BUF_SIZE (ETH_FRAME_LEN + ETH_FCS_LEN + VLAN_HLEN) #define XGBE_RX_BUF_ALIGN 64 +#define XGBE_SKB_ALLOC_SIZE 256 +#define XGBE_SPH_HDSMS_SIZE 2 /* Keep in sync with SKB_ALLOC_SIZE */ #define XGBE_MAX_DMA_CHANNELS 16 #define XGBE_MAX_QUEUES 16 +#define XGBE_DMA_STOP_TIMEOUT 5 /* DMA cache settings - Outer sharable, write-back, write-allocate */ #define XGBE_DMA_OS_AXDOMAIN 0x2 @@ -171,6 +185,7 @@ /* Device-tree clock names */ #define XGBE_DMA_CLOCK "dma_clk" #define XGBE_PTP_CLOCK "ptp_clk" +#define XGBE_DMA_IRQS "amd,per-channel-interrupt" /* Timestamp support - values based on 50MHz PTP clock * 50MHz => 20 nsec @@ -212,9 +227,17 @@ /* Maximum MAC address hash table size (256 bits = 8 bytes) */ #define XGBE_MAC_HASH_TABLE_SIZE 8 +/* Receive Side Scaling */ +#define XGBE_RSS_HASH_KEY_SIZE 40 +#define XGBE_RSS_MAX_TABLE_SIZE 256 +#define XGBE_RSS_LOOKUP_TABLE_TYPE 0 +#define XGBE_RSS_HASH_KEY_TYPE 1 + struct xgbe_prv_data; struct xgbe_packet_data { + struct sk_buff *skb; + unsigned int attributes; unsigned int errors; @@ -230,14 +253,53 @@ struct xgbe_packet_data { unsigned short vlan_ctag; u64 rx_tstamp; + + u32 rss_hash; + enum pkt_hash_types rss_hash_type; + + unsigned int tx_packets; + unsigned int tx_bytes; }; /* Common Rx and Tx descriptor mapping */ struct xgbe_ring_desc { - unsigned int desc0; - unsigned int desc1; - unsigned int desc2; - unsigned int desc3; + __le32 desc0; + __le32 desc1; + __le32 desc2; + __le32 desc3; +}; + +/* Page allocation related values */ +struct xgbe_page_alloc { + struct page *pages; + unsigned int pages_len; + unsigned int pages_offset; + + dma_addr_t pages_dma; +}; + +/* Ring entry buffer data */ +struct xgbe_buffer_data { + struct xgbe_page_alloc pa; + struct xgbe_page_alloc pa_unmap; + + dma_addr_t dma; + unsigned int dma_len; +}; + +/* Tx-related ring data */ +struct xgbe_tx_ring_data { + unsigned int packets; /* BQL packet count */ + unsigned int bytes; /* BQL byte count */ +}; + +/* Rx-related ring data */ +struct xgbe_rx_ring_data { + struct xgbe_buffer_data hdr; /* Header locations */ + struct xgbe_buffer_data buf; /* Payload locations */ + + unsigned short hdr_len; /* Length of received header */ + unsigned short len; /* Length of received packet */ }; /* Structure used to hold information related to the descriptor @@ -251,9 +313,9 @@ struct xgbe_ring_data { struct sk_buff *skb; /* Virtual address of SKB */ dma_addr_t skb_dma; /* DMA address of SKB data */ unsigned int skb_dma_len; /* Length of SKB DMA area */ - unsigned int tso_header; /* TSO header indicator */ - unsigned short len; /* Length of received Rx packet */ + struct xgbe_tx_ring_data tx; /* Tx-related data */ + struct xgbe_rx_ring_data rx; /* Rx-related data */ unsigned int interrupt; /* Interrupt indicator */ @@ -291,6 +353,10 @@ struct xgbe_ring { */ struct xgbe_ring_data *rdata; + /* Page allocation for RX buffers */ + struct xgbe_page_alloc rx_hdr_pa; + struct xgbe_page_alloc rx_buf_pa; + /* Ring index values * cur - Tx: index of descriptor to be used for current transfer * Rx: index of descriptor to check for packet availability @@ -307,6 +373,7 @@ struct xgbe_ring { union { struct { unsigned int queue_stopped; + unsigned int xmit_more; unsigned short cur_mss; unsigned short cur_vlan_ctag; } tx; @@ -331,6 +398,12 @@ struct xgbe_channel { unsigned int queue_index; void __iomem *dma_regs; + /* Per channel interrupt irq number */ + int dma_irq; + + /* Netdev related settings */ + struct napi_struct napi; + unsigned int saved_ier; unsigned int tx_timer_active; @@ -456,7 +529,7 @@ struct xgbe_hw_if { int (*enable_int)(struct xgbe_channel *, enum xgbe_int); int (*disable_int)(struct xgbe_channel *, enum xgbe_int); - void (*pre_xmit)(struct xgbe_channel *); + void (*dev_xmit)(struct xgbe_channel *); int (*dev_read)(struct xgbe_channel *); void (*tx_desc_init)(struct xgbe_channel *); void (*rx_desc_init)(struct xgbe_channel *); @@ -464,6 +537,7 @@ struct xgbe_hw_if { void (*tx_desc_reset)(struct xgbe_ring_data *); int (*is_last_desc)(struct xgbe_ring_desc *); int (*is_context_desc)(struct xgbe_ring_desc *); + void (*tx_start_xmit)(struct xgbe_channel *, struct xgbe_ring *); /* For FLOW ctrl */ int (*config_tx_flow_control)(struct xgbe_prv_data *); @@ -509,14 +583,20 @@ struct xgbe_hw_if { /* For Data Center Bridging config */ void (*config_dcb_tc)(struct xgbe_prv_data *); void (*config_dcb_pfc)(struct xgbe_prv_data *); + + /* For Receive Side Scaling */ + int (*enable_rss)(struct xgbe_prv_data *); + int (*disable_rss)(struct xgbe_prv_data *); + int (*set_rss_hash_key)(struct xgbe_prv_data *, const u8 *); + int (*set_rss_lookup_table)(struct xgbe_prv_data *, const u32 *); }; struct xgbe_desc_if { int (*alloc_ring_resources)(struct xgbe_prv_data *); void (*free_ring_resources)(struct xgbe_prv_data *); int (*map_tx_skb)(struct xgbe_channel *, struct sk_buff *); - void (*realloc_skb)(struct xgbe_channel *); - void (*unmap_skb)(struct xgbe_prv_data *, struct xgbe_ring_data *); + void (*realloc_rx_buffer)(struct xgbe_channel *); + void (*unmap_rdata)(struct xgbe_prv_data *, struct xgbe_ring_data *); void (*wrapper_tx_desc_init)(struct xgbe_prv_data *); void (*wrapper_rx_desc_init)(struct xgbe_prv_data *); }; @@ -581,7 +661,11 @@ struct xgbe_prv_data { /* XPCS indirect addressing mutex */ struct mutex xpcs_mutex; - int irq_number; + /* RSS addressing mutex */ + struct mutex rss_mutex; + + int dev_irq; + unsigned int per_channel_irq; struct xgbe_hw_if hw_if; struct xgbe_desc_if desc_if; @@ -624,7 +708,7 @@ struct xgbe_prv_data { unsigned int rx_riwt; unsigned int rx_frames; - /* Current MTU */ + /* Current Rx buffer size */ unsigned int rx_buf_size; /* Flow control settings */ @@ -632,6 +716,11 @@ struct xgbe_prv_data { unsigned int tx_pause; unsigned int rx_pause; + /* Receive Side Scaling settings */ + u8 rss_key[XGBE_RSS_HASH_KEY_SIZE]; + u32 rss_table[XGBE_RSS_MAX_TABLE_SIZE]; + u32 rss_options; + /* MDIO settings */ struct module *phy_module; char *mii_bus_id; diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c index 123669696184..83a50280bb70 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c @@ -761,10 +761,6 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata) ndev = pdata->ndev; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "enet_csr"); - if (!res) { - dev_err(dev, "Resource enet_csr not defined\n"); - return -ENODEV; - } pdata->base_addr = devm_ioremap_resource(dev, res); if (IS_ERR(pdata->base_addr)) { dev_err(dev, "Unable to retrieve ENET Port CSR region\n"); @@ -772,10 +768,6 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata) } res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ring_csr"); - if (!res) { - dev_err(dev, "Resource ring_csr not defined\n"); - return -ENODEV; - } pdata->ring_csr_addr = devm_ioremap_resource(dev, res); if (IS_ERR(pdata->ring_csr_addr)) { dev_err(dev, "Unable to retrieve ENET Ring CSR region\n"); @@ -783,10 +775,6 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata) } res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ring_cmd"); - if (!res) { - dev_err(dev, "Resource ring_cmd not defined\n"); - return -ENODEV; - } pdata->ring_cmd_addr = devm_ioremap_resource(dev, res); if (IS_ERR(pdata->ring_cmd_addr)) { dev_err(dev, "Unable to retrieve ENET Ring command region\n"); diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c index 531bb7c57531..c1d255972dae 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.c +++ b/drivers/net/ethernet/broadcom/bcmsysport.c @@ -274,6 +274,9 @@ static const struct bcm_sysport_stats bcm_sysport_gstrings_stats[] = { /* RBUF misc statistics */ STAT_RBUF("rbuf_ovflow_cnt", mib.rbuf_ovflow_cnt, RBUF_OVFL_DISC_CNTR), STAT_RBUF("rbuf_err_cnt", mib.rbuf_err_cnt, RBUF_ERR_PKT_CNTR), + STAT_MIB_RX("alloc_rx_buff_failed", mib.alloc_rx_buff_failed), + STAT_MIB_RX("rx_dma_failed", mib.rx_dma_failed), + STAT_MIB_TX("tx_dma_failed", mib.tx_dma_failed), }; #define BCM_SYSPORT_STATS_LEN ARRAY_SIZE(bcm_sysport_gstrings_stats) @@ -477,6 +480,7 @@ static int bcm_sysport_rx_refill(struct bcm_sysport_priv *priv, RX_BUF_LENGTH, DMA_FROM_DEVICE); ret = dma_mapping_error(kdev, mapping); if (ret) { + priv->mib.rx_dma_failed++; bcm_sysport_free_cb(cb); netif_err(priv, rx_err, ndev, "DMA mapping failure\n"); return ret; @@ -526,6 +530,7 @@ static unsigned int bcm_sysport_desc_rx(struct bcm_sysport_priv *priv, unsigned int p_index; u16 len, status; struct bcm_rsb *rsb; + int ret; /* Determine how much we should process since last call */ p_index = rdma_readl(priv, RDMA_PROD_INDEX); @@ -620,7 +625,9 @@ static unsigned int bcm_sysport_desc_rx(struct bcm_sysport_priv *priv, napi_gro_receive(&priv->napi, skb); refill: - bcm_sysport_rx_refill(priv, cb); + ret = bcm_sysport_rx_refill(priv, cb); + if (ret) + priv->mib.alloc_rx_buff_failed++; } return processed; @@ -731,9 +738,11 @@ static int bcm_sysport_tx_poll(struct napi_struct *napi, int budget) napi_complete(napi); /* re-enable TX interrupt */ intrl2_1_mask_clear(ring->priv, BIT(ring->index)); + + return 0; } - return 0; + return budget; } static void bcm_sysport_tx_reclaim_all(struct bcm_sysport_priv *priv) @@ -971,6 +980,7 @@ static netdev_tx_t bcm_sysport_xmit(struct sk_buff *skb, mapping = dma_map_single(kdev, skb->data, skb_len, DMA_TO_DEVICE); if (dma_mapping_error(kdev, mapping)) { + priv->mib.tx_dma_failed++; netif_err(priv, tx_err, dev, "DMA map failed at %p (len=%d)\n", skb->data, skb_len); ret = NETDEV_TX_OK; diff --git a/drivers/net/ethernet/broadcom/bcmsysport.h b/drivers/net/ethernet/broadcom/bcmsysport.h index b08dab828101..fc19417d82a5 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.h +++ b/drivers/net/ethernet/broadcom/bcmsysport.h @@ -557,6 +557,9 @@ struct bcm_sysport_mib { u32 rxchk_other_pkt_disc; u32 rbuf_ovflow_cnt; u32 rbuf_err_cnt; + u32 alloc_rx_buff_failed; + u32 rx_dma_failed; + u32 tx_dma_failed; }; /* HW maintains a large list of counters */ diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 40beef5bca88..b4d71fd909ee 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -1139,7 +1139,7 @@ static irqreturn_t bnx2x_msix_fp_int(int irq, void *fp_cookie) prefetch(fp->txdata_ptr[cos]->tx_cons_sb); prefetch(&fp->sb_running_index[SM_RX_ID]); - napi_schedule(&bnx2x_fp(bp, fp->index, napi)); + napi_schedule_irqoff(&bnx2x_fp(bp, fp->index, napi)); return IRQ_HANDLED; } @@ -2099,7 +2099,7 @@ int bnx2x_rss(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj, if (config_hash) { /* RSS keys */ - prandom_bytes(params.rss_key, T_ETH_RSS_KEY * 4); + netdev_rss_key_fill(params.rss_key, T_ETH_RSS_KEY * 4); __set_bit(BNX2X_RSS_SET_SRCH, ¶ms.rss_flags); } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 74fbf9ea7bd8..c4bd025c74c9 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -1931,7 +1931,7 @@ irqreturn_t bnx2x_interrupt(int irq, void *dev_instance) for_each_cos_in_tx_queue(fp, cos) prefetch(fp->txdata_ptr[cos]->tx_cons_sb); prefetch(&fp->sb_running_index[SM_RX_ID]); - napi_schedule(&bnx2x_fp(bp, fp->index, napi)); + napi_schedule_irqoff(&bnx2x_fp(bp, fp->index, napi)); status &= ~mask; } } diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index da1a2500c91c..f2fadb053d52 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -613,6 +613,9 @@ static const struct bcmgenet_stats bcmgenet_gstrings_stats[] = { UMAC_RBUF_OVFL_CNT), STAT_GENET_MISC("rbuf_err_cnt", mib.rbuf_err_cnt, UMAC_RBUF_ERR_CNT), STAT_GENET_MISC("mdf_err_cnt", mib.mdf_err_cnt, UMAC_MDF_ERR_CNT), + STAT_GENET_MIB_RX("alloc_rx_buff_failed", mib.alloc_rx_buff_failed), + STAT_GENET_MIB_RX("rx_dma_failed", mib.rx_dma_failed), + STAT_GENET_MIB_TX("tx_dma_failed", mib.tx_dma_failed), }; #define BCMGENET_STATS_LEN ARRAY_SIZE(bcmgenet_gstrings_stats) @@ -711,6 +714,98 @@ static void bcmgenet_get_ethtool_stats(struct net_device *dev, } } +static void bcmgenet_eee_enable_set(struct net_device *dev, bool enable) +{ + struct bcmgenet_priv *priv = netdev_priv(dev); + u32 off = priv->hw_params->tbuf_offset + TBUF_ENERGY_CTRL; + u32 reg; + + if (enable && !priv->clk_eee_enabled) { + clk_prepare_enable(priv->clk_eee); + priv->clk_eee_enabled = true; + } + + reg = bcmgenet_umac_readl(priv, UMAC_EEE_CTRL); + if (enable) + reg |= EEE_EN; + else + reg &= ~EEE_EN; + bcmgenet_umac_writel(priv, reg, UMAC_EEE_CTRL); + + /* Enable EEE and switch to a 27Mhz clock automatically */ + reg = __raw_readl(priv->base + off); + if (enable) + reg |= TBUF_EEE_EN | TBUF_PM_EN; + else + reg &= ~(TBUF_EEE_EN | TBUF_PM_EN); + __raw_writel(reg, priv->base + off); + + /* Do the same for thing for RBUF */ + reg = bcmgenet_rbuf_readl(priv, RBUF_ENERGY_CTRL); + if (enable) + reg |= RBUF_EEE_EN | RBUF_PM_EN; + else + reg &= ~(RBUF_EEE_EN | RBUF_PM_EN); + bcmgenet_rbuf_writel(priv, reg, RBUF_ENERGY_CTRL); + + if (!enable && priv->clk_eee_enabled) { + clk_disable_unprepare(priv->clk_eee); + priv->clk_eee_enabled = false; + } + + priv->eee.eee_enabled = enable; + priv->eee.eee_active = enable; +} + +static int bcmgenet_get_eee(struct net_device *dev, struct ethtool_eee *e) +{ + struct bcmgenet_priv *priv = netdev_priv(dev); + struct ethtool_eee *p = &priv->eee; + + if (GENET_IS_V1(priv)) + return -EOPNOTSUPP; + + e->eee_enabled = p->eee_enabled; + e->eee_active = p->eee_active; + e->tx_lpi_timer = bcmgenet_umac_readl(priv, UMAC_EEE_LPI_TIMER); + + return phy_ethtool_get_eee(priv->phydev, e); +} + +static int bcmgenet_set_eee(struct net_device *dev, struct ethtool_eee *e) +{ + struct bcmgenet_priv *priv = netdev_priv(dev); + struct ethtool_eee *p = &priv->eee; + int ret = 0; + + if (GENET_IS_V1(priv)) + return -EOPNOTSUPP; + + p->eee_enabled = e->eee_enabled; + + if (!p->eee_enabled) { + bcmgenet_eee_enable_set(dev, false); + } else { + ret = phy_init_eee(priv->phydev, 0); + if (ret) { + netif_err(priv, hw, dev, "EEE initialization failed\n"); + return ret; + } + + bcmgenet_umac_writel(priv, e->tx_lpi_timer, UMAC_EEE_LPI_TIMER); + bcmgenet_eee_enable_set(dev, true); + } + + return phy_ethtool_set_eee(priv->phydev, e); +} + +static int bcmgenet_nway_reset(struct net_device *dev) +{ + struct bcmgenet_priv *priv = netdev_priv(dev); + + return genphy_restart_aneg(priv->phydev); +} + /* standard ethtool support functions. */ static struct ethtool_ops bcmgenet_ethtool_ops = { .get_strings = bcmgenet_get_strings, @@ -724,6 +819,9 @@ static struct ethtool_ops bcmgenet_ethtool_ops = { .set_msglevel = bcmgenet_set_msglevel, .get_wol = bcmgenet_get_wol, .set_wol = bcmgenet_set_wol, + .get_eee = bcmgenet_get_eee, + .set_eee = bcmgenet_set_eee, + .nway_reset = bcmgenet_nway_reset, }; /* Power down the unimac, based on mode. */ @@ -989,6 +1087,7 @@ static int bcmgenet_xmit_single(struct net_device *dev, mapping = dma_map_single(kdev, skb->data, skb_len, DMA_TO_DEVICE); ret = dma_mapping_error(kdev, mapping); if (ret) { + priv->mib.tx_dma_failed++; netif_err(priv, tx_err, dev, "Tx DMA map failed\n"); dev_kfree_skb(skb); return ret; @@ -1035,6 +1134,7 @@ static int bcmgenet_xmit_frag(struct net_device *dev, skb_frag_size(frag), DMA_TO_DEVICE); ret = dma_mapping_error(kdev, mapping); if (ret) { + priv->mib.tx_dma_failed++; netif_err(priv, tx_err, dev, "%s: Tx DMA map failed\n", __func__); return ret; @@ -1231,6 +1331,7 @@ static int bcmgenet_rx_refill(struct bcmgenet_priv *priv, struct enet_cb *cb) priv->rx_buf_len, DMA_FROM_DEVICE); ret = dma_mapping_error(kdev, mapping); if (ret) { + priv->mib.rx_dma_failed++; bcmgenet_free_cb(cb); netif_err(priv, rx_err, priv->dev, "%s DMA map failed\n", __func__); @@ -1397,8 +1498,10 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_priv *priv, /* refill RX path on the current control block */ refill: err = bcmgenet_rx_refill(priv, cb); - if (err) + if (err) { + priv->mib.alloc_rx_buff_failed++; netif_err(priv, rx_err, dev, "Rx refill failed\n"); + } rxpktprocessed++; priv->rx_read_ptr++; @@ -2577,6 +2680,12 @@ static int bcmgenet_probe(struct platform_device *pdev) if (IS_ERR(priv->clk_wol)) dev_warn(&priv->pdev->dev, "failed to get enet-wol clock\n"); + priv->clk_eee = devm_clk_get(&priv->pdev->dev, "enet-eee"); + if (IS_ERR(priv->clk_eee)) { + dev_warn(&priv->pdev->dev, "failed to get enet-eee clock\n"); + priv->clk_eee = NULL; + } + err = reset_umac(priv); if (err) goto err_clk_disable; @@ -2727,6 +2836,9 @@ static int bcmgenet_resume(struct device *d) phy_resume(priv->phydev); + if (priv->eee.eee_enabled) + bcmgenet_eee_enable_set(dev, true); + bcmgenet_netif_start(dev); return 0; diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h index 31b2da5f9b82..b36ddec0cc0a 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h @@ -143,6 +143,9 @@ struct bcmgenet_mib_counters { u32 rbuf_ovflow_cnt; u32 rbuf_err_cnt; u32 mdf_err_cnt; + u32 alloc_rx_buff_failed; + u32 rx_dma_failed; + u32 tx_dma_failed; }; #define UMAC_HD_BKP_CTRL 0x004 @@ -182,6 +185,21 @@ struct bcmgenet_mib_counters { #define UMAC_MAC1 0x010 #define UMAC_MAX_FRAME_LEN 0x014 +#define UMAC_EEE_CTRL 0x064 +#define EN_LPI_RX_PAUSE (1 << 0) +#define EN_LPI_TX_PFC (1 << 1) +#define EN_LPI_TX_PAUSE (1 << 2) +#define EEE_EN (1 << 3) +#define RX_FIFO_CHECK (1 << 4) +#define EEE_TX_CLK_DIS (1 << 5) +#define DIS_EEE_10M (1 << 6) +#define LP_IDLE_PREDICTION_MODE (1 << 7) + +#define UMAC_EEE_LPI_TIMER 0x068 +#define UMAC_EEE_WAKE_TIMER 0x06C +#define UMAC_EEE_REF_COUNT 0x070 +#define EEE_REFERENCE_COUNT_MASK 0xffff + #define UMAC_TX_FLUSH 0x334 #define UMAC_MIB_START 0x400 @@ -229,6 +247,10 @@ struct bcmgenet_mib_counters { #define RBUF_RXCHK_EN (1 << 0) #define RBUF_SKIP_FCS (1 << 4) +#define RBUF_ENERGY_CTRL 0x9c +#define RBUF_EEE_EN (1 << 0) +#define RBUF_PM_EN (1 << 1) + #define RBUF_TBUF_SIZE_CTRL 0xb4 #define RBUF_HFB_CTRL_V1 0x38 @@ -244,6 +266,9 @@ struct bcmgenet_mib_counters { #define TBUF_CTRL 0x00 #define TBUF_BP_MC 0x0C +#define TBUF_ENERGY_CTRL 0x14 +#define TBUF_EEE_EN (1 << 0) +#define TBUF_PM_EN (1 << 1) #define TBUF_CTRL_V1 0x80 #define TBUF_BP_MC_V1 0xA0 @@ -548,6 +573,8 @@ struct bcmgenet_priv { struct device_node *phy_dn; struct mii_bus *mii_bus; u16 gphy_rev; + struct clk *clk_eee; + bool clk_eee_enabled; /* PHY device variables */ int old_link; @@ -584,6 +611,8 @@ struct bcmgenet_priv { u32 wolopts; struct bcmgenet_mib_counters mib; + + struct ethtool_eee eee; }; #define GENET_IO_MACRO(name, offset) \ diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 77f8f836cbbe..43fd1b72c1ea 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -10541,19 +10541,14 @@ static int tg3_reset_hw(struct tg3 *tp, bool reset_phy) udelay(100); if (tg3_flag(tp, ENABLE_RSS)) { + u32 rss_key[10]; + tg3_rss_write_indir_tbl(tp); - /* Setup the "secret" hash key. */ - tw32(MAC_RSS_HASH_KEY_0, 0x5f865437); - tw32(MAC_RSS_HASH_KEY_1, 0xe4ac62cc); - tw32(MAC_RSS_HASH_KEY_2, 0x50103a45); - tw32(MAC_RSS_HASH_KEY_3, 0x36621985); - tw32(MAC_RSS_HASH_KEY_4, 0xbf14c0e8); - tw32(MAC_RSS_HASH_KEY_5, 0x1bc27a1e); - tw32(MAC_RSS_HASH_KEY_6, 0x84f4b556); - tw32(MAC_RSS_HASH_KEY_7, 0x094ea6fe); - tw32(MAC_RSS_HASH_KEY_8, 0x7dda01e7); - tw32(MAC_RSS_HASH_KEY_9, 0xc04d7481); + netdev_rss_key_fill(rss_key, 10 * sizeof(u32)); + + for (i = 0; i < 10 ; i++) + tw32(MAC_RSS_HASH_KEY_0 + i*4, rss_key[i]); } tp->rx_mode = RX_MODE_ENABLE; diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c index c3861de9dc81..323721838cf9 100644 --- a/drivers/net/ethernet/brocade/bna/bnad.c +++ b/drivers/net/ethernet/brocade/bna/bnad.c @@ -2054,7 +2054,7 @@ bnad_init_rx_config(struct bnad *bnad, struct bna_rx_config *rx_config) BFI_ENET_RSS_IPV4_TCP); rx_config->rss_config.hash_mask = bnad->num_rxp_per_rx - 1; - get_random_bytes(rx_config->rss_config.toeplitz_hash_key, + netdev_rss_key_fill(rx_config->rss_config.toeplitz_hash_key, sizeof(rx_config->rss_config.toeplitz_hash_key)); } else { rx_config->rss_status = BNA_STATUS_T_DISABLED; diff --git a/drivers/net/ethernet/chelsio/cxgb4/Makefile b/drivers/net/ethernet/chelsio/cxgb4/Makefile index 1df65c915b99..b85280775997 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/Makefile +++ b/drivers/net/ethernet/chelsio/cxgb4/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_CHELSIO_T4) += cxgb4.o cxgb4-objs := cxgb4_main.o l2t.o t4_hw.o sge.o cxgb4-$(CONFIG_CHELSIO_T4_DCB) += cxgb4_dcb.o +cxgb4-$(CONFIG_DEBUG_FS) += cxgb4_debugfs.o diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index 3c481b260745..e8b09bbdc226 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h @@ -318,10 +318,10 @@ struct adapter_params { #include "t4fw_api.h" #define FW_VERSION(chip) ( \ - FW_HDR_FW_VER_MAJOR_GET(chip##FW_VERSION_MAJOR) | \ - FW_HDR_FW_VER_MINOR_GET(chip##FW_VERSION_MINOR) | \ - FW_HDR_FW_VER_MICRO_GET(chip##FW_VERSION_MICRO) | \ - FW_HDR_FW_VER_BUILD_GET(chip##FW_VERSION_BUILD)) + FW_HDR_FW_VER_MAJOR_G(chip##FW_VERSION_MAJOR) | \ + FW_HDR_FW_VER_MINOR_G(chip##FW_VERSION_MINOR) | \ + FW_HDR_FW_VER_MICRO_G(chip##FW_VERSION_MICRO) | \ + FW_HDR_FW_VER_BUILD_G(chip##FW_VERSION_BUILD)) #define FW_INTFVER(chip, intf) (FW_HDR_INTFVER_##intf) struct fw_info { @@ -354,7 +354,7 @@ struct link_config { unsigned char link_ok; /* link up? */ }; -#define FW_LEN16(fw_struct) FW_CMD_LEN16(sizeof(fw_struct) / 16) +#define FW_LEN16(fw_struct) FW_CMD_LEN16_V(sizeof(fw_struct) / 16) enum { MAX_ETH_QSETS = 32, /* # of Ethernet Tx/Rx queue sets */ @@ -1085,4 +1085,5 @@ void t4_db_dropped(struct adapter *adapter); int t4_fwaddrspace_write(struct adapter *adap, unsigned int mbox, u32 addr, u32 val); void t4_sge_decode_idma_state(struct adapter *adapter, int state); +void t4_free_mem(void *addr); #endif /* __CXGB4_H__ */ diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.c index 4fe33606f372..a35d1ec6950e 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.c @@ -243,7 +243,7 @@ void cxgb4_dcb_handle_fw_update(struct adapter *adap, const struct fw_port_cmd *pcmd) { const union fw_port_dcb *fwdcb = &pcmd->u.dcb; - int port = FW_PORT_CMD_PORTID_GET(be32_to_cpu(pcmd->op_to_portid)); + int port = FW_PORT_CMD_PORTID_G(be32_to_cpu(pcmd->op_to_portid)); struct net_device *dev = adap->port[port]; struct port_info *pi = netdev_priv(dev); struct port_dcb_info *dcb = &pi->dcb; @@ -256,12 +256,12 @@ void cxgb4_dcb_handle_fw_update(struct adapter *adap, if (dcb_type == FW_PORT_DCB_TYPE_CONTROL) { enum cxgb4_dcb_state_input input = ((pcmd->u.dcb.control.all_syncd_pkd & - FW_PORT_CMD_ALL_SYNCD) + FW_PORT_CMD_ALL_SYNCD_F) ? CXGB4_DCB_STATE_FW_ALLSYNCED : CXGB4_DCB_STATE_FW_INCOMPLETE); if (dcb->dcb_version != FW_PORT_DCB_VER_UNKNOWN) { - dcb_running_version = FW_PORT_CMD_DCB_VERSION_GET( + dcb_running_version = FW_PORT_CMD_DCB_VERSION_G( be16_to_cpu( pcmd->u.dcb.control.dcb_version_to_app_state)); if (dcb_running_version == FW_PORT_DCB_VER_CEE1D01 || @@ -519,7 +519,7 @@ static void cxgb4_setpgtccfg_tx(struct net_device *dev, int tc, INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id); if (pi->dcb.state == CXGB4_DCB_STATE_HOST) - pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY); + pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY_F); err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd); if (err != FW_PORT_DCB_CFG_SUCCESS) @@ -583,7 +583,7 @@ static void cxgb4_setpgbwgcfg_tx(struct net_device *dev, int pgid, INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id); if (pi->dcb.state == CXGB4_DCB_STATE_HOST) - pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY); + pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY_F); err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd); @@ -623,7 +623,7 @@ static void cxgb4_setpfccfg(struct net_device *dev, int priority, u8 pfccfg) INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id); if (pi->dcb.state == CXGB4_DCB_STATE_HOST) - pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY); + pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY_F); pcmd.u.dcb.pfc.type = FW_PORT_DCB_TYPE_PFC; pcmd.u.dcb.pfc.pfcen = pi->dcb.pfcen; @@ -842,7 +842,7 @@ static int __cxgb4_setapp(struct net_device *dev, u8 app_idtype, u16 app_id, /* write out new app table entry */ INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id); if (pi->dcb.state == CXGB4_DCB_STATE_HOST) - pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY); + pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY_F); pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID; pcmd.u.dcb.app_priority.protocolid = cpu_to_be16(app_id); diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.h index 2a6aa88984f4..31ce425616c9 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.h @@ -42,12 +42,12 @@ do { \ memset(&(__pcmd), 0, sizeof(__pcmd)); \ (__pcmd).op_to_portid = \ - cpu_to_be32(FW_CMD_OP(FW_PORT_CMD) | \ - FW_CMD_REQUEST | \ - FW_CMD_##__op | \ - FW_PORT_CMD_PORTID(__port)); \ + cpu_to_be32(FW_CMD_OP_V(FW_PORT_CMD) | \ + FW_CMD_REQUEST_F | \ + FW_CMD_##__op##_F | \ + FW_PORT_CMD_PORTID_V(__port)); \ (__pcmd).action_to_len16 = \ - cpu_to_be32(FW_PORT_CMD_ACTION(__action) | \ + cpu_to_be32(FW_PORT_CMD_ACTION_V(__action) | \ FW_LEN16(pcmd)); \ } while (0) diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c new file mode 100644 index 000000000000..c98a350d857e --- /dev/null +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c @@ -0,0 +1,158 @@ +/* + * This file is part of the Chelsio T4 Ethernet driver for Linux. + * + * Copyright (c) 2003-2014 Chelsio Communications, Inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include <linux/seq_file.h> +#include <linux/debugfs.h> +#include <linux/string_helpers.h> +#include <linux/sort.h> + +#include "cxgb4.h" +#include "t4_regs.h" +#include "t4fw_api.h" +#include "cxgb4_debugfs.h" +#include "l2t.h" + +static ssize_t mem_read(struct file *file, char __user *buf, size_t count, + loff_t *ppos) +{ + loff_t pos = *ppos; + loff_t avail = file_inode(file)->i_size; + unsigned int mem = (uintptr_t)file->private_data & 3; + struct adapter *adap = file->private_data - mem; + __be32 *data; + int ret; + + if (pos < 0) + return -EINVAL; + if (pos >= avail) + return 0; + if (count > avail - pos) + count = avail - pos; + + data = t4_alloc_mem(count); + if (!data) + return -ENOMEM; + + spin_lock(&adap->win0_lock); + ret = t4_memory_rw(adap, 0, mem, pos, count, data, T4_MEMORY_READ); + spin_unlock(&adap->win0_lock); + if (ret) { + t4_free_mem(data); + return ret; + } + ret = copy_to_user(buf, data, count); + + t4_free_mem(data); + if (ret) + return -EFAULT; + + *ppos = pos + count; + return count; +} + +static const struct file_operations mem_debugfs_fops = { + .owner = THIS_MODULE, + .open = simple_open, + .read = mem_read, + .llseek = default_llseek, +}; + +static void add_debugfs_mem(struct adapter *adap, const char *name, + unsigned int idx, unsigned int size_mb) +{ + struct dentry *de; + + de = debugfs_create_file(name, S_IRUSR, adap->debugfs_root, + (void *)adap + idx, &mem_debugfs_fops); + if (de && de->d_inode) + de->d_inode->i_size = size_mb << 20; +} + +/* Add an array of Debug FS files. + */ +void add_debugfs_files(struct adapter *adap, + struct t4_debugfs_entry *files, + unsigned int nfiles) +{ + int i; + + /* debugfs support is best effort */ + for (i = 0; i < nfiles; i++) + debugfs_create_file(files[i].name, files[i].mode, + adap->debugfs_root, + (void *)adap + files[i].data, + files[i].ops); +} + +int t4_setup_debugfs(struct adapter *adap) +{ + int i; + u32 size; + + static struct t4_debugfs_entry t4_debugfs_files[] = { + { "l2t", &t4_l2t_fops, S_IRUSR, 0}, + }; + + add_debugfs_files(adap, + t4_debugfs_files, + ARRAY_SIZE(t4_debugfs_files)); + + i = t4_read_reg(adap, MA_TARGET_MEM_ENABLE_A); + if (i & EDRAM0_ENABLE_F) { + size = t4_read_reg(adap, MA_EDRAM0_BAR_A); + add_debugfs_mem(adap, "edc0", MEM_EDC0, EDRAM0_SIZE_G(size)); + } + if (i & EDRAM1_ENABLE_F) { + size = t4_read_reg(adap, MA_EDRAM1_BAR_A); + add_debugfs_mem(adap, "edc1", MEM_EDC1, EDRAM1_SIZE_G(size)); + } + if (is_t4(adap->params.chip)) { + size = t4_read_reg(adap, MA_EXT_MEMORY_BAR_A); + if (i & EXT_MEM_ENABLE_F) + add_debugfs_mem(adap, "mc", MEM_MC, + EXT_MEM_SIZE_G(size)); + } else { + if (i & EXT_MEM0_ENABLE_F) { + size = t4_read_reg(adap, MA_EXT_MEMORY0_BAR_A); + add_debugfs_mem(adap, "mc0", MEM_MC0, + EXT_MEM0_SIZE_G(size)); + } + if (i & EXT_MEM1_ENABLE_F) { + size = t4_read_reg(adap, MA_EXT_MEMORY1_BAR_A); + add_debugfs_mem(adap, "mc1", MEM_MC1, + EXT_MEM1_SIZE_G(size)); + } + } + return 0; +} diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.h new file mode 100644 index 000000000000..a3d8867efd3d --- /dev/null +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.h @@ -0,0 +1,52 @@ +/* + * This file is part of the Chelsio T4 Ethernet driver for Linux. + * + * Copyright (c) 2003-2014 Chelsio Communications, Inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __CXGB4_DEBUGFS_H +#define __CXGB4_DEBUGFS_H + +#include <linux/export.h> + +struct t4_debugfs_entry { + const char *name; + const struct file_operations *ops; + mode_t mode; + unsigned char data; +}; + +int t4_setup_debugfs(struct adapter *adap); +void add_debugfs_files(struct adapter *adap, + struct t4_debugfs_entry *files, + unsigned int nfiles); + +#endif diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index 8520d5529df8..3aea82bb9039 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -61,6 +61,7 @@ #include <net/neighbour.h> #include <net/netevent.h> #include <net/addrconf.h> +#include <net/bonding.h> #include <asm/uaccess.h> #include "cxgb4.h" @@ -68,10 +69,9 @@ #include "t4_msg.h" #include "t4fw_api.h" #include "cxgb4_dcb.h" +#include "cxgb4_debugfs.h" #include "l2t.h" -#include <../drivers/net/bonding/bonding.h> - #ifdef DRV_VERSION #undef DRV_VERSION #endif @@ -141,7 +141,7 @@ static unsigned int pfvfres_pmask(struct adapter *adapter, * Give PF's access to all of the ports. */ if (vf == 0) - return FW_PFVF_CMD_PMASK_MASK; + return FW_PFVF_CMD_PMASK_M; /* * For VFs, we'll assign them access to the ports based purely on the @@ -210,114 +210,25 @@ struct filter_entry { NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP |\ NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR) -#define CH_DEVICE(devid, data) { PCI_VDEVICE(CHELSIO, devid), (data) } - -static const struct pci_device_id cxgb4_pci_tbl[] = { - CH_DEVICE(0xa000, 0), /* PE10K */ - CH_DEVICE(0x4001, -1), - CH_DEVICE(0x4002, -1), - CH_DEVICE(0x4003, -1), - CH_DEVICE(0x4004, -1), - CH_DEVICE(0x4005, -1), - CH_DEVICE(0x4006, -1), - CH_DEVICE(0x4007, -1), - CH_DEVICE(0x4008, -1), - CH_DEVICE(0x4009, -1), - CH_DEVICE(0x400a, -1), - CH_DEVICE(0x400d, -1), - CH_DEVICE(0x400e, -1), - CH_DEVICE(0x4080, -1), - CH_DEVICE(0x4081, -1), - CH_DEVICE(0x4082, -1), - CH_DEVICE(0x4083, -1), - CH_DEVICE(0x4084, -1), - CH_DEVICE(0x4085, -1), - CH_DEVICE(0x4086, -1), - CH_DEVICE(0x4087, -1), - CH_DEVICE(0x4088, -1), - CH_DEVICE(0x4401, 4), - CH_DEVICE(0x4402, 4), - CH_DEVICE(0x4403, 4), - CH_DEVICE(0x4404, 4), - CH_DEVICE(0x4405, 4), - CH_DEVICE(0x4406, 4), - CH_DEVICE(0x4407, 4), - CH_DEVICE(0x4408, 4), - CH_DEVICE(0x4409, 4), - CH_DEVICE(0x440a, 4), - CH_DEVICE(0x440d, 4), - CH_DEVICE(0x440e, 4), - CH_DEVICE(0x4480, 4), - CH_DEVICE(0x4481, 4), - CH_DEVICE(0x4482, 4), - CH_DEVICE(0x4483, 4), - CH_DEVICE(0x4484, 4), - CH_DEVICE(0x4485, 4), - CH_DEVICE(0x4486, 4), - CH_DEVICE(0x4487, 4), - CH_DEVICE(0x4488, 4), - CH_DEVICE(0x5001, 4), - CH_DEVICE(0x5002, 4), - CH_DEVICE(0x5003, 4), - CH_DEVICE(0x5004, 4), - CH_DEVICE(0x5005, 4), - CH_DEVICE(0x5006, 4), - CH_DEVICE(0x5007, 4), - CH_DEVICE(0x5008, 4), - CH_DEVICE(0x5009, 4), - CH_DEVICE(0x500A, 4), - CH_DEVICE(0x500B, 4), - CH_DEVICE(0x500C, 4), - CH_DEVICE(0x500D, 4), - CH_DEVICE(0x500E, 4), - CH_DEVICE(0x500F, 4), - CH_DEVICE(0x5010, 4), - CH_DEVICE(0x5011, 4), - CH_DEVICE(0x5012, 4), - CH_DEVICE(0x5013, 4), - CH_DEVICE(0x5014, 4), - CH_DEVICE(0x5015, 4), - CH_DEVICE(0x5080, 4), - CH_DEVICE(0x5081, 4), - CH_DEVICE(0x5082, 4), - CH_DEVICE(0x5083, 4), - CH_DEVICE(0x5084, 4), - CH_DEVICE(0x5085, 4), - CH_DEVICE(0x5086, 4), - CH_DEVICE(0x5087, 4), - CH_DEVICE(0x5088, 4), - CH_DEVICE(0x5401, 4), - CH_DEVICE(0x5402, 4), - CH_DEVICE(0x5403, 4), - CH_DEVICE(0x5404, 4), - CH_DEVICE(0x5405, 4), - CH_DEVICE(0x5406, 4), - CH_DEVICE(0x5407, 4), - CH_DEVICE(0x5408, 4), - CH_DEVICE(0x5409, 4), - CH_DEVICE(0x540A, 4), - CH_DEVICE(0x540B, 4), - CH_DEVICE(0x540C, 4), - CH_DEVICE(0x540D, 4), - CH_DEVICE(0x540E, 4), - CH_DEVICE(0x540F, 4), - CH_DEVICE(0x5410, 4), - CH_DEVICE(0x5411, 4), - CH_DEVICE(0x5412, 4), - CH_DEVICE(0x5413, 4), - CH_DEVICE(0x5414, 4), - CH_DEVICE(0x5415, 4), - CH_DEVICE(0x5480, 4), - CH_DEVICE(0x5481, 4), - CH_DEVICE(0x5482, 4), - CH_DEVICE(0x5483, 4), - CH_DEVICE(0x5484, 4), - CH_DEVICE(0x5485, 4), - CH_DEVICE(0x5486, 4), - CH_DEVICE(0x5487, 4), - CH_DEVICE(0x5488, 4), - { 0, } -}; +/* Macros needed to support the PCI Device ID Table ... + */ +#define CH_PCI_DEVICE_ID_TABLE_DEFINE_BEGIN \ + static struct pci_device_id cxgb4_pci_tbl[] = { +#define CH_PCI_DEVICE_ID_FUNCTION 0x4 + +/* Include PCI Device IDs for both PF4 and PF0-3 so our PCI probe() routine is + * called for both. + */ +#define CH_PCI_DEVICE_ID_FUNCTION2 0x0 + +#define CH_PCI_ID_TABLE_ENTRY(devid) \ + {PCI_VDEVICE(CHELSIO, (devid)), 4} + +#define CH_PCI_DEVICE_ID_TABLE_DEFINE_END \ + { 0, } \ + } + +#include "t4_pci_id_tbl.h" #define FW4_FNAME "cxgb4/t4fw.bin" #define FW5_FNAME "cxgb4/t5fw.bin" @@ -512,9 +423,10 @@ static void dcb_tx_queue_prio_enable(struct net_device *dev, int enable) u32 name, value; int err; - name = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_DMAQ) | - FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DMAQ_EQ_DCBPRIO_ETH) | - FW_PARAMS_PARAM_YZ(txq->q.cntxt_id)); + name = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DMAQ) | + FW_PARAMS_PARAM_X_V( + FW_PARAMS_PARAM_DMAQ_EQ_DCBPRIO_ETH) | + FW_PARAMS_PARAM_YZ_V(txq->q.cntxt_id)); value = enable ? i : 0xffffffff; /* Since we can be called while atomic (from "interrupt @@ -709,7 +621,7 @@ EXPORT_SYMBOL(cxgb4_dcb_enabled); /* Handle a Data Center Bridging update message from the firmware. */ static void dcb_rpl(struct adapter *adap, const struct fw_port_cmd *pcmd) { - int port = FW_PORT_CMD_PORTID_GET(ntohl(pcmd->op_to_portid)); + int port = FW_PORT_CMD_PORTID_G(ntohl(pcmd->op_to_portid)); struct net_device *dev = adap->port[port]; int old_dcb_enabled = cxgb4_dcb_enabled(dev); int new_dcb_enabled; @@ -832,17 +744,17 @@ static int fwevtq_handler(struct sge_rspq *q, const __be64 *rsp, #ifdef CONFIG_CHELSIO_T4_DCB const struct fw_port_cmd *pcmd = (const void *)p->data; - unsigned int cmd = FW_CMD_OP_GET(ntohl(pcmd->op_to_portid)); + unsigned int cmd = FW_CMD_OP_G(ntohl(pcmd->op_to_portid)); unsigned int action = - FW_PORT_CMD_ACTION_GET(ntohl(pcmd->action_to_len16)); + FW_PORT_CMD_ACTION_G(ntohl(pcmd->action_to_len16)); if (cmd == FW_PORT_CMD && action == FW_PORT_ACTION_GET_PORT_INFO) { - int port = FW_PORT_CMD_PORTID_GET( + int port = FW_PORT_CMD_PORTID_G( be32_to_cpu(pcmd->op_to_portid)); struct net_device *dev = q->adap->port[port]; int state_input = ((pcmd->u.info.dcbxdis_pkd & - FW_PORT_CMD_DCBXDIS) + FW_PORT_CMD_DCBXDIS_F) ? CXGB4_DCB_INPUT_FW_DISABLED : CXGB4_DCB_INPUT_FW_ENABLED); @@ -1287,7 +1199,7 @@ void *t4_alloc_mem(size_t size) /* * Free memory allocated through alloc_mem(). */ -static void t4_free_mem(void *addr) +void t4_free_mem(void *addr) { if (is_vmalloc_addr(addr)) vfree(addr); @@ -1339,52 +1251,52 @@ static int set_filter_wr(struct adapter *adapter, int fidx) * filter specification structure but for now it's easiest to simply * put this fairly direct code in line ... */ - fwr->op_pkd = htonl(FW_WR_OP(FW_FILTER_WR)); - fwr->len16_pkd = htonl(FW_WR_LEN16(sizeof(*fwr)/16)); + fwr->op_pkd = htonl(FW_WR_OP_V(FW_FILTER_WR)); + fwr->len16_pkd = htonl(FW_WR_LEN16_V(sizeof(*fwr)/16)); fwr->tid_to_iq = - htonl(V_FW_FILTER_WR_TID(ftid) | - V_FW_FILTER_WR_RQTYPE(f->fs.type) | - V_FW_FILTER_WR_NOREPLY(0) | - V_FW_FILTER_WR_IQ(f->fs.iq)); + htonl(FW_FILTER_WR_TID_V(ftid) | + FW_FILTER_WR_RQTYPE_V(f->fs.type) | + FW_FILTER_WR_NOREPLY_V(0) | + FW_FILTER_WR_IQ_V(f->fs.iq)); fwr->del_filter_to_l2tix = - htonl(V_FW_FILTER_WR_RPTTID(f->fs.rpttid) | - V_FW_FILTER_WR_DROP(f->fs.action == FILTER_DROP) | - V_FW_FILTER_WR_DIRSTEER(f->fs.dirsteer) | - V_FW_FILTER_WR_MASKHASH(f->fs.maskhash) | - V_FW_FILTER_WR_DIRSTEERHASH(f->fs.dirsteerhash) | - V_FW_FILTER_WR_LPBK(f->fs.action == FILTER_SWITCH) | - V_FW_FILTER_WR_DMAC(f->fs.newdmac) | - V_FW_FILTER_WR_SMAC(f->fs.newsmac) | - V_FW_FILTER_WR_INSVLAN(f->fs.newvlan == VLAN_INSERT || + htonl(FW_FILTER_WR_RPTTID_V(f->fs.rpttid) | + FW_FILTER_WR_DROP_V(f->fs.action == FILTER_DROP) | + FW_FILTER_WR_DIRSTEER_V(f->fs.dirsteer) | + FW_FILTER_WR_MASKHASH_V(f->fs.maskhash) | + FW_FILTER_WR_DIRSTEERHASH_V(f->fs.dirsteerhash) | + FW_FILTER_WR_LPBK_V(f->fs.action == FILTER_SWITCH) | + FW_FILTER_WR_DMAC_V(f->fs.newdmac) | + FW_FILTER_WR_SMAC_V(f->fs.newsmac) | + FW_FILTER_WR_INSVLAN_V(f->fs.newvlan == VLAN_INSERT || f->fs.newvlan == VLAN_REWRITE) | - V_FW_FILTER_WR_RMVLAN(f->fs.newvlan == VLAN_REMOVE || + FW_FILTER_WR_RMVLAN_V(f->fs.newvlan == VLAN_REMOVE || f->fs.newvlan == VLAN_REWRITE) | - V_FW_FILTER_WR_HITCNTS(f->fs.hitcnts) | - V_FW_FILTER_WR_TXCHAN(f->fs.eport) | - V_FW_FILTER_WR_PRIO(f->fs.prio) | - V_FW_FILTER_WR_L2TIX(f->l2t ? f->l2t->idx : 0)); + FW_FILTER_WR_HITCNTS_V(f->fs.hitcnts) | + FW_FILTER_WR_TXCHAN_V(f->fs.eport) | + FW_FILTER_WR_PRIO_V(f->fs.prio) | + FW_FILTER_WR_L2TIX_V(f->l2t ? f->l2t->idx : 0)); fwr->ethtype = htons(f->fs.val.ethtype); fwr->ethtypem = htons(f->fs.mask.ethtype); fwr->frag_to_ovlan_vldm = - (V_FW_FILTER_WR_FRAG(f->fs.val.frag) | - V_FW_FILTER_WR_FRAGM(f->fs.mask.frag) | - V_FW_FILTER_WR_IVLAN_VLD(f->fs.val.ivlan_vld) | - V_FW_FILTER_WR_OVLAN_VLD(f->fs.val.ovlan_vld) | - V_FW_FILTER_WR_IVLAN_VLDM(f->fs.mask.ivlan_vld) | - V_FW_FILTER_WR_OVLAN_VLDM(f->fs.mask.ovlan_vld)); + (FW_FILTER_WR_FRAG_V(f->fs.val.frag) | + FW_FILTER_WR_FRAGM_V(f->fs.mask.frag) | + FW_FILTER_WR_IVLAN_VLD_V(f->fs.val.ivlan_vld) | + FW_FILTER_WR_OVLAN_VLD_V(f->fs.val.ovlan_vld) | + FW_FILTER_WR_IVLAN_VLDM_V(f->fs.mask.ivlan_vld) | + FW_FILTER_WR_OVLAN_VLDM_V(f->fs.mask.ovlan_vld)); fwr->smac_sel = 0; fwr->rx_chan_rx_rpl_iq = - htons(V_FW_FILTER_WR_RX_CHAN(0) | - V_FW_FILTER_WR_RX_RPL_IQ(adapter->sge.fw_evtq.abs_id)); + htons(FW_FILTER_WR_RX_CHAN_V(0) | + FW_FILTER_WR_RX_RPL_IQ_V(adapter->sge.fw_evtq.abs_id)); fwr->maci_to_matchtypem = - htonl(V_FW_FILTER_WR_MACI(f->fs.val.macidx) | - V_FW_FILTER_WR_MACIM(f->fs.mask.macidx) | - V_FW_FILTER_WR_FCOE(f->fs.val.fcoe) | - V_FW_FILTER_WR_FCOEM(f->fs.mask.fcoe) | - V_FW_FILTER_WR_PORT(f->fs.val.iport) | - V_FW_FILTER_WR_PORTM(f->fs.mask.iport) | - V_FW_FILTER_WR_MATCHTYPE(f->fs.val.matchtype) | - V_FW_FILTER_WR_MATCHTYPEM(f->fs.mask.matchtype)); + htonl(FW_FILTER_WR_MACI_V(f->fs.val.macidx) | + FW_FILTER_WR_MACIM_V(f->fs.mask.macidx) | + FW_FILTER_WR_FCOE_V(f->fs.val.fcoe) | + FW_FILTER_WR_FCOEM_V(f->fs.mask.fcoe) | + FW_FILTER_WR_PORT_V(f->fs.val.iport) | + FW_FILTER_WR_PORTM_V(f->fs.mask.iport) | + FW_FILTER_WR_MATCHTYPE_V(f->fs.val.matchtype) | + FW_FILTER_WR_MATCHTYPEM_V(f->fs.mask.matchtype)); fwr->ptcl = f->fs.val.proto; fwr->ptclm = f->fs.mask.proto; fwr->ttyp = f->fs.val.tos; @@ -1615,14 +1527,14 @@ static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) if (adapter->params.fw_vers) snprintf(info->fw_version, sizeof(info->fw_version), "%u.%u.%u.%u, TP %u.%u.%u.%u", - FW_HDR_FW_VER_MAJOR_GET(adapter->params.fw_vers), - FW_HDR_FW_VER_MINOR_GET(adapter->params.fw_vers), - FW_HDR_FW_VER_MICRO_GET(adapter->params.fw_vers), - FW_HDR_FW_VER_BUILD_GET(adapter->params.fw_vers), - FW_HDR_FW_VER_MAJOR_GET(adapter->params.tp_vers), - FW_HDR_FW_VER_MINOR_GET(adapter->params.tp_vers), - FW_HDR_FW_VER_MICRO_GET(adapter->params.tp_vers), - FW_HDR_FW_VER_BUILD_GET(adapter->params.tp_vers)); + FW_HDR_FW_VER_MAJOR_G(adapter->params.fw_vers), + FW_HDR_FW_VER_MINOR_G(adapter->params.fw_vers), + FW_HDR_FW_VER_MICRO_G(adapter->params.fw_vers), + FW_HDR_FW_VER_BUILD_G(adapter->params.fw_vers), + FW_HDR_FW_VER_MAJOR_G(adapter->params.tp_vers), + FW_HDR_FW_VER_MINOR_G(adapter->params.tp_vers), + FW_HDR_FW_VER_MICRO_G(adapter->params.tp_vers), + FW_HDR_FW_VER_BUILD_G(adapter->params.tp_vers)); } static void get_strings(struct net_device *dev, u32 stringset, u8 *data) @@ -2717,9 +2629,10 @@ static int set_rspq_intr_params(struct sge_rspq *q, new_idx = closest_thres(&adap->sge, cnt); if (q->desc && q->pktcnt_idx != new_idx) { /* the queue has already been created, update it */ - v = FW_PARAMS_MNEM(FW_PARAMS_MNEM_DMAQ) | - FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DMAQ_IQ_INTCNTTHRESH) | - FW_PARAMS_PARAM_YZ(q->cntxt_id); + v = FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DMAQ) | + FW_PARAMS_PARAM_X_V( + FW_PARAMS_PARAM_DMAQ_IQ_INTCNTTHRESH) | + FW_PARAMS_PARAM_YZ_V(q->cntxt_id); err = t4_set_params(adap, adap->fn, adap->fn, 0, 1, &v, &new_idx); if (err) @@ -2933,7 +2846,7 @@ static int set_flash(struct net_device *netdev, struct ethtool_flash *ef) int ret; const struct firmware *fw; struct adapter *adap = netdev2adap(netdev); - unsigned int mbox = FW_PCIE_FW_MASTER_MASK + 1; + unsigned int mbox = PCIE_FW_MASTER_M + 1; ef->data[sizeof(ef->data) - 1] = '\0'; ret = request_firmware(&fw, ef->data, adap->pdev_dev); @@ -3044,45 +2957,45 @@ static int get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, info->data = 0; switch (info->flow_type) { case TCP_V4_FLOW: - if (v & FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN) + if (v & FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN_F) info->data = RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 | RXH_L4_B_2_3; - else if (v & FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN) + else if (v & FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN_F) info->data = RXH_IP_SRC | RXH_IP_DST; break; case UDP_V4_FLOW: - if ((v & FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN) && - (v & FW_RSS_VI_CONFIG_CMD_UDPEN)) + if ((v & FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN_F) && + (v & FW_RSS_VI_CONFIG_CMD_UDPEN_F)) info->data = RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 | RXH_L4_B_2_3; - else if (v & FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN) + else if (v & FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN_F) info->data = RXH_IP_SRC | RXH_IP_DST; break; case SCTP_V4_FLOW: case AH_ESP_V4_FLOW: case IPV4_FLOW: - if (v & FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN) + if (v & FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN_F) info->data = RXH_IP_SRC | RXH_IP_DST; break; case TCP_V6_FLOW: - if (v & FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN) + if (v & FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN_F) info->data = RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 | RXH_L4_B_2_3; - else if (v & FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN) + else if (v & FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN_F) info->data = RXH_IP_SRC | RXH_IP_DST; break; case UDP_V6_FLOW: - if ((v & FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN) && - (v & FW_RSS_VI_CONFIG_CMD_UDPEN)) + if ((v & FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN_F) && + (v & FW_RSS_VI_CONFIG_CMD_UDPEN_F)) info->data = RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 | RXH_L4_B_2_3; - else if (v & FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN) + else if (v & FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN_F) info->data = RXH_IP_SRC | RXH_IP_DST; break; case SCTP_V6_FLOW: case AH_ESP_V6_FLOW: case IPV6_FLOW: - if (v & FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN) + if (v & FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN_F) info->data = RXH_IP_SRC | RXH_IP_DST; break; } @@ -3127,102 +3040,14 @@ static const struct ethtool_ops cxgb_ethtool_ops = { .flash_device = set_flash, }; -/* - * debugfs support - */ -static ssize_t mem_read(struct file *file, char __user *buf, size_t count, - loff_t *ppos) -{ - loff_t pos = *ppos; - loff_t avail = file_inode(file)->i_size; - unsigned int mem = (uintptr_t)file->private_data & 3; - struct adapter *adap = file->private_data - mem; - __be32 *data; - int ret; - - if (pos < 0) - return -EINVAL; - if (pos >= avail) - return 0; - if (count > avail - pos) - count = avail - pos; - - data = t4_alloc_mem(count); - if (!data) - return -ENOMEM; - - spin_lock(&adap->win0_lock); - ret = t4_memory_rw(adap, 0, mem, pos, count, data, T4_MEMORY_READ); - spin_unlock(&adap->win0_lock); - if (ret) { - t4_free_mem(data); - return ret; - } - ret = copy_to_user(buf, data, count); - - t4_free_mem(data); - if (ret) - return -EFAULT; - - *ppos = pos + count; - return count; -} - -static const struct file_operations mem_debugfs_fops = { - .owner = THIS_MODULE, - .open = simple_open, - .read = mem_read, - .llseek = default_llseek, -}; - -static void add_debugfs_mem(struct adapter *adap, const char *name, - unsigned int idx, unsigned int size_mb) -{ - struct dentry *de; - - de = debugfs_create_file(name, S_IRUSR, adap->debugfs_root, - (void *)adap + idx, &mem_debugfs_fops); - if (de && de->d_inode) - de->d_inode->i_size = size_mb << 20; -} - static int setup_debugfs(struct adapter *adap) { - int i; - u32 size; - if (IS_ERR_OR_NULL(adap->debugfs_root)) return -1; - i = t4_read_reg(adap, MA_TARGET_MEM_ENABLE); - if (i & EDRAM0_ENABLE) { - size = t4_read_reg(adap, MA_EDRAM0_BAR); - add_debugfs_mem(adap, "edc0", MEM_EDC0, EDRAM_SIZE_GET(size)); - } - if (i & EDRAM1_ENABLE) { - size = t4_read_reg(adap, MA_EDRAM1_BAR); - add_debugfs_mem(adap, "edc1", MEM_EDC1, EDRAM_SIZE_GET(size)); - } - if (is_t4(adap->params.chip)) { - size = t4_read_reg(adap, MA_EXT_MEMORY_BAR); - if (i & EXT_MEM_ENABLE) - add_debugfs_mem(adap, "mc", MEM_MC, - EXT_MEM_SIZE_GET(size)); - } else { - if (i & EXT_MEM_ENABLE) { - size = t4_read_reg(adap, MA_EXT_MEMORY_BAR); - add_debugfs_mem(adap, "mc0", MEM_MC0, - EXT_MEM_SIZE_GET(size)); - } - if (i & EXT_MEM1_ENABLE) { - size = t4_read_reg(adap, MA_EXT_MEMORY1_BAR); - add_debugfs_mem(adap, "mc1", MEM_MC1, - EXT_MEM_SIZE_GET(size)); - } - } - if (adap->l2t) - debugfs_create_file("l2t", S_IRUSR, adap->debugfs_root, adap, - &t4_l2t_fops); +#ifdef CONFIG_DEBUG_FS + t4_setup_debugfs(adap); +#endif return 0; } @@ -3504,9 +3329,9 @@ int cxgb4_clip_get(const struct net_device *dev, adap = netdev2adap(dev); memset(&c, 0, sizeof(c)); - c.op_to_write = htonl(FW_CMD_OP(FW_CLIP_CMD) | - FW_CMD_REQUEST | FW_CMD_WRITE); - c.alloc_to_len16 = htonl(F_FW_CLIP_CMD_ALLOC | FW_LEN16(c)); + c.op_to_write = htonl(FW_CMD_OP_V(FW_CLIP_CMD) | + FW_CMD_REQUEST_F | FW_CMD_WRITE_F); + c.alloc_to_len16 = htonl(FW_CLIP_CMD_ALLOC_F | FW_LEN16(c)); c.ip_hi = *(__be64 *)(lip->s6_addr); c.ip_lo = *(__be64 *)(lip->s6_addr + 8); return t4_wr_mbox_meat(adap, adap->mbox, &c, sizeof(c), &c, false); @@ -3521,9 +3346,9 @@ int cxgb4_clip_release(const struct net_device *dev, adap = netdev2adap(dev); memset(&c, 0, sizeof(c)); - c.op_to_write = htonl(FW_CMD_OP(FW_CLIP_CMD) | - FW_CMD_REQUEST | FW_CMD_READ); - c.alloc_to_len16 = htonl(F_FW_CLIP_CMD_FREE | FW_LEN16(c)); + c.op_to_write = htonl(FW_CMD_OP_V(FW_CLIP_CMD) | + FW_CMD_REQUEST_F | FW_CMD_READ_F); + c.alloc_to_len16 = htonl(FW_CLIP_CMD_FREE_F | FW_LEN16(c)); c.ip_hi = *(__be64 *)(lip->s6_addr); c.ip_lo = *(__be64 *)(lip->s6_addr + 8); return t4_wr_mbox_meat(adap, adap->mbox, &c, sizeof(c), &c, false); @@ -3564,7 +3389,7 @@ int cxgb4_create_server(const struct net_device *dev, unsigned int stid, req->local_ip = sip; req->peer_ip = htonl(0); chan = rxq_to_chan(&adap->sge, queue); - req->opt0 = cpu_to_be64(TX_CHAN(chan)); + req->opt0 = cpu_to_be64(TX_CHAN_V(chan)); req->opt1 = cpu_to_be64(CONN_POLICY_ASK | SYN_RSS_ENABLE | SYN_RSS_QUEUE(queue)); ret = t4_mgmt_tx(adap, skb); @@ -3607,7 +3432,7 @@ int cxgb4_create_server6(const struct net_device *dev, unsigned int stid, req->peer_ip_hi = cpu_to_be64(0); req->peer_ip_lo = cpu_to_be64(0); chan = rxq_to_chan(&adap->sge, queue); - req->opt0 = cpu_to_be64(TX_CHAN(chan)); + req->opt0 = cpu_to_be64(TX_CHAN_V(chan)); req->opt1 = cpu_to_be64(CONN_POLICY_ASK | SYN_RSS_ENABLE | SYN_RSS_QUEUE(queue)); ret = t4_mgmt_tx(adap, skb); @@ -3889,7 +3714,7 @@ int cxgb4_read_tpte(struct net_device *dev, u32 stag, __be32 *tpte) { struct adapter *adap; u32 offset, memtype, memaddr; - u32 edc0_size, edc1_size, mc0_size, mc1_size; + u32 edc0_size, edc1_size, mc0_size, mc1_size, size; u32 edc0_end, edc1_end, mc0_end, mc1_end; int ret; @@ -3903,9 +3728,12 @@ int cxgb4_read_tpte(struct net_device *dev, u32 stag, __be32 *tpte) * and EDC1. Some cards will have neither MC0 nor MC1, most cards have * MC0, and some have both MC0 and MC1. */ - edc0_size = EDRAM_SIZE_GET(t4_read_reg(adap, MA_EDRAM0_BAR)) << 20; - edc1_size = EDRAM_SIZE_GET(t4_read_reg(adap, MA_EDRAM1_BAR)) << 20; - mc0_size = EXT_MEM_SIZE_GET(t4_read_reg(adap, MA_EXT_MEMORY_BAR)) << 20; + size = t4_read_reg(adap, MA_EDRAM0_BAR_A); + edc0_size = EDRAM0_SIZE_G(size) << 20; + size = t4_read_reg(adap, MA_EDRAM1_BAR_A); + edc1_size = EDRAM1_SIZE_G(size) << 20; + size = t4_read_reg(adap, MA_EXT_MEMORY0_BAR_A); + mc0_size = EXT_MEM0_SIZE_G(size) << 20; edc0_end = edc0_size; edc1_end = edc0_end + edc1_size; @@ -3925,9 +3753,8 @@ int cxgb4_read_tpte(struct net_device *dev, u32 stag, __be32 *tpte) /* T4 only has a single memory channel */ goto err; } else { - mc1_size = EXT_MEM_SIZE_GET( - t4_read_reg(adap, - MA_EXT_MEMORY1_BAR)) << 20; + size = t4_read_reg(adap, MA_EXT_MEMORY1_BAR_A); + mc1_size = EXT_MEM1_SIZE_G(size) << 20; mc1_end = mc0_end + mc1_size; if (offset < mc1_end) { memtype = MEM_MC1; @@ -4395,8 +4222,7 @@ static int clip_add(struct net_device *event_dev, struct inet6_ifaddr *ifa, if (cxgb4_netdev(event_dev)) { switch (event) { case NETDEV_UP: - ret = cxgb4_clip_get(event_dev, - (const struct in6_addr *)ifa->addr.s6_addr); + ret = cxgb4_clip_get(event_dev, &ifa->addr); if (ret < 0) { rcu_read_unlock(); return ret; @@ -4404,8 +4230,7 @@ static int clip_add(struct net_device *event_dev, struct inet6_ifaddr *ifa, ret = NOTIFY_OK; break; case NETDEV_DOWN: - cxgb4_clip_release(event_dev, - (const struct in6_addr *)ifa->addr.s6_addr); + cxgb4_clip_release(event_dev, &ifa->addr); ret = NOTIFY_OK; break; default: @@ -4474,8 +4299,7 @@ static int update_dev_clip(struct net_device *root_dev, struct net_device *dev) read_lock_bh(&idev->lock); list_for_each_entry(ifa, &idev->addr_list, if_list) { - ret = cxgb4_clip_get(dev, - (const struct in6_addr *)ifa->addr.s6_addr); + ret = cxgb4_clip_get(dev, &ifa->addr); if (ret < 0) break; } @@ -4956,14 +4780,14 @@ static u32 t4_read_pcie_cfg4(struct adapter *adap, int reg) */ memset(&ldst_cmd, 0, sizeof(ldst_cmd)); ldst_cmd.op_to_addrspace = - htonl(FW_CMD_OP(FW_LDST_CMD) | - FW_CMD_REQUEST | - FW_CMD_READ | - FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_FUNC_PCIE)); + htonl(FW_CMD_OP_V(FW_LDST_CMD) | + FW_CMD_REQUEST_F | + FW_CMD_READ_F | + FW_LDST_CMD_ADDRSPACE_V(FW_LDST_ADDRSPC_FUNC_PCIE)); ldst_cmd.cycles_to_len16 = htonl(FW_LEN16(ldst_cmd)); - ldst_cmd.u.pcie.select_naccess = FW_LDST_CMD_NACCESS(1); + ldst_cmd.u.pcie.select_naccess = FW_LDST_CMD_NACCESS_V(1); ldst_cmd.u.pcie.ctrl_to_fn = - (FW_LDST_CMD_LC | FW_LDST_CMD_FN(adap->fn)); + (FW_LDST_CMD_LC_F | FW_LDST_CMD_FN_V(adap->fn)); ldst_cmd.u.pcie.r = reg; ret = t4_wr_mbox(adap, adap->mbox, &ldst_cmd, sizeof(ldst_cmd), &ldst_cmd); @@ -5050,8 +4874,8 @@ static int adap_init1(struct adapter *adap, struct fw_caps_config_cmd *c) /* get device capabilities */ memset(c, 0, sizeof(*c)); - c->op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) | - FW_CMD_REQUEST | FW_CMD_READ); + c->op_to_write = htonl(FW_CMD_OP_V(FW_CAPS_CONFIG_CMD) | + FW_CMD_REQUEST_F | FW_CMD_READ_F); c->cfvalid_to_len16 = htonl(FW_LEN16(*c)); ret = t4_wr_mbox(adap, adap->fn, c, sizeof(*c), c); if (ret < 0) @@ -5067,16 +4891,16 @@ static int adap_init1(struct adapter *adap, struct fw_caps_config_cmd *c) dev_err(adap->pdev_dev, "virtualization ACLs not supported"); return ret; } - c->op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) | - FW_CMD_REQUEST | FW_CMD_WRITE); + c->op_to_write = htonl(FW_CMD_OP_V(FW_CAPS_CONFIG_CMD) | + FW_CMD_REQUEST_F | FW_CMD_WRITE_F); ret = t4_wr_mbox(adap, adap->fn, c, sizeof(*c), NULL); if (ret < 0) return ret; ret = t4_config_glbl_rss(adap, adap->fn, FW_RSS_GLB_CONFIG_CMD_MODE_BASICVIRTUAL, - FW_RSS_GLB_CONFIG_CMD_TNLMAPEN | - FW_RSS_GLB_CONFIG_CMD_TNLALLLKP); + FW_RSS_GLB_CONFIG_CMD_TNLMAPEN_F | + FW_RSS_GLB_CONFIG_CMD_TNLALLLKP_F); if (ret < 0) return ret; @@ -5237,8 +5061,8 @@ static int adap_init0_config(struct adapter *adapter, int reset) if (cf->size >= FLASH_CFG_MAX_SIZE) ret = -ENOMEM; else { - params[0] = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | - FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_CF)); + params[0] = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DEV) | + FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_DEV_CF)); ret = t4_query_params(adapter, adapter->mbox, adapter->fn, 0, 1, params, val); if (ret == 0) { @@ -5256,8 +5080,8 @@ static int adap_init0_config(struct adapter *adapter, int reset) size_t size = cf->size & ~0x3; __be32 *data = (__be32 *)cf->data; - mtype = FW_PARAMS_PARAM_Y_GET(val[0]); - maddr = FW_PARAMS_PARAM_Z_GET(val[0]) << 16; + mtype = FW_PARAMS_PARAM_Y_G(val[0]); + maddr = FW_PARAMS_PARAM_Z_G(val[0]) << 16; spin_lock(&adapter->win0_lock); ret = t4_memory_rw(adapter, 0, mtype, maddr, @@ -5294,13 +5118,13 @@ static int adap_init0_config(struct adapter *adapter, int reset) */ memset(&caps_cmd, 0, sizeof(caps_cmd)); caps_cmd.op_to_write = - htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) | - FW_CMD_REQUEST | - FW_CMD_READ); + htonl(FW_CMD_OP_V(FW_CAPS_CONFIG_CMD) | + FW_CMD_REQUEST_F | + FW_CMD_READ_F); caps_cmd.cfvalid_to_len16 = - htonl(FW_CAPS_CONFIG_CMD_CFVALID | - FW_CAPS_CONFIG_CMD_MEMTYPE_CF(mtype) | - FW_CAPS_CONFIG_CMD_MEMADDR64K_CF(maddr >> 16) | + htonl(FW_CAPS_CONFIG_CMD_CFVALID_F | + FW_CAPS_CONFIG_CMD_MEMTYPE_CF_V(mtype) | + FW_CAPS_CONFIG_CMD_MEMADDR64K_CF_V(maddr >> 16) | FW_LEN16(caps_cmd)); ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd, sizeof(caps_cmd), &caps_cmd); @@ -5314,9 +5138,9 @@ static int adap_init0_config(struct adapter *adapter, int reset) if (ret == -ENOENT) { memset(&caps_cmd, 0, sizeof(caps_cmd)); caps_cmd.op_to_write = - htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) | - FW_CMD_REQUEST | - FW_CMD_READ); + htonl(FW_CMD_OP_V(FW_CAPS_CONFIG_CMD) | + FW_CMD_REQUEST_F | + FW_CMD_READ_F); caps_cmd.cfvalid_to_len16 = htonl(FW_LEN16(caps_cmd)); ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd, sizeof(caps_cmd), &caps_cmd); @@ -5339,9 +5163,9 @@ static int adap_init0_config(struct adapter *adapter, int reset) * And now tell the firmware to use the configuration we just loaded. */ caps_cmd.op_to_write = - htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) | - FW_CMD_REQUEST | - FW_CMD_WRITE); + htonl(FW_CMD_OP_V(FW_CAPS_CONFIG_CMD) | + FW_CMD_REQUEST_F | + FW_CMD_WRITE_F); caps_cmd.cfvalid_to_len16 = htonl(FW_LEN16(caps_cmd)); ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd, sizeof(caps_cmd), NULL); @@ -5412,8 +5236,8 @@ static int adap_init0_no_config(struct adapter *adapter, int reset) * Get device capabilities and select which we'll be using. */ memset(&caps_cmd, 0, sizeof(caps_cmd)); - caps_cmd.op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) | - FW_CMD_REQUEST | FW_CMD_READ); + caps_cmd.op_to_write = htonl(FW_CMD_OP_V(FW_CAPS_CONFIG_CMD) | + FW_CMD_REQUEST_F | FW_CMD_READ_F); caps_cmd.cfvalid_to_len16 = htonl(FW_LEN16(caps_cmd)); ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd, sizeof(caps_cmd), &caps_cmd); @@ -5429,8 +5253,8 @@ static int adap_init0_no_config(struct adapter *adapter, int reset) dev_err(adapter->pdev_dev, "virtualization ACLs not supported"); goto bye; } - caps_cmd.op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) | - FW_CMD_REQUEST | FW_CMD_WRITE); + caps_cmd.op_to_write = htonl(FW_CMD_OP_V(FW_CAPS_CONFIG_CMD) | + FW_CMD_REQUEST_F | FW_CMD_WRITE_F); ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd, sizeof(caps_cmd), NULL); if (ret < 0) @@ -5452,10 +5276,10 @@ static int adap_init0_no_config(struct adapter *adapter, int reset) adapter->flags |= RSS_TNLALLLOOKUP; ret = t4_config_glbl_rss(adapter, adapter->mbox, FW_RSS_GLB_CONFIG_CMD_MODE_BASICVIRTUAL, - FW_RSS_GLB_CONFIG_CMD_TNLMAPEN | - FW_RSS_GLB_CONFIG_CMD_HASHTOEPLITZ | + FW_RSS_GLB_CONFIG_CMD_TNLMAPEN_F | + FW_RSS_GLB_CONFIG_CMD_HASHTOEPLITZ_F | ((adapter->flags & RSS_TNLALLLOOKUP) ? - FW_RSS_GLB_CONFIG_CMD_TNLALLLKP : 0)); + FW_RSS_GLB_CONFIG_CMD_TNLALLLKP_F : 0)); if (ret < 0) goto bye; @@ -5466,7 +5290,7 @@ static int adap_init0_no_config(struct adapter *adapter, int reset) PFRES_NEQ, PFRES_NETHCTRL, PFRES_NIQFLINT, PFRES_NIQ, PFRES_TC, PFRES_NVI, - FW_PFVF_CMD_CMASK_MASK, + FW_PFVF_CMD_CMASK_M, pfvfres_pmask(adapter, adapter->fn, 0), PFRES_NEXACTF, PFRES_R_CAPS, PFRES_WX_CAPS); @@ -5511,7 +5335,7 @@ static int adap_init0_no_config(struct adapter *adapter, int reset) VFRES_NEQ, VFRES_NETHCTRL, VFRES_NIQFLINT, VFRES_NIQ, VFRES_TC, VFRES_NVI, - FW_PFVF_CMD_CMASK_MASK, + FW_PFVF_CMD_CMASK_M, pfvfres_pmask( adapter, pf, vf), VFRES_NEXACTF, @@ -5775,8 +5599,8 @@ static int adap_init0(struct adapter *adap) * and portvec ... */ v = - FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | - FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_PORTVEC); + FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DEV) | + FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_DEV_PORTVEC); ret = t4_query_params(adap, adap->mbox, adap->fn, 0, 1, &v, &port_vec); if (ret < 0) goto bye; @@ -5798,7 +5622,6 @@ static int adap_init0(struct adapter *adap) } else { dev_info(adap->pdev_dev, "Coming up as MASTER: "\ "Initializing adapter\n"); - /* * If the firmware doesn't support Configuration * Files warn user and exit, @@ -5813,8 +5636,9 @@ static int adap_init0(struct adapter *adap) * Find out whether we're dealing with a version of * the firmware which has configuration file support. */ - params[0] = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | - FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_CF)); + params[0] = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DEV) | + FW_PARAMS_PARAM_X_V( + FW_PARAMS_PARAM_DEV_CF)); ret = t4_query_params(adap, adap->mbox, adap->fn, 0, 1, params, val); @@ -5874,14 +5698,14 @@ static int adap_init0(struct adapter *adap) * Grab some of our basic fundamental operating parameters. */ #define FW_PARAM_DEV(param) \ - (FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | \ - FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_##param)) + (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DEV) | \ + FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_DEV_##param)) #define FW_PARAM_PFVF(param) \ - FW_PARAMS_MNEM(FW_PARAMS_MNEM_PFVF) | \ - FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_PFVF_##param)| \ - FW_PARAMS_PARAM_Y(0) | \ - FW_PARAMS_PARAM_Z(0) + FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_PFVF) | \ + FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_PFVF_##param)| \ + FW_PARAMS_PARAM_Y_V(0) | \ + FW_PARAMS_PARAM_Z_V(0) params[0] = FW_PARAM_PFVF(EQ_START); params[1] = FW_PARAM_PFVF(L2T_START); @@ -5941,8 +5765,8 @@ static int adap_init0(struct adapter *adap) * to manage. */ memset(&caps_cmd, 0, sizeof(caps_cmd)); - caps_cmd.op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) | - FW_CMD_REQUEST | FW_CMD_READ); + caps_cmd.op_to_write = htonl(FW_CMD_OP_V(FW_CAPS_CONFIG_CMD) | + FW_CMD_REQUEST_F | FW_CMD_READ_F); caps_cmd.cfvalid_to_len16 = htonl(FW_LEN16(caps_cmd)); ret = t4_wr_mbox(adap, adap->mbox, &caps_cmd, sizeof(caps_cmd), &caps_cmd); diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h index 1366ba620c87..4eba7cb1b89c 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h @@ -52,10 +52,10 @@ enum { }; #define INIT_TP_WR(w, tid) do { \ - (w)->wr.wr_hi = htonl(FW_WR_OP(FW_TP_WR) | \ - FW_WR_IMMDLEN(sizeof(*w) - sizeof(w->wr))); \ - (w)->wr.wr_mid = htonl(FW_WR_LEN16(DIV_ROUND_UP(sizeof(*w), 16)) | \ - FW_WR_FLOWID(tid)); \ + (w)->wr.wr_hi = htonl(FW_WR_OP_V(FW_TP_WR) | \ + FW_WR_IMMDLEN_V(sizeof(*w) - sizeof(w->wr))); \ + (w)->wr.wr_mid = htonl(FW_WR_LEN16_V(DIV_ROUND_UP(sizeof(*w), 16)) | \ + FW_WR_FLOWID_V(tid)); \ (w)->wr.wr_lo = cpu_to_be64(0); \ } while (0) @@ -65,9 +65,10 @@ enum { } while (0) #define INIT_ULPTX_WR(w, wrlen, atomic, tid) do { \ - (w)->wr.wr_hi = htonl(FW_WR_OP(FW_ULPTX_WR) | FW_WR_ATOMIC(atomic)); \ - (w)->wr.wr_mid = htonl(FW_WR_LEN16(DIV_ROUND_UP(wrlen, 16)) | \ - FW_WR_FLOWID(tid)); \ + (w)->wr.wr_hi = htonl(FW_WR_OP_V(FW_ULPTX_WR) | \ + FW_WR_ATOMIC_V(atomic)); \ + (w)->wr.wr_mid = htonl(FW_WR_LEN16_V(DIV_ROUND_UP(wrlen, 16)) | \ + FW_WR_FLOWID_V(tid)); \ (w)->wr.wr_lo = cpu_to_be64(0); \ } while (0) diff --git a/drivers/net/ethernet/chelsio/cxgb4/l2t.c b/drivers/net/ethernet/chelsio/cxgb4/l2t.c index 96041397ee15..a047baa9fd04 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/l2t.c +++ b/drivers/net/ethernet/chelsio/cxgb4/l2t.c @@ -435,9 +435,9 @@ u64 cxgb4_select_ntuple(struct net_device *dev, if (tp->vnic_shift >= 0) { u32 viid = cxgb4_port_viid(dev); - u32 vf = FW_VIID_VIN_GET(viid); - u32 pf = FW_VIID_PFN_GET(viid); - u32 vld = FW_VIID_VIVLD_GET(viid); + u32 vf = FW_VIID_VIN_G(viid); + u32 pf = FW_VIID_PFN_G(viid); + u32 vld = FW_VIID_VIVLD_G(viid); ntuple |= (u64)(V_FT_VNID_ID_VF(vf) | V_FT_VNID_ID_PF(pf) | diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c index 39f2b13e66c7..433560b8cb1b 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c @@ -576,7 +576,7 @@ static unsigned int refill_fl(struct adapter *adap, struct sge_fl *q, int n, __be64 *d = &q->desc[q->pidx]; struct rx_sw_desc *sd = &q->sdesc[q->pidx]; - gfp |= __GFP_NOWARN | __GFP_COLD; + gfp |= __GFP_NOWARN; if (s->fl_pg_order == 0) goto alloc_small_pages; @@ -585,7 +585,7 @@ static unsigned int refill_fl(struct adapter *adap, struct sge_fl *q, int n, * Prefer large buffers */ while (n) { - pg = alloc_pages(gfp | __GFP_COMP, s->fl_pg_order); + pg = __dev_alloc_pages(gfp, s->fl_pg_order); if (unlikely(!pg)) { q->large_alloc_failed++; break; /* fall back to single pages */ @@ -615,7 +615,7 @@ static unsigned int refill_fl(struct adapter *adap, struct sge_fl *q, int n, alloc_small_pages: while (n--) { - pg = __skb_alloc_page(gfp, NULL); + pg = __dev_alloc_page(gfp); if (unlikely(!pg)) { q->alloc_failed++; break; @@ -816,7 +816,7 @@ static void write_sgl(const struct sk_buff *skb, struct sge_txq *q, sgl->addr0 = cpu_to_be64(addr[1]); } - sgl->cmd_nsge = htonl(ULPTX_CMD(ULP_TX_SC_DSGL) | ULPTX_NSGE(nfrags)); + sgl->cmd_nsge = htonl(ULPTX_CMD_V(ULP_TX_SC_DSGL) | ULPTX_NSGE(nfrags)); if (likely(--nfrags == 0)) return; /* @@ -1092,10 +1092,10 @@ out_free: dev_kfree_skb_any(skb); goto out_free; } - wr_mid = FW_WR_LEN16(DIV_ROUND_UP(flits, 2)); + wr_mid = FW_WR_LEN16_V(DIV_ROUND_UP(flits, 2)); if (unlikely(credits < ETHTXQ_STOP_THRES)) { eth_txq_stop(q); - wr_mid |= FW_WR_EQUEQ | FW_WR_EQUIQ; + wr_mid |= FW_WR_EQUEQ_F | FW_WR_EQUIQ_F; } wr = (void *)&q->q.desc[q->q.pidx]; @@ -1112,8 +1112,8 @@ out_free: dev_kfree_skb_any(skb); int eth_xtra_len = skb_network_offset(skb) - ETH_HLEN; len += sizeof(*lso); - wr->op_immdlen = htonl(FW_WR_OP(FW_ETH_TX_PKT_WR) | - FW_WR_IMMDLEN(len)); + wr->op_immdlen = htonl(FW_WR_OP_V(FW_ETH_TX_PKT_WR) | + FW_WR_IMMDLEN_V(len)); lso->c.lso_ctrl = htonl(LSO_OPCODE(CPL_TX_PKT_LSO) | LSO_FIRST_SLICE | LSO_LAST_SLICE | LSO_IPV6(v6) | @@ -1135,8 +1135,8 @@ out_free: dev_kfree_skb_any(skb); q->tx_cso += ssi->gso_segs; } else { len += sizeof(*cpl); - wr->op_immdlen = htonl(FW_WR_OP(FW_ETH_TX_PKT_WR) | - FW_WR_IMMDLEN(len)); + wr->op_immdlen = htonl(FW_WR_OP_V(FW_ETH_TX_PKT_WR) | + FW_WR_IMMDLEN_V(len)); cpl = (void *)(wr + 1); if (skb->ip_summed == CHECKSUM_PARTIAL) { cntrl = hwcsum(skb) | TXPKT_IPCSUM_DIS; @@ -1224,7 +1224,7 @@ static void ctrlq_check_stop(struct sge_ctrl_txq *q, struct fw_wr_hdr *wr) { reclaim_completed_tx_imm(&q->q); if (unlikely(txq_avail(&q->q) < TXQ_STOP_THRES)) { - wr->lo |= htonl(FW_WR_EQUEQ | FW_WR_EQUIQ); + wr->lo |= htonl(FW_WR_EQUEQ_F | FW_WR_EQUIQ_F); q->q.stops++; q->full = 1; } @@ -1406,7 +1406,7 @@ static void ofldtxq_stop(struct sge_ofld_txq *q, struct sk_buff *skb) { struct fw_wr_hdr *wr = (struct fw_wr_hdr *)skb->data; - wr->lo |= htonl(FW_WR_EQUEQ | FW_WR_EQUIQ); + wr->lo |= htonl(FW_WR_EQUEQ_F | FW_WR_EQUIQ_F); q->q.stops++; q->full = 1; } @@ -2297,20 +2297,20 @@ int t4_sge_alloc_rxq(struct adapter *adap, struct sge_rspq *iq, bool fwevtq, return -ENOMEM; memset(&c, 0, sizeof(c)); - c.op_to_vfn = htonl(FW_CMD_OP(FW_IQ_CMD) | FW_CMD_REQUEST | - FW_CMD_WRITE | FW_CMD_EXEC | - FW_IQ_CMD_PFN(adap->fn) | FW_IQ_CMD_VFN(0)); - c.alloc_to_len16 = htonl(FW_IQ_CMD_ALLOC | FW_IQ_CMD_IQSTART(1) | + c.op_to_vfn = htonl(FW_CMD_OP_V(FW_IQ_CMD) | FW_CMD_REQUEST_F | + FW_CMD_WRITE_F | FW_CMD_EXEC_F | + FW_IQ_CMD_PFN_V(adap->fn) | FW_IQ_CMD_VFN_V(0)); + c.alloc_to_len16 = htonl(FW_IQ_CMD_ALLOC_F | FW_IQ_CMD_IQSTART_F | FW_LEN16(c)); - c.type_to_iqandstindex = htonl(FW_IQ_CMD_TYPE(FW_IQ_TYPE_FL_INT_CAP) | - FW_IQ_CMD_IQASYNCH(fwevtq) | FW_IQ_CMD_VIID(pi->viid) | - FW_IQ_CMD_IQANDST(intr_idx < 0) | FW_IQ_CMD_IQANUD(1) | - FW_IQ_CMD_IQANDSTINDEX(intr_idx >= 0 ? intr_idx : + c.type_to_iqandstindex = htonl(FW_IQ_CMD_TYPE_V(FW_IQ_TYPE_FL_INT_CAP) | + FW_IQ_CMD_IQASYNCH_V(fwevtq) | FW_IQ_CMD_VIID_V(pi->viid) | + FW_IQ_CMD_IQANDST_V(intr_idx < 0) | FW_IQ_CMD_IQANUD_V(1) | + FW_IQ_CMD_IQANDSTINDEX_V(intr_idx >= 0 ? intr_idx : -intr_idx - 1)); - c.iqdroprss_to_iqesize = htons(FW_IQ_CMD_IQPCIECH(pi->tx_chan) | - FW_IQ_CMD_IQGTSMODE | - FW_IQ_CMD_IQINTCNTTHRESH(iq->pktcnt_idx) | - FW_IQ_CMD_IQESIZE(ilog2(iq->iqe_len) - 4)); + c.iqdroprss_to_iqesize = htons(FW_IQ_CMD_IQPCIECH_V(pi->tx_chan) | + FW_IQ_CMD_IQGTSMODE_F | + FW_IQ_CMD_IQINTCNTTHRESH_V(iq->pktcnt_idx) | + FW_IQ_CMD_IQESIZE_V(ilog2(iq->iqe_len) - 4)); c.iqsize = htons(iq->size); c.iqaddr = cpu_to_be64(iq->phys_addr); @@ -2323,12 +2323,12 @@ int t4_sge_alloc_rxq(struct adapter *adap, struct sge_rspq *iq, bool fwevtq, goto fl_nomem; flsz = fl->size / 8 + s->stat_len / sizeof(struct tx_desc); - c.iqns_to_fl0congen = htonl(FW_IQ_CMD_FL0PACKEN(1) | - FW_IQ_CMD_FL0FETCHRO(1) | - FW_IQ_CMD_FL0DATARO(1) | - FW_IQ_CMD_FL0PADEN(1)); - c.fl0dcaen_to_fl0cidxfthresh = htons(FW_IQ_CMD_FL0FBMIN(2) | - FW_IQ_CMD_FL0FBMAX(3)); + c.iqns_to_fl0congen = htonl(FW_IQ_CMD_FL0PACKEN_F | + FW_IQ_CMD_FL0FETCHRO_F | + FW_IQ_CMD_FL0DATARO_F | + FW_IQ_CMD_FL0PADEN_F); + c.fl0dcaen_to_fl0cidxfthresh = htons(FW_IQ_CMD_FL0FBMIN_V(2) | + FW_IQ_CMD_FL0FBMAX_V(3)); c.fl0size = htons(flsz); c.fl0addr = cpu_to_be64(fl->addr); } @@ -2423,21 +2423,22 @@ int t4_sge_alloc_eth_txq(struct adapter *adap, struct sge_eth_txq *txq, return -ENOMEM; memset(&c, 0, sizeof(c)); - c.op_to_vfn = htonl(FW_CMD_OP(FW_EQ_ETH_CMD) | FW_CMD_REQUEST | - FW_CMD_WRITE | FW_CMD_EXEC | - FW_EQ_ETH_CMD_PFN(adap->fn) | FW_EQ_ETH_CMD_VFN(0)); - c.alloc_to_len16 = htonl(FW_EQ_ETH_CMD_ALLOC | - FW_EQ_ETH_CMD_EQSTART | FW_LEN16(c)); - c.viid_pkd = htonl(FW_EQ_ETH_CMD_AUTOEQUEQE | - FW_EQ_ETH_CMD_VIID(pi->viid)); - c.fetchszm_to_iqid = htonl(FW_EQ_ETH_CMD_HOSTFCMODE(2) | - FW_EQ_ETH_CMD_PCIECHN(pi->tx_chan) | - FW_EQ_ETH_CMD_FETCHRO(1) | - FW_EQ_ETH_CMD_IQID(iqid)); - c.dcaen_to_eqsize = htonl(FW_EQ_ETH_CMD_FBMIN(2) | - FW_EQ_ETH_CMD_FBMAX(3) | - FW_EQ_ETH_CMD_CIDXFTHRESH(5) | - FW_EQ_ETH_CMD_EQSIZE(nentries)); + c.op_to_vfn = htonl(FW_CMD_OP_V(FW_EQ_ETH_CMD) | FW_CMD_REQUEST_F | + FW_CMD_WRITE_F | FW_CMD_EXEC_F | + FW_EQ_ETH_CMD_PFN_V(adap->fn) | + FW_EQ_ETH_CMD_VFN_V(0)); + c.alloc_to_len16 = htonl(FW_EQ_ETH_CMD_ALLOC_F | + FW_EQ_ETH_CMD_EQSTART_F | FW_LEN16(c)); + c.viid_pkd = htonl(FW_EQ_ETH_CMD_AUTOEQUEQE_F | + FW_EQ_ETH_CMD_VIID_V(pi->viid)); + c.fetchszm_to_iqid = htonl(FW_EQ_ETH_CMD_HOSTFCMODE_V(2) | + FW_EQ_ETH_CMD_PCIECHN_V(pi->tx_chan) | + FW_EQ_ETH_CMD_FETCHRO_V(1) | + FW_EQ_ETH_CMD_IQID_V(iqid)); + c.dcaen_to_eqsize = htonl(FW_EQ_ETH_CMD_FBMIN_V(2) | + FW_EQ_ETH_CMD_FBMAX_V(3) | + FW_EQ_ETH_CMD_CIDXFTHRESH_V(5) | + FW_EQ_ETH_CMD_EQSIZE_V(nentries)); c.eqaddr = cpu_to_be64(txq->q.phys_addr); ret = t4_wr_mbox(adap, adap->fn, &c, sizeof(c), &c); @@ -2451,7 +2452,7 @@ int t4_sge_alloc_eth_txq(struct adapter *adap, struct sge_eth_txq *txq, return ret; } - init_txq(adap, &txq->q, FW_EQ_ETH_CMD_EQID_GET(ntohl(c.eqid_pkd))); + init_txq(adap, &txq->q, FW_EQ_ETH_CMD_EQID_G(ntohl(c.eqid_pkd))); txq->txq = netdevq; txq->tso = txq->tx_cso = txq->vlan_ins = 0; txq->mapping_err = 0; @@ -2476,22 +2477,22 @@ int t4_sge_alloc_ctrl_txq(struct adapter *adap, struct sge_ctrl_txq *txq, if (!txq->q.desc) return -ENOMEM; - c.op_to_vfn = htonl(FW_CMD_OP(FW_EQ_CTRL_CMD) | FW_CMD_REQUEST | - FW_CMD_WRITE | FW_CMD_EXEC | - FW_EQ_CTRL_CMD_PFN(adap->fn) | - FW_EQ_CTRL_CMD_VFN(0)); - c.alloc_to_len16 = htonl(FW_EQ_CTRL_CMD_ALLOC | - FW_EQ_CTRL_CMD_EQSTART | FW_LEN16(c)); - c.cmpliqid_eqid = htonl(FW_EQ_CTRL_CMD_CMPLIQID(cmplqid)); + c.op_to_vfn = htonl(FW_CMD_OP_V(FW_EQ_CTRL_CMD) | FW_CMD_REQUEST_F | + FW_CMD_WRITE_F | FW_CMD_EXEC_F | + FW_EQ_CTRL_CMD_PFN_V(adap->fn) | + FW_EQ_CTRL_CMD_VFN_V(0)); + c.alloc_to_len16 = htonl(FW_EQ_CTRL_CMD_ALLOC_F | + FW_EQ_CTRL_CMD_EQSTART_F | FW_LEN16(c)); + c.cmpliqid_eqid = htonl(FW_EQ_CTRL_CMD_CMPLIQID_V(cmplqid)); c.physeqid_pkd = htonl(0); - c.fetchszm_to_iqid = htonl(FW_EQ_CTRL_CMD_HOSTFCMODE(2) | - FW_EQ_CTRL_CMD_PCIECHN(pi->tx_chan) | - FW_EQ_CTRL_CMD_FETCHRO | - FW_EQ_CTRL_CMD_IQID(iqid)); - c.dcaen_to_eqsize = htonl(FW_EQ_CTRL_CMD_FBMIN(2) | - FW_EQ_CTRL_CMD_FBMAX(3) | - FW_EQ_CTRL_CMD_CIDXFTHRESH(5) | - FW_EQ_CTRL_CMD_EQSIZE(nentries)); + c.fetchszm_to_iqid = htonl(FW_EQ_CTRL_CMD_HOSTFCMODE_V(2) | + FW_EQ_CTRL_CMD_PCIECHN_V(pi->tx_chan) | + FW_EQ_CTRL_CMD_FETCHRO_F | + FW_EQ_CTRL_CMD_IQID_V(iqid)); + c.dcaen_to_eqsize = htonl(FW_EQ_CTRL_CMD_FBMIN_V(2) | + FW_EQ_CTRL_CMD_FBMAX_V(3) | + FW_EQ_CTRL_CMD_CIDXFTHRESH_V(5) | + FW_EQ_CTRL_CMD_EQSIZE_V(nentries)); c.eqaddr = cpu_to_be64(txq->q.phys_addr); ret = t4_wr_mbox(adap, adap->fn, &c, sizeof(c), &c); @@ -2503,7 +2504,7 @@ int t4_sge_alloc_ctrl_txq(struct adapter *adap, struct sge_ctrl_txq *txq, return ret; } - init_txq(adap, &txq->q, FW_EQ_CTRL_CMD_EQID_GET(ntohl(c.cmpliqid_eqid))); + init_txq(adap, &txq->q, FW_EQ_CTRL_CMD_EQID_G(ntohl(c.cmpliqid_eqid))); txq->adap = adap; skb_queue_head_init(&txq->sendq); tasklet_init(&txq->qresume_tsk, restart_ctrlq, (unsigned long)txq); @@ -2530,20 +2531,20 @@ int t4_sge_alloc_ofld_txq(struct adapter *adap, struct sge_ofld_txq *txq, return -ENOMEM; memset(&c, 0, sizeof(c)); - c.op_to_vfn = htonl(FW_CMD_OP(FW_EQ_OFLD_CMD) | FW_CMD_REQUEST | - FW_CMD_WRITE | FW_CMD_EXEC | - FW_EQ_OFLD_CMD_PFN(adap->fn) | - FW_EQ_OFLD_CMD_VFN(0)); - c.alloc_to_len16 = htonl(FW_EQ_OFLD_CMD_ALLOC | - FW_EQ_OFLD_CMD_EQSTART | FW_LEN16(c)); - c.fetchszm_to_iqid = htonl(FW_EQ_OFLD_CMD_HOSTFCMODE(2) | - FW_EQ_OFLD_CMD_PCIECHN(pi->tx_chan) | - FW_EQ_OFLD_CMD_FETCHRO(1) | - FW_EQ_OFLD_CMD_IQID(iqid)); - c.dcaen_to_eqsize = htonl(FW_EQ_OFLD_CMD_FBMIN(2) | - FW_EQ_OFLD_CMD_FBMAX(3) | - FW_EQ_OFLD_CMD_CIDXFTHRESH(5) | - FW_EQ_OFLD_CMD_EQSIZE(nentries)); + c.op_to_vfn = htonl(FW_CMD_OP_V(FW_EQ_OFLD_CMD) | FW_CMD_REQUEST_F | + FW_CMD_WRITE_F | FW_CMD_EXEC_F | + FW_EQ_OFLD_CMD_PFN_V(adap->fn) | + FW_EQ_OFLD_CMD_VFN_V(0)); + c.alloc_to_len16 = htonl(FW_EQ_OFLD_CMD_ALLOC_F | + FW_EQ_OFLD_CMD_EQSTART_F | FW_LEN16(c)); + c.fetchszm_to_iqid = htonl(FW_EQ_OFLD_CMD_HOSTFCMODE_V(2) | + FW_EQ_OFLD_CMD_PCIECHN_V(pi->tx_chan) | + FW_EQ_OFLD_CMD_FETCHRO_F | + FW_EQ_OFLD_CMD_IQID_V(iqid)); + c.dcaen_to_eqsize = htonl(FW_EQ_OFLD_CMD_FBMIN_V(2) | + FW_EQ_OFLD_CMD_FBMAX_V(3) | + FW_EQ_OFLD_CMD_CIDXFTHRESH_V(5) | + FW_EQ_OFLD_CMD_EQSIZE_V(nentries)); c.eqaddr = cpu_to_be64(txq->q.phys_addr); ret = t4_wr_mbox(adap, adap->fn, &c, sizeof(c), &c); @@ -2557,7 +2558,7 @@ int t4_sge_alloc_ofld_txq(struct adapter *adap, struct sge_ofld_txq *txq, return ret; } - init_txq(adap, &txq->q, FW_EQ_OFLD_CMD_EQID_GET(ntohl(c.eqid_pkd))); + init_txq(adap, &txq->q, FW_EQ_OFLD_CMD_EQID_G(ntohl(c.eqid_pkd))); txq->adap = adap; skb_queue_head_init(&txq->sendq); tasklet_init(&txq->qresume_tsk, restart_ofldq, (unsigned long)txq); diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index 163a2a14948c..7975d26f50df 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c @@ -188,9 +188,9 @@ static void t4_report_fw_error(struct adapter *adap) u32 pcie_fw; pcie_fw = t4_read_reg(adap, MA_PCIE_FW); - if (pcie_fw & FW_PCIE_FW_ERR) + if (pcie_fw & PCIE_FW_ERR) dev_err(adap->pdev_dev, "Firmware reports adapter error: %s\n", - reason[FW_PCIE_FW_EVAL_GET(pcie_fw)]); + reason[PCIE_FW_EVAL_G(pcie_fw)]); } /* @@ -310,16 +310,17 @@ int t4_wr_mbox_meat(struct adapter *adap, int mbox, const void *cmd, int size, } res = t4_read_reg64(adap, data_reg); - if (FW_CMD_OP_GET(res >> 32) == FW_DEBUG_CMD) { + if (FW_CMD_OP_G(res >> 32) == FW_DEBUG_CMD) { fw_asrt(adap, data_reg); - res = FW_CMD_RETVAL(EIO); - } else if (rpl) + res = FW_CMD_RETVAL_V(EIO); + } else if (rpl) { get_mbox_rpl(adap, rpl, size / 8, data_reg); + } - if (FW_CMD_RETVAL_GET((int)res)) + if (FW_CMD_RETVAL_G((int)res)) dump_mbox(adap, mbox, data_reg); t4_write_reg(adap, ctl_reg, 0); - return -FW_CMD_RETVAL_GET((int)res); + return -FW_CMD_RETVAL_G((int)res); } } @@ -483,12 +484,12 @@ int t4_memory_rw(struct adapter *adap, int win, int mtype, u32 addr, * MEM_MC0 = 2 -- For T5 * MEM_MC1 = 3 -- For T5 */ - edc_size = EDRAM_SIZE_GET(t4_read_reg(adap, MA_EDRAM0_BAR)); + edc_size = EDRAM0_SIZE_G(t4_read_reg(adap, MA_EDRAM0_BAR_A)); if (mtype != MEM_MC1) memoffset = (mtype * (edc_size * 1024 * 1024)); else { - mc_size = EXT_MEM_SIZE_GET(t4_read_reg(adap, - MA_EXT_MEMORY_BAR)); + mc_size = EXT_MEM0_SIZE_G(t4_read_reg(adap, + MA_EXT_MEMORY1_BAR_A)); memoffset = (MEM_MC0 * edc_size + mc_size) * 1024 * 1024; } @@ -710,8 +711,8 @@ int get_vpd_params(struct adapter *adapter, struct vpd_params *p) * Ask firmware for the Core Clock since it knows how to translate the * Reference Clock ('V2') VPD field into a Core Clock value ... */ - cclk_param = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | - FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_CCLK)); + cclk_param = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DEV) | + FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_DEV_CCLK)); ret = t4_query_params(adapter, adapter->mbox, 0, 0, 1, &cclk_param, &cclk_val); @@ -992,10 +993,10 @@ static int should_install_fs_fw(struct adapter *adap, int card_fw_usable, install: dev_err(adap->pdev_dev, "firmware on card (%u.%u.%u.%u) is %s, " "installing firmware %u.%u.%u.%u on card.\n", - FW_HDR_FW_VER_MAJOR_GET(c), FW_HDR_FW_VER_MINOR_GET(c), - FW_HDR_FW_VER_MICRO_GET(c), FW_HDR_FW_VER_BUILD_GET(c), reason, - FW_HDR_FW_VER_MAJOR_GET(k), FW_HDR_FW_VER_MINOR_GET(k), - FW_HDR_FW_VER_MICRO_GET(k), FW_HDR_FW_VER_BUILD_GET(k)); + FW_HDR_FW_VER_MAJOR_G(c), FW_HDR_FW_VER_MINOR_G(c), + FW_HDR_FW_VER_MICRO_G(c), FW_HDR_FW_VER_BUILD_G(c), reason, + FW_HDR_FW_VER_MAJOR_G(k), FW_HDR_FW_VER_MINOR_G(k), + FW_HDR_FW_VER_MICRO_G(k), FW_HDR_FW_VER_BUILD_G(k)); return 1; } @@ -1067,12 +1068,12 @@ int t4_prep_fw(struct adapter *adap, struct fw_info *fw_info, "driver compiled with %d.%d.%d.%d, " "card has %d.%d.%d.%d, filesystem has %d.%d.%d.%d\n", state, - FW_HDR_FW_VER_MAJOR_GET(d), FW_HDR_FW_VER_MINOR_GET(d), - FW_HDR_FW_VER_MICRO_GET(d), FW_HDR_FW_VER_BUILD_GET(d), - FW_HDR_FW_VER_MAJOR_GET(c), FW_HDR_FW_VER_MINOR_GET(c), - FW_HDR_FW_VER_MICRO_GET(c), FW_HDR_FW_VER_BUILD_GET(c), - FW_HDR_FW_VER_MAJOR_GET(k), FW_HDR_FW_VER_MINOR_GET(k), - FW_HDR_FW_VER_MICRO_GET(k), FW_HDR_FW_VER_BUILD_GET(k)); + FW_HDR_FW_VER_MAJOR_G(d), FW_HDR_FW_VER_MINOR_G(d), + FW_HDR_FW_VER_MICRO_G(d), FW_HDR_FW_VER_BUILD_G(d), + FW_HDR_FW_VER_MAJOR_G(c), FW_HDR_FW_VER_MINOR_G(c), + FW_HDR_FW_VER_MICRO_G(c), FW_HDR_FW_VER_BUILD_G(c), + FW_HDR_FW_VER_MAJOR_G(k), FW_HDR_FW_VER_MINOR_G(k), + FW_HDR_FW_VER_MICRO_G(k), FW_HDR_FW_VER_BUILD_G(k)); ret = EINVAL; goto bye; } @@ -1236,7 +1237,7 @@ int t4_link_start(struct adapter *adap, unsigned int mbox, unsigned int port, struct link_config *lc) { struct fw_port_cmd c; - unsigned int fc = 0, mdi = FW_PORT_MDI(FW_PORT_MDI_AUTO); + unsigned int fc = 0, mdi = FW_PORT_CAP_MDI_V(FW_PORT_CAP_MDI_AUTO); lc->link_ok = 0; if (lc->requested_fc & PAUSE_RX) @@ -1245,9 +1246,9 @@ int t4_link_start(struct adapter *adap, unsigned int mbox, unsigned int port, fc |= FW_PORT_CAP_FC_TX; memset(&c, 0, sizeof(c)); - c.op_to_portid = htonl(FW_CMD_OP(FW_PORT_CMD) | FW_CMD_REQUEST | - FW_CMD_EXEC | FW_PORT_CMD_PORTID(port)); - c.action_to_len16 = htonl(FW_PORT_CMD_ACTION(FW_PORT_ACTION_L1_CFG) | + c.op_to_portid = htonl(FW_CMD_OP_V(FW_PORT_CMD) | FW_CMD_REQUEST_F | + FW_CMD_EXEC_F | FW_PORT_CMD_PORTID_V(port)); + c.action_to_len16 = htonl(FW_PORT_CMD_ACTION_V(FW_PORT_ACTION_L1_CFG) | FW_LEN16(c)); if (!(lc->supported & FW_PORT_CAP_ANEG)) { @@ -1275,9 +1276,9 @@ int t4_restart_aneg(struct adapter *adap, unsigned int mbox, unsigned int port) struct fw_port_cmd c; memset(&c, 0, sizeof(c)); - c.op_to_portid = htonl(FW_CMD_OP(FW_PORT_CMD) | FW_CMD_REQUEST | - FW_CMD_EXEC | FW_PORT_CMD_PORTID(port)); - c.action_to_len16 = htonl(FW_PORT_CMD_ACTION(FW_PORT_ACTION_L1_CFG) | + c.op_to_portid = htonl(FW_CMD_OP_V(FW_PORT_CMD) | FW_CMD_REQUEST_F | + FW_CMD_EXEC_F | FW_PORT_CMD_PORTID_V(port)); + c.action_to_len16 = htonl(FW_PORT_CMD_ACTION_V(FW_PORT_ACTION_L1_CFG) | FW_LEN16(c)); c.u.l1cfg.rcap = htonl(FW_PORT_CAP_ANEG); return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); @@ -1563,7 +1564,7 @@ static void cim_intr_handler(struct adapter *adapter) int fat; - if (t4_read_reg(adapter, MA_PCIE_FW) & FW_PCIE_FW_ERR) + if (t4_read_reg(adapter, MA_PCIE_FW) & PCIE_FW_ERR) t4_report_fw_error(adapter); fat = t4_handle_intr_status(adapter, CIM_HOST_INT_CAUSE, @@ -2071,9 +2072,9 @@ int t4_config_rss_range(struct adapter *adapter, int mbox, unsigned int viid, struct fw_rss_ind_tbl_cmd cmd; memset(&cmd, 0, sizeof(cmd)); - cmd.op_to_viid = htonl(FW_CMD_OP(FW_RSS_IND_TBL_CMD) | - FW_CMD_REQUEST | FW_CMD_WRITE | - FW_RSS_IND_TBL_CMD_VIID(viid)); + cmd.op_to_viid = htonl(FW_CMD_OP_V(FW_RSS_IND_TBL_CMD) | + FW_CMD_REQUEST_F | FW_CMD_WRITE_F | + FW_RSS_IND_TBL_CMD_VIID_V(viid)); cmd.retval_len16 = htonl(FW_LEN16(cmd)); /* each fw_rss_ind_tbl_cmd takes up to 32 entries */ @@ -2090,13 +2091,13 @@ int t4_config_rss_range(struct adapter *adapter, int mbox, unsigned int viid, while (nq > 0) { unsigned int v; - v = FW_RSS_IND_TBL_CMD_IQ0(*rsp); + v = FW_RSS_IND_TBL_CMD_IQ0_V(*rsp); if (++rsp >= rsp_end) rsp = rspq; - v |= FW_RSS_IND_TBL_CMD_IQ1(*rsp); + v |= FW_RSS_IND_TBL_CMD_IQ1_V(*rsp); if (++rsp >= rsp_end) rsp = rspq; - v |= FW_RSS_IND_TBL_CMD_IQ2(*rsp); + v |= FW_RSS_IND_TBL_CMD_IQ2_V(*rsp); if (++rsp >= rsp_end) rsp = rspq; @@ -2126,14 +2127,14 @@ int t4_config_glbl_rss(struct adapter *adapter, int mbox, unsigned int mode, struct fw_rss_glb_config_cmd c; memset(&c, 0, sizeof(c)); - c.op_to_write = htonl(FW_CMD_OP(FW_RSS_GLB_CONFIG_CMD) | - FW_CMD_REQUEST | FW_CMD_WRITE); + c.op_to_write = htonl(FW_CMD_OP_V(FW_RSS_GLB_CONFIG_CMD) | + FW_CMD_REQUEST_F | FW_CMD_WRITE_F); c.retval_len16 = htonl(FW_LEN16(c)); if (mode == FW_RSS_GLB_CONFIG_CMD_MODE_MANUAL) { - c.u.manual.mode_pkd = htonl(FW_RSS_GLB_CONFIG_CMD_MODE(mode)); + c.u.manual.mode_pkd = htonl(FW_RSS_GLB_CONFIG_CMD_MODE_V(mode)); } else if (mode == FW_RSS_GLB_CONFIG_CMD_MODE_BASICVIRTUAL) { c.u.basicvirtual.mode_pkd = - htonl(FW_RSS_GLB_CONFIG_CMD_MODE(mode)); + htonl(FW_RSS_GLB_CONFIG_CMD_MODE_V(mode)); c.u.basicvirtual.synmapen_to_hashtoeplitz = htonl(flags); } else return -EINVAL; @@ -2553,18 +2554,18 @@ int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map, void t4_mk_filtdelwr(unsigned int ftid, struct fw_filter_wr *wr, int qid) { memset(wr, 0, sizeof(*wr)); - wr->op_pkd = htonl(FW_WR_OP(FW_FILTER_WR)); - wr->len16_pkd = htonl(FW_WR_LEN16(sizeof(*wr) / 16)); - wr->tid_to_iq = htonl(V_FW_FILTER_WR_TID(ftid) | - V_FW_FILTER_WR_NOREPLY(qid < 0)); - wr->del_filter_to_l2tix = htonl(F_FW_FILTER_WR_DEL_FILTER); + wr->op_pkd = htonl(FW_WR_OP_V(FW_FILTER_WR)); + wr->len16_pkd = htonl(FW_WR_LEN16_V(sizeof(*wr) / 16)); + wr->tid_to_iq = htonl(FW_FILTER_WR_TID_V(ftid) | + FW_FILTER_WR_NOREPLY_V(qid < 0)); + wr->del_filter_to_l2tix = htonl(FW_FILTER_WR_DEL_FILTER_F); if (qid >= 0) - wr->rx_chan_rx_rpl_iq = htons(V_FW_FILTER_WR_RX_RPL_IQ(qid)); + wr->rx_chan_rx_rpl_iq = htons(FW_FILTER_WR_RX_RPL_IQ_V(qid)); } #define INIT_CMD(var, cmd, rd_wr) do { \ - (var).op_to_write = htonl(FW_CMD_OP(FW_##cmd##_CMD) | \ - FW_CMD_REQUEST | FW_CMD_##rd_wr); \ + (var).op_to_write = htonl(FW_CMD_OP_V(FW_##cmd##_CMD) | \ + FW_CMD_REQUEST_F | FW_CMD_##rd_wr##_F); \ (var).retval_len16 = htonl(FW_LEN16(var)); \ } while (0) @@ -2574,9 +2575,9 @@ int t4_fwaddrspace_write(struct adapter *adap, unsigned int mbox, struct fw_ldst_cmd c; memset(&c, 0, sizeof(c)); - c.op_to_addrspace = htonl(FW_CMD_OP(FW_LDST_CMD) | FW_CMD_REQUEST | - FW_CMD_WRITE | - FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_FIRMWARE)); + c.op_to_addrspace = htonl(FW_CMD_OP_V(FW_LDST_CMD) | FW_CMD_REQUEST_F | + FW_CMD_WRITE_F | + FW_LDST_CMD_ADDRSPACE_V(FW_LDST_ADDRSPC_FIRMWARE)); c.cycles_to_len16 = htonl(FW_LEN16(c)); c.u.addrval.addr = htonl(addr); c.u.addrval.val = htonl(val); @@ -2602,11 +2603,11 @@ int t4_mdio_rd(struct adapter *adap, unsigned int mbox, unsigned int phy_addr, struct fw_ldst_cmd c; memset(&c, 0, sizeof(c)); - c.op_to_addrspace = htonl(FW_CMD_OP(FW_LDST_CMD) | FW_CMD_REQUEST | - FW_CMD_READ | FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_MDIO)); + c.op_to_addrspace = htonl(FW_CMD_OP_V(FW_LDST_CMD) | FW_CMD_REQUEST_F | + FW_CMD_READ_F | FW_LDST_CMD_ADDRSPACE_V(FW_LDST_ADDRSPC_MDIO)); c.cycles_to_len16 = htonl(FW_LEN16(c)); - c.u.mdio.paddr_mmd = htons(FW_LDST_CMD_PADDR(phy_addr) | - FW_LDST_CMD_MMD(mmd)); + c.u.mdio.paddr_mmd = htons(FW_LDST_CMD_PADDR_V(phy_addr) | + FW_LDST_CMD_MMD_V(mmd)); c.u.mdio.raddr = htons(reg); ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c); @@ -2632,11 +2633,11 @@ int t4_mdio_wr(struct adapter *adap, unsigned int mbox, unsigned int phy_addr, struct fw_ldst_cmd c; memset(&c, 0, sizeof(c)); - c.op_to_addrspace = htonl(FW_CMD_OP(FW_LDST_CMD) | FW_CMD_REQUEST | - FW_CMD_WRITE | FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_MDIO)); + c.op_to_addrspace = htonl(FW_CMD_OP_V(FW_LDST_CMD) | FW_CMD_REQUEST_F | + FW_CMD_WRITE_F | FW_LDST_CMD_ADDRSPACE_V(FW_LDST_ADDRSPC_MDIO)); c.cycles_to_len16 = htonl(FW_LEN16(c)); - c.u.mdio.paddr_mmd = htons(FW_LDST_CMD_PADDR(phy_addr) | - FW_LDST_CMD_MMD(mmd)); + c.u.mdio.paddr_mmd = htons(FW_LDST_CMD_PADDR_V(phy_addr) | + FW_LDST_CMD_MMD_V(mmd)); c.u.mdio.raddr = htons(reg); c.u.mdio.rval = htons(val); @@ -2773,13 +2774,13 @@ retry: memset(&c, 0, sizeof(c)); INIT_CMD(c, HELLO, WRITE); c.err_to_clearinit = htonl( - FW_HELLO_CMD_MASTERDIS(master == MASTER_CANT) | - FW_HELLO_CMD_MASTERFORCE(master == MASTER_MUST) | - FW_HELLO_CMD_MBMASTER(master == MASTER_MUST ? mbox : - FW_HELLO_CMD_MBMASTER_MASK) | - FW_HELLO_CMD_MBASYNCNOT(evt_mbox) | - FW_HELLO_CMD_STAGE(fw_hello_cmd_stage_os) | - FW_HELLO_CMD_CLEARINIT); + FW_HELLO_CMD_MASTERDIS_V(master == MASTER_CANT) | + FW_HELLO_CMD_MASTERFORCE_V(master == MASTER_MUST) | + FW_HELLO_CMD_MBMASTER_V(master == MASTER_MUST ? mbox : + FW_HELLO_CMD_MBMASTER_M) | + FW_HELLO_CMD_MBASYNCNOT_V(evt_mbox) | + FW_HELLO_CMD_STAGE_V(fw_hello_cmd_stage_os) | + FW_HELLO_CMD_CLEARINIT_F); /* * Issue the HELLO command to the firmware. If it's not successful @@ -2792,17 +2793,17 @@ retry: if (ret < 0) { if ((ret == -EBUSY || ret == -ETIMEDOUT) && retries-- > 0) goto retry; - if (t4_read_reg(adap, MA_PCIE_FW) & FW_PCIE_FW_ERR) + if (t4_read_reg(adap, MA_PCIE_FW) & PCIE_FW_ERR) t4_report_fw_error(adap); return ret; } v = ntohl(c.err_to_clearinit); - master_mbox = FW_HELLO_CMD_MBMASTER_GET(v); + master_mbox = FW_HELLO_CMD_MBMASTER_G(v); if (state) { - if (v & FW_HELLO_CMD_ERR) + if (v & FW_HELLO_CMD_ERR_F) *state = DEV_STATE_ERR; - else if (v & FW_HELLO_CMD_INIT) + else if (v & FW_HELLO_CMD_INIT_F) *state = DEV_STATE_INIT; else *state = DEV_STATE_UNINIT; @@ -2817,9 +2818,9 @@ retry: * and we wouldn't want to fail pointlessly. (This can happen when an * OS loads lots of different drivers rapidly at the same time). In * this case, the Master PF returned by the firmware will be - * FW_PCIE_FW_MASTER_MASK so the test below will work ... + * PCIE_FW_MASTER_M so the test below will work ... */ - if ((v & (FW_HELLO_CMD_ERR|FW_HELLO_CMD_INIT)) == 0 && + if ((v & (FW_HELLO_CMD_ERR_F|FW_HELLO_CMD_INIT_F)) == 0 && master_mbox != mbox) { int waiting = FW_CMD_HELLO_TIMEOUT; @@ -2843,7 +2844,7 @@ retry: * our retries ... */ pcie_fw = t4_read_reg(adap, MA_PCIE_FW); - if (!(pcie_fw & (FW_PCIE_FW_ERR|FW_PCIE_FW_INIT))) { + if (!(pcie_fw & (PCIE_FW_ERR|PCIE_FW_INIT))) { if (waiting <= 0) { if (retries-- > 0) goto retry; @@ -2858,9 +2859,9 @@ retry: * report errors preferentially. */ if (state) { - if (pcie_fw & FW_PCIE_FW_ERR) + if (pcie_fw & PCIE_FW_ERR) *state = DEV_STATE_ERR; - else if (pcie_fw & FW_PCIE_FW_INIT) + else if (pcie_fw & PCIE_FW_INIT) *state = DEV_STATE_INIT; } @@ -2869,9 +2870,9 @@ retry: * there's not a valid Master PF, grab its identity * for our caller. */ - if (master_mbox == FW_PCIE_FW_MASTER_MASK && - (pcie_fw & FW_PCIE_FW_MASTER_VLD)) - master_mbox = FW_PCIE_FW_MASTER_GET(pcie_fw); + if (master_mbox == PCIE_FW_MASTER_M && + (pcie_fw & PCIE_FW_MASTER_VLD)) + master_mbox = PCIE_FW_MASTER_G(pcie_fw); break; } } @@ -2939,7 +2940,7 @@ int t4_fw_reset(struct adapter *adap, unsigned int mbox, int reset) * Issues a RESET command to firmware (if desired) with a HALT indication * and then puts the microprocessor into RESET state. The RESET command * will only be issued if a legitimate mailbox is provided (mbox <= - * FW_PCIE_FW_MASTER_MASK). + * PCIE_FW_MASTER_M). * * This is generally used in order for the host to safely manipulate the * adapter without fear of conflicting with whatever the firmware might @@ -2954,13 +2955,13 @@ static int t4_fw_halt(struct adapter *adap, unsigned int mbox, int force) * If a legitimate mailbox is provided, issue a RESET command * with a HALT indication. */ - if (mbox <= FW_PCIE_FW_MASTER_MASK) { + if (mbox <= PCIE_FW_MASTER_M) { struct fw_reset_cmd c; memset(&c, 0, sizeof(c)); INIT_CMD(c, RESET, WRITE); c.val = htonl(PIORST | PIORSTMODE); - c.halt_pkd = htonl(FW_RESET_CMD_HALT(1U)); + c.halt_pkd = htonl(FW_RESET_CMD_HALT_F); ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); } @@ -2979,8 +2980,8 @@ static int t4_fw_halt(struct adapter *adap, unsigned int mbox, int force) */ if (ret == 0 || force) { t4_set_reg_field(adap, CIM_BOOT_CFG, UPCRST, UPCRST); - t4_set_reg_field(adap, PCIE_FW, FW_PCIE_FW_HALT, - FW_PCIE_FW_HALT); + t4_set_reg_field(adap, PCIE_FW, PCIE_FW_HALT_F, + PCIE_FW_HALT_F); } /* @@ -3019,7 +3020,7 @@ static int t4_fw_restart(struct adapter *adap, unsigned int mbox, int reset) * doing it automatically, we need to clear the PCIE_FW.HALT * bit. */ - t4_set_reg_field(adap, PCIE_FW, FW_PCIE_FW_HALT, 0); + t4_set_reg_field(adap, PCIE_FW, PCIE_FW_HALT_F, 0); /* * If we've been given a valid mailbox, first try to get the @@ -3028,7 +3029,7 @@ static int t4_fw_restart(struct adapter *adap, unsigned int mbox, int reset) * valid mailbox or the RESET command failed, fall back to * hitting the chip with a hammer. */ - if (mbox <= FW_PCIE_FW_MASTER_MASK) { + if (mbox <= PCIE_FW_MASTER_M) { t4_set_reg_field(adap, CIM_BOOT_CFG, UPCRST, 0); msleep(100); if (t4_fw_reset(adap, mbox, @@ -3043,7 +3044,7 @@ static int t4_fw_restart(struct adapter *adap, unsigned int mbox, int reset) t4_set_reg_field(adap, CIM_BOOT_CFG, UPCRST, 0); for (ms = 0; ms < FW_CMD_MAX_TIMEOUT; ) { - if (!(t4_read_reg(adap, PCIE_FW) & FW_PCIE_FW_HALT)) + if (!(t4_read_reg(adap, PCIE_FW) & PCIE_FW_HALT_F)) return 0; msleep(100); ms += 100; @@ -3250,9 +3251,9 @@ int t4_query_params(struct adapter *adap, unsigned int mbox, unsigned int pf, return -EINVAL; memset(&c, 0, sizeof(c)); - c.op_to_vfn = htonl(FW_CMD_OP(FW_PARAMS_CMD) | FW_CMD_REQUEST | - FW_CMD_READ | FW_PARAMS_CMD_PFN(pf) | - FW_PARAMS_CMD_VFN(vf)); + c.op_to_vfn = htonl(FW_CMD_OP_V(FW_PARAMS_CMD) | FW_CMD_REQUEST_F | + FW_CMD_READ_F | FW_PARAMS_CMD_PFN_V(pf) | + FW_PARAMS_CMD_VFN_V(vf)); c.retval_len16 = htonl(FW_LEN16(c)); for (i = 0; i < nparams; i++, p += 2) *p = htonl(*params++); @@ -3290,10 +3291,10 @@ int t4_set_params_nosleep(struct adapter *adap, unsigned int mbox, return -EINVAL; memset(&c, 0, sizeof(c)); - c.op_to_vfn = cpu_to_be32(FW_CMD_OP(FW_PARAMS_CMD) | - FW_CMD_REQUEST | FW_CMD_WRITE | - FW_PARAMS_CMD_PFN(pf) | - FW_PARAMS_CMD_VFN(vf)); + c.op_to_vfn = cpu_to_be32(FW_CMD_OP_V(FW_PARAMS_CMD) | + FW_CMD_REQUEST_F | FW_CMD_WRITE_F | + FW_PARAMS_CMD_PFN_V(pf) | + FW_PARAMS_CMD_VFN_V(vf)); c.retval_len16 = cpu_to_be32(FW_LEN16(c)); while (nparams--) { @@ -3328,9 +3329,9 @@ int t4_set_params(struct adapter *adap, unsigned int mbox, unsigned int pf, return -EINVAL; memset(&c, 0, sizeof(c)); - c.op_to_vfn = htonl(FW_CMD_OP(FW_PARAMS_CMD) | FW_CMD_REQUEST | - FW_CMD_WRITE | FW_PARAMS_CMD_PFN(pf) | - FW_PARAMS_CMD_VFN(vf)); + c.op_to_vfn = htonl(FW_CMD_OP_V(FW_PARAMS_CMD) | FW_CMD_REQUEST_F | + FW_CMD_WRITE_F | FW_PARAMS_CMD_PFN_V(pf) | + FW_PARAMS_CMD_VFN_V(vf)); c.retval_len16 = htonl(FW_LEN16(c)); while (nparams--) { *p++ = htonl(*params++); @@ -3370,20 +3371,20 @@ int t4_cfg_pfvf(struct adapter *adap, unsigned int mbox, unsigned int pf, struct fw_pfvf_cmd c; memset(&c, 0, sizeof(c)); - c.op_to_vfn = htonl(FW_CMD_OP(FW_PFVF_CMD) | FW_CMD_REQUEST | - FW_CMD_WRITE | FW_PFVF_CMD_PFN(pf) | - FW_PFVF_CMD_VFN(vf)); + c.op_to_vfn = htonl(FW_CMD_OP_V(FW_PFVF_CMD) | FW_CMD_REQUEST_F | + FW_CMD_WRITE_F | FW_PFVF_CMD_PFN_V(pf) | + FW_PFVF_CMD_VFN_V(vf)); c.retval_len16 = htonl(FW_LEN16(c)); - c.niqflint_niq = htonl(FW_PFVF_CMD_NIQFLINT(rxqi) | - FW_PFVF_CMD_NIQ(rxq)); - c.type_to_neq = htonl(FW_PFVF_CMD_CMASK(cmask) | - FW_PFVF_CMD_PMASK(pmask) | - FW_PFVF_CMD_NEQ(txq)); - c.tc_to_nexactf = htonl(FW_PFVF_CMD_TC(tc) | FW_PFVF_CMD_NVI(vi) | - FW_PFVF_CMD_NEXACTF(nexact)); - c.r_caps_to_nethctrl = htonl(FW_PFVF_CMD_R_CAPS(rcaps) | - FW_PFVF_CMD_WX_CAPS(wxcaps) | - FW_PFVF_CMD_NETHCTRL(txq_eth_ctrl)); + c.niqflint_niq = htonl(FW_PFVF_CMD_NIQFLINT_V(rxqi) | + FW_PFVF_CMD_NIQ_V(rxq)); + c.type_to_neq = htonl(FW_PFVF_CMD_CMASK_V(cmask) | + FW_PFVF_CMD_PMASK_V(pmask) | + FW_PFVF_CMD_NEQ_V(txq)); + c.tc_to_nexactf = htonl(FW_PFVF_CMD_TC_V(tc) | FW_PFVF_CMD_NVI_V(vi) | + FW_PFVF_CMD_NEXACTF_V(nexact)); + c.r_caps_to_nethctrl = htonl(FW_PFVF_CMD_R_CAPS_V(rcaps) | + FW_PFVF_CMD_WX_CAPS_V(wxcaps) | + FW_PFVF_CMD_NETHCTRL_V(txq_eth_ctrl)); return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); } @@ -3412,11 +3413,11 @@ int t4_alloc_vi(struct adapter *adap, unsigned int mbox, unsigned int port, struct fw_vi_cmd c; memset(&c, 0, sizeof(c)); - c.op_to_vfn = htonl(FW_CMD_OP(FW_VI_CMD) | FW_CMD_REQUEST | - FW_CMD_WRITE | FW_CMD_EXEC | - FW_VI_CMD_PFN(pf) | FW_VI_CMD_VFN(vf)); - c.alloc_to_len16 = htonl(FW_VI_CMD_ALLOC | FW_LEN16(c)); - c.portid_pkd = FW_VI_CMD_PORTID(port); + c.op_to_vfn = htonl(FW_CMD_OP_V(FW_VI_CMD) | FW_CMD_REQUEST_F | + FW_CMD_WRITE_F | FW_CMD_EXEC_F | + FW_VI_CMD_PFN_V(pf) | FW_VI_CMD_VFN_V(vf)); + c.alloc_to_len16 = htonl(FW_VI_CMD_ALLOC_F | FW_LEN16(c)); + c.portid_pkd = FW_VI_CMD_PORTID_V(port); c.nmac = nmac - 1; ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c); @@ -3437,8 +3438,8 @@ int t4_alloc_vi(struct adapter *adap, unsigned int mbox, unsigned int port, } } if (rss_size) - *rss_size = FW_VI_CMD_RSSSIZE_GET(ntohs(c.rsssize_pkd)); - return FW_VI_CMD_VIID_GET(ntohs(c.type_viid)); + *rss_size = FW_VI_CMD_RSSSIZE_G(ntohs(c.rsssize_pkd)); + return FW_VI_CMD_VIID_G(ntohs(c.type_viid)); } /** @@ -3465,23 +3466,23 @@ int t4_set_rxmode(struct adapter *adap, unsigned int mbox, unsigned int viid, if (mtu < 0) mtu = FW_RXMODE_MTU_NO_CHG; if (promisc < 0) - promisc = FW_VI_RXMODE_CMD_PROMISCEN_MASK; + promisc = FW_VI_RXMODE_CMD_PROMISCEN_M; if (all_multi < 0) - all_multi = FW_VI_RXMODE_CMD_ALLMULTIEN_MASK; + all_multi = FW_VI_RXMODE_CMD_ALLMULTIEN_M; if (bcast < 0) - bcast = FW_VI_RXMODE_CMD_BROADCASTEN_MASK; + bcast = FW_VI_RXMODE_CMD_BROADCASTEN_M; if (vlanex < 0) - vlanex = FW_VI_RXMODE_CMD_VLANEXEN_MASK; + vlanex = FW_VI_RXMODE_CMD_VLANEXEN_M; memset(&c, 0, sizeof(c)); - c.op_to_viid = htonl(FW_CMD_OP(FW_VI_RXMODE_CMD) | FW_CMD_REQUEST | - FW_CMD_WRITE | FW_VI_RXMODE_CMD_VIID(viid)); + c.op_to_viid = htonl(FW_CMD_OP_V(FW_VI_RXMODE_CMD) | FW_CMD_REQUEST_F | + FW_CMD_WRITE_F | FW_VI_RXMODE_CMD_VIID_V(viid)); c.retval_len16 = htonl(FW_LEN16(c)); - c.mtu_to_vlanexen = htonl(FW_VI_RXMODE_CMD_MTU(mtu) | - FW_VI_RXMODE_CMD_PROMISCEN(promisc) | - FW_VI_RXMODE_CMD_ALLMULTIEN(all_multi) | - FW_VI_RXMODE_CMD_BROADCASTEN(bcast) | - FW_VI_RXMODE_CMD_VLANEXEN(vlanex)); + c.mtu_to_vlanexen = htonl(FW_VI_RXMODE_CMD_MTU_V(mtu) | + FW_VI_RXMODE_CMD_PROMISCEN_V(promisc) | + FW_VI_RXMODE_CMD_ALLMULTIEN_V(all_multi) | + FW_VI_RXMODE_CMD_BROADCASTEN_V(bcast) | + FW_VI_RXMODE_CMD_VLANEXEN_V(vlanex)); return t4_wr_mbox_meat(adap, mbox, &c, sizeof(c), NULL, sleep_ok); } @@ -3522,15 +3523,15 @@ int t4_alloc_mac_filt(struct adapter *adap, unsigned int mbox, return -EINVAL; memset(&c, 0, sizeof(c)); - c.op_to_viid = htonl(FW_CMD_OP(FW_VI_MAC_CMD) | FW_CMD_REQUEST | - FW_CMD_WRITE | (free ? FW_CMD_EXEC : 0) | - FW_VI_MAC_CMD_VIID(viid)); - c.freemacs_to_len16 = htonl(FW_VI_MAC_CMD_FREEMACS(free) | - FW_CMD_LEN16((naddr + 2) / 2)); + c.op_to_viid = htonl(FW_CMD_OP_V(FW_VI_MAC_CMD) | FW_CMD_REQUEST_F | + FW_CMD_WRITE_F | (free ? FW_CMD_EXEC_F : 0) | + FW_VI_MAC_CMD_VIID_V(viid)); + c.freemacs_to_len16 = htonl(FW_VI_MAC_CMD_FREEMACS_V(free) | + FW_CMD_LEN16_V((naddr + 2) / 2)); for (i = 0, p = c.u.exact; i < naddr; i++, p++) { - p->valid_to_idx = htons(FW_VI_MAC_CMD_VALID | - FW_VI_MAC_CMD_IDX(FW_VI_MAC_ADD_MAC)); + p->valid_to_idx = htons(FW_VI_MAC_CMD_VALID_F | + FW_VI_MAC_CMD_IDX_V(FW_VI_MAC_ADD_MAC)); memcpy(p->macaddr, addr[i], sizeof(p->macaddr)); } @@ -3539,7 +3540,7 @@ int t4_alloc_mac_filt(struct adapter *adap, unsigned int mbox, return ret; for (i = 0, p = c.u.exact; i < naddr; i++, p++) { - u16 index = FW_VI_MAC_CMD_IDX_GET(ntohs(p->valid_to_idx)); + u16 index = FW_VI_MAC_CMD_IDX_G(ntohs(p->valid_to_idx)); if (idx) idx[i] = index >= max_naddr ? 0xffff : index; @@ -3585,17 +3586,17 @@ int t4_change_mac(struct adapter *adap, unsigned int mbox, unsigned int viid, mode = add_smt ? FW_VI_MAC_SMT_AND_MPSTCAM : FW_VI_MAC_MPS_TCAM_ENTRY; memset(&c, 0, sizeof(c)); - c.op_to_viid = htonl(FW_CMD_OP(FW_VI_MAC_CMD) | FW_CMD_REQUEST | - FW_CMD_WRITE | FW_VI_MAC_CMD_VIID(viid)); - c.freemacs_to_len16 = htonl(FW_CMD_LEN16(1)); - p->valid_to_idx = htons(FW_VI_MAC_CMD_VALID | - FW_VI_MAC_CMD_SMAC_RESULT(mode) | - FW_VI_MAC_CMD_IDX(idx)); + c.op_to_viid = htonl(FW_CMD_OP_V(FW_VI_MAC_CMD) | FW_CMD_REQUEST_F | + FW_CMD_WRITE_F | FW_VI_MAC_CMD_VIID_V(viid)); + c.freemacs_to_len16 = htonl(FW_CMD_LEN16_V(1)); + p->valid_to_idx = htons(FW_VI_MAC_CMD_VALID_F | + FW_VI_MAC_CMD_SMAC_RESULT_V(mode) | + FW_VI_MAC_CMD_IDX_V(idx)); memcpy(p->macaddr, addr, sizeof(p->macaddr)); ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c); if (ret == 0) { - ret = FW_VI_MAC_CMD_IDX_GET(ntohs(p->valid_to_idx)); + ret = FW_VI_MAC_CMD_IDX_G(ntohs(p->valid_to_idx)); if (ret >= max_mac_addr) ret = -ENOMEM; } @@ -3619,11 +3620,11 @@ int t4_set_addr_hash(struct adapter *adap, unsigned int mbox, unsigned int viid, struct fw_vi_mac_cmd c; memset(&c, 0, sizeof(c)); - c.op_to_viid = htonl(FW_CMD_OP(FW_VI_MAC_CMD) | FW_CMD_REQUEST | - FW_CMD_WRITE | FW_VI_ENABLE_CMD_VIID(viid)); - c.freemacs_to_len16 = htonl(FW_VI_MAC_CMD_HASHVECEN | - FW_VI_MAC_CMD_HASHUNIEN(ucast) | - FW_CMD_LEN16(1)); + c.op_to_viid = htonl(FW_CMD_OP_V(FW_VI_MAC_CMD) | FW_CMD_REQUEST_F | + FW_CMD_WRITE_F | FW_VI_ENABLE_CMD_VIID_V(viid)); + c.freemacs_to_len16 = htonl(FW_VI_MAC_CMD_HASHVECEN_F | + FW_VI_MAC_CMD_HASHUNIEN_V(ucast) | + FW_CMD_LEN16_V(1)); c.u.hash.hashvec = cpu_to_be64(vec); return t4_wr_mbox_meat(adap, mbox, &c, sizeof(c), NULL, sleep_ok); } @@ -3646,12 +3647,12 @@ int t4_enable_vi_params(struct adapter *adap, unsigned int mbox, struct fw_vi_enable_cmd c; memset(&c, 0, sizeof(c)); - c.op_to_viid = htonl(FW_CMD_OP(FW_VI_ENABLE_CMD) | FW_CMD_REQUEST | - FW_CMD_EXEC | FW_VI_ENABLE_CMD_VIID(viid)); + c.op_to_viid = htonl(FW_CMD_OP_V(FW_VI_ENABLE_CMD) | FW_CMD_REQUEST_F | + FW_CMD_EXEC_F | FW_VI_ENABLE_CMD_VIID_V(viid)); - c.ien_to_len16 = htonl(FW_VI_ENABLE_CMD_IEN(rx_en) | - FW_VI_ENABLE_CMD_EEN(tx_en) | FW_LEN16(c) | - FW_VI_ENABLE_CMD_DCB_INFO(dcb_en)); + c.ien_to_len16 = htonl(FW_VI_ENABLE_CMD_IEN_V(rx_en) | + FW_VI_ENABLE_CMD_EEN_V(tx_en) | FW_LEN16(c) | + FW_VI_ENABLE_CMD_DCB_INFO_V(dcb_en)); return t4_wr_mbox_ns(adap, mbox, &c, sizeof(c), NULL); } @@ -3686,9 +3687,9 @@ int t4_identify_port(struct adapter *adap, unsigned int mbox, unsigned int viid, struct fw_vi_enable_cmd c; memset(&c, 0, sizeof(c)); - c.op_to_viid = htonl(FW_CMD_OP(FW_VI_ENABLE_CMD) | FW_CMD_REQUEST | - FW_CMD_EXEC | FW_VI_ENABLE_CMD_VIID(viid)); - c.ien_to_len16 = htonl(FW_VI_ENABLE_CMD_LED | FW_LEN16(c)); + c.op_to_viid = htonl(FW_CMD_OP_V(FW_VI_ENABLE_CMD) | FW_CMD_REQUEST_F | + FW_CMD_EXEC_F | FW_VI_ENABLE_CMD_VIID_V(viid)); + c.ien_to_len16 = htonl(FW_VI_ENABLE_CMD_LED_F | FW_LEN16(c)); c.blinkdur = htons(nblinks); return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); } @@ -3713,11 +3714,11 @@ int t4_iq_free(struct adapter *adap, unsigned int mbox, unsigned int pf, struct fw_iq_cmd c; memset(&c, 0, sizeof(c)); - c.op_to_vfn = htonl(FW_CMD_OP(FW_IQ_CMD) | FW_CMD_REQUEST | - FW_CMD_EXEC | FW_IQ_CMD_PFN(pf) | - FW_IQ_CMD_VFN(vf)); - c.alloc_to_len16 = htonl(FW_IQ_CMD_FREE | FW_LEN16(c)); - c.type_to_iqandstindex = htonl(FW_IQ_CMD_TYPE(iqtype)); + c.op_to_vfn = htonl(FW_CMD_OP_V(FW_IQ_CMD) | FW_CMD_REQUEST_F | + FW_CMD_EXEC_F | FW_IQ_CMD_PFN_V(pf) | + FW_IQ_CMD_VFN_V(vf)); + c.alloc_to_len16 = htonl(FW_IQ_CMD_FREE_F | FW_LEN16(c)); + c.type_to_iqandstindex = htonl(FW_IQ_CMD_TYPE_V(iqtype)); c.iqid = htons(iqid); c.fl0id = htons(fl0id); c.fl1id = htons(fl1id); @@ -3740,11 +3741,11 @@ int t4_eth_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf, struct fw_eq_eth_cmd c; memset(&c, 0, sizeof(c)); - c.op_to_vfn = htonl(FW_CMD_OP(FW_EQ_ETH_CMD) | FW_CMD_REQUEST | - FW_CMD_EXEC | FW_EQ_ETH_CMD_PFN(pf) | - FW_EQ_ETH_CMD_VFN(vf)); - c.alloc_to_len16 = htonl(FW_EQ_ETH_CMD_FREE | FW_LEN16(c)); - c.eqid_pkd = htonl(FW_EQ_ETH_CMD_EQID(eqid)); + c.op_to_vfn = htonl(FW_CMD_OP_V(FW_EQ_ETH_CMD) | FW_CMD_REQUEST_F | + FW_CMD_EXEC_F | FW_EQ_ETH_CMD_PFN_V(pf) | + FW_EQ_ETH_CMD_VFN_V(vf)); + c.alloc_to_len16 = htonl(FW_EQ_ETH_CMD_FREE_F | FW_LEN16(c)); + c.eqid_pkd = htonl(FW_EQ_ETH_CMD_EQID_V(eqid)); return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); } @@ -3764,11 +3765,11 @@ int t4_ctrl_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf, struct fw_eq_ctrl_cmd c; memset(&c, 0, sizeof(c)); - c.op_to_vfn = htonl(FW_CMD_OP(FW_EQ_CTRL_CMD) | FW_CMD_REQUEST | - FW_CMD_EXEC | FW_EQ_CTRL_CMD_PFN(pf) | - FW_EQ_CTRL_CMD_VFN(vf)); - c.alloc_to_len16 = htonl(FW_EQ_CTRL_CMD_FREE | FW_LEN16(c)); - c.cmpliqid_eqid = htonl(FW_EQ_CTRL_CMD_EQID(eqid)); + c.op_to_vfn = htonl(FW_CMD_OP_V(FW_EQ_CTRL_CMD) | FW_CMD_REQUEST_F | + FW_CMD_EXEC_F | FW_EQ_CTRL_CMD_PFN_V(pf) | + FW_EQ_CTRL_CMD_VFN_V(vf)); + c.alloc_to_len16 = htonl(FW_EQ_CTRL_CMD_FREE_F | FW_LEN16(c)); + c.cmpliqid_eqid = htonl(FW_EQ_CTRL_CMD_EQID_V(eqid)); return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); } @@ -3788,11 +3789,11 @@ int t4_ofld_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf, struct fw_eq_ofld_cmd c; memset(&c, 0, sizeof(c)); - c.op_to_vfn = htonl(FW_CMD_OP(FW_EQ_OFLD_CMD) | FW_CMD_REQUEST | - FW_CMD_EXEC | FW_EQ_OFLD_CMD_PFN(pf) | - FW_EQ_OFLD_CMD_VFN(vf)); - c.alloc_to_len16 = htonl(FW_EQ_OFLD_CMD_FREE | FW_LEN16(c)); - c.eqid_pkd = htonl(FW_EQ_OFLD_CMD_EQID(eqid)); + c.op_to_vfn = htonl(FW_CMD_OP_V(FW_EQ_OFLD_CMD) | FW_CMD_REQUEST_F | + FW_CMD_EXEC_F | FW_EQ_OFLD_CMD_PFN_V(pf) | + FW_EQ_OFLD_CMD_VFN_V(vf)); + c.alloc_to_len16 = htonl(FW_EQ_OFLD_CMD_FREE_F | FW_LEN16(c)); + c.eqid_pkd = htonl(FW_EQ_OFLD_CMD_EQID_V(eqid)); return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); } @@ -3810,25 +3811,25 @@ int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl) if (opcode == FW_PORT_CMD) { /* link/module state change message */ int speed = 0, fc = 0; const struct fw_port_cmd *p = (void *)rpl; - int chan = FW_PORT_CMD_PORTID_GET(ntohl(p->op_to_portid)); + int chan = FW_PORT_CMD_PORTID_G(ntohl(p->op_to_portid)); int port = adap->chan_map[chan]; struct port_info *pi = adap2pinfo(adap, port); struct link_config *lc = &pi->link_cfg; u32 stat = ntohl(p->u.info.lstatus_to_modtype); - int link_ok = (stat & FW_PORT_CMD_LSTATUS) != 0; - u32 mod = FW_PORT_CMD_MODTYPE_GET(stat); + int link_ok = (stat & FW_PORT_CMD_LSTATUS_F) != 0; + u32 mod = FW_PORT_CMD_MODTYPE_G(stat); - if (stat & FW_PORT_CMD_RXPAUSE) + if (stat & FW_PORT_CMD_RXPAUSE_F) fc |= PAUSE_RX; - if (stat & FW_PORT_CMD_TXPAUSE) + if (stat & FW_PORT_CMD_TXPAUSE_F) fc |= PAUSE_TX; - if (stat & FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_100M)) + if (stat & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_100M)) speed = 100; - else if (stat & FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_1G)) + else if (stat & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_1G)) speed = 1000; - else if (stat & FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_10G)) + else if (stat & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_10G)) speed = 10000; - else if (stat & FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_40G)) + else if (stat & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_40G)) speed = 40000; if (link_ok != lc->link_ok || speed != lc->speed || @@ -4121,11 +4122,11 @@ int t4_port_init(struct adapter *adap, int mbox, int pf, int vf) while ((adap->params.portvec & (1 << j)) == 0) j++; - c.op_to_portid = htonl(FW_CMD_OP(FW_PORT_CMD) | - FW_CMD_REQUEST | FW_CMD_READ | - FW_PORT_CMD_PORTID(j)); + c.op_to_portid = htonl(FW_CMD_OP_V(FW_PORT_CMD) | + FW_CMD_REQUEST_F | FW_CMD_READ_F | + FW_PORT_CMD_PORTID_V(j)); c.action_to_len16 = htonl( - FW_PORT_CMD_ACTION(FW_PORT_ACTION_GET_PORT_INFO) | + FW_PORT_CMD_ACTION_V(FW_PORT_ACTION_GET_PORT_INFO) | FW_LEN16(c)); ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c); if (ret) @@ -4143,13 +4144,13 @@ int t4_port_init(struct adapter *adap, int mbox, int pf, int vf) adap->port[i]->dev_port = j; ret = ntohl(c.u.info.lstatus_to_modtype); - p->mdio_addr = (ret & FW_PORT_CMD_MDIOCAP) ? - FW_PORT_CMD_MDIOADDR_GET(ret) : -1; - p->port_type = FW_PORT_CMD_PTYPE_GET(ret); + p->mdio_addr = (ret & FW_PORT_CMD_MDIOCAP_F) ? + FW_PORT_CMD_MDIOADDR_G(ret) : -1; + p->port_type = FW_PORT_CMD_PTYPE_G(ret); p->mod_type = FW_PORT_MOD_TYPE_NA; - rvc.op_to_viid = htonl(FW_CMD_OP(FW_RSS_VI_CONFIG_CMD) | - FW_CMD_REQUEST | FW_CMD_READ | + rvc.op_to_viid = htonl(FW_CMD_OP_V(FW_RSS_VI_CONFIG_CMD) | + FW_CMD_REQUEST_F | FW_CMD_READ_F | FW_RSS_VI_CONFIG_CMD_VIID(p->viid)); rvc.retval_len16 = htonl(FW_LEN16(rvc)); ret = t4_wr_mbox(adap, mbox, &rvc, sizeof(rvc), &rvc); diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h index 5f4db2398c71..0f89f68948ab 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h @@ -205,16 +205,62 @@ struct work_request_hdr { #define WR_HDR struct work_request_hdr wr /* option 0 fields */ -#define S_MSS_IDX 60 -#define M_MSS_IDX 0xF -#define V_MSS_IDX(x) ((__u64)(x) << S_MSS_IDX) -#define G_MSS_IDX(x) (((x) >> S_MSS_IDX) & M_MSS_IDX) +#define TX_CHAN_S 2 +#define TX_CHAN_V(x) ((x) << TX_CHAN_S) + +#define ULP_MODE_S 8 +#define ULP_MODE_V(x) ((x) << ULP_MODE_S) + +#define RCV_BUFSIZ_S 12 +#define RCV_BUFSIZ_M 0x3FFU +#define RCV_BUFSIZ_V(x) ((x) << RCV_BUFSIZ_S) + +#define SMAC_SEL_S 28 +#define SMAC_SEL_V(x) ((__u64)(x) << SMAC_SEL_S) + +#define L2T_IDX_S 36 +#define L2T_IDX_V(x) ((__u64)(x) << L2T_IDX_S) + +#define WND_SCALE_S 50 +#define WND_SCALE_V(x) ((__u64)(x) << WND_SCALE_S) + +#define KEEP_ALIVE_S 54 +#define KEEP_ALIVE_V(x) ((__u64)(x) << KEEP_ALIVE_S) +#define KEEP_ALIVE_F KEEP_ALIVE_V(1ULL) + +#define MSS_IDX_S 60 +#define MSS_IDX_M 0xF +#define MSS_IDX_V(x) ((__u64)(x) << MSS_IDX_S) +#define MSS_IDX_G(x) (((x) >> MSS_IDX_S) & MSS_IDX_M) /* option 2 fields */ -#define S_RSS_QUEUE 0 -#define M_RSS_QUEUE 0x3FF -#define V_RSS_QUEUE(x) ((x) << S_RSS_QUEUE) -#define G_RSS_QUEUE(x) (((x) >> S_RSS_QUEUE) & M_RSS_QUEUE) +#define RSS_QUEUE_S 0 +#define RSS_QUEUE_M 0x3FF +#define RSS_QUEUE_V(x) ((x) << RSS_QUEUE_S) +#define RSS_QUEUE_G(x) (((x) >> RSS_QUEUE_S) & RSS_QUEUE_M) + +#define RSS_QUEUE_VALID_S 10 +#define RSS_QUEUE_VALID_V(x) ((x) << RSS_QUEUE_VALID_S) +#define RSS_QUEUE_VALID_F RSS_QUEUE_VALID_V(1U) + +#define RX_FC_DISABLE_S 20 +#define RX_FC_DISABLE_V(x) ((x) << RX_FC_DISABLE_S) +#define RX_FC_DISABLE_F RX_FC_DISABLE_V(1U) + +#define RX_FC_VALID_S 22 +#define RX_FC_VALID_V(x) ((x) << RX_FC_VALID_S) +#define RX_FC_VALID_F RX_FC_VALID_V(1U) + +#define RX_CHANNEL_S 26 +#define RX_CHANNEL_V(x) ((x) << RX_CHANNEL_S) + +#define WND_SCALE_EN_S 28 +#define WND_SCALE_EN_V(x) ((x) << WND_SCALE_EN_S) +#define WND_SCALE_EN_F WND_SCALE_EN_V(1U) + +#define T5_OPT_2_VALID_S 31 +#define T5_OPT_2_VALID_V(x) ((x) << T5_OPT_2_VALID_S) +#define T5_OPT_2_VALID_F T5_OPT_2_VALID_V(1U) struct cpl_pass_open_req { WR_HDR; @@ -224,20 +270,11 @@ struct cpl_pass_open_req { __be32 local_ip; __be32 peer_ip; __be64 opt0; -#define TX_CHAN(x) ((x) << 2) #define NO_CONG(x) ((x) << 4) #define DELACK(x) ((x) << 5) -#define ULP_MODE(x) ((x) << 8) -#define RCV_BUFSIZ(x) ((x) << 12) -#define RCV_BUFSIZ_MASK 0x3FFU #define DSCP(x) ((x) << 22) -#define SMAC_SEL(x) ((u64)(x) << 28) -#define L2T_IDX(x) ((u64)(x) << 36) #define TCAM_BYPASS(x) ((u64)(x) << 48) #define NAGLE(x) ((u64)(x) << 49) -#define WND_SCALE(x) ((u64)(x) << 50) -#define KEEP_ALIVE(x) ((u64)(x) << 54) -#define MSS_IDX(x) ((u64)(x) << 60) __be64 opt1; #define SYN_RSS_ENABLE (1 << 0) #define SYN_RSS_QUEUE(x) ((x) << 2) @@ -267,20 +304,13 @@ struct cpl_pass_accept_rpl { WR_HDR; union opcode_tid ot; __be32 opt2; -#define RSS_QUEUE(x) ((x) << 0) -#define RSS_QUEUE_VALID (1 << 10) #define RX_COALESCE_VALID(x) ((x) << 11) #define RX_COALESCE(x) ((x) << 12) #define PACE(x) ((x) << 16) -#define RX_FC_VALID ((1U) << 19) -#define RX_FC_DISABLE ((1U) << 20) #define TX_QUEUE(x) ((x) << 23) -#define RX_CHANNEL(x) ((x) << 26) #define CCTRL_ECN(x) ((x) << 27) -#define WND_SCALE_EN(x) ((x) << 28) #define TSTAMPS_EN(x) ((x) << 29) #define SACK_EN(x) ((x) << 30) -#define T5_OPT_2_VALID ((1U) << 31) __be64 opt0; }; @@ -305,10 +335,10 @@ struct cpl_act_open_req { __be32 opt2; }; -#define S_FILTER_TUPLE 24 -#define M_FILTER_TUPLE 0xFFFFFFFFFF -#define V_FILTER_TUPLE(x) ((x) << S_FILTER_TUPLE) -#define G_FILTER_TUPLE(x) (((x) >> S_FILTER_TUPLE) & M_FILTER_TUPLE) +#define FILTER_TUPLE_S 24 +#define FILTER_TUPLE_M 0xFFFFFFFFFF +#define FILTER_TUPLE_V(x) ((x) << FILTER_TUPLE_S) +#define FILTER_TUPLE_G(x) (((x) >> FILTER_TUPLE_S) & FILTER_TUPLE_M) struct cpl_t5_act_open_req { WR_HDR; union opcode_tid ot; @@ -579,10 +609,16 @@ struct cpl_rx_data_ack { WR_HDR; union opcode_tid ot; __be32 credit_dack; -#define RX_CREDITS(x) ((x) << 0) -#define RX_FORCE_ACK(x) ((x) << 28) }; +/* cpl_rx_data_ack.ack_seq fields */ +#define RX_CREDITS_S 0 +#define RX_CREDITS_V(x) ((x) << RX_CREDITS_S) + +#define RX_FORCE_ACK_S 28 +#define RX_FORCE_ACK_V(x) ((x) << RX_FORCE_ACK_S) +#define RX_FORCE_ACK_F RX_FORCE_ACK_V(1U) + struct cpl_rx_pkt { struct rss_header rsshdr; u8 opcode; @@ -803,6 +839,9 @@ enum { ULP_TX_SC_ISGL = 0x83 }; +#define ULPTX_CMD_S 24 +#define ULPTX_CMD_V(x) ((x) << ULPTX_CMD_S) + struct ulptx_sge_pair { __be32 len[2]; __be64 addr[2]; @@ -810,7 +849,6 @@ struct ulptx_sge_pair { struct ulptx_sgl { __be32 cmd_nsge; -#define ULPTX_CMD(x) ((x) << 24) #define ULPTX_NSGE(x) ((x) << 0) #define ULPTX_MORE (1U << 23) __be32 len0; @@ -821,15 +859,21 @@ struct ulptx_sgl { struct ulp_mem_io { WR_HDR; __be32 cmd; -#define ULP_MEMIO_ORDER(x) ((x) << 23) __be32 len16; /* command length */ __be32 dlen; /* data length in 32-byte units */ -#define ULP_MEMIO_DATA_LEN(x) ((x) << 0) __be32 lock_addr; -#define ULP_MEMIO_ADDR(x) ((x) << 0) #define ULP_MEMIO_LOCK(x) ((x) << 31) }; +/* additional ulp_mem_io.cmd fields */ +#define ULP_MEMIO_ORDER_S 23 +#define ULP_MEMIO_ORDER_V(x) ((x) << ULP_MEMIO_ORDER_S) +#define ULP_MEMIO_ORDER_F ULP_MEMIO_ORDER_V(1U) + +#define T5_ULP_MEMIO_IMM_S 23 +#define T5_ULP_MEMIO_IMM_V(x) ((x) << T5_ULP_MEMIO_IMM_S) +#define T5_ULP_MEMIO_IMM_F T5_ULP_MEMIO_IMM_V(1U) + #define S_T5_ULP_MEMIO_IMM 23 #define V_T5_ULP_MEMIO_IMM(x) ((x) << S_T5_ULP_MEMIO_IMM) #define F_T5_ULP_MEMIO_IMM V_T5_ULP_MEMIO_IMM(1U) @@ -838,4 +882,12 @@ struct ulp_mem_io { #define V_T5_ULP_MEMIO_ORDER(x) ((x) << S_T5_ULP_MEMIO_ORDER) #define F_T5_ULP_MEMIO_ORDER V_T5_ULP_MEMIO_ORDER(1U) +/* ulp_mem_io.lock_addr fields */ +#define ULP_MEMIO_ADDR_S 0 +#define ULP_MEMIO_ADDR_V(x) ((x) << ULP_MEMIO_ADDR_S) + +/* ulp_mem_io.dlen fields */ +#define ULP_MEMIO_DATA_LEN_S 0 +#define ULP_MEMIO_DATA_LEN_V(x) ((x) << ULP_MEMIO_DATA_LEN_S) + #endif /* __T4_MSG_H */ diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_pci_id_tbl.h b/drivers/net/ethernet/chelsio/cxgb4/t4_pci_id_tbl.h new file mode 100644 index 000000000000..9e4f95a91fb4 --- /dev/null +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_pci_id_tbl.h @@ -0,0 +1,160 @@ +/* + * This file is part of the Chelsio T4/T5 Ethernet driver for Linux. + * + * Copyright (c) 2003-2014 Chelsio Communications, Inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef __T4_PCI_ID_TBL_H__ +#define __T4_PCI_ID_TBL_H__ + +/* The code can defined cpp macros for creating a PCI Device ID Table. This is + * useful because it allows the PCI ID Table to be maintained in a single place. + * + * The macros are: + * + * CH_PCI_DEVICE_ID_TABLE_DEFINE_BEGIN + * -- Used to start the definition of the PCI ID Table. + * + * CH_PCI_DEVICE_ID_FUNCTION + * -- The PCI Function Number to use in the PCI Device ID Table. "0" + * -- for drivers attaching to PF0-3, "4" for drivers attaching to PF4, + * -- "8" for drivers attaching to SR-IOV Virtual Functions, etc. + * + * CH_PCI_DEVICE_ID_FUNCTION2 [optional] + * -- If defined, create a PCI Device ID Table with both + * -- CH_PCI_DEVICE_ID_FUNCTION and CH_PCI_DEVICE_ID_FUNCTION2 populated. + * + * CH_PCI_ID_TABLE_ENTRY(DeviceID) + * -- Used for the individual PCI Device ID entries. Note that we will + * -- be adding a trailing comma (",") after all of the entries (and + * -- between the pairs of entries if CH_PCI_DEVICE_ID_FUNCTION2 is defined). + * + * CH_PCI_DEVICE_ID_TABLE_DEFINE_END + * -- Used to finish the definition of the PCI ID Table. Note that we + * -- will be adding a trailing semi-colon (";") here. + */ +#ifdef CH_PCI_DEVICE_ID_TABLE_DEFINE_BEGIN + +#ifndef CH_PCI_DEVICE_ID_FUNCTION +#error CH_PCI_DEVICE_ID_FUNCTION not defined! +#endif +#ifndef CH_PCI_ID_TABLE_ENTRY +#error CH_PCI_ID_TABLE_ENTRY not defined! +#endif +#ifndef CH_PCI_DEVICE_ID_TABLE_DEFINE_END +#error CH_PCI_DEVICE_ID_TABLE_DEFINE_END not defined! +#endif + +/* T4 and later ASICs use a PCI Device ID scheme of 0xVFPP where: + * + * V = "4" for T4; "5" for T5, etc. + * F = "0" for PF 0..3; "4".."7" for PF4..7; and "8" for VFs + * PP = adapter product designation + * + * We use this consistency in order to create the proper PCI Device IDs + * for the specified CH_PCI_DEVICE_ID_FUNCTION. + */ +#ifndef CH_PCI_DEVICE_ID_FUNCTION2 +#define CH_PCI_ID_TABLE_FENTRY(devid) \ + CH_PCI_ID_TABLE_ENTRY((devid) | \ + ((CH_PCI_DEVICE_ID_FUNCTION) << 8)) +#else +#define CH_PCI_ID_TABLE_FENTRY(devid) \ + CH_PCI_ID_TABLE_ENTRY((devid) | \ + ((CH_PCI_DEVICE_ID_FUNCTION) << 8)), \ + CH_PCI_ID_TABLE_ENTRY((devid) | \ + ((CH_PCI_DEVICE_ID_FUNCTION2) << 8)) +#endif + +CH_PCI_DEVICE_ID_TABLE_DEFINE_BEGIN + /* T4 adapters: + */ + CH_PCI_ID_TABLE_FENTRY(0x4000), /* T440-dbg */ + CH_PCI_ID_TABLE_FENTRY(0x4001), /* T420-cr */ + CH_PCI_ID_TABLE_FENTRY(0x4002), /* T422-cr */ + CH_PCI_ID_TABLE_FENTRY(0x4003), /* T440-cr */ + CH_PCI_ID_TABLE_FENTRY(0x4004), /* T420-bch */ + CH_PCI_ID_TABLE_FENTRY(0x4005), /* T440-bch */ + CH_PCI_ID_TABLE_FENTRY(0x4006), /* T440-ch */ + CH_PCI_ID_TABLE_FENTRY(0x4007), /* T420-so */ + CH_PCI_ID_TABLE_FENTRY(0x4008), /* T420-cx */ + CH_PCI_ID_TABLE_FENTRY(0x4009), /* T420-bt */ + CH_PCI_ID_TABLE_FENTRY(0x400a), /* T404-bt */ + CH_PCI_ID_TABLE_FENTRY(0x400b), /* B420-sr */ + CH_PCI_ID_TABLE_FENTRY(0x400c), /* B404-bt */ + CH_PCI_ID_TABLE_FENTRY(0x400d), /* T480-cr */ + CH_PCI_ID_TABLE_FENTRY(0x400e), /* T440-LP-cr */ + CH_PCI_ID_TABLE_FENTRY(0x4080), /* Custom T480-cr */ + CH_PCI_ID_TABLE_FENTRY(0x4081), /* Custom T440-cr */ + CH_PCI_ID_TABLE_FENTRY(0x4082), /* Custom T420-cr */ + CH_PCI_ID_TABLE_FENTRY(0x4083), /* Custom T420-xaui */ + CH_PCI_ID_TABLE_FENTRY(0x4084), /* Custom T440-cr */ + CH_PCI_ID_TABLE_FENTRY(0x4085), /* Custom T420-cr */ + CH_PCI_ID_TABLE_FENTRY(0x4086), /* Custom T440-bt */ + CH_PCI_ID_TABLE_FENTRY(0x4087), /* Custom T440-cr */ + CH_PCI_ID_TABLE_FENTRY(0x4088), /* Custom T440 2-xaui, 2-xfi */ + + /* T5 adapters: + */ + CH_PCI_ID_TABLE_FENTRY(0x5000), /* T580-dbg */ + CH_PCI_ID_TABLE_FENTRY(0x5001), /* T520-cr */ + CH_PCI_ID_TABLE_FENTRY(0x5002), /* T522-cr */ + CH_PCI_ID_TABLE_FENTRY(0x5003), /* T540-cr */ + CH_PCI_ID_TABLE_FENTRY(0x5004), /* T520-bch */ + CH_PCI_ID_TABLE_FENTRY(0x5005), /* T540-bch */ + CH_PCI_ID_TABLE_FENTRY(0x5006), /* T540-ch */ + CH_PCI_ID_TABLE_FENTRY(0x5007), /* T520-so */ + CH_PCI_ID_TABLE_FENTRY(0x5008), /* T520-cx */ + CH_PCI_ID_TABLE_FENTRY(0x5009), /* T520-bt */ + CH_PCI_ID_TABLE_FENTRY(0x500a), /* T504-bt */ + CH_PCI_ID_TABLE_FENTRY(0x500b), /* B520-sr */ + CH_PCI_ID_TABLE_FENTRY(0x500c), /* B504-bt */ + CH_PCI_ID_TABLE_FENTRY(0x500d), /* T580-cr */ + CH_PCI_ID_TABLE_FENTRY(0x500e), /* T540-LP-cr */ + CH_PCI_ID_TABLE_FENTRY(0x5010), /* T580-LP-cr */ + CH_PCI_ID_TABLE_FENTRY(0x5011), /* T520-LL-cr */ + CH_PCI_ID_TABLE_FENTRY(0x5012), /* T560-cr */ + CH_PCI_ID_TABLE_FENTRY(0x5013), /* T580-chr */ + CH_PCI_ID_TABLE_FENTRY(0x5014), /* T580-so */ + CH_PCI_ID_TABLE_FENTRY(0x5015), /* T502-bt */ + CH_PCI_ID_TABLE_FENTRY(0x5080), /* Custom T540-cr */ + CH_PCI_ID_TABLE_FENTRY(0x5081), /* Custom T540-LL-cr */ + CH_PCI_ID_TABLE_FENTRY(0x5082), /* Custom T504-cr */ + CH_PCI_ID_TABLE_FENTRY(0x5083), /* Custom T540-LP-CR */ + CH_PCI_ID_TABLE_FENTRY(0x5084), /* Custom T580-cr */ + CH_PCI_ID_TABLE_FENTRY(0x5085), /* Custom 3x T580-CR */ + CH_PCI_ID_TABLE_FENTRY(0x5086), /* Custom 2x T580-CR */ + CH_PCI_ID_TABLE_FENTRY(0x5087), /* Custom T580-CR */ + CH_PCI_ID_TABLE_FENTRY(0x5088), /* Custom T570-CR */ +CH_PCI_DEVICE_ID_TABLE_DEFINE_END; + +#endif /* CH_PCI_DEVICE_ID_TABLE_DEFINE_BEGIN */ + +#endif /* __T4_PCI_ID_TBL_H__ */ diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h index 8d2de1006b08..ccdf8a7f4916 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h @@ -511,21 +511,62 @@ #define MC_BIST_STATUS_RDATA 0x7688 -#define MA_EDRAM0_BAR 0x77c0 -#define MA_EDRAM1_BAR 0x77c4 -#define EDRAM_SIZE_MASK 0xfffU -#define EDRAM_SIZE_GET(x) ((x) & EDRAM_SIZE_MASK) - -#define MA_EXT_MEMORY_BAR 0x77c8 -#define EXT_MEM_SIZE_MASK 0x00000fffU -#define EXT_MEM_SIZE_SHIFT 0 -#define EXT_MEM_SIZE_GET(x) (((x) & EXT_MEM_SIZE_MASK) >> EXT_MEM_SIZE_SHIFT) - -#define MA_TARGET_MEM_ENABLE 0x77d8 -#define EXT_MEM1_ENABLE 0x00000010U -#define EXT_MEM_ENABLE 0x00000004U -#define EDRAM1_ENABLE 0x00000002U -#define EDRAM0_ENABLE 0x00000001U +#define MA_EDRAM0_BAR_A 0x77c0 + +#define EDRAM0_SIZE_S 0 +#define EDRAM0_SIZE_M 0xfffU +#define EDRAM0_SIZE_V(x) ((x) << EDRAM0_SIZE_S) +#define EDRAM0_SIZE_G(x) (((x) >> EDRAM0_SIZE_S) & EDRAM0_SIZE_M) + +#define MA_EDRAM1_BAR_A 0x77c4 + +#define EDRAM1_SIZE_S 0 +#define EDRAM1_SIZE_M 0xfffU +#define EDRAM1_SIZE_V(x) ((x) << EDRAM1_SIZE_S) +#define EDRAM1_SIZE_G(x) (((x) >> EDRAM1_SIZE_S) & EDRAM1_SIZE_M) + +#define MA_EXT_MEMORY_BAR_A 0x77c8 + +#define EXT_MEM_SIZE_S 0 +#define EXT_MEM_SIZE_M 0xfffU +#define EXT_MEM_SIZE_V(x) ((x) << EXT_MEM_SIZE_S) +#define EXT_MEM_SIZE_G(x) (((x) >> EXT_MEM_SIZE_S) & EXT_MEM_SIZE_M) + +#define MA_EXT_MEMORY1_BAR_A 0x7808 + +#define EXT_MEM1_SIZE_S 0 +#define EXT_MEM1_SIZE_M 0xfffU +#define EXT_MEM1_SIZE_V(x) ((x) << EXT_MEM1_SIZE_S) +#define EXT_MEM1_SIZE_G(x) (((x) >> EXT_MEM1_SIZE_S) & EXT_MEM1_SIZE_M) + +#define MA_EXT_MEMORY0_BAR_A 0x77c8 + +#define EXT_MEM0_SIZE_S 0 +#define EXT_MEM0_SIZE_M 0xfffU +#define EXT_MEM0_SIZE_V(x) ((x) << EXT_MEM0_SIZE_S) +#define EXT_MEM0_SIZE_G(x) (((x) >> EXT_MEM0_SIZE_S) & EXT_MEM0_SIZE_M) + +#define MA_TARGET_MEM_ENABLE_A 0x77d8 + +#define EXT_MEM_ENABLE_S 2 +#define EXT_MEM_ENABLE_V(x) ((x) << EXT_MEM_ENABLE_S) +#define EXT_MEM_ENABLE_F EXT_MEM_ENABLE_V(1U) + +#define EDRAM1_ENABLE_S 1 +#define EDRAM1_ENABLE_V(x) ((x) << EDRAM1_ENABLE_S) +#define EDRAM1_ENABLE_F EDRAM1_ENABLE_V(1U) + +#define EDRAM0_ENABLE_S 0 +#define EDRAM0_ENABLE_V(x) ((x) << EDRAM0_ENABLE_S) +#define EDRAM0_ENABLE_F EDRAM0_ENABLE_V(1U) + +#define EXT_MEM1_ENABLE_S 4 +#define EXT_MEM1_ENABLE_V(x) ((x) << EXT_MEM1_ENABLE_S) +#define EXT_MEM1_ENABLE_F EXT_MEM1_ENABLE_V(1U) + +#define EXT_MEM0_ENABLE_S 2 +#define EXT_MEM0_ENABLE_V(x) ((x) << EXT_MEM0_ENABLE_S) +#define EXT_MEM0_ENABLE_F EXT_MEM0_ENABLE_V(1U) #define MA_INT_CAUSE 0x77e0 #define MEM_PERR_INT_CAUSE 0x00000002U @@ -542,7 +583,6 @@ #define MA_PARITY_ERROR_STATUS 0x77f4 #define MA_PARITY_ERROR_STATUS2 0x7804 -#define MA_EXT_MEMORY1_BAR 0x7808 #define EDC_0_BASE_ADDR 0x7900 #define EDC_BIST_CMD 0x7904 diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h index 3409756a85b9..beaf80a6214b 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h @@ -109,18 +109,49 @@ struct fw_wr_hdr { __be32 lo; }; -#define FW_WR_OP(x) ((x) << 24) -#define FW_WR_OP_GET(x) (((x) >> 24) & 0xff) -#define FW_WR_ATOMIC(x) ((x) << 23) -#define FW_WR_FLUSH(x) ((x) << 22) -#define FW_WR_COMPL(x) ((x) << 21) -#define FW_WR_IMMDLEN_MASK 0xff -#define FW_WR_IMMDLEN(x) ((x) << 0) - -#define FW_WR_EQUIQ (1U << 31) -#define FW_WR_EQUEQ (1U << 30) -#define FW_WR_FLOWID(x) ((x) << 8) -#define FW_WR_LEN16(x) ((x) << 0) +/* work request opcode (hi) */ +#define FW_WR_OP_S 24 +#define FW_WR_OP_M 0xff +#define FW_WR_OP_V(x) ((x) << FW_WR_OP_S) +#define FW_WR_OP_G(x) (((x) >> FW_WR_OP_S) & FW_WR_OP_M) + +/* atomic flag (hi) - firmware encapsulates CPLs in CPL_BARRIER */ +#define FW_WR_ATOMIC_S 23 +#define FW_WR_ATOMIC_V(x) ((x) << FW_WR_ATOMIC_S) + +/* flush flag (hi) - firmware flushes flushable work request buffered + * in the flow context. + */ +#define FW_WR_FLUSH_S 22 +#define FW_WR_FLUSH_V(x) ((x) << FW_WR_FLUSH_S) + +/* completion flag (hi) - firmware generates a cpl_fw6_ack */ +#define FW_WR_COMPL_S 21 +#define FW_WR_COMPL_V(x) ((x) << FW_WR_COMPL_S) +#define FW_WR_COMPL_F FW_WR_COMPL_V(1U) + +/* work request immediate data length (hi) */ +#define FW_WR_IMMDLEN_S 0 +#define FW_WR_IMMDLEN_M 0xff +#define FW_WR_IMMDLEN_V(x) ((x) << FW_WR_IMMDLEN_S) + +/* egress queue status update to associated ingress queue entry (lo) */ +#define FW_WR_EQUIQ_S 31 +#define FW_WR_EQUIQ_V(x) ((x) << FW_WR_EQUIQ_S) +#define FW_WR_EQUIQ_F FW_WR_EQUIQ_V(1U) + +/* egress queue status update to egress queue status entry (lo) */ +#define FW_WR_EQUEQ_S 30 +#define FW_WR_EQUEQ_V(x) ((x) << FW_WR_EQUEQ_S) +#define FW_WR_EQUEQ_F FW_WR_EQUEQ_V(1U) + +/* flow context identifier (lo) */ +#define FW_WR_FLOWID_S 8 +#define FW_WR_FLOWID_V(x) ((x) << FW_WR_FLOWID_S) + +/* length in units of 16-bytes (lo) */ +#define FW_WR_LEN16_S 0 +#define FW_WR_LEN16_V(x) ((x) << FW_WR_LEN16_S) #define HW_TPL_FR_MT_PR_IV_P_FC 0X32B #define HW_TPL_FR_MT_PR_OV_P_FC 0X327 @@ -166,239 +197,239 @@ struct fw_filter_wr { __u8 sma[6]; }; -#define S_FW_FILTER_WR_TID 12 -#define M_FW_FILTER_WR_TID 0xfffff -#define V_FW_FILTER_WR_TID(x) ((x) << S_FW_FILTER_WR_TID) -#define G_FW_FILTER_WR_TID(x) \ - (((x) >> S_FW_FILTER_WR_TID) & M_FW_FILTER_WR_TID) - -#define S_FW_FILTER_WR_RQTYPE 11 -#define M_FW_FILTER_WR_RQTYPE 0x1 -#define V_FW_FILTER_WR_RQTYPE(x) ((x) << S_FW_FILTER_WR_RQTYPE) -#define G_FW_FILTER_WR_RQTYPE(x) \ - (((x) >> S_FW_FILTER_WR_RQTYPE) & M_FW_FILTER_WR_RQTYPE) -#define F_FW_FILTER_WR_RQTYPE V_FW_FILTER_WR_RQTYPE(1U) - -#define S_FW_FILTER_WR_NOREPLY 10 -#define M_FW_FILTER_WR_NOREPLY 0x1 -#define V_FW_FILTER_WR_NOREPLY(x) ((x) << S_FW_FILTER_WR_NOREPLY) -#define G_FW_FILTER_WR_NOREPLY(x) \ - (((x) >> S_FW_FILTER_WR_NOREPLY) & M_FW_FILTER_WR_NOREPLY) -#define F_FW_FILTER_WR_NOREPLY V_FW_FILTER_WR_NOREPLY(1U) - -#define S_FW_FILTER_WR_IQ 0 -#define M_FW_FILTER_WR_IQ 0x3ff -#define V_FW_FILTER_WR_IQ(x) ((x) << S_FW_FILTER_WR_IQ) -#define G_FW_FILTER_WR_IQ(x) \ - (((x) >> S_FW_FILTER_WR_IQ) & M_FW_FILTER_WR_IQ) - -#define S_FW_FILTER_WR_DEL_FILTER 31 -#define M_FW_FILTER_WR_DEL_FILTER 0x1 -#define V_FW_FILTER_WR_DEL_FILTER(x) ((x) << S_FW_FILTER_WR_DEL_FILTER) -#define G_FW_FILTER_WR_DEL_FILTER(x) \ - (((x) >> S_FW_FILTER_WR_DEL_FILTER) & M_FW_FILTER_WR_DEL_FILTER) -#define F_FW_FILTER_WR_DEL_FILTER V_FW_FILTER_WR_DEL_FILTER(1U) - -#define S_FW_FILTER_WR_RPTTID 25 -#define M_FW_FILTER_WR_RPTTID 0x1 -#define V_FW_FILTER_WR_RPTTID(x) ((x) << S_FW_FILTER_WR_RPTTID) -#define G_FW_FILTER_WR_RPTTID(x) \ - (((x) >> S_FW_FILTER_WR_RPTTID) & M_FW_FILTER_WR_RPTTID) -#define F_FW_FILTER_WR_RPTTID V_FW_FILTER_WR_RPTTID(1U) - -#define S_FW_FILTER_WR_DROP 24 -#define M_FW_FILTER_WR_DROP 0x1 -#define V_FW_FILTER_WR_DROP(x) ((x) << S_FW_FILTER_WR_DROP) -#define G_FW_FILTER_WR_DROP(x) \ - (((x) >> S_FW_FILTER_WR_DROP) & M_FW_FILTER_WR_DROP) -#define F_FW_FILTER_WR_DROP V_FW_FILTER_WR_DROP(1U) - -#define S_FW_FILTER_WR_DIRSTEER 23 -#define M_FW_FILTER_WR_DIRSTEER 0x1 -#define V_FW_FILTER_WR_DIRSTEER(x) ((x) << S_FW_FILTER_WR_DIRSTEER) -#define G_FW_FILTER_WR_DIRSTEER(x) \ - (((x) >> S_FW_FILTER_WR_DIRSTEER) & M_FW_FILTER_WR_DIRSTEER) -#define F_FW_FILTER_WR_DIRSTEER V_FW_FILTER_WR_DIRSTEER(1U) - -#define S_FW_FILTER_WR_MASKHASH 22 -#define M_FW_FILTER_WR_MASKHASH 0x1 -#define V_FW_FILTER_WR_MASKHASH(x) ((x) << S_FW_FILTER_WR_MASKHASH) -#define G_FW_FILTER_WR_MASKHASH(x) \ - (((x) >> S_FW_FILTER_WR_MASKHASH) & M_FW_FILTER_WR_MASKHASH) -#define F_FW_FILTER_WR_MASKHASH V_FW_FILTER_WR_MASKHASH(1U) - -#define S_FW_FILTER_WR_DIRSTEERHASH 21 -#define M_FW_FILTER_WR_DIRSTEERHASH 0x1 -#define V_FW_FILTER_WR_DIRSTEERHASH(x) ((x) << S_FW_FILTER_WR_DIRSTEERHASH) -#define G_FW_FILTER_WR_DIRSTEERHASH(x) \ - (((x) >> S_FW_FILTER_WR_DIRSTEERHASH) & M_FW_FILTER_WR_DIRSTEERHASH) -#define F_FW_FILTER_WR_DIRSTEERHASH V_FW_FILTER_WR_DIRSTEERHASH(1U) - -#define S_FW_FILTER_WR_LPBK 20 -#define M_FW_FILTER_WR_LPBK 0x1 -#define V_FW_FILTER_WR_LPBK(x) ((x) << S_FW_FILTER_WR_LPBK) -#define G_FW_FILTER_WR_LPBK(x) \ - (((x) >> S_FW_FILTER_WR_LPBK) & M_FW_FILTER_WR_LPBK) -#define F_FW_FILTER_WR_LPBK V_FW_FILTER_WR_LPBK(1U) - -#define S_FW_FILTER_WR_DMAC 19 -#define M_FW_FILTER_WR_DMAC 0x1 -#define V_FW_FILTER_WR_DMAC(x) ((x) << S_FW_FILTER_WR_DMAC) -#define G_FW_FILTER_WR_DMAC(x) \ - (((x) >> S_FW_FILTER_WR_DMAC) & M_FW_FILTER_WR_DMAC) -#define F_FW_FILTER_WR_DMAC V_FW_FILTER_WR_DMAC(1U) - -#define S_FW_FILTER_WR_SMAC 18 -#define M_FW_FILTER_WR_SMAC 0x1 -#define V_FW_FILTER_WR_SMAC(x) ((x) << S_FW_FILTER_WR_SMAC) -#define G_FW_FILTER_WR_SMAC(x) \ - (((x) >> S_FW_FILTER_WR_SMAC) & M_FW_FILTER_WR_SMAC) -#define F_FW_FILTER_WR_SMAC V_FW_FILTER_WR_SMAC(1U) - -#define S_FW_FILTER_WR_INSVLAN 17 -#define M_FW_FILTER_WR_INSVLAN 0x1 -#define V_FW_FILTER_WR_INSVLAN(x) ((x) << S_FW_FILTER_WR_INSVLAN) -#define G_FW_FILTER_WR_INSVLAN(x) \ - (((x) >> S_FW_FILTER_WR_INSVLAN) & M_FW_FILTER_WR_INSVLAN) -#define F_FW_FILTER_WR_INSVLAN V_FW_FILTER_WR_INSVLAN(1U) - -#define S_FW_FILTER_WR_RMVLAN 16 -#define M_FW_FILTER_WR_RMVLAN 0x1 -#define V_FW_FILTER_WR_RMVLAN(x) ((x) << S_FW_FILTER_WR_RMVLAN) -#define G_FW_FILTER_WR_RMVLAN(x) \ - (((x) >> S_FW_FILTER_WR_RMVLAN) & M_FW_FILTER_WR_RMVLAN) -#define F_FW_FILTER_WR_RMVLAN V_FW_FILTER_WR_RMVLAN(1U) - -#define S_FW_FILTER_WR_HITCNTS 15 -#define M_FW_FILTER_WR_HITCNTS 0x1 -#define V_FW_FILTER_WR_HITCNTS(x) ((x) << S_FW_FILTER_WR_HITCNTS) -#define G_FW_FILTER_WR_HITCNTS(x) \ - (((x) >> S_FW_FILTER_WR_HITCNTS) & M_FW_FILTER_WR_HITCNTS) -#define F_FW_FILTER_WR_HITCNTS V_FW_FILTER_WR_HITCNTS(1U) - -#define S_FW_FILTER_WR_TXCHAN 13 -#define M_FW_FILTER_WR_TXCHAN 0x3 -#define V_FW_FILTER_WR_TXCHAN(x) ((x) << S_FW_FILTER_WR_TXCHAN) -#define G_FW_FILTER_WR_TXCHAN(x) \ - (((x) >> S_FW_FILTER_WR_TXCHAN) & M_FW_FILTER_WR_TXCHAN) - -#define S_FW_FILTER_WR_PRIO 12 -#define M_FW_FILTER_WR_PRIO 0x1 -#define V_FW_FILTER_WR_PRIO(x) ((x) << S_FW_FILTER_WR_PRIO) -#define G_FW_FILTER_WR_PRIO(x) \ - (((x) >> S_FW_FILTER_WR_PRIO) & M_FW_FILTER_WR_PRIO) -#define F_FW_FILTER_WR_PRIO V_FW_FILTER_WR_PRIO(1U) - -#define S_FW_FILTER_WR_L2TIX 0 -#define M_FW_FILTER_WR_L2TIX 0xfff -#define V_FW_FILTER_WR_L2TIX(x) ((x) << S_FW_FILTER_WR_L2TIX) -#define G_FW_FILTER_WR_L2TIX(x) \ - (((x) >> S_FW_FILTER_WR_L2TIX) & M_FW_FILTER_WR_L2TIX) - -#define S_FW_FILTER_WR_FRAG 7 -#define M_FW_FILTER_WR_FRAG 0x1 -#define V_FW_FILTER_WR_FRAG(x) ((x) << S_FW_FILTER_WR_FRAG) -#define G_FW_FILTER_WR_FRAG(x) \ - (((x) >> S_FW_FILTER_WR_FRAG) & M_FW_FILTER_WR_FRAG) -#define F_FW_FILTER_WR_FRAG V_FW_FILTER_WR_FRAG(1U) - -#define S_FW_FILTER_WR_FRAGM 6 -#define M_FW_FILTER_WR_FRAGM 0x1 -#define V_FW_FILTER_WR_FRAGM(x) ((x) << S_FW_FILTER_WR_FRAGM) -#define G_FW_FILTER_WR_FRAGM(x) \ - (((x) >> S_FW_FILTER_WR_FRAGM) & M_FW_FILTER_WR_FRAGM) -#define F_FW_FILTER_WR_FRAGM V_FW_FILTER_WR_FRAGM(1U) - -#define S_FW_FILTER_WR_IVLAN_VLD 5 -#define M_FW_FILTER_WR_IVLAN_VLD 0x1 -#define V_FW_FILTER_WR_IVLAN_VLD(x) ((x) << S_FW_FILTER_WR_IVLAN_VLD) -#define G_FW_FILTER_WR_IVLAN_VLD(x) \ - (((x) >> S_FW_FILTER_WR_IVLAN_VLD) & M_FW_FILTER_WR_IVLAN_VLD) -#define F_FW_FILTER_WR_IVLAN_VLD V_FW_FILTER_WR_IVLAN_VLD(1U) - -#define S_FW_FILTER_WR_OVLAN_VLD 4 -#define M_FW_FILTER_WR_OVLAN_VLD 0x1 -#define V_FW_FILTER_WR_OVLAN_VLD(x) ((x) << S_FW_FILTER_WR_OVLAN_VLD) -#define G_FW_FILTER_WR_OVLAN_VLD(x) \ - (((x) >> S_FW_FILTER_WR_OVLAN_VLD) & M_FW_FILTER_WR_OVLAN_VLD) -#define F_FW_FILTER_WR_OVLAN_VLD V_FW_FILTER_WR_OVLAN_VLD(1U) - -#define S_FW_FILTER_WR_IVLAN_VLDM 3 -#define M_FW_FILTER_WR_IVLAN_VLDM 0x1 -#define V_FW_FILTER_WR_IVLAN_VLDM(x) ((x) << S_FW_FILTER_WR_IVLAN_VLDM) -#define G_FW_FILTER_WR_IVLAN_VLDM(x) \ - (((x) >> S_FW_FILTER_WR_IVLAN_VLDM) & M_FW_FILTER_WR_IVLAN_VLDM) -#define F_FW_FILTER_WR_IVLAN_VLDM V_FW_FILTER_WR_IVLAN_VLDM(1U) - -#define S_FW_FILTER_WR_OVLAN_VLDM 2 -#define M_FW_FILTER_WR_OVLAN_VLDM 0x1 -#define V_FW_FILTER_WR_OVLAN_VLDM(x) ((x) << S_FW_FILTER_WR_OVLAN_VLDM) -#define G_FW_FILTER_WR_OVLAN_VLDM(x) \ - (((x) >> S_FW_FILTER_WR_OVLAN_VLDM) & M_FW_FILTER_WR_OVLAN_VLDM) -#define F_FW_FILTER_WR_OVLAN_VLDM V_FW_FILTER_WR_OVLAN_VLDM(1U) - -#define S_FW_FILTER_WR_RX_CHAN 15 -#define M_FW_FILTER_WR_RX_CHAN 0x1 -#define V_FW_FILTER_WR_RX_CHAN(x) ((x) << S_FW_FILTER_WR_RX_CHAN) -#define G_FW_FILTER_WR_RX_CHAN(x) \ - (((x) >> S_FW_FILTER_WR_RX_CHAN) & M_FW_FILTER_WR_RX_CHAN) -#define F_FW_FILTER_WR_RX_CHAN V_FW_FILTER_WR_RX_CHAN(1U) - -#define S_FW_FILTER_WR_RX_RPL_IQ 0 -#define M_FW_FILTER_WR_RX_RPL_IQ 0x3ff -#define V_FW_FILTER_WR_RX_RPL_IQ(x) ((x) << S_FW_FILTER_WR_RX_RPL_IQ) -#define G_FW_FILTER_WR_RX_RPL_IQ(x) \ - (((x) >> S_FW_FILTER_WR_RX_RPL_IQ) & M_FW_FILTER_WR_RX_RPL_IQ) - -#define S_FW_FILTER_WR_MACI 23 -#define M_FW_FILTER_WR_MACI 0x1ff -#define V_FW_FILTER_WR_MACI(x) ((x) << S_FW_FILTER_WR_MACI) -#define G_FW_FILTER_WR_MACI(x) \ - (((x) >> S_FW_FILTER_WR_MACI) & M_FW_FILTER_WR_MACI) - -#define S_FW_FILTER_WR_MACIM 14 -#define M_FW_FILTER_WR_MACIM 0x1ff -#define V_FW_FILTER_WR_MACIM(x) ((x) << S_FW_FILTER_WR_MACIM) -#define G_FW_FILTER_WR_MACIM(x) \ - (((x) >> S_FW_FILTER_WR_MACIM) & M_FW_FILTER_WR_MACIM) - -#define S_FW_FILTER_WR_FCOE 13 -#define M_FW_FILTER_WR_FCOE 0x1 -#define V_FW_FILTER_WR_FCOE(x) ((x) << S_FW_FILTER_WR_FCOE) -#define G_FW_FILTER_WR_FCOE(x) \ - (((x) >> S_FW_FILTER_WR_FCOE) & M_FW_FILTER_WR_FCOE) -#define F_FW_FILTER_WR_FCOE V_FW_FILTER_WR_FCOE(1U) - -#define S_FW_FILTER_WR_FCOEM 12 -#define M_FW_FILTER_WR_FCOEM 0x1 -#define V_FW_FILTER_WR_FCOEM(x) ((x) << S_FW_FILTER_WR_FCOEM) -#define G_FW_FILTER_WR_FCOEM(x) \ - (((x) >> S_FW_FILTER_WR_FCOEM) & M_FW_FILTER_WR_FCOEM) -#define F_FW_FILTER_WR_FCOEM V_FW_FILTER_WR_FCOEM(1U) - -#define S_FW_FILTER_WR_PORT 9 -#define M_FW_FILTER_WR_PORT 0x7 -#define V_FW_FILTER_WR_PORT(x) ((x) << S_FW_FILTER_WR_PORT) -#define G_FW_FILTER_WR_PORT(x) \ - (((x) >> S_FW_FILTER_WR_PORT) & M_FW_FILTER_WR_PORT) - -#define S_FW_FILTER_WR_PORTM 6 -#define M_FW_FILTER_WR_PORTM 0x7 -#define V_FW_FILTER_WR_PORTM(x) ((x) << S_FW_FILTER_WR_PORTM) -#define G_FW_FILTER_WR_PORTM(x) \ - (((x) >> S_FW_FILTER_WR_PORTM) & M_FW_FILTER_WR_PORTM) - -#define S_FW_FILTER_WR_MATCHTYPE 3 -#define M_FW_FILTER_WR_MATCHTYPE 0x7 -#define V_FW_FILTER_WR_MATCHTYPE(x) ((x) << S_FW_FILTER_WR_MATCHTYPE) -#define G_FW_FILTER_WR_MATCHTYPE(x) \ - (((x) >> S_FW_FILTER_WR_MATCHTYPE) & M_FW_FILTER_WR_MATCHTYPE) - -#define S_FW_FILTER_WR_MATCHTYPEM 0 -#define M_FW_FILTER_WR_MATCHTYPEM 0x7 -#define V_FW_FILTER_WR_MATCHTYPEM(x) ((x) << S_FW_FILTER_WR_MATCHTYPEM) -#define G_FW_FILTER_WR_MATCHTYPEM(x) \ - (((x) >> S_FW_FILTER_WR_MATCHTYPEM) & M_FW_FILTER_WR_MATCHTYPEM) +#define FW_FILTER_WR_TID_S 12 +#define FW_FILTER_WR_TID_M 0xfffff +#define FW_FILTER_WR_TID_V(x) ((x) << FW_FILTER_WR_TID_S) +#define FW_FILTER_WR_TID_G(x) \ + (((x) >> FW_FILTER_WR_TID_S) & FW_FILTER_WR_TID_M) + +#define FW_FILTER_WR_RQTYPE_S 11 +#define FW_FILTER_WR_RQTYPE_M 0x1 +#define FW_FILTER_WR_RQTYPE_V(x) ((x) << FW_FILTER_WR_RQTYPE_S) +#define FW_FILTER_WR_RQTYPE_G(x) \ + (((x) >> FW_FILTER_WR_RQTYPE_S) & FW_FILTER_WR_RQTYPE_M) +#define FW_FILTER_WR_RQTYPE_F FW_FILTER_WR_RQTYPE_V(1U) + +#define FW_FILTER_WR_NOREPLY_S 10 +#define FW_FILTER_WR_NOREPLY_M 0x1 +#define FW_FILTER_WR_NOREPLY_V(x) ((x) << FW_FILTER_WR_NOREPLY_S) +#define FW_FILTER_WR_NOREPLY_G(x) \ + (((x) >> FW_FILTER_WR_NOREPLY_S) & FW_FILTER_WR_NOREPLY_M) +#define FW_FILTER_WR_NOREPLY_F FW_FILTER_WR_NOREPLY_V(1U) + +#define FW_FILTER_WR_IQ_S 0 +#define FW_FILTER_WR_IQ_M 0x3ff +#define FW_FILTER_WR_IQ_V(x) ((x) << FW_FILTER_WR_IQ_S) +#define FW_FILTER_WR_IQ_G(x) \ + (((x) >> FW_FILTER_WR_IQ_S) & FW_FILTER_WR_IQ_M) + +#define FW_FILTER_WR_DEL_FILTER_S 31 +#define FW_FILTER_WR_DEL_FILTER_M 0x1 +#define FW_FILTER_WR_DEL_FILTER_V(x) ((x) << FW_FILTER_WR_DEL_FILTER_S) +#define FW_FILTER_WR_DEL_FILTER_G(x) \ + (((x) >> FW_FILTER_WR_DEL_FILTER_S) & FW_FILTER_WR_DEL_FILTER_M) +#define FW_FILTER_WR_DEL_FILTER_F FW_FILTER_WR_DEL_FILTER_V(1U) + +#define FW_FILTER_WR_RPTTID_S 25 +#define FW_FILTER_WR_RPTTID_M 0x1 +#define FW_FILTER_WR_RPTTID_V(x) ((x) << FW_FILTER_WR_RPTTID_S) +#define FW_FILTER_WR_RPTTID_G(x) \ + (((x) >> FW_FILTER_WR_RPTTID_S) & FW_FILTER_WR_RPTTID_M) +#define FW_FILTER_WR_RPTTID_F FW_FILTER_WR_RPTTID_V(1U) + +#define FW_FILTER_WR_DROP_S 24 +#define FW_FILTER_WR_DROP_M 0x1 +#define FW_FILTER_WR_DROP_V(x) ((x) << FW_FILTER_WR_DROP_S) +#define FW_FILTER_WR_DROP_G(x) \ + (((x) >> FW_FILTER_WR_DROP_S) & FW_FILTER_WR_DROP_M) +#define FW_FILTER_WR_DROP_F FW_FILTER_WR_DROP_V(1U) + +#define FW_FILTER_WR_DIRSTEER_S 23 +#define FW_FILTER_WR_DIRSTEER_M 0x1 +#define FW_FILTER_WR_DIRSTEER_V(x) ((x) << FW_FILTER_WR_DIRSTEER_S) +#define FW_FILTER_WR_DIRSTEER_G(x) \ + (((x) >> FW_FILTER_WR_DIRSTEER_S) & FW_FILTER_WR_DIRSTEER_M) +#define FW_FILTER_WR_DIRSTEER_F FW_FILTER_WR_DIRSTEER_V(1U) + +#define FW_FILTER_WR_MASKHASH_S 22 +#define FW_FILTER_WR_MASKHASH_M 0x1 +#define FW_FILTER_WR_MASKHASH_V(x) ((x) << FW_FILTER_WR_MASKHASH_S) +#define FW_FILTER_WR_MASKHASH_G(x) \ + (((x) >> FW_FILTER_WR_MASKHASH_S) & FW_FILTER_WR_MASKHASH_M) +#define FW_FILTER_WR_MASKHASH_F FW_FILTER_WR_MASKHASH_V(1U) + +#define FW_FILTER_WR_DIRSTEERHASH_S 21 +#define FW_FILTER_WR_DIRSTEERHASH_M 0x1 +#define FW_FILTER_WR_DIRSTEERHASH_V(x) ((x) << FW_FILTER_WR_DIRSTEERHASH_S) +#define FW_FILTER_WR_DIRSTEERHASH_G(x) \ + (((x) >> FW_FILTER_WR_DIRSTEERHASH_S) & FW_FILTER_WR_DIRSTEERHASH_M) +#define FW_FILTER_WR_DIRSTEERHASH_F FW_FILTER_WR_DIRSTEERHASH_V(1U) + +#define FW_FILTER_WR_LPBK_S 20 +#define FW_FILTER_WR_LPBK_M 0x1 +#define FW_FILTER_WR_LPBK_V(x) ((x) << FW_FILTER_WR_LPBK_S) +#define FW_FILTER_WR_LPBK_G(x) \ + (((x) >> FW_FILTER_WR_LPBK_S) & FW_FILTER_WR_LPBK_M) +#define FW_FILTER_WR_LPBK_F FW_FILTER_WR_LPBK_V(1U) + +#define FW_FILTER_WR_DMAC_S 19 +#define FW_FILTER_WR_DMAC_M 0x1 +#define FW_FILTER_WR_DMAC_V(x) ((x) << FW_FILTER_WR_DMAC_S) +#define FW_FILTER_WR_DMAC_G(x) \ + (((x) >> FW_FILTER_WR_DMAC_S) & FW_FILTER_WR_DMAC_M) +#define FW_FILTER_WR_DMAC_F FW_FILTER_WR_DMAC_V(1U) + +#define FW_FILTER_WR_SMAC_S 18 +#define FW_FILTER_WR_SMAC_M 0x1 +#define FW_FILTER_WR_SMAC_V(x) ((x) << FW_FILTER_WR_SMAC_S) +#define FW_FILTER_WR_SMAC_G(x) \ + (((x) >> FW_FILTER_WR_SMAC_S) & FW_FILTER_WR_SMAC_M) +#define FW_FILTER_WR_SMAC_F FW_FILTER_WR_SMAC_V(1U) + +#define FW_FILTER_WR_INSVLAN_S 17 +#define FW_FILTER_WR_INSVLAN_M 0x1 +#define FW_FILTER_WR_INSVLAN_V(x) ((x) << FW_FILTER_WR_INSVLAN_S) +#define FW_FILTER_WR_INSVLAN_G(x) \ + (((x) >> FW_FILTER_WR_INSVLAN_S) & FW_FILTER_WR_INSVLAN_M) +#define FW_FILTER_WR_INSVLAN_F FW_FILTER_WR_INSVLAN_V(1U) + +#define FW_FILTER_WR_RMVLAN_S 16 +#define FW_FILTER_WR_RMVLAN_M 0x1 +#define FW_FILTER_WR_RMVLAN_V(x) ((x) << FW_FILTER_WR_RMVLAN_S) +#define FW_FILTER_WR_RMVLAN_G(x) \ + (((x) >> FW_FILTER_WR_RMVLAN_S) & FW_FILTER_WR_RMVLAN_M) +#define FW_FILTER_WR_RMVLAN_F FW_FILTER_WR_RMVLAN_V(1U) + +#define FW_FILTER_WR_HITCNTS_S 15 +#define FW_FILTER_WR_HITCNTS_M 0x1 +#define FW_FILTER_WR_HITCNTS_V(x) ((x) << FW_FILTER_WR_HITCNTS_S) +#define FW_FILTER_WR_HITCNTS_G(x) \ + (((x) >> FW_FILTER_WR_HITCNTS_S) & FW_FILTER_WR_HITCNTS_M) +#define FW_FILTER_WR_HITCNTS_F FW_FILTER_WR_HITCNTS_V(1U) + +#define FW_FILTER_WR_TXCHAN_S 13 +#define FW_FILTER_WR_TXCHAN_M 0x3 +#define FW_FILTER_WR_TXCHAN_V(x) ((x) << FW_FILTER_WR_TXCHAN_S) +#define FW_FILTER_WR_TXCHAN_G(x) \ + (((x) >> FW_FILTER_WR_TXCHAN_S) & FW_FILTER_WR_TXCHAN_M) + +#define FW_FILTER_WR_PRIO_S 12 +#define FW_FILTER_WR_PRIO_M 0x1 +#define FW_FILTER_WR_PRIO_V(x) ((x) << FW_FILTER_WR_PRIO_S) +#define FW_FILTER_WR_PRIO_G(x) \ + (((x) >> FW_FILTER_WR_PRIO_S) & FW_FILTER_WR_PRIO_M) +#define FW_FILTER_WR_PRIO_F FW_FILTER_WR_PRIO_V(1U) + +#define FW_FILTER_WR_L2TIX_S 0 +#define FW_FILTER_WR_L2TIX_M 0xfff +#define FW_FILTER_WR_L2TIX_V(x) ((x) << FW_FILTER_WR_L2TIX_S) +#define FW_FILTER_WR_L2TIX_G(x) \ + (((x) >> FW_FILTER_WR_L2TIX_S) & FW_FILTER_WR_L2TIX_M) + +#define FW_FILTER_WR_FRAG_S 7 +#define FW_FILTER_WR_FRAG_M 0x1 +#define FW_FILTER_WR_FRAG_V(x) ((x) << FW_FILTER_WR_FRAG_S) +#define FW_FILTER_WR_FRAG_G(x) \ + (((x) >> FW_FILTER_WR_FRAG_S) & FW_FILTER_WR_FRAG_M) +#define FW_FILTER_WR_FRAG_F FW_FILTER_WR_FRAG_V(1U) + +#define FW_FILTER_WR_FRAGM_S 6 +#define FW_FILTER_WR_FRAGM_M 0x1 +#define FW_FILTER_WR_FRAGM_V(x) ((x) << FW_FILTER_WR_FRAGM_S) +#define FW_FILTER_WR_FRAGM_G(x) \ + (((x) >> FW_FILTER_WR_FRAGM_S) & FW_FILTER_WR_FRAGM_M) +#define FW_FILTER_WR_FRAGM_F FW_FILTER_WR_FRAGM_V(1U) + +#define FW_FILTER_WR_IVLAN_VLD_S 5 +#define FW_FILTER_WR_IVLAN_VLD_M 0x1 +#define FW_FILTER_WR_IVLAN_VLD_V(x) ((x) << FW_FILTER_WR_IVLAN_VLD_S) +#define FW_FILTER_WR_IVLAN_VLD_G(x) \ + (((x) >> FW_FILTER_WR_IVLAN_VLD_S) & FW_FILTER_WR_IVLAN_VLD_M) +#define FW_FILTER_WR_IVLAN_VLD_F FW_FILTER_WR_IVLAN_VLD_V(1U) + +#define FW_FILTER_WR_OVLAN_VLD_S 4 +#define FW_FILTER_WR_OVLAN_VLD_M 0x1 +#define FW_FILTER_WR_OVLAN_VLD_V(x) ((x) << FW_FILTER_WR_OVLAN_VLD_S) +#define FW_FILTER_WR_OVLAN_VLD_G(x) \ + (((x) >> FW_FILTER_WR_OVLAN_VLD_S) & FW_FILTER_WR_OVLAN_VLD_M) +#define FW_FILTER_WR_OVLAN_VLD_F FW_FILTER_WR_OVLAN_VLD_V(1U) + +#define FW_FILTER_WR_IVLAN_VLDM_S 3 +#define FW_FILTER_WR_IVLAN_VLDM_M 0x1 +#define FW_FILTER_WR_IVLAN_VLDM_V(x) ((x) << FW_FILTER_WR_IVLAN_VLDM_S) +#define FW_FILTER_WR_IVLAN_VLDM_G(x) \ + (((x) >> FW_FILTER_WR_IVLAN_VLDM_S) & FW_FILTER_WR_IVLAN_VLDM_M) +#define FW_FILTER_WR_IVLAN_VLDM_F FW_FILTER_WR_IVLAN_VLDM_V(1U) + +#define FW_FILTER_WR_OVLAN_VLDM_S 2 +#define FW_FILTER_WR_OVLAN_VLDM_M 0x1 +#define FW_FILTER_WR_OVLAN_VLDM_V(x) ((x) << FW_FILTER_WR_OVLAN_VLDM_S) +#define FW_FILTER_WR_OVLAN_VLDM_G(x) \ + (((x) >> FW_FILTER_WR_OVLAN_VLDM_S) & FW_FILTER_WR_OVLAN_VLDM_M) +#define FW_FILTER_WR_OVLAN_VLDM_F FW_FILTER_WR_OVLAN_VLDM_V(1U) + +#define FW_FILTER_WR_RX_CHAN_S 15 +#define FW_FILTER_WR_RX_CHAN_M 0x1 +#define FW_FILTER_WR_RX_CHAN_V(x) ((x) << FW_FILTER_WR_RX_CHAN_S) +#define FW_FILTER_WR_RX_CHAN_G(x) \ + (((x) >> FW_FILTER_WR_RX_CHAN_S) & FW_FILTER_WR_RX_CHAN_M) +#define FW_FILTER_WR_RX_CHAN_F FW_FILTER_WR_RX_CHAN_V(1U) + +#define FW_FILTER_WR_RX_RPL_IQ_S 0 +#define FW_FILTER_WR_RX_RPL_IQ_M 0x3ff +#define FW_FILTER_WR_RX_RPL_IQ_V(x) ((x) << FW_FILTER_WR_RX_RPL_IQ_S) +#define FW_FILTER_WR_RX_RPL_IQ_G(x) \ + (((x) >> FW_FILTER_WR_RX_RPL_IQ_S) & FW_FILTER_WR_RX_RPL_IQ_M) + +#define FW_FILTER_WR_MACI_S 23 +#define FW_FILTER_WR_MACI_M 0x1ff +#define FW_FILTER_WR_MACI_V(x) ((x) << FW_FILTER_WR_MACI_S) +#define FW_FILTER_WR_MACI_G(x) \ + (((x) >> FW_FILTER_WR_MACI_S) & FW_FILTER_WR_MACI_M) + +#define FW_FILTER_WR_MACIM_S 14 +#define FW_FILTER_WR_MACIM_M 0x1ff +#define FW_FILTER_WR_MACIM_V(x) ((x) << FW_FILTER_WR_MACIM_S) +#define FW_FILTER_WR_MACIM_G(x) \ + (((x) >> FW_FILTER_WR_MACIM_S) & FW_FILTER_WR_MACIM_M) + +#define FW_FILTER_WR_FCOE_S 13 +#define FW_FILTER_WR_FCOE_M 0x1 +#define FW_FILTER_WR_FCOE_V(x) ((x) << FW_FILTER_WR_FCOE_S) +#define FW_FILTER_WR_FCOE_G(x) \ + (((x) >> FW_FILTER_WR_FCOE_S) & FW_FILTER_WR_FCOE_M) +#define FW_FILTER_WR_FCOE_F FW_FILTER_WR_FCOE_V(1U) + +#define FW_FILTER_WR_FCOEM_S 12 +#define FW_FILTER_WR_FCOEM_M 0x1 +#define FW_FILTER_WR_FCOEM_V(x) ((x) << FW_FILTER_WR_FCOEM_S) +#define FW_FILTER_WR_FCOEM_G(x) \ + (((x) >> FW_FILTER_WR_FCOEM_S) & FW_FILTER_WR_FCOEM_M) +#define FW_FILTER_WR_FCOEM_F FW_FILTER_WR_FCOEM_V(1U) + +#define FW_FILTER_WR_PORT_S 9 +#define FW_FILTER_WR_PORT_M 0x7 +#define FW_FILTER_WR_PORT_V(x) ((x) << FW_FILTER_WR_PORT_S) +#define FW_FILTER_WR_PORT_G(x) \ + (((x) >> FW_FILTER_WR_PORT_S) & FW_FILTER_WR_PORT_M) + +#define FW_FILTER_WR_PORTM_S 6 +#define FW_FILTER_WR_PORTM_M 0x7 +#define FW_FILTER_WR_PORTM_V(x) ((x) << FW_FILTER_WR_PORTM_S) +#define FW_FILTER_WR_PORTM_G(x) \ + (((x) >> FW_FILTER_WR_PORTM_S) & FW_FILTER_WR_PORTM_M) + +#define FW_FILTER_WR_MATCHTYPE_S 3 +#define FW_FILTER_WR_MATCHTYPE_M 0x7 +#define FW_FILTER_WR_MATCHTYPE_V(x) ((x) << FW_FILTER_WR_MATCHTYPE_S) +#define FW_FILTER_WR_MATCHTYPE_G(x) \ + (((x) >> FW_FILTER_WR_MATCHTYPE_S) & FW_FILTER_WR_MATCHTYPE_M) + +#define FW_FILTER_WR_MATCHTYPEM_S 0 +#define FW_FILTER_WR_MATCHTYPEM_M 0x7 +#define FW_FILTER_WR_MATCHTYPEM_V(x) ((x) << FW_FILTER_WR_MATCHTYPEM_S) +#define FW_FILTER_WR_MATCHTYPEM_G(x) \ + (((x) >> FW_FILTER_WR_MATCHTYPEM_S) & FW_FILTER_WR_MATCHTYPEM_M) struct fw_ulptx_wr { __be32 op_to_compl; @@ -460,65 +491,65 @@ struct fw_ofld_connection_wr { } tcb; }; -#define S_FW_OFLD_CONNECTION_WR_VERSION 31 -#define M_FW_OFLD_CONNECTION_WR_VERSION 0x1 -#define V_FW_OFLD_CONNECTION_WR_VERSION(x) \ - ((x) << S_FW_OFLD_CONNECTION_WR_VERSION) -#define G_FW_OFLD_CONNECTION_WR_VERSION(x) \ - (((x) >> S_FW_OFLD_CONNECTION_WR_VERSION) & \ - M_FW_OFLD_CONNECTION_WR_VERSION) -#define F_FW_OFLD_CONNECTION_WR_VERSION \ - V_FW_OFLD_CONNECTION_WR_VERSION(1U) - -#define S_FW_OFLD_CONNECTION_WR_CPL 30 -#define M_FW_OFLD_CONNECTION_WR_CPL 0x1 -#define V_FW_OFLD_CONNECTION_WR_CPL(x) ((x) << S_FW_OFLD_CONNECTION_WR_CPL) -#define G_FW_OFLD_CONNECTION_WR_CPL(x) \ - (((x) >> S_FW_OFLD_CONNECTION_WR_CPL) & M_FW_OFLD_CONNECTION_WR_CPL) -#define F_FW_OFLD_CONNECTION_WR_CPL V_FW_OFLD_CONNECTION_WR_CPL(1U) - -#define S_FW_OFLD_CONNECTION_WR_T_STATE 28 -#define M_FW_OFLD_CONNECTION_WR_T_STATE 0xf -#define V_FW_OFLD_CONNECTION_WR_T_STATE(x) \ - ((x) << S_FW_OFLD_CONNECTION_WR_T_STATE) -#define G_FW_OFLD_CONNECTION_WR_T_STATE(x) \ - (((x) >> S_FW_OFLD_CONNECTION_WR_T_STATE) & \ - M_FW_OFLD_CONNECTION_WR_T_STATE) - -#define S_FW_OFLD_CONNECTION_WR_RCV_SCALE 24 -#define M_FW_OFLD_CONNECTION_WR_RCV_SCALE 0xf -#define V_FW_OFLD_CONNECTION_WR_RCV_SCALE(x) \ - ((x) << S_FW_OFLD_CONNECTION_WR_RCV_SCALE) -#define G_FW_OFLD_CONNECTION_WR_RCV_SCALE(x) \ - (((x) >> S_FW_OFLD_CONNECTION_WR_RCV_SCALE) & \ - M_FW_OFLD_CONNECTION_WR_RCV_SCALE) - -#define S_FW_OFLD_CONNECTION_WR_ASTID 0 -#define M_FW_OFLD_CONNECTION_WR_ASTID 0xffffff -#define V_FW_OFLD_CONNECTION_WR_ASTID(x) \ - ((x) << S_FW_OFLD_CONNECTION_WR_ASTID) -#define G_FW_OFLD_CONNECTION_WR_ASTID(x) \ - (((x) >> S_FW_OFLD_CONNECTION_WR_ASTID) & M_FW_OFLD_CONNECTION_WR_ASTID) - -#define S_FW_OFLD_CONNECTION_WR_CPLRXDATAACK 15 -#define M_FW_OFLD_CONNECTION_WR_CPLRXDATAACK 0x1 -#define V_FW_OFLD_CONNECTION_WR_CPLRXDATAACK(x) \ - ((x) << S_FW_OFLD_CONNECTION_WR_CPLRXDATAACK) -#define G_FW_OFLD_CONNECTION_WR_CPLRXDATAACK(x) \ - (((x) >> S_FW_OFLD_CONNECTION_WR_CPLRXDATAACK) & \ - M_FW_OFLD_CONNECTION_WR_CPLRXDATAACK) -#define F_FW_OFLD_CONNECTION_WR_CPLRXDATAACK \ - V_FW_OFLD_CONNECTION_WR_CPLRXDATAACK(1U) - -#define S_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL 14 -#define M_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL 0x1 -#define V_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL(x) \ - ((x) << S_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL) -#define G_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL(x) \ - (((x) >> S_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL) & \ - M_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL) -#define F_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL \ - V_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL(1U) +#define FW_OFLD_CONNECTION_WR_VERSION_S 31 +#define FW_OFLD_CONNECTION_WR_VERSION_M 0x1 +#define FW_OFLD_CONNECTION_WR_VERSION_V(x) \ + ((x) << FW_OFLD_CONNECTION_WR_VERSION_S) +#define FW_OFLD_CONNECTION_WR_VERSION_G(x) \ + (((x) >> FW_OFLD_CONNECTION_WR_VERSION_S) & \ + FW_OFLD_CONNECTION_WR_VERSION_M) +#define FW_OFLD_CONNECTION_WR_VERSION_F \ + FW_OFLD_CONNECTION_WR_VERSION_V(1U) + +#define FW_OFLD_CONNECTION_WR_CPL_S 30 +#define FW_OFLD_CONNECTION_WR_CPL_M 0x1 +#define FW_OFLD_CONNECTION_WR_CPL_V(x) ((x) << FW_OFLD_CONNECTION_WR_CPL_S) +#define FW_OFLD_CONNECTION_WR_CPL_G(x) \ + (((x) >> FW_OFLD_CONNECTION_WR_CPL_S) & FW_OFLD_CONNECTION_WR_CPL_M) +#define FW_OFLD_CONNECTION_WR_CPL_F FW_OFLD_CONNECTION_WR_CPL_V(1U) + +#define FW_OFLD_CONNECTION_WR_T_STATE_S 28 +#define FW_OFLD_CONNECTION_WR_T_STATE_M 0xf +#define FW_OFLD_CONNECTION_WR_T_STATE_V(x) \ + ((x) << FW_OFLD_CONNECTION_WR_T_STATE_S) +#define FW_OFLD_CONNECTION_WR_T_STATE_G(x) \ + (((x) >> FW_OFLD_CONNECTION_WR_T_STATE_S) & \ + FW_OFLD_CONNECTION_WR_T_STATE_M) + +#define FW_OFLD_CONNECTION_WR_RCV_SCALE_S 24 +#define FW_OFLD_CONNECTION_WR_RCV_SCALE_M 0xf +#define FW_OFLD_CONNECTION_WR_RCV_SCALE_V(x) \ + ((x) << FW_OFLD_CONNECTION_WR_RCV_SCALE_S) +#define FW_OFLD_CONNECTION_WR_RCV_SCALE_G(x) \ + (((x) >> FW_OFLD_CONNECTION_WR_RCV_SCALE_S) & \ + FW_OFLD_CONNECTION_WR_RCV_SCALE_M) + +#define FW_OFLD_CONNECTION_WR_ASTID_S 0 +#define FW_OFLD_CONNECTION_WR_ASTID_M 0xffffff +#define FW_OFLD_CONNECTION_WR_ASTID_V(x) \ + ((x) << FW_OFLD_CONNECTION_WR_ASTID_S) +#define FW_OFLD_CONNECTION_WR_ASTID_G(x) \ + (((x) >> FW_OFLD_CONNECTION_WR_ASTID_S) & FW_OFLD_CONNECTION_WR_ASTID_M) + +#define FW_OFLD_CONNECTION_WR_CPLRXDATAACK_S 15 +#define FW_OFLD_CONNECTION_WR_CPLRXDATAACK_M 0x1 +#define FW_OFLD_CONNECTION_WR_CPLRXDATAACK_V(x) \ + ((x) << FW_OFLD_CONNECTION_WR_CPLRXDATAACK_S) +#define FW_OFLD_CONNECTION_WR_CPLRXDATAACK_G(x) \ + (((x) >> FW_OFLD_CONNECTION_WR_CPLRXDATAACK_S) & \ + FW_OFLD_CONNECTION_WR_CPLRXDATAACK_M) +#define FW_OFLD_CONNECTION_WR_CPLRXDATAACK_F \ + FW_OFLD_CONNECTION_WR_CPLRXDATAACK_V(1U) + +#define FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL_S 14 +#define FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL_M 0x1 +#define FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL_V(x) \ + ((x) << FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL_S) +#define FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL_G(x) \ + (((x) >> FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL_S) & \ + FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL_M) +#define FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL_F \ + FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL_V(1U) enum fw_flowc_mnem { FW_FLOWC_MNEM_PFNVFN, /* PFN [15:8] VFN [7:0] */ @@ -539,33 +570,56 @@ struct fw_flowc_mnemval { struct fw_flowc_wr { __be32 op_to_nparams; -#define FW_FLOWC_WR_NPARAMS(x) ((x) << 0) __be32 flowid_len16; struct fw_flowc_mnemval mnemval[0]; }; +#define FW_FLOWC_WR_NPARAMS_S 0 +#define FW_FLOWC_WR_NPARAMS_V(x) ((x) << FW_FLOWC_WR_NPARAMS_S) + struct fw_ofld_tx_data_wr { __be32 op_to_immdlen; __be32 flowid_len16; __be32 plen; __be32 tunnel_to_proxy; -#define FW_OFLD_TX_DATA_WR_TUNNEL(x) ((x) << 19) -#define FW_OFLD_TX_DATA_WR_SAVE(x) ((x) << 18) -#define FW_OFLD_TX_DATA_WR_FLUSH(x) ((x) << 17) -#define FW_OFLD_TX_DATA_WR_URGENT(x) ((x) << 16) -#define FW_OFLD_TX_DATA_WR_MORE(x) ((x) << 15) -#define FW_OFLD_TX_DATA_WR_SHOVE(x) ((x) << 14) -#define FW_OFLD_TX_DATA_WR_ULPMODE(x) ((x) << 10) -#define FW_OFLD_TX_DATA_WR_ULPSUBMODE(x) ((x) << 6) }; +#define FW_OFLD_TX_DATA_WR_TUNNEL_S 19 +#define FW_OFLD_TX_DATA_WR_TUNNEL_V(x) ((x) << FW_OFLD_TX_DATA_WR_TUNNEL_S) + +#define FW_OFLD_TX_DATA_WR_SAVE_S 18 +#define FW_OFLD_TX_DATA_WR_SAVE_V(x) ((x) << FW_OFLD_TX_DATA_WR_SAVE_S) + +#define FW_OFLD_TX_DATA_WR_FLUSH_S 17 +#define FW_OFLD_TX_DATA_WR_FLUSH_V(x) ((x) << FW_OFLD_TX_DATA_WR_FLUSH_S) +#define FW_OFLD_TX_DATA_WR_FLUSH_F FW_OFLD_TX_DATA_WR_FLUSH_V(1U) + +#define FW_OFLD_TX_DATA_WR_URGENT_S 16 +#define FW_OFLD_TX_DATA_WR_URGENT_V(x) ((x) << FW_OFLD_TX_DATA_WR_URGENT_S) + +#define FW_OFLD_TX_DATA_WR_MORE_S 15 +#define FW_OFLD_TX_DATA_WR_MORE_V(x) ((x) << FW_OFLD_TX_DATA_WR_MORE_S) + +#define FW_OFLD_TX_DATA_WR_SHOVE_S 14 +#define FW_OFLD_TX_DATA_WR_SHOVE_V(x) ((x) << FW_OFLD_TX_DATA_WR_SHOVE_S) +#define FW_OFLD_TX_DATA_WR_SHOVE_F FW_OFLD_TX_DATA_WR_SHOVE_V(1U) + +#define FW_OFLD_TX_DATA_WR_ULPMODE_S 10 +#define FW_OFLD_TX_DATA_WR_ULPMODE_V(x) ((x) << FW_OFLD_TX_DATA_WR_ULPMODE_S) + +#define FW_OFLD_TX_DATA_WR_ULPSUBMODE_S 6 +#define FW_OFLD_TX_DATA_WR_ULPSUBMODE_V(x) \ + ((x) << FW_OFLD_TX_DATA_WR_ULPSUBMODE_S) + struct fw_cmd_wr { __be32 op_dma; -#define FW_CMD_WR_DMA (1U << 17) __be32 len16_pkd; __be64 cookie_daddr; }; +#define FW_CMD_WR_DMA_S 17 +#define FW_CMD_WR_DMA_V(x) ((x) << FW_CMD_WR_DMA_S) + struct fw_eth_tx_pkt_vm_wr { __be32 op_immdlen; __be32 equiq_to_len16; @@ -641,18 +695,39 @@ struct fw_cmd_hdr { __be32 lo; }; -#define FW_CMD_OP(x) ((x) << 24) -#define FW_CMD_OP_GET(x) (((x) >> 24) & 0xff) -#define FW_CMD_REQUEST (1U << 23) -#define FW_CMD_REQUEST_GET(x) (((x) >> 23) & 0x1) -#define FW_CMD_READ (1U << 22) -#define FW_CMD_WRITE (1U << 21) -#define FW_CMD_EXEC (1U << 20) -#define FW_CMD_RAMASK(x) ((x) << 20) -#define FW_CMD_RETVAL(x) ((x) << 8) -#define FW_CMD_RETVAL_GET(x) (((x) >> 8) & 0xff) -#define FW_CMD_LEN16(x) ((x) << 0) -#define FW_LEN16(fw_struct) FW_CMD_LEN16(sizeof(fw_struct) / 16) +#define FW_CMD_OP_S 24 +#define FW_CMD_OP_M 0xff +#define FW_CMD_OP_V(x) ((x) << FW_CMD_OP_S) +#define FW_CMD_OP_G(x) (((x) >> FW_CMD_OP_S) & FW_CMD_OP_M) + +#define FW_CMD_REQUEST_S 23 +#define FW_CMD_REQUEST_V(x) ((x) << FW_CMD_REQUEST_S) +#define FW_CMD_REQUEST_F FW_CMD_REQUEST_V(1U) + +#define FW_CMD_READ_S 22 +#define FW_CMD_READ_V(x) ((x) << FW_CMD_READ_S) +#define FW_CMD_READ_F FW_CMD_READ_V(1U) + +#define FW_CMD_WRITE_S 21 +#define FW_CMD_WRITE_V(x) ((x) << FW_CMD_WRITE_S) +#define FW_CMD_WRITE_F FW_CMD_WRITE_V(1U) + +#define FW_CMD_EXEC_S 20 +#define FW_CMD_EXEC_V(x) ((x) << FW_CMD_EXEC_S) +#define FW_CMD_EXEC_F FW_CMD_EXEC_V(1U) + +#define FW_CMD_RAMASK_S 20 +#define FW_CMD_RAMASK_V(x) ((x) << FW_CMD_RAMASK_S) + +#define FW_CMD_RETVAL_S 8 +#define FW_CMD_RETVAL_M 0xff +#define FW_CMD_RETVAL_V(x) ((x) << FW_CMD_RETVAL_S) +#define FW_CMD_RETVAL_G(x) (((x) >> FW_CMD_RETVAL_S) & FW_CMD_RETVAL_M) + +#define FW_CMD_LEN16_S 0 +#define FW_CMD_LEN16_V(x) ((x) << FW_CMD_LEN16_S) + +#define FW_LEN16(fw_struct) FW_CMD_LEN16_V(sizeof(fw_struct) / 16) enum fw_ldst_addrspc { FW_LDST_ADDRSPC_FIRMWARE = 0x0001, @@ -685,7 +760,8 @@ enum fw_ldst_func_mod_index { struct fw_ldst_cmd { __be32 op_to_addrspace; -#define FW_LDST_CMD_ADDRSPACE(x) ((x) << 0) +#define FW_LDST_CMD_ADDRSPACE_S 0 +#define FW_LDST_CMD_ADDRSPACE_V(x) ((x) << FW_LDST_CMD_ADDRSPACE_S) __be32 cycles_to_len16; union fw_ldst { struct fw_ldst_addrval { @@ -741,15 +817,33 @@ struct fw_ldst_cmd { } u; }; -#define FW_LDST_CMD_MSG(x) ((x) << 31) -#define FW_LDST_CMD_PADDR(x) ((x) << 8) -#define FW_LDST_CMD_MMD(x) ((x) << 0) -#define FW_LDST_CMD_FID(x) ((x) << 15) -#define FW_LDST_CMD_CTL(x) ((x) << 0) -#define FW_LDST_CMD_RPLCPF(x) ((x) << 0) -#define FW_LDST_CMD_LC (1U << 4) -#define FW_LDST_CMD_NACCESS(x) ((x) << 0) -#define FW_LDST_CMD_FN(x) ((x) << 0) +#define FW_LDST_CMD_MSG_S 31 +#define FW_LDST_CMD_MSG_V(x) ((x) << FW_LDST_CMD_MSG_S) + +#define FW_LDST_CMD_PADDR_S 8 +#define FW_LDST_CMD_PADDR_V(x) ((x) << FW_LDST_CMD_PADDR_S) + +#define FW_LDST_CMD_MMD_S 0 +#define FW_LDST_CMD_MMD_V(x) ((x) << FW_LDST_CMD_MMD_S) + +#define FW_LDST_CMD_FID_S 15 +#define FW_LDST_CMD_FID_V(x) ((x) << FW_LDST_CMD_FID_S) + +#define FW_LDST_CMD_CTL_S 0 +#define FW_LDST_CMD_CTL_V(x) ((x) << FW_LDST_CMD_CTL_S) + +#define FW_LDST_CMD_RPLCPF_S 0 +#define FW_LDST_CMD_RPLCPF_V(x) ((x) << FW_LDST_CMD_RPLCPF_S) + +#define FW_LDST_CMD_LC_S 4 +#define FW_LDST_CMD_LC_V(x) ((x) << FW_LDST_CMD_LC_S) +#define FW_LDST_CMD_LC_F FW_LDST_CMD_LC_V(1U) + +#define FW_LDST_CMD_FN_S 0 +#define FW_LDST_CMD_FN_V(x) ((x) << FW_LDST_CMD_FN_S) + +#define FW_LDST_CMD_NACCESS_S 0 +#define FW_LDST_CMD_NACCESS_V(x) ((x) << FW_LDST_CMD_NACCESS_S) struct fw_reset_cmd { __be32 op_to_write; @@ -758,11 +852,12 @@ struct fw_reset_cmd { __be32 halt_pkd; }; -#define FW_RESET_CMD_HALT_SHIFT 31 -#define FW_RESET_CMD_HALT_MASK 0x1 -#define FW_RESET_CMD_HALT(x) ((x) << FW_RESET_CMD_HALT_SHIFT) -#define FW_RESET_CMD_HALT_GET(x) \ - (((x) >> FW_RESET_CMD_HALT_SHIFT) & FW_RESET_CMD_HALT_MASK) +#define FW_RESET_CMD_HALT_S 31 +#define FW_RESET_CMD_HALT_M 0x1 +#define FW_RESET_CMD_HALT_V(x) ((x) << FW_RESET_CMD_HALT_S) +#define FW_RESET_CMD_HALT_G(x) \ + (((x) >> FW_RESET_CMD_HALT_S) & FW_RESET_CMD_HALT_M) +#define FW_RESET_CMD_HALT_F FW_RESET_CMD_HALT_V(1U) enum fw_hellow_cmd { fw_hello_cmd_stage_os = 0x0 @@ -772,22 +867,42 @@ struct fw_hello_cmd { __be32 op_to_write; __be32 retval_len16; __be32 err_to_clearinit; -#define FW_HELLO_CMD_ERR (1U << 31) -#define FW_HELLO_CMD_INIT (1U << 30) -#define FW_HELLO_CMD_MASTERDIS(x) ((x) << 29) -#define FW_HELLO_CMD_MASTERFORCE(x) ((x) << 28) -#define FW_HELLO_CMD_MBMASTER_MASK 0xfU -#define FW_HELLO_CMD_MBMASTER_SHIFT 24 -#define FW_HELLO_CMD_MBMASTER(x) ((x) << FW_HELLO_CMD_MBMASTER_SHIFT) -#define FW_HELLO_CMD_MBMASTER_GET(x) \ - (((x) >> FW_HELLO_CMD_MBMASTER_SHIFT) & FW_HELLO_CMD_MBMASTER_MASK) -#define FW_HELLO_CMD_MBASYNCNOTINT(x) ((x) << 23) -#define FW_HELLO_CMD_MBASYNCNOT(x) ((x) << 20) -#define FW_HELLO_CMD_STAGE(x) ((x) << 17) -#define FW_HELLO_CMD_CLEARINIT (1U << 16) __be32 fwrev; }; +#define FW_HELLO_CMD_ERR_S 31 +#define FW_HELLO_CMD_ERR_V(x) ((x) << FW_HELLO_CMD_ERR_S) +#define FW_HELLO_CMD_ERR_F FW_HELLO_CMD_ERR_V(1U) + +#define FW_HELLO_CMD_INIT_S 30 +#define FW_HELLO_CMD_INIT_V(x) ((x) << FW_HELLO_CMD_INIT_S) +#define FW_HELLO_CMD_INIT_F FW_HELLO_CMD_INIT_V(1U) + +#define FW_HELLO_CMD_MASTERDIS_S 29 +#define FW_HELLO_CMD_MASTERDIS_V(x) ((x) << FW_HELLO_CMD_MASTERDIS_S) + +#define FW_HELLO_CMD_MASTERFORCE_S 28 +#define FW_HELLO_CMD_MASTERFORCE_V(x) ((x) << FW_HELLO_CMD_MASTERFORCE_S) + +#define FW_HELLO_CMD_MBMASTER_S 24 +#define FW_HELLO_CMD_MBMASTER_M 0xfU +#define FW_HELLO_CMD_MBMASTER_V(x) ((x) << FW_HELLO_CMD_MBMASTER_S) +#define FW_HELLO_CMD_MBMASTER_G(x) \ + (((x) >> FW_HELLO_CMD_MBMASTER_S) & FW_HELLO_CMD_MBMASTER_M) + +#define FW_HELLO_CMD_MBASYNCNOTINT_S 23 +#define FW_HELLO_CMD_MBASYNCNOTINT_V(x) ((x) << FW_HELLO_CMD_MBASYNCNOTINT_S) + +#define FW_HELLO_CMD_MBASYNCNOT_S 20 +#define FW_HELLO_CMD_MBASYNCNOT_V(x) ((x) << FW_HELLO_CMD_MBASYNCNOT_S) + +#define FW_HELLO_CMD_STAGE_S 17 +#define FW_HELLO_CMD_STAGE_V(x) ((x) << FW_HELLO_CMD_STAGE_S) + +#define FW_HELLO_CMD_CLEARINIT_S 16 +#define FW_HELLO_CMD_CLEARINIT_V(x) ((x) << FW_HELLO_CMD_CLEARINIT_S) +#define FW_HELLO_CMD_CLEARINIT_F FW_HELLO_CMD_CLEARINIT_V(1U) + struct fw_bye_cmd { __be32 op_to_write; __be32 retval_len16; @@ -898,9 +1013,17 @@ struct fw_caps_config_cmd { __be32 finicsum; }; -#define FW_CAPS_CONFIG_CMD_CFVALID (1U << 27) -#define FW_CAPS_CONFIG_CMD_MEMTYPE_CF(x) ((x) << 24) -#define FW_CAPS_CONFIG_CMD_MEMADDR64K_CF(x) ((x) << 16) +#define FW_CAPS_CONFIG_CMD_CFVALID_S 27 +#define FW_CAPS_CONFIG_CMD_CFVALID_V(x) ((x) << FW_CAPS_CONFIG_CMD_CFVALID_S) +#define FW_CAPS_CONFIG_CMD_CFVALID_F FW_CAPS_CONFIG_CMD_CFVALID_V(1U) + +#define FW_CAPS_CONFIG_CMD_MEMTYPE_CF_S 24 +#define FW_CAPS_CONFIG_CMD_MEMTYPE_CF_V(x) \ + ((x) << FW_CAPS_CONFIG_CMD_MEMTYPE_CF_S) + +#define FW_CAPS_CONFIG_CMD_MEMADDR64K_CF_S 16 +#define FW_CAPS_CONFIG_CMD_MEMADDR64K_CF_V(x) \ + ((x) << FW_CAPS_CONFIG_CMD_MEMADDR64K_CF_S) /* * params command mnemonics @@ -996,20 +1119,29 @@ enum fw_params_param_dmaq { FW_PARAMS_PARAM_DMAQ_EQ_DCBPRIO_ETH = 0x13, }; -#define FW_PARAMS_MNEM(x) ((x) << 24) -#define FW_PARAMS_PARAM_X(x) ((x) << 16) -#define FW_PARAMS_PARAM_Y_SHIFT 8 -#define FW_PARAMS_PARAM_Y_MASK 0xffU -#define FW_PARAMS_PARAM_Y(x) ((x) << FW_PARAMS_PARAM_Y_SHIFT) -#define FW_PARAMS_PARAM_Y_GET(x) (((x) >> FW_PARAMS_PARAM_Y_SHIFT) &\ - FW_PARAMS_PARAM_Y_MASK) -#define FW_PARAMS_PARAM_Z_SHIFT 0 -#define FW_PARAMS_PARAM_Z_MASK 0xffu -#define FW_PARAMS_PARAM_Z(x) ((x) << FW_PARAMS_PARAM_Z_SHIFT) -#define FW_PARAMS_PARAM_Z_GET(x) (((x) >> FW_PARAMS_PARAM_Z_SHIFT) &\ - FW_PARAMS_PARAM_Z_MASK) -#define FW_PARAMS_PARAM_XYZ(x) ((x) << 0) -#define FW_PARAMS_PARAM_YZ(x) ((x) << 0) +#define FW_PARAMS_MNEM_S 24 +#define FW_PARAMS_MNEM_V(x) ((x) << FW_PARAMS_MNEM_S) + +#define FW_PARAMS_PARAM_X_S 16 +#define FW_PARAMS_PARAM_X_V(x) ((x) << FW_PARAMS_PARAM_X_S) + +#define FW_PARAMS_PARAM_Y_S 8 +#define FW_PARAMS_PARAM_Y_M 0xffU +#define FW_PARAMS_PARAM_Y_V(x) ((x) << FW_PARAMS_PARAM_Y_S) +#define FW_PARAMS_PARAM_Y_G(x) (((x) >> FW_PARAMS_PARAM_Y_S) &\ + FW_PARAMS_PARAM_Y_M) + +#define FW_PARAMS_PARAM_Z_S 0 +#define FW_PARAMS_PARAM_Z_M 0xffu +#define FW_PARAMS_PARAM_Z_V(x) ((x) << FW_PARAMS_PARAM_Z_S) +#define FW_PARAMS_PARAM_Z_G(x) (((x) >> FW_PARAMS_PARAM_Z_S) &\ + FW_PARAMS_PARAM_Z_M) + +#define FW_PARAMS_PARAM_XYZ_S 0 +#define FW_PARAMS_PARAM_XYZ_V(x) ((x) << FW_PARAMS_PARAM_XYZ_S) + +#define FW_PARAMS_PARAM_YZ_S 0 +#define FW_PARAMS_PARAM_YZ_V(x) ((x) << FW_PARAMS_PARAM_YZ_S) struct fw_params_cmd { __be32 op_to_vfn; @@ -1020,8 +1152,11 @@ struct fw_params_cmd { } param[7]; }; -#define FW_PARAMS_CMD_PFN(x) ((x) << 8) -#define FW_PARAMS_CMD_VFN(x) ((x) << 0) +#define FW_PARAMS_CMD_PFN_S 8 +#define FW_PARAMS_CMD_PFN_V(x) ((x) << FW_PARAMS_CMD_PFN_S) + +#define FW_PARAMS_CMD_VFN_S 0 +#define FW_PARAMS_CMD_VFN_V(x) ((x) << FW_PARAMS_CMD_VFN_S) struct fw_pfvf_cmd { __be32 op_to_vfn; @@ -1035,46 +1170,82 @@ struct fw_pfvf_cmd { __be32 r4; }; -#define FW_PFVF_CMD_PFN(x) ((x) << 8) -#define FW_PFVF_CMD_VFN(x) ((x) << 0) - -#define FW_PFVF_CMD_NIQFLINT(x) ((x) << 20) -#define FW_PFVF_CMD_NIQFLINT_GET(x) (((x) >> 20) & 0xfff) - -#define FW_PFVF_CMD_NIQ(x) ((x) << 0) -#define FW_PFVF_CMD_NIQ_GET(x) (((x) >> 0) & 0xfffff) - -#define FW_PFVF_CMD_TYPE (1 << 31) -#define FW_PFVF_CMD_TYPE_GET(x) (((x) >> 31) & 0x1) - -#define FW_PFVF_CMD_CMASK(x) ((x) << 24) -#define FW_PFVF_CMD_CMASK_MASK 0xf -#define FW_PFVF_CMD_CMASK_GET(x) (((x) >> 24) & FW_PFVF_CMD_CMASK_MASK) - -#define FW_PFVF_CMD_PMASK(x) ((x) << 20) -#define FW_PFVF_CMD_PMASK_MASK 0xf -#define FW_PFVF_CMD_PMASK_GET(x) (((x) >> 20) & FW_PFVF_CMD_PMASK_MASK) - -#define FW_PFVF_CMD_NEQ(x) ((x) << 0) -#define FW_PFVF_CMD_NEQ_GET(x) (((x) >> 0) & 0xfffff) - -#define FW_PFVF_CMD_TC(x) ((x) << 24) -#define FW_PFVF_CMD_TC_GET(x) (((x) >> 24) & 0xff) - -#define FW_PFVF_CMD_NVI(x) ((x) << 16) -#define FW_PFVF_CMD_NVI_GET(x) (((x) >> 16) & 0xff) - -#define FW_PFVF_CMD_NEXACTF(x) ((x) << 0) -#define FW_PFVF_CMD_NEXACTF_GET(x) (((x) >> 0) & 0xffff) - -#define FW_PFVF_CMD_R_CAPS(x) ((x) << 24) -#define FW_PFVF_CMD_R_CAPS_GET(x) (((x) >> 24) & 0xff) - -#define FW_PFVF_CMD_WX_CAPS(x) ((x) << 16) -#define FW_PFVF_CMD_WX_CAPS_GET(x) (((x) >> 16) & 0xff) - -#define FW_PFVF_CMD_NETHCTRL(x) ((x) << 0) -#define FW_PFVF_CMD_NETHCTRL_GET(x) (((x) >> 0) & 0xffff) +#define FW_PFVF_CMD_PFN_S 8 +#define FW_PFVF_CMD_PFN_V(x) ((x) << FW_PFVF_CMD_PFN_S) + +#define FW_PFVF_CMD_VFN_S 0 +#define FW_PFVF_CMD_VFN_V(x) ((x) << FW_PFVF_CMD_VFN_S) + +#define FW_PFVF_CMD_NIQFLINT_S 20 +#define FW_PFVF_CMD_NIQFLINT_M 0xfff +#define FW_PFVF_CMD_NIQFLINT_V(x) ((x) << FW_PFVF_CMD_NIQFLINT_S) +#define FW_PFVF_CMD_NIQFLINT_G(x) \ + (((x) >> FW_PFVF_CMD_NIQFLINT_S) & FW_PFVF_CMD_NIQFLINT_M) + +#define FW_PFVF_CMD_NIQ_S 0 +#define FW_PFVF_CMD_NIQ_M 0xfffff +#define FW_PFVF_CMD_NIQ_V(x) ((x) << FW_PFVF_CMD_NIQ_S) +#define FW_PFVF_CMD_NIQ_G(x) \ + (((x) >> FW_PFVF_CMD_NIQ_S) & FW_PFVF_CMD_NIQ_M) + +#define FW_PFVF_CMD_TYPE_S 31 +#define FW_PFVF_CMD_TYPE_M 0x1 +#define FW_PFVF_CMD_TYPE_V(x) ((x) << FW_PFVF_CMD_TYPE_S) +#define FW_PFVF_CMD_TYPE_G(x) \ + (((x) >> FW_PFVF_CMD_TYPE_S) & FW_PFVF_CMD_TYPE_M) +#define FW_PFVF_CMD_TYPE_F FW_PFVF_CMD_TYPE_V(1U) + +#define FW_PFVF_CMD_CMASK_S 24 +#define FW_PFVF_CMD_CMASK_M 0xf +#define FW_PFVF_CMD_CMASK_V(x) ((x) << FW_PFVF_CMD_CMASK_S) +#define FW_PFVF_CMD_CMASK_G(x) \ + (((x) >> FW_PFVF_CMD_CMASK_S) & FW_PFVF_CMD_CMASK_M) + +#define FW_PFVF_CMD_PMASK_S 20 +#define FW_PFVF_CMD_PMASK_M 0xf +#define FW_PFVF_CMD_PMASK_V(x) ((x) << FW_PFVF_CMD_PMASK_S) +#define FW_PFVF_CMD_PMASK_G(x) \ + (((x) >> FW_PFVF_CMD_PMASK_S) & FW_PFVF_CMD_PMASK_M) + +#define FW_PFVF_CMD_NEQ_S 0 +#define FW_PFVF_CMD_NEQ_M 0xfffff +#define FW_PFVF_CMD_NEQ_V(x) ((x) << FW_PFVF_CMD_NEQ_S) +#define FW_PFVF_CMD_NEQ_G(x) \ + (((x) >> FW_PFVF_CMD_NEQ_S) & FW_PFVF_CMD_NEQ_M) + +#define FW_PFVF_CMD_TC_S 24 +#define FW_PFVF_CMD_TC_M 0xff +#define FW_PFVF_CMD_TC_V(x) ((x) << FW_PFVF_CMD_TC_S) +#define FW_PFVF_CMD_TC_G(x) (((x) >> FW_PFVF_CMD_TC_S) & FW_PFVF_CMD_TC_M) + +#define FW_PFVF_CMD_NVI_S 16 +#define FW_PFVF_CMD_NVI_M 0xff +#define FW_PFVF_CMD_NVI_V(x) ((x) << FW_PFVF_CMD_NVI_S) +#define FW_PFVF_CMD_NVI_G(x) (((x) >> FW_PFVF_CMD_NVI_S) & FW_PFVF_CMD_NVI_M) + +#define FW_PFVF_CMD_NEXACTF_S 0 +#define FW_PFVF_CMD_NEXACTF_M 0xffff +#define FW_PFVF_CMD_NEXACTF_V(x) ((x) << FW_PFVF_CMD_NEXACTF_S) +#define FW_PFVF_CMD_NEXACTF_G(x) \ + (((x) >> FW_PFVF_CMD_NEXACTF_S) & FW_PFVF_CMD_NEXACTF_M) + +#define FW_PFVF_CMD_R_CAPS_S 24 +#define FW_PFVF_CMD_R_CAPS_M 0xff +#define FW_PFVF_CMD_R_CAPS_V(x) ((x) << FW_PFVF_CMD_R_CAPS_S) +#define FW_PFVF_CMD_R_CAPS_G(x) \ + (((x) >> FW_PFVF_CMD_R_CAPS_S) & FW_PFVF_CMD_R_CAPS_M) + +#define FW_PFVF_CMD_WX_CAPS_S 16 +#define FW_PFVF_CMD_WX_CAPS_M 0xff +#define FW_PFVF_CMD_WX_CAPS_V(x) ((x) << FW_PFVF_CMD_WX_CAPS_S) +#define FW_PFVF_CMD_WX_CAPS_G(x) \ + (((x) >> FW_PFVF_CMD_WX_CAPS_S) & FW_PFVF_CMD_WX_CAPS_M) + +#define FW_PFVF_CMD_NETHCTRL_S 0 +#define FW_PFVF_CMD_NETHCTRL_M 0xffff +#define FW_PFVF_CMD_NETHCTRL_V(x) ((x) << FW_PFVF_CMD_NETHCTRL_S) +#define FW_PFVF_CMD_NETHCTRL_G(x) \ + (((x) >> FW_PFVF_CMD_NETHCTRL_S) & FW_PFVF_CMD_NETHCTRL_M) enum fw_iq_type { FW_IQ_TYPE_FL_INT_CAP, @@ -1102,85 +1273,239 @@ struct fw_iq_cmd { __be64 fl1addr; }; -#define FW_IQ_CMD_PFN(x) ((x) << 8) -#define FW_IQ_CMD_VFN(x) ((x) << 0) - -#define FW_IQ_CMD_ALLOC (1U << 31) -#define FW_IQ_CMD_FREE (1U << 30) -#define FW_IQ_CMD_MODIFY (1U << 29) -#define FW_IQ_CMD_IQSTART(x) ((x) << 28) -#define FW_IQ_CMD_IQSTOP(x) ((x) << 27) - -#define FW_IQ_CMD_TYPE(x) ((x) << 29) -#define FW_IQ_CMD_IQASYNCH(x) ((x) << 28) -#define FW_IQ_CMD_VIID(x) ((x) << 16) -#define FW_IQ_CMD_IQANDST(x) ((x) << 15) -#define FW_IQ_CMD_IQANUS(x) ((x) << 14) -#define FW_IQ_CMD_IQANUD(x) ((x) << 12) -#define FW_IQ_CMD_IQANDSTINDEX(x) ((x) << 0) - -#define FW_IQ_CMD_IQDROPRSS (1U << 15) -#define FW_IQ_CMD_IQGTSMODE (1U << 14) -#define FW_IQ_CMD_IQPCIECH(x) ((x) << 12) -#define FW_IQ_CMD_IQDCAEN(x) ((x) << 11) -#define FW_IQ_CMD_IQDCACPU(x) ((x) << 6) -#define FW_IQ_CMD_IQINTCNTTHRESH(x) ((x) << 4) -#define FW_IQ_CMD_IQO (1U << 3) -#define FW_IQ_CMD_IQCPRIO(x) ((x) << 2) -#define FW_IQ_CMD_IQESIZE(x) ((x) << 0) - -#define FW_IQ_CMD_IQNS(x) ((x) << 31) -#define FW_IQ_CMD_IQRO(x) ((x) << 30) -#define FW_IQ_CMD_IQFLINTIQHSEN(x) ((x) << 28) -#define FW_IQ_CMD_IQFLINTCONGEN(x) ((x) << 27) -#define FW_IQ_CMD_IQFLINTISCSIC(x) ((x) << 26) -#define FW_IQ_CMD_FL0CNGCHMAP(x) ((x) << 20) -#define FW_IQ_CMD_FL0CACHELOCK(x) ((x) << 15) -#define FW_IQ_CMD_FL0DBP(x) ((x) << 14) -#define FW_IQ_CMD_FL0DATANS(x) ((x) << 13) -#define FW_IQ_CMD_FL0DATARO(x) ((x) << 12) -#define FW_IQ_CMD_FL0CONGCIF(x) ((x) << 11) -#define FW_IQ_CMD_FL0ONCHIP(x) ((x) << 10) -#define FW_IQ_CMD_FL0STATUSPGNS(x) ((x) << 9) -#define FW_IQ_CMD_FL0STATUSPGRO(x) ((x) << 8) -#define FW_IQ_CMD_FL0FETCHNS(x) ((x) << 7) -#define FW_IQ_CMD_FL0FETCHRO(x) ((x) << 6) -#define FW_IQ_CMD_FL0HOSTFCMODE(x) ((x) << 4) -#define FW_IQ_CMD_FL0CPRIO(x) ((x) << 3) -#define FW_IQ_CMD_FL0PADEN(x) ((x) << 2) -#define FW_IQ_CMD_FL0PACKEN(x) ((x) << 1) -#define FW_IQ_CMD_FL0CONGEN (1U << 0) - -#define FW_IQ_CMD_FL0DCAEN(x) ((x) << 15) -#define FW_IQ_CMD_FL0DCACPU(x) ((x) << 10) -#define FW_IQ_CMD_FL0FBMIN(x) ((x) << 7) -#define FW_IQ_CMD_FL0FBMAX(x) ((x) << 4) -#define FW_IQ_CMD_FL0CIDXFTHRESHO (1U << 3) -#define FW_IQ_CMD_FL0CIDXFTHRESH(x) ((x) << 0) - -#define FW_IQ_CMD_FL1CNGCHMAP(x) ((x) << 20) -#define FW_IQ_CMD_FL1CACHELOCK(x) ((x) << 15) -#define FW_IQ_CMD_FL1DBP(x) ((x) << 14) -#define FW_IQ_CMD_FL1DATANS(x) ((x) << 13) -#define FW_IQ_CMD_FL1DATARO(x) ((x) << 12) -#define FW_IQ_CMD_FL1CONGCIF(x) ((x) << 11) -#define FW_IQ_CMD_FL1ONCHIP(x) ((x) << 10) -#define FW_IQ_CMD_FL1STATUSPGNS(x) ((x) << 9) -#define FW_IQ_CMD_FL1STATUSPGRO(x) ((x) << 8) -#define FW_IQ_CMD_FL1FETCHNS(x) ((x) << 7) -#define FW_IQ_CMD_FL1FETCHRO(x) ((x) << 6) -#define FW_IQ_CMD_FL1HOSTFCMODE(x) ((x) << 4) -#define FW_IQ_CMD_FL1CPRIO(x) ((x) << 3) -#define FW_IQ_CMD_FL1PADEN (1U << 2) -#define FW_IQ_CMD_FL1PACKEN (1U << 1) -#define FW_IQ_CMD_FL1CONGEN (1U << 0) - -#define FW_IQ_CMD_FL1DCAEN(x) ((x) << 15) -#define FW_IQ_CMD_FL1DCACPU(x) ((x) << 10) -#define FW_IQ_CMD_FL1FBMIN(x) ((x) << 7) -#define FW_IQ_CMD_FL1FBMAX(x) ((x) << 4) -#define FW_IQ_CMD_FL1CIDXFTHRESHO (1U << 3) -#define FW_IQ_CMD_FL1CIDXFTHRESH(x) ((x) << 0) +#define FW_IQ_CMD_PFN_S 8 +#define FW_IQ_CMD_PFN_V(x) ((x) << FW_IQ_CMD_PFN_S) + +#define FW_IQ_CMD_VFN_S 0 +#define FW_IQ_CMD_VFN_V(x) ((x) << FW_IQ_CMD_VFN_S) + +#define FW_IQ_CMD_ALLOC_S 31 +#define FW_IQ_CMD_ALLOC_V(x) ((x) << FW_IQ_CMD_ALLOC_S) +#define FW_IQ_CMD_ALLOC_F FW_IQ_CMD_ALLOC_V(1U) + +#define FW_IQ_CMD_FREE_S 30 +#define FW_IQ_CMD_FREE_V(x) ((x) << FW_IQ_CMD_FREE_S) +#define FW_IQ_CMD_FREE_F FW_IQ_CMD_FREE_V(1U) + +#define FW_IQ_CMD_MODIFY_S 29 +#define FW_IQ_CMD_MODIFY_V(x) ((x) << FW_IQ_CMD_MODIFY_S) +#define FW_IQ_CMD_MODIFY_F FW_IQ_CMD_MODIFY_V(1U) + +#define FW_IQ_CMD_IQSTART_S 28 +#define FW_IQ_CMD_IQSTART_V(x) ((x) << FW_IQ_CMD_IQSTART_S) +#define FW_IQ_CMD_IQSTART_F FW_IQ_CMD_IQSTART_V(1U) + +#define FW_IQ_CMD_IQSTOP_S 27 +#define FW_IQ_CMD_IQSTOP_V(x) ((x) << FW_IQ_CMD_IQSTOP_S) +#define FW_IQ_CMD_IQSTOP_F FW_IQ_CMD_IQSTOP_V(1U) + +#define FW_IQ_CMD_TYPE_S 29 +#define FW_IQ_CMD_TYPE_V(x) ((x) << FW_IQ_CMD_TYPE_S) + +#define FW_IQ_CMD_IQASYNCH_S 28 +#define FW_IQ_CMD_IQASYNCH_V(x) ((x) << FW_IQ_CMD_IQASYNCH_S) + +#define FW_IQ_CMD_VIID_S 16 +#define FW_IQ_CMD_VIID_V(x) ((x) << FW_IQ_CMD_VIID_S) + +#define FW_IQ_CMD_IQANDST_S 15 +#define FW_IQ_CMD_IQANDST_V(x) ((x) << FW_IQ_CMD_IQANDST_S) + +#define FW_IQ_CMD_IQANUS_S 14 +#define FW_IQ_CMD_IQANUS_V(x) ((x) << FW_IQ_CMD_IQANUS_S) + +#define FW_IQ_CMD_IQANUD_S 12 +#define FW_IQ_CMD_IQANUD_V(x) ((x) << FW_IQ_CMD_IQANUD_S) + +#define FW_IQ_CMD_IQANDSTINDEX_S 0 +#define FW_IQ_CMD_IQANDSTINDEX_V(x) ((x) << FW_IQ_CMD_IQANDSTINDEX_S) + +#define FW_IQ_CMD_IQDROPRSS_S 15 +#define FW_IQ_CMD_IQDROPRSS_V(x) ((x) << FW_IQ_CMD_IQDROPRSS_S) +#define FW_IQ_CMD_IQDROPRSS_F FW_IQ_CMD_IQDROPRSS_V(1U) + +#define FW_IQ_CMD_IQGTSMODE_S 14 +#define FW_IQ_CMD_IQGTSMODE_V(x) ((x) << FW_IQ_CMD_IQGTSMODE_S) +#define FW_IQ_CMD_IQGTSMODE_F FW_IQ_CMD_IQGTSMODE_V(1U) + +#define FW_IQ_CMD_IQPCIECH_S 12 +#define FW_IQ_CMD_IQPCIECH_V(x) ((x) << FW_IQ_CMD_IQPCIECH_S) + +#define FW_IQ_CMD_IQDCAEN_S 11 +#define FW_IQ_CMD_IQDCAEN_V(x) ((x) << FW_IQ_CMD_IQDCAEN_S) + +#define FW_IQ_CMD_IQDCACPU_S 6 +#define FW_IQ_CMD_IQDCACPU_V(x) ((x) << FW_IQ_CMD_IQDCACPU_S) + +#define FW_IQ_CMD_IQINTCNTTHRESH_S 4 +#define FW_IQ_CMD_IQINTCNTTHRESH_V(x) ((x) << FW_IQ_CMD_IQINTCNTTHRESH_S) + +#define FW_IQ_CMD_IQO_S 3 +#define FW_IQ_CMD_IQO_V(x) ((x) << FW_IQ_CMD_IQO_S) +#define FW_IQ_CMD_IQO_F FW_IQ_CMD_IQO_V(1U) + +#define FW_IQ_CMD_IQCPRIO_S 2 +#define FW_IQ_CMD_IQCPRIO_V(x) ((x) << FW_IQ_CMD_IQCPRIO_S) + +#define FW_IQ_CMD_IQESIZE_S 0 +#define FW_IQ_CMD_IQESIZE_V(x) ((x) << FW_IQ_CMD_IQESIZE_S) + +#define FW_IQ_CMD_IQNS_S 31 +#define FW_IQ_CMD_IQNS_V(x) ((x) << FW_IQ_CMD_IQNS_S) + +#define FW_IQ_CMD_IQRO_S 30 +#define FW_IQ_CMD_IQRO_V(x) ((x) << FW_IQ_CMD_IQRO_S) + +#define FW_IQ_CMD_IQFLINTIQHSEN_S 28 +#define FW_IQ_CMD_IQFLINTIQHSEN_V(x) ((x) << FW_IQ_CMD_IQFLINTIQHSEN_S) + +#define FW_IQ_CMD_IQFLINTCONGEN_S 27 +#define FW_IQ_CMD_IQFLINTCONGEN_V(x) ((x) << FW_IQ_CMD_IQFLINTCONGEN_S) + +#define FW_IQ_CMD_IQFLINTISCSIC_S 26 +#define FW_IQ_CMD_IQFLINTISCSIC_V(x) ((x) << FW_IQ_CMD_IQFLINTISCSIC_S) + +#define FW_IQ_CMD_FL0CNGCHMAP_S 20 +#define FW_IQ_CMD_FL0CNGCHMAP_V(x) ((x) << FW_IQ_CMD_FL0CNGCHMAP_S) + +#define FW_IQ_CMD_FL0CACHELOCK_S 15 +#define FW_IQ_CMD_FL0CACHELOCK_V(x) ((x) << FW_IQ_CMD_FL0CACHELOCK_S) + +#define FW_IQ_CMD_FL0DBP_S 14 +#define FW_IQ_CMD_FL0DBP_V(x) ((x) << FW_IQ_CMD_FL0DBP_S) + +#define FW_IQ_CMD_FL0DATANS_S 13 +#define FW_IQ_CMD_FL0DATANS_V(x) ((x) << FW_IQ_CMD_FL0DATANS_S) + +#define FW_IQ_CMD_FL0DATARO_S 12 +#define FW_IQ_CMD_FL0DATARO_V(x) ((x) << FW_IQ_CMD_FL0DATARO_S) +#define FW_IQ_CMD_FL0DATARO_F FW_IQ_CMD_FL0DATARO_V(1U) + +#define FW_IQ_CMD_FL0CONGCIF_S 11 +#define FW_IQ_CMD_FL0CONGCIF_V(x) ((x) << FW_IQ_CMD_FL0CONGCIF_S) + +#define FW_IQ_CMD_FL0ONCHIP_S 10 +#define FW_IQ_CMD_FL0ONCHIP_V(x) ((x) << FW_IQ_CMD_FL0ONCHIP_S) + +#define FW_IQ_CMD_FL0STATUSPGNS_S 9 +#define FW_IQ_CMD_FL0STATUSPGNS_V(x) ((x) << FW_IQ_CMD_FL0STATUSPGNS_S) + +#define FW_IQ_CMD_FL0STATUSPGRO_S 8 +#define FW_IQ_CMD_FL0STATUSPGRO_V(x) ((x) << FW_IQ_CMD_FL0STATUSPGRO_S) + +#define FW_IQ_CMD_FL0FETCHNS_S 7 +#define FW_IQ_CMD_FL0FETCHNS_V(x) ((x) << FW_IQ_CMD_FL0FETCHNS_S) + +#define FW_IQ_CMD_FL0FETCHRO_S 6 +#define FW_IQ_CMD_FL0FETCHRO_V(x) ((x) << FW_IQ_CMD_FL0FETCHRO_S) +#define FW_IQ_CMD_FL0FETCHRO_F FW_IQ_CMD_FL0FETCHRO_V(1U) + +#define FW_IQ_CMD_FL0HOSTFCMODE_S 4 +#define FW_IQ_CMD_FL0HOSTFCMODE_V(x) ((x) << FW_IQ_CMD_FL0HOSTFCMODE_S) + +#define FW_IQ_CMD_FL0CPRIO_S 3 +#define FW_IQ_CMD_FL0CPRIO_V(x) ((x) << FW_IQ_CMD_FL0CPRIO_S) + +#define FW_IQ_CMD_FL0PADEN_S 2 +#define FW_IQ_CMD_FL0PADEN_V(x) ((x) << FW_IQ_CMD_FL0PADEN_S) +#define FW_IQ_CMD_FL0PADEN_F FW_IQ_CMD_FL0PADEN_V(1U) + +#define FW_IQ_CMD_FL0PACKEN_S 1 +#define FW_IQ_CMD_FL0PACKEN_V(x) ((x) << FW_IQ_CMD_FL0PACKEN_S) +#define FW_IQ_CMD_FL0PACKEN_F FW_IQ_CMD_FL0PACKEN_V(1U) + +#define FW_IQ_CMD_FL0CONGEN_S 0 +#define FW_IQ_CMD_FL0CONGEN_V(x) ((x) << FW_IQ_CMD_FL0CONGEN_S) +#define FW_IQ_CMD_FL0CONGEN_F FW_IQ_CMD_FL0CONGEN_V(1U) + +#define FW_IQ_CMD_FL0DCAEN_S 15 +#define FW_IQ_CMD_FL0DCAEN_V(x) ((x) << FW_IQ_CMD_FL0DCAEN_S) + +#define FW_IQ_CMD_FL0DCACPU_S 10 +#define FW_IQ_CMD_FL0DCACPU_V(x) ((x) << FW_IQ_CMD_FL0DCACPU_S) + +#define FW_IQ_CMD_FL0FBMIN_S 7 +#define FW_IQ_CMD_FL0FBMIN_V(x) ((x) << FW_IQ_CMD_FL0FBMIN_S) + +#define FW_IQ_CMD_FL0FBMAX_S 4 +#define FW_IQ_CMD_FL0FBMAX_V(x) ((x) << FW_IQ_CMD_FL0FBMAX_S) + +#define FW_IQ_CMD_FL0CIDXFTHRESHO_S 3 +#define FW_IQ_CMD_FL0CIDXFTHRESHO_V(x) ((x) << FW_IQ_CMD_FL0CIDXFTHRESHO_S) +#define FW_IQ_CMD_FL0CIDXFTHRESHO_F FW_IQ_CMD_FL0CIDXFTHRESHO_V(1U) + +#define FW_IQ_CMD_FL0CIDXFTHRESH_S 0 +#define FW_IQ_CMD_FL0CIDXFTHRESH_V(x) ((x) << FW_IQ_CMD_FL0CIDXFTHRESH_S) + +#define FW_IQ_CMD_FL1CNGCHMAP_S 20 +#define FW_IQ_CMD_FL1CNGCHMAP_V(x) ((x) << FW_IQ_CMD_FL1CNGCHMAP_S) + +#define FW_IQ_CMD_FL1CACHELOCK_S 15 +#define FW_IQ_CMD_FL1CACHELOCK_V(x) ((x) << FW_IQ_CMD_FL1CACHELOCK_S) + +#define FW_IQ_CMD_FL1DBP_S 14 +#define FW_IQ_CMD_FL1DBP_V(x) ((x) << FW_IQ_CMD_FL1DBP_S) + +#define FW_IQ_CMD_FL1DATANS_S 13 +#define FW_IQ_CMD_FL1DATANS_V(x) ((x) << FW_IQ_CMD_FL1DATANS_S) + +#define FW_IQ_CMD_FL1DATARO_S 12 +#define FW_IQ_CMD_FL1DATARO_V(x) ((x) << FW_IQ_CMD_FL1DATARO_S) + +#define FW_IQ_CMD_FL1CONGCIF_S 11 +#define FW_IQ_CMD_FL1CONGCIF_V(x) ((x) << FW_IQ_CMD_FL1CONGCIF_S) + +#define FW_IQ_CMD_FL1ONCHIP_S 10 +#define FW_IQ_CMD_FL1ONCHIP_V(x) ((x) << FW_IQ_CMD_FL1ONCHIP_S) + +#define FW_IQ_CMD_FL1STATUSPGNS_S 9 +#define FW_IQ_CMD_FL1STATUSPGNS_V(x) ((x) << FW_IQ_CMD_FL1STATUSPGNS_S) + +#define FW_IQ_CMD_FL1STATUSPGRO_S 8 +#define FW_IQ_CMD_FL1STATUSPGRO_V(x) ((x) << FW_IQ_CMD_FL1STATUSPGRO_S) + +#define FW_IQ_CMD_FL1FETCHNS_S 7 +#define FW_IQ_CMD_FL1FETCHNS_V(x) ((x) << FW_IQ_CMD_FL1FETCHNS_S) + +#define FW_IQ_CMD_FL1FETCHRO_S 6 +#define FW_IQ_CMD_FL1FETCHRO_V(x) ((x) << FW_IQ_CMD_FL1FETCHRO_S) + +#define FW_IQ_CMD_FL1HOSTFCMODE_S 4 +#define FW_IQ_CMD_FL1HOSTFCMODE_V(x) ((x) << FW_IQ_CMD_FL1HOSTFCMODE_S) + +#define FW_IQ_CMD_FL1CPRIO_S 3 +#define FW_IQ_CMD_FL1CPRIO_V(x) ((x) << FW_IQ_CMD_FL1CPRIO_S) + +#define FW_IQ_CMD_FL1PADEN_S 2 +#define FW_IQ_CMD_FL1PADEN_V(x) ((x) << FW_IQ_CMD_FL1PADEN_S) +#define FW_IQ_CMD_FL1PADEN_F FW_IQ_CMD_FL1PADEN_V(1U) + +#define FW_IQ_CMD_FL1PACKEN_S 1 +#define FW_IQ_CMD_FL1PACKEN_V(x) ((x) << FW_IQ_CMD_FL1PACKEN_S) +#define FW_IQ_CMD_FL1PACKEN_F FW_IQ_CMD_FL1PACKEN_V(1U) + +#define FW_IQ_CMD_FL1CONGEN_S 0 +#define FW_IQ_CMD_FL1CONGEN_V(x) ((x) << FW_IQ_CMD_FL1CONGEN_S) +#define FW_IQ_CMD_FL1CONGEN_F FW_IQ_CMD_FL1CONGEN_V(1U) + +#define FW_IQ_CMD_FL1DCAEN_S 15 +#define FW_IQ_CMD_FL1DCAEN_V(x) ((x) << FW_IQ_CMD_FL1DCAEN_S) + +#define FW_IQ_CMD_FL1DCACPU_S 10 +#define FW_IQ_CMD_FL1DCACPU_V(x) ((x) << FW_IQ_CMD_FL1DCACPU_S) + +#define FW_IQ_CMD_FL1FBMIN_S 7 +#define FW_IQ_CMD_FL1FBMIN_V(x) ((x) << FW_IQ_CMD_FL1FBMIN_S) + +#define FW_IQ_CMD_FL1FBMAX_S 4 +#define FW_IQ_CMD_FL1FBMAX_V(x) ((x) << FW_IQ_CMD_FL1FBMAX_S) + +#define FW_IQ_CMD_FL1CIDXFTHRESHO_S 3 +#define FW_IQ_CMD_FL1CIDXFTHRESHO_V(x) ((x) << FW_IQ_CMD_FL1CIDXFTHRESHO_S) +#define FW_IQ_CMD_FL1CIDXFTHRESHO_F FW_IQ_CMD_FL1CIDXFTHRESHO_V(1U) + +#define FW_IQ_CMD_FL1CIDXFTHRESH_S 0 +#define FW_IQ_CMD_FL1CIDXFTHRESH_V(x) ((x) << FW_IQ_CMD_FL1CIDXFTHRESH_S) struct fw_eq_eth_cmd { __be32 op_to_vfn; @@ -1195,40 +1520,102 @@ struct fw_eq_eth_cmd { __be64 r9; }; -#define FW_EQ_ETH_CMD_PFN(x) ((x) << 8) -#define FW_EQ_ETH_CMD_VFN(x) ((x) << 0) -#define FW_EQ_ETH_CMD_ALLOC (1U << 31) -#define FW_EQ_ETH_CMD_FREE (1U << 30) -#define FW_EQ_ETH_CMD_MODIFY (1U << 29) -#define FW_EQ_ETH_CMD_EQSTART (1U << 28) -#define FW_EQ_ETH_CMD_EQSTOP (1U << 27) - -#define FW_EQ_ETH_CMD_EQID(x) ((x) << 0) -#define FW_EQ_ETH_CMD_EQID_GET(x) (((x) >> 0) & 0xfffff) -#define FW_EQ_ETH_CMD_PHYSEQID(x) ((x) << 0) -#define FW_EQ_ETH_CMD_PHYSEQID_GET(x) (((x) >> 0) & 0xfffff) - -#define FW_EQ_ETH_CMD_FETCHSZM(x) ((x) << 26) -#define FW_EQ_ETH_CMD_STATUSPGNS(x) ((x) << 25) -#define FW_EQ_ETH_CMD_STATUSPGRO(x) ((x) << 24) -#define FW_EQ_ETH_CMD_FETCHNS(x) ((x) << 23) -#define FW_EQ_ETH_CMD_FETCHRO(x) ((x) << 22) -#define FW_EQ_ETH_CMD_HOSTFCMODE(x) ((x) << 20) -#define FW_EQ_ETH_CMD_CPRIO(x) ((x) << 19) -#define FW_EQ_ETH_CMD_ONCHIP(x) ((x) << 18) -#define FW_EQ_ETH_CMD_PCIECHN(x) ((x) << 16) -#define FW_EQ_ETH_CMD_IQID(x) ((x) << 0) - -#define FW_EQ_ETH_CMD_DCAEN(x) ((x) << 31) -#define FW_EQ_ETH_CMD_DCACPU(x) ((x) << 26) -#define FW_EQ_ETH_CMD_FBMIN(x) ((x) << 23) -#define FW_EQ_ETH_CMD_FBMAX(x) ((x) << 20) -#define FW_EQ_ETH_CMD_CIDXFTHRESHO(x) ((x) << 19) -#define FW_EQ_ETH_CMD_CIDXFTHRESH(x) ((x) << 16) -#define FW_EQ_ETH_CMD_EQSIZE(x) ((x) << 0) - -#define FW_EQ_ETH_CMD_AUTOEQUEQE (1U << 30) -#define FW_EQ_ETH_CMD_VIID(x) ((x) << 16) +#define FW_EQ_ETH_CMD_PFN_S 8 +#define FW_EQ_ETH_CMD_PFN_V(x) ((x) << FW_EQ_ETH_CMD_PFN_S) + +#define FW_EQ_ETH_CMD_VFN_S 0 +#define FW_EQ_ETH_CMD_VFN_V(x) ((x) << FW_EQ_ETH_CMD_VFN_S) + +#define FW_EQ_ETH_CMD_ALLOC_S 31 +#define FW_EQ_ETH_CMD_ALLOC_V(x) ((x) << FW_EQ_ETH_CMD_ALLOC_S) +#define FW_EQ_ETH_CMD_ALLOC_F FW_EQ_ETH_CMD_ALLOC_V(1U) + +#define FW_EQ_ETH_CMD_FREE_S 30 +#define FW_EQ_ETH_CMD_FREE_V(x) ((x) << FW_EQ_ETH_CMD_FREE_S) +#define FW_EQ_ETH_CMD_FREE_F FW_EQ_ETH_CMD_FREE_V(1U) + +#define FW_EQ_ETH_CMD_MODIFY_S 29 +#define FW_EQ_ETH_CMD_MODIFY_V(x) ((x) << FW_EQ_ETH_CMD_MODIFY_S) +#define FW_EQ_ETH_CMD_MODIFY_F FW_EQ_ETH_CMD_MODIFY_V(1U) + +#define FW_EQ_ETH_CMD_EQSTART_S 28 +#define FW_EQ_ETH_CMD_EQSTART_V(x) ((x) << FW_EQ_ETH_CMD_EQSTART_S) +#define FW_EQ_ETH_CMD_EQSTART_F FW_EQ_ETH_CMD_EQSTART_V(1U) + +#define FW_EQ_ETH_CMD_EQSTOP_S 27 +#define FW_EQ_ETH_CMD_EQSTOP_V(x) ((x) << FW_EQ_ETH_CMD_EQSTOP_S) +#define FW_EQ_ETH_CMD_EQSTOP_F FW_EQ_ETH_CMD_EQSTOP_V(1U) + +#define FW_EQ_ETH_CMD_EQID_S 0 +#define FW_EQ_ETH_CMD_EQID_M 0xfffff +#define FW_EQ_ETH_CMD_EQID_V(x) ((x) << FW_EQ_ETH_CMD_EQID_S) +#define FW_EQ_ETH_CMD_EQID_G(x) \ + (((x) >> FW_EQ_ETH_CMD_EQID_S) & FW_EQ_ETH_CMD_EQID_M) + +#define FW_EQ_ETH_CMD_PHYSEQID_S 0 +#define FW_EQ_ETH_CMD_PHYSEQID_M 0xfffff +#define FW_EQ_ETH_CMD_PHYSEQID_V(x) ((x) << FW_EQ_ETH_CMD_PHYSEQID_S) +#define FW_EQ_ETH_CMD_PHYSEQID_G(x) \ + (((x) >> FW_EQ_ETH_CMD_PHYSEQID_S) & FW_EQ_ETH_CMD_PHYSEQID_M) + +#define FW_EQ_ETH_CMD_FETCHSZM_S 26 +#define FW_EQ_ETH_CMD_FETCHSZM_V(x) ((x) << FW_EQ_ETH_CMD_FETCHSZM_S) +#define FW_EQ_ETH_CMD_FETCHSZM_F FW_EQ_ETH_CMD_FETCHSZM_V(1U) + +#define FW_EQ_ETH_CMD_STATUSPGNS_S 25 +#define FW_EQ_ETH_CMD_STATUSPGNS_V(x) ((x) << FW_EQ_ETH_CMD_STATUSPGNS_S) + +#define FW_EQ_ETH_CMD_STATUSPGRO_S 24 +#define FW_EQ_ETH_CMD_STATUSPGRO_V(x) ((x) << FW_EQ_ETH_CMD_STATUSPGRO_S) + +#define FW_EQ_ETH_CMD_FETCHNS_S 23 +#define FW_EQ_ETH_CMD_FETCHNS_V(x) ((x) << FW_EQ_ETH_CMD_FETCHNS_S) + +#define FW_EQ_ETH_CMD_FETCHRO_S 22 +#define FW_EQ_ETH_CMD_FETCHRO_V(x) ((x) << FW_EQ_ETH_CMD_FETCHRO_S) + +#define FW_EQ_ETH_CMD_HOSTFCMODE_S 20 +#define FW_EQ_ETH_CMD_HOSTFCMODE_V(x) ((x) << FW_EQ_ETH_CMD_HOSTFCMODE_S) + +#define FW_EQ_ETH_CMD_CPRIO_S 19 +#define FW_EQ_ETH_CMD_CPRIO_V(x) ((x) << FW_EQ_ETH_CMD_CPRIO_S) + +#define FW_EQ_ETH_CMD_ONCHIP_S 18 +#define FW_EQ_ETH_CMD_ONCHIP_V(x) ((x) << FW_EQ_ETH_CMD_ONCHIP_S) + +#define FW_EQ_ETH_CMD_PCIECHN_S 16 +#define FW_EQ_ETH_CMD_PCIECHN_V(x) ((x) << FW_EQ_ETH_CMD_PCIECHN_S) + +#define FW_EQ_ETH_CMD_IQID_S 0 +#define FW_EQ_ETH_CMD_IQID_V(x) ((x) << FW_EQ_ETH_CMD_IQID_S) + +#define FW_EQ_ETH_CMD_DCAEN_S 31 +#define FW_EQ_ETH_CMD_DCAEN_V(x) ((x) << FW_EQ_ETH_CMD_DCAEN_S) + +#define FW_EQ_ETH_CMD_DCACPU_S 26 +#define FW_EQ_ETH_CMD_DCACPU_V(x) ((x) << FW_EQ_ETH_CMD_DCACPU_S) + +#define FW_EQ_ETH_CMD_FBMIN_S 23 +#define FW_EQ_ETH_CMD_FBMIN_V(x) ((x) << FW_EQ_ETH_CMD_FBMIN_S) + +#define FW_EQ_ETH_CMD_FBMAX_S 20 +#define FW_EQ_ETH_CMD_FBMAX_V(x) ((x) << FW_EQ_ETH_CMD_FBMAX_S) + +#define FW_EQ_ETH_CMD_CIDXFTHRESHO_S 19 +#define FW_EQ_ETH_CMD_CIDXFTHRESHO_V(x) ((x) << FW_EQ_ETH_CMD_CIDXFTHRESHO_S) + +#define FW_EQ_ETH_CMD_CIDXFTHRESH_S 16 +#define FW_EQ_ETH_CMD_CIDXFTHRESH_V(x) ((x) << FW_EQ_ETH_CMD_CIDXFTHRESH_S) + +#define FW_EQ_ETH_CMD_EQSIZE_S 0 +#define FW_EQ_ETH_CMD_EQSIZE_V(x) ((x) << FW_EQ_ETH_CMD_EQSIZE_S) + +#define FW_EQ_ETH_CMD_AUTOEQUEQE_S 30 +#define FW_EQ_ETH_CMD_AUTOEQUEQE_V(x) ((x) << FW_EQ_ETH_CMD_AUTOEQUEQE_S) +#define FW_EQ_ETH_CMD_AUTOEQUEQE_F FW_EQ_ETH_CMD_AUTOEQUEQE_V(1U) + +#define FW_EQ_ETH_CMD_VIID_S 16 +#define FW_EQ_ETH_CMD_VIID_V(x) ((x) << FW_EQ_ETH_CMD_VIID_S) struct fw_eq_ctrl_cmd { __be32 op_to_vfn; @@ -1240,38 +1627,102 @@ struct fw_eq_ctrl_cmd { __be64 eqaddr; }; -#define FW_EQ_CTRL_CMD_PFN(x) ((x) << 8) -#define FW_EQ_CTRL_CMD_VFN(x) ((x) << 0) - -#define FW_EQ_CTRL_CMD_ALLOC (1U << 31) -#define FW_EQ_CTRL_CMD_FREE (1U << 30) -#define FW_EQ_CTRL_CMD_MODIFY (1U << 29) -#define FW_EQ_CTRL_CMD_EQSTART (1U << 28) -#define FW_EQ_CTRL_CMD_EQSTOP (1U << 27) - -#define FW_EQ_CTRL_CMD_CMPLIQID(x) ((x) << 20) -#define FW_EQ_CTRL_CMD_EQID(x) ((x) << 0) -#define FW_EQ_CTRL_CMD_EQID_GET(x) (((x) >> 0) & 0xfffff) -#define FW_EQ_CTRL_CMD_PHYSEQID_GET(x) (((x) >> 0) & 0xfffff) - -#define FW_EQ_CTRL_CMD_FETCHSZM (1U << 26) -#define FW_EQ_CTRL_CMD_STATUSPGNS (1U << 25) -#define FW_EQ_CTRL_CMD_STATUSPGRO (1U << 24) -#define FW_EQ_CTRL_CMD_FETCHNS (1U << 23) -#define FW_EQ_CTRL_CMD_FETCHRO (1U << 22) -#define FW_EQ_CTRL_CMD_HOSTFCMODE(x) ((x) << 20) -#define FW_EQ_CTRL_CMD_CPRIO(x) ((x) << 19) -#define FW_EQ_CTRL_CMD_ONCHIP(x) ((x) << 18) -#define FW_EQ_CTRL_CMD_PCIECHN(x) ((x) << 16) -#define FW_EQ_CTRL_CMD_IQID(x) ((x) << 0) - -#define FW_EQ_CTRL_CMD_DCAEN(x) ((x) << 31) -#define FW_EQ_CTRL_CMD_DCACPU(x) ((x) << 26) -#define FW_EQ_CTRL_CMD_FBMIN(x) ((x) << 23) -#define FW_EQ_CTRL_CMD_FBMAX(x) ((x) << 20) -#define FW_EQ_CTRL_CMD_CIDXFTHRESHO(x) ((x) << 19) -#define FW_EQ_CTRL_CMD_CIDXFTHRESH(x) ((x) << 16) -#define FW_EQ_CTRL_CMD_EQSIZE(x) ((x) << 0) +#define FW_EQ_CTRL_CMD_PFN_S 8 +#define FW_EQ_CTRL_CMD_PFN_V(x) ((x) << FW_EQ_CTRL_CMD_PFN_S) + +#define FW_EQ_CTRL_CMD_VFN_S 0 +#define FW_EQ_CTRL_CMD_VFN_V(x) ((x) << FW_EQ_CTRL_CMD_VFN_S) + +#define FW_EQ_CTRL_CMD_ALLOC_S 31 +#define FW_EQ_CTRL_CMD_ALLOC_V(x) ((x) << FW_EQ_CTRL_CMD_ALLOC_S) +#define FW_EQ_CTRL_CMD_ALLOC_F FW_EQ_CTRL_CMD_ALLOC_V(1U) + +#define FW_EQ_CTRL_CMD_FREE_S 30 +#define FW_EQ_CTRL_CMD_FREE_V(x) ((x) << FW_EQ_CTRL_CMD_FREE_S) +#define FW_EQ_CTRL_CMD_FREE_F FW_EQ_CTRL_CMD_FREE_V(1U) + +#define FW_EQ_CTRL_CMD_MODIFY_S 29 +#define FW_EQ_CTRL_CMD_MODIFY_V(x) ((x) << FW_EQ_CTRL_CMD_MODIFY_S) +#define FW_EQ_CTRL_CMD_MODIFY_F FW_EQ_CTRL_CMD_MODIFY_V(1U) + +#define FW_EQ_CTRL_CMD_EQSTART_S 28 +#define FW_EQ_CTRL_CMD_EQSTART_V(x) ((x) << FW_EQ_CTRL_CMD_EQSTART_S) +#define FW_EQ_CTRL_CMD_EQSTART_F FW_EQ_CTRL_CMD_EQSTART_V(1U) + +#define FW_EQ_CTRL_CMD_EQSTOP_S 27 +#define FW_EQ_CTRL_CMD_EQSTOP_V(x) ((x) << FW_EQ_CTRL_CMD_EQSTOP_S) +#define FW_EQ_CTRL_CMD_EQSTOP_F FW_EQ_CTRL_CMD_EQSTOP_V(1U) + +#define FW_EQ_CTRL_CMD_CMPLIQID_S 20 +#define FW_EQ_CTRL_CMD_CMPLIQID_V(x) ((x) << FW_EQ_CTRL_CMD_CMPLIQID_S) + +#define FW_EQ_CTRL_CMD_EQID_S 0 +#define FW_EQ_CTRL_CMD_EQID_M 0xfffff +#define FW_EQ_CTRL_CMD_EQID_V(x) ((x) << FW_EQ_CTRL_CMD_EQID_S) +#define FW_EQ_CTRL_CMD_EQID_G(x) \ + (((x) >> FW_EQ_CTRL_CMD_EQID_S) & FW_EQ_CTRL_CMD_EQID_M) + +#define FW_EQ_CTRL_CMD_PHYSEQID_S 0 +#define FW_EQ_CTRL_CMD_PHYSEQID_M 0xfffff +#define FW_EQ_CTRL_CMD_PHYSEQID_G(x) \ + (((x) >> FW_EQ_CTRL_CMD_PHYSEQID_S) & FW_EQ_CTRL_CMD_PHYSEQID_M) + +#define FW_EQ_CTRL_CMD_FETCHSZM_S 26 +#define FW_EQ_CTRL_CMD_FETCHSZM_V(x) ((x) << FW_EQ_CTRL_CMD_FETCHSZM_S) +#define FW_EQ_CTRL_CMD_FETCHSZM_F FW_EQ_CTRL_CMD_FETCHSZM_V(1U) + +#define FW_EQ_CTRL_CMD_STATUSPGNS_S 25 +#define FW_EQ_CTRL_CMD_STATUSPGNS_V(x) ((x) << FW_EQ_CTRL_CMD_STATUSPGNS_S) +#define FW_EQ_CTRL_CMD_STATUSPGNS_F FW_EQ_CTRL_CMD_STATUSPGNS_V(1U) + +#define FW_EQ_CTRL_CMD_STATUSPGRO_S 24 +#define FW_EQ_CTRL_CMD_STATUSPGRO_V(x) ((x) << FW_EQ_CTRL_CMD_STATUSPGRO_S) +#define FW_EQ_CTRL_CMD_STATUSPGRO_F FW_EQ_CTRL_CMD_STATUSPGRO_V(1U) + +#define FW_EQ_CTRL_CMD_FETCHNS_S 23 +#define FW_EQ_CTRL_CMD_FETCHNS_V(x) ((x) << FW_EQ_CTRL_CMD_FETCHNS_S) +#define FW_EQ_CTRL_CMD_FETCHNS_F FW_EQ_CTRL_CMD_FETCHNS_V(1U) + +#define FW_EQ_CTRL_CMD_FETCHRO_S 22 +#define FW_EQ_CTRL_CMD_FETCHRO_V(x) ((x) << FW_EQ_CTRL_CMD_FETCHRO_S) +#define FW_EQ_CTRL_CMD_FETCHRO_F FW_EQ_CTRL_CMD_FETCHRO_V(1U) + +#define FW_EQ_CTRL_CMD_HOSTFCMODE_S 20 +#define FW_EQ_CTRL_CMD_HOSTFCMODE_V(x) ((x) << FW_EQ_CTRL_CMD_HOSTFCMODE_S) + +#define FW_EQ_CTRL_CMD_CPRIO_S 19 +#define FW_EQ_CTRL_CMD_CPRIO_V(x) ((x) << FW_EQ_CTRL_CMD_CPRIO_S) + +#define FW_EQ_CTRL_CMD_ONCHIP_S 18 +#define FW_EQ_CTRL_CMD_ONCHIP_V(x) ((x) << FW_EQ_CTRL_CMD_ONCHIP_S) + +#define FW_EQ_CTRL_CMD_PCIECHN_S 16 +#define FW_EQ_CTRL_CMD_PCIECHN_V(x) ((x) << FW_EQ_CTRL_CMD_PCIECHN_S) + +#define FW_EQ_CTRL_CMD_IQID_S 0 +#define FW_EQ_CTRL_CMD_IQID_V(x) ((x) << FW_EQ_CTRL_CMD_IQID_S) + +#define FW_EQ_CTRL_CMD_DCAEN_S 31 +#define FW_EQ_CTRL_CMD_DCAEN_V(x) ((x) << FW_EQ_CTRL_CMD_DCAEN_S) + +#define FW_EQ_CTRL_CMD_DCACPU_S 26 +#define FW_EQ_CTRL_CMD_DCACPU_V(x) ((x) << FW_EQ_CTRL_CMD_DCACPU_S) + +#define FW_EQ_CTRL_CMD_FBMIN_S 23 +#define FW_EQ_CTRL_CMD_FBMIN_V(x) ((x) << FW_EQ_CTRL_CMD_FBMIN_S) + +#define FW_EQ_CTRL_CMD_FBMAX_S 20 +#define FW_EQ_CTRL_CMD_FBMAX_V(x) ((x) << FW_EQ_CTRL_CMD_FBMAX_S) + +#define FW_EQ_CTRL_CMD_CIDXFTHRESHO_S 19 +#define FW_EQ_CTRL_CMD_CIDXFTHRESHO_V(x) \ + ((x) << FW_EQ_CTRL_CMD_CIDXFTHRESHO_S) + +#define FW_EQ_CTRL_CMD_CIDXFTHRESH_S 16 +#define FW_EQ_CTRL_CMD_CIDXFTHRESH_V(x) ((x) << FW_EQ_CTRL_CMD_CIDXFTHRESH_S) + +#define FW_EQ_CTRL_CMD_EQSIZE_S 0 +#define FW_EQ_CTRL_CMD_EQSIZE_V(x) ((x) << FW_EQ_CTRL_CMD_EQSIZE_S) struct fw_eq_ofld_cmd { __be32 op_to_vfn; @@ -1283,45 +1734,112 @@ struct fw_eq_ofld_cmd { __be64 eqaddr; }; -#define FW_EQ_OFLD_CMD_PFN(x) ((x) << 8) -#define FW_EQ_OFLD_CMD_VFN(x) ((x) << 0) - -#define FW_EQ_OFLD_CMD_ALLOC (1U << 31) -#define FW_EQ_OFLD_CMD_FREE (1U << 30) -#define FW_EQ_OFLD_CMD_MODIFY (1U << 29) -#define FW_EQ_OFLD_CMD_EQSTART (1U << 28) -#define FW_EQ_OFLD_CMD_EQSTOP (1U << 27) - -#define FW_EQ_OFLD_CMD_EQID(x) ((x) << 0) -#define FW_EQ_OFLD_CMD_EQID_GET(x) (((x) >> 0) & 0xfffff) -#define FW_EQ_OFLD_CMD_PHYSEQID_GET(x) (((x) >> 0) & 0xfffff) - -#define FW_EQ_OFLD_CMD_FETCHSZM(x) ((x) << 26) -#define FW_EQ_OFLD_CMD_STATUSPGNS(x) ((x) << 25) -#define FW_EQ_OFLD_CMD_STATUSPGRO(x) ((x) << 24) -#define FW_EQ_OFLD_CMD_FETCHNS(x) ((x) << 23) -#define FW_EQ_OFLD_CMD_FETCHRO(x) ((x) << 22) -#define FW_EQ_OFLD_CMD_HOSTFCMODE(x) ((x) << 20) -#define FW_EQ_OFLD_CMD_CPRIO(x) ((x) << 19) -#define FW_EQ_OFLD_CMD_ONCHIP(x) ((x) << 18) -#define FW_EQ_OFLD_CMD_PCIECHN(x) ((x) << 16) -#define FW_EQ_OFLD_CMD_IQID(x) ((x) << 0) - -#define FW_EQ_OFLD_CMD_DCAEN(x) ((x) << 31) -#define FW_EQ_OFLD_CMD_DCACPU(x) ((x) << 26) -#define FW_EQ_OFLD_CMD_FBMIN(x) ((x) << 23) -#define FW_EQ_OFLD_CMD_FBMAX(x) ((x) << 20) -#define FW_EQ_OFLD_CMD_CIDXFTHRESHO(x) ((x) << 19) -#define FW_EQ_OFLD_CMD_CIDXFTHRESH(x) ((x) << 16) -#define FW_EQ_OFLD_CMD_EQSIZE(x) ((x) << 0) +#define FW_EQ_OFLD_CMD_PFN_S 8 +#define FW_EQ_OFLD_CMD_PFN_V(x) ((x) << FW_EQ_OFLD_CMD_PFN_S) + +#define FW_EQ_OFLD_CMD_VFN_S 0 +#define FW_EQ_OFLD_CMD_VFN_V(x) ((x) << FW_EQ_OFLD_CMD_VFN_S) + +#define FW_EQ_OFLD_CMD_ALLOC_S 31 +#define FW_EQ_OFLD_CMD_ALLOC_V(x) ((x) << FW_EQ_OFLD_CMD_ALLOC_S) +#define FW_EQ_OFLD_CMD_ALLOC_F FW_EQ_OFLD_CMD_ALLOC_V(1U) + +#define FW_EQ_OFLD_CMD_FREE_S 30 +#define FW_EQ_OFLD_CMD_FREE_V(x) ((x) << FW_EQ_OFLD_CMD_FREE_S) +#define FW_EQ_OFLD_CMD_FREE_F FW_EQ_OFLD_CMD_FREE_V(1U) + +#define FW_EQ_OFLD_CMD_MODIFY_S 29 +#define FW_EQ_OFLD_CMD_MODIFY_V(x) ((x) << FW_EQ_OFLD_CMD_MODIFY_S) +#define FW_EQ_OFLD_CMD_MODIFY_F FW_EQ_OFLD_CMD_MODIFY_V(1U) + +#define FW_EQ_OFLD_CMD_EQSTART_S 28 +#define FW_EQ_OFLD_CMD_EQSTART_V(x) ((x) << FW_EQ_OFLD_CMD_EQSTART_S) +#define FW_EQ_OFLD_CMD_EQSTART_F FW_EQ_OFLD_CMD_EQSTART_V(1U) + +#define FW_EQ_OFLD_CMD_EQSTOP_S 27 +#define FW_EQ_OFLD_CMD_EQSTOP_V(x) ((x) << FW_EQ_OFLD_CMD_EQSTOP_S) +#define FW_EQ_OFLD_CMD_EQSTOP_F FW_EQ_OFLD_CMD_EQSTOP_V(1U) + +#define FW_EQ_OFLD_CMD_EQID_S 0 +#define FW_EQ_OFLD_CMD_EQID_M 0xfffff +#define FW_EQ_OFLD_CMD_EQID_V(x) ((x) << FW_EQ_OFLD_CMD_EQID_S) +#define FW_EQ_OFLD_CMD_EQID_G(x) \ + (((x) >> FW_EQ_OFLD_CMD_EQID_S) & FW_EQ_OFLD_CMD_EQID_M) + +#define FW_EQ_OFLD_CMD_PHYSEQID_S 0 +#define FW_EQ_OFLD_CMD_PHYSEQID_M 0xfffff +#define FW_EQ_OFLD_CMD_PHYSEQID_G(x) \ + (((x) >> FW_EQ_OFLD_CMD_PHYSEQID_S) & FW_EQ_OFLD_CMD_PHYSEQID_M) + +#define FW_EQ_OFLD_CMD_FETCHSZM_S 26 +#define FW_EQ_OFLD_CMD_FETCHSZM_V(x) ((x) << FW_EQ_OFLD_CMD_FETCHSZM_S) + +#define FW_EQ_OFLD_CMD_STATUSPGNS_S 25 +#define FW_EQ_OFLD_CMD_STATUSPGNS_V(x) ((x) << FW_EQ_OFLD_CMD_STATUSPGNS_S) + +#define FW_EQ_OFLD_CMD_STATUSPGRO_S 24 +#define FW_EQ_OFLD_CMD_STATUSPGRO_V(x) ((x) << FW_EQ_OFLD_CMD_STATUSPGRO_S) + +#define FW_EQ_OFLD_CMD_FETCHNS_S 23 +#define FW_EQ_OFLD_CMD_FETCHNS_V(x) ((x) << FW_EQ_OFLD_CMD_FETCHNS_S) + +#define FW_EQ_OFLD_CMD_FETCHRO_S 22 +#define FW_EQ_OFLD_CMD_FETCHRO_V(x) ((x) << FW_EQ_OFLD_CMD_FETCHRO_S) +#define FW_EQ_OFLD_CMD_FETCHRO_F FW_EQ_OFLD_CMD_FETCHRO_V(1U) + +#define FW_EQ_OFLD_CMD_HOSTFCMODE_S 20 +#define FW_EQ_OFLD_CMD_HOSTFCMODE_V(x) ((x) << FW_EQ_OFLD_CMD_HOSTFCMODE_S) + +#define FW_EQ_OFLD_CMD_CPRIO_S 19 +#define FW_EQ_OFLD_CMD_CPRIO_V(x) ((x) << FW_EQ_OFLD_CMD_CPRIO_S) + +#define FW_EQ_OFLD_CMD_ONCHIP_S 18 +#define FW_EQ_OFLD_CMD_ONCHIP_V(x) ((x) << FW_EQ_OFLD_CMD_ONCHIP_S) + +#define FW_EQ_OFLD_CMD_PCIECHN_S 16 +#define FW_EQ_OFLD_CMD_PCIECHN_V(x) ((x) << FW_EQ_OFLD_CMD_PCIECHN_S) + +#define FW_EQ_OFLD_CMD_IQID_S 0 +#define FW_EQ_OFLD_CMD_IQID_V(x) ((x) << FW_EQ_OFLD_CMD_IQID_S) + +#define FW_EQ_OFLD_CMD_DCAEN_S 31 +#define FW_EQ_OFLD_CMD_DCAEN_V(x) ((x) << FW_EQ_OFLD_CMD_DCAEN_S) + +#define FW_EQ_OFLD_CMD_DCACPU_S 26 +#define FW_EQ_OFLD_CMD_DCACPU_V(x) ((x) << FW_EQ_OFLD_CMD_DCACPU_S) + +#define FW_EQ_OFLD_CMD_FBMIN_S 23 +#define FW_EQ_OFLD_CMD_FBMIN_V(x) ((x) << FW_EQ_OFLD_CMD_FBMIN_S) + +#define FW_EQ_OFLD_CMD_FBMAX_S 20 +#define FW_EQ_OFLD_CMD_FBMAX_V(x) ((x) << FW_EQ_OFLD_CMD_FBMAX_S) + +#define FW_EQ_OFLD_CMD_CIDXFTHRESHO_S 19 +#define FW_EQ_OFLD_CMD_CIDXFTHRESHO_V(x) \ + ((x) << FW_EQ_OFLD_CMD_CIDXFTHRESHO_S) + +#define FW_EQ_OFLD_CMD_CIDXFTHRESH_S 16 +#define FW_EQ_OFLD_CMD_CIDXFTHRESH_V(x) ((x) << FW_EQ_OFLD_CMD_CIDXFTHRESH_S) + +#define FW_EQ_OFLD_CMD_EQSIZE_S 0 +#define FW_EQ_OFLD_CMD_EQSIZE_V(x) ((x) << FW_EQ_OFLD_CMD_EQSIZE_S) /* * Macros for VIID parsing: * VIID - [10:8] PFN, [7] VI Valid, [6:0] VI number */ -#define FW_VIID_PFN_GET(x) (((x) >> 8) & 0x7) -#define FW_VIID_VIVLD_GET(x) (((x) >> 7) & 0x1) -#define FW_VIID_VIN_GET(x) (((x) >> 0) & 0x7F) + +#define FW_VIID_PFN_S 8 +#define FW_VIID_PFN_M 0x7 +#define FW_VIID_PFN_G(x) (((x) >> FW_VIID_PFN_S) & FW_VIID_PFN_M) + +#define FW_VIID_VIVLD_S 7 +#define FW_VIID_VIVLD_M 0x1 +#define FW_VIID_VIVLD_G(x) (((x) >> FW_VIID_VIVLD_S) & FW_VIID_VIVLD_M) + +#define FW_VIID_VIN_S 0 +#define FW_VIID_VIN_M 0x7F +#define FW_VIID_VIN_G(x) (((x) >> FW_VIID_VIN_S) & FW_VIID_VIN_M) struct fw_vi_cmd { __be32 op_to_vfn; @@ -1341,15 +1859,35 @@ struct fw_vi_cmd { __be64 r10; }; -#define FW_VI_CMD_PFN(x) ((x) << 8) -#define FW_VI_CMD_VFN(x) ((x) << 0) -#define FW_VI_CMD_ALLOC (1U << 31) -#define FW_VI_CMD_FREE (1U << 30) -#define FW_VI_CMD_VIID(x) ((x) << 0) -#define FW_VI_CMD_VIID_GET(x) ((x) & 0xfff) -#define FW_VI_CMD_PORTID(x) ((x) << 4) -#define FW_VI_CMD_PORTID_GET(x) (((x) >> 4) & 0xf) -#define FW_VI_CMD_RSSSIZE_GET(x) (((x) >> 0) & 0x7ff) +#define FW_VI_CMD_PFN_S 8 +#define FW_VI_CMD_PFN_V(x) ((x) << FW_VI_CMD_PFN_S) + +#define FW_VI_CMD_VFN_S 0 +#define FW_VI_CMD_VFN_V(x) ((x) << FW_VI_CMD_VFN_S) + +#define FW_VI_CMD_ALLOC_S 31 +#define FW_VI_CMD_ALLOC_V(x) ((x) << FW_VI_CMD_ALLOC_S) +#define FW_VI_CMD_ALLOC_F FW_VI_CMD_ALLOC_V(1U) + +#define FW_VI_CMD_FREE_S 30 +#define FW_VI_CMD_FREE_V(x) ((x) << FW_VI_CMD_FREE_S) +#define FW_VI_CMD_FREE_F FW_VI_CMD_FREE_V(1U) + +#define FW_VI_CMD_VIID_S 0 +#define FW_VI_CMD_VIID_M 0xfff +#define FW_VI_CMD_VIID_V(x) ((x) << FW_VI_CMD_VIID_S) +#define FW_VI_CMD_VIID_G(x) (((x) >> FW_VI_CMD_VIID_S) & FW_VI_CMD_VIID_M) + +#define FW_VI_CMD_PORTID_S 4 +#define FW_VI_CMD_PORTID_M 0xf +#define FW_VI_CMD_PORTID_V(x) ((x) << FW_VI_CMD_PORTID_S) +#define FW_VI_CMD_PORTID_G(x) \ + (((x) >> FW_VI_CMD_PORTID_S) & FW_VI_CMD_PORTID_M) + +#define FW_VI_CMD_RSSSIZE_S 0 +#define FW_VI_CMD_RSSSIZE_M 0x7ff +#define FW_VI_CMD_RSSSIZE_G(x) \ + (((x) >> FW_VI_CMD_RSSSIZE_S) & FW_VI_CMD_RSSSIZE_M) /* Special VI_MAC command index ids */ #define FW_VI_MAC_ADD_MAC 0x3FF @@ -1385,16 +1923,37 @@ struct fw_vi_mac_cmd { } u; }; -#define FW_VI_MAC_CMD_VIID(x) ((x) << 0) -#define FW_VI_MAC_CMD_FREEMACS(x) ((x) << 31) -#define FW_VI_MAC_CMD_HASHVECEN (1U << 23) -#define FW_VI_MAC_CMD_HASHUNIEN(x) ((x) << 22) -#define FW_VI_MAC_CMD_VALID (1U << 15) -#define FW_VI_MAC_CMD_PRIO(x) ((x) << 12) -#define FW_VI_MAC_CMD_SMAC_RESULT(x) ((x) << 10) -#define FW_VI_MAC_CMD_SMAC_RESULT_GET(x) (((x) >> 10) & 0x3) -#define FW_VI_MAC_CMD_IDX(x) ((x) << 0) -#define FW_VI_MAC_CMD_IDX_GET(x) (((x) >> 0) & 0x3ff) +#define FW_VI_MAC_CMD_VIID_S 0 +#define FW_VI_MAC_CMD_VIID_V(x) ((x) << FW_VI_MAC_CMD_VIID_S) + +#define FW_VI_MAC_CMD_FREEMACS_S 31 +#define FW_VI_MAC_CMD_FREEMACS_V(x) ((x) << FW_VI_MAC_CMD_FREEMACS_S) + +#define FW_VI_MAC_CMD_HASHVECEN_S 23 +#define FW_VI_MAC_CMD_HASHVECEN_V(x) ((x) << FW_VI_MAC_CMD_HASHVECEN_S) +#define FW_VI_MAC_CMD_HASHVECEN_F FW_VI_MAC_CMD_HASHVECEN_V(1U) + +#define FW_VI_MAC_CMD_HASHUNIEN_S 22 +#define FW_VI_MAC_CMD_HASHUNIEN_V(x) ((x) << FW_VI_MAC_CMD_HASHUNIEN_S) + +#define FW_VI_MAC_CMD_VALID_S 15 +#define FW_VI_MAC_CMD_VALID_V(x) ((x) << FW_VI_MAC_CMD_VALID_S) +#define FW_VI_MAC_CMD_VALID_F FW_VI_MAC_CMD_VALID_V(1U) + +#define FW_VI_MAC_CMD_PRIO_S 12 +#define FW_VI_MAC_CMD_PRIO_V(x) ((x) << FW_VI_MAC_CMD_PRIO_S) + +#define FW_VI_MAC_CMD_SMAC_RESULT_S 10 +#define FW_VI_MAC_CMD_SMAC_RESULT_M 0x3 +#define FW_VI_MAC_CMD_SMAC_RESULT_V(x) ((x) << FW_VI_MAC_CMD_SMAC_RESULT_S) +#define FW_VI_MAC_CMD_SMAC_RESULT_G(x) \ + (((x) >> FW_VI_MAC_CMD_SMAC_RESULT_S) & FW_VI_MAC_CMD_SMAC_RESULT_M) + +#define FW_VI_MAC_CMD_IDX_S 0 +#define FW_VI_MAC_CMD_IDX_M 0x3ff +#define FW_VI_MAC_CMD_IDX_V(x) ((x) << FW_VI_MAC_CMD_IDX_S) +#define FW_VI_MAC_CMD_IDX_G(x) \ + (((x) >> FW_VI_MAC_CMD_IDX_S) & FW_VI_MAC_CMD_IDX_M) #define FW_RXMODE_MTU_NO_CHG 65535 @@ -1405,17 +1964,30 @@ struct fw_vi_rxmode_cmd { __be32 r4_lo; }; -#define FW_VI_RXMODE_CMD_VIID(x) ((x) << 0) -#define FW_VI_RXMODE_CMD_MTU_MASK 0xffff -#define FW_VI_RXMODE_CMD_MTU(x) ((x) << 16) -#define FW_VI_RXMODE_CMD_PROMISCEN_MASK 0x3 -#define FW_VI_RXMODE_CMD_PROMISCEN(x) ((x) << 14) -#define FW_VI_RXMODE_CMD_ALLMULTIEN_MASK 0x3 -#define FW_VI_RXMODE_CMD_ALLMULTIEN(x) ((x) << 12) -#define FW_VI_RXMODE_CMD_BROADCASTEN_MASK 0x3 -#define FW_VI_RXMODE_CMD_BROADCASTEN(x) ((x) << 10) -#define FW_VI_RXMODE_CMD_VLANEXEN_MASK 0x3 -#define FW_VI_RXMODE_CMD_VLANEXEN(x) ((x) << 8) +#define FW_VI_RXMODE_CMD_VIID_S 0 +#define FW_VI_RXMODE_CMD_VIID_V(x) ((x) << FW_VI_RXMODE_CMD_VIID_S) + +#define FW_VI_RXMODE_CMD_MTU_S 16 +#define FW_VI_RXMODE_CMD_MTU_M 0xffff +#define FW_VI_RXMODE_CMD_MTU_V(x) ((x) << FW_VI_RXMODE_CMD_MTU_S) + +#define FW_VI_RXMODE_CMD_PROMISCEN_S 14 +#define FW_VI_RXMODE_CMD_PROMISCEN_M 0x3 +#define FW_VI_RXMODE_CMD_PROMISCEN_V(x) ((x) << FW_VI_RXMODE_CMD_PROMISCEN_S) + +#define FW_VI_RXMODE_CMD_ALLMULTIEN_S 12 +#define FW_VI_RXMODE_CMD_ALLMULTIEN_M 0x3 +#define FW_VI_RXMODE_CMD_ALLMULTIEN_V(x) \ + ((x) << FW_VI_RXMODE_CMD_ALLMULTIEN_S) + +#define FW_VI_RXMODE_CMD_BROADCASTEN_S 10 +#define FW_VI_RXMODE_CMD_BROADCASTEN_M 0x3 +#define FW_VI_RXMODE_CMD_BROADCASTEN_V(x) \ + ((x) << FW_VI_RXMODE_CMD_BROADCASTEN_S) + +#define FW_VI_RXMODE_CMD_VLANEXEN_S 8 +#define FW_VI_RXMODE_CMD_VLANEXEN_M 0x3 +#define FW_VI_RXMODE_CMD_VLANEXEN_V(x) ((x) << FW_VI_RXMODE_CMD_VLANEXEN_S) struct fw_vi_enable_cmd { __be32 op_to_viid; @@ -1425,11 +1997,21 @@ struct fw_vi_enable_cmd { __be32 r4; }; -#define FW_VI_ENABLE_CMD_VIID(x) ((x) << 0) -#define FW_VI_ENABLE_CMD_IEN(x) ((x) << 31) -#define FW_VI_ENABLE_CMD_EEN(x) ((x) << 30) -#define FW_VI_ENABLE_CMD_DCB_INFO(x) ((x) << 28) -#define FW_VI_ENABLE_CMD_LED (1U << 29) +#define FW_VI_ENABLE_CMD_VIID_S 0 +#define FW_VI_ENABLE_CMD_VIID_V(x) ((x) << FW_VI_ENABLE_CMD_VIID_S) + +#define FW_VI_ENABLE_CMD_IEN_S 31 +#define FW_VI_ENABLE_CMD_IEN_V(x) ((x) << FW_VI_ENABLE_CMD_IEN_S) + +#define FW_VI_ENABLE_CMD_EEN_S 30 +#define FW_VI_ENABLE_CMD_EEN_V(x) ((x) << FW_VI_ENABLE_CMD_EEN_S) + +#define FW_VI_ENABLE_CMD_LED_S 29 +#define FW_VI_ENABLE_CMD_LED_V(x) ((x) << FW_VI_ENABLE_CMD_LED_S) +#define FW_VI_ENABLE_CMD_LED_F FW_VI_ENABLE_CMD_LED_V(1U) + +#define FW_VI_ENABLE_CMD_DCB_INFO_S 28 +#define FW_VI_ENABLE_CMD_DCB_INFO_V(x) ((x) << FW_VI_ENABLE_CMD_DCB_INFO_S) /* VI VF stats offset definitions */ #define VI_VF_NUM_STATS 16 @@ -1529,9 +2111,14 @@ struct fw_vi_stats_cmd { } u; }; -#define FW_VI_STATS_CMD_VIID(x) ((x) << 0) -#define FW_VI_STATS_CMD_NSTATS(x) ((x) << 12) -#define FW_VI_STATS_CMD_IX(x) ((x) << 0) +#define FW_VI_STATS_CMD_VIID_S 0 +#define FW_VI_STATS_CMD_VIID_V(x) ((x) << FW_VI_STATS_CMD_VIID_S) + +#define FW_VI_STATS_CMD_NSTATS_S 12 +#define FW_VI_STATS_CMD_NSTATS_V(x) ((x) << FW_VI_STATS_CMD_NSTATS_S) + +#define FW_VI_STATS_CMD_IX_S 0 +#define FW_VI_STATS_CMD_IX_V(x) ((x) << FW_VI_STATS_CMD_IX_S) struct fw_acl_mac_cmd { __be32 op_to_vfn; @@ -1548,9 +2135,14 @@ struct fw_acl_mac_cmd { u8 macaddr3[6]; }; -#define FW_ACL_MAC_CMD_PFN(x) ((x) << 8) -#define FW_ACL_MAC_CMD_VFN(x) ((x) << 0) -#define FW_ACL_MAC_CMD_EN(x) ((x) << 31) +#define FW_ACL_MAC_CMD_PFN_S 8 +#define FW_ACL_MAC_CMD_PFN_V(x) ((x) << FW_ACL_MAC_CMD_PFN_S) + +#define FW_ACL_MAC_CMD_VFN_S 0 +#define FW_ACL_MAC_CMD_VFN_V(x) ((x) << FW_ACL_MAC_CMD_VFN_S) + +#define FW_ACL_MAC_CMD_EN_S 31 +#define FW_ACL_MAC_CMD_EN_V(x) ((x) << FW_ACL_MAC_CMD_EN_S) struct fw_acl_vlan_cmd { __be32 op_to_vfn; @@ -1561,11 +2153,20 @@ struct fw_acl_vlan_cmd { __be16 vlanid[16]; }; -#define FW_ACL_VLAN_CMD_PFN(x) ((x) << 8) -#define FW_ACL_VLAN_CMD_VFN(x) ((x) << 0) -#define FW_ACL_VLAN_CMD_EN(x) ((x) << 31) -#define FW_ACL_VLAN_CMD_DROPNOVLAN(x) ((x) << 7) -#define FW_ACL_VLAN_CMD_FM(x) ((x) << 6) +#define FW_ACL_VLAN_CMD_PFN_S 8 +#define FW_ACL_VLAN_CMD_PFN_V(x) ((x) << FW_ACL_VLAN_CMD_PFN_S) + +#define FW_ACL_VLAN_CMD_VFN_S 0 +#define FW_ACL_VLAN_CMD_VFN_V(x) ((x) << FW_ACL_VLAN_CMD_VFN_S) + +#define FW_ACL_VLAN_CMD_EN_S 31 +#define FW_ACL_VLAN_CMD_EN_V(x) ((x) << FW_ACL_VLAN_CMD_EN_S) + +#define FW_ACL_VLAN_CMD_DROPNOVLAN_S 7 +#define FW_ACL_VLAN_CMD_DROPNOVLAN_V(x) ((x) << FW_ACL_VLAN_CMD_DROPNOVLAN_S) + +#define FW_ACL_VLAN_CMD_FM_S 6 +#define FW_ACL_VLAN_CMD_FM_V(x) ((x) << FW_ACL_VLAN_CMD_FM_S) enum fw_port_cap { FW_PORT_CAP_SPEED_100M = 0x0001, @@ -1587,13 +2188,14 @@ enum fw_port_cap { }; enum fw_port_mdi { - FW_PORT_MDI_UNCHANGED, - FW_PORT_MDI_AUTO, - FW_PORT_MDI_F_STRAIGHT, - FW_PORT_MDI_F_CROSSOVER + FW_PORT_CAP_MDI_UNCHANGED, + FW_PORT_CAP_MDI_AUTO, + FW_PORT_CAP_MDI_F_STRAIGHT, + FW_PORT_CAP_MDI_F_CROSSOVER }; -#define FW_PORT_MDI(x) ((x) << 9) +#define FW_PORT_CAP_MDI_S 9 +#define FW_PORT_CAP_MDI_V(x) ((x) << FW_PORT_CAP_MDI_S) enum fw_port_action { FW_PORT_ACTION_L1_CFG = 0x0001, @@ -1753,52 +2355,105 @@ struct fw_port_cmd { } u; }; -#define FW_PORT_CMD_READ (1U << 22) - -#define FW_PORT_CMD_PORTID(x) ((x) << 0) -#define FW_PORT_CMD_PORTID_GET(x) (((x) >> 0) & 0xf) - -#define FW_PORT_CMD_ACTION(x) ((x) << 16) -#define FW_PORT_CMD_ACTION_GET(x) (((x) >> 16) & 0xffff) - -#define FW_PORT_CMD_CTLBF(x) ((x) << 10) -#define FW_PORT_CMD_OVLAN3(x) ((x) << 7) -#define FW_PORT_CMD_OVLAN2(x) ((x) << 6) -#define FW_PORT_CMD_OVLAN1(x) ((x) << 5) -#define FW_PORT_CMD_OVLAN0(x) ((x) << 4) -#define FW_PORT_CMD_IVLAN0(x) ((x) << 3) - -#define FW_PORT_CMD_TXIPG(x) ((x) << 19) - -#define FW_PORT_CMD_LSTATUS (1U << 31) -#define FW_PORT_CMD_LSTATUS_GET(x) (((x) >> 31) & 0x1) -#define FW_PORT_CMD_LSPEED(x) ((x) << 24) -#define FW_PORT_CMD_LSPEED_GET(x) (((x) >> 24) & 0x3f) -#define FW_PORT_CMD_TXPAUSE (1U << 23) -#define FW_PORT_CMD_RXPAUSE (1U << 22) -#define FW_PORT_CMD_MDIOCAP (1U << 21) -#define FW_PORT_CMD_MDIOADDR_GET(x) (((x) >> 16) & 0x1f) -#define FW_PORT_CMD_LPTXPAUSE (1U << 15) -#define FW_PORT_CMD_LPRXPAUSE (1U << 14) -#define FW_PORT_CMD_PTYPE_MASK 0x1f -#define FW_PORT_CMD_PTYPE_GET(x) (((x) >> 8) & FW_PORT_CMD_PTYPE_MASK) -#define FW_PORT_CMD_MODTYPE_MASK 0x1f -#define FW_PORT_CMD_MODTYPE_GET(x) (((x) >> 0) & FW_PORT_CMD_MODTYPE_MASK) - -#define FW_PORT_CMD_DCBXDIS (1U << 7) -#define FW_PORT_CMD_APPLY (1U << 7) -#define FW_PORT_CMD_ALL_SYNCD (1U << 7) -#define FW_PORT_CMD_DCB_VERSION_GET(x) (((x) >> 8) & 0xf) - -#define FW_PORT_CMD_PPPEN(x) ((x) << 31) -#define FW_PORT_CMD_TPSRC(x) ((x) << 28) -#define FW_PORT_CMD_NCSISRC(x) ((x) << 24) - -#define FW_PORT_CMD_CH0(x) ((x) << 20) -#define FW_PORT_CMD_CH1(x) ((x) << 16) -#define FW_PORT_CMD_CH2(x) ((x) << 12) -#define FW_PORT_CMD_CH3(x) ((x) << 8) -#define FW_PORT_CMD_NCSICH(x) ((x) << 4) +#define FW_PORT_CMD_READ_S 22 +#define FW_PORT_CMD_READ_V(x) ((x) << FW_PORT_CMD_READ_S) +#define FW_PORT_CMD_READ_F FW_PORT_CMD_READ_V(1U) + +#define FW_PORT_CMD_PORTID_S 0 +#define FW_PORT_CMD_PORTID_M 0xf +#define FW_PORT_CMD_PORTID_V(x) ((x) << FW_PORT_CMD_PORTID_S) +#define FW_PORT_CMD_PORTID_G(x) \ + (((x) >> FW_PORT_CMD_PORTID_S) & FW_PORT_CMD_PORTID_M) + +#define FW_PORT_CMD_ACTION_S 16 +#define FW_PORT_CMD_ACTION_M 0xffff +#define FW_PORT_CMD_ACTION_V(x) ((x) << FW_PORT_CMD_ACTION_S) +#define FW_PORT_CMD_ACTION_G(x) \ + (((x) >> FW_PORT_CMD_ACTION_S) & FW_PORT_CMD_ACTION_M) + +#define FW_PORT_CMD_OVLAN3_S 7 +#define FW_PORT_CMD_OVLAN3_V(x) ((x) << FW_PORT_CMD_OVLAN3_S) + +#define FW_PORT_CMD_OVLAN2_S 6 +#define FW_PORT_CMD_OVLAN2_V(x) ((x) << FW_PORT_CMD_OVLAN2_S) + +#define FW_PORT_CMD_OVLAN1_S 5 +#define FW_PORT_CMD_OVLAN1_V(x) ((x) << FW_PORT_CMD_OVLAN1_S) + +#define FW_PORT_CMD_OVLAN0_S 4 +#define FW_PORT_CMD_OVLAN0_V(x) ((x) << FW_PORT_CMD_OVLAN0_S) + +#define FW_PORT_CMD_IVLAN0_S 3 +#define FW_PORT_CMD_IVLAN0_V(x) ((x) << FW_PORT_CMD_IVLAN0_S) + +#define FW_PORT_CMD_TXIPG_S 3 +#define FW_PORT_CMD_TXIPG_V(x) ((x) << FW_PORT_CMD_TXIPG_S) + +#define FW_PORT_CMD_LSTATUS_S 31 +#define FW_PORT_CMD_LSTATUS_M 0x1 +#define FW_PORT_CMD_LSTATUS_V(x) ((x) << FW_PORT_CMD_LSTATUS_S) +#define FW_PORT_CMD_LSTATUS_G(x) \ + (((x) >> FW_PORT_CMD_LSTATUS_S) & FW_PORT_CMD_LSTATUS_M) +#define FW_PORT_CMD_LSTATUS_F FW_PORT_CMD_LSTATUS_V(1U) + +#define FW_PORT_CMD_LSPEED_S 24 +#define FW_PORT_CMD_LSPEED_M 0x3f +#define FW_PORT_CMD_LSPEED_V(x) ((x) << FW_PORT_CMD_LSPEED_S) +#define FW_PORT_CMD_LSPEED_G(x) \ + (((x) >> FW_PORT_CMD_LSPEED_S) & FW_PORT_CMD_LSPEED_M) + +#define FW_PORT_CMD_TXPAUSE_S 23 +#define FW_PORT_CMD_TXPAUSE_V(x) ((x) << FW_PORT_CMD_TXPAUSE_S) +#define FW_PORT_CMD_TXPAUSE_F FW_PORT_CMD_TXPAUSE_V(1U) + +#define FW_PORT_CMD_RXPAUSE_S 22 +#define FW_PORT_CMD_RXPAUSE_V(x) ((x) << FW_PORT_CMD_RXPAUSE_S) +#define FW_PORT_CMD_RXPAUSE_F FW_PORT_CMD_RXPAUSE_V(1U) + +#define FW_PORT_CMD_MDIOCAP_S 21 +#define FW_PORT_CMD_MDIOCAP_V(x) ((x) << FW_PORT_CMD_MDIOCAP_S) +#define FW_PORT_CMD_MDIOCAP_F FW_PORT_CMD_MDIOCAP_V(1U) + +#define FW_PORT_CMD_MDIOADDR_S 16 +#define FW_PORT_CMD_MDIOADDR_M 0x1f +#define FW_PORT_CMD_MDIOADDR_G(x) \ + (((x) >> FW_PORT_CMD_MDIOADDR_S) & FW_PORT_CMD_MDIOADDR_M) + +#define FW_PORT_CMD_LPTXPAUSE_S 15 +#define FW_PORT_CMD_LPTXPAUSE_V(x) ((x) << FW_PORT_CMD_LPTXPAUSE_S) +#define FW_PORT_CMD_LPTXPAUSE_F FW_PORT_CMD_LPTXPAUSE_V(1U) + +#define FW_PORT_CMD_LPRXPAUSE_S 14 +#define FW_PORT_CMD_LPRXPAUSE_V(x) ((x) << FW_PORT_CMD_LPRXPAUSE_S) +#define FW_PORT_CMD_LPRXPAUSE_F FW_PORT_CMD_LPRXPAUSE_V(1U) + +#define FW_PORT_CMD_PTYPE_S 8 +#define FW_PORT_CMD_PTYPE_M 0x1f +#define FW_PORT_CMD_PTYPE_G(x) \ + (((x) >> FW_PORT_CMD_PTYPE_S) & FW_PORT_CMD_PTYPE_M) + +#define FW_PORT_CMD_MODTYPE_S 0 +#define FW_PORT_CMD_MODTYPE_M 0x1f +#define FW_PORT_CMD_MODTYPE_V(x) ((x) << FW_PORT_CMD_MODTYPE_S) +#define FW_PORT_CMD_MODTYPE_G(x) \ + (((x) >> FW_PORT_CMD_MODTYPE_S) & FW_PORT_CMD_MODTYPE_M) + +#define FW_PORT_CMD_DCBXDIS_S 7 +#define FW_PORT_CMD_DCBXDIS_V(x) ((x) << FW_PORT_CMD_DCBXDIS_S) +#define FW_PORT_CMD_DCBXDIS_F FW_PORT_CMD_DCBXDIS_V(1U) + +#define FW_PORT_CMD_APPLY_S 7 +#define FW_PORT_CMD_APPLY_V(x) ((x) << FW_PORT_CMD_APPLY_S) +#define FW_PORT_CMD_APPLY_F FW_PORT_CMD_APPLY_V(1U) + +#define FW_PORT_CMD_ALL_SYNCD_S 7 +#define FW_PORT_CMD_ALL_SYNCD_V(x) ((x) << FW_PORT_CMD_ALL_SYNCD_S) +#define FW_PORT_CMD_ALL_SYNCD_F FW_PORT_CMD_ALL_SYNCD_V(1U) + +#define FW_PORT_CMD_DCB_VERSION_S 12 +#define FW_PORT_CMD_DCB_VERSION_M 0x7 +#define FW_PORT_CMD_DCB_VERSION_G(x) \ + (((x) >> FW_PORT_CMD_DCB_VERSION_S) & FW_PORT_CMD_DCB_VERSION_M) enum fw_port_type { FW_PORT_TYPE_FIBER_XFI, @@ -1817,7 +2472,7 @@ enum fw_port_type { FW_PORT_TYPE_QSFP, FW_PORT_TYPE_BP40_BA, - FW_PORT_TYPE_NONE = FW_PORT_CMD_PTYPE_MASK + FW_PORT_TYPE_NONE = FW_PORT_CMD_PTYPE_M }; enum fw_port_module_type { @@ -1828,11 +2483,11 @@ enum fw_port_module_type { FW_PORT_MOD_TYPE_TWINAX_PASSIVE, FW_PORT_MOD_TYPE_TWINAX_ACTIVE, FW_PORT_MOD_TYPE_LRM, - FW_PORT_MOD_TYPE_ERROR = FW_PORT_CMD_MODTYPE_MASK - 3, - FW_PORT_MOD_TYPE_UNKNOWN = FW_PORT_CMD_MODTYPE_MASK - 2, - FW_PORT_MOD_TYPE_NOTSUPPORTED = FW_PORT_CMD_MODTYPE_MASK - 1, + FW_PORT_MOD_TYPE_ERROR = FW_PORT_CMD_MODTYPE_M - 3, + FW_PORT_MOD_TYPE_UNKNOWN = FW_PORT_CMD_MODTYPE_M - 2, + FW_PORT_MOD_TYPE_NOTSUPPORTED = FW_PORT_CMD_MODTYPE_M - 1, - FW_PORT_MOD_TYPE_NONE = FW_PORT_CMD_MODTYPE_MASK + FW_PORT_MOD_TYPE_NONE = FW_PORT_CMD_MODTYPE_M }; enum fw_port_mod_sub_type { @@ -1988,11 +2643,6 @@ struct fw_port_stats_cmd { } u; }; -#define FW_PORT_STATS_CMD_NSTATS(x) ((x) << 4) -#define FW_PORT_STATS_CMD_BG_BM(x) ((x) << 0) -#define FW_PORT_STATS_CMD_TX(x) ((x) << 7) -#define FW_PORT_STATS_CMD_IX(x) ((x) << 0) - /* port loopback stats */ #define FW_NUM_LB_STATS 16 enum fw_port_lb_stats_index { @@ -2048,22 +2698,13 @@ struct fw_port_lb_stats_cmd { } u; }; -#define FW_PORT_LB_STATS_CMD_LBPORT(x) ((x) << 0) -#define FW_PORT_LB_STATS_CMD_NSTATS(x) ((x) << 4) -#define FW_PORT_LB_STATS_CMD_BG_BM(x) ((x) << 0) -#define FW_PORT_LB_STATS_CMD_IX(x) ((x) << 0) - struct fw_rss_ind_tbl_cmd { __be32 op_to_viid; -#define FW_RSS_IND_TBL_CMD_VIID(x) ((x) << 0) __be32 retval_len16; __be16 niqid; __be16 startidx; __be32 r3; __be32 iq0_to_iq2; -#define FW_RSS_IND_TBL_CMD_IQ0(x) ((x) << 20) -#define FW_RSS_IND_TBL_CMD_IQ1(x) ((x) << 10) -#define FW_RSS_IND_TBL_CMD_IQ2(x) ((x) << 0) __be32 iq3_to_iq5; __be32 iq6_to_iq8; __be32 iq9_to_iq11; @@ -2077,6 +2718,18 @@ struct fw_rss_ind_tbl_cmd { __be32 r15_lo; }; +#define FW_RSS_IND_TBL_CMD_VIID_S 0 +#define FW_RSS_IND_TBL_CMD_VIID_V(x) ((x) << FW_RSS_IND_TBL_CMD_VIID_S) + +#define FW_RSS_IND_TBL_CMD_IQ0_S 20 +#define FW_RSS_IND_TBL_CMD_IQ0_V(x) ((x) << FW_RSS_IND_TBL_CMD_IQ0_S) + +#define FW_RSS_IND_TBL_CMD_IQ1_S 10 +#define FW_RSS_IND_TBL_CMD_IQ1_V(x) ((x) << FW_RSS_IND_TBL_CMD_IQ1_S) + +#define FW_RSS_IND_TBL_CMD_IQ2_S 0 +#define FW_RSS_IND_TBL_CMD_IQ2_V(x) ((x) << FW_RSS_IND_TBL_CMD_IQ2_S) + struct fw_rss_glb_config_cmd { __be32 op_to_write; __be32 retval_len16; @@ -2090,27 +2743,75 @@ struct fw_rss_glb_config_cmd { struct fw_rss_glb_config_basicvirtual { __be32 mode_pkd; __be32 synmapen_to_hashtoeplitz; -#define FW_RSS_GLB_CONFIG_CMD_SYNMAPEN (1U << 8) -#define FW_RSS_GLB_CONFIG_CMD_SYN4TUPENIPV6 (1U << 7) -#define FW_RSS_GLB_CONFIG_CMD_SYN2TUPENIPV6 (1U << 6) -#define FW_RSS_GLB_CONFIG_CMD_SYN4TUPENIPV4 (1U << 5) -#define FW_RSS_GLB_CONFIG_CMD_SYN2TUPENIPV4 (1U << 4) -#define FW_RSS_GLB_CONFIG_CMD_OFDMAPEN (1U << 3) -#define FW_RSS_GLB_CONFIG_CMD_TNLMAPEN (1U << 2) -#define FW_RSS_GLB_CONFIG_CMD_TNLALLLKP (1U << 1) -#define FW_RSS_GLB_CONFIG_CMD_HASHTOEPLITZ (1U << 0) __be64 r8; __be64 r9; } basicvirtual; } u; }; -#define FW_RSS_GLB_CONFIG_CMD_MODE(x) ((x) << 28) -#define FW_RSS_GLB_CONFIG_CMD_MODE_GET(x) (((x) >> 28) & 0xf) +#define FW_RSS_GLB_CONFIG_CMD_MODE_S 28 +#define FW_RSS_GLB_CONFIG_CMD_MODE_M 0xf +#define FW_RSS_GLB_CONFIG_CMD_MODE_V(x) ((x) << FW_RSS_GLB_CONFIG_CMD_MODE_S) +#define FW_RSS_GLB_CONFIG_CMD_MODE_G(x) \ + (((x) >> FW_RSS_GLB_CONFIG_CMD_MODE_S) & FW_RSS_GLB_CONFIG_CMD_MODE_M) #define FW_RSS_GLB_CONFIG_CMD_MODE_MANUAL 0 #define FW_RSS_GLB_CONFIG_CMD_MODE_BASICVIRTUAL 1 +#define FW_RSS_GLB_CONFIG_CMD_SYNMAPEN_S 8 +#define FW_RSS_GLB_CONFIG_CMD_SYNMAPEN_V(x) \ + ((x) << FW_RSS_GLB_CONFIG_CMD_SYNMAPEN_S) +#define FW_RSS_GLB_CONFIG_CMD_SYNMAPEN_F \ + FW_RSS_GLB_CONFIG_CMD_SYNMAPEN_V(1U) + +#define FW_RSS_GLB_CONFIG_CMD_SYN4TUPENIPV6_S 7 +#define FW_RSS_GLB_CONFIG_CMD_SYN4TUPENIPV6_V(x) \ + ((x) << FW_RSS_GLB_CONFIG_CMD_SYN4TUPENIPV6_S) +#define FW_RSS_GLB_CONFIG_CMD_SYN4TUPENIPV6_F \ + FW_RSS_GLB_CONFIG_CMD_SYN4TUPENIPV6_V(1U) + +#define FW_RSS_GLB_CONFIG_CMD_SYN2TUPENIPV6_S 6 +#define FW_RSS_GLB_CONFIG_CMD_SYN2TUPENIPV6_V(x) \ + ((x) << FW_RSS_GLB_CONFIG_CMD_SYN2TUPENIPV6_S) +#define FW_RSS_GLB_CONFIG_CMD_SYN2TUPENIPV6_F \ + FW_RSS_GLB_CONFIG_CMD_SYN2TUPENIPV6_V(1U) + +#define FW_RSS_GLB_CONFIG_CMD_SYN4TUPENIPV4_S 5 +#define FW_RSS_GLB_CONFIG_CMD_SYN4TUPENIPV4_V(x) \ + ((x) << FW_RSS_GLB_CONFIG_CMD_SYN4TUPENIPV4_S) +#define FW_RSS_GLB_CONFIG_CMD_SYN4TUPENIPV4_F \ + FW_RSS_GLB_CONFIG_CMD_SYN4TUPENIPV4_V(1U) + +#define FW_RSS_GLB_CONFIG_CMD_SYN2TUPENIPV4_S 4 +#define FW_RSS_GLB_CONFIG_CMD_SYN2TUPENIPV4_V(x) \ + ((x) << FW_RSS_GLB_CONFIG_CMD_SYN2TUPENIPV4_S) +#define FW_RSS_GLB_CONFIG_CMD_SYN2TUPENIPV4_F \ + FW_RSS_GLB_CONFIG_CMD_SYN2TUPENIPV4_V(1U) + +#define FW_RSS_GLB_CONFIG_CMD_OFDMAPEN_S 3 +#define FW_RSS_GLB_CONFIG_CMD_OFDMAPEN_V(x) \ + ((x) << FW_RSS_GLB_CONFIG_CMD_OFDMAPEN_S) +#define FW_RSS_GLB_CONFIG_CMD_OFDMAPEN_F \ + FW_RSS_GLB_CONFIG_CMD_OFDMAPEN_V(1U) + +#define FW_RSS_GLB_CONFIG_CMD_TNLMAPEN_S 2 +#define FW_RSS_GLB_CONFIG_CMD_TNLMAPEN_V(x) \ + ((x) << FW_RSS_GLB_CONFIG_CMD_TNLMAPEN_S) +#define FW_RSS_GLB_CONFIG_CMD_TNLMAPEN_F \ + FW_RSS_GLB_CONFIG_CMD_TNLMAPEN_V(1U) + +#define FW_RSS_GLB_CONFIG_CMD_TNLALLLKP_S 1 +#define FW_RSS_GLB_CONFIG_CMD_TNLALLLKP_V(x) \ + ((x) << FW_RSS_GLB_CONFIG_CMD_TNLALLLKP_S) +#define FW_RSS_GLB_CONFIG_CMD_TNLALLLKP_F \ + FW_RSS_GLB_CONFIG_CMD_TNLALLLKP_V(1U) + +#define FW_RSS_GLB_CONFIG_CMD_HASHTOEPLITZ_S 0 +#define FW_RSS_GLB_CONFIG_CMD_HASHTOEPLITZ_V(x) \ + ((x) << FW_RSS_GLB_CONFIG_CMD_HASHTOEPLITZ_S) +#define FW_RSS_GLB_CONFIG_CMD_HASHTOEPLITZ_F \ + FW_RSS_GLB_CONFIG_CMD_HASHTOEPLITZ_V(1U) + struct fw_rss_vi_config_cmd { __be32 op_to_viid; #define FW_RSS_VI_CONFIG_CMD_VIID(x) ((x) << 0) @@ -2124,19 +2825,51 @@ struct fw_rss_vi_config_cmd { struct fw_rss_vi_config_basicvirtual { __be32 r6; __be32 defaultq_to_udpen; -#define FW_RSS_VI_CONFIG_CMD_DEFAULTQ(x) ((x) << 16) -#define FW_RSS_VI_CONFIG_CMD_DEFAULTQ_GET(x) (((x) >> 16) & 0x3ff) -#define FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN (1U << 4) -#define FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN (1U << 3) -#define FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN (1U << 2) -#define FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN (1U << 1) -#define FW_RSS_VI_CONFIG_CMD_UDPEN (1U << 0) __be64 r9; __be64 r10; } basicvirtual; } u; }; +#define FW_RSS_VI_CONFIG_CMD_VIID_S 0 +#define FW_RSS_VI_CONFIG_CMD_VIID_V(x) ((x) << FW_RSS_VI_CONFIG_CMD_VIID_S) + +#define FW_RSS_VI_CONFIG_CMD_DEFAULTQ_S 16 +#define FW_RSS_VI_CONFIG_CMD_DEFAULTQ_M 0x3ff +#define FW_RSS_VI_CONFIG_CMD_DEFAULTQ_V(x) \ + ((x) << FW_RSS_VI_CONFIG_CMD_DEFAULTQ_S) +#define FW_RSS_VI_CONFIG_CMD_DEFAULTQ_G(x) \ + (((x) >> FW_RSS_VI_CONFIG_CMD_DEFAULTQ_S) & \ + FW_RSS_VI_CONFIG_CMD_DEFAULTQ_M) + +#define FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN_S 4 +#define FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN_V(x) \ + ((x) << FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN_S) +#define FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN_F \ + FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN_V(1U) + +#define FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN_S 3 +#define FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN_V(x) \ + ((x) << FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN_S) +#define FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN_F \ + FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN_V(1U) + +#define FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN_S 2 +#define FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN_V(x) \ + ((x) << FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN_S) +#define FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN_F \ + FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN_V(1U) + +#define FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN_S 1 +#define FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN_V(x) \ + ((x) << FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN_S) +#define FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN_F \ + FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN_V(1U) + +#define FW_RSS_VI_CONFIG_CMD_UDPEN_S 0 +#define FW_RSS_VI_CONFIG_CMD_UDPEN_V(x) ((x) << FW_RSS_VI_CONFIG_CMD_UDPEN_S) +#define FW_RSS_VI_CONFIG_CMD_UDPEN_F FW_RSS_VI_CONFIG_CMD_UDPEN_V(1U) + struct fw_clip_cmd { __be32 op_to_write; __be32 alloc_to_len16; @@ -2145,19 +2878,13 @@ struct fw_clip_cmd { __be32 r4[2]; }; -#define S_FW_CLIP_CMD_ALLOC 31 -#define M_FW_CLIP_CMD_ALLOC 0x1 -#define V_FW_CLIP_CMD_ALLOC(x) ((x) << S_FW_CLIP_CMD_ALLOC) -#define G_FW_CLIP_CMD_ALLOC(x) \ - (((x) >> S_FW_CLIP_CMD_ALLOC) & M_FW_CLIP_CMD_ALLOC) -#define F_FW_CLIP_CMD_ALLOC V_FW_CLIP_CMD_ALLOC(1U) +#define FW_CLIP_CMD_ALLOC_S 31 +#define FW_CLIP_CMD_ALLOC_V(x) ((x) << FW_CLIP_CMD_ALLOC_S) +#define FW_CLIP_CMD_ALLOC_F FW_CLIP_CMD_ALLOC_V(1U) -#define S_FW_CLIP_CMD_FREE 30 -#define M_FW_CLIP_CMD_FREE 0x1 -#define V_FW_CLIP_CMD_FREE(x) ((x) << S_FW_CLIP_CMD_FREE) -#define G_FW_CLIP_CMD_FREE(x) \ - (((x) >> S_FW_CLIP_CMD_FREE) & M_FW_CLIP_CMD_FREE) -#define F_FW_CLIP_CMD_FREE V_FW_CLIP_CMD_FREE(1U) +#define FW_CLIP_CMD_FREE_S 30 +#define FW_CLIP_CMD_FREE_V(x) ((x) << FW_CLIP_CMD_FREE_S) +#define FW_CLIP_CMD_FREE_F FW_CLIP_CMD_FREE_V(1U) enum fw_error_type { FW_ERROR_TYPE_EXCEPTION = 0x0, @@ -2196,7 +2923,6 @@ struct fw_error_cmd { struct fw_debug_cmd { __be32 op_type; -#define FW_DEBUG_CMD_TYPE_GET(x) ((x) & 0xff) __be32 len16_pkd; union fw_debug { struct fw_debug_assert { @@ -2219,19 +2945,35 @@ struct fw_debug_cmd { } u; }; -#define FW_PCIE_FW_ERR (1U << 31) -#define FW_PCIE_FW_INIT (1U << 30) -#define FW_PCIE_FW_HALT (1U << 29) -#define FW_PCIE_FW_MASTER_VLD (1U << 15) -#define FW_PCIE_FW_MASTER_MASK 0x7 -#define FW_PCIE_FW_MASTER_SHIFT 12 -#define FW_PCIE_FW_MASTER(x) ((x) << FW_PCIE_FW_MASTER_SHIFT) -#define FW_PCIE_FW_MASTER_GET(x) (((x) >> FW_PCIE_FW_MASTER_SHIFT) & \ - FW_PCIE_FW_MASTER_MASK) -#define FW_PCIE_FW_EVAL_MASK 0x7 -#define FW_PCIE_FW_EVAL_SHIFT 24 -#define FW_PCIE_FW_EVAL_GET(x) (((x) >> FW_PCIE_FW_EVAL_SHIFT) & \ - FW_PCIE_FW_EVAL_MASK) +#define FW_DEBUG_CMD_TYPE_S 0 +#define FW_DEBUG_CMD_TYPE_M 0xff +#define FW_DEBUG_CMD_TYPE_G(x) \ + (((x) >> FW_DEBUG_CMD_TYPE_S) & FW_DEBUG_CMD_TYPE_M) + +#define PCIE_FW_ERR_S 31 +#define PCIE_FW_ERR_V(x) ((x) << PCIE_FW_ERR_S) +#define PCIE_FW_ERR_F PCIE_FW_ERR_V(1U) + +#define PCIE_FW_INIT_S 30 +#define PCIE_FW_INIT_V(x) ((x) << PCIE_FW_INIT_S) +#define PCIE_FW_INIT_F PCIE_FW_INIT_V(1U) + +#define PCIE_FW_HALT_S 29 +#define PCIE_FW_HALT_V(x) ((x) << PCIE_FW_HALT_S) +#define PCIE_FW_HALT_F PCIE_FW_HALT_V(1U) + +#define PCIE_FW_EVAL_S 24 +#define PCIE_FW_EVAL_M 0x7 +#define PCIE_FW_EVAL_G(x) (((x) >> PCIE_FW_EVAL_S) & PCIE_FW_EVAL_M) + +#define PCIE_FW_MASTER_VLD_S 15 +#define PCIE_FW_MASTER_VLD_V(x) ((x) << PCIE_FW_MASTER_VLD_S) +#define PCIE_FW_MASTER_VLD_F PCIE_FW_MASTER_VLD_V(1U) + +#define PCIE_FW_MASTER_S 12 +#define PCIE_FW_MASTER_M 0x7 +#define PCIE_FW_MASTER_V(x) ((x) << PCIE_FW_MASTER_S) +#define PCIE_FW_MASTER_G(x) (((x) >> PCIE_FW_MASTER_S) & PCIE_FW_MASTER_M) struct fw_hdr { u8 ver; @@ -2259,10 +3001,25 @@ enum fw_hdr_chip { FW_HDR_CHIP_T5 }; -#define FW_HDR_FW_VER_MAJOR_GET(x) (((x) >> 24) & 0xff) -#define FW_HDR_FW_VER_MINOR_GET(x) (((x) >> 16) & 0xff) -#define FW_HDR_FW_VER_MICRO_GET(x) (((x) >> 8) & 0xff) -#define FW_HDR_FW_VER_BUILD_GET(x) (((x) >> 0) & 0xff) +#define FW_HDR_FW_VER_MAJOR_S 24 +#define FW_HDR_FW_VER_MAJOR_M 0xff +#define FW_HDR_FW_VER_MAJOR_G(x) \ + (((x) >> FW_HDR_FW_VER_MAJOR_S) & FW_HDR_FW_VER_MAJOR_M) + +#define FW_HDR_FW_VER_MINOR_S 16 +#define FW_HDR_FW_VER_MINOR_M 0xff +#define FW_HDR_FW_VER_MINOR_G(x) \ + (((x) >> FW_HDR_FW_VER_MINOR_S) & FW_HDR_FW_VER_MINOR_M) + +#define FW_HDR_FW_VER_MICRO_S 8 +#define FW_HDR_FW_VER_MICRO_M 0xff +#define FW_HDR_FW_VER_MICRO_G(x) \ + (((x) >> FW_HDR_FW_VER_MICRO_S) & FW_HDR_FW_VER_MICRO_M) + +#define FW_HDR_FW_VER_BUILD_S 0 +#define FW_HDR_FW_VER_BUILD_M 0xff +#define FW_HDR_FW_VER_BUILD_G(x) \ + (((x) >> FW_HDR_FW_VER_BUILD_S) & FW_HDR_FW_VER_BUILD_M) enum fw_hdr_intfver { FW_HDR_INTFVER_NIC = 0x00, diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c index 0b42bddaf284..ad88246a428e 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c @@ -1030,10 +1030,10 @@ static int set_rxq_intr_params(struct adapter *adapter, struct sge_rspq *rspq, pktcnt_idx = closest_thres(&adapter->sge, cnt); if (rspq->desc && rspq->pktcnt_idx != pktcnt_idx) { - v = FW_PARAMS_MNEM(FW_PARAMS_MNEM_DMAQ) | - FW_PARAMS_PARAM_X( + v = FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DMAQ) | + FW_PARAMS_PARAM_X_V( FW_PARAMS_PARAM_DMAQ_IQ_INTCNTTHRESH) | - FW_PARAMS_PARAM_YZ(rspq->cntxt_id); + FW_PARAMS_PARAM_YZ_V(rspq->cntxt_id); err = t4vf_set_params(adapter, 1, &v, &pktcnt_idx); if (err) return err; @@ -1230,14 +1230,14 @@ static void cxgb4vf_get_drvinfo(struct net_device *dev, sizeof(drvinfo->bus_info)); snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), "%u.%u.%u.%u, TP %u.%u.%u.%u", - FW_HDR_FW_VER_MAJOR_GET(adapter->params.dev.fwrev), - FW_HDR_FW_VER_MINOR_GET(adapter->params.dev.fwrev), - FW_HDR_FW_VER_MICRO_GET(adapter->params.dev.fwrev), - FW_HDR_FW_VER_BUILD_GET(adapter->params.dev.fwrev), - FW_HDR_FW_VER_MAJOR_GET(adapter->params.dev.tprev), - FW_HDR_FW_VER_MINOR_GET(adapter->params.dev.tprev), - FW_HDR_FW_VER_MICRO_GET(adapter->params.dev.tprev), - FW_HDR_FW_VER_BUILD_GET(adapter->params.dev.tprev)); + FW_HDR_FW_VER_MAJOR_G(adapter->params.dev.fwrev), + FW_HDR_FW_VER_MINOR_G(adapter->params.dev.fwrev), + FW_HDR_FW_VER_MICRO_G(adapter->params.dev.fwrev), + FW_HDR_FW_VER_BUILD_G(adapter->params.dev.fwrev), + FW_HDR_FW_VER_MAJOR_G(adapter->params.dev.tprev), + FW_HDR_FW_VER_MINOR_G(adapter->params.dev.tprev), + FW_HDR_FW_VER_MICRO_G(adapter->params.dev.tprev), + FW_HDR_FW_VER_BUILD_G(adapter->params.dev.tprev)); } /* @@ -2184,8 +2184,8 @@ static int adap_init0(struct adapter *adapter) * firmware won't understand this and we'll just get * unencapsulated messages ... */ - param = FW_PARAMS_MNEM(FW_PARAMS_MNEM_PFVF) | - FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_PFVF_CPLFW4MSG_ENCAP); + param = FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_PFVF) | + FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_PFVF_CPLFW4MSG_ENCAP); val = 1; (void) t4vf_set_params(adapter, 1, ¶m, &val); @@ -2908,67 +2908,18 @@ static void cxgb4vf_pci_shutdown(struct pci_dev *pdev) pci_set_drvdata(pdev, NULL); } -/* - * PCI Device registration data structures. - */ -#define CH_DEVICE(devid) \ - { PCI_VENDOR_ID_CHELSIO, devid, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 } - -static const struct pci_device_id cxgb4vf_pci_tbl[] = { - CH_DEVICE(0xb000), /* PE10K FPGA */ - CH_DEVICE(0x4801), /* T420-cr */ - CH_DEVICE(0x4802), /* T422-cr */ - CH_DEVICE(0x4803), /* T440-cr */ - CH_DEVICE(0x4804), /* T420-bch */ - CH_DEVICE(0x4805), /* T440-bch */ - CH_DEVICE(0x4806), /* T460-ch */ - CH_DEVICE(0x4807), /* T420-so */ - CH_DEVICE(0x4808), /* T420-cx */ - CH_DEVICE(0x4809), /* T420-bt */ - CH_DEVICE(0x480a), /* T404-bt */ - CH_DEVICE(0x480d), /* T480-cr */ - CH_DEVICE(0x480e), /* T440-lp-cr */ - CH_DEVICE(0x4880), - CH_DEVICE(0x4881), - CH_DEVICE(0x4882), - CH_DEVICE(0x4883), - CH_DEVICE(0x4884), - CH_DEVICE(0x4885), - CH_DEVICE(0x4886), - CH_DEVICE(0x4887), - CH_DEVICE(0x4888), - CH_DEVICE(0x5801), /* T520-cr */ - CH_DEVICE(0x5802), /* T522-cr */ - CH_DEVICE(0x5803), /* T540-cr */ - CH_DEVICE(0x5804), /* T520-bch */ - CH_DEVICE(0x5805), /* T540-bch */ - CH_DEVICE(0x5806), /* T540-ch */ - CH_DEVICE(0x5807), /* T520-so */ - CH_DEVICE(0x5808), /* T520-cx */ - CH_DEVICE(0x5809), /* T520-bt */ - CH_DEVICE(0x580a), /* T504-bt */ - CH_DEVICE(0x580b), /* T520-sr */ - CH_DEVICE(0x580c), /* T504-bt */ - CH_DEVICE(0x580d), /* T580-cr */ - CH_DEVICE(0x580e), /* T540-lp-cr */ - CH_DEVICE(0x580f), /* Amsterdam */ - CH_DEVICE(0x5810), /* T580-lp-cr */ - CH_DEVICE(0x5811), /* T520-lp-cr */ - CH_DEVICE(0x5812), /* T560-cr */ - CH_DEVICE(0x5813), /* T580-cr */ - CH_DEVICE(0x5814), /* T580-so-cr */ - CH_DEVICE(0x5815), /* T502-bt */ - CH_DEVICE(0x5880), - CH_DEVICE(0x5881), - CH_DEVICE(0x5882), - CH_DEVICE(0x5883), - CH_DEVICE(0x5884), - CH_DEVICE(0x5885), - CH_DEVICE(0x5886), - CH_DEVICE(0x5887), - CH_DEVICE(0x5888), - { 0, } -}; +/* Macros needed to support the PCI Device ID Table ... + */ +#define CH_PCI_DEVICE_ID_TABLE_DEFINE_BEGIN \ + static struct pci_device_id cxgb4vf_pci_tbl[] = { +#define CH_PCI_DEVICE_ID_FUNCTION 0x8 + +#define CH_PCI_ID_TABLE_ENTRY(devid) \ + { PCI_VDEVICE(CHELSIO, (devid)), 0 } + +#define CH_PCI_DEVICE_ID_TABLE_DEFINE_END { 0, } } + +#include "../cxgb4/t4_pci_id_tbl.h" MODULE_DESCRIPTION(DRV_DESC); MODULE_AUTHOR("Chelsio Communications"); diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c index fdd078d7d82c..045301d336bb 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c @@ -118,7 +118,7 @@ enum { * we can specify for immediate data in the firmware Ethernet TX * Work Request. */ - MAX_IMM_TX_PKT_LEN = FW_WR_IMMDLEN_MASK, + MAX_IMM_TX_PKT_LEN = FW_WR_IMMDLEN_M, /* * Max size of a WR sent through a control TX queue. @@ -598,6 +598,8 @@ static unsigned int refill_fl(struct adapter *adapter, struct sge_fl *fl, */ BUG_ON(fl->avail + n > fl->size - FL_PER_EQ_UNIT); + gfp |= __GFP_NOWARN; + /* * If we support large pages, prefer large buffers and fail over to * small pages if we can't allocate large pages to satisfy the refill. @@ -608,8 +610,7 @@ static unsigned int refill_fl(struct adapter *adapter, struct sge_fl *fl, goto alloc_small_pages; while (n) { - page = alloc_pages(gfp | __GFP_COMP | __GFP_NOWARN, - s->fl_pg_order); + page = __dev_alloc_pages(gfp, s->fl_pg_order); if (unlikely(!page)) { /* * We've failed inour attempt to allocate a "large @@ -653,7 +654,7 @@ static unsigned int refill_fl(struct adapter *adapter, struct sge_fl *fl, alloc_small_pages: while (n--) { - page = __skb_alloc_page(gfp | __GFP_NOWARN, NULL); + page = __dev_alloc_page(gfp); if (unlikely(!page)) { fl->alloc_failed++; break; @@ -902,7 +903,7 @@ static void write_sgl(const struct sk_buff *skb, struct sge_txq *tq, sgl->addr0 = cpu_to_be64(addr[1]); } - sgl->cmd_nsge = htonl(ULPTX_CMD(ULP_TX_SC_DSGL) | + sgl->cmd_nsge = htonl(ULPTX_CMD_V(ULP_TX_SC_DSGL) | ULPTX_NSGE(nfrags)); if (likely(--nfrags == 0)) return; @@ -1145,7 +1146,7 @@ int t4vf_eth_xmit(struct sk_buff *skb, struct net_device *dev) goto out_free; } - wr_mid = FW_WR_LEN16(DIV_ROUND_UP(flits, 2)); + wr_mid = FW_WR_LEN16_V(DIV_ROUND_UP(flits, 2)); if (unlikely(credits < ETHTXQ_STOP_THRES)) { /* * After we're done injecting the Work Request for this @@ -1157,7 +1158,7 @@ int t4vf_eth_xmit(struct sk_buff *skb, struct net_device *dev) * has opened up. */ txq_stop(txq); - wr_mid |= FW_WR_EQUEQ | FW_WR_EQUIQ; + wr_mid |= FW_WR_EQUEQ_F | FW_WR_EQUIQ_F; } /* @@ -1187,9 +1188,9 @@ int t4vf_eth_xmit(struct sk_buff *skb, struct net_device *dev) int eth_xtra_len = skb_network_offset(skb) - ETH_HLEN; wr->op_immdlen = - cpu_to_be32(FW_WR_OP(FW_ETH_TX_PKT_VM_WR) | - FW_WR_IMMDLEN(sizeof(*lso) + - sizeof(*cpl))); + cpu_to_be32(FW_WR_OP_V(FW_ETH_TX_PKT_VM_WR) | + FW_WR_IMMDLEN_V(sizeof(*lso) + + sizeof(*cpl))); /* * Fill in the LSO CPL message. */ @@ -1224,8 +1225,8 @@ int t4vf_eth_xmit(struct sk_buff *skb, struct net_device *dev) len = is_eth_imm(skb) ? skb->len + sizeof(*cpl) : sizeof(*cpl); wr->op_immdlen = - cpu_to_be32(FW_WR_OP(FW_ETH_TX_PKT_VM_WR) | - FW_WR_IMMDLEN(len)); + cpu_to_be32(FW_WR_OP_V(FW_ETH_TX_PKT_VM_WR) | + FW_WR_IMMDLEN_V(len)); /* * Set up TX Packet CPL pointer, control word and perform @@ -2087,26 +2088,26 @@ int t4vf_sge_alloc_rxq(struct adapter *adapter, struct sge_rspq *rspq, * into OS-independent common code ... */ memset(&cmd, 0, sizeof(cmd)); - cmd.op_to_vfn = cpu_to_be32(FW_CMD_OP(FW_IQ_CMD) | - FW_CMD_REQUEST | - FW_CMD_WRITE | - FW_CMD_EXEC); - cmd.alloc_to_len16 = cpu_to_be32(FW_IQ_CMD_ALLOC | - FW_IQ_CMD_IQSTART(1) | + cmd.op_to_vfn = cpu_to_be32(FW_CMD_OP_V(FW_IQ_CMD) | + FW_CMD_REQUEST_F | + FW_CMD_WRITE_F | + FW_CMD_EXEC_F); + cmd.alloc_to_len16 = cpu_to_be32(FW_IQ_CMD_ALLOC_F | + FW_IQ_CMD_IQSTART_F | FW_LEN16(cmd)); cmd.type_to_iqandstindex = - cpu_to_be32(FW_IQ_CMD_TYPE(FW_IQ_TYPE_FL_INT_CAP) | - FW_IQ_CMD_IQASYNCH(iqasynch) | - FW_IQ_CMD_VIID(pi->viid) | - FW_IQ_CMD_IQANDST(iqandst) | - FW_IQ_CMD_IQANUS(1) | - FW_IQ_CMD_IQANUD(SGE_UPDATEDEL_INTR) | - FW_IQ_CMD_IQANDSTINDEX(intr_dest)); + cpu_to_be32(FW_IQ_CMD_TYPE_V(FW_IQ_TYPE_FL_INT_CAP) | + FW_IQ_CMD_IQASYNCH_V(iqasynch) | + FW_IQ_CMD_VIID_V(pi->viid) | + FW_IQ_CMD_IQANDST_V(iqandst) | + FW_IQ_CMD_IQANUS_V(1) | + FW_IQ_CMD_IQANUD_V(SGE_UPDATEDEL_INTR) | + FW_IQ_CMD_IQANDSTINDEX_V(intr_dest)); cmd.iqdroprss_to_iqesize = - cpu_to_be16(FW_IQ_CMD_IQPCIECH(pi->port_id) | - FW_IQ_CMD_IQGTSMODE | - FW_IQ_CMD_IQINTCNTTHRESH(rspq->pktcnt_idx) | - FW_IQ_CMD_IQESIZE(ilog2(rspq->iqe_len) - 4)); + cpu_to_be16(FW_IQ_CMD_IQPCIECH_V(pi->port_id) | + FW_IQ_CMD_IQGTSMODE_F | + FW_IQ_CMD_IQINTCNTTHRESH_V(rspq->pktcnt_idx) | + FW_IQ_CMD_IQESIZE_V(ilog2(rspq->iqe_len) - 4)); cmd.iqsize = cpu_to_be16(rspq->size); cmd.iqaddr = cpu_to_be64(rspq->phys_addr); @@ -2140,13 +2141,13 @@ int t4vf_sge_alloc_rxq(struct adapter *adapter, struct sge_rspq *rspq, */ cmd.iqns_to_fl0congen = cpu_to_be32( - FW_IQ_CMD_FL0HOSTFCMODE(SGE_HOSTFCMODE_NONE) | - FW_IQ_CMD_FL0PACKEN(1) | - FW_IQ_CMD_FL0PADEN(1)); + FW_IQ_CMD_FL0HOSTFCMODE_V(SGE_HOSTFCMODE_NONE) | + FW_IQ_CMD_FL0PACKEN_F | + FW_IQ_CMD_FL0PADEN_F); cmd.fl0dcaen_to_fl0cidxfthresh = cpu_to_be16( - FW_IQ_CMD_FL0FBMIN(SGE_FETCHBURSTMIN_64B) | - FW_IQ_CMD_FL0FBMAX(SGE_FETCHBURSTMAX_512B)); + FW_IQ_CMD_FL0FBMIN_V(SGE_FETCHBURSTMIN_64B) | + FW_IQ_CMD_FL0FBMAX_V(SGE_FETCHBURSTMAX_512B)); cmd.fl0size = cpu_to_be16(flsz); cmd.fl0addr = cpu_to_be64(fl->addr); } @@ -2250,24 +2251,25 @@ int t4vf_sge_alloc_eth_txq(struct adapter *adapter, struct sge_eth_txq *txq, * into the common code ... */ memset(&cmd, 0, sizeof(cmd)); - cmd.op_to_vfn = cpu_to_be32(FW_CMD_OP(FW_EQ_ETH_CMD) | - FW_CMD_REQUEST | - FW_CMD_WRITE | - FW_CMD_EXEC); - cmd.alloc_to_len16 = cpu_to_be32(FW_EQ_ETH_CMD_ALLOC | - FW_EQ_ETH_CMD_EQSTART | + cmd.op_to_vfn = cpu_to_be32(FW_CMD_OP_V(FW_EQ_ETH_CMD) | + FW_CMD_REQUEST_F | + FW_CMD_WRITE_F | + FW_CMD_EXEC_F); + cmd.alloc_to_len16 = cpu_to_be32(FW_EQ_ETH_CMD_ALLOC_F | + FW_EQ_ETH_CMD_EQSTART_F | FW_LEN16(cmd)); - cmd.viid_pkd = cpu_to_be32(FW_EQ_ETH_CMD_AUTOEQUEQE | - FW_EQ_ETH_CMD_VIID(pi->viid)); + cmd.viid_pkd = cpu_to_be32(FW_EQ_ETH_CMD_AUTOEQUEQE_F | + FW_EQ_ETH_CMD_VIID_V(pi->viid)); cmd.fetchszm_to_iqid = - cpu_to_be32(FW_EQ_ETH_CMD_HOSTFCMODE(SGE_HOSTFCMODE_STPG) | - FW_EQ_ETH_CMD_PCIECHN(pi->port_id) | - FW_EQ_ETH_CMD_IQID(iqid)); + cpu_to_be32(FW_EQ_ETH_CMD_HOSTFCMODE_V(SGE_HOSTFCMODE_STPG) | + FW_EQ_ETH_CMD_PCIECHN_V(pi->port_id) | + FW_EQ_ETH_CMD_IQID_V(iqid)); cmd.dcaen_to_eqsize = - cpu_to_be32(FW_EQ_ETH_CMD_FBMIN(SGE_FETCHBURSTMIN_64B) | - FW_EQ_ETH_CMD_FBMAX(SGE_FETCHBURSTMAX_512B) | - FW_EQ_ETH_CMD_CIDXFTHRESH(SGE_CIDXFLUSHTHRESH_32) | - FW_EQ_ETH_CMD_EQSIZE(nentries)); + cpu_to_be32(FW_EQ_ETH_CMD_FBMIN_V(SGE_FETCHBURSTMIN_64B) | + FW_EQ_ETH_CMD_FBMAX_V(SGE_FETCHBURSTMAX_512B) | + FW_EQ_ETH_CMD_CIDXFTHRESH_V( + SGE_CIDXFLUSHTHRESH_32) | + FW_EQ_ETH_CMD_EQSIZE_V(nentries)); cmd.eqaddr = cpu_to_be64(txq->q.phys_addr); /* @@ -2293,9 +2295,9 @@ int t4vf_sge_alloc_eth_txq(struct adapter *adapter, struct sge_eth_txq *txq, txq->q.cidx = 0; txq->q.pidx = 0; txq->q.stat = (void *)&txq->q.desc[txq->q.size]; - txq->q.cntxt_id = FW_EQ_ETH_CMD_EQID_GET(be32_to_cpu(rpl.eqid_pkd)); + txq->q.cntxt_id = FW_EQ_ETH_CMD_EQID_G(be32_to_cpu(rpl.eqid_pkd)); txq->q.abs_id = - FW_EQ_ETH_CMD_PHYSEQID_GET(be32_to_cpu(rpl.physeqid_pkd)); + FW_EQ_ETH_CMD_PHYSEQID_G(be32_to_cpu(rpl.physeqid_pkd)); txq->txq = devq; txq->tso = 0; txq->tx_cso = 0; diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h index 4b6a6d14d86d..a608c6657d63 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h +++ b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h @@ -67,7 +67,7 @@ enum chip_type { /* * The "len16" field of a Firmware Command Structure ... */ -#define FW_LEN16(fw_struct) FW_CMD_LEN16(sizeof(fw_struct) / 16) +#define FW_LEN16(fw_struct) FW_CMD_LEN16_V(sizeof(fw_struct) / 16) /* * Per-VF statistics. diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c index 1e896b923234..624a213dea87 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c @@ -204,20 +204,20 @@ int t4vf_wr_mbox_core(struct adapter *adapter, const void *cmd, int size, /* return value in low-order little-endian word */ v = t4_read_reg(adapter, mbox_data); - if (FW_CMD_RETVAL_GET(v)) + if (FW_CMD_RETVAL_G(v)) dump_mbox(adapter, "FW Error", mbox_data); if (rpl) { /* request bit in high-order BE word */ WARN_ON((be32_to_cpu(*(const u32 *)cmd) - & FW_CMD_REQUEST) == 0); + & FW_CMD_REQUEST_F) == 0); get_mbox_rpl(adapter, rpl, size, mbox_data); WARN_ON((be32_to_cpu(*(u32 *)rpl) - & FW_CMD_REQUEST) != 0); + & FW_CMD_REQUEST_F) != 0); } t4_write_reg(adapter, mbox_ctl, MBOWNER(MBOX_OWNER_NONE)); - return -FW_CMD_RETVAL_GET(v); + return -FW_CMD_RETVAL_G(v); } } @@ -287,17 +287,17 @@ int t4vf_port_init(struct adapter *adapter, int pidx) * like MAC address, etc. */ memset(&vi_cmd, 0, sizeof(vi_cmd)); - vi_cmd.op_to_vfn = cpu_to_be32(FW_CMD_OP(FW_VI_CMD) | - FW_CMD_REQUEST | - FW_CMD_READ); + vi_cmd.op_to_vfn = cpu_to_be32(FW_CMD_OP_V(FW_VI_CMD) | + FW_CMD_REQUEST_F | + FW_CMD_READ_F); vi_cmd.alloc_to_len16 = cpu_to_be32(FW_LEN16(vi_cmd)); - vi_cmd.type_viid = cpu_to_be16(FW_VI_CMD_VIID(pi->viid)); + vi_cmd.type_viid = cpu_to_be16(FW_VI_CMD_VIID_V(pi->viid)); v = t4vf_wr_mbox(adapter, &vi_cmd, sizeof(vi_cmd), &vi_rpl); if (v) return v; - BUG_ON(pi->port_id != FW_VI_CMD_PORTID_GET(vi_rpl.portid_pkd)); - pi->rss_size = FW_VI_CMD_RSSSIZE_GET(be16_to_cpu(vi_rpl.rsssize_pkd)); + BUG_ON(pi->port_id != FW_VI_CMD_PORTID_G(vi_rpl.portid_pkd)); + pi->rss_size = FW_VI_CMD_RSSSIZE_G(be16_to_cpu(vi_rpl.rsssize_pkd)); t4_os_set_hw_addr(adapter, pidx, vi_rpl.mac); /* @@ -308,12 +308,12 @@ int t4vf_port_init(struct adapter *adapter, int pidx) return 0; memset(&port_cmd, 0, sizeof(port_cmd)); - port_cmd.op_to_portid = cpu_to_be32(FW_CMD_OP(FW_PORT_CMD) | - FW_CMD_REQUEST | - FW_CMD_READ | - FW_PORT_CMD_PORTID(pi->port_id)); + port_cmd.op_to_portid = cpu_to_be32(FW_CMD_OP_V(FW_PORT_CMD) | + FW_CMD_REQUEST_F | + FW_CMD_READ_F | + FW_PORT_CMD_PORTID_V(pi->port_id)); port_cmd.action_to_len16 = - cpu_to_be32(FW_PORT_CMD_ACTION(FW_PORT_ACTION_GET_PORT_INFO) | + cpu_to_be32(FW_PORT_CMD_ACTION_V(FW_PORT_ACTION_GET_PORT_INFO) | FW_LEN16(port_cmd)); v = t4vf_wr_mbox(adapter, &port_cmd, sizeof(port_cmd), &port_rpl); if (v) @@ -349,8 +349,8 @@ int t4vf_fw_reset(struct adapter *adapter) struct fw_reset_cmd cmd; memset(&cmd, 0, sizeof(cmd)); - cmd.op_to_write = cpu_to_be32(FW_CMD_OP(FW_RESET_CMD) | - FW_CMD_WRITE); + cmd.op_to_write = cpu_to_be32(FW_CMD_OP_V(FW_RESET_CMD) | + FW_CMD_WRITE_F); cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd)); return t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), NULL); } @@ -377,12 +377,12 @@ static int t4vf_query_params(struct adapter *adapter, unsigned int nparams, return -EINVAL; memset(&cmd, 0, sizeof(cmd)); - cmd.op_to_vfn = cpu_to_be32(FW_CMD_OP(FW_PARAMS_CMD) | - FW_CMD_REQUEST | - FW_CMD_READ); + cmd.op_to_vfn = cpu_to_be32(FW_CMD_OP_V(FW_PARAMS_CMD) | + FW_CMD_REQUEST_F | + FW_CMD_READ_F); len16 = DIV_ROUND_UP(offsetof(struct fw_params_cmd, param[nparams].mnem), 16); - cmd.retval_len16 = cpu_to_be32(FW_CMD_LEN16(len16)); + cmd.retval_len16 = cpu_to_be32(FW_CMD_LEN16_V(len16)); for (i = 0, p = &cmd.param[0]; i < nparams; i++, p++) p->mnem = htonl(*params++); @@ -415,12 +415,12 @@ int t4vf_set_params(struct adapter *adapter, unsigned int nparams, return -EINVAL; memset(&cmd, 0, sizeof(cmd)); - cmd.op_to_vfn = cpu_to_be32(FW_CMD_OP(FW_PARAMS_CMD) | - FW_CMD_REQUEST | - FW_CMD_WRITE); + cmd.op_to_vfn = cpu_to_be32(FW_CMD_OP_V(FW_PARAMS_CMD) | + FW_CMD_REQUEST_F | + FW_CMD_WRITE_F); len16 = DIV_ROUND_UP(offsetof(struct fw_params_cmd, param[nparams]), 16); - cmd.retval_len16 = cpu_to_be32(FW_CMD_LEN16(len16)); + cmd.retval_len16 = cpu_to_be32(FW_CMD_LEN16_V(len16)); for (i = 0, p = &cmd.param[0]; i < nparams; i++, p++) { p->mnem = cpu_to_be32(*params++); p->val = cpu_to_be32(*vals++); @@ -443,20 +443,20 @@ int t4vf_get_sge_params(struct adapter *adapter) u32 params[7], vals[7]; int v; - params[0] = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | - FW_PARAMS_PARAM_XYZ(SGE_CONTROL)); - params[1] = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | - FW_PARAMS_PARAM_XYZ(SGE_HOST_PAGE_SIZE)); - params[2] = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | - FW_PARAMS_PARAM_XYZ(SGE_FL_BUFFER_SIZE0)); - params[3] = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | - FW_PARAMS_PARAM_XYZ(SGE_FL_BUFFER_SIZE1)); - params[4] = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | - FW_PARAMS_PARAM_XYZ(SGE_TIMER_VALUE_0_AND_1)); - params[5] = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | - FW_PARAMS_PARAM_XYZ(SGE_TIMER_VALUE_2_AND_3)); - params[6] = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | - FW_PARAMS_PARAM_XYZ(SGE_TIMER_VALUE_4_AND_5)); + params[0] = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_REG) | + FW_PARAMS_PARAM_XYZ_V(SGE_CONTROL)); + params[1] = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_REG) | + FW_PARAMS_PARAM_XYZ_V(SGE_HOST_PAGE_SIZE)); + params[2] = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_REG) | + FW_PARAMS_PARAM_XYZ_V(SGE_FL_BUFFER_SIZE0)); + params[3] = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_REG) | + FW_PARAMS_PARAM_XYZ_V(SGE_FL_BUFFER_SIZE1)); + params[4] = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_REG) | + FW_PARAMS_PARAM_XYZ_V(SGE_TIMER_VALUE_0_AND_1)); + params[5] = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_REG) | + FW_PARAMS_PARAM_XYZ_V(SGE_TIMER_VALUE_2_AND_3)); + params[6] = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_REG) | + FW_PARAMS_PARAM_XYZ_V(SGE_TIMER_VALUE_4_AND_5)); v = t4vf_query_params(adapter, 7, params, vals); if (v) return v; @@ -479,8 +479,8 @@ int t4vf_get_sge_params(struct adapter *adapter) * right value. */ if (!is_t4(adapter->params.chip)) { - params[0] = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | - FW_PARAMS_PARAM_XYZ(SGE_CONTROL2_A)); + params[0] = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_REG) | + FW_PARAMS_PARAM_XYZ_V(SGE_CONTROL2_A)); v = t4vf_query_params(adapter, 1, params, vals); if (v != FW_SUCCESS) { dev_err(adapter->pdev_dev, @@ -491,10 +491,10 @@ int t4vf_get_sge_params(struct adapter *adapter) sge_params->sge_control2 = vals[0]; } - params[0] = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | - FW_PARAMS_PARAM_XYZ(SGE_INGRESS_RX_THRESHOLD)); - params[1] = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | - FW_PARAMS_PARAM_XYZ(SGE_CONM_CTRL)); + params[0] = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_REG) | + FW_PARAMS_PARAM_XYZ_V(SGE_INGRESS_RX_THRESHOLD)); + params[1] = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_REG) | + FW_PARAMS_PARAM_XYZ_V(SGE_CONM_CTRL)); v = t4vf_query_params(adapter, 2, params, vals); if (v) return v; @@ -517,8 +517,8 @@ int t4vf_get_vpd_params(struct adapter *adapter) u32 params[7], vals[7]; int v; - params[0] = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | - FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_CCLK)); + params[0] = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DEV) | + FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_DEV_CCLK)); v = t4vf_query_params(adapter, 1, params, vals); if (v) return v; @@ -540,10 +540,10 @@ int t4vf_get_dev_params(struct adapter *adapter) u32 params[7], vals[7]; int v; - params[0] = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | - FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_FWREV)); - params[1] = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | - FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_TPREV)); + params[0] = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DEV) | + FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_DEV_FWREV)); + params[1] = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DEV) | + FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_DEV_TPREV)); v = t4vf_query_params(adapter, 2, params, vals); if (v) return v; @@ -571,9 +571,9 @@ int t4vf_get_rss_glb_config(struct adapter *adapter) * our RSS configuration. */ memset(&cmd, 0, sizeof(cmd)); - cmd.op_to_write = cpu_to_be32(FW_CMD_OP(FW_RSS_GLB_CONFIG_CMD) | - FW_CMD_REQUEST | - FW_CMD_READ); + cmd.op_to_write = cpu_to_be32(FW_CMD_OP_V(FW_RSS_GLB_CONFIG_CMD) | + FW_CMD_REQUEST_F | + FW_CMD_READ_F); cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd)); v = t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), &rpl); if (v) @@ -585,7 +585,7 @@ int t4vf_get_rss_glb_config(struct adapter *adapter) * filtering at this point to weed out modes which don't support * VF Drivers ... */ - rss->mode = FW_RSS_GLB_CONFIG_CMD_MODE_GET( + rss->mode = FW_RSS_GLB_CONFIG_CMD_MODE_G( be32_to_cpu(rpl.u.manual.mode_pkd)); switch (rss->mode) { case FW_RSS_GLB_CONFIG_CMD_MODE_BASICVIRTUAL: { @@ -593,26 +593,26 @@ int t4vf_get_rss_glb_config(struct adapter *adapter) rpl.u.basicvirtual.synmapen_to_hashtoeplitz); rss->u.basicvirtual.synmapen = - ((word & FW_RSS_GLB_CONFIG_CMD_SYNMAPEN) != 0); + ((word & FW_RSS_GLB_CONFIG_CMD_SYNMAPEN_F) != 0); rss->u.basicvirtual.syn4tupenipv6 = - ((word & FW_RSS_GLB_CONFIG_CMD_SYN4TUPENIPV6) != 0); + ((word & FW_RSS_GLB_CONFIG_CMD_SYN4TUPENIPV6_F) != 0); rss->u.basicvirtual.syn2tupenipv6 = - ((word & FW_RSS_GLB_CONFIG_CMD_SYN2TUPENIPV6) != 0); + ((word & FW_RSS_GLB_CONFIG_CMD_SYN2TUPENIPV6_F) != 0); rss->u.basicvirtual.syn4tupenipv4 = - ((word & FW_RSS_GLB_CONFIG_CMD_SYN4TUPENIPV4) != 0); + ((word & FW_RSS_GLB_CONFIG_CMD_SYN4TUPENIPV4_F) != 0); rss->u.basicvirtual.syn2tupenipv4 = - ((word & FW_RSS_GLB_CONFIG_CMD_SYN2TUPENIPV4) != 0); + ((word & FW_RSS_GLB_CONFIG_CMD_SYN2TUPENIPV4_F) != 0); rss->u.basicvirtual.ofdmapen = - ((word & FW_RSS_GLB_CONFIG_CMD_OFDMAPEN) != 0); + ((word & FW_RSS_GLB_CONFIG_CMD_OFDMAPEN_F) != 0); rss->u.basicvirtual.tnlmapen = - ((word & FW_RSS_GLB_CONFIG_CMD_TNLMAPEN) != 0); + ((word & FW_RSS_GLB_CONFIG_CMD_TNLMAPEN_F) != 0); rss->u.basicvirtual.tnlalllookup = - ((word & FW_RSS_GLB_CONFIG_CMD_TNLALLLKP) != 0); + ((word & FW_RSS_GLB_CONFIG_CMD_TNLALLLKP_F) != 0); rss->u.basicvirtual.hashtoeplitz = - ((word & FW_RSS_GLB_CONFIG_CMD_HASHTOEPLITZ) != 0); + ((word & FW_RSS_GLB_CONFIG_CMD_HASHTOEPLITZ_F) != 0); /* we need at least Tunnel Map Enable to be set */ if (!rss->u.basicvirtual.tnlmapen) @@ -647,9 +647,9 @@ int t4vf_get_vfres(struct adapter *adapter) * with error on command failure. */ memset(&cmd, 0, sizeof(cmd)); - cmd.op_to_vfn = cpu_to_be32(FW_CMD_OP(FW_PFVF_CMD) | - FW_CMD_REQUEST | - FW_CMD_READ); + cmd.op_to_vfn = cpu_to_be32(FW_CMD_OP_V(FW_PFVF_CMD) | + FW_CMD_REQUEST_F | + FW_CMD_READ_F); cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd)); v = t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), &rpl); if (v) @@ -659,22 +659,22 @@ int t4vf_get_vfres(struct adapter *adapter) * Extract VF resource limits and return success. */ word = be32_to_cpu(rpl.niqflint_niq); - vfres->niqflint = FW_PFVF_CMD_NIQFLINT_GET(word); - vfres->niq = FW_PFVF_CMD_NIQ_GET(word); + vfres->niqflint = FW_PFVF_CMD_NIQFLINT_G(word); + vfres->niq = FW_PFVF_CMD_NIQ_G(word); word = be32_to_cpu(rpl.type_to_neq); - vfres->neq = FW_PFVF_CMD_NEQ_GET(word); - vfres->pmask = FW_PFVF_CMD_PMASK_GET(word); + vfres->neq = FW_PFVF_CMD_NEQ_G(word); + vfres->pmask = FW_PFVF_CMD_PMASK_G(word); word = be32_to_cpu(rpl.tc_to_nexactf); - vfres->tc = FW_PFVF_CMD_TC_GET(word); - vfres->nvi = FW_PFVF_CMD_NVI_GET(word); - vfres->nexactf = FW_PFVF_CMD_NEXACTF_GET(word); + vfres->tc = FW_PFVF_CMD_TC_G(word); + vfres->nvi = FW_PFVF_CMD_NVI_G(word); + vfres->nexactf = FW_PFVF_CMD_NEXACTF_G(word); word = be32_to_cpu(rpl.r_caps_to_nethctrl); - vfres->r_caps = FW_PFVF_CMD_R_CAPS_GET(word); - vfres->wx_caps = FW_PFVF_CMD_WX_CAPS_GET(word); - vfres->nethctrl = FW_PFVF_CMD_NETHCTRL_GET(word); + vfres->r_caps = FW_PFVF_CMD_R_CAPS_G(word); + vfres->wx_caps = FW_PFVF_CMD_WX_CAPS_G(word); + vfres->nethctrl = FW_PFVF_CMD_NETHCTRL_G(word); return 0; } @@ -695,9 +695,9 @@ int t4vf_read_rss_vi_config(struct adapter *adapter, unsigned int viid, int v; memset(&cmd, 0, sizeof(cmd)); - cmd.op_to_viid = cpu_to_be32(FW_CMD_OP(FW_RSS_VI_CONFIG_CMD) | - FW_CMD_REQUEST | - FW_CMD_READ | + cmd.op_to_viid = cpu_to_be32(FW_CMD_OP_V(FW_RSS_VI_CONFIG_CMD) | + FW_CMD_REQUEST_F | + FW_CMD_READ_F | FW_RSS_VI_CONFIG_CMD_VIID(viid)); cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd)); v = t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), &rpl); @@ -709,17 +709,17 @@ int t4vf_read_rss_vi_config(struct adapter *adapter, unsigned int viid, u32 word = be32_to_cpu(rpl.u.basicvirtual.defaultq_to_udpen); config->basicvirtual.ip6fourtupen = - ((word & FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN) != 0); + ((word & FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN_F) != 0); config->basicvirtual.ip6twotupen = - ((word & FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN) != 0); + ((word & FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN_F) != 0); config->basicvirtual.ip4fourtupen = - ((word & FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN) != 0); + ((word & FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN_F) != 0); config->basicvirtual.ip4twotupen = - ((word & FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN) != 0); + ((word & FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN_F) != 0); config->basicvirtual.udpen = - ((word & FW_RSS_VI_CONFIG_CMD_UDPEN) != 0); + ((word & FW_RSS_VI_CONFIG_CMD_UDPEN_F) != 0); config->basicvirtual.defaultq = - FW_RSS_VI_CONFIG_CMD_DEFAULTQ_GET(word); + FW_RSS_VI_CONFIG_CMD_DEFAULTQ_G(word); break; } @@ -745,9 +745,9 @@ int t4vf_write_rss_vi_config(struct adapter *adapter, unsigned int viid, struct fw_rss_vi_config_cmd cmd, rpl; memset(&cmd, 0, sizeof(cmd)); - cmd.op_to_viid = cpu_to_be32(FW_CMD_OP(FW_RSS_VI_CONFIG_CMD) | - FW_CMD_REQUEST | - FW_CMD_WRITE | + cmd.op_to_viid = cpu_to_be32(FW_CMD_OP_V(FW_RSS_VI_CONFIG_CMD) | + FW_CMD_REQUEST_F | + FW_CMD_WRITE_F | FW_RSS_VI_CONFIG_CMD_VIID(viid)); cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd)); switch (adapter->params.rss.mode) { @@ -755,16 +755,16 @@ int t4vf_write_rss_vi_config(struct adapter *adapter, unsigned int viid, u32 word = 0; if (config->basicvirtual.ip6fourtupen) - word |= FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN; + word |= FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN_F; if (config->basicvirtual.ip6twotupen) - word |= FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN; + word |= FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN_F; if (config->basicvirtual.ip4fourtupen) - word |= FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN; + word |= FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN_F; if (config->basicvirtual.ip4twotupen) - word |= FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN; + word |= FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN_F; if (config->basicvirtual.udpen) - word |= FW_RSS_VI_CONFIG_CMD_UDPEN; - word |= FW_RSS_VI_CONFIG_CMD_DEFAULTQ( + word |= FW_RSS_VI_CONFIG_CMD_UDPEN_F; + word |= FW_RSS_VI_CONFIG_CMD_DEFAULTQ_V( config->basicvirtual.defaultq); cmd.u.basicvirtual.defaultq_to_udpen = cpu_to_be32(word); break; @@ -803,10 +803,10 @@ int t4vf_config_rss_range(struct adapter *adapter, unsigned int viid, * Initialize firmware command template to write the RSS table. */ memset(&cmd, 0, sizeof(cmd)); - cmd.op_to_viid = cpu_to_be32(FW_CMD_OP(FW_RSS_IND_TBL_CMD) | - FW_CMD_REQUEST | - FW_CMD_WRITE | - FW_RSS_IND_TBL_CMD_VIID(viid)); + cmd.op_to_viid = cpu_to_be32(FW_CMD_OP_V(FW_RSS_IND_TBL_CMD) | + FW_CMD_REQUEST_F | + FW_CMD_WRITE_F | + FW_RSS_IND_TBL_CMD_VIID_V(viid)); cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd)); /* @@ -857,9 +857,9 @@ int t4vf_config_rss_range(struct adapter *adapter, unsigned int viid, if (rsp >= rsp_end) rsp = rspq; } - *qp++ = cpu_to_be32(FW_RSS_IND_TBL_CMD_IQ0(qbuf[0]) | - FW_RSS_IND_TBL_CMD_IQ1(qbuf[1]) | - FW_RSS_IND_TBL_CMD_IQ2(qbuf[2])); + *qp++ = cpu_to_be32(FW_RSS_IND_TBL_CMD_IQ0_V(qbuf[0]) | + FW_RSS_IND_TBL_CMD_IQ1_V(qbuf[1]) | + FW_RSS_IND_TBL_CMD_IQ2_V(qbuf[2])); } /* @@ -892,18 +892,18 @@ int t4vf_alloc_vi(struct adapter *adapter, int port_id) * VIID. */ memset(&cmd, 0, sizeof(cmd)); - cmd.op_to_vfn = cpu_to_be32(FW_CMD_OP(FW_VI_CMD) | - FW_CMD_REQUEST | - FW_CMD_WRITE | - FW_CMD_EXEC); + cmd.op_to_vfn = cpu_to_be32(FW_CMD_OP_V(FW_VI_CMD) | + FW_CMD_REQUEST_F | + FW_CMD_WRITE_F | + FW_CMD_EXEC_F); cmd.alloc_to_len16 = cpu_to_be32(FW_LEN16(cmd) | - FW_VI_CMD_ALLOC); - cmd.portid_pkd = FW_VI_CMD_PORTID(port_id); + FW_VI_CMD_ALLOC_F); + cmd.portid_pkd = FW_VI_CMD_PORTID_V(port_id); v = t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), &rpl); if (v) return v; - return FW_VI_CMD_VIID_GET(be16_to_cpu(rpl.type_viid)); + return FW_VI_CMD_VIID_G(be16_to_cpu(rpl.type_viid)); } /** @@ -922,12 +922,12 @@ int t4vf_free_vi(struct adapter *adapter, int viid) * Execute a VI command to free the Virtual Interface. */ memset(&cmd, 0, sizeof(cmd)); - cmd.op_to_vfn = cpu_to_be32(FW_CMD_OP(FW_VI_CMD) | - FW_CMD_REQUEST | - FW_CMD_EXEC); + cmd.op_to_vfn = cpu_to_be32(FW_CMD_OP_V(FW_VI_CMD) | + FW_CMD_REQUEST_F | + FW_CMD_EXEC_F); cmd.alloc_to_len16 = cpu_to_be32(FW_LEN16(cmd) | - FW_VI_CMD_FREE); - cmd.type_viid = cpu_to_be16(FW_VI_CMD_VIID(viid)); + FW_VI_CMD_FREE_F); + cmd.type_viid = cpu_to_be16(FW_VI_CMD_VIID_V(viid)); return t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), NULL); } @@ -946,12 +946,12 @@ int t4vf_enable_vi(struct adapter *adapter, unsigned int viid, struct fw_vi_enable_cmd cmd; memset(&cmd, 0, sizeof(cmd)); - cmd.op_to_viid = cpu_to_be32(FW_CMD_OP(FW_VI_ENABLE_CMD) | - FW_CMD_REQUEST | - FW_CMD_EXEC | - FW_VI_ENABLE_CMD_VIID(viid)); - cmd.ien_to_len16 = cpu_to_be32(FW_VI_ENABLE_CMD_IEN(rx_en) | - FW_VI_ENABLE_CMD_EEN(tx_en) | + cmd.op_to_viid = cpu_to_be32(FW_CMD_OP_V(FW_VI_ENABLE_CMD) | + FW_CMD_REQUEST_F | + FW_CMD_EXEC_F | + FW_VI_ENABLE_CMD_VIID_V(viid)); + cmd.ien_to_len16 = cpu_to_be32(FW_VI_ENABLE_CMD_IEN_V(rx_en) | + FW_VI_ENABLE_CMD_EEN_V(tx_en) | FW_LEN16(cmd)); return t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), NULL); } @@ -970,11 +970,11 @@ int t4vf_identify_port(struct adapter *adapter, unsigned int viid, struct fw_vi_enable_cmd cmd; memset(&cmd, 0, sizeof(cmd)); - cmd.op_to_viid = cpu_to_be32(FW_CMD_OP(FW_VI_ENABLE_CMD) | - FW_CMD_REQUEST | - FW_CMD_EXEC | - FW_VI_ENABLE_CMD_VIID(viid)); - cmd.ien_to_len16 = cpu_to_be32(FW_VI_ENABLE_CMD_LED | + cmd.op_to_viid = cpu_to_be32(FW_CMD_OP_V(FW_VI_ENABLE_CMD) | + FW_CMD_REQUEST_F | + FW_CMD_EXEC_F | + FW_VI_ENABLE_CMD_VIID_V(viid)); + cmd.ien_to_len16 = cpu_to_be32(FW_VI_ENABLE_CMD_LED_F | FW_LEN16(cmd)); cmd.blinkdur = cpu_to_be16(nblinks); return t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), NULL); @@ -1001,28 +1001,28 @@ int t4vf_set_rxmode(struct adapter *adapter, unsigned int viid, /* convert to FW values */ if (mtu < 0) - mtu = FW_VI_RXMODE_CMD_MTU_MASK; + mtu = FW_VI_RXMODE_CMD_MTU_M; if (promisc < 0) - promisc = FW_VI_RXMODE_CMD_PROMISCEN_MASK; + promisc = FW_VI_RXMODE_CMD_PROMISCEN_M; if (all_multi < 0) - all_multi = FW_VI_RXMODE_CMD_ALLMULTIEN_MASK; + all_multi = FW_VI_RXMODE_CMD_ALLMULTIEN_M; if (bcast < 0) - bcast = FW_VI_RXMODE_CMD_BROADCASTEN_MASK; + bcast = FW_VI_RXMODE_CMD_BROADCASTEN_M; if (vlanex < 0) - vlanex = FW_VI_RXMODE_CMD_VLANEXEN_MASK; + vlanex = FW_VI_RXMODE_CMD_VLANEXEN_M; memset(&cmd, 0, sizeof(cmd)); - cmd.op_to_viid = cpu_to_be32(FW_CMD_OP(FW_VI_RXMODE_CMD) | - FW_CMD_REQUEST | - FW_CMD_WRITE | - FW_VI_RXMODE_CMD_VIID(viid)); + cmd.op_to_viid = cpu_to_be32(FW_CMD_OP_V(FW_VI_RXMODE_CMD) | + FW_CMD_REQUEST_F | + FW_CMD_WRITE_F | + FW_VI_RXMODE_CMD_VIID_V(viid)); cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd)); cmd.mtu_to_vlanexen = - cpu_to_be32(FW_VI_RXMODE_CMD_MTU(mtu) | - FW_VI_RXMODE_CMD_PROMISCEN(promisc) | - FW_VI_RXMODE_CMD_ALLMULTIEN(all_multi) | - FW_VI_RXMODE_CMD_BROADCASTEN(bcast) | - FW_VI_RXMODE_CMD_VLANEXEN(vlanex)); + cpu_to_be32(FW_VI_RXMODE_CMD_MTU_V(mtu) | + FW_VI_RXMODE_CMD_PROMISCEN_V(promisc) | + FW_VI_RXMODE_CMD_ALLMULTIEN_V(all_multi) | + FW_VI_RXMODE_CMD_BROADCASTEN_V(bcast) | + FW_VI_RXMODE_CMD_VLANEXEN_V(vlanex)); return t4vf_wr_mbox_core(adapter, &cmd, sizeof(cmd), NULL, sleep_ok); } @@ -1072,19 +1072,19 @@ int t4vf_alloc_mac_filt(struct adapter *adapter, unsigned int viid, bool free, int i; memset(&cmd, 0, sizeof(cmd)); - cmd.op_to_viid = cpu_to_be32(FW_CMD_OP(FW_VI_MAC_CMD) | - FW_CMD_REQUEST | - FW_CMD_WRITE | - (free ? FW_CMD_EXEC : 0) | - FW_VI_MAC_CMD_VIID(viid)); + cmd.op_to_viid = cpu_to_be32(FW_CMD_OP_V(FW_VI_MAC_CMD) | + FW_CMD_REQUEST_F | + FW_CMD_WRITE_F | + (free ? FW_CMD_EXEC_F : 0) | + FW_VI_MAC_CMD_VIID_V(viid)); cmd.freemacs_to_len16 = - cpu_to_be32(FW_VI_MAC_CMD_FREEMACS(free) | - FW_CMD_LEN16(len16)); + cpu_to_be32(FW_VI_MAC_CMD_FREEMACS_V(free) | + FW_CMD_LEN16_V(len16)); for (i = 0, p = cmd.u.exact; i < fw_naddr; i++, p++) { p->valid_to_idx = cpu_to_be16( - FW_VI_MAC_CMD_VALID | - FW_VI_MAC_CMD_IDX(FW_VI_MAC_ADD_MAC)); + FW_VI_MAC_CMD_VALID_F | + FW_VI_MAC_CMD_IDX_V(FW_VI_MAC_ADD_MAC)); memcpy(p->macaddr, addr[offset+i], sizeof(p->macaddr)); } @@ -1095,7 +1095,7 @@ int t4vf_alloc_mac_filt(struct adapter *adapter, unsigned int viid, bool free, break; for (i = 0, p = rpl.u.exact; i < fw_naddr; i++, p++) { - u16 index = FW_VI_MAC_CMD_IDX_GET( + u16 index = FW_VI_MAC_CMD_IDX_G( be16_to_cpu(p->valid_to_idx)); if (idx) @@ -1161,19 +1161,19 @@ int t4vf_change_mac(struct adapter *adapter, unsigned int viid, idx = persist ? FW_VI_MAC_ADD_PERSIST_MAC : FW_VI_MAC_ADD_MAC; memset(&cmd, 0, sizeof(cmd)); - cmd.op_to_viid = cpu_to_be32(FW_CMD_OP(FW_VI_MAC_CMD) | - FW_CMD_REQUEST | - FW_CMD_WRITE | - FW_VI_MAC_CMD_VIID(viid)); - cmd.freemacs_to_len16 = cpu_to_be32(FW_CMD_LEN16(len16)); - p->valid_to_idx = cpu_to_be16(FW_VI_MAC_CMD_VALID | - FW_VI_MAC_CMD_IDX(idx)); + cmd.op_to_viid = cpu_to_be32(FW_CMD_OP_V(FW_VI_MAC_CMD) | + FW_CMD_REQUEST_F | + FW_CMD_WRITE_F | + FW_VI_MAC_CMD_VIID_V(viid)); + cmd.freemacs_to_len16 = cpu_to_be32(FW_CMD_LEN16_V(len16)); + p->valid_to_idx = cpu_to_be16(FW_VI_MAC_CMD_VALID_F | + FW_VI_MAC_CMD_IDX_V(idx)); memcpy(p->macaddr, addr, sizeof(p->macaddr)); ret = t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), &rpl); if (ret == 0) { p = &rpl.u.exact[0]; - ret = FW_VI_MAC_CMD_IDX_GET(be16_to_cpu(p->valid_to_idx)); + ret = FW_VI_MAC_CMD_IDX_G(be16_to_cpu(p->valid_to_idx)); if (ret >= max_naddr) ret = -ENOMEM; } @@ -1198,13 +1198,13 @@ int t4vf_set_addr_hash(struct adapter *adapter, unsigned int viid, u.exact[0]), 16); memset(&cmd, 0, sizeof(cmd)); - cmd.op_to_viid = cpu_to_be32(FW_CMD_OP(FW_VI_MAC_CMD) | - FW_CMD_REQUEST | - FW_CMD_WRITE | - FW_VI_ENABLE_CMD_VIID(viid)); - cmd.freemacs_to_len16 = cpu_to_be32(FW_VI_MAC_CMD_HASHVECEN | - FW_VI_MAC_CMD_HASHUNIEN(ucast) | - FW_CMD_LEN16(len16)); + cmd.op_to_viid = cpu_to_be32(FW_CMD_OP_V(FW_VI_MAC_CMD) | + FW_CMD_REQUEST_F | + FW_CMD_WRITE_F | + FW_VI_ENABLE_CMD_VIID_V(viid)); + cmd.freemacs_to_len16 = cpu_to_be32(FW_VI_MAC_CMD_HASHVECEN_F | + FW_VI_MAC_CMD_HASHUNIEN_V(ucast) | + FW_CMD_LEN16_V(len16)); cmd.u.hash.hashvec = cpu_to_be64(vec); return t4vf_wr_mbox_core(adapter, &cmd, sizeof(cmd), NULL, sleep_ok); } @@ -1240,14 +1240,14 @@ int t4vf_get_port_stats(struct adapter *adapter, int pidx, int ret; memset(&cmd, 0, sizeof(cmd)); - cmd.op_to_viid = cpu_to_be32(FW_CMD_OP(FW_VI_STATS_CMD) | - FW_VI_STATS_CMD_VIID(pi->viid) | - FW_CMD_REQUEST | - FW_CMD_READ); - cmd.retval_len16 = cpu_to_be32(FW_CMD_LEN16(len16)); + cmd.op_to_viid = cpu_to_be32(FW_CMD_OP_V(FW_VI_STATS_CMD) | + FW_VI_STATS_CMD_VIID_V(pi->viid) | + FW_CMD_REQUEST_F | + FW_CMD_READ_F); + cmd.retval_len16 = cpu_to_be32(FW_CMD_LEN16_V(len16)); cmd.u.ctl.nstats_ix = - cpu_to_be16(FW_VI_STATS_CMD_IX(ix) | - FW_VI_STATS_CMD_NSTATS(nstats)); + cpu_to_be16(FW_VI_STATS_CMD_IX_V(ix) | + FW_VI_STATS_CMD_NSTATS_V(nstats)); ret = t4vf_wr_mbox_ns(adapter, &cmd, len, &rpl); if (ret) return ret; @@ -1299,13 +1299,13 @@ int t4vf_iq_free(struct adapter *adapter, unsigned int iqtype, struct fw_iq_cmd cmd; memset(&cmd, 0, sizeof(cmd)); - cmd.op_to_vfn = cpu_to_be32(FW_CMD_OP(FW_IQ_CMD) | - FW_CMD_REQUEST | - FW_CMD_EXEC); - cmd.alloc_to_len16 = cpu_to_be32(FW_IQ_CMD_FREE | + cmd.op_to_vfn = cpu_to_be32(FW_CMD_OP_V(FW_IQ_CMD) | + FW_CMD_REQUEST_F | + FW_CMD_EXEC_F); + cmd.alloc_to_len16 = cpu_to_be32(FW_IQ_CMD_FREE_F | FW_LEN16(cmd)); cmd.type_to_iqandstindex = - cpu_to_be32(FW_IQ_CMD_TYPE(iqtype)); + cpu_to_be32(FW_IQ_CMD_TYPE_V(iqtype)); cmd.iqid = cpu_to_be16(iqid); cmd.fl0id = cpu_to_be16(fl0id); @@ -1325,12 +1325,12 @@ int t4vf_eth_eq_free(struct adapter *adapter, unsigned int eqid) struct fw_eq_eth_cmd cmd; memset(&cmd, 0, sizeof(cmd)); - cmd.op_to_vfn = cpu_to_be32(FW_CMD_OP(FW_EQ_ETH_CMD) | - FW_CMD_REQUEST | - FW_CMD_EXEC); - cmd.alloc_to_len16 = cpu_to_be32(FW_EQ_ETH_CMD_FREE | + cmd.op_to_vfn = cpu_to_be32(FW_CMD_OP_V(FW_EQ_ETH_CMD) | + FW_CMD_REQUEST_F | + FW_CMD_EXEC_F); + cmd.alloc_to_len16 = cpu_to_be32(FW_EQ_ETH_CMD_FREE_F | FW_LEN16(cmd)); - cmd.eqid_pkd = cpu_to_be32(FW_EQ_ETH_CMD_EQID(eqid)); + cmd.eqid_pkd = cpu_to_be32(FW_EQ_ETH_CMD_EQID_V(eqid)); return t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), NULL); } @@ -1344,7 +1344,7 @@ int t4vf_eth_eq_free(struct adapter *adapter, unsigned int eqid) int t4vf_handle_fw_rpl(struct adapter *adapter, const __be64 *rpl) { const struct fw_cmd_hdr *cmd_hdr = (const struct fw_cmd_hdr *)rpl; - u8 opcode = FW_CMD_OP_GET(be32_to_cpu(cmd_hdr->hi)); + u8 opcode = FW_CMD_OP_G(be32_to_cpu(cmd_hdr->hi)); switch (opcode) { case FW_PORT_CMD: { @@ -1359,7 +1359,7 @@ int t4vf_handle_fw_rpl(struct adapter *adapter, const __be64 *rpl) /* * Extract various fields from port status change message. */ - action = FW_PORT_CMD_ACTION_GET( + action = FW_PORT_CMD_ACTION_G( be32_to_cpu(port_cmd->action_to_len16)); if (action != FW_PORT_ACTION_GET_PORT_INFO) { dev_err(adapter->pdev_dev, @@ -1368,24 +1368,24 @@ int t4vf_handle_fw_rpl(struct adapter *adapter, const __be64 *rpl) break; } - port_id = FW_PORT_CMD_PORTID_GET( + port_id = FW_PORT_CMD_PORTID_G( be32_to_cpu(port_cmd->op_to_portid)); word = be32_to_cpu(port_cmd->u.info.lstatus_to_modtype); - link_ok = (word & FW_PORT_CMD_LSTATUS) != 0; + link_ok = (word & FW_PORT_CMD_LSTATUS_F) != 0; speed = 0; fc = 0; - if (word & FW_PORT_CMD_RXPAUSE) + if (word & FW_PORT_CMD_RXPAUSE_F) fc |= PAUSE_RX; - if (word & FW_PORT_CMD_TXPAUSE) + if (word & FW_PORT_CMD_TXPAUSE_F) fc |= PAUSE_TX; - if (word & FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_100M)) + if (word & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_100M)) speed = 100; - else if (word & FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_1G)) + else if (word & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_1G)) speed = 1000; - else if (word & FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_10G)) + else if (word & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_10G)) speed = 10000; - else if (word & FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_40G)) + else if (word & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_40G)) speed = 40000; /* diff --git a/drivers/net/ethernet/cirrus/mac89x0.c b/drivers/net/ethernet/cirrus/mac89x0.c index e285f384b096..07719676c305 100644 --- a/drivers/net/ethernet/cirrus/mac89x0.c +++ b/drivers/net/ethernet/cirrus/mac89x0.c @@ -216,14 +216,10 @@ struct net_device * __init mac89x0_probe(int unit) ioaddr = (unsigned long) nubus_slot_addr(slot) | (((slot&0xf) << 20) + DEFAULTIOBASE); { - unsigned long flags; int card_present; - local_irq_save(flags); - card_present = (hwreg_present((void*) ioaddr+4) && - hwreg_present((void*) ioaddr + DATA_PORT)); - local_irq_restore(flags); - + card_present = (hwreg_present((void *)ioaddr + 4) && + hwreg_present((void *)ioaddr + DATA_PORT)); if (!card_present) goto out; } diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c index 73cf1653a4a3..86ee350e57f0 100644 --- a/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/drivers/net/ethernet/cisco/enic/enic_main.c @@ -283,12 +283,10 @@ static irqreturn_t enic_isr_legacy(int irq, void *data) return IRQ_HANDLED; } - if (ENIC_TEST_INTR(pba, io_intr)) { - if (napi_schedule_prep(&enic->napi[0])) - __napi_schedule(&enic->napi[0]); - } else { + if (ENIC_TEST_INTR(pba, io_intr)) + napi_schedule_irqoff(&enic->napi[0]); + else vnic_intr_unmask(&enic->intr[io_intr]); - } return IRQ_HANDLED; } @@ -313,7 +311,7 @@ static irqreturn_t enic_isr_msi(int irq, void *data) * writes). */ - napi_schedule(&enic->napi[0]); + napi_schedule_irqoff(&enic->napi[0]); return IRQ_HANDLED; } @@ -322,7 +320,7 @@ static irqreturn_t enic_isr_msix(int irq, void *data) { struct napi_struct *napi = data; - napi_schedule(napi); + napi_schedule_irqoff(napi); return IRQ_HANDLED; } @@ -531,8 +529,8 @@ static netdev_tx_t enic_hard_start_xmit(struct sk_buff *skb, { struct enic *enic = netdev_priv(netdev); struct vnic_wq *wq; - unsigned long flags; unsigned int txq_map; + struct netdev_queue *txq; if (skb->len <= 0) { dev_kfree_skb_any(skb); @@ -541,6 +539,7 @@ static netdev_tx_t enic_hard_start_xmit(struct sk_buff *skb, txq_map = skb_get_queue_mapping(skb) % enic->wq_count; wq = &enic->wq[txq_map]; + txq = netdev_get_tx_queue(netdev, txq_map); /* Non-TSO sends must fit within ENIC_NON_TSO_MAX_DESC descs, * which is very likely. In the off chance it's going to take @@ -554,23 +553,25 @@ static netdev_tx_t enic_hard_start_xmit(struct sk_buff *skb, return NETDEV_TX_OK; } - spin_lock_irqsave(&enic->wq_lock[txq_map], flags); + spin_lock(&enic->wq_lock[txq_map]); if (vnic_wq_desc_avail(wq) < skb_shinfo(skb)->nr_frags + ENIC_DESC_MAX_SPLITS) { - netif_tx_stop_queue(netdev_get_tx_queue(netdev, txq_map)); + netif_tx_stop_queue(txq); /* This is a hard error, log it */ netdev_err(netdev, "BUG! Tx ring full when queue awake!\n"); - spin_unlock_irqrestore(&enic->wq_lock[txq_map], flags); + spin_unlock(&enic->wq_lock[txq_map]); return NETDEV_TX_BUSY; } enic_queue_wq_skb(enic, wq, skb); if (vnic_wq_desc_avail(wq) < MAX_SKB_FRAGS + ENIC_DESC_MAX_SPLITS) - netif_tx_stop_queue(netdev_get_tx_queue(netdev, txq_map)); + netif_tx_stop_queue(txq); + if (!skb->xmit_more || netif_xmit_stopped(txq)) + vnic_wq_doorbell(wq); - spin_unlock_irqrestore(&enic->wq_lock[txq_map], flags); + spin_unlock(&enic->wq_lock[txq_map]); return NETDEV_TX_OK; } @@ -1312,9 +1313,10 @@ static int enic_poll_msix_wq(struct napi_struct *napi, int budget) if (!wq_work_done) { napi_complete(napi); vnic_intr_unmask(&enic->intr[intr]); + return 0; } - return 0; + return budget; } static int enic_poll_msix_rq(struct napi_struct *napi, int budget) @@ -1888,23 +1890,23 @@ static int enic_dev_hang_reset(struct enic *enic) static int enic_set_rsskey(struct enic *enic) { + union vnic_rss_key *rss_key_buf_va; dma_addr_t rss_key_buf_pa; - union vnic_rss_key *rss_key_buf_va = NULL; - union vnic_rss_key rss_key = { - .key[0].b = {85, 67, 83, 97, 119, 101, 115, 111, 109, 101}, - .key[1].b = {80, 65, 76, 79, 117, 110, 105, 113, 117, 101}, - .key[2].b = {76, 73, 78, 85, 88, 114, 111, 99, 107, 115}, - .key[3].b = {69, 78, 73, 67, 105, 115, 99, 111, 111, 108}, - }; - int err; + u8 rss_key[ENIC_RSS_LEN]; + int i, kidx, bidx, err; - rss_key_buf_va = pci_alloc_consistent(enic->pdev, - sizeof(union vnic_rss_key), &rss_key_buf_pa); + rss_key_buf_va = pci_zalloc_consistent(enic->pdev, + sizeof(union vnic_rss_key), + &rss_key_buf_pa); if (!rss_key_buf_va) return -ENOMEM; - memcpy(rss_key_buf_va, &rss_key, sizeof(union vnic_rss_key)); - + netdev_rss_key_fill(rss_key, ENIC_RSS_LEN); + for (i = 0; i < ENIC_RSS_LEN; i++) { + kidx = i / ENIC_RSS_BYTES_PER_KEY; + bidx = i % ENIC_RSS_BYTES_PER_KEY; + rss_key_buf_va->key[kidx].b[bidx] = rss_key[i]; + } spin_lock_bh(&enic->devcmd_lock); err = enic_set_rss_key(enic, rss_key_buf_pa, diff --git a/drivers/net/ethernet/cisco/enic/vnic_rss.h b/drivers/net/ethernet/cisco/enic/vnic_rss.h index fa421baf45b8..881fa18542b3 100644 --- a/drivers/net/ethernet/cisco/enic/vnic_rss.h +++ b/drivers/net/ethernet/cisco/enic/vnic_rss.h @@ -20,11 +20,16 @@ #define _VNIC_RSS_H_ /* RSS key array */ + +#define ENIC_RSS_BYTES_PER_KEY 10 +#define ENIC_RSS_KEYS 4 +#define ENIC_RSS_LEN (ENIC_RSS_BYTES_PER_KEY * ENIC_RSS_KEYS) + union vnic_rss_key { struct { - u8 b[10]; + u8 b[ENIC_RSS_BYTES_PER_KEY]; u8 b_pad[6]; - } key[4]; + } key[ENIC_RSS_KEYS]; u64 raw[8]; }; diff --git a/drivers/net/ethernet/cisco/enic/vnic_wq.h b/drivers/net/ethernet/cisco/enic/vnic_wq.h index 2c6c70804a39..816f1ad6072f 100644 --- a/drivers/net/ethernet/cisco/enic/vnic_wq.h +++ b/drivers/net/ethernet/cisco/enic/vnic_wq.h @@ -104,6 +104,17 @@ static inline void *vnic_wq_next_desc(struct vnic_wq *wq) return wq->to_use->desc; } +static inline void vnic_wq_doorbell(struct vnic_wq *wq) +{ + /* Adding write memory barrier prevents compiler and/or CPU + * reordering, thus avoiding descriptor posting before + * descriptor is initialized. Otherwise, hardware can read + * stale descriptor fields. + */ + wmb(); + iowrite32(wq->to_use->index, &wq->ctrl->posted_index); +} + static inline void vnic_wq_post(struct vnic_wq *wq, void *os_buf, dma_addr_t dma_addr, unsigned int len, int sop, int eop, @@ -122,15 +133,6 @@ static inline void vnic_wq_post(struct vnic_wq *wq, buf->wr_id = wrid; buf = buf->next; - if (eop) { - /* Adding write memory barrier prevents compiler and/or CPU - * reordering, thus avoiding descriptor posting before - * descriptor is initialized. Otherwise, hardware can read - * stale descriptor fields. - */ - wmb(); - iowrite32(buf->index, &wq->ctrl->posted_index); - } wq->to_use = buf; wq->ring.desc_avail -= desc_skip_cnt; diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 597c463e384d..dc77ec2bdafd 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -887,7 +887,8 @@ static struct sk_buff *be_insert_vlan_in_pkt(struct be_adapter *adapter, } if (vlan_tag) { - skb = __vlan_put_tag(skb, htons(ETH_P_8021Q), vlan_tag); + skb = vlan_insert_tag_set_proto(skb, htons(ETH_P_8021Q), + vlan_tag); if (unlikely(!skb)) return skb; skb->vlan_tci = 0; @@ -896,7 +897,8 @@ static struct sk_buff *be_insert_vlan_in_pkt(struct be_adapter *adapter, /* Insert the outer VLAN, if any */ if (adapter->qnq_vid) { vlan_tag = adapter->qnq_vid; - skb = __vlan_put_tag(skb, htons(ETH_P_8021Q), vlan_tag); + skb = vlan_insert_tag_set_proto(skb, htons(ETH_P_8021Q), + vlan_tag); if (unlikely(!skb)) return skb; if (skip_hw_vlan) @@ -2853,10 +2855,10 @@ static int be_close(struct net_device *netdev) static int be_rx_qs_create(struct be_adapter *adapter) { + struct rss_info *rss = &adapter->rss_info; + u8 rss_key[RSS_HASH_KEY_LEN]; struct be_rx_obj *rxo; int rc, i, j; - u8 rss_hkey[RSS_HASH_KEY_LEN]; - struct rss_info *rss = &adapter->rss_info; for_all_rx_queues(adapter, rxo, i) { rc = be_queue_alloc(adapter, &rxo->q, RX_Q_LEN, @@ -2901,15 +2903,15 @@ static int be_rx_qs_create(struct be_adapter *adapter) rss->rss_flags = RSS_ENABLE_NONE; } - get_random_bytes(rss_hkey, RSS_HASH_KEY_LEN); + netdev_rss_key_fill(rss_key, RSS_HASH_KEY_LEN); rc = be_cmd_rss_config(adapter, rss->rsstable, rss->rss_flags, - 128, rss_hkey); + 128, rss_key); if (rc) { rss->rss_flags = RSS_ENABLE_NONE; return rc; } - memcpy(rss->rss_hkey, rss_hkey, RSS_HASH_KEY_LEN); + memcpy(rss->rss_hkey, rss_key, RSS_HASH_KEY_LEN); /* First time posting */ for_all_rx_queues(adapter, rxo, i) diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index 9af296a1ca99..469691ad4a1e 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -38,9 +38,9 @@ #define FEC_ADDR_LOW 0x0e4 /* Low 32bits MAC address */ #define FEC_ADDR_HIGH 0x0e8 /* High 16bits MAC address */ #define FEC_OPD 0x0ec /* Opcode + Pause duration */ -#define FEC_TXIC0 0xF0 /* Tx Interrupt Coalescing for ring 0 */ -#define FEC_TXIC1 0xF4 /* Tx Interrupt Coalescing for ring 1 */ -#define FEC_TXIC2 0xF8 /* Tx Interrupt Coalescing for ring 2 */ +#define FEC_TXIC0 0x0f0 /* Tx Interrupt Coalescing for ring 0 */ +#define FEC_TXIC1 0x0f4 /* Tx Interrupt Coalescing for ring 1 */ +#define FEC_TXIC2 0x0f8 /* Tx Interrupt Coalescing for ring 2 */ #define FEC_RXIC0 0x100 /* Rx Interrupt Coalescing for ring 0 */ #define FEC_RXIC1 0x104 /* Rx Interrupt Coalescing for ring 1 */ #define FEC_RXIC2 0x108 /* Rx Interrupt Coalescing for ring 2 */ @@ -53,16 +53,18 @@ #define FEC_R_FSTART 0x150 /* FIFO receive start reg */ #define FEC_R_DES_START_1 0x160 /* Receive descriptor ring 1 */ #define FEC_X_DES_START_1 0x164 /* Transmit descriptor ring 1 */ +#define FEC_R_BUFF_SIZE_1 0x168 /* Maximum receive buff ring1 size */ #define FEC_R_DES_START_2 0x16c /* Receive descriptor ring 2 */ #define FEC_X_DES_START_2 0x170 /* Transmit descriptor ring 2 */ +#define FEC_R_BUFF_SIZE_2 0x174 /* Maximum receive buff ring2 size */ #define FEC_R_DES_START_0 0x180 /* Receive descriptor ring */ #define FEC_X_DES_START_0 0x184 /* Transmit descriptor ring */ -#define FEC_R_BUFF_SIZE 0x188 /* Maximum receive buff size */ +#define FEC_R_BUFF_SIZE_0 0x188 /* Maximum receive buff size */ #define FEC_R_FIFO_RSFL 0x190 /* Receive FIFO section full threshold */ #define FEC_R_FIFO_RSEM 0x194 /* Receive FIFO section empty threshold */ #define FEC_R_FIFO_RAEM 0x198 /* Receive FIFO almost empty threshold */ #define FEC_R_FIFO_RAFL 0x19c /* Receive FIFO almost full threshold */ -#define FEC_RACC 0x1C4 /* Receive Accelerator function */ +#define FEC_RACC 0x1c4 /* Receive Accelerator function */ #define FEC_RCMR_1 0x1c8 /* Receive classification match ring 1 */ #define FEC_RCMR_2 0x1cc /* Receive classification match ring 2 */ #define FEC_DMA_CFG_1 0x1d8 /* DMA class configuration for ring 1 */ @@ -82,57 +84,57 @@ #define RMON_T_DROP 0x200 /* Count of frames not cntd correctly */ #define RMON_T_PACKETS 0x204 /* RMON TX packet count */ #define RMON_T_BC_PKT 0x208 /* RMON TX broadcast pkts */ -#define RMON_T_MC_PKT 0x20C /* RMON TX multicast pkts */ +#define RMON_T_MC_PKT 0x20c /* RMON TX multicast pkts */ #define RMON_T_CRC_ALIGN 0x210 /* RMON TX pkts with CRC align err */ #define RMON_T_UNDERSIZE 0x214 /* RMON TX pkts < 64 bytes, good CRC */ #define RMON_T_OVERSIZE 0x218 /* RMON TX pkts > MAX_FL bytes good CRC */ -#define RMON_T_FRAG 0x21C /* RMON TX pkts < 64 bytes, bad CRC */ +#define RMON_T_FRAG 0x21c /* RMON TX pkts < 64 bytes, bad CRC */ #define RMON_T_JAB 0x220 /* RMON TX pkts > MAX_FL bytes, bad CRC */ #define RMON_T_COL 0x224 /* RMON TX collision count */ #define RMON_T_P64 0x228 /* RMON TX 64 byte pkts */ -#define RMON_T_P65TO127 0x22C /* RMON TX 65 to 127 byte pkts */ +#define RMON_T_P65TO127 0x22c /* RMON TX 65 to 127 byte pkts */ #define RMON_T_P128TO255 0x230 /* RMON TX 128 to 255 byte pkts */ #define RMON_T_P256TO511 0x234 /* RMON TX 256 to 511 byte pkts */ #define RMON_T_P512TO1023 0x238 /* RMON TX 512 to 1023 byte pkts */ -#define RMON_T_P1024TO2047 0x23C /* RMON TX 1024 to 2047 byte pkts */ +#define RMON_T_P1024TO2047 0x23c /* RMON TX 1024 to 2047 byte pkts */ #define RMON_T_P_GTE2048 0x240 /* RMON TX pkts > 2048 bytes */ #define RMON_T_OCTETS 0x244 /* RMON TX octets */ #define IEEE_T_DROP 0x248 /* Count of frames not counted crtly */ -#define IEEE_T_FRAME_OK 0x24C /* Frames tx'd OK */ +#define IEEE_T_FRAME_OK 0x24c /* Frames tx'd OK */ #define IEEE_T_1COL 0x250 /* Frames tx'd with single collision */ #define IEEE_T_MCOL 0x254 /* Frames tx'd with multiple collision */ #define IEEE_T_DEF 0x258 /* Frames tx'd after deferral delay */ -#define IEEE_T_LCOL 0x25C /* Frames tx'd with late collision */ +#define IEEE_T_LCOL 0x25c /* Frames tx'd with late collision */ #define IEEE_T_EXCOL 0x260 /* Frames tx'd with excesv collisions */ #define IEEE_T_MACERR 0x264 /* Frames tx'd with TX FIFO underrun */ #define IEEE_T_CSERR 0x268 /* Frames tx'd with carrier sense err */ -#define IEEE_T_SQE 0x26C /* Frames tx'd with SQE err */ +#define IEEE_T_SQE 0x26c /* Frames tx'd with SQE err */ #define IEEE_T_FDXFC 0x270 /* Flow control pause frames tx'd */ #define IEEE_T_OCTETS_OK 0x274 /* Octet count for frames tx'd w/o err */ #define RMON_R_PACKETS 0x284 /* RMON RX packet count */ #define RMON_R_BC_PKT 0x288 /* RMON RX broadcast pkts */ -#define RMON_R_MC_PKT 0x28C /* RMON RX multicast pkts */ +#define RMON_R_MC_PKT 0x28c /* RMON RX multicast pkts */ #define RMON_R_CRC_ALIGN 0x290 /* RMON RX pkts with CRC alignment err */ #define RMON_R_UNDERSIZE 0x294 /* RMON RX pkts < 64 bytes, good CRC */ #define RMON_R_OVERSIZE 0x298 /* RMON RX pkts > MAX_FL bytes good CRC */ -#define RMON_R_FRAG 0x29C /* RMON RX pkts < 64 bytes, bad CRC */ -#define RMON_R_JAB 0x2A0 /* RMON RX pkts > MAX_FL bytes, bad CRC */ -#define RMON_R_RESVD_O 0x2A4 /* Reserved */ -#define RMON_R_P64 0x2A8 /* RMON RX 64 byte pkts */ -#define RMON_R_P65TO127 0x2AC /* RMON RX 65 to 127 byte pkts */ -#define RMON_R_P128TO255 0x2B0 /* RMON RX 128 to 255 byte pkts */ -#define RMON_R_P256TO511 0x2B4 /* RMON RX 256 to 511 byte pkts */ -#define RMON_R_P512TO1023 0x2B8 /* RMON RX 512 to 1023 byte pkts */ -#define RMON_R_P1024TO2047 0x2BC /* RMON RX 1024 to 2047 byte pkts */ -#define RMON_R_P_GTE2048 0x2C0 /* RMON RX pkts > 2048 bytes */ -#define RMON_R_OCTETS 0x2C4 /* RMON RX octets */ -#define IEEE_R_DROP 0x2C8 /* Count frames not counted correctly */ -#define IEEE_R_FRAME_OK 0x2CC /* Frames rx'd OK */ -#define IEEE_R_CRC 0x2D0 /* Frames rx'd with CRC err */ -#define IEEE_R_ALIGN 0x2D4 /* Frames rx'd with alignment err */ -#define IEEE_R_MACERR 0x2D8 /* Receive FIFO overflow count */ -#define IEEE_R_FDXFC 0x2DC /* Flow control pause frames rx'd */ -#define IEEE_R_OCTETS_OK 0x2E0 /* Octet cnt for frames rx'd w/o err */ +#define RMON_R_FRAG 0x29c /* RMON RX pkts < 64 bytes, bad CRC */ +#define RMON_R_JAB 0x2a0 /* RMON RX pkts > MAX_FL bytes, bad CRC */ +#define RMON_R_RESVD_O 0x2a4 /* Reserved */ +#define RMON_R_P64 0x2a8 /* RMON RX 64 byte pkts */ +#define RMON_R_P65TO127 0x2ac /* RMON RX 65 to 127 byte pkts */ +#define RMON_R_P128TO255 0x2b0 /* RMON RX 128 to 255 byte pkts */ +#define RMON_R_P256TO511 0x2b4 /* RMON RX 256 to 511 byte pkts */ +#define RMON_R_P512TO1023 0x2b8 /* RMON RX 512 to 1023 byte pkts */ +#define RMON_R_P1024TO2047 0x2bc /* RMON RX 1024 to 2047 byte pkts */ +#define RMON_R_P_GTE2048 0x2c0 /* RMON RX pkts > 2048 bytes */ +#define RMON_R_OCTETS 0x2c4 /* RMON RX octets */ +#define IEEE_R_DROP 0x2c8 /* Count frames not counted correctly */ +#define IEEE_R_FRAME_OK 0x2cc /* Frames rx'd OK */ +#define IEEE_R_CRC 0x2d0 /* Frames rx'd with CRC err */ +#define IEEE_R_ALIGN 0x2d4 /* Frames rx'd with alignment err */ +#define IEEE_R_MACERR 0x2d8 /* Receive FIFO overflow count */ +#define IEEE_R_FDXFC 0x2dc /* Flow control pause frames rx'd */ +#define IEEE_R_OCTETS_OK 0x2e0 /* Octet cnt for frames rx'd w/o err */ #else @@ -165,21 +167,23 @@ #define FEC_X_DES_START_0 0x3d4 /* Transmit descriptor ring */ #define FEC_X_DES_START_1 FEC_X_DES_START_0 #define FEC_X_DES_START_2 FEC_X_DES_START_0 -#define FEC_R_BUFF_SIZE 0x3d8 /* Maximum receive buff size */ +#define FEC_R_BUFF_SIZE_0 0x3d8 /* Maximum receive buff size */ +#define FEC_R_BUFF_SIZE_1 FEC_R_BUFF_SIZE_0 +#define FEC_R_BUFF_SIZE_2 FEC_R_BUFF_SIZE_0 #define FEC_FIFO_RAM 0x400 /* FIFO RAM buffer */ /* Not existed in real chip * Just for pass build. */ -#define FEC_RCMR_1 0xFFF -#define FEC_RCMR_2 0xFFF -#define FEC_DMA_CFG_1 0xFFF -#define FEC_DMA_CFG_2 0xFFF -#define FEC_TXIC0 0xFFF -#define FEC_TXIC1 0xFFF -#define FEC_TXIC2 0xFFF -#define FEC_RXIC0 0xFFF -#define FEC_RXIC1 0xFFF -#define FEC_RXIC2 0xFFF +#define FEC_RCMR_1 0xfff +#define FEC_RCMR_2 0xfff +#define FEC_DMA_CFG_1 0xfff +#define FEC_DMA_CFG_2 0xfff +#define FEC_TXIC0 0xfff +#define FEC_TXIC1 0xfff +#define FEC_TXIC2 0xfff +#define FEC_RXIC0 0xfff +#define FEC_RXIC1 0xfff +#define FEC_RXIC2 0xfff #endif /* CONFIG_M5272 */ @@ -213,60 +217,60 @@ struct bufdesc_ex { * The following definitions courtesy of commproc.h, which where * Copyright (c) 1997 Dan Malek (dmalek@jlc.net). */ -#define BD_SC_EMPTY ((ushort)0x8000) /* Receive is empty */ -#define BD_SC_READY ((ushort)0x8000) /* Transmit is ready */ -#define BD_SC_WRAP ((ushort)0x2000) /* Last buffer descriptor */ -#define BD_SC_INTRPT ((ushort)0x1000) /* Interrupt on change */ -#define BD_SC_CM ((ushort)0x0200) /* Continuous mode */ -#define BD_SC_ID ((ushort)0x0100) /* Rec'd too many idles */ -#define BD_SC_P ((ushort)0x0100) /* xmt preamble */ -#define BD_SC_BR ((ushort)0x0020) /* Break received */ -#define BD_SC_FR ((ushort)0x0010) /* Framing error */ -#define BD_SC_PR ((ushort)0x0008) /* Parity error */ -#define BD_SC_OV ((ushort)0x0002) /* Overrun */ -#define BD_SC_CD ((ushort)0x0001) /* ?? */ +#define BD_SC_EMPTY ((ushort)0x8000) /* Receive is empty */ +#define BD_SC_READY ((ushort)0x8000) /* Transmit is ready */ +#define BD_SC_WRAP ((ushort)0x2000) /* Last buffer descriptor */ +#define BD_SC_INTRPT ((ushort)0x1000) /* Interrupt on change */ +#define BD_SC_CM ((ushort)0x0200) /* Continuous mode */ +#define BD_SC_ID ((ushort)0x0100) /* Rec'd too many idles */ +#define BD_SC_P ((ushort)0x0100) /* xmt preamble */ +#define BD_SC_BR ((ushort)0x0020) /* Break received */ +#define BD_SC_FR ((ushort)0x0010) /* Framing error */ +#define BD_SC_PR ((ushort)0x0008) /* Parity error */ +#define BD_SC_OV ((ushort)0x0002) /* Overrun */ +#define BD_SC_CD ((ushort)0x0001) /* ?? */ /* Buffer descriptor control/status used by Ethernet receive. -*/ -#define BD_ENET_RX_EMPTY ((ushort)0x8000) -#define BD_ENET_RX_WRAP ((ushort)0x2000) -#define BD_ENET_RX_INTR ((ushort)0x1000) -#define BD_ENET_RX_LAST ((ushort)0x0800) -#define BD_ENET_RX_FIRST ((ushort)0x0400) -#define BD_ENET_RX_MISS ((ushort)0x0100) -#define BD_ENET_RX_LG ((ushort)0x0020) -#define BD_ENET_RX_NO ((ushort)0x0010) -#define BD_ENET_RX_SH ((ushort)0x0008) -#define BD_ENET_RX_CR ((ushort)0x0004) -#define BD_ENET_RX_OV ((ushort)0x0002) -#define BD_ENET_RX_CL ((ushort)0x0001) -#define BD_ENET_RX_STATS ((ushort)0x013f) /* All status bits */ + */ +#define BD_ENET_RX_EMPTY ((ushort)0x8000) +#define BD_ENET_RX_WRAP ((ushort)0x2000) +#define BD_ENET_RX_INTR ((ushort)0x1000) +#define BD_ENET_RX_LAST ((ushort)0x0800) +#define BD_ENET_RX_FIRST ((ushort)0x0400) +#define BD_ENET_RX_MISS ((ushort)0x0100) +#define BD_ENET_RX_LG ((ushort)0x0020) +#define BD_ENET_RX_NO ((ushort)0x0010) +#define BD_ENET_RX_SH ((ushort)0x0008) +#define BD_ENET_RX_CR ((ushort)0x0004) +#define BD_ENET_RX_OV ((ushort)0x0002) +#define BD_ENET_RX_CL ((ushort)0x0001) +#define BD_ENET_RX_STATS ((ushort)0x013f) /* All status bits */ /* Enhanced buffer descriptor control/status used by Ethernet receive */ -#define BD_ENET_RX_VLAN 0x00000004 +#define BD_ENET_RX_VLAN 0x00000004 /* Buffer descriptor control/status used by Ethernet transmit. -*/ -#define BD_ENET_TX_READY ((ushort)0x8000) -#define BD_ENET_TX_PAD ((ushort)0x4000) -#define BD_ENET_TX_WRAP ((ushort)0x2000) -#define BD_ENET_TX_INTR ((ushort)0x1000) -#define BD_ENET_TX_LAST ((ushort)0x0800) -#define BD_ENET_TX_TC ((ushort)0x0400) -#define BD_ENET_TX_DEF ((ushort)0x0200) -#define BD_ENET_TX_HB ((ushort)0x0100) -#define BD_ENET_TX_LC ((ushort)0x0080) -#define BD_ENET_TX_RL ((ushort)0x0040) -#define BD_ENET_TX_RCMASK ((ushort)0x003c) -#define BD_ENET_TX_UN ((ushort)0x0002) -#define BD_ENET_TX_CSL ((ushort)0x0001) -#define BD_ENET_TX_STATS ((ushort)0x0fff) /* All status bits */ - -/*enhanced buffer descriptor control/status used by Ethernet transmit*/ -#define BD_ENET_TX_INT 0x40000000 -#define BD_ENET_TX_TS 0x20000000 -#define BD_ENET_TX_PINS 0x10000000 -#define BD_ENET_TX_IINS 0x08000000 + */ +#define BD_ENET_TX_READY ((ushort)0x8000) +#define BD_ENET_TX_PAD ((ushort)0x4000) +#define BD_ENET_TX_WRAP ((ushort)0x2000) +#define BD_ENET_TX_INTR ((ushort)0x1000) +#define BD_ENET_TX_LAST ((ushort)0x0800) +#define BD_ENET_TX_TC ((ushort)0x0400) +#define BD_ENET_TX_DEF ((ushort)0x0200) +#define BD_ENET_TX_HB ((ushort)0x0100) +#define BD_ENET_TX_LC ((ushort)0x0080) +#define BD_ENET_TX_RL ((ushort)0x0040) +#define BD_ENET_TX_RCMASK ((ushort)0x003c) +#define BD_ENET_TX_UN ((ushort)0x0002) +#define BD_ENET_TX_CSL ((ushort)0x0001) +#define BD_ENET_TX_STATS ((ushort)0x0fff) /* All status bits */ + +/* enhanced buffer descriptor control/status used by Ethernet transmit */ +#define BD_ENET_TX_INT 0x40000000 +#define BD_ENET_TX_TS 0x20000000 +#define BD_ENET_TX_PINS 0x10000000 +#define BD_ENET_TX_IINS 0x08000000 /* This device has up to three irqs on some platforms */ @@ -279,36 +283,40 @@ struct bufdesc_ex { #define FEC_ENET_MAX_TX_QS 3 #define FEC_ENET_MAX_RX_QS 3 -#define FEC_R_DES_START(X) ((X == 1) ? FEC_R_DES_START_1 : \ - ((X == 2) ? \ +#define FEC_R_DES_START(X) (((X) == 1) ? FEC_R_DES_START_1 : \ + (((X) == 2) ? \ FEC_R_DES_START_2 : FEC_R_DES_START_0)) -#define FEC_X_DES_START(X) ((X == 1) ? FEC_X_DES_START_1 : \ - ((X == 2) ? \ +#define FEC_X_DES_START(X) (((X) == 1) ? FEC_X_DES_START_1 : \ + (((X) == 2) ? \ FEC_X_DES_START_2 : FEC_X_DES_START_0)) -#define FEC_R_DES_ACTIVE(X) ((X == 1) ? FEC_R_DES_ACTIVE_1 : \ - ((X == 2) ? \ +#define FEC_R_BUFF_SIZE(X) (((X) == 1) ? FEC_R_BUFF_SIZE_1 : \ + (((X) == 2) ? \ + FEC_R_BUFF_SIZE_2 : FEC_R_BUFF_SIZE_0)) +#define FEC_R_DES_ACTIVE(X) (((X) == 1) ? FEC_R_DES_ACTIVE_1 : \ + (((X) == 2) ? \ FEC_R_DES_ACTIVE_2 : FEC_R_DES_ACTIVE_0)) -#define FEC_X_DES_ACTIVE(X) ((X == 1) ? FEC_X_DES_ACTIVE_1 : \ - ((X == 2) ? \ +#define FEC_X_DES_ACTIVE(X) (((X) == 1) ? FEC_X_DES_ACTIVE_1 : \ + (((X) == 2) ? \ FEC_X_DES_ACTIVE_2 : FEC_X_DES_ACTIVE_0)) -#define FEC_DMA_CFG(X) ((X == 2) ? FEC_DMA_CFG_2 : FEC_DMA_CFG_1) +#define FEC_DMA_CFG(X) (((X) == 2) ? FEC_DMA_CFG_2 : FEC_DMA_CFG_1) #define DMA_CLASS_EN (1 << 16) -#define FEC_RCMR(X) ((X == 2) ? FEC_RCMR_2 : FEC_RCMR_1) -#define IDLE_SLOPE_MASK 0xFFFF +#define FEC_RCMR(X) (((X) == 2) ? FEC_RCMR_2 : FEC_RCMR_1) +#define IDLE_SLOPE_MASK 0xffff #define IDLE_SLOPE_1 0x200 /* BW fraction: 0.5 */ #define IDLE_SLOPE_2 0x200 /* BW fraction: 0.5 */ -#define IDLE_SLOPE(X) ((X == 1) ? (IDLE_SLOPE_1 & IDLE_SLOPE_MASK) : \ +#define IDLE_SLOPE(X) (((X) == 1) ? \ + (IDLE_SLOPE_1 & IDLE_SLOPE_MASK) : \ (IDLE_SLOPE_2 & IDLE_SLOPE_MASK)) -#define RCMR_MATCHEN (0x1 << 16) -#define RCMR_CMP_CFG(v, n) ((v & 0x7) << (n << 2)) +#define RCMR_MATCHEN (0x1 << 16) +#define RCMR_CMP_CFG(v, n) (((v) & 0x7) << (n << 2)) #define RCMR_CMP_1 (RCMR_CMP_CFG(0, 0) | RCMR_CMP_CFG(1, 1) | \ RCMR_CMP_CFG(2, 2) | RCMR_CMP_CFG(3, 3)) #define RCMR_CMP_2 (RCMR_CMP_CFG(4, 0) | RCMR_CMP_CFG(5, 1) | \ RCMR_CMP_CFG(6, 2) | RCMR_CMP_CFG(7, 3)) -#define RCMR_CMP(X) ((X == 1) ? RCMR_CMP_1 : RCMR_CMP_2) -#define FEC_TX_BD_FTYPE(X) ((X & 0xF) << 20) +#define RCMR_CMP(X) (((X) == 1) ? RCMR_CMP_1 : RCMR_CMP_2) +#define FEC_TX_BD_FTYPE(X) (((X) & 0xf) << 20) /* The number of Tx and Rx buffers. These are allocated from the page * pool. The code may assume these are power of two, so it it best @@ -326,8 +334,8 @@ struct bufdesc_ex { #define TX_RING_SIZE 512 /* Must be power of two */ #define TX_RING_MOD_MASK 511 /* for this to work */ -#define BD_ENET_RX_INT 0x00800000 -#define BD_ENET_RX_PTP ((ushort)0x0400) +#define BD_ENET_RX_INT 0x00800000 +#define BD_ENET_RX_PTP ((ushort)0x0400) #define BD_ENET_RX_ICE 0x00000020 #define BD_ENET_RX_PCR 0x00000010 #define FLAG_RX_CSUM_ENABLED (BD_ENET_RX_ICE | BD_ENET_RX_PCR) @@ -359,13 +367,13 @@ struct bufdesc_ex { /* ENET interrupt coalescing macro define */ #define FEC_ITR_CLK_SEL (0x1 << 30) #define FEC_ITR_EN (0x1 << 31) -#define FEC_ITR_ICFT(X) ((X & 0xFF) << 20) -#define FEC_ITR_ICTT(X) ((X) & 0xFFFF) +#define FEC_ITR_ICFT(X) (((X) & 0xff) << 20) +#define FEC_ITR_ICTT(X) ((X) & 0xffff) #define FEC_ITR_ICFT_DEFAULT 200 /* Set 200 frame count threshold */ #define FEC_ITR_ICTT_DEFAULT 1000 /* Set 1000us timer threshold */ -#define FEC_VLAN_TAG_LEN 0x04 -#define FEC_ETHTYPE_LEN 0x02 +#define FEC_VLAN_TAG_LEN 0x04 +#define FEC_ETHTYPE_LEN 0x02 /* Controller is ENET-MAC */ #define FEC_QUIRK_ENET_MAC (1 << 0) @@ -390,7 +398,7 @@ struct bufdesc_ex { * frames not being transmitted until there is a 0-to-1 transition on * ENET_TDAR[TDAR]. */ -#define FEC_QUIRK_ERR006358 (1 << 7) +#define FEC_QUIRK_ERR006358 (1 << 7) /* ENET IP hw AVB * * i.MX6SX ENET IP add Audio Video Bridging (AVB) feature support. @@ -501,8 +509,9 @@ struct fec_enet_private { int speed; struct completion mdio_done; int irq[FEC_IRQ_NUM]; - int bufdesc_ex; + bool bufdesc_ex; int pause_flag; + u32 quirks; struct napi_struct napi; int csum_flags; diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 3dca494797bd..d2955ce24d0b 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -287,15 +287,13 @@ static int fec_enet_get_free_txdesc_num(struct fec_enet_private *fep, return entries > 0 ? entries : entries + txq->tx_ring_size; } -static void *swap_buffer(void *bufaddr, int len) +static void swap_buffer(void *bufaddr, int len) { int i; unsigned int *buf = bufaddr; - for (i = 0; i < DIV_ROUND_UP(len, 4); i++, buf++) - *buf = cpu_to_be32(*buf); - - return bufaddr; + for (i = 0; i < len; i += 4, buf++) + swab32s(buf); } static void swap_buffer2(void *dst_buf, void *src_buf, int len) @@ -361,8 +359,6 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq, struct net_device *ndev) { struct fec_enet_private *fep = netdev_priv(ndev); - const struct platform_device_id *id_entry = - platform_get_device_id(fep->pdev); struct bufdesc *bdp = txq->cur_tx; struct bufdesc_ex *ebdp; int nr_frags = skb_shinfo(skb)->nr_frags; @@ -398,7 +394,7 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq, } if (fep->bufdesc_ex) { - if (id_entry->driver_data & FEC_QUIRK_HAS_AVB) + if (fep->quirks & FEC_QUIRK_HAS_AVB) estatus |= FEC_TX_BD_FTYPE(queue); if (skb->ip_summed == CHECKSUM_PARTIAL) estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS; @@ -410,11 +406,11 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq, index = fec_enet_get_bd_index(txq->tx_bd_base, bdp, fep); if (((unsigned long) bufaddr) & fep->tx_align || - id_entry->driver_data & FEC_QUIRK_SWAP_FRAME) { + fep->quirks & FEC_QUIRK_SWAP_FRAME) { memcpy(txq->tx_bounce[index], bufaddr, frag_len); bufaddr = txq->tx_bounce[index]; - if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME) + if (fep->quirks & FEC_QUIRK_SWAP_FRAME) swap_buffer(bufaddr, frag_len); } @@ -450,8 +446,6 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, struct sk_buff *skb, struct net_device *ndev) { struct fec_enet_private *fep = netdev_priv(ndev); - const struct platform_device_id *id_entry = - platform_get_device_id(fep->pdev); int nr_frags = skb_shinfo(skb)->nr_frags; struct bufdesc *bdp, *last_bdp; void *bufaddr; @@ -490,11 +484,11 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, queue = skb_get_queue_mapping(skb); index = fec_enet_get_bd_index(txq->tx_bd_base, bdp, fep); if (((unsigned long) bufaddr) & fep->tx_align || - id_entry->driver_data & FEC_QUIRK_SWAP_FRAME) { + fep->quirks & FEC_QUIRK_SWAP_FRAME) { memcpy(txq->tx_bounce[index], skb->data, buflen); bufaddr = txq->tx_bounce[index]; - if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME) + if (fep->quirks & FEC_QUIRK_SWAP_FRAME) swap_buffer(bufaddr, buflen); } @@ -529,7 +523,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, fep->hwts_tx_en)) skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; - if (id_entry->driver_data & FEC_QUIRK_HAS_AVB) + if (fep->quirks & FEC_QUIRK_HAS_AVB) estatus |= FEC_TX_BD_FTYPE(queue); if (skb->ip_summed == CHECKSUM_PARTIAL) @@ -573,8 +567,6 @@ fec_enet_txq_put_data_tso(struct fec_enet_priv_tx_q *txq, struct sk_buff *skb, int size, bool last_tcp, bool is_last) { struct fec_enet_private *fep = netdev_priv(ndev); - const struct platform_device_id *id_entry = - platform_get_device_id(fep->pdev); struct bufdesc_ex *ebdp = container_of(bdp, struct bufdesc_ex, desc); unsigned short queue = skb_get_queue_mapping(skb); unsigned short status; @@ -587,11 +579,11 @@ fec_enet_txq_put_data_tso(struct fec_enet_priv_tx_q *txq, struct sk_buff *skb, status |= (BD_ENET_TX_TC | BD_ENET_TX_READY); if (((unsigned long) data) & fep->tx_align || - id_entry->driver_data & FEC_QUIRK_SWAP_FRAME) { + fep->quirks & FEC_QUIRK_SWAP_FRAME) { memcpy(txq->tx_bounce[index], data, size); data = txq->tx_bounce[index]; - if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME) + if (fep->quirks & FEC_QUIRK_SWAP_FRAME) swap_buffer(data, size); } @@ -607,7 +599,7 @@ fec_enet_txq_put_data_tso(struct fec_enet_priv_tx_q *txq, struct sk_buff *skb, bdp->cbd_bufaddr = addr; if (fep->bufdesc_ex) { - if (id_entry->driver_data & FEC_QUIRK_HAS_AVB) + if (fep->quirks & FEC_QUIRK_HAS_AVB) estatus |= FEC_TX_BD_FTYPE(queue); if (skb->ip_summed == CHECKSUM_PARTIAL) estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS; @@ -635,8 +627,6 @@ fec_enet_txq_put_hdr_tso(struct fec_enet_priv_tx_q *txq, struct bufdesc *bdp, int index) { struct fec_enet_private *fep = netdev_priv(ndev); - const struct platform_device_id *id_entry = - platform_get_device_id(fep->pdev); int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); struct bufdesc_ex *ebdp = container_of(bdp, struct bufdesc_ex, desc); unsigned short queue = skb_get_queue_mapping(skb); @@ -652,11 +642,11 @@ fec_enet_txq_put_hdr_tso(struct fec_enet_priv_tx_q *txq, bufaddr = txq->tso_hdrs + index * TSO_HEADER_SIZE; dmabuf = txq->tso_hdrs_dma + index * TSO_HEADER_SIZE; if (((unsigned long)bufaddr) & fep->tx_align || - id_entry->driver_data & FEC_QUIRK_SWAP_FRAME) { + fep->quirks & FEC_QUIRK_SWAP_FRAME) { memcpy(txq->tx_bounce[index], skb->data, hdr_len); bufaddr = txq->tx_bounce[index]; - if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME) + if (fep->quirks & FEC_QUIRK_SWAP_FRAME) swap_buffer(bufaddr, hdr_len); dmabuf = dma_map_single(&fep->pdev->dev, bufaddr, @@ -673,7 +663,7 @@ fec_enet_txq_put_hdr_tso(struct fec_enet_priv_tx_q *txq, bdp->cbd_datlen = hdr_len; if (fep->bufdesc_ex) { - if (id_entry->driver_data & FEC_QUIRK_HAS_AVB) + if (fep->quirks & FEC_QUIRK_HAS_AVB) estatus |= FEC_TX_BD_FTYPE(queue); if (skb->ip_summed == CHECKSUM_PARTIAL) estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS; @@ -698,8 +688,6 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq, struct tso_t tso; unsigned int index = 0; int ret; - const struct platform_device_id *id_entry = - platform_get_device_id(fep->pdev); if (tso_count_descs(skb) >= fec_enet_get_free_txdesc_num(fep, txq)) { dev_kfree_skb_any(skb); @@ -761,7 +749,7 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq, txq->cur_tx = bdp; /* Trigger transmission start */ - if (!(id_entry->driver_data & FEC_QUIRK_ERR007885) || + if (!(fep->quirks & FEC_QUIRK_ERR007885) || !readl(fep->hwp + FEC_X_DES_ACTIVE(queue)) || !readl(fep->hwp + FEC_X_DES_ACTIVE(queue)) || !readl(fep->hwp + FEC_X_DES_ACTIVE(queue)) || @@ -879,6 +867,7 @@ static void fec_enet_enable_ring(struct net_device *ndev) for (i = 0; i < fep->num_rx_queues; i++) { rxq = fep->rx_queue[i]; writel(rxq->bd_dma, fep->hwp + FEC_R_DES_START(i)); + writel(PKT_MAXBLR_SIZE, fep->hwp + FEC_R_BUFF_SIZE(i)); /* enable DMA1/2 */ if (i) @@ -924,8 +913,6 @@ static void fec_restart(struct net_device *ndev) { struct fec_enet_private *fep = netdev_priv(ndev); - const struct platform_device_id *id_entry = - platform_get_device_id(fep->pdev); u32 val; u32 temp_mac[2]; u32 rcntl = OPT_FRAME_SIZE | 0x04; @@ -935,7 +922,7 @@ fec_restart(struct net_device *ndev) * For i.MX6SX SOC, enet use AXI bus, we use disable MAC * instead of reset MAC itself. */ - if (id_entry && id_entry->driver_data & FEC_QUIRK_HAS_AVB) { + if (fep->quirks & FEC_QUIRK_HAS_AVB) { writel(0, fep->hwp + FEC_ECNTRL); } else { writel(1, fep->hwp + FEC_ECNTRL); @@ -946,7 +933,7 @@ fec_restart(struct net_device *ndev) * enet-mac reset will reset mac address registers too, * so need to reconfigure it. */ - if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) { + if (fep->quirks & FEC_QUIRK_ENET_MAC) { memcpy(&temp_mac, ndev->dev_addr, ETH_ALEN); writel(cpu_to_be32(temp_mac[0]), fep->hwp + FEC_ADDR_LOW); writel(cpu_to_be32(temp_mac[1]), fep->hwp + FEC_ADDR_HIGH); @@ -955,9 +942,6 @@ fec_restart(struct net_device *ndev) /* Clear any outstanding interrupt. */ writel(0xffc00000, fep->hwp + FEC_IEVENT); - /* Set maximum receive buffer size. */ - writel(PKT_MAXBLR_SIZE, fep->hwp + FEC_R_BUFF_SIZE); - fec_enet_bd_init(ndev); fec_enet_enable_ring(ndev); @@ -992,7 +976,7 @@ fec_restart(struct net_device *ndev) * The phy interface and speed need to get configured * differently on enet-mac. */ - if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) { + if (fep->quirks & FEC_QUIRK_ENET_MAC) { /* Enable flow control and length check */ rcntl |= 0x40000000 | 0x00000020; @@ -1015,7 +999,7 @@ fec_restart(struct net_device *ndev) } } else { #ifdef FEC_MIIGSK_ENR - if (id_entry->driver_data & FEC_QUIRK_USE_GASKET) { + if (fep->quirks & FEC_QUIRK_USE_GASKET) { u32 cfgr; /* disable the gasket and wait */ writel(0, fep->hwp + FEC_MIIGSK_ENR); @@ -1068,7 +1052,7 @@ fec_restart(struct net_device *ndev) writel(0, fep->hwp + FEC_HASH_TABLE_LOW); #endif - if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) { + if (fep->quirks & FEC_QUIRK_ENET_MAC) { /* enable ENET endian swap */ ecntl |= (1 << 8); /* enable ENET store and forward mode */ @@ -1102,8 +1086,6 @@ static void fec_stop(struct net_device *ndev) { struct fec_enet_private *fep = netdev_priv(ndev); - const struct platform_device_id *id_entry = - platform_get_device_id(fep->pdev); u32 rmii_mode = readl(fep->hwp + FEC_R_CNTRL) & (1 << 8); /* We cannot expect a graceful transmit stop without link !!! */ @@ -1118,7 +1100,7 @@ fec_stop(struct net_device *ndev) * For i.MX6SX SOC, enet use AXI bus, we use disable MAC * instead of reset MAC itself. */ - if (id_entry && id_entry->driver_data & FEC_QUIRK_HAS_AVB) { + if (fep->quirks & FEC_QUIRK_HAS_AVB) { writel(0, fep->hwp + FEC_ECNTRL); } else { writel(1, fep->hwp + FEC_ECNTRL); @@ -1128,7 +1110,7 @@ fec_stop(struct net_device *ndev) writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK); /* We have to keep ENET enabled to have MII interrupt stay working */ - if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) { + if (fep->quirks & FEC_QUIRK_ENET_MAC) { writel(2, fep->hwp + FEC_ECNTRL); writel(rmii_mode, fep->hwp + FEC_R_CNTRL); } @@ -1350,8 +1332,6 @@ static int fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) { struct fec_enet_private *fep = netdev_priv(ndev); - const struct platform_device_id *id_entry = - platform_get_device_id(fep->pdev); struct fec_enet_priv_rx_q *rxq; struct bufdesc *bdp; unsigned short status; @@ -1365,7 +1345,7 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) u16 vlan_tag; int index = 0; bool is_copybreak; - bool need_swap = id_entry->driver_data & FEC_QUIRK_SWAP_FRAME; + bool need_swap = fep->quirks & FEC_QUIRK_SWAP_FRAME; #ifdef CONFIG_M532x flush_cache_all(); @@ -1880,8 +1860,6 @@ failed_clk_ipg: static int fec_enet_mii_probe(struct net_device *ndev) { struct fec_enet_private *fep = netdev_priv(ndev); - const struct platform_device_id *id_entry = - platform_get_device_id(fep->pdev); struct phy_device *phy_dev = NULL; char mdio_bus_id[MII_BUS_ID_SIZE]; char phy_name[MII_BUS_ID_SIZE + 3]; @@ -1927,7 +1905,7 @@ static int fec_enet_mii_probe(struct net_device *ndev) } /* mask with MAC supported features */ - if (id_entry->driver_data & FEC_QUIRK_HAS_GBIT) { + if (fep->quirks & FEC_QUIRK_HAS_GBIT) { phy_dev->supported &= PHY_GBIT_FEATURES; phy_dev->supported &= ~SUPPORTED_1000baseT_Half; #if !defined(CONFIG_M5272) @@ -1955,8 +1933,6 @@ static int fec_enet_mii_init(struct platform_device *pdev) static struct mii_bus *fec0_mii_bus; struct net_device *ndev = platform_get_drvdata(pdev); struct fec_enet_private *fep = netdev_priv(ndev); - const struct platform_device_id *id_entry = - platform_get_device_id(fep->pdev); struct device_node *node; int err = -ENXIO, i; @@ -1976,7 +1952,7 @@ static int fec_enet_mii_init(struct platform_device *pdev) * mdio interface in board design, and need to be configured by * fec0 mii_bus. */ - if ((id_entry->driver_data & FEC_QUIRK_ENET_MAC) && fep->dev_id > 0) { + if ((fep->quirks & FEC_QUIRK_ENET_MAC) && fep->dev_id > 0) { /* fec1 uses fec0 mii_bus */ if (mii_cnt && fec0_mii_bus) { fep->mii_bus = fec0_mii_bus; @@ -1997,7 +1973,7 @@ static int fec_enet_mii_init(struct platform_device *pdev) * document. */ fep->phy_speed = DIV_ROUND_UP(clk_get_rate(fep->clk_ipg), 5000000); - if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) + if (fep->quirks & FEC_QUIRK_ENET_MAC) fep->phy_speed--; fep->phy_speed <<= 1; writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); @@ -2039,7 +2015,7 @@ static int fec_enet_mii_init(struct platform_device *pdev) mii_cnt++; /* save fec0 mii_bus */ - if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) + if (fep->quirks & FEC_QUIRK_ENET_MAC) fec0_mii_bus = fep->mii_bus; return 0; @@ -2308,11 +2284,9 @@ static int fec_enet_us_to_itr_clock(struct net_device *ndev, int us) static void fec_enet_itr_coal_set(struct net_device *ndev) { struct fec_enet_private *fep = netdev_priv(ndev); - const struct platform_device_id *id_entry = - platform_get_device_id(fep->pdev); int rx_itr, tx_itr; - if (!(id_entry->driver_data & FEC_QUIRK_HAS_AVB)) + if (!(fep->quirks & FEC_QUIRK_HAS_AVB)) return; /* Must be greater than zero to avoid unpredictable behavior */ @@ -2347,10 +2321,8 @@ static int fec_enet_get_coalesce(struct net_device *ndev, struct ethtool_coalesce *ec) { struct fec_enet_private *fep = netdev_priv(ndev); - const struct platform_device_id *id_entry = - platform_get_device_id(fep->pdev); - if (!(id_entry->driver_data & FEC_QUIRK_HAS_AVB)) + if (!(fep->quirks & FEC_QUIRK_HAS_AVB)) return -EOPNOTSUPP; ec->rx_coalesce_usecs = fep->rx_time_itr; @@ -2366,12 +2338,9 @@ static int fec_enet_set_coalesce(struct net_device *ndev, struct ethtool_coalesce *ec) { struct fec_enet_private *fep = netdev_priv(ndev); - const struct platform_device_id *id_entry = - platform_get_device_id(fep->pdev); - unsigned int cycle; - if (!(id_entry->driver_data & FEC_QUIRK_HAS_AVB)) + if (!(fep->quirks & FEC_QUIRK_HAS_AVB)) return -EOPNOTSUPP; if (ec->rx_max_coalesced_frames > 255) { @@ -2951,8 +2920,6 @@ static const struct net_device_ops fec_netdev_ops = { static int fec_enet_init(struct net_device *ndev) { struct fec_enet_private *fep = netdev_priv(ndev); - const struct platform_device_id *id_entry = - platform_get_device_id(fep->pdev); struct fec_enet_priv_tx_q *txq; struct fec_enet_priv_rx_q *rxq; struct bufdesc *cbd_base; @@ -3031,11 +2998,11 @@ static int fec_enet_init(struct net_device *ndev) writel(FEC_RX_DISABLED_IMASK, fep->hwp + FEC_IMASK); netif_napi_add(ndev, &fep->napi, fec_enet_rx_napi, NAPI_POLL_WEIGHT); - if (id_entry->driver_data & FEC_QUIRK_HAS_VLAN) + if (fep->quirks & FEC_QUIRK_HAS_VLAN) /* enable hw VLAN support */ ndev->features |= NETIF_F_HW_VLAN_CTAG_RX; - if (id_entry->driver_data & FEC_QUIRK_HAS_CSUM) { + if (fep->quirks & FEC_QUIRK_HAS_CSUM) { ndev->gso_max_segs = FEC_MAX_TSO_SEGS; /* enable hw accelerator */ @@ -3044,7 +3011,7 @@ static int fec_enet_init(struct net_device *ndev) fep->csum_flags |= FLAG_RX_CSUM_ENABLED; } - if (id_entry->driver_data & FEC_QUIRK_HAS_AVB) { + if (fep->quirks & FEC_QUIRK_HAS_AVB) { fep->tx_align = 0; fep->rx_align = 0x3f; } @@ -3144,10 +3111,6 @@ fec_probe(struct platform_device *pdev) int num_tx_qs; int num_rx_qs; - of_id = of_match_device(fec_dt_ids, &pdev->dev); - if (of_id) - pdev->id_entry = of_id->data; - fec_enet_get_queue_num(pdev, &num_tx_qs, &num_rx_qs); /* Init network device */ @@ -3161,13 +3124,17 @@ fec_probe(struct platform_device *pdev) /* setup board info structure */ fep = netdev_priv(ndev); + of_id = of_match_device(fec_dt_ids, &pdev->dev); + if (of_id) + pdev->id_entry = of_id->data; + fep->quirks = pdev->id_entry->driver_data; + fep->num_rx_queues = num_rx_qs; fep->num_tx_queues = num_tx_qs; #if !defined(CONFIG_M5272) /* default enable pause frame auto negotiation */ - if (pdev->id_entry && - (pdev->id_entry->driver_data & FEC_QUIRK_HAS_GBIT)) + if (fep->quirks & FEC_QUIRK_HAS_GBIT) fep->pause_flag |= FEC_PAUSE_FLAG_AUTONEG; #endif @@ -3184,8 +3151,6 @@ fec_probe(struct platform_device *pdev) fep->pdev = pdev; fep->dev_id = dev_id++; - fep->bufdesc_ex = 0; - platform_set_drvdata(pdev, ndev); phy_node = of_parse_phandle(np, "phy-handle", 0); @@ -3238,12 +3203,11 @@ fec_probe(struct platform_device *pdev) if (IS_ERR(fep->clk_ref)) fep->clk_ref = NULL; + fep->bufdesc_ex = fep->quirks & FEC_QUIRK_HAS_BUFDESC_EX; fep->clk_ptp = devm_clk_get(&pdev->dev, "ptp"); - fep->bufdesc_ex = - pdev->id_entry->driver_data & FEC_QUIRK_HAS_BUFDESC_EX; if (IS_ERR(fep->clk_ptp)) { fep->clk_ptp = NULL; - fep->bufdesc_ex = 0; + fep->bufdesc_ex = false; } ret = fec_enet_clk_enable(ndev, true); diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index 4fdf0aa16978..86dccb26fecc 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -173,10 +173,12 @@ static void gfar_init_rxbdp(struct gfar_priv_rx_q *rx_queue, struct rxbd8 *bdp, static int gfar_init_bds(struct net_device *ndev) { struct gfar_private *priv = netdev_priv(ndev); + struct gfar __iomem *regs = priv->gfargrp[0].regs; struct gfar_priv_tx_q *tx_queue = NULL; struct gfar_priv_rx_q *rx_queue = NULL; struct txbd8 *txbdp; struct rxbd8 *rxbdp; + u32 *rfbptr; int i, j; for (i = 0; i < priv->num_tx_queues; i++) { @@ -201,6 +203,7 @@ static int gfar_init_bds(struct net_device *ndev) txbdp->status |= TXBD_WRAP; } + rfbptr = ®s->rfbptr0; for (i = 0; i < priv->num_rx_queues; i++) { rx_queue = priv->rx_queue[i]; rx_queue->cur_rx = rx_queue->rx_bd_base; @@ -227,6 +230,8 @@ static int gfar_init_bds(struct net_device *ndev) rxbdp++; } + rx_queue->rfbptr = rfbptr; + rfbptr += 2; } return 0; @@ -336,6 +341,20 @@ static void gfar_init_tx_rx_base(struct gfar_private *priv) } } +static void gfar_init_rqprm(struct gfar_private *priv) +{ + struct gfar __iomem *regs = priv->gfargrp[0].regs; + u32 __iomem *baddr; + int i; + + baddr = ®s->rqprm0; + for (i = 0; i < priv->num_rx_queues; i++) { + gfar_write(baddr, priv->rx_queue[i]->rx_ring_size | + (DEFAULT_RX_LFC_THR << FBTHR_SHIFT)); + baddr++; + } +} + static void gfar_rx_buff_size_config(struct gfar_private *priv) { int frame_size = priv->ndev->mtu + ETH_HLEN + ETH_FCS_LEN; @@ -396,6 +415,13 @@ static void gfar_mac_rx_config(struct gfar_private *priv) if (priv->ndev->features & NETIF_F_HW_VLAN_CTAG_RX) rctrl |= RCTRL_VLEX | RCTRL_PRSDEP_INIT; + /* Clear the LFC bit */ + gfar_write(®s->rctrl, rctrl); + /* Init flow control threshold values */ + gfar_init_rqprm(priv); + gfar_write(®s->ptv, DEFAULT_LFC_PTVVAL); + rctrl |= RCTRL_LFC; + /* Init rctrl based on our settings */ gfar_write(®s->rctrl, rctrl); } @@ -1687,6 +1713,9 @@ static int init_phy(struct net_device *dev) priv->phydev->supported &= (GFAR_SUPPORTED | gigabit_support); priv->phydev->advertising = priv->phydev->supported; + /* Add support for flow control, but don't advertise it by default */ + priv->phydev->supported |= (SUPPORTED_Pause | SUPPORTED_Asym_Pause); + return 0; } @@ -2856,6 +2885,10 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit) /* Setup the new bdp */ gfar_new_rxbdp(rx_queue, bdp, newskb); + /* Update Last Free RxBD pointer for LFC */ + if (unlikely(rx_queue->rfbptr && priv->tx_actual_en)) + gfar_write(rx_queue->rfbptr, (u32)bdp); + /* Update to the next pointer */ bdp = next_bd(bdp, base, rx_queue->rx_ring_size); @@ -3370,7 +3403,11 @@ static u32 gfar_get_flowctrl_cfg(struct gfar_private *priv) if (phydev->asym_pause) rmt_adv |= LPA_PAUSE_ASYM; - lcl_adv = mii_advertise_flowctrl(phydev->advertising); + lcl_adv = 0; + if (phydev->advertising & ADVERTISED_Pause) + lcl_adv |= ADVERTISE_PAUSE_CAP; + if (phydev->advertising & ADVERTISED_Asym_Pause) + lcl_adv |= ADVERTISE_PAUSE_ASYM; flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv); if (flowctrl & FLOW_CTRL_TX) @@ -3386,6 +3423,9 @@ static noinline void gfar_update_link_state(struct gfar_private *priv) { struct gfar __iomem *regs = priv->gfargrp[0].regs; struct phy_device *phydev = priv->phydev; + struct gfar_priv_rx_q *rx_queue = NULL; + int i; + struct rxbd8 *bdp; if (unlikely(test_bit(GFAR_RESETTING, &priv->state))) return; @@ -3394,6 +3434,7 @@ static noinline void gfar_update_link_state(struct gfar_private *priv) u32 tempval1 = gfar_read(®s->maccfg1); u32 tempval = gfar_read(®s->maccfg2); u32 ecntrl = gfar_read(®s->ecntrl); + u32 tx_flow_oldval = (tempval & MACCFG1_TX_FLOW); if (phydev->duplex != priv->oldduplex) { if (!(phydev->duplex)) @@ -3438,6 +3479,26 @@ static noinline void gfar_update_link_state(struct gfar_private *priv) tempval1 &= ~(MACCFG1_TX_FLOW | MACCFG1_RX_FLOW); tempval1 |= gfar_get_flowctrl_cfg(priv); + /* Turn last free buffer recording on */ + if ((tempval1 & MACCFG1_TX_FLOW) && !tx_flow_oldval) { + for (i = 0; i < priv->num_rx_queues; i++) { + rx_queue = priv->rx_queue[i]; + bdp = rx_queue->cur_rx; + /* skip to previous bd */ + bdp = skip_bd(bdp, rx_queue->rx_ring_size - 1, + rx_queue->rx_bd_base, + rx_queue->rx_ring_size); + + if (rx_queue->rfbptr) + gfar_write(rx_queue->rfbptr, (u32)bdp); + } + + priv->tx_actual_en = 1; + } + + if (unlikely(!(tempval1 & MACCFG1_TX_FLOW) && tx_flow_oldval)) + priv->tx_actual_en = 0; + gfar_write(®s->maccfg1, tempval1); gfar_write(®s->maccfg2, tempval); gfar_write(®s->ecntrl, ecntrl); diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h index 2805cfbf1765..b581b8823a2a 100644 --- a/drivers/net/ethernet/freescale/gianfar.h +++ b/drivers/net/ethernet/freescale/gianfar.h @@ -99,6 +99,10 @@ extern const char gfar_driver_version[]; #define GFAR_MAX_FIFO_STARVE 511 #define GFAR_MAX_FIFO_STARVE_OFF 511 +#define FBTHR_SHIFT 24 +#define DEFAULT_RX_LFC_THR 16 +#define DEFAULT_LFC_PTVVAL 4 + #define DEFAULT_RX_BUFFER_SIZE 1536 #define TX_RING_MOD_MASK(size) (size-1) #define RX_RING_MOD_MASK(size) (size-1) @@ -145,9 +149,7 @@ extern const char gfar_driver_version[]; | SUPPORTED_Autoneg \ | SUPPORTED_MII) -#define GFAR_SUPPORTED_GBIT (SUPPORTED_1000baseT_Full \ - | SUPPORTED_Pause \ - | SUPPORTED_Asym_Pause) +#define GFAR_SUPPORTED_GBIT SUPPORTED_1000baseT_Full /* TBI register addresses */ #define MII_TBICON 0x11 @@ -275,6 +277,7 @@ extern const char gfar_driver_version[]; #define RCTRL_TS_ENABLE 0x01000000 #define RCTRL_PAL_MASK 0x001f0000 +#define RCTRL_LFC 0x00004000 #define RCTRL_VLEX 0x00002000 #define RCTRL_FILREN 0x00001000 #define RCTRL_GHTX 0x00000400 @@ -851,7 +854,32 @@ struct gfar { u8 res23c[248]; u32 attr; /* 0x.bf8 - Attributes Register */ u32 attreli; /* 0x.bfc - Attributes Extract Length and Extract Index Register */ - u8 res24[688]; + u32 rqprm0; /* 0x.c00 - Receive queue parameters register 0 */ + u32 rqprm1; /* 0x.c04 - Receive queue parameters register 1 */ + u32 rqprm2; /* 0x.c08 - Receive queue parameters register 2 */ + u32 rqprm3; /* 0x.c0c - Receive queue parameters register 3 */ + u32 rqprm4; /* 0x.c10 - Receive queue parameters register 4 */ + u32 rqprm5; /* 0x.c14 - Receive queue parameters register 5 */ + u32 rqprm6; /* 0x.c18 - Receive queue parameters register 6 */ + u32 rqprm7; /* 0x.c1c - Receive queue parameters register 7 */ + u8 res24[36]; + u32 rfbptr0; /* 0x.c44 - Last free RxBD pointer for ring 0 */ + u8 res24a[4]; + u32 rfbptr1; /* 0x.c4c - Last free RxBD pointer for ring 1 */ + u8 res24b[4]; + u32 rfbptr2; /* 0x.c54 - Last free RxBD pointer for ring 2 */ + u8 res24c[4]; + u32 rfbptr3; /* 0x.c5c - Last free RxBD pointer for ring 3 */ + u8 res24d[4]; + u32 rfbptr4; /* 0x.c64 - Last free RxBD pointer for ring 4 */ + u8 res24e[4]; + u32 rfbptr5; /* 0x.c6c - Last free RxBD pointer for ring 5 */ + u8 res24f[4]; + u32 rfbptr6; /* 0x.c74 - Last free RxBD pointer for ring 6 */ + u8 res24g[4]; + u32 rfbptr7; /* 0x.c7c - Last free RxBD pointer for ring 7 */ + u8 res24h[4]; + u8 res24x[556]; u32 isrg0; /* 0x.eb0 - Interrupt steering group 0 register */ u32 isrg1; /* 0x.eb4 - Interrupt steering group 1 register */ u32 isrg2; /* 0x.eb8 - Interrupt steering group 2 register */ @@ -1011,6 +1039,7 @@ struct gfar_priv_rx_q { /* RX Coalescing values */ unsigned char rxcoalescing; unsigned long rxic; + u32 *rfbptr; }; enum gfar_irqinfo_id { @@ -1101,6 +1130,7 @@ struct gfar_private { unsigned int num_tx_queues; unsigned int num_rx_queues; unsigned int num_grps; + int tx_actual_en; /* Network Statistics */ struct gfar_extra_stats extra_stats; diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c index 76d70708f864..3e1a9c1a67a9 100644 --- a/drivers/net/ethernet/freescale/gianfar_ethtool.c +++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c @@ -579,8 +579,13 @@ static int gfar_spauseparam(struct net_device *dev, u32 tempval; tempval = gfar_read(®s->maccfg1); tempval &= ~(MACCFG1_TX_FLOW | MACCFG1_RX_FLOW); - if (priv->tx_pause_en) + + priv->tx_actual_en = 0; + if (priv->tx_pause_en) { + priv->tx_actual_en = 1; tempval |= MACCFG1_TX_FLOW; + } + if (priv->rx_pause_en) tempval |= MACCFG1_RX_FLOW; gfar_write(®s->maccfg1, tempval); diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c index 87bd953cc2ee..3f3fba9e4650 100644 --- a/drivers/net/ethernet/ibm/emac/core.c +++ b/drivers/net/ethernet/ibm/emac/core.c @@ -2323,16 +2323,11 @@ static int emac_check_deps(struct emac_instance *dev, static void emac_put_deps(struct emac_instance *dev) { - if (dev->mal_dev) - of_dev_put(dev->mal_dev); - if (dev->zmii_dev) - of_dev_put(dev->zmii_dev); - if (dev->rgmii_dev) - of_dev_put(dev->rgmii_dev); - if (dev->mdio_dev) - of_dev_put(dev->mdio_dev); - if (dev->tah_dev) - of_dev_put(dev->tah_dev); + of_dev_put(dev->mal_dev); + of_dev_put(dev->zmii_dev); + of_dev_put(dev->rgmii_dev); + of_dev_put(dev->mdio_dev); + of_dev_put(dev->tah_dev); } static int emac_of_bus_notify(struct notifier_block *nb, unsigned long action, @@ -2371,8 +2366,7 @@ static int emac_wait_deps(struct emac_instance *dev) bus_unregister_notifier(&platform_bus_type, &emac_of_bus_notifier); err = emac_check_deps(dev, deps) ? 0 : -ENODEV; for (i = 0; i < EMAC_DEP_COUNT; i++) { - if (deps[i].node) - of_node_put(deps[i].node); + of_node_put(deps[i].node); if (err && deps[i].ofdev) of_dev_put(deps[i].ofdev); } @@ -2383,8 +2377,7 @@ static int emac_wait_deps(struct emac_instance *dev) dev->tah_dev = deps[EMAC_DEP_TAH_IDX].ofdev; dev->mdio_dev = deps[EMAC_DEP_MDIO_IDX].ofdev; } - if (deps[EMAC_DEP_PREV_IDX].ofdev) - of_dev_put(deps[EMAC_DEP_PREV_IDX].ofdev); + of_dev_put(deps[EMAC_DEP_PREV_IDX].ofdev); return err; } @@ -3113,8 +3106,7 @@ static void __exit emac_exit(void) /* Destroy EMAC boot list */ for (i = 0; i < EMAC_BOOT_LIST_SIZE; i++) - if (emac_boot_list[i]) - of_node_put(emac_boot_list[i]); + of_node_put(emac_boot_list[i]); } module_init(emac_init); diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index 247335d2c7ec..370cfa275ddb 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -3449,15 +3449,12 @@ static void e1000e_setup_rss_hash(struct e1000_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; u32 mrqc, rxcsum; + u32 rss_key[10]; int i; - static const u32 rsskey[10] = { - 0xda565a6d, 0xc20e5b25, 0x3d256741, 0xb08fa343, 0xcb2bcad0, - 0xb4307bae, 0xa32dcb77, 0x0cf23080, 0x3bb7426a, 0xfa01acbe - }; - /* Fill out hash function seed */ + netdev_rss_key_fill(rss_key, sizeof(rss_key)); for (i = 0; i < 10; i++) - ew32(RSSRK(i), rsskey[i]); + ew32(RSSRK(i), rss_key[i]); /* Direct all traffic to queue 0 */ for (i = 0; i < 32; i++) diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_main.c b/drivers/net/ethernet/intel/fm10k/fm10k_main.c index e645af412e76..73457ede53ec 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_main.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_main.c @@ -83,7 +83,7 @@ static bool fm10k_alloc_mapped_page(struct fm10k_ring *rx_ring, return true; /* alloc new page for storage */ - page = alloc_page(GFP_ATOMIC | __GFP_COLD); + page = dev_alloc_page(); if (unlikely(!page)) { rx_ring->rx_stats.alloc_failed++; return false; diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c index a0cb74ab3dc6..4f5892cc32d7 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c @@ -1551,15 +1551,11 @@ void fm10k_down(struct fm10k_intfc *interface) static int fm10k_sw_init(struct fm10k_intfc *interface, const struct pci_device_id *ent) { - static const u32 seed[FM10K_RSSRK_SIZE] = { 0xda565a6d, 0xc20e5b25, - 0x3d256741, 0xb08fa343, - 0xcb2bcad0, 0xb4307bae, - 0xa32dcb77, 0x0cf23080, - 0x3bb7426a, 0xfa01acbe }; const struct fm10k_info *fi = fm10k_info_tbl[ent->driver_data]; struct fm10k_hw *hw = &interface->hw; struct pci_dev *pdev = interface->pdev; struct net_device *netdev = interface->netdev; + u32 rss_key[FM10K_RSSRK_SIZE]; unsigned int rss; int err; @@ -1673,8 +1669,8 @@ static int fm10k_sw_init(struct fm10k_intfc *interface, /* initialize vxlan_port list */ INIT_LIST_HEAD(&interface->vxlan_port); - /* initialize RSS key */ - memcpy(interface->rssrk, seed, sizeof(seed)); + netdev_rss_key_fill(rss_key, sizeof(rss_key)); + memcpy(interface->rssrk, rss_key, sizeof(rss_key)); /* Start off interface as being down */ set_bit(__FM10K_DOWN, &interface->state); diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index f1e33f896439..464342a35214 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -146,6 +146,7 @@ enum i40e_state_t { __I40E_DOWN_REQUESTED, __I40E_FD_FLUSH_REQUESTED, __I40E_RESET_FAILED, + __I40E_PORT_TX_SUSPENDED, }; enum i40e_interrupt_policy { @@ -269,7 +270,8 @@ struct i40e_pf { u16 msg_enable; char misc_int_name[IFNAMSIZ + 9]; u16 adminq_work_limit; /* num of admin receive queue desc to process */ - int service_timer_period; + unsigned long service_timer_period; + unsigned long service_timer_previous; struct timer_list service_timer; struct work_struct service_task; diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.c b/drivers/net/ethernet/intel/i40e/i40e_adminq.c index 72f5d25a222f..5bb4914bda56 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq.c +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.c @@ -853,7 +853,6 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw, */ if (!details->async && !details->postpone) { u32 total_delay = 0; - u32 delay_len = 10; do { /* AQ designers suggest use of head for better @@ -861,9 +860,8 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw, */ if (i40e_asq_done(hw)) break; - /* ugh! delay while spin_lock */ - udelay(delay_len); - total_delay += delay_len; + usleep_range(1000, 2000); + total_delay++; } while (total_delay < hw->aq.asq_cmd_timeout); } @@ -982,10 +980,10 @@ i40e_status i40e_clean_arq_element(struct i40e_hw *hw, e->desc = *desc; datalen = le16_to_cpu(desc->datalen); - e->msg_size = min(datalen, e->msg_size); - if (e->msg_buf != NULL && (e->msg_size != 0)) + e->msg_len = min(datalen, e->buf_len); + if (e->msg_buf != NULL && (e->msg_len != 0)) memcpy(e->msg_buf, hw->aq.arq.r.arq_bi[desc_idx].va, - e->msg_size); + e->msg_len); i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQRX: desc and buffer:\n"); i40e_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc, e->msg_buf, diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.h b/drivers/net/ethernet/intel/i40e/i40e_adminq.h index ba38a89c79d6..003a227b8515 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq.h +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.h @@ -76,7 +76,8 @@ struct i40e_asq_cmd_details { /* ARQ event information */ struct i40e_arq_event_info { struct i40e_aq_desc desc; - u16 msg_size; + u16 msg_len; + u16 buf_len; u8 *msg_buf; }; @@ -141,7 +142,7 @@ static inline int i40e_aq_rc_to_posix(u16 aq_rc) /* general information */ #define I40E_AQ_LARGE_BUF 512 -#define I40E_ASQ_CMD_TIMEOUT 100000 /* usecs */ +#define I40E_ASQ_CMD_TIMEOUT 100 /* msecs */ void i40e_fill_default_direct_cmd_desc(struct i40e_aq_desc *desc, u16 opcode); diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h index 15f289f2917f..8835aeeff23e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h @@ -33,8 +33,8 @@ * This file needs to comply with the Linux Kernel coding style. */ -#define I40E_FW_API_VERSION_MAJOR 0x0001 -#define I40E_FW_API_VERSION_MINOR 0x0002 +#define I40E_FW_API_VERSION_MAJOR 0x0001 +#define I40E_FW_API_VERSION_MINOR 0x0002 struct i40e_aq_desc { __le16 flags; @@ -66,216 +66,217 @@ struct i40e_aq_desc { */ /* command flags and offsets*/ -#define I40E_AQ_FLAG_DD_SHIFT 0 -#define I40E_AQ_FLAG_CMP_SHIFT 1 -#define I40E_AQ_FLAG_ERR_SHIFT 2 -#define I40E_AQ_FLAG_VFE_SHIFT 3 -#define I40E_AQ_FLAG_LB_SHIFT 9 -#define I40E_AQ_FLAG_RD_SHIFT 10 -#define I40E_AQ_FLAG_VFC_SHIFT 11 -#define I40E_AQ_FLAG_BUF_SHIFT 12 -#define I40E_AQ_FLAG_SI_SHIFT 13 -#define I40E_AQ_FLAG_EI_SHIFT 14 -#define I40E_AQ_FLAG_FE_SHIFT 15 - -#define I40E_AQ_FLAG_DD (1 << I40E_AQ_FLAG_DD_SHIFT) /* 0x1 */ -#define I40E_AQ_FLAG_CMP (1 << I40E_AQ_FLAG_CMP_SHIFT) /* 0x2 */ -#define I40E_AQ_FLAG_ERR (1 << I40E_AQ_FLAG_ERR_SHIFT) /* 0x4 */ -#define I40E_AQ_FLAG_VFE (1 << I40E_AQ_FLAG_VFE_SHIFT) /* 0x8 */ -#define I40E_AQ_FLAG_LB (1 << I40E_AQ_FLAG_LB_SHIFT) /* 0x200 */ -#define I40E_AQ_FLAG_RD (1 << I40E_AQ_FLAG_RD_SHIFT) /* 0x400 */ -#define I40E_AQ_FLAG_VFC (1 << I40E_AQ_FLAG_VFC_SHIFT) /* 0x800 */ -#define I40E_AQ_FLAG_BUF (1 << I40E_AQ_FLAG_BUF_SHIFT) /* 0x1000 */ -#define I40E_AQ_FLAG_SI (1 << I40E_AQ_FLAG_SI_SHIFT) /* 0x2000 */ -#define I40E_AQ_FLAG_EI (1 << I40E_AQ_FLAG_EI_SHIFT) /* 0x4000 */ -#define I40E_AQ_FLAG_FE (1 << I40E_AQ_FLAG_FE_SHIFT) /* 0x8000 */ +#define I40E_AQ_FLAG_DD_SHIFT 0 +#define I40E_AQ_FLAG_CMP_SHIFT 1 +#define I40E_AQ_FLAG_ERR_SHIFT 2 +#define I40E_AQ_FLAG_VFE_SHIFT 3 +#define I40E_AQ_FLAG_LB_SHIFT 9 +#define I40E_AQ_FLAG_RD_SHIFT 10 +#define I40E_AQ_FLAG_VFC_SHIFT 11 +#define I40E_AQ_FLAG_BUF_SHIFT 12 +#define I40E_AQ_FLAG_SI_SHIFT 13 +#define I40E_AQ_FLAG_EI_SHIFT 14 +#define I40E_AQ_FLAG_FE_SHIFT 15 + +#define I40E_AQ_FLAG_DD (1 << I40E_AQ_FLAG_DD_SHIFT) /* 0x1 */ +#define I40E_AQ_FLAG_CMP (1 << I40E_AQ_FLAG_CMP_SHIFT) /* 0x2 */ +#define I40E_AQ_FLAG_ERR (1 << I40E_AQ_FLAG_ERR_SHIFT) /* 0x4 */ +#define I40E_AQ_FLAG_VFE (1 << I40E_AQ_FLAG_VFE_SHIFT) /* 0x8 */ +#define I40E_AQ_FLAG_LB (1 << I40E_AQ_FLAG_LB_SHIFT) /* 0x200 */ +#define I40E_AQ_FLAG_RD (1 << I40E_AQ_FLAG_RD_SHIFT) /* 0x400 */ +#define I40E_AQ_FLAG_VFC (1 << I40E_AQ_FLAG_VFC_SHIFT) /* 0x800 */ +#define I40E_AQ_FLAG_BUF (1 << I40E_AQ_FLAG_BUF_SHIFT) /* 0x1000 */ +#define I40E_AQ_FLAG_SI (1 << I40E_AQ_FLAG_SI_SHIFT) /* 0x2000 */ +#define I40E_AQ_FLAG_EI (1 << I40E_AQ_FLAG_EI_SHIFT) /* 0x4000 */ +#define I40E_AQ_FLAG_FE (1 << I40E_AQ_FLAG_FE_SHIFT) /* 0x8000 */ /* error codes */ enum i40e_admin_queue_err { - I40E_AQ_RC_OK = 0, /* success */ - I40E_AQ_RC_EPERM = 1, /* Operation not permitted */ - I40E_AQ_RC_ENOENT = 2, /* No such element */ - I40E_AQ_RC_ESRCH = 3, /* Bad opcode */ - I40E_AQ_RC_EINTR = 4, /* operation interrupted */ - I40E_AQ_RC_EIO = 5, /* I/O error */ - I40E_AQ_RC_ENXIO = 6, /* No such resource */ - I40E_AQ_RC_E2BIG = 7, /* Arg too long */ - I40E_AQ_RC_EAGAIN = 8, /* Try again */ - I40E_AQ_RC_ENOMEM = 9, /* Out of memory */ - I40E_AQ_RC_EACCES = 10, /* Permission denied */ - I40E_AQ_RC_EFAULT = 11, /* Bad address */ - I40E_AQ_RC_EBUSY = 12, /* Device or resource busy */ - I40E_AQ_RC_EEXIST = 13, /* object already exists */ - I40E_AQ_RC_EINVAL = 14, /* Invalid argument */ - I40E_AQ_RC_ENOTTY = 15, /* Not a typewriter */ - I40E_AQ_RC_ENOSPC = 16, /* No space left or alloc failure */ - I40E_AQ_RC_ENOSYS = 17, /* Function not implemented */ - I40E_AQ_RC_ERANGE = 18, /* Parameter out of range */ - I40E_AQ_RC_EFLUSHED = 19, /* Cmd flushed because of prev cmd error */ - I40E_AQ_RC_BAD_ADDR = 20, /* Descriptor contains a bad pointer */ - I40E_AQ_RC_EMODE = 21, /* Op not allowed in current dev mode */ - I40E_AQ_RC_EFBIG = 22, /* File too large */ + I40E_AQ_RC_OK = 0, /* success */ + I40E_AQ_RC_EPERM = 1, /* Operation not permitted */ + I40E_AQ_RC_ENOENT = 2, /* No such element */ + I40E_AQ_RC_ESRCH = 3, /* Bad opcode */ + I40E_AQ_RC_EINTR = 4, /* operation interrupted */ + I40E_AQ_RC_EIO = 5, /* I/O error */ + I40E_AQ_RC_ENXIO = 6, /* No such resource */ + I40E_AQ_RC_E2BIG = 7, /* Arg too long */ + I40E_AQ_RC_EAGAIN = 8, /* Try again */ + I40E_AQ_RC_ENOMEM = 9, /* Out of memory */ + I40E_AQ_RC_EACCES = 10, /* Permission denied */ + I40E_AQ_RC_EFAULT = 11, /* Bad address */ + I40E_AQ_RC_EBUSY = 12, /* Device or resource busy */ + I40E_AQ_RC_EEXIST = 13, /* object already exists */ + I40E_AQ_RC_EINVAL = 14, /* Invalid argument */ + I40E_AQ_RC_ENOTTY = 15, /* Not a typewriter */ + I40E_AQ_RC_ENOSPC = 16, /* No space left or alloc failure */ + I40E_AQ_RC_ENOSYS = 17, /* Function not implemented */ + I40E_AQ_RC_ERANGE = 18, /* Parameter out of range */ + I40E_AQ_RC_EFLUSHED = 19, /* Cmd flushed due to prev cmd error */ + I40E_AQ_RC_BAD_ADDR = 20, /* Descriptor contains a bad pointer */ + I40E_AQ_RC_EMODE = 21, /* Op not allowed in current dev mode */ + I40E_AQ_RC_EFBIG = 22, /* File too large */ }; /* Admin Queue command opcodes */ enum i40e_admin_queue_opc { /* aq commands */ - i40e_aqc_opc_get_version = 0x0001, - i40e_aqc_opc_driver_version = 0x0002, - i40e_aqc_opc_queue_shutdown = 0x0003, - i40e_aqc_opc_set_pf_context = 0x0004, + i40e_aqc_opc_get_version = 0x0001, + i40e_aqc_opc_driver_version = 0x0002, + i40e_aqc_opc_queue_shutdown = 0x0003, + i40e_aqc_opc_set_pf_context = 0x0004, /* resource ownership */ - i40e_aqc_opc_request_resource = 0x0008, - i40e_aqc_opc_release_resource = 0x0009, + i40e_aqc_opc_request_resource = 0x0008, + i40e_aqc_opc_release_resource = 0x0009, - i40e_aqc_opc_list_func_capabilities = 0x000A, - i40e_aqc_opc_list_dev_capabilities = 0x000B, + i40e_aqc_opc_list_func_capabilities = 0x000A, + i40e_aqc_opc_list_dev_capabilities = 0x000B, - i40e_aqc_opc_set_cppm_configuration = 0x0103, - i40e_aqc_opc_set_arp_proxy_entry = 0x0104, - i40e_aqc_opc_set_ns_proxy_entry = 0x0105, + i40e_aqc_opc_set_cppm_configuration = 0x0103, + i40e_aqc_opc_set_arp_proxy_entry = 0x0104, + i40e_aqc_opc_set_ns_proxy_entry = 0x0105, /* LAA */ - i40e_aqc_opc_mng_laa = 0x0106, /* AQ obsolete */ - i40e_aqc_opc_mac_address_read = 0x0107, - i40e_aqc_opc_mac_address_write = 0x0108, + i40e_aqc_opc_mng_laa = 0x0106, /* AQ obsolete */ + i40e_aqc_opc_mac_address_read = 0x0107, + i40e_aqc_opc_mac_address_write = 0x0108, /* PXE */ - i40e_aqc_opc_clear_pxe_mode = 0x0110, + i40e_aqc_opc_clear_pxe_mode = 0x0110, /* internal switch commands */ - i40e_aqc_opc_get_switch_config = 0x0200, - i40e_aqc_opc_add_statistics = 0x0201, - i40e_aqc_opc_remove_statistics = 0x0202, - i40e_aqc_opc_set_port_parameters = 0x0203, - i40e_aqc_opc_get_switch_resource_alloc = 0x0204, - - i40e_aqc_opc_add_vsi = 0x0210, - i40e_aqc_opc_update_vsi_parameters = 0x0211, - i40e_aqc_opc_get_vsi_parameters = 0x0212, - - i40e_aqc_opc_add_pv = 0x0220, - i40e_aqc_opc_update_pv_parameters = 0x0221, - i40e_aqc_opc_get_pv_parameters = 0x0222, - - i40e_aqc_opc_add_veb = 0x0230, - i40e_aqc_opc_update_veb_parameters = 0x0231, - i40e_aqc_opc_get_veb_parameters = 0x0232, - - i40e_aqc_opc_delete_element = 0x0243, - - i40e_aqc_opc_add_macvlan = 0x0250, - i40e_aqc_opc_remove_macvlan = 0x0251, - i40e_aqc_opc_add_vlan = 0x0252, - i40e_aqc_opc_remove_vlan = 0x0253, - i40e_aqc_opc_set_vsi_promiscuous_modes = 0x0254, - i40e_aqc_opc_add_tag = 0x0255, - i40e_aqc_opc_remove_tag = 0x0256, - i40e_aqc_opc_add_multicast_etag = 0x0257, - i40e_aqc_opc_remove_multicast_etag = 0x0258, - i40e_aqc_opc_update_tag = 0x0259, - i40e_aqc_opc_add_control_packet_filter = 0x025A, - i40e_aqc_opc_remove_control_packet_filter = 0x025B, - i40e_aqc_opc_add_cloud_filters = 0x025C, - i40e_aqc_opc_remove_cloud_filters = 0x025D, - - i40e_aqc_opc_add_mirror_rule = 0x0260, - i40e_aqc_opc_delete_mirror_rule = 0x0261, + i40e_aqc_opc_get_switch_config = 0x0200, + i40e_aqc_opc_add_statistics = 0x0201, + i40e_aqc_opc_remove_statistics = 0x0202, + i40e_aqc_opc_set_port_parameters = 0x0203, + i40e_aqc_opc_get_switch_resource_alloc = 0x0204, + + i40e_aqc_opc_add_vsi = 0x0210, + i40e_aqc_opc_update_vsi_parameters = 0x0211, + i40e_aqc_opc_get_vsi_parameters = 0x0212, + + i40e_aqc_opc_add_pv = 0x0220, + i40e_aqc_opc_update_pv_parameters = 0x0221, + i40e_aqc_opc_get_pv_parameters = 0x0222, + + i40e_aqc_opc_add_veb = 0x0230, + i40e_aqc_opc_update_veb_parameters = 0x0231, + i40e_aqc_opc_get_veb_parameters = 0x0232, + + i40e_aqc_opc_delete_element = 0x0243, + + i40e_aqc_opc_add_macvlan = 0x0250, + i40e_aqc_opc_remove_macvlan = 0x0251, + i40e_aqc_opc_add_vlan = 0x0252, + i40e_aqc_opc_remove_vlan = 0x0253, + i40e_aqc_opc_set_vsi_promiscuous_modes = 0x0254, + i40e_aqc_opc_add_tag = 0x0255, + i40e_aqc_opc_remove_tag = 0x0256, + i40e_aqc_opc_add_multicast_etag = 0x0257, + i40e_aqc_opc_remove_multicast_etag = 0x0258, + i40e_aqc_opc_update_tag = 0x0259, + i40e_aqc_opc_add_control_packet_filter = 0x025A, + i40e_aqc_opc_remove_control_packet_filter = 0x025B, + i40e_aqc_opc_add_cloud_filters = 0x025C, + i40e_aqc_opc_remove_cloud_filters = 0x025D, + + i40e_aqc_opc_add_mirror_rule = 0x0260, + i40e_aqc_opc_delete_mirror_rule = 0x0261, /* DCB commands */ - i40e_aqc_opc_dcb_ignore_pfc = 0x0301, - i40e_aqc_opc_dcb_updated = 0x0302, + i40e_aqc_opc_dcb_ignore_pfc = 0x0301, + i40e_aqc_opc_dcb_updated = 0x0302, /* TX scheduler */ - i40e_aqc_opc_configure_vsi_bw_limit = 0x0400, - i40e_aqc_opc_configure_vsi_ets_sla_bw_limit = 0x0406, - i40e_aqc_opc_configure_vsi_tc_bw = 0x0407, - i40e_aqc_opc_query_vsi_bw_config = 0x0408, - i40e_aqc_opc_query_vsi_ets_sla_config = 0x040A, - i40e_aqc_opc_configure_switching_comp_bw_limit = 0x0410, - - i40e_aqc_opc_enable_switching_comp_ets = 0x0413, - i40e_aqc_opc_modify_switching_comp_ets = 0x0414, - i40e_aqc_opc_disable_switching_comp_ets = 0x0415, - i40e_aqc_opc_configure_switching_comp_ets_bw_limit = 0x0416, - i40e_aqc_opc_configure_switching_comp_bw_config = 0x0417, - i40e_aqc_opc_query_switching_comp_ets_config = 0x0418, - i40e_aqc_opc_query_port_ets_config = 0x0419, - i40e_aqc_opc_query_switching_comp_bw_config = 0x041A, - i40e_aqc_opc_suspend_port_tx = 0x041B, - i40e_aqc_opc_resume_port_tx = 0x041C, - i40e_aqc_opc_configure_partition_bw = 0x041D, + i40e_aqc_opc_configure_vsi_bw_limit = 0x0400, + i40e_aqc_opc_configure_vsi_ets_sla_bw_limit = 0x0406, + i40e_aqc_opc_configure_vsi_tc_bw = 0x0407, + i40e_aqc_opc_query_vsi_bw_config = 0x0408, + i40e_aqc_opc_query_vsi_ets_sla_config = 0x040A, + i40e_aqc_opc_configure_switching_comp_bw_limit = 0x0410, + + i40e_aqc_opc_enable_switching_comp_ets = 0x0413, + i40e_aqc_opc_modify_switching_comp_ets = 0x0414, + i40e_aqc_opc_disable_switching_comp_ets = 0x0415, + i40e_aqc_opc_configure_switching_comp_ets_bw_limit = 0x0416, + i40e_aqc_opc_configure_switching_comp_bw_config = 0x0417, + i40e_aqc_opc_query_switching_comp_ets_config = 0x0418, + i40e_aqc_opc_query_port_ets_config = 0x0419, + i40e_aqc_opc_query_switching_comp_bw_config = 0x041A, + i40e_aqc_opc_suspend_port_tx = 0x041B, + i40e_aqc_opc_resume_port_tx = 0x041C, + i40e_aqc_opc_configure_partition_bw = 0x041D, /* hmc */ - i40e_aqc_opc_query_hmc_resource_profile = 0x0500, - i40e_aqc_opc_set_hmc_resource_profile = 0x0501, + i40e_aqc_opc_query_hmc_resource_profile = 0x0500, + i40e_aqc_opc_set_hmc_resource_profile = 0x0501, /* phy commands*/ - i40e_aqc_opc_get_phy_abilities = 0x0600, - i40e_aqc_opc_set_phy_config = 0x0601, - i40e_aqc_opc_set_mac_config = 0x0603, - i40e_aqc_opc_set_link_restart_an = 0x0605, - i40e_aqc_opc_get_link_status = 0x0607, - i40e_aqc_opc_set_phy_int_mask = 0x0613, - i40e_aqc_opc_get_local_advt_reg = 0x0614, - i40e_aqc_opc_set_local_advt_reg = 0x0615, - i40e_aqc_opc_get_partner_advt = 0x0616, - i40e_aqc_opc_set_lb_modes = 0x0618, - i40e_aqc_opc_get_phy_wol_caps = 0x0621, - i40e_aqc_opc_set_phy_debug = 0x0622, - i40e_aqc_opc_upload_ext_phy_fm = 0x0625, + i40e_aqc_opc_get_phy_abilities = 0x0600, + i40e_aqc_opc_set_phy_config = 0x0601, + i40e_aqc_opc_set_mac_config = 0x0603, + i40e_aqc_opc_set_link_restart_an = 0x0605, + i40e_aqc_opc_get_link_status = 0x0607, + i40e_aqc_opc_set_phy_int_mask = 0x0613, + i40e_aqc_opc_get_local_advt_reg = 0x0614, + i40e_aqc_opc_set_local_advt_reg = 0x0615, + i40e_aqc_opc_get_partner_advt = 0x0616, + i40e_aqc_opc_set_lb_modes = 0x0618, + i40e_aqc_opc_get_phy_wol_caps = 0x0621, + i40e_aqc_opc_set_phy_debug = 0x0622, + i40e_aqc_opc_upload_ext_phy_fm = 0x0625, /* NVM commands */ - i40e_aqc_opc_nvm_read = 0x0701, - i40e_aqc_opc_nvm_erase = 0x0702, - i40e_aqc_opc_nvm_update = 0x0703, - i40e_aqc_opc_nvm_config_read = 0x0704, - i40e_aqc_opc_nvm_config_write = 0x0705, + i40e_aqc_opc_nvm_read = 0x0701, + i40e_aqc_opc_nvm_erase = 0x0702, + i40e_aqc_opc_nvm_update = 0x0703, + i40e_aqc_opc_nvm_config_read = 0x0704, + i40e_aqc_opc_nvm_config_write = 0x0705, /* virtualization commands */ - i40e_aqc_opc_send_msg_to_pf = 0x0801, - i40e_aqc_opc_send_msg_to_vf = 0x0802, - i40e_aqc_opc_send_msg_to_peer = 0x0803, + i40e_aqc_opc_send_msg_to_pf = 0x0801, + i40e_aqc_opc_send_msg_to_vf = 0x0802, + i40e_aqc_opc_send_msg_to_peer = 0x0803, /* alternate structure */ - i40e_aqc_opc_alternate_write = 0x0900, - i40e_aqc_opc_alternate_write_indirect = 0x0901, - i40e_aqc_opc_alternate_read = 0x0902, - i40e_aqc_opc_alternate_read_indirect = 0x0903, - i40e_aqc_opc_alternate_write_done = 0x0904, - i40e_aqc_opc_alternate_set_mode = 0x0905, - i40e_aqc_opc_alternate_clear_port = 0x0906, + i40e_aqc_opc_alternate_write = 0x0900, + i40e_aqc_opc_alternate_write_indirect = 0x0901, + i40e_aqc_opc_alternate_read = 0x0902, + i40e_aqc_opc_alternate_read_indirect = 0x0903, + i40e_aqc_opc_alternate_write_done = 0x0904, + i40e_aqc_opc_alternate_set_mode = 0x0905, + i40e_aqc_opc_alternate_clear_port = 0x0906, /* LLDP commands */ - i40e_aqc_opc_lldp_get_mib = 0x0A00, - i40e_aqc_opc_lldp_update_mib = 0x0A01, - i40e_aqc_opc_lldp_add_tlv = 0x0A02, - i40e_aqc_opc_lldp_update_tlv = 0x0A03, - i40e_aqc_opc_lldp_delete_tlv = 0x0A04, - i40e_aqc_opc_lldp_stop = 0x0A05, - i40e_aqc_opc_lldp_start = 0x0A06, + i40e_aqc_opc_lldp_get_mib = 0x0A00, + i40e_aqc_opc_lldp_update_mib = 0x0A01, + i40e_aqc_opc_lldp_add_tlv = 0x0A02, + i40e_aqc_opc_lldp_update_tlv = 0x0A03, + i40e_aqc_opc_lldp_delete_tlv = 0x0A04, + i40e_aqc_opc_lldp_stop = 0x0A05, + i40e_aqc_opc_lldp_start = 0x0A06, + i40e_aqc_opc_get_cee_dcb_cfg = 0x0A07, /* Tunnel commands */ - i40e_aqc_opc_add_udp_tunnel = 0x0B00, - i40e_aqc_opc_del_udp_tunnel = 0x0B01, - i40e_aqc_opc_tunnel_key_structure = 0x0B10, + i40e_aqc_opc_add_udp_tunnel = 0x0B00, + i40e_aqc_opc_del_udp_tunnel = 0x0B01, + i40e_aqc_opc_tunnel_key_structure = 0x0B10, /* Async Events */ - i40e_aqc_opc_event_lan_overflow = 0x1001, + i40e_aqc_opc_event_lan_overflow = 0x1001, /* OEM commands */ - i40e_aqc_opc_oem_parameter_change = 0xFE00, - i40e_aqc_opc_oem_device_status_change = 0xFE01, + i40e_aqc_opc_oem_parameter_change = 0xFE00, + i40e_aqc_opc_oem_device_status_change = 0xFE01, /* debug commands */ - i40e_aqc_opc_debug_get_deviceid = 0xFF00, - i40e_aqc_opc_debug_set_mode = 0xFF01, - i40e_aqc_opc_debug_read_reg = 0xFF03, - i40e_aqc_opc_debug_write_reg = 0xFF04, - i40e_aqc_opc_debug_modify_reg = 0xFF07, - i40e_aqc_opc_debug_dump_internals = 0xFF08, - i40e_aqc_opc_debug_modify_internals = 0xFF09, + i40e_aqc_opc_debug_get_deviceid = 0xFF00, + i40e_aqc_opc_debug_set_mode = 0xFF01, + i40e_aqc_opc_debug_read_reg = 0xFF03, + i40e_aqc_opc_debug_write_reg = 0xFF04, + i40e_aqc_opc_debug_modify_reg = 0xFF07, + i40e_aqc_opc_debug_dump_internals = 0xFF08, + i40e_aqc_opc_debug_modify_internals = 0xFF09, }; /* command structures and indirect data structures */ @@ -302,7 +303,7 @@ enum i40e_admin_queue_opc { /* This macro is used extensively to ensure that command structures are 16 * bytes in length as they have to map to the raw array of that size. */ -#define I40E_CHECK_CMD_LENGTH(X) I40E_CHECK_STRUCT_LEN(16, X) +#define I40E_CHECK_CMD_LENGTH(X) I40E_CHECK_STRUCT_LEN(16, X) /* internal (0x00XX) commands */ @@ -320,22 +321,22 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_get_version); /* Send driver version (indirect 0x0002) */ struct i40e_aqc_driver_version { - u8 driver_major_ver; - u8 driver_minor_ver; - u8 driver_build_ver; - u8 driver_subbuild_ver; - u8 reserved[4]; - __le32 address_high; - __le32 address_low; + u8 driver_major_ver; + u8 driver_minor_ver; + u8 driver_build_ver; + u8 driver_subbuild_ver; + u8 reserved[4]; + __le32 address_high; + __le32 address_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_driver_version); /* Queue Shutdown (direct 0x0003) */ struct i40e_aqc_queue_shutdown { - __le32 driver_unloading; -#define I40E_AQ_DRIVER_UNLOADING 0x1 - u8 reserved[12]; + __le32 driver_unloading; +#define I40E_AQ_DRIVER_UNLOADING 0x1 + u8 reserved[12]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_queue_shutdown); @@ -351,19 +352,19 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_set_pf_context); /* Request resource ownership (direct 0x0008) * Release resource ownership (direct 0x0009) */ -#define I40E_AQ_RESOURCE_NVM 1 -#define I40E_AQ_RESOURCE_SDP 2 -#define I40E_AQ_RESOURCE_ACCESS_READ 1 -#define I40E_AQ_RESOURCE_ACCESS_WRITE 2 -#define I40E_AQ_RESOURCE_NVM_READ_TIMEOUT 3000 -#define I40E_AQ_RESOURCE_NVM_WRITE_TIMEOUT 180000 +#define I40E_AQ_RESOURCE_NVM 1 +#define I40E_AQ_RESOURCE_SDP 2 +#define I40E_AQ_RESOURCE_ACCESS_READ 1 +#define I40E_AQ_RESOURCE_ACCESS_WRITE 2 +#define I40E_AQ_RESOURCE_NVM_READ_TIMEOUT 3000 +#define I40E_AQ_RESOURCE_NVM_WRITE_TIMEOUT 180000 struct i40e_aqc_request_resource { - __le16 resource_id; - __le16 access_type; - __le32 timeout; - __le32 resource_number; - u8 reserved[4]; + __le16 resource_id; + __le16 access_type; + __le32 timeout; + __le32 resource_number; + u8 reserved[4]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_request_resource); @@ -373,7 +374,7 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_request_resource); */ struct i40e_aqc_list_capabilites { u8 command_flags; -#define I40E_AQ_LIST_CAP_PF_INDEX_EN 1 +#define I40E_AQ_LIST_CAP_PF_INDEX_EN 1 u8 pf_index; u8 reserved[2]; __le32 count; @@ -384,123 +385,123 @@ struct i40e_aqc_list_capabilites { I40E_CHECK_CMD_LENGTH(i40e_aqc_list_capabilites); struct i40e_aqc_list_capabilities_element_resp { - __le16 id; - u8 major_rev; - u8 minor_rev; - __le32 number; - __le32 logical_id; - __le32 phys_id; - u8 reserved[16]; + __le16 id; + u8 major_rev; + u8 minor_rev; + __le32 number; + __le32 logical_id; + __le32 phys_id; + u8 reserved[16]; }; /* list of caps */ -#define I40E_AQ_CAP_ID_SWITCH_MODE 0x0001 -#define I40E_AQ_CAP_ID_MNG_MODE 0x0002 -#define I40E_AQ_CAP_ID_NPAR_ACTIVE 0x0003 -#define I40E_AQ_CAP_ID_OS2BMC_CAP 0x0004 -#define I40E_AQ_CAP_ID_FUNCTIONS_VALID 0x0005 -#define I40E_AQ_CAP_ID_ALTERNATE_RAM 0x0006 -#define I40E_AQ_CAP_ID_SRIOV 0x0012 -#define I40E_AQ_CAP_ID_VF 0x0013 -#define I40E_AQ_CAP_ID_VMDQ 0x0014 -#define I40E_AQ_CAP_ID_8021QBG 0x0015 -#define I40E_AQ_CAP_ID_8021QBR 0x0016 -#define I40E_AQ_CAP_ID_VSI 0x0017 -#define I40E_AQ_CAP_ID_DCB 0x0018 -#define I40E_AQ_CAP_ID_FCOE 0x0021 -#define I40E_AQ_CAP_ID_RSS 0x0040 -#define I40E_AQ_CAP_ID_RXQ 0x0041 -#define I40E_AQ_CAP_ID_TXQ 0x0042 -#define I40E_AQ_CAP_ID_MSIX 0x0043 -#define I40E_AQ_CAP_ID_VF_MSIX 0x0044 -#define I40E_AQ_CAP_ID_FLOW_DIRECTOR 0x0045 -#define I40E_AQ_CAP_ID_1588 0x0046 -#define I40E_AQ_CAP_ID_IWARP 0x0051 -#define I40E_AQ_CAP_ID_LED 0x0061 -#define I40E_AQ_CAP_ID_SDP 0x0062 -#define I40E_AQ_CAP_ID_MDIO 0x0063 -#define I40E_AQ_CAP_ID_FLEX10 0x00F1 -#define I40E_AQ_CAP_ID_CEM 0x00F2 +#define I40E_AQ_CAP_ID_SWITCH_MODE 0x0001 +#define I40E_AQ_CAP_ID_MNG_MODE 0x0002 +#define I40E_AQ_CAP_ID_NPAR_ACTIVE 0x0003 +#define I40E_AQ_CAP_ID_OS2BMC_CAP 0x0004 +#define I40E_AQ_CAP_ID_FUNCTIONS_VALID 0x0005 +#define I40E_AQ_CAP_ID_ALTERNATE_RAM 0x0006 +#define I40E_AQ_CAP_ID_SRIOV 0x0012 +#define I40E_AQ_CAP_ID_VF 0x0013 +#define I40E_AQ_CAP_ID_VMDQ 0x0014 +#define I40E_AQ_CAP_ID_8021QBG 0x0015 +#define I40E_AQ_CAP_ID_8021QBR 0x0016 +#define I40E_AQ_CAP_ID_VSI 0x0017 +#define I40E_AQ_CAP_ID_DCB 0x0018 +#define I40E_AQ_CAP_ID_FCOE 0x0021 +#define I40E_AQ_CAP_ID_RSS 0x0040 +#define I40E_AQ_CAP_ID_RXQ 0x0041 +#define I40E_AQ_CAP_ID_TXQ 0x0042 +#define I40E_AQ_CAP_ID_MSIX 0x0043 +#define I40E_AQ_CAP_ID_VF_MSIX 0x0044 +#define I40E_AQ_CAP_ID_FLOW_DIRECTOR 0x0045 +#define I40E_AQ_CAP_ID_1588 0x0046 +#define I40E_AQ_CAP_ID_IWARP 0x0051 +#define I40E_AQ_CAP_ID_LED 0x0061 +#define I40E_AQ_CAP_ID_SDP 0x0062 +#define I40E_AQ_CAP_ID_MDIO 0x0063 +#define I40E_AQ_CAP_ID_FLEX10 0x00F1 +#define I40E_AQ_CAP_ID_CEM 0x00F2 /* Set CPPM Configuration (direct 0x0103) */ struct i40e_aqc_cppm_configuration { - __le16 command_flags; -#define I40E_AQ_CPPM_EN_LTRC 0x0800 -#define I40E_AQ_CPPM_EN_DMCTH 0x1000 -#define I40E_AQ_CPPM_EN_DMCTLX 0x2000 -#define I40E_AQ_CPPM_EN_HPTC 0x4000 -#define I40E_AQ_CPPM_EN_DMARC 0x8000 - __le16 ttlx; - __le32 dmacr; - __le16 dmcth; - u8 hptc; - u8 reserved; - __le32 pfltrc; + __le16 command_flags; +#define I40E_AQ_CPPM_EN_LTRC 0x0800 +#define I40E_AQ_CPPM_EN_DMCTH 0x1000 +#define I40E_AQ_CPPM_EN_DMCTLX 0x2000 +#define I40E_AQ_CPPM_EN_HPTC 0x4000 +#define I40E_AQ_CPPM_EN_DMARC 0x8000 + __le16 ttlx; + __le32 dmacr; + __le16 dmcth; + u8 hptc; + u8 reserved; + __le32 pfltrc; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_cppm_configuration); /* Set ARP Proxy command / response (indirect 0x0104) */ struct i40e_aqc_arp_proxy_data { - __le16 command_flags; -#define I40E_AQ_ARP_INIT_IPV4 0x0008 -#define I40E_AQ_ARP_UNSUP_CTL 0x0010 -#define I40E_AQ_ARP_ENA 0x0020 -#define I40E_AQ_ARP_ADD_IPV4 0x0040 -#define I40E_AQ_ARP_DEL_IPV4 0x0080 - __le16 table_id; - __le32 pfpm_proxyfc; - __le32 ip_addr; - u8 mac_addr[6]; + __le16 command_flags; +#define I40E_AQ_ARP_INIT_IPV4 0x0008 +#define I40E_AQ_ARP_UNSUP_CTL 0x0010 +#define I40E_AQ_ARP_ENA 0x0020 +#define I40E_AQ_ARP_ADD_IPV4 0x0040 +#define I40E_AQ_ARP_DEL_IPV4 0x0080 + __le16 table_id; + __le32 pfpm_proxyfc; + __le32 ip_addr; + u8 mac_addr[6]; }; /* Set NS Proxy Table Entry Command (indirect 0x0105) */ struct i40e_aqc_ns_proxy_data { - __le16 table_idx_mac_addr_0; - __le16 table_idx_mac_addr_1; - __le16 table_idx_ipv6_0; - __le16 table_idx_ipv6_1; - __le16 control; -#define I40E_AQ_NS_PROXY_ADD_0 0x0100 -#define I40E_AQ_NS_PROXY_DEL_0 0x0200 -#define I40E_AQ_NS_PROXY_ADD_1 0x0400 -#define I40E_AQ_NS_PROXY_DEL_1 0x0800 -#define I40E_AQ_NS_PROXY_ADD_IPV6_0 0x1000 -#define I40E_AQ_NS_PROXY_DEL_IPV6_0 0x2000 -#define I40E_AQ_NS_PROXY_ADD_IPV6_1 0x4000 -#define I40E_AQ_NS_PROXY_DEL_IPV6_1 0x8000 -#define I40E_AQ_NS_PROXY_COMMAND_SEQ 0x0001 -#define I40E_AQ_NS_PROXY_INIT_IPV6_TBL 0x0002 -#define I40E_AQ_NS_PROXY_INIT_MAC_TBL 0x0004 - u8 mac_addr_0[6]; - u8 mac_addr_1[6]; - u8 local_mac_addr[6]; - u8 ipv6_addr_0[16]; /* Warning! spec specifies BE byte order */ - u8 ipv6_addr_1[16]; + __le16 table_idx_mac_addr_0; + __le16 table_idx_mac_addr_1; + __le16 table_idx_ipv6_0; + __le16 table_idx_ipv6_1; + __le16 control; +#define I40E_AQ_NS_PROXY_ADD_0 0x0100 +#define I40E_AQ_NS_PROXY_DEL_0 0x0200 +#define I40E_AQ_NS_PROXY_ADD_1 0x0400 +#define I40E_AQ_NS_PROXY_DEL_1 0x0800 +#define I40E_AQ_NS_PROXY_ADD_IPV6_0 0x1000 +#define I40E_AQ_NS_PROXY_DEL_IPV6_0 0x2000 +#define I40E_AQ_NS_PROXY_ADD_IPV6_1 0x4000 +#define I40E_AQ_NS_PROXY_DEL_IPV6_1 0x8000 +#define I40E_AQ_NS_PROXY_COMMAND_SEQ 0x0001 +#define I40E_AQ_NS_PROXY_INIT_IPV6_TBL 0x0002 +#define I40E_AQ_NS_PROXY_INIT_MAC_TBL 0x0004 + u8 mac_addr_0[6]; + u8 mac_addr_1[6]; + u8 local_mac_addr[6]; + u8 ipv6_addr_0[16]; /* Warning! spec specifies BE byte order */ + u8 ipv6_addr_1[16]; }; /* Manage LAA Command (0x0106) - obsolete */ struct i40e_aqc_mng_laa { __le16 command_flags; -#define I40E_AQ_LAA_FLAG_WR 0x8000 - u8 reserved[2]; - __le32 sal; - __le16 sah; - u8 reserved2[6]; +#define I40E_AQ_LAA_FLAG_WR 0x8000 + u8 reserved[2]; + __le32 sal; + __le16 sah; + u8 reserved2[6]; }; /* Manage MAC Address Read Command (indirect 0x0107) */ struct i40e_aqc_mac_address_read { __le16 command_flags; -#define I40E_AQC_LAN_ADDR_VALID 0x10 -#define I40E_AQC_SAN_ADDR_VALID 0x20 -#define I40E_AQC_PORT_ADDR_VALID 0x40 -#define I40E_AQC_WOL_ADDR_VALID 0x80 -#define I40E_AQC_ADDR_VALID_MASK 0xf0 - u8 reserved[6]; - __le32 addr_high; - __le32 addr_low; +#define I40E_AQC_LAN_ADDR_VALID 0x10 +#define I40E_AQC_SAN_ADDR_VALID 0x20 +#define I40E_AQC_PORT_ADDR_VALID 0x40 +#define I40E_AQC_WOL_ADDR_VALID 0x80 +#define I40E_AQC_ADDR_VALID_MASK 0xf0 + u8 reserved[6]; + __le32 addr_high; + __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_mac_address_read); @@ -516,14 +517,14 @@ I40E_CHECK_STRUCT_LEN(24, i40e_aqc_mac_address_read_data); /* Manage MAC Address Write Command (0x0108) */ struct i40e_aqc_mac_address_write { - __le16 command_flags; -#define I40E_AQC_WRITE_TYPE_LAA_ONLY 0x0000 -#define I40E_AQC_WRITE_TYPE_LAA_WOL 0x4000 -#define I40E_AQC_WRITE_TYPE_PORT 0x8000 -#define I40E_AQC_WRITE_TYPE_MASK 0xc000 - __le16 mac_sah; - __le32 mac_sal; - u8 reserved[8]; + __le16 command_flags; +#define I40E_AQC_WRITE_TYPE_LAA_ONLY 0x0000 +#define I40E_AQC_WRITE_TYPE_LAA_WOL 0x4000 +#define I40E_AQC_WRITE_TYPE_PORT 0x8000 +#define I40E_AQC_WRITE_TYPE_MASK 0xc000 + __le16 mac_sah; + __le32 mac_sal; + u8 reserved[8]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_mac_address_write); @@ -544,10 +545,10 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_clear_pxe); * command */ struct i40e_aqc_switch_seid { - __le16 seid; - u8 reserved[6]; - __le32 addr_high; - __le32 addr_low; + __le16 seid; + u8 reserved[6]; + __le32 addr_high; + __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_switch_seid); @@ -556,34 +557,34 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_switch_seid); * uses i40e_aqc_switch_seid for the descriptor */ struct i40e_aqc_get_switch_config_header_resp { - __le16 num_reported; - __le16 num_total; - u8 reserved[12]; + __le16 num_reported; + __le16 num_total; + u8 reserved[12]; }; struct i40e_aqc_switch_config_element_resp { - u8 element_type; -#define I40E_AQ_SW_ELEM_TYPE_MAC 1 -#define I40E_AQ_SW_ELEM_TYPE_PF 2 -#define I40E_AQ_SW_ELEM_TYPE_VF 3 -#define I40E_AQ_SW_ELEM_TYPE_EMP 4 -#define I40E_AQ_SW_ELEM_TYPE_BMC 5 -#define I40E_AQ_SW_ELEM_TYPE_PV 16 -#define I40E_AQ_SW_ELEM_TYPE_VEB 17 -#define I40E_AQ_SW_ELEM_TYPE_PA 18 -#define I40E_AQ_SW_ELEM_TYPE_VSI 19 - u8 revision; -#define I40E_AQ_SW_ELEM_REV_1 1 - __le16 seid; - __le16 uplink_seid; - __le16 downlink_seid; - u8 reserved[3]; - u8 connection_type; -#define I40E_AQ_CONN_TYPE_REGULAR 0x1 -#define I40E_AQ_CONN_TYPE_DEFAULT 0x2 -#define I40E_AQ_CONN_TYPE_CASCADED 0x3 - __le16 scheduler_id; - __le16 element_info; + u8 element_type; +#define I40E_AQ_SW_ELEM_TYPE_MAC 1 +#define I40E_AQ_SW_ELEM_TYPE_PF 2 +#define I40E_AQ_SW_ELEM_TYPE_VF 3 +#define I40E_AQ_SW_ELEM_TYPE_EMP 4 +#define I40E_AQ_SW_ELEM_TYPE_BMC 5 +#define I40E_AQ_SW_ELEM_TYPE_PV 16 +#define I40E_AQ_SW_ELEM_TYPE_VEB 17 +#define I40E_AQ_SW_ELEM_TYPE_PA 18 +#define I40E_AQ_SW_ELEM_TYPE_VSI 19 + u8 revision; +#define I40E_AQ_SW_ELEM_REV_1 1 + __le16 seid; + __le16 uplink_seid; + __le16 downlink_seid; + u8 reserved[3]; + u8 connection_type; +#define I40E_AQ_CONN_TYPE_REGULAR 0x1 +#define I40E_AQ_CONN_TYPE_DEFAULT 0x2 +#define I40E_AQ_CONN_TYPE_CASCADED 0x3 + __le16 scheduler_id; + __le16 element_info; }; /* Get Switch Configuration (indirect 0x0200) @@ -591,73 +592,73 @@ struct i40e_aqc_switch_config_element_resp { * the first in the array is the header, remainder are elements */ struct i40e_aqc_get_switch_config_resp { - struct i40e_aqc_get_switch_config_header_resp header; - struct i40e_aqc_switch_config_element_resp element[1]; + struct i40e_aqc_get_switch_config_header_resp header; + struct i40e_aqc_switch_config_element_resp element[1]; }; /* Add Statistics (direct 0x0201) * Remove Statistics (direct 0x0202) */ struct i40e_aqc_add_remove_statistics { - __le16 seid; - __le16 vlan; - __le16 stat_index; - u8 reserved[10]; + __le16 seid; + __le16 vlan; + __le16 stat_index; + u8 reserved[10]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_statistics); /* Set Port Parameters command (direct 0x0203) */ struct i40e_aqc_set_port_parameters { - __le16 command_flags; -#define I40E_AQ_SET_P_PARAMS_SAVE_BAD_PACKETS 1 -#define I40E_AQ_SET_P_PARAMS_PAD_SHORT_PACKETS 2 /* must set! */ -#define I40E_AQ_SET_P_PARAMS_DOUBLE_VLAN_ENA 4 - __le16 bad_frame_vsi; - __le16 default_seid; /* reserved for command */ - u8 reserved[10]; + __le16 command_flags; +#define I40E_AQ_SET_P_PARAMS_SAVE_BAD_PACKETS 1 +#define I40E_AQ_SET_P_PARAMS_PAD_SHORT_PACKETS 2 /* must set! */ +#define I40E_AQ_SET_P_PARAMS_DOUBLE_VLAN_ENA 4 + __le16 bad_frame_vsi; + __le16 default_seid; /* reserved for command */ + u8 reserved[10]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_set_port_parameters); /* Get Switch Resource Allocation (indirect 0x0204) */ struct i40e_aqc_get_switch_resource_alloc { - u8 num_entries; /* reserved for command */ - u8 reserved[7]; - __le32 addr_high; - __le32 addr_low; + u8 num_entries; /* reserved for command */ + u8 reserved[7]; + __le32 addr_high; + __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_get_switch_resource_alloc); /* expect an array of these structs in the response buffer */ struct i40e_aqc_switch_resource_alloc_element_resp { - u8 resource_type; -#define I40E_AQ_RESOURCE_TYPE_VEB 0x0 -#define I40E_AQ_RESOURCE_TYPE_VSI 0x1 -#define I40E_AQ_RESOURCE_TYPE_MACADDR 0x2 -#define I40E_AQ_RESOURCE_TYPE_STAG 0x3 -#define I40E_AQ_RESOURCE_TYPE_ETAG 0x4 -#define I40E_AQ_RESOURCE_TYPE_MULTICAST_HASH 0x5 -#define I40E_AQ_RESOURCE_TYPE_UNICAST_HASH 0x6 -#define I40E_AQ_RESOURCE_TYPE_VLAN 0x7 -#define I40E_AQ_RESOURCE_TYPE_VSI_LIST_ENTRY 0x8 -#define I40E_AQ_RESOURCE_TYPE_ETAG_LIST_ENTRY 0x9 -#define I40E_AQ_RESOURCE_TYPE_VLAN_STAT_POOL 0xA -#define I40E_AQ_RESOURCE_TYPE_MIRROR_RULE 0xB -#define I40E_AQ_RESOURCE_TYPE_QUEUE_SETS 0xC -#define I40E_AQ_RESOURCE_TYPE_VLAN_FILTERS 0xD -#define I40E_AQ_RESOURCE_TYPE_INNER_MAC_FILTERS 0xF -#define I40E_AQ_RESOURCE_TYPE_IP_FILTERS 0x10 -#define I40E_AQ_RESOURCE_TYPE_GRE_VN_KEYS 0x11 -#define I40E_AQ_RESOURCE_TYPE_VN2_KEYS 0x12 -#define I40E_AQ_RESOURCE_TYPE_TUNNEL_PORTS 0x13 - u8 reserved1; - __le16 guaranteed; - __le16 total; - __le16 used; - __le16 total_unalloced; - u8 reserved2[6]; + u8 resource_type; +#define I40E_AQ_RESOURCE_TYPE_VEB 0x0 +#define I40E_AQ_RESOURCE_TYPE_VSI 0x1 +#define I40E_AQ_RESOURCE_TYPE_MACADDR 0x2 +#define I40E_AQ_RESOURCE_TYPE_STAG 0x3 +#define I40E_AQ_RESOURCE_TYPE_ETAG 0x4 +#define I40E_AQ_RESOURCE_TYPE_MULTICAST_HASH 0x5 +#define I40E_AQ_RESOURCE_TYPE_UNICAST_HASH 0x6 +#define I40E_AQ_RESOURCE_TYPE_VLAN 0x7 +#define I40E_AQ_RESOURCE_TYPE_VSI_LIST_ENTRY 0x8 +#define I40E_AQ_RESOURCE_TYPE_ETAG_LIST_ENTRY 0x9 +#define I40E_AQ_RESOURCE_TYPE_VLAN_STAT_POOL 0xA +#define I40E_AQ_RESOURCE_TYPE_MIRROR_RULE 0xB +#define I40E_AQ_RESOURCE_TYPE_QUEUE_SETS 0xC +#define I40E_AQ_RESOURCE_TYPE_VLAN_FILTERS 0xD +#define I40E_AQ_RESOURCE_TYPE_INNER_MAC_FILTERS 0xF +#define I40E_AQ_RESOURCE_TYPE_IP_FILTERS 0x10 +#define I40E_AQ_RESOURCE_TYPE_GRE_VN_KEYS 0x11 +#define I40E_AQ_RESOURCE_TYPE_VN2_KEYS 0x12 +#define I40E_AQ_RESOURCE_TYPE_TUNNEL_PORTS 0x13 + u8 reserved1; + __le16 guaranteed; + __le16 total; + __le16 used; + __le16 total_unalloced; + u8 reserved2[6]; }; /* Add VSI (indirect 0x0210) @@ -671,24 +672,24 @@ struct i40e_aqc_switch_resource_alloc_element_resp { * uses the same completion and data structure as Add VSI */ struct i40e_aqc_add_get_update_vsi { - __le16 uplink_seid; - u8 connection_type; -#define I40E_AQ_VSI_CONN_TYPE_NORMAL 0x1 -#define I40E_AQ_VSI_CONN_TYPE_DEFAULT 0x2 -#define I40E_AQ_VSI_CONN_TYPE_CASCADED 0x3 - u8 reserved1; - u8 vf_id; - u8 reserved2; - __le16 vsi_flags; -#define I40E_AQ_VSI_TYPE_SHIFT 0x0 -#define I40E_AQ_VSI_TYPE_MASK (0x3 << I40E_AQ_VSI_TYPE_SHIFT) -#define I40E_AQ_VSI_TYPE_VF 0x0 -#define I40E_AQ_VSI_TYPE_VMDQ2 0x1 -#define I40E_AQ_VSI_TYPE_PF 0x2 -#define I40E_AQ_VSI_TYPE_EMP_MNG 0x3 -#define I40E_AQ_VSI_FLAG_CASCADED_PV 0x4 - __le32 addr_high; - __le32 addr_low; + __le16 uplink_seid; + u8 connection_type; +#define I40E_AQ_VSI_CONN_TYPE_NORMAL 0x1 +#define I40E_AQ_VSI_CONN_TYPE_DEFAULT 0x2 +#define I40E_AQ_VSI_CONN_TYPE_CASCADED 0x3 + u8 reserved1; + u8 vf_id; + u8 reserved2; + __le16 vsi_flags; +#define I40E_AQ_VSI_TYPE_SHIFT 0x0 +#define I40E_AQ_VSI_TYPE_MASK (0x3 << I40E_AQ_VSI_TYPE_SHIFT) +#define I40E_AQ_VSI_TYPE_VF 0x0 +#define I40E_AQ_VSI_TYPE_VMDQ2 0x1 +#define I40E_AQ_VSI_TYPE_PF 0x2 +#define I40E_AQ_VSI_TYPE_EMP_MNG 0x3 +#define I40E_AQ_VSI_FLAG_CASCADED_PV 0x4 + __le32 addr_high; + __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_get_update_vsi); @@ -706,121 +707,121 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_add_get_update_vsi_completion); struct i40e_aqc_vsi_properties_data { /* first 96 byte are written by SW */ - __le16 valid_sections; -#define I40E_AQ_VSI_PROP_SWITCH_VALID 0x0001 -#define I40E_AQ_VSI_PROP_SECURITY_VALID 0x0002 -#define I40E_AQ_VSI_PROP_VLAN_VALID 0x0004 -#define I40E_AQ_VSI_PROP_CAS_PV_VALID 0x0008 -#define I40E_AQ_VSI_PROP_INGRESS_UP_VALID 0x0010 -#define I40E_AQ_VSI_PROP_EGRESS_UP_VALID 0x0020 -#define I40E_AQ_VSI_PROP_QUEUE_MAP_VALID 0x0040 -#define I40E_AQ_VSI_PROP_QUEUE_OPT_VALID 0x0080 -#define I40E_AQ_VSI_PROP_OUTER_UP_VALID 0x0100 -#define I40E_AQ_VSI_PROP_SCHED_VALID 0x0200 + __le16 valid_sections; +#define I40E_AQ_VSI_PROP_SWITCH_VALID 0x0001 +#define I40E_AQ_VSI_PROP_SECURITY_VALID 0x0002 +#define I40E_AQ_VSI_PROP_VLAN_VALID 0x0004 +#define I40E_AQ_VSI_PROP_CAS_PV_VALID 0x0008 +#define I40E_AQ_VSI_PROP_INGRESS_UP_VALID 0x0010 +#define I40E_AQ_VSI_PROP_EGRESS_UP_VALID 0x0020 +#define I40E_AQ_VSI_PROP_QUEUE_MAP_VALID 0x0040 +#define I40E_AQ_VSI_PROP_QUEUE_OPT_VALID 0x0080 +#define I40E_AQ_VSI_PROP_OUTER_UP_VALID 0x0100 +#define I40E_AQ_VSI_PROP_SCHED_VALID 0x0200 /* switch section */ - __le16 switch_id; /* 12bit id combined with flags below */ -#define I40E_AQ_VSI_SW_ID_SHIFT 0x0000 -#define I40E_AQ_VSI_SW_ID_MASK (0xFFF << I40E_AQ_VSI_SW_ID_SHIFT) -#define I40E_AQ_VSI_SW_ID_FLAG_NOT_STAG 0x1000 -#define I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB 0x2000 -#define I40E_AQ_VSI_SW_ID_FLAG_LOCAL_LB 0x4000 - u8 sw_reserved[2]; + __le16 switch_id; /* 12bit id combined with flags below */ +#define I40E_AQ_VSI_SW_ID_SHIFT 0x0000 +#define I40E_AQ_VSI_SW_ID_MASK (0xFFF << I40E_AQ_VSI_SW_ID_SHIFT) +#define I40E_AQ_VSI_SW_ID_FLAG_NOT_STAG 0x1000 +#define I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB 0x2000 +#define I40E_AQ_VSI_SW_ID_FLAG_LOCAL_LB 0x4000 + u8 sw_reserved[2]; /* security section */ - u8 sec_flags; -#define I40E_AQ_VSI_SEC_FLAG_ALLOW_DEST_OVRD 0x01 -#define I40E_AQ_VSI_SEC_FLAG_ENABLE_VLAN_CHK 0x02 -#define I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK 0x04 - u8 sec_reserved; + u8 sec_flags; +#define I40E_AQ_VSI_SEC_FLAG_ALLOW_DEST_OVRD 0x01 +#define I40E_AQ_VSI_SEC_FLAG_ENABLE_VLAN_CHK 0x02 +#define I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK 0x04 + u8 sec_reserved; /* VLAN section */ - __le16 pvid; /* VLANS include priority bits */ - __le16 fcoe_pvid; - u8 port_vlan_flags; -#define I40E_AQ_VSI_PVLAN_MODE_SHIFT 0x00 -#define I40E_AQ_VSI_PVLAN_MODE_MASK (0x03 << \ - I40E_AQ_VSI_PVLAN_MODE_SHIFT) -#define I40E_AQ_VSI_PVLAN_MODE_TAGGED 0x01 -#define I40E_AQ_VSI_PVLAN_MODE_UNTAGGED 0x02 -#define I40E_AQ_VSI_PVLAN_MODE_ALL 0x03 -#define I40E_AQ_VSI_PVLAN_INSERT_PVID 0x04 -#define I40E_AQ_VSI_PVLAN_EMOD_SHIFT 0x03 -#define I40E_AQ_VSI_PVLAN_EMOD_MASK (0x3 << \ - I40E_AQ_VSI_PVLAN_EMOD_SHIFT) -#define I40E_AQ_VSI_PVLAN_EMOD_STR_BOTH 0x0 -#define I40E_AQ_VSI_PVLAN_EMOD_STR_UP 0x08 -#define I40E_AQ_VSI_PVLAN_EMOD_STR 0x10 -#define I40E_AQ_VSI_PVLAN_EMOD_NOTHING 0x18 - u8 pvlan_reserved[3]; + __le16 pvid; /* VLANS include priority bits */ + __le16 fcoe_pvid; + u8 port_vlan_flags; +#define I40E_AQ_VSI_PVLAN_MODE_SHIFT 0x00 +#define I40E_AQ_VSI_PVLAN_MODE_MASK (0x03 << \ + I40E_AQ_VSI_PVLAN_MODE_SHIFT) +#define I40E_AQ_VSI_PVLAN_MODE_TAGGED 0x01 +#define I40E_AQ_VSI_PVLAN_MODE_UNTAGGED 0x02 +#define I40E_AQ_VSI_PVLAN_MODE_ALL 0x03 +#define I40E_AQ_VSI_PVLAN_INSERT_PVID 0x04 +#define I40E_AQ_VSI_PVLAN_EMOD_SHIFT 0x03 +#define I40E_AQ_VSI_PVLAN_EMOD_MASK (0x3 << \ + I40E_AQ_VSI_PVLAN_EMOD_SHIFT) +#define I40E_AQ_VSI_PVLAN_EMOD_STR_BOTH 0x0 +#define I40E_AQ_VSI_PVLAN_EMOD_STR_UP 0x08 +#define I40E_AQ_VSI_PVLAN_EMOD_STR 0x10 +#define I40E_AQ_VSI_PVLAN_EMOD_NOTHING 0x18 + u8 pvlan_reserved[3]; /* ingress egress up sections */ - __le32 ingress_table; /* bitmap, 3 bits per up */ -#define I40E_AQ_VSI_UP_TABLE_UP0_SHIFT 0 -#define I40E_AQ_VSI_UP_TABLE_UP0_MASK (0x7 << \ - I40E_AQ_VSI_UP_TABLE_UP0_SHIFT) -#define I40E_AQ_VSI_UP_TABLE_UP1_SHIFT 3 -#define I40E_AQ_VSI_UP_TABLE_UP1_MASK (0x7 << \ - I40E_AQ_VSI_UP_TABLE_UP1_SHIFT) -#define I40E_AQ_VSI_UP_TABLE_UP2_SHIFT 6 -#define I40E_AQ_VSI_UP_TABLE_UP2_MASK (0x7 << \ - I40E_AQ_VSI_UP_TABLE_UP2_SHIFT) -#define I40E_AQ_VSI_UP_TABLE_UP3_SHIFT 9 -#define I40E_AQ_VSI_UP_TABLE_UP3_MASK (0x7 << \ - I40E_AQ_VSI_UP_TABLE_UP3_SHIFT) -#define I40E_AQ_VSI_UP_TABLE_UP4_SHIFT 12 -#define I40E_AQ_VSI_UP_TABLE_UP4_MASK (0x7 << \ - I40E_AQ_VSI_UP_TABLE_UP4_SHIFT) -#define I40E_AQ_VSI_UP_TABLE_UP5_SHIFT 15 -#define I40E_AQ_VSI_UP_TABLE_UP5_MASK (0x7 << \ - I40E_AQ_VSI_UP_TABLE_UP5_SHIFT) -#define I40E_AQ_VSI_UP_TABLE_UP6_SHIFT 18 -#define I40E_AQ_VSI_UP_TABLE_UP6_MASK (0x7 << \ - I40E_AQ_VSI_UP_TABLE_UP6_SHIFT) -#define I40E_AQ_VSI_UP_TABLE_UP7_SHIFT 21 -#define I40E_AQ_VSI_UP_TABLE_UP7_MASK (0x7 << \ - I40E_AQ_VSI_UP_TABLE_UP7_SHIFT) - __le32 egress_table; /* same defines as for ingress table */ + __le32 ingress_table; /* bitmap, 3 bits per up */ +#define I40E_AQ_VSI_UP_TABLE_UP0_SHIFT 0 +#define I40E_AQ_VSI_UP_TABLE_UP0_MASK (0x7 << \ + I40E_AQ_VSI_UP_TABLE_UP0_SHIFT) +#define I40E_AQ_VSI_UP_TABLE_UP1_SHIFT 3 +#define I40E_AQ_VSI_UP_TABLE_UP1_MASK (0x7 << \ + I40E_AQ_VSI_UP_TABLE_UP1_SHIFT) +#define I40E_AQ_VSI_UP_TABLE_UP2_SHIFT 6 +#define I40E_AQ_VSI_UP_TABLE_UP2_MASK (0x7 << \ + I40E_AQ_VSI_UP_TABLE_UP2_SHIFT) +#define I40E_AQ_VSI_UP_TABLE_UP3_SHIFT 9 +#define I40E_AQ_VSI_UP_TABLE_UP3_MASK (0x7 << \ + I40E_AQ_VSI_UP_TABLE_UP3_SHIFT) +#define I40E_AQ_VSI_UP_TABLE_UP4_SHIFT 12 +#define I40E_AQ_VSI_UP_TABLE_UP4_MASK (0x7 << \ + I40E_AQ_VSI_UP_TABLE_UP4_SHIFT) +#define I40E_AQ_VSI_UP_TABLE_UP5_SHIFT 15 +#define I40E_AQ_VSI_UP_TABLE_UP5_MASK (0x7 << \ + I40E_AQ_VSI_UP_TABLE_UP5_SHIFT) +#define I40E_AQ_VSI_UP_TABLE_UP6_SHIFT 18 +#define I40E_AQ_VSI_UP_TABLE_UP6_MASK (0x7 << \ + I40E_AQ_VSI_UP_TABLE_UP6_SHIFT) +#define I40E_AQ_VSI_UP_TABLE_UP7_SHIFT 21 +#define I40E_AQ_VSI_UP_TABLE_UP7_MASK (0x7 << \ + I40E_AQ_VSI_UP_TABLE_UP7_SHIFT) + __le32 egress_table; /* same defines as for ingress table */ /* cascaded PV section */ - __le16 cas_pv_tag; - u8 cas_pv_flags; -#define I40E_AQ_VSI_CAS_PV_TAGX_SHIFT 0x00 -#define I40E_AQ_VSI_CAS_PV_TAGX_MASK (0x03 << \ - I40E_AQ_VSI_CAS_PV_TAGX_SHIFT) -#define I40E_AQ_VSI_CAS_PV_TAGX_LEAVE 0x00 -#define I40E_AQ_VSI_CAS_PV_TAGX_REMOVE 0x01 -#define I40E_AQ_VSI_CAS_PV_TAGX_COPY 0x02 -#define I40E_AQ_VSI_CAS_PV_INSERT_TAG 0x10 -#define I40E_AQ_VSI_CAS_PV_ETAG_PRUNE 0x20 -#define I40E_AQ_VSI_CAS_PV_ACCEPT_HOST_TAG 0x40 - u8 cas_pv_reserved; + __le16 cas_pv_tag; + u8 cas_pv_flags; +#define I40E_AQ_VSI_CAS_PV_TAGX_SHIFT 0x00 +#define I40E_AQ_VSI_CAS_PV_TAGX_MASK (0x03 << \ + I40E_AQ_VSI_CAS_PV_TAGX_SHIFT) +#define I40E_AQ_VSI_CAS_PV_TAGX_LEAVE 0x00 +#define I40E_AQ_VSI_CAS_PV_TAGX_REMOVE 0x01 +#define I40E_AQ_VSI_CAS_PV_TAGX_COPY 0x02 +#define I40E_AQ_VSI_CAS_PV_INSERT_TAG 0x10 +#define I40E_AQ_VSI_CAS_PV_ETAG_PRUNE 0x20 +#define I40E_AQ_VSI_CAS_PV_ACCEPT_HOST_TAG 0x40 + u8 cas_pv_reserved; /* queue mapping section */ - __le16 mapping_flags; -#define I40E_AQ_VSI_QUE_MAP_CONTIG 0x0 -#define I40E_AQ_VSI_QUE_MAP_NONCONTIG 0x1 - __le16 queue_mapping[16]; -#define I40E_AQ_VSI_QUEUE_SHIFT 0x0 -#define I40E_AQ_VSI_QUEUE_MASK (0x7FF << I40E_AQ_VSI_QUEUE_SHIFT) - __le16 tc_mapping[8]; -#define I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT 0 -#define I40E_AQ_VSI_TC_QUE_OFFSET_MASK (0x1FF << \ - I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT) -#define I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT 9 -#define I40E_AQ_VSI_TC_QUE_NUMBER_MASK (0x7 << \ - I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT) + __le16 mapping_flags; +#define I40E_AQ_VSI_QUE_MAP_CONTIG 0x0 +#define I40E_AQ_VSI_QUE_MAP_NONCONTIG 0x1 + __le16 queue_mapping[16]; +#define I40E_AQ_VSI_QUEUE_SHIFT 0x0 +#define I40E_AQ_VSI_QUEUE_MASK (0x7FF << I40E_AQ_VSI_QUEUE_SHIFT) + __le16 tc_mapping[8]; +#define I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT 0 +#define I40E_AQ_VSI_TC_QUE_OFFSET_MASK (0x1FF << \ + I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT) +#define I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT 9 +#define I40E_AQ_VSI_TC_QUE_NUMBER_MASK (0x7 << \ + I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT) /* queueing option section */ - u8 queueing_opt_flags; -#define I40E_AQ_VSI_QUE_OPT_TCP_ENA 0x10 -#define I40E_AQ_VSI_QUE_OPT_FCOE_ENA 0x20 - u8 queueing_opt_reserved[3]; + u8 queueing_opt_flags; +#define I40E_AQ_VSI_QUE_OPT_TCP_ENA 0x10 +#define I40E_AQ_VSI_QUE_OPT_FCOE_ENA 0x20 + u8 queueing_opt_reserved[3]; /* scheduler section */ - u8 up_enable_bits; - u8 sched_reserved; + u8 up_enable_bits; + u8 sched_reserved; /* outer up section */ - __le32 outer_up_table; /* same structure and defines as ingress table */ - u8 cmd_reserved[8]; + __le32 outer_up_table; /* same structure and defines as ingress tbl */ + u8 cmd_reserved[8]; /* last 32 bytes are written by FW */ - __le16 qs_handle[8]; + __le16 qs_handle[8]; #define I40E_AQ_VSI_QS_HANDLE_INVALID 0xFFFF - __le16 stat_counter_idx; - __le16 sched_id; - u8 resp_reserved[12]; + __le16 stat_counter_idx; + __le16 sched_id; + u8 resp_reserved[12]; }; I40E_CHECK_STRUCT_LEN(128, i40e_aqc_vsi_properties_data); @@ -830,26 +831,26 @@ I40E_CHECK_STRUCT_LEN(128, i40e_aqc_vsi_properties_data); * (IS_CTRL_PORT only works on add PV) */ struct i40e_aqc_add_update_pv { - __le16 command_flags; -#define I40E_AQC_PV_FLAG_PV_TYPE 0x1 -#define I40E_AQC_PV_FLAG_FWD_UNKNOWN_STAG_EN 0x2 -#define I40E_AQC_PV_FLAG_FWD_UNKNOWN_ETAG_EN 0x4 -#define I40E_AQC_PV_FLAG_IS_CTRL_PORT 0x8 - __le16 uplink_seid; - __le16 connected_seid; - u8 reserved[10]; + __le16 command_flags; +#define I40E_AQC_PV_FLAG_PV_TYPE 0x1 +#define I40E_AQC_PV_FLAG_FWD_UNKNOWN_STAG_EN 0x2 +#define I40E_AQC_PV_FLAG_FWD_UNKNOWN_ETAG_EN 0x4 +#define I40E_AQC_PV_FLAG_IS_CTRL_PORT 0x8 + __le16 uplink_seid; + __le16 connected_seid; + u8 reserved[10]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_update_pv); struct i40e_aqc_add_update_pv_completion { /* reserved for update; for add also encodes error if rc == ENOSPC */ - __le16 pv_seid; -#define I40E_AQC_PV_ERR_FLAG_NO_PV 0x1 -#define I40E_AQC_PV_ERR_FLAG_NO_SCHED 0x2 -#define I40E_AQC_PV_ERR_FLAG_NO_COUNTER 0x4 -#define I40E_AQC_PV_ERR_FLAG_NO_ENTRY 0x8 - u8 reserved[14]; + __le16 pv_seid; +#define I40E_AQC_PV_ERR_FLAG_NO_PV 0x1 +#define I40E_AQC_PV_ERR_FLAG_NO_SCHED 0x2 +#define I40E_AQC_PV_ERR_FLAG_NO_COUNTER 0x4 +#define I40E_AQC_PV_ERR_FLAG_NO_ENTRY 0x8 + u8 reserved[14]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_update_pv_completion); @@ -859,48 +860,48 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_add_update_pv_completion); */ struct i40e_aqc_get_pv_params_completion { - __le16 seid; - __le16 default_stag; - __le16 pv_flags; /* same flags as add_pv */ -#define I40E_AQC_GET_PV_PV_TYPE 0x1 -#define I40E_AQC_GET_PV_FRWD_UNKNOWN_STAG 0x2 -#define I40E_AQC_GET_PV_FRWD_UNKNOWN_ETAG 0x4 - u8 reserved[8]; - __le16 default_port_seid; + __le16 seid; + __le16 default_stag; + __le16 pv_flags; /* same flags as add_pv */ +#define I40E_AQC_GET_PV_PV_TYPE 0x1 +#define I40E_AQC_GET_PV_FRWD_UNKNOWN_STAG 0x2 +#define I40E_AQC_GET_PV_FRWD_UNKNOWN_ETAG 0x4 + u8 reserved[8]; + __le16 default_port_seid; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_get_pv_params_completion); /* Add VEB (direct 0x0230) */ struct i40e_aqc_add_veb { - __le16 uplink_seid; - __le16 downlink_seid; - __le16 veb_flags; -#define I40E_AQC_ADD_VEB_FLOATING 0x1 -#define I40E_AQC_ADD_VEB_PORT_TYPE_SHIFT 1 -#define I40E_AQC_ADD_VEB_PORT_TYPE_MASK (0x3 << \ + __le16 uplink_seid; + __le16 downlink_seid; + __le16 veb_flags; +#define I40E_AQC_ADD_VEB_FLOATING 0x1 +#define I40E_AQC_ADD_VEB_PORT_TYPE_SHIFT 1 +#define I40E_AQC_ADD_VEB_PORT_TYPE_MASK (0x3 << \ I40E_AQC_ADD_VEB_PORT_TYPE_SHIFT) -#define I40E_AQC_ADD_VEB_PORT_TYPE_DEFAULT 0x2 -#define I40E_AQC_ADD_VEB_PORT_TYPE_DATA 0x4 -#define I40E_AQC_ADD_VEB_ENABLE_L2_FILTER 0x8 - u8 enable_tcs; - u8 reserved[9]; +#define I40E_AQC_ADD_VEB_PORT_TYPE_DEFAULT 0x2 +#define I40E_AQC_ADD_VEB_PORT_TYPE_DATA 0x4 +#define I40E_AQC_ADD_VEB_ENABLE_L2_FILTER 0x8 + u8 enable_tcs; + u8 reserved[9]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_veb); struct i40e_aqc_add_veb_completion { - u8 reserved[6]; - __le16 switch_seid; + u8 reserved[6]; + __le16 switch_seid; /* also encodes error if rc == ENOSPC; codes are the same as add_pv */ - __le16 veb_seid; -#define I40E_AQC_VEB_ERR_FLAG_NO_VEB 0x1 -#define I40E_AQC_VEB_ERR_FLAG_NO_SCHED 0x2 -#define I40E_AQC_VEB_ERR_FLAG_NO_COUNTER 0x4 -#define I40E_AQC_VEB_ERR_FLAG_NO_ENTRY 0x8 - __le16 statistic_index; - __le16 vebs_used; - __le16 vebs_free; + __le16 veb_seid; +#define I40E_AQC_VEB_ERR_FLAG_NO_VEB 0x1 +#define I40E_AQC_VEB_ERR_FLAG_NO_SCHED 0x2 +#define I40E_AQC_VEB_ERR_FLAG_NO_COUNTER 0x4 +#define I40E_AQC_VEB_ERR_FLAG_NO_ENTRY 0x8 + __le16 statistic_index; + __le16 vebs_used; + __le16 vebs_free; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_veb_completion); @@ -909,13 +910,13 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_add_veb_completion); * uses i40e_aqc_switch_seid for the descriptor */ struct i40e_aqc_get_veb_parameters_completion { - __le16 seid; - __le16 switch_id; - __le16 veb_flags; /* only the first/last flags from 0x0230 is valid */ - __le16 statistic_index; - __le16 vebs_used; - __le16 vebs_free; - u8 reserved[4]; + __le16 seid; + __le16 switch_id; + __le16 veb_flags; /* only the first/last flags from 0x0230 is valid */ + __le16 statistic_index; + __le16 vebs_used; + __le16 vebs_free; + u8 reserved[4]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_get_veb_parameters_completion); @@ -928,37 +929,37 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_get_veb_parameters_completion); /* used for the command for most vlan commands */ struct i40e_aqc_macvlan { - __le16 num_addresses; - __le16 seid[3]; -#define I40E_AQC_MACVLAN_CMD_SEID_NUM_SHIFT 0 -#define I40E_AQC_MACVLAN_CMD_SEID_NUM_MASK (0x3FF << \ + __le16 num_addresses; + __le16 seid[3]; +#define I40E_AQC_MACVLAN_CMD_SEID_NUM_SHIFT 0 +#define I40E_AQC_MACVLAN_CMD_SEID_NUM_MASK (0x3FF << \ I40E_AQC_MACVLAN_CMD_SEID_NUM_SHIFT) -#define I40E_AQC_MACVLAN_CMD_SEID_VALID 0x8000 - __le32 addr_high; - __le32 addr_low; +#define I40E_AQC_MACVLAN_CMD_SEID_VALID 0x8000 + __le32 addr_high; + __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_macvlan); /* indirect data for command and response */ struct i40e_aqc_add_macvlan_element_data { - u8 mac_addr[6]; - __le16 vlan_tag; - __le16 flags; -#define I40E_AQC_MACVLAN_ADD_PERFECT_MATCH 0x0001 -#define I40E_AQC_MACVLAN_ADD_HASH_MATCH 0x0002 -#define I40E_AQC_MACVLAN_ADD_IGNORE_VLAN 0x0004 -#define I40E_AQC_MACVLAN_ADD_TO_QUEUE 0x0008 - __le16 queue_number; -#define I40E_AQC_MACVLAN_CMD_QUEUE_SHIFT 0 -#define I40E_AQC_MACVLAN_CMD_QUEUE_MASK (0x7FF << \ + u8 mac_addr[6]; + __le16 vlan_tag; + __le16 flags; +#define I40E_AQC_MACVLAN_ADD_PERFECT_MATCH 0x0001 +#define I40E_AQC_MACVLAN_ADD_HASH_MATCH 0x0002 +#define I40E_AQC_MACVLAN_ADD_IGNORE_VLAN 0x0004 +#define I40E_AQC_MACVLAN_ADD_TO_QUEUE 0x0008 + __le16 queue_number; +#define I40E_AQC_MACVLAN_CMD_QUEUE_SHIFT 0 +#define I40E_AQC_MACVLAN_CMD_QUEUE_MASK (0x7FF << \ I40E_AQC_MACVLAN_CMD_SEID_NUM_SHIFT) /* response section */ - u8 match_method; -#define I40E_AQC_MM_PERFECT_MATCH 0x01 -#define I40E_AQC_MM_HASH_MATCH 0x02 -#define I40E_AQC_MM_ERR_NO_RES 0xFF - u8 reserved1[3]; + u8 match_method; +#define I40E_AQC_MM_PERFECT_MATCH 0x01 +#define I40E_AQC_MM_HASH_MATCH 0x02 +#define I40E_AQC_MM_ERR_NO_RES 0xFF + u8 reserved1[3]; }; struct i40e_aqc_add_remove_macvlan_completion { @@ -978,19 +979,19 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_macvlan_completion); */ struct i40e_aqc_remove_macvlan_element_data { - u8 mac_addr[6]; - __le16 vlan_tag; - u8 flags; -#define I40E_AQC_MACVLAN_DEL_PERFECT_MATCH 0x01 -#define I40E_AQC_MACVLAN_DEL_HASH_MATCH 0x02 -#define I40E_AQC_MACVLAN_DEL_IGNORE_VLAN 0x08 -#define I40E_AQC_MACVLAN_DEL_ALL_VSIS 0x10 - u8 reserved[3]; + u8 mac_addr[6]; + __le16 vlan_tag; + u8 flags; +#define I40E_AQC_MACVLAN_DEL_PERFECT_MATCH 0x01 +#define I40E_AQC_MACVLAN_DEL_HASH_MATCH 0x02 +#define I40E_AQC_MACVLAN_DEL_IGNORE_VLAN 0x08 +#define I40E_AQC_MACVLAN_DEL_ALL_VSIS 0x10 + u8 reserved[3]; /* reply section */ - u8 error_code; -#define I40E_AQC_REMOVE_MACVLAN_SUCCESS 0x0 -#define I40E_AQC_REMOVE_MACVLAN_FAIL 0xFF - u8 reply_reserved[3]; + u8 error_code; +#define I40E_AQC_REMOVE_MACVLAN_SUCCESS 0x0 +#define I40E_AQC_REMOVE_MACVLAN_FAIL 0xFF + u8 reply_reserved[3]; }; /* Add VLAN (indirect 0x0252) @@ -998,59 +999,58 @@ struct i40e_aqc_remove_macvlan_element_data { * use the generic i40e_aqc_macvlan for the command */ struct i40e_aqc_add_remove_vlan_element_data { - __le16 vlan_tag; - u8 vlan_flags; + __le16 vlan_tag; + u8 vlan_flags; /* flags for add VLAN */ -#define I40E_AQC_ADD_VLAN_LOCAL 0x1 -#define I40E_AQC_ADD_PVLAN_TYPE_SHIFT 1 -#define I40E_AQC_ADD_PVLAN_TYPE_MASK (0x3 << \ - I40E_AQC_ADD_PVLAN_TYPE_SHIFT) -#define I40E_AQC_ADD_PVLAN_TYPE_REGULAR 0x0 -#define I40E_AQC_ADD_PVLAN_TYPE_PRIMARY 0x2 -#define I40E_AQC_ADD_PVLAN_TYPE_SECONDARY 0x4 -#define I40E_AQC_VLAN_PTYPE_SHIFT 3 -#define I40E_AQC_VLAN_PTYPE_MASK (0x3 << I40E_AQC_VLAN_PTYPE_SHIFT) -#define I40E_AQC_VLAN_PTYPE_REGULAR_VSI 0x0 -#define I40E_AQC_VLAN_PTYPE_PROMISC_VSI 0x8 -#define I40E_AQC_VLAN_PTYPE_COMMUNITY_VSI 0x10 -#define I40E_AQC_VLAN_PTYPE_ISOLATED_VSI 0x18 +#define I40E_AQC_ADD_VLAN_LOCAL 0x1 +#define I40E_AQC_ADD_PVLAN_TYPE_SHIFT 1 +#define I40E_AQC_ADD_PVLAN_TYPE_MASK (0x3 << I40E_AQC_ADD_PVLAN_TYPE_SHIFT) +#define I40E_AQC_ADD_PVLAN_TYPE_REGULAR 0x0 +#define I40E_AQC_ADD_PVLAN_TYPE_PRIMARY 0x2 +#define I40E_AQC_ADD_PVLAN_TYPE_SECONDARY 0x4 +#define I40E_AQC_VLAN_PTYPE_SHIFT 3 +#define I40E_AQC_VLAN_PTYPE_MASK (0x3 << I40E_AQC_VLAN_PTYPE_SHIFT) +#define I40E_AQC_VLAN_PTYPE_REGULAR_VSI 0x0 +#define I40E_AQC_VLAN_PTYPE_PROMISC_VSI 0x8 +#define I40E_AQC_VLAN_PTYPE_COMMUNITY_VSI 0x10 +#define I40E_AQC_VLAN_PTYPE_ISOLATED_VSI 0x18 /* flags for remove VLAN */ -#define I40E_AQC_REMOVE_VLAN_ALL 0x1 - u8 reserved; - u8 result; +#define I40E_AQC_REMOVE_VLAN_ALL 0x1 + u8 reserved; + u8 result; /* flags for add VLAN */ -#define I40E_AQC_ADD_VLAN_SUCCESS 0x0 -#define I40E_AQC_ADD_VLAN_FAIL_REQUEST 0xFE -#define I40E_AQC_ADD_VLAN_FAIL_RESOURCE 0xFF +#define I40E_AQC_ADD_VLAN_SUCCESS 0x0 +#define I40E_AQC_ADD_VLAN_FAIL_REQUEST 0xFE +#define I40E_AQC_ADD_VLAN_FAIL_RESOURCE 0xFF /* flags for remove VLAN */ -#define I40E_AQC_REMOVE_VLAN_SUCCESS 0x0 -#define I40E_AQC_REMOVE_VLAN_FAIL 0xFF - u8 reserved1[3]; +#define I40E_AQC_REMOVE_VLAN_SUCCESS 0x0 +#define I40E_AQC_REMOVE_VLAN_FAIL 0xFF + u8 reserved1[3]; }; struct i40e_aqc_add_remove_vlan_completion { - u8 reserved[4]; - __le16 vlans_used; - __le16 vlans_free; - __le32 addr_high; - __le32 addr_low; + u8 reserved[4]; + __le16 vlans_used; + __le16 vlans_free; + __le32 addr_high; + __le32 addr_low; }; /* Set VSI Promiscuous Modes (direct 0x0254) */ struct i40e_aqc_set_vsi_promiscuous_modes { - __le16 promiscuous_flags; - __le16 valid_flags; + __le16 promiscuous_flags; + __le16 valid_flags; /* flags used for both fields above */ -#define I40E_AQC_SET_VSI_PROMISC_UNICAST 0x01 -#define I40E_AQC_SET_VSI_PROMISC_MULTICAST 0x02 -#define I40E_AQC_SET_VSI_PROMISC_BROADCAST 0x04 -#define I40E_AQC_SET_VSI_DEFAULT 0x08 -#define I40E_AQC_SET_VSI_PROMISC_VLAN 0x10 - __le16 seid; -#define I40E_AQC_VSI_PROM_CMD_SEID_MASK 0x3FF - __le16 vlan_tag; -#define I40E_AQC_SET_VSI_VLAN_VALID 0x8000 - u8 reserved[8]; +#define I40E_AQC_SET_VSI_PROMISC_UNICAST 0x01 +#define I40E_AQC_SET_VSI_PROMISC_MULTICAST 0x02 +#define I40E_AQC_SET_VSI_PROMISC_BROADCAST 0x04 +#define I40E_AQC_SET_VSI_DEFAULT 0x08 +#define I40E_AQC_SET_VSI_PROMISC_VLAN 0x10 + __le16 seid; +#define I40E_AQC_VSI_PROM_CMD_SEID_MASK 0x3FF + __le16 vlan_tag; +#define I40E_AQC_SET_VSI_VLAN_VALID 0x8000 + u8 reserved[8]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_set_vsi_promiscuous_modes); @@ -1059,23 +1059,23 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_set_vsi_promiscuous_modes); * Uses generic i40e_aqc_add_remove_tag_completion for completion */ struct i40e_aqc_add_tag { - __le16 flags; -#define I40E_AQC_ADD_TAG_FLAG_TO_QUEUE 0x0001 - __le16 seid; -#define I40E_AQC_ADD_TAG_CMD_SEID_NUM_SHIFT 0 -#define I40E_AQC_ADD_TAG_CMD_SEID_NUM_MASK (0x3FF << \ + __le16 flags; +#define I40E_AQC_ADD_TAG_FLAG_TO_QUEUE 0x0001 + __le16 seid; +#define I40E_AQC_ADD_TAG_CMD_SEID_NUM_SHIFT 0 +#define I40E_AQC_ADD_TAG_CMD_SEID_NUM_MASK (0x3FF << \ I40E_AQC_ADD_TAG_CMD_SEID_NUM_SHIFT) - __le16 tag; - __le16 queue_number; - u8 reserved[8]; + __le16 tag; + __le16 queue_number; + u8 reserved[8]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_tag); struct i40e_aqc_add_remove_tag_completion { - u8 reserved[12]; - __le16 tags_used; - __le16 tags_free; + u8 reserved[12]; + __le16 tags_used; + __le16 tags_free; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_tag_completion); @@ -1084,12 +1084,12 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_tag_completion); * Uses generic i40e_aqc_add_remove_tag_completion for completion */ struct i40e_aqc_remove_tag { - __le16 seid; -#define I40E_AQC_REMOVE_TAG_CMD_SEID_NUM_SHIFT 0 -#define I40E_AQC_REMOVE_TAG_CMD_SEID_NUM_MASK (0x3FF << \ + __le16 seid; +#define I40E_AQC_REMOVE_TAG_CMD_SEID_NUM_SHIFT 0 +#define I40E_AQC_REMOVE_TAG_CMD_SEID_NUM_MASK (0x3FF << \ I40E_AQC_REMOVE_TAG_CMD_SEID_NUM_SHIFT) - __le16 tag; - u8 reserved[12]; + __le16 tag; + u8 reserved[12]; }; /* Add multicast E-Tag (direct 0x0257) @@ -1097,22 +1097,22 @@ struct i40e_aqc_remove_tag { * and no external data */ struct i40e_aqc_add_remove_mcast_etag { - __le16 pv_seid; - __le16 etag; - u8 num_unicast_etags; - u8 reserved[3]; - __le32 addr_high; /* address of array of 2-byte s-tags */ - __le32 addr_low; + __le16 pv_seid; + __le16 etag; + u8 num_unicast_etags; + u8 reserved[3]; + __le32 addr_high; /* address of array of 2-byte s-tags */ + __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_mcast_etag); struct i40e_aqc_add_remove_mcast_etag_completion { - u8 reserved[4]; - __le16 mcast_etags_used; - __le16 mcast_etags_free; - __le32 addr_high; - __le32 addr_low; + u8 reserved[4]; + __le16 mcast_etags_used; + __le16 mcast_etags_free; + __le32 addr_high; + __le32 addr_low; }; @@ -1120,21 +1120,21 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_mcast_etag_completion); /* Update S/E-Tag (direct 0x0259) */ struct i40e_aqc_update_tag { - __le16 seid; -#define I40E_AQC_UPDATE_TAG_CMD_SEID_NUM_SHIFT 0 -#define I40E_AQC_UPDATE_TAG_CMD_SEID_NUM_MASK (0x3FF << \ + __le16 seid; +#define I40E_AQC_UPDATE_TAG_CMD_SEID_NUM_SHIFT 0 +#define I40E_AQC_UPDATE_TAG_CMD_SEID_NUM_MASK (0x3FF << \ I40E_AQC_UPDATE_TAG_CMD_SEID_NUM_SHIFT) - __le16 old_tag; - __le16 new_tag; - u8 reserved[10]; + __le16 old_tag; + __le16 new_tag; + u8 reserved[10]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_update_tag); struct i40e_aqc_update_tag_completion { - u8 reserved[12]; - __le16 tags_used; - __le16 tags_free; + u8 reserved[12]; + __le16 tags_used; + __le16 tags_free; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_update_tag_completion); @@ -1145,30 +1145,30 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_update_tag_completion); * and the generic direct completion structure */ struct i40e_aqc_add_remove_control_packet_filter { - u8 mac[6]; - __le16 etype; - __le16 flags; -#define I40E_AQC_ADD_CONTROL_PACKET_FLAGS_IGNORE_MAC 0x0001 -#define I40E_AQC_ADD_CONTROL_PACKET_FLAGS_DROP 0x0002 -#define I40E_AQC_ADD_CONTROL_PACKET_FLAGS_TO_QUEUE 0x0004 -#define I40E_AQC_ADD_CONTROL_PACKET_FLAGS_TX 0x0008 -#define I40E_AQC_ADD_CONTROL_PACKET_FLAGS_RX 0x0000 - __le16 seid; -#define I40E_AQC_ADD_CONTROL_PACKET_CMD_SEID_NUM_SHIFT 0 -#define I40E_AQC_ADD_CONTROL_PACKET_CMD_SEID_NUM_MASK (0x3FF << \ + u8 mac[6]; + __le16 etype; + __le16 flags; +#define I40E_AQC_ADD_CONTROL_PACKET_FLAGS_IGNORE_MAC 0x0001 +#define I40E_AQC_ADD_CONTROL_PACKET_FLAGS_DROP 0x0002 +#define I40E_AQC_ADD_CONTROL_PACKET_FLAGS_TO_QUEUE 0x0004 +#define I40E_AQC_ADD_CONTROL_PACKET_FLAGS_TX 0x0008 +#define I40E_AQC_ADD_CONTROL_PACKET_FLAGS_RX 0x0000 + __le16 seid; +#define I40E_AQC_ADD_CONTROL_PACKET_CMD_SEID_NUM_SHIFT 0 +#define I40E_AQC_ADD_CONTROL_PACKET_CMD_SEID_NUM_MASK (0x3FF << \ I40E_AQC_ADD_CONTROL_PACKET_CMD_SEID_NUM_SHIFT) - __le16 queue; - u8 reserved[2]; + __le16 queue; + u8 reserved[2]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_control_packet_filter); struct i40e_aqc_add_remove_control_packet_filter_completion { - __le16 mac_etype_used; - __le16 etype_used; - __le16 mac_etype_free; - __le16 etype_free; - u8 reserved[8]; + __le16 mac_etype_used; + __le16 etype_used; + __le16 mac_etype_free; + __le16 etype_free; + u8 reserved[8]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_control_packet_filter_completion); @@ -1179,23 +1179,23 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_control_packet_filter_completion); * and the generic indirect completion structure */ struct i40e_aqc_add_remove_cloud_filters { - u8 num_filters; - u8 reserved; - __le16 seid; -#define I40E_AQC_ADD_CLOUD_CMD_SEID_NUM_SHIFT 0 -#define I40E_AQC_ADD_CLOUD_CMD_SEID_NUM_MASK (0x3FF << \ + u8 num_filters; + u8 reserved; + __le16 seid; +#define I40E_AQC_ADD_CLOUD_CMD_SEID_NUM_SHIFT 0 +#define I40E_AQC_ADD_CLOUD_CMD_SEID_NUM_MASK (0x3FF << \ I40E_AQC_ADD_CLOUD_CMD_SEID_NUM_SHIFT) - u8 reserved2[4]; - __le32 addr_high; - __le32 addr_low; + u8 reserved2[4]; + __le32 addr_high; + __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_cloud_filters); struct i40e_aqc_add_remove_cloud_filters_element_data { - u8 outer_mac[6]; - u8 inner_mac[6]; - __le16 inner_vlan; + u8 outer_mac[6]; + u8 inner_mac[6]; + __le16 inner_vlan; union { struct { u8 reserved[12]; @@ -1205,49 +1205,49 @@ struct i40e_aqc_add_remove_cloud_filters_element_data { u8 data[16]; } v6; } ipaddr; - __le16 flags; -#define I40E_AQC_ADD_CLOUD_FILTER_SHIFT 0 -#define I40E_AQC_ADD_CLOUD_FILTER_MASK (0x3F << \ + __le16 flags; +#define I40E_AQC_ADD_CLOUD_FILTER_SHIFT 0 +#define I40E_AQC_ADD_CLOUD_FILTER_MASK (0x3F << \ I40E_AQC_ADD_CLOUD_FILTER_SHIFT) /* 0x0000 reserved */ -#define I40E_AQC_ADD_CLOUD_FILTER_OIP 0x0001 +#define I40E_AQC_ADD_CLOUD_FILTER_OIP 0x0001 /* 0x0002 reserved */ -#define I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN 0x0003 -#define I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN_TEN_ID 0x0004 +#define I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN 0x0003 +#define I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN_TEN_ID 0x0004 /* 0x0005 reserved */ -#define I40E_AQC_ADD_CLOUD_FILTER_IMAC_TEN_ID 0x0006 +#define I40E_AQC_ADD_CLOUD_FILTER_IMAC_TEN_ID 0x0006 /* 0x0007 reserved */ /* 0x0008 reserved */ -#define I40E_AQC_ADD_CLOUD_FILTER_OMAC 0x0009 -#define I40E_AQC_ADD_CLOUD_FILTER_IMAC 0x000A -#define I40E_AQC_ADD_CLOUD_FILTER_OMAC_TEN_ID_IMAC 0x000B -#define I40E_AQC_ADD_CLOUD_FILTER_IIP 0x000C - -#define I40E_AQC_ADD_CLOUD_FLAGS_TO_QUEUE 0x0080 -#define I40E_AQC_ADD_CLOUD_VNK_SHIFT 6 -#define I40E_AQC_ADD_CLOUD_VNK_MASK 0x00C0 -#define I40E_AQC_ADD_CLOUD_FLAGS_IPV4 0 -#define I40E_AQC_ADD_CLOUD_FLAGS_IPV6 0x0100 - -#define I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT 9 -#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MASK 0x1E00 -#define I40E_AQC_ADD_CLOUD_TNL_TYPE_XVLAN 0 -#define I40E_AQC_ADD_CLOUD_TNL_TYPE_NVGRE_OMAC 1 -#define I40E_AQC_ADD_CLOUD_TNL_TYPE_NGE 2 -#define I40E_AQC_ADD_CLOUD_TNL_TYPE_IP 3 - - __le32 tenant_id; - u8 reserved[4]; - __le16 queue_number; -#define I40E_AQC_ADD_CLOUD_QUEUE_SHIFT 0 -#define I40E_AQC_ADD_CLOUD_QUEUE_MASK (0x3F << \ - I40E_AQC_ADD_CLOUD_QUEUE_SHIFT) - u8 reserved2[14]; +#define I40E_AQC_ADD_CLOUD_FILTER_OMAC 0x0009 +#define I40E_AQC_ADD_CLOUD_FILTER_IMAC 0x000A +#define I40E_AQC_ADD_CLOUD_FILTER_OMAC_TEN_ID_IMAC 0x000B +#define I40E_AQC_ADD_CLOUD_FILTER_IIP 0x000C + +#define I40E_AQC_ADD_CLOUD_FLAGS_TO_QUEUE 0x0080 +#define I40E_AQC_ADD_CLOUD_VNK_SHIFT 6 +#define I40E_AQC_ADD_CLOUD_VNK_MASK 0x00C0 +#define I40E_AQC_ADD_CLOUD_FLAGS_IPV4 0 +#define I40E_AQC_ADD_CLOUD_FLAGS_IPV6 0x0100 + +#define I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT 9 +#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MASK 0x1E00 +#define I40E_AQC_ADD_CLOUD_TNL_TYPE_XVLAN 0 +#define I40E_AQC_ADD_CLOUD_TNL_TYPE_NVGRE_OMAC 1 +#define I40E_AQC_ADD_CLOUD_TNL_TYPE_NGE 2 +#define I40E_AQC_ADD_CLOUD_TNL_TYPE_IP 3 + + __le32 tenant_id; + u8 reserved[4]; + __le16 queue_number; +#define I40E_AQC_ADD_CLOUD_QUEUE_SHIFT 0 +#define I40E_AQC_ADD_CLOUD_QUEUE_MASK (0x3F << \ + I40E_AQC_ADD_CLOUD_QUEUE_SHIFT) + u8 reserved2[14]; /* response section */ - u8 allocation_result; -#define I40E_AQC_ADD_CLOUD_FILTER_SUCCESS 0x0 -#define I40E_AQC_ADD_CLOUD_FILTER_FAIL 0xFF - u8 response_reserved[7]; + u8 allocation_result; +#define I40E_AQC_ADD_CLOUD_FILTER_SUCCESS 0x0 +#define I40E_AQC_ADD_CLOUD_FILTER_FAIL 0xFF + u8 response_reserved[7]; }; struct i40e_aqc_remove_cloud_filters_completion { @@ -1269,14 +1269,14 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_remove_cloud_filters_completion); struct i40e_aqc_add_delete_mirror_rule { __le16 seid; __le16 rule_type; -#define I40E_AQC_MIRROR_RULE_TYPE_SHIFT 0 -#define I40E_AQC_MIRROR_RULE_TYPE_MASK (0x7 << \ +#define I40E_AQC_MIRROR_RULE_TYPE_SHIFT 0 +#define I40E_AQC_MIRROR_RULE_TYPE_MASK (0x7 << \ I40E_AQC_MIRROR_RULE_TYPE_SHIFT) -#define I40E_AQC_MIRROR_RULE_TYPE_VPORT_INGRESS 1 -#define I40E_AQC_MIRROR_RULE_TYPE_VPORT_EGRESS 2 -#define I40E_AQC_MIRROR_RULE_TYPE_VLAN 3 -#define I40E_AQC_MIRROR_RULE_TYPE_ALL_INGRESS 4 -#define I40E_AQC_MIRROR_RULE_TYPE_ALL_EGRESS 5 +#define I40E_AQC_MIRROR_RULE_TYPE_VPORT_INGRESS 1 +#define I40E_AQC_MIRROR_RULE_TYPE_VPORT_EGRESS 2 +#define I40E_AQC_MIRROR_RULE_TYPE_VLAN 3 +#define I40E_AQC_MIRROR_RULE_TYPE_ALL_INGRESS 4 +#define I40E_AQC_MIRROR_RULE_TYPE_ALL_EGRESS 5 __le16 num_entries; __le16 destination; /* VSI for add, rule id for delete */ __le32 addr_high; /* address of array of 2-byte VSI or VLAN ids */ @@ -1286,12 +1286,12 @@ struct i40e_aqc_add_delete_mirror_rule { I40E_CHECK_CMD_LENGTH(i40e_aqc_add_delete_mirror_rule); struct i40e_aqc_add_delete_mirror_rule_completion { - u8 reserved[2]; - __le16 rule_id; /* only used on add */ - __le16 mirror_rules_used; - __le16 mirror_rules_free; - __le32 addr_high; - __le32 addr_low; + u8 reserved[2]; + __le16 rule_id; /* only used on add */ + __le16 mirror_rules_used; + __le16 mirror_rules_free; + __le32 addr_high; + __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_delete_mirror_rule_completion); @@ -1302,11 +1302,11 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_add_delete_mirror_rule_completion); * the command and response use the same descriptor structure */ struct i40e_aqc_pfc_ignore { - u8 tc_bitmap; - u8 command_flags; /* unused on response */ -#define I40E_AQC_PFC_IGNORE_SET 0x80 -#define I40E_AQC_PFC_IGNORE_CLEAR 0x0 - u8 reserved[14]; + u8 tc_bitmap; + u8 command_flags; /* unused on response */ +#define I40E_AQC_PFC_IGNORE_SET 0x80 +#define I40E_AQC_PFC_IGNORE_CLEAR 0x0 + u8 reserved[14]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_pfc_ignore); @@ -1321,10 +1321,10 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_pfc_ignore); * this generic struct to pass the SEID in param0 */ struct i40e_aqc_tx_sched_ind { - __le16 vsi_seid; - u8 reserved[6]; - __le32 addr_high; - __le32 addr_low; + __le16 vsi_seid; + u8 reserved[6]; + __le32 addr_high; + __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_tx_sched_ind); @@ -1336,12 +1336,12 @@ struct i40e_aqc_qs_handles_resp { /* Configure VSI BW limits (direct 0x0400) */ struct i40e_aqc_configure_vsi_bw_limit { - __le16 vsi_seid; - u8 reserved[2]; - __le16 credit; - u8 reserved1[2]; - u8 max_credit; /* 0-3, limit = 2^max */ - u8 reserved2[7]; + __le16 vsi_seid; + u8 reserved[2]; + __le16 credit; + u8 reserved1[2]; + u8 max_credit; /* 0-3, limit = 2^max */ + u8 reserved2[7]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_configure_vsi_bw_limit); @@ -1350,58 +1350,58 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_configure_vsi_bw_limit); * responds with i40e_aqc_qs_handles_resp */ struct i40e_aqc_configure_vsi_ets_sla_bw_data { - u8 tc_valid_bits; - u8 reserved[15]; - __le16 tc_bw_credits[8]; /* FW writesback QS handles here */ + u8 tc_valid_bits; + u8 reserved[15]; + __le16 tc_bw_credits[8]; /* FW writesback QS handles here */ /* 4 bits per tc 0-7, 4th bit is reserved, limit = 2^max */ - __le16 tc_bw_max[2]; - u8 reserved1[28]; + __le16 tc_bw_max[2]; + u8 reserved1[28]; }; /* Configure VSI Bandwidth Allocation per Traffic Type (indirect 0x0407) * responds with i40e_aqc_qs_handles_resp */ struct i40e_aqc_configure_vsi_tc_bw_data { - u8 tc_valid_bits; - u8 reserved[3]; - u8 tc_bw_credits[8]; - u8 reserved1[4]; - __le16 qs_handles[8]; + u8 tc_valid_bits; + u8 reserved[3]; + u8 tc_bw_credits[8]; + u8 reserved1[4]; + __le16 qs_handles[8]; }; /* Query vsi bw configuration (indirect 0x0408) */ struct i40e_aqc_query_vsi_bw_config_resp { - u8 tc_valid_bits; - u8 tc_suspended_bits; - u8 reserved[14]; - __le16 qs_handles[8]; - u8 reserved1[4]; - __le16 port_bw_limit; - u8 reserved2[2]; - u8 max_bw; /* 0-3, limit = 2^max */ - u8 reserved3[23]; + u8 tc_valid_bits; + u8 tc_suspended_bits; + u8 reserved[14]; + __le16 qs_handles[8]; + u8 reserved1[4]; + __le16 port_bw_limit; + u8 reserved2[2]; + u8 max_bw; /* 0-3, limit = 2^max */ + u8 reserved3[23]; }; /* Query VSI Bandwidth Allocation per Traffic Type (indirect 0x040A) */ struct i40e_aqc_query_vsi_ets_sla_config_resp { - u8 tc_valid_bits; - u8 reserved[3]; - u8 share_credits[8]; - __le16 credits[8]; + u8 tc_valid_bits; + u8 reserved[3]; + u8 share_credits[8]; + __le16 credits[8]; /* 4 bits per tc 0-7, 4th bit is reserved, limit = 2^max */ - __le16 tc_bw_max[2]; + __le16 tc_bw_max[2]; }; /* Configure Switching Component Bandwidth Limit (direct 0x0410) */ struct i40e_aqc_configure_switching_comp_bw_limit { - __le16 seid; - u8 reserved[2]; - __le16 credit; - u8 reserved1[2]; - u8 max_bw; /* 0-3, limit = 2^max */ - u8 reserved2[7]; + __le16 seid; + u8 reserved[2]; + __le16 credit; + u8 reserved1[2]; + u8 max_bw; /* 0-3, limit = 2^max */ + u8 reserved2[7]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_configure_switching_comp_bw_limit); @@ -1411,75 +1411,75 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_configure_switching_comp_bw_limit); * Disable Physical Port ETS (indirect 0x0415) */ struct i40e_aqc_configure_switching_comp_ets_data { - u8 reserved[4]; - u8 tc_valid_bits; - u8 seepage; -#define I40E_AQ_ETS_SEEPAGE_EN_MASK 0x1 - u8 tc_strict_priority_flags; - u8 reserved1[17]; - u8 tc_bw_share_credits[8]; - u8 reserved2[96]; + u8 reserved[4]; + u8 tc_valid_bits; + u8 seepage; +#define I40E_AQ_ETS_SEEPAGE_EN_MASK 0x1 + u8 tc_strict_priority_flags; + u8 reserved1[17]; + u8 tc_bw_share_credits[8]; + u8 reserved2[96]; }; /* Configure Switching Component Bandwidth Limits per Tc (indirect 0x0416) */ struct i40e_aqc_configure_switching_comp_ets_bw_limit_data { - u8 tc_valid_bits; - u8 reserved[15]; - __le16 tc_bw_credit[8]; + u8 tc_valid_bits; + u8 reserved[15]; + __le16 tc_bw_credit[8]; /* 4 bits per tc 0-7, 4th bit is reserved, limit = 2^max */ - __le16 tc_bw_max[2]; - u8 reserved1[28]; + __le16 tc_bw_max[2]; + u8 reserved1[28]; }; /* Configure Switching Component Bandwidth Allocation per Tc * (indirect 0x0417) */ struct i40e_aqc_configure_switching_comp_bw_config_data { - u8 tc_valid_bits; - u8 reserved[2]; - u8 absolute_credits; /* bool */ - u8 tc_bw_share_credits[8]; - u8 reserved1[20]; + u8 tc_valid_bits; + u8 reserved[2]; + u8 absolute_credits; /* bool */ + u8 tc_bw_share_credits[8]; + u8 reserved1[20]; }; /* Query Switching Component Configuration (indirect 0x0418) */ struct i40e_aqc_query_switching_comp_ets_config_resp { - u8 tc_valid_bits; - u8 reserved[35]; - __le16 port_bw_limit; - u8 reserved1[2]; - u8 tc_bw_max; /* 0-3, limit = 2^max */ - u8 reserved2[23]; + u8 tc_valid_bits; + u8 reserved[35]; + __le16 port_bw_limit; + u8 reserved1[2]; + u8 tc_bw_max; /* 0-3, limit = 2^max */ + u8 reserved2[23]; }; /* Query PhysicalPort ETS Configuration (indirect 0x0419) */ struct i40e_aqc_query_port_ets_config_resp { - u8 reserved[4]; - u8 tc_valid_bits; - u8 reserved1; - u8 tc_strict_priority_bits; - u8 reserved2; - u8 tc_bw_share_credits[8]; - __le16 tc_bw_limits[8]; + u8 reserved[4]; + u8 tc_valid_bits; + u8 reserved1; + u8 tc_strict_priority_bits; + u8 reserved2; + u8 tc_bw_share_credits[8]; + __le16 tc_bw_limits[8]; /* 4 bits per tc 0-7, 4th bit reserved, limit = 2^max */ - __le16 tc_bw_max[2]; - u8 reserved3[32]; + __le16 tc_bw_max[2]; + u8 reserved3[32]; }; /* Query Switching Component Bandwidth Allocation per Traffic Type * (indirect 0x041A) */ struct i40e_aqc_query_switching_comp_bw_config_resp { - u8 tc_valid_bits; - u8 reserved[2]; - u8 absolute_credits_enable; /* bool */ - u8 tc_bw_share_credits[8]; - __le16 tc_bw_limits[8]; + u8 tc_valid_bits; + u8 reserved[2]; + u8 absolute_credits_enable; /* bool */ + u8 tc_bw_share_credits[8]; + __le16 tc_bw_limits[8]; /* 4 bits per tc 0-7, 4th bit is reserved, limit = 2^max */ - __le16 tc_bw_max[2]; + __le16 tc_bw_max[2]; }; /* Suspend/resume port TX traffic @@ -1490,37 +1490,37 @@ struct i40e_aqc_query_switching_comp_bw_config_resp { * (indirect 0x041D) */ struct i40e_aqc_configure_partition_bw_data { - __le16 pf_valid_bits; - u8 min_bw[16]; /* guaranteed bandwidth */ - u8 max_bw[16]; /* bandwidth limit */ + __le16 pf_valid_bits; + u8 min_bw[16]; /* guaranteed bandwidth */ + u8 max_bw[16]; /* bandwidth limit */ }; /* Get and set the active HMC resource profile and status. * (direct 0x0500) and (direct 0x0501) */ struct i40e_aq_get_set_hmc_resource_profile { - u8 pm_profile; - u8 pe_vf_enabled; - u8 reserved[14]; + u8 pm_profile; + u8 pe_vf_enabled; + u8 reserved[14]; }; I40E_CHECK_CMD_LENGTH(i40e_aq_get_set_hmc_resource_profile); enum i40e_aq_hmc_profile { /* I40E_HMC_PROFILE_NO_CHANGE = 0, reserved */ - I40E_HMC_PROFILE_DEFAULT = 1, - I40E_HMC_PROFILE_FAVOR_VF = 2, - I40E_HMC_PROFILE_EQUAL = 3, + I40E_HMC_PROFILE_DEFAULT = 1, + I40E_HMC_PROFILE_FAVOR_VF = 2, + I40E_HMC_PROFILE_EQUAL = 3, }; -#define I40E_AQ_GET_HMC_RESOURCE_PROFILE_PM_MASK 0xF -#define I40E_AQ_GET_HMC_RESOURCE_PROFILE_COUNT_MASK 0x3F +#define I40E_AQ_GET_HMC_RESOURCE_PROFILE_PM_MASK 0xF +#define I40E_AQ_GET_HMC_RESOURCE_PROFILE_COUNT_MASK 0x3F /* Get PHY Abilities (indirect 0x0600) uses the generic indirect struct */ /* set in param0 for get phy abilities to report qualified modules */ -#define I40E_AQ_PHY_REPORT_QUALIFIED_MODULES 0x0001 -#define I40E_AQ_PHY_REPORT_INITIAL_VALUES 0x0002 +#define I40E_AQ_PHY_REPORT_QUALIFIED_MODULES 0x0001 +#define I40E_AQ_PHY_REPORT_INITIAL_VALUES 0x0002 enum i40e_aq_phy_type { I40E_PHY_TYPE_SGMII = 0x0, @@ -1578,147 +1578,147 @@ struct i40e_aqc_module_desc { }; struct i40e_aq_get_phy_abilities_resp { - __le32 phy_type; /* bitmap using the above enum for offsets */ - u8 link_speed; /* bitmap using the above enum bit patterns */ - u8 abilities; -#define I40E_AQ_PHY_FLAG_PAUSE_TX 0x01 -#define I40E_AQ_PHY_FLAG_PAUSE_RX 0x02 -#define I40E_AQ_PHY_FLAG_LOW_POWER 0x04 -#define I40E_AQ_PHY_LINK_ENABLED 0x08 -#define I40E_AQ_PHY_AN_ENABLED 0x10 -#define I40E_AQ_PHY_FLAG_MODULE_QUAL 0x20 - __le16 eee_capability; -#define I40E_AQ_EEE_100BASE_TX 0x0002 -#define I40E_AQ_EEE_1000BASE_T 0x0004 -#define I40E_AQ_EEE_10GBASE_T 0x0008 -#define I40E_AQ_EEE_1000BASE_KX 0x0010 -#define I40E_AQ_EEE_10GBASE_KX4 0x0020 -#define I40E_AQ_EEE_10GBASE_KR 0x0040 - __le32 eeer_val; - u8 d3_lpan; -#define I40E_AQ_SET_PHY_D3_LPAN_ENA 0x01 - u8 reserved[3]; - u8 phy_id[4]; - u8 module_type[3]; - u8 qualified_module_count; -#define I40E_AQ_PHY_MAX_QMS 16 - struct i40e_aqc_module_desc qualified_module[I40E_AQ_PHY_MAX_QMS]; + __le32 phy_type; /* bitmap using the above enum for offsets */ + u8 link_speed; /* bitmap using the above enum bit patterns */ + u8 abilities; +#define I40E_AQ_PHY_FLAG_PAUSE_TX 0x01 +#define I40E_AQ_PHY_FLAG_PAUSE_RX 0x02 +#define I40E_AQ_PHY_FLAG_LOW_POWER 0x04 +#define I40E_AQ_PHY_LINK_ENABLED 0x08 +#define I40E_AQ_PHY_AN_ENABLED 0x10 +#define I40E_AQ_PHY_FLAG_MODULE_QUAL 0x20 + __le16 eee_capability; +#define I40E_AQ_EEE_100BASE_TX 0x0002 +#define I40E_AQ_EEE_1000BASE_T 0x0004 +#define I40E_AQ_EEE_10GBASE_T 0x0008 +#define I40E_AQ_EEE_1000BASE_KX 0x0010 +#define I40E_AQ_EEE_10GBASE_KX4 0x0020 +#define I40E_AQ_EEE_10GBASE_KR 0x0040 + __le32 eeer_val; + u8 d3_lpan; +#define I40E_AQ_SET_PHY_D3_LPAN_ENA 0x01 + u8 reserved[3]; + u8 phy_id[4]; + u8 module_type[3]; + u8 qualified_module_count; +#define I40E_AQ_PHY_MAX_QMS 16 + struct i40e_aqc_module_desc qualified_module[I40E_AQ_PHY_MAX_QMS]; }; /* Set PHY Config (direct 0x0601) */ struct i40e_aq_set_phy_config { /* same bits as above in all */ - __le32 phy_type; - u8 link_speed; - u8 abilities; + __le32 phy_type; + u8 link_speed; + u8 abilities; /* bits 0-2 use the values from get_phy_abilities_resp */ #define I40E_AQ_PHY_ENABLE_LINK 0x08 #define I40E_AQ_PHY_ENABLE_AN 0x10 #define I40E_AQ_PHY_ENABLE_ATOMIC_LINK 0x20 - __le16 eee_capability; - __le32 eeer; - u8 low_power_ctrl; - u8 reserved[3]; + __le16 eee_capability; + __le32 eeer; + u8 low_power_ctrl; + u8 reserved[3]; }; I40E_CHECK_CMD_LENGTH(i40e_aq_set_phy_config); /* Set MAC Config command data structure (direct 0x0603) */ struct i40e_aq_set_mac_config { - __le16 max_frame_size; - u8 params; -#define I40E_AQ_SET_MAC_CONFIG_CRC_EN 0x04 -#define I40E_AQ_SET_MAC_CONFIG_PACING_MASK 0x78 -#define I40E_AQ_SET_MAC_CONFIG_PACING_SHIFT 3 -#define I40E_AQ_SET_MAC_CONFIG_PACING_NONE 0x0 -#define I40E_AQ_SET_MAC_CONFIG_PACING_1B_13TX 0xF -#define I40E_AQ_SET_MAC_CONFIG_PACING_1DW_9TX 0x9 -#define I40E_AQ_SET_MAC_CONFIG_PACING_1DW_4TX 0x8 -#define I40E_AQ_SET_MAC_CONFIG_PACING_3DW_7TX 0x7 -#define I40E_AQ_SET_MAC_CONFIG_PACING_2DW_3TX 0x6 -#define I40E_AQ_SET_MAC_CONFIG_PACING_1DW_1TX 0x5 -#define I40E_AQ_SET_MAC_CONFIG_PACING_3DW_2TX 0x4 -#define I40E_AQ_SET_MAC_CONFIG_PACING_7DW_3TX 0x3 -#define I40E_AQ_SET_MAC_CONFIG_PACING_4DW_1TX 0x2 -#define I40E_AQ_SET_MAC_CONFIG_PACING_9DW_1TX 0x1 - u8 tx_timer_priority; /* bitmap */ - __le16 tx_timer_value; - __le16 fc_refresh_threshold; - u8 reserved[8]; + __le16 max_frame_size; + u8 params; +#define I40E_AQ_SET_MAC_CONFIG_CRC_EN 0x04 +#define I40E_AQ_SET_MAC_CONFIG_PACING_MASK 0x78 +#define I40E_AQ_SET_MAC_CONFIG_PACING_SHIFT 3 +#define I40E_AQ_SET_MAC_CONFIG_PACING_NONE 0x0 +#define I40E_AQ_SET_MAC_CONFIG_PACING_1B_13TX 0xF +#define I40E_AQ_SET_MAC_CONFIG_PACING_1DW_9TX 0x9 +#define I40E_AQ_SET_MAC_CONFIG_PACING_1DW_4TX 0x8 +#define I40E_AQ_SET_MAC_CONFIG_PACING_3DW_7TX 0x7 +#define I40E_AQ_SET_MAC_CONFIG_PACING_2DW_3TX 0x6 +#define I40E_AQ_SET_MAC_CONFIG_PACING_1DW_1TX 0x5 +#define I40E_AQ_SET_MAC_CONFIG_PACING_3DW_2TX 0x4 +#define I40E_AQ_SET_MAC_CONFIG_PACING_7DW_3TX 0x3 +#define I40E_AQ_SET_MAC_CONFIG_PACING_4DW_1TX 0x2 +#define I40E_AQ_SET_MAC_CONFIG_PACING_9DW_1TX 0x1 + u8 tx_timer_priority; /* bitmap */ + __le16 tx_timer_value; + __le16 fc_refresh_threshold; + u8 reserved[8]; }; I40E_CHECK_CMD_LENGTH(i40e_aq_set_mac_config); /* Restart Auto-Negotiation (direct 0x605) */ struct i40e_aqc_set_link_restart_an { - u8 command; -#define I40E_AQ_PHY_RESTART_AN 0x02 -#define I40E_AQ_PHY_LINK_ENABLE 0x04 - u8 reserved[15]; + u8 command; +#define I40E_AQ_PHY_RESTART_AN 0x02 +#define I40E_AQ_PHY_LINK_ENABLE 0x04 + u8 reserved[15]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_set_link_restart_an); /* Get Link Status cmd & response data structure (direct 0x0607) */ struct i40e_aqc_get_link_status { - __le16 command_flags; /* only field set on command */ -#define I40E_AQ_LSE_MASK 0x3 -#define I40E_AQ_LSE_NOP 0x0 -#define I40E_AQ_LSE_DISABLE 0x2 -#define I40E_AQ_LSE_ENABLE 0x3 + __le16 command_flags; /* only field set on command */ +#define I40E_AQ_LSE_MASK 0x3 +#define I40E_AQ_LSE_NOP 0x0 +#define I40E_AQ_LSE_DISABLE 0x2 +#define I40E_AQ_LSE_ENABLE 0x3 /* only response uses this flag */ -#define I40E_AQ_LSE_IS_ENABLED 0x1 - u8 phy_type; /* i40e_aq_phy_type */ - u8 link_speed; /* i40e_aq_link_speed */ - u8 link_info; -#define I40E_AQ_LINK_UP 0x01 -#define I40E_AQ_LINK_FAULT 0x02 -#define I40E_AQ_LINK_FAULT_TX 0x04 -#define I40E_AQ_LINK_FAULT_RX 0x08 -#define I40E_AQ_LINK_FAULT_REMOTE 0x10 -#define I40E_AQ_MEDIA_AVAILABLE 0x40 -#define I40E_AQ_SIGNAL_DETECT 0x80 - u8 an_info; -#define I40E_AQ_AN_COMPLETED 0x01 -#define I40E_AQ_LP_AN_ABILITY 0x02 -#define I40E_AQ_PD_FAULT 0x04 -#define I40E_AQ_FEC_EN 0x08 -#define I40E_AQ_PHY_LOW_POWER 0x10 -#define I40E_AQ_LINK_PAUSE_TX 0x20 -#define I40E_AQ_LINK_PAUSE_RX 0x40 -#define I40E_AQ_QUALIFIED_MODULE 0x80 - u8 ext_info; -#define I40E_AQ_LINK_PHY_TEMP_ALARM 0x01 -#define I40E_AQ_LINK_XCESSIVE_ERRORS 0x02 -#define I40E_AQ_LINK_TX_SHIFT 0x02 -#define I40E_AQ_LINK_TX_MASK (0x03 << I40E_AQ_LINK_TX_SHIFT) -#define I40E_AQ_LINK_TX_ACTIVE 0x00 -#define I40E_AQ_LINK_TX_DRAINED 0x01 -#define I40E_AQ_LINK_TX_FLUSHED 0x03 -#define I40E_AQ_LINK_FORCED_40G 0x10 - u8 loopback; /* use defines from i40e_aqc_set_lb_mode */ - __le16 max_frame_size; - u8 config; -#define I40E_AQ_CONFIG_CRC_ENA 0x04 -#define I40E_AQ_CONFIG_PACING_MASK 0x78 - u8 reserved[5]; +#define I40E_AQ_LSE_IS_ENABLED 0x1 + u8 phy_type; /* i40e_aq_phy_type */ + u8 link_speed; /* i40e_aq_link_speed */ + u8 link_info; +#define I40E_AQ_LINK_UP 0x01 +#define I40E_AQ_LINK_FAULT 0x02 +#define I40E_AQ_LINK_FAULT_TX 0x04 +#define I40E_AQ_LINK_FAULT_RX 0x08 +#define I40E_AQ_LINK_FAULT_REMOTE 0x10 +#define I40E_AQ_MEDIA_AVAILABLE 0x40 +#define I40E_AQ_SIGNAL_DETECT 0x80 + u8 an_info; +#define I40E_AQ_AN_COMPLETED 0x01 +#define I40E_AQ_LP_AN_ABILITY 0x02 +#define I40E_AQ_PD_FAULT 0x04 +#define I40E_AQ_FEC_EN 0x08 +#define I40E_AQ_PHY_LOW_POWER 0x10 +#define I40E_AQ_LINK_PAUSE_TX 0x20 +#define I40E_AQ_LINK_PAUSE_RX 0x40 +#define I40E_AQ_QUALIFIED_MODULE 0x80 + u8 ext_info; +#define I40E_AQ_LINK_PHY_TEMP_ALARM 0x01 +#define I40E_AQ_LINK_XCESSIVE_ERRORS 0x02 +#define I40E_AQ_LINK_TX_SHIFT 0x02 +#define I40E_AQ_LINK_TX_MASK (0x03 << I40E_AQ_LINK_TX_SHIFT) +#define I40E_AQ_LINK_TX_ACTIVE 0x00 +#define I40E_AQ_LINK_TX_DRAINED 0x01 +#define I40E_AQ_LINK_TX_FLUSHED 0x03 +#define I40E_AQ_LINK_FORCED_40G 0x10 + u8 loopback; /* use defines from i40e_aqc_set_lb_mode */ + __le16 max_frame_size; + u8 config; +#define I40E_AQ_CONFIG_CRC_ENA 0x04 +#define I40E_AQ_CONFIG_PACING_MASK 0x78 + u8 reserved[5]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_get_link_status); /* Set event mask command (direct 0x613) */ struct i40e_aqc_set_phy_int_mask { - u8 reserved[8]; - __le16 event_mask; -#define I40E_AQ_EVENT_LINK_UPDOWN 0x0002 -#define I40E_AQ_EVENT_MEDIA_NA 0x0004 -#define I40E_AQ_EVENT_LINK_FAULT 0x0008 -#define I40E_AQ_EVENT_PHY_TEMP_ALARM 0x0010 -#define I40E_AQ_EVENT_EXCESSIVE_ERRORS 0x0020 -#define I40E_AQ_EVENT_SIGNAL_DETECT 0x0040 -#define I40E_AQ_EVENT_AN_COMPLETED 0x0080 -#define I40E_AQ_EVENT_MODULE_QUAL_FAIL 0x0100 -#define I40E_AQ_EVENT_PORT_TX_SUSPENDED 0x0200 - u8 reserved1[6]; + u8 reserved[8]; + __le16 event_mask; +#define I40E_AQ_EVENT_LINK_UPDOWN 0x0002 +#define I40E_AQ_EVENT_MEDIA_NA 0x0004 +#define I40E_AQ_EVENT_LINK_FAULT 0x0008 +#define I40E_AQ_EVENT_PHY_TEMP_ALARM 0x0010 +#define I40E_AQ_EVENT_EXCESSIVE_ERRORS 0x0020 +#define I40E_AQ_EVENT_SIGNAL_DETECT 0x0040 +#define I40E_AQ_EVENT_AN_COMPLETED 0x0080 +#define I40E_AQ_EVENT_MODULE_QUAL_FAIL 0x0100 +#define I40E_AQ_EVENT_PORT_TX_SUSPENDED 0x0200 + u8 reserved1[6]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_set_phy_int_mask); @@ -1728,27 +1728,27 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_set_phy_int_mask); * Get Link Partner AN advt register (direct 0x0616) */ struct i40e_aqc_an_advt_reg { - __le32 local_an_reg0; - __le16 local_an_reg1; - u8 reserved[10]; + __le32 local_an_reg0; + __le16 local_an_reg1; + u8 reserved[10]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_an_advt_reg); /* Set Loopback mode (0x0618) */ struct i40e_aqc_set_lb_mode { - __le16 lb_mode; -#define I40E_AQ_LB_PHY_LOCAL 0x01 -#define I40E_AQ_LB_PHY_REMOTE 0x02 -#define I40E_AQ_LB_MAC_LOCAL 0x04 - u8 reserved[14]; + __le16 lb_mode; +#define I40E_AQ_LB_PHY_LOCAL 0x01 +#define I40E_AQ_LB_PHY_REMOTE 0x02 +#define I40E_AQ_LB_MAC_LOCAL 0x04 + u8 reserved[14]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_set_lb_mode); /* Set PHY Debug command (0x0622) */ struct i40e_aqc_set_phy_debug { - u8 command_flags; + u8 command_flags; #define I40E_AQ_PHY_DEBUG_RESET_INTERNAL 0x02 #define I40E_AQ_PHY_DEBUG_RESET_EXTERNAL_SHIFT 2 #define I40E_AQ_PHY_DEBUG_RESET_EXTERNAL_MASK (0x03 << \ @@ -1757,15 +1757,15 @@ struct i40e_aqc_set_phy_debug { #define I40E_AQ_PHY_DEBUG_RESET_EXTERNAL_HARD 0x01 #define I40E_AQ_PHY_DEBUG_RESET_EXTERNAL_SOFT 0x02 #define I40E_AQ_PHY_DEBUG_DISABLE_LINK_FW 0x10 - u8 reserved[15]; + u8 reserved[15]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_set_phy_debug); enum i40e_aq_phy_reg_type { - I40E_AQC_PHY_REG_INTERNAL = 0x1, - I40E_AQC_PHY_REG_EXERNAL_BASET = 0x2, - I40E_AQC_PHY_REG_EXERNAL_MODULE = 0x3 + I40E_AQC_PHY_REG_INTERNAL = 0x1, + I40E_AQC_PHY_REG_EXERNAL_BASET = 0x2, + I40E_AQC_PHY_REG_EXERNAL_MODULE = 0x3 }; /* NVM Read command (indirect 0x0701) @@ -1773,40 +1773,40 @@ enum i40e_aq_phy_reg_type { * NVM Update commands (indirect 0x0703) */ struct i40e_aqc_nvm_update { - u8 command_flags; -#define I40E_AQ_NVM_LAST_CMD 0x01 -#define I40E_AQ_NVM_FLASH_ONLY 0x80 - u8 module_pointer; - __le16 length; - __le32 offset; - __le32 addr_high; - __le32 addr_low; + u8 command_flags; +#define I40E_AQ_NVM_LAST_CMD 0x01 +#define I40E_AQ_NVM_FLASH_ONLY 0x80 + u8 module_pointer; + __le16 length; + __le32 offset; + __le32 addr_high; + __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_nvm_update); /* NVM Config Read (indirect 0x0704) */ struct i40e_aqc_nvm_config_read { - __le16 cmd_flags; + __le16 cmd_flags; #define ANVM_SINGLE_OR_MULTIPLE_FEATURES_MASK 1 #define ANVM_READ_SINGLE_FEATURE 0 #define ANVM_READ_MULTIPLE_FEATURES 1 - __le16 element_count; - __le16 element_id; /* Feature/field ID */ - u8 reserved[2]; - __le32 address_high; - __le32 address_low; + __le16 element_count; + __le16 element_id; /* Feature/field ID */ + u8 reserved[2]; + __le32 address_high; + __le32 address_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_nvm_config_read); /* NVM Config Write (indirect 0x0705) */ struct i40e_aqc_nvm_config_write { - __le16 cmd_flags; - __le16 element_count; - u8 reserved[4]; - __le32 address_high; - __le32 address_low; + __le16 cmd_flags; + __le16 element_count; + u8 reserved[4]; + __le32 address_high; + __le32 address_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_nvm_config_write); @@ -1831,10 +1831,10 @@ struct i40e_aqc_nvm_config_data_immediate_field { * Send to Peer PF command (indirect 0x0803) */ struct i40e_aqc_pf_vf_message { - __le32 id; - u8 reserved[4]; - __le32 addr_high; - __le32 addr_low; + __le32 id; + u8 reserved[4]; + __le32 addr_high; + __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_pf_vf_message); @@ -1870,22 +1870,22 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_alternate_ind_write); * uses i40e_aq_desc */ struct i40e_aqc_alternate_write_done { - __le16 cmd_flags; + __le16 cmd_flags; #define I40E_AQ_ALTERNATE_MODE_BIOS_MASK 1 #define I40E_AQ_ALTERNATE_MODE_BIOS_LEGACY 0 #define I40E_AQ_ALTERNATE_MODE_BIOS_UEFI 1 #define I40E_AQ_ALTERNATE_RESET_NEEDED 2 - u8 reserved[14]; + u8 reserved[14]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_alternate_write_done); /* Set OEM mode (direct 0x0905) */ struct i40e_aqc_alternate_set_mode { - __le32 mode; + __le32 mode; #define I40E_AQ_ALTERNATE_MODE_NONE 0 #define I40E_AQ_ALTERNATE_MODE_OEM 1 - u8 reserved[12]; + u8 reserved[12]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_alternate_set_mode); @@ -1896,33 +1896,33 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_alternate_set_mode); /* Lan Queue Overflow Event (direct, 0x1001) */ struct i40e_aqc_lan_overflow { - __le32 prtdcb_rupto; - __le32 otx_ctl; - u8 reserved[8]; + __le32 prtdcb_rupto; + __le32 otx_ctl; + u8 reserved[8]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_lan_overflow); /* Get LLDP MIB (indirect 0x0A00) */ struct i40e_aqc_lldp_get_mib { - u8 type; - u8 reserved1; -#define I40E_AQ_LLDP_MIB_TYPE_MASK 0x3 -#define I40E_AQ_LLDP_MIB_LOCAL 0x0 -#define I40E_AQ_LLDP_MIB_REMOTE 0x1 -#define I40E_AQ_LLDP_MIB_LOCAL_AND_REMOTE 0x2 -#define I40E_AQ_LLDP_BRIDGE_TYPE_MASK 0xC -#define I40E_AQ_LLDP_BRIDGE_TYPE_SHIFT 0x2 -#define I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE 0x0 -#define I40E_AQ_LLDP_BRIDGE_TYPE_NON_TPMR 0x1 -#define I40E_AQ_LLDP_TX_SHIFT 0x4 -#define I40E_AQ_LLDP_TX_MASK (0x03 << I40E_AQ_LLDP_TX_SHIFT) + u8 type; + u8 reserved1; +#define I40E_AQ_LLDP_MIB_TYPE_MASK 0x3 +#define I40E_AQ_LLDP_MIB_LOCAL 0x0 +#define I40E_AQ_LLDP_MIB_REMOTE 0x1 +#define I40E_AQ_LLDP_MIB_LOCAL_AND_REMOTE 0x2 +#define I40E_AQ_LLDP_BRIDGE_TYPE_MASK 0xC +#define I40E_AQ_LLDP_BRIDGE_TYPE_SHIFT 0x2 +#define I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE 0x0 +#define I40E_AQ_LLDP_BRIDGE_TYPE_NON_TPMR 0x1 +#define I40E_AQ_LLDP_TX_SHIFT 0x4 +#define I40E_AQ_LLDP_TX_MASK (0x03 << I40E_AQ_LLDP_TX_SHIFT) /* TX pause flags use I40E_AQ_LINK_TX_* above */ - __le16 local_len; - __le16 remote_len; - u8 reserved2[2]; - __le32 addr_high; - __le32 addr_low; + __le16 local_len; + __le16 remote_len; + u8 reserved2[2]; + __le32 addr_high; + __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_get_mib); @@ -1931,12 +1931,12 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_get_mib); * also used for the event (with type in the command field) */ struct i40e_aqc_lldp_update_mib { - u8 command; -#define I40E_AQ_LLDP_MIB_UPDATE_ENABLE 0x0 -#define I40E_AQ_LLDP_MIB_UPDATE_DISABLE 0x1 - u8 reserved[7]; - __le32 addr_high; - __le32 addr_low; + u8 command; +#define I40E_AQ_LLDP_MIB_UPDATE_ENABLE 0x0 +#define I40E_AQ_LLDP_MIB_UPDATE_DISABLE 0x1 + u8 reserved[7]; + __le32 addr_high; + __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_update_mib); @@ -1945,35 +1945,35 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_update_mib); * Delete LLDP TLV (indirect 0x0A04) */ struct i40e_aqc_lldp_add_tlv { - u8 type; /* only nearest bridge and non-TPMR from 0x0A00 */ - u8 reserved1[1]; - __le16 len; - u8 reserved2[4]; - __le32 addr_high; - __le32 addr_low; + u8 type; /* only nearest bridge and non-TPMR from 0x0A00 */ + u8 reserved1[1]; + __le16 len; + u8 reserved2[4]; + __le32 addr_high; + __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_add_tlv); /* Update LLDP TLV (indirect 0x0A03) */ struct i40e_aqc_lldp_update_tlv { - u8 type; /* only nearest bridge and non-TPMR from 0x0A00 */ - u8 reserved; - __le16 old_len; - __le16 new_offset; - __le16 new_len; - __le32 addr_high; - __le32 addr_low; + u8 type; /* only nearest bridge and non-TPMR from 0x0A00 */ + u8 reserved; + __le16 old_len; + __le16 new_offset; + __le16 new_len; + __le32 addr_high; + __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_update_tlv); /* Stop LLDP (direct 0x0A05) */ struct i40e_aqc_lldp_stop { - u8 command; -#define I40E_AQ_LLDP_AGENT_STOP 0x0 -#define I40E_AQ_LLDP_AGENT_SHUTDOWN 0x1 - u8 reserved[15]; + u8 command; +#define I40E_AQ_LLDP_AGENT_STOP 0x0 +#define I40E_AQ_LLDP_AGENT_SHUTDOWN 0x1 + u8 reserved[15]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_stop); @@ -1981,57 +1981,97 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_stop); /* Start LLDP (direct 0x0A06) */ struct i40e_aqc_lldp_start { - u8 command; -#define I40E_AQ_LLDP_AGENT_START 0x1 - u8 reserved[15]; + u8 command; +#define I40E_AQ_LLDP_AGENT_START 0x1 + u8 reserved[15]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_start); -/* Apply MIB changes (0x0A07) - * uses the generic struc as it contains no data +/* Get CEE DCBX Oper Config (0x0A07) + * uses the generic descriptor struct + * returns below as indirect response */ +#define I40E_AQC_CEE_APP_FCOE_SHIFT 0x0 +#define I40E_AQC_CEE_APP_FCOE_MASK (0x7 << I40E_AQC_CEE_APP_FCOE_SHIFT) +#define I40E_AQC_CEE_APP_ISCSI_SHIFT 0x3 +#define I40E_AQC_CEE_APP_ISCSI_MASK (0x7 << I40E_AQC_CEE_APP_ISCSI_SHIFT) +#define I40E_AQC_CEE_APP_FIP_SHIFT 0x8 +#define I40E_AQC_CEE_APP_FIP_MASK (0x7 << I40E_AQC_CEE_APP_FIP_SHIFT) +#define I40E_AQC_CEE_PG_STATUS_SHIFT 0x0 +#define I40E_AQC_CEE_PG_STATUS_MASK (0x7 << I40E_AQC_CEE_PG_STATUS_SHIFT) +#define I40E_AQC_CEE_PFC_STATUS_SHIFT 0x3 +#define I40E_AQC_CEE_PFC_STATUS_MASK (0x7 << I40E_AQC_CEE_PFC_STATUS_SHIFT) +#define I40E_AQC_CEE_APP_STATUS_SHIFT 0x8 +#define I40E_AQC_CEE_APP_STATUS_MASK (0x7 << I40E_AQC_CEE_APP_STATUS_SHIFT) +struct i40e_aqc_get_cee_dcb_cfg_v1_resp { + u8 reserved1; + u8 oper_num_tc; + u8 oper_prio_tc[4]; + u8 reserved2; + u8 oper_tc_bw[8]; + u8 oper_pfc_en; + u8 reserved3; + __le16 oper_app_prio; + u8 reserved4; + __le16 tlv_status; +}; + +I40E_CHECK_STRUCT_LEN(0x18, i40e_aqc_get_cee_dcb_cfg_v1_resp); + +struct i40e_aqc_get_cee_dcb_cfg_resp { + u8 oper_num_tc; + u8 oper_prio_tc[4]; + u8 oper_tc_bw[8]; + u8 oper_pfc_en; + __le16 oper_app_prio; + __le32 tlv_status; + u8 reserved[12]; +}; + +I40E_CHECK_STRUCT_LEN(0x20, i40e_aqc_get_cee_dcb_cfg_resp); + /* Add Udp Tunnel command and completion (direct 0x0B00) */ struct i40e_aqc_add_udp_tunnel { - __le16 udp_port; - u8 reserved0[3]; - u8 protocol_type; + __le16 udp_port; + u8 reserved0[3]; + u8 protocol_type; #define I40E_AQC_TUNNEL_TYPE_VXLAN 0x00 #define I40E_AQC_TUNNEL_TYPE_NGE 0x01 #define I40E_AQC_TUNNEL_TYPE_TEREDO 0x10 - u8 reserved1[10]; + u8 reserved1[10]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_udp_tunnel); struct i40e_aqc_add_udp_tunnel_completion { - __le16 udp_port; - u8 filter_entry_index; - u8 multiple_pfs; -#define I40E_AQC_SINGLE_PF 0x0 -#define I40E_AQC_MULTIPLE_PFS 0x1 - u8 total_filters; - u8 reserved[11]; + __le16 udp_port; + u8 filter_entry_index; + u8 multiple_pfs; +#define I40E_AQC_SINGLE_PF 0x0 +#define I40E_AQC_MULTIPLE_PFS 0x1 + u8 total_filters; + u8 reserved[11]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_udp_tunnel_completion); /* remove UDP Tunnel command (0x0B01) */ struct i40e_aqc_remove_udp_tunnel { - u8 reserved[2]; - u8 index; /* 0 to 15 */ - u8 reserved2[13]; + u8 reserved[2]; + u8 index; /* 0 to 15 */ + u8 reserved2[13]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_remove_udp_tunnel); struct i40e_aqc_del_udp_tunnel_completion { - __le16 udp_port; - u8 index; /* 0 to 15 */ - u8 multiple_pfs; - u8 total_filters_used; - u8 reserved1[11]; + __le16 udp_port; + u8 index; /* 0 to 15 */ + u8 multiple_pfs; + u8 total_filters_used; + u8 reserved1[11]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_del_udp_tunnel_completion); @@ -2044,11 +2084,11 @@ struct i40e_aqc_tunnel_key_structure { u8 key1_len; /* 0 to 15 */ u8 key2_len; /* 0 to 15 */ u8 flags; -#define I40E_AQC_TUNNEL_KEY_STRUCT_OVERRIDE 0x01 +#define I40E_AQC_TUNNEL_KEY_STRUCT_OVERRIDE 0x01 /* response flags */ -#define I40E_AQC_TUNNEL_KEY_STRUCT_SUCCESS 0x01 -#define I40E_AQC_TUNNEL_KEY_STRUCT_MODIFIED 0x02 -#define I40E_AQC_TUNNEL_KEY_STRUCT_OVERRIDDEN 0x03 +#define I40E_AQC_TUNNEL_KEY_STRUCT_SUCCESS 0x01 +#define I40E_AQC_TUNNEL_KEY_STRUCT_MODIFIED 0x02 +#define I40E_AQC_TUNNEL_KEY_STRUCT_OVERRIDDEN 0x03 u8 network_key_index; #define I40E_AQC_NETWORK_KEY_INDEX_VXLAN 0x0 #define I40E_AQC_NETWORK_KEY_INDEX_NGE 0x1 @@ -2061,21 +2101,21 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_tunnel_key_structure); /* OEM mode commands (direct 0xFE0x) */ struct i40e_aqc_oem_param_change { - __le32 param_type; -#define I40E_AQ_OEM_PARAM_TYPE_PF_CTL 0 -#define I40E_AQ_OEM_PARAM_TYPE_BW_CTL 1 -#define I40E_AQ_OEM_PARAM_MAC 2 - __le32 param_value1; - u8 param_value2[8]; + __le32 param_type; +#define I40E_AQ_OEM_PARAM_TYPE_PF_CTL 0 +#define I40E_AQ_OEM_PARAM_TYPE_BW_CTL 1 +#define I40E_AQ_OEM_PARAM_MAC 2 + __le32 param_value1; + u8 param_value2[8]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_oem_param_change); struct i40e_aqc_oem_state_change { - __le32 state; -#define I40E_AQ_OEM_STATE_LINK_DOWN 0x0 -#define I40E_AQ_OEM_STATE_LINK_UP 0x1 - u8 reserved[12]; + __le32 state; +#define I40E_AQ_OEM_STATE_LINK_DOWN 0x0 +#define I40E_AQ_OEM_STATE_LINK_UP 0x1 + u8 reserved[12]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_oem_state_change); @@ -2087,18 +2127,18 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_oem_state_change); /* set test more (0xFF01, internal) */ struct i40e_acq_set_test_mode { - u8 mode; -#define I40E_AQ_TEST_PARTIAL 0 -#define I40E_AQ_TEST_FULL 1 -#define I40E_AQ_TEST_NVM 2 - u8 reserved[3]; - u8 command; -#define I40E_AQ_TEST_OPEN 0 -#define I40E_AQ_TEST_CLOSE 1 -#define I40E_AQ_TEST_INC 2 - u8 reserved2[3]; - __le32 address_high; - __le32 address_low; + u8 mode; +#define I40E_AQ_TEST_PARTIAL 0 +#define I40E_AQ_TEST_FULL 1 +#define I40E_AQ_TEST_NVM 2 + u8 reserved[3]; + u8 command; +#define I40E_AQ_TEST_OPEN 0 +#define I40E_AQ_TEST_CLOSE 1 +#define I40E_AQ_TEST_INC 2 + u8 reserved2[3]; + __le32 address_high; + __le32 address_low; }; I40E_CHECK_CMD_LENGTH(i40e_acq_set_test_mode); @@ -2151,21 +2191,21 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_debug_modify_reg); #define I40E_AQ_CLUSTER_ID_ALTRAM 11 struct i40e_aqc_debug_dump_internals { - u8 cluster_id; - u8 table_id; - __le16 data_size; - __le32 idx; - __le32 address_high; - __le32 address_low; + u8 cluster_id; + u8 table_id; + __le16 data_size; + __le32 idx; + __le32 address_high; + __le32 address_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_debug_dump_internals); struct i40e_aqc_debug_modify_internals { - u8 cluster_id; - u8 cluster_specific_params[7]; - __le32 address_high; - __le32 address_low; + u8 cluster_id; + u8 cluster_specific_params[7]; + __le32 address_high; + __le32 address_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_debug_modify_internals); diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index 30056b25d94e..b601b3cfd92b 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -50,6 +50,7 @@ static i40e_status i40e_set_mac_type(struct i40e_hw *hw) case I40E_DEV_ID_QSFP_A: case I40E_DEV_ID_QSFP_B: case I40E_DEV_ID_QSFP_C: + case I40E_DEV_ID_10G_BASE_T: hw->mac.type = I40E_MAC_XL710; break; case I40E_DEV_ID_VF: @@ -1420,6 +1421,33 @@ i40e_status i40e_update_link_info(struct i40e_hw *hw, bool enable_lse) } /** + * i40e_aq_set_phy_int_mask + * @hw: pointer to the hw struct + * @mask: interrupt mask to be set + * @cmd_details: pointer to command details structure or NULL + * + * Set link interrupt mask. + **/ +i40e_status i40e_aq_set_phy_int_mask(struct i40e_hw *hw, + u16 mask, + struct i40e_asq_cmd_details *cmd_details) +{ + struct i40e_aq_desc desc; + struct i40e_aqc_set_phy_int_mask *cmd = + (struct i40e_aqc_set_phy_int_mask *)&desc.params.raw; + i40e_status status; + + i40e_fill_default_direct_cmd_desc(&desc, + i40e_aqc_opc_set_phy_int_mask); + + cmd->event_mask = cpu_to_le16(mask); + + status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); + + return status; +} + +/** * i40e_aq_add_vsi * @hw: pointer to the hw struct * @vsi_ctx: pointer to a vsi context struct @@ -2632,6 +2660,34 @@ i40e_status i40e_aq_start_lldp(struct i40e_hw *hw, } /** + * i40e_aq_get_cee_dcb_config + * @hw: pointer to the hw struct + * @buff: response buffer that stores CEE operational configuration + * @buff_size: size of the buffer passed + * @cmd_details: pointer to command details structure or NULL + * + * Get CEE DCBX mode operational configuration from firmware + **/ +i40e_status i40e_aq_get_cee_dcb_config(struct i40e_hw *hw, + void *buff, u16 buff_size, + struct i40e_asq_cmd_details *cmd_details) +{ + struct i40e_aq_desc desc; + i40e_status status; + + if (buff_size == 0 || !buff) + return I40E_ERR_PARAM; + + i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_get_cee_dcb_cfg); + + desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_BUF); + status = i40e_asq_send_command(hw, &desc, (void *)buff, buff_size, + cmd_details); + + return status; +} + +/** * i40e_aq_add_udp_tunnel * @hw: pointer to the hw struct * @udp_port: the UDP port to add @@ -3189,6 +3245,26 @@ i40e_status i40e_aq_add_rem_control_packet_filter(struct i40e_hw *hw, } /** + * i40e_aq_resume_port_tx + * @hw: pointer to the hardware structure + * @cmd_details: pointer to command details structure or NULL + * + * Resume port's Tx traffic + **/ +i40e_status i40e_aq_resume_port_tx(struct i40e_hw *hw, + struct i40e_asq_cmd_details *cmd_details) +{ + struct i40e_aq_desc desc; + i40e_status status; + + i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_resume_port_tx); + + status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); + + return status; +} + +/** * i40e_set_pci_config_data - store PCI bus info * @hw: pointer to hardware structure * @link_status: the link status word from PCI config space diff --git a/drivers/net/ethernet/intel/i40e/i40e_dcb.c b/drivers/net/ethernet/intel/i40e/i40e_dcb.c index 036570d76176..3ce43588592d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_dcb.c +++ b/drivers/net/ethernet/intel/i40e/i40e_dcb.c @@ -59,7 +59,7 @@ i40e_status i40e_get_dcbx_status(struct i40e_hw *hw, u16 *status) static void i40e_parse_ieee_etscfg_tlv(struct i40e_lldp_org_tlv *tlv, struct i40e_dcbx_config *dcbcfg) { - struct i40e_ieee_ets_config *etscfg; + struct i40e_dcb_ets_config *etscfg; u8 *buf = tlv->tlvinfo; u16 offset = 0; u8 priority; @@ -407,6 +407,166 @@ free_mem: } /** + * i40e_cee_to_dcb_v1_config + * @cee_cfg: pointer to CEE v1 response configuration struct + * @dcbcfg: DCB configuration struct + * + * Convert CEE v1 configuration from firmware to DCB configuration + **/ +static void i40e_cee_to_dcb_v1_config( + struct i40e_aqc_get_cee_dcb_cfg_v1_resp *cee_cfg, + struct i40e_dcbx_config *dcbcfg) +{ + u16 status, tlv_status = le16_to_cpu(cee_cfg->tlv_status); + u16 app_prio = le16_to_cpu(cee_cfg->oper_app_prio); + u8 i, tc, err, sync, oper; + + /* CEE PG data to ETS config */ + dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc; + + for (i = 0; i < 4; i++) { + tc = (u8)((cee_cfg->oper_prio_tc[i] & + I40E_CEE_PGID_PRIO_1_MASK) >> + I40E_CEE_PGID_PRIO_1_SHIFT); + dcbcfg->etscfg.prioritytable[i*2] = tc; + tc = (u8)((cee_cfg->oper_prio_tc[i] & + I40E_CEE_PGID_PRIO_0_MASK) >> + I40E_CEE_PGID_PRIO_0_SHIFT); + dcbcfg->etscfg.prioritytable[i*2 + 1] = tc; + } + + for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) + dcbcfg->etscfg.tcbwtable[i] = cee_cfg->oper_tc_bw[i]; + + for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { + if (dcbcfg->etscfg.prioritytable[i] == I40E_CEE_PGID_STRICT) { + /* Map it to next empty TC */ + dcbcfg->etscfg.prioritytable[i] = + cee_cfg->oper_num_tc - 1; + dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_STRICT; + } else { + dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS; + } + } + + /* CEE PFC data to ETS config */ + dcbcfg->pfc.pfcenable = cee_cfg->oper_pfc_en; + dcbcfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS; + + status = (tlv_status & I40E_AQC_CEE_APP_STATUS_MASK) >> + I40E_AQC_CEE_APP_STATUS_SHIFT; + err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0; + sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0; + oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0; + /* Add APPs if Error is False and Oper/Sync is True */ + if (!err && sync && oper) { + /* CEE operating configuration supports FCoE/iSCSI/FIP only */ + dcbcfg->numapps = I40E_CEE_OPER_MAX_APPS; + + /* FCoE APP */ + dcbcfg->app[0].priority = + (app_prio & I40E_AQC_CEE_APP_FCOE_MASK) >> + I40E_AQC_CEE_APP_FCOE_SHIFT; + dcbcfg->app[0].selector = I40E_APP_SEL_ETHTYPE; + dcbcfg->app[0].protocolid = I40E_APP_PROTOID_FCOE; + + /* iSCSI APP */ + dcbcfg->app[1].priority = + (app_prio & I40E_AQC_CEE_APP_ISCSI_MASK) >> + I40E_AQC_CEE_APP_ISCSI_SHIFT; + dcbcfg->app[1].selector = I40E_APP_SEL_TCPIP; + dcbcfg->app[1].protocolid = I40E_APP_PROTOID_ISCSI; + + /* FIP APP */ + dcbcfg->app[2].priority = + (app_prio & I40E_AQC_CEE_APP_FIP_MASK) >> + I40E_AQC_CEE_APP_FIP_SHIFT; + dcbcfg->app[2].selector = I40E_APP_SEL_ETHTYPE; + dcbcfg->app[2].protocolid = I40E_APP_PROTOID_FIP; + } +} + +/** + * i40e_cee_to_dcb_config + * @cee_cfg: pointer to CEE configuration struct + * @dcbcfg: DCB configuration struct + * + * Convert CEE configuration from firmware to DCB configuration + **/ +static void i40e_cee_to_dcb_config( + struct i40e_aqc_get_cee_dcb_cfg_resp *cee_cfg, + struct i40e_dcbx_config *dcbcfg) +{ + u32 status, tlv_status = le32_to_cpu(cee_cfg->tlv_status); + u16 app_prio = le16_to_cpu(cee_cfg->oper_app_prio); + u8 i, tc, err, sync, oper; + + /* CEE PG data to ETS config */ + dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc; + + for (i = 0; i < 4; i++) { + tc = (u8)((cee_cfg->oper_prio_tc[i] & + I40E_CEE_PGID_PRIO_1_MASK) >> + I40E_CEE_PGID_PRIO_1_SHIFT); + dcbcfg->etscfg.prioritytable[i*2] = tc; + tc = (u8)((cee_cfg->oper_prio_tc[i] & + I40E_CEE_PGID_PRIO_0_MASK) >> + I40E_CEE_PGID_PRIO_0_SHIFT); + dcbcfg->etscfg.prioritytable[i*2 + 1] = tc; + } + + for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) + dcbcfg->etscfg.tcbwtable[i] = cee_cfg->oper_tc_bw[i]; + + for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { + if (dcbcfg->etscfg.prioritytable[i] == I40E_CEE_PGID_STRICT) { + /* Map it to next empty TC */ + dcbcfg->etscfg.prioritytable[i] = + cee_cfg->oper_num_tc - 1; + dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_STRICT; + } else { + dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS; + } + } + + /* CEE PFC data to ETS config */ + dcbcfg->pfc.pfcenable = cee_cfg->oper_pfc_en; + dcbcfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS; + + status = (tlv_status & I40E_AQC_CEE_APP_STATUS_MASK) >> + I40E_AQC_CEE_APP_STATUS_SHIFT; + err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0; + sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0; + oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0; + /* Add APPs if Error is False and Oper/Sync is True */ + if (!err && sync && oper) { + /* CEE operating configuration supports FCoE/iSCSI/FIP only */ + dcbcfg->numapps = I40E_CEE_OPER_MAX_APPS; + + /* FCoE APP */ + dcbcfg->app[0].priority = + (app_prio & I40E_AQC_CEE_APP_FCOE_MASK) >> + I40E_AQC_CEE_APP_FCOE_SHIFT; + dcbcfg->app[0].selector = I40E_APP_SEL_ETHTYPE; + dcbcfg->app[0].protocolid = I40E_APP_PROTOID_FCOE; + + /* iSCSI APP */ + dcbcfg->app[1].priority = + (app_prio & I40E_AQC_CEE_APP_ISCSI_MASK) >> + I40E_AQC_CEE_APP_ISCSI_SHIFT; + dcbcfg->app[1].selector = I40E_APP_SEL_TCPIP; + dcbcfg->app[1].protocolid = I40E_APP_PROTOID_ISCSI; + + /* FIP APP */ + dcbcfg->app[2].priority = + (app_prio & I40E_AQC_CEE_APP_FIP_MASK) >> + I40E_AQC_CEE_APP_FIP_SHIFT; + dcbcfg->app[2].selector = I40E_APP_SEL_ETHTYPE; + dcbcfg->app[2].protocolid = I40E_APP_PROTOID_FIP; + } +} + +/** * i40e_get_dcb_config * @hw: pointer to the hw struct * @@ -415,7 +575,44 @@ free_mem: i40e_status i40e_get_dcb_config(struct i40e_hw *hw) { i40e_status ret = 0; + struct i40e_aqc_get_cee_dcb_cfg_resp cee_cfg; + struct i40e_aqc_get_cee_dcb_cfg_v1_resp cee_v1_cfg; + + /* If Firmware version < v4.33 IEEE only */ + if (((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver < 33)) || + (hw->aq.fw_maj_ver < 4)) + goto ieee; + + /* If Firmware version == v4.33 use old CEE struct */ + if ((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver == 33)) { + ret = i40e_aq_get_cee_dcb_config(hw, &cee_v1_cfg, + sizeof(cee_v1_cfg), NULL); + if (!ret) { + /* CEE mode */ + hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_CEE; + i40e_cee_to_dcb_v1_config(&cee_v1_cfg, + &hw->local_dcbx_config); + } + } else { + ret = i40e_aq_get_cee_dcb_config(hw, &cee_cfg, + sizeof(cee_cfg), NULL); + if (!ret) { + /* CEE mode */ + hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_CEE; + i40e_cee_to_dcb_config(&cee_cfg, + &hw->local_dcbx_config); + } + } + + /* CEE mode not enabled try querying IEEE data */ + if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT) + goto ieee; + else + goto out; +ieee: + /* IEEE mode */ + hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_IEEE; /* Get Local DCB Config */ ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_LOCAL, 0, &hw->local_dcbx_config); @@ -426,6 +623,10 @@ i40e_status i40e_get_dcb_config(struct i40e_hw *hw) ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_REMOTE, I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE, &hw->remote_dcbx_config); + /* Don't treat ENOENT as an error for Remote MIBs */ + if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT) + ret = 0; + out: return ret; } @@ -439,10 +640,27 @@ out: i40e_status i40e_init_dcb(struct i40e_hw *hw) { i40e_status ret = 0; + struct i40e_lldp_variables lldp_cfg; + u8 adminstatus = 0; if (!hw->func_caps.dcb) return ret; + /* Read LLDP NVM area */ + ret = i40e_read_lldp_cfg(hw, &lldp_cfg); + if (ret) + return ret; + + /* Get the LLDP AdminStatus for the current port */ + adminstatus = lldp_cfg.adminstatus >> (hw->port * 4); + adminstatus &= 0xF; + + /* LLDP agent disabled */ + if (!adminstatus) { + hw->dcbx_status = I40E_DCBX_STATUS_DISABLED; + return ret; + } + /* Get DCBX status */ ret = i40e_get_dcbx_status(hw, &hw->dcbx_status); if (ret) @@ -454,6 +672,8 @@ i40e_status i40e_init_dcb(struct i40e_hw *hw) case I40E_DCBX_STATUS_IN_PROGRESS: /* Get current DCBX configuration */ ret = i40e_get_dcb_config(hw); + if (ret) + return ret; break; case I40E_DCBX_STATUS_DISABLED: return ret; @@ -470,3 +690,33 @@ i40e_status i40e_init_dcb(struct i40e_hw *hw) return ret; } + +/** + * i40e_read_lldp_cfg - read LLDP Configuration data from NVM + * @hw: pointer to the HW structure + * @lldp_cfg: pointer to hold lldp configuration variables + * + * Reads the LLDP configuration data from NVM + **/ +i40e_status i40e_read_lldp_cfg(struct i40e_hw *hw, + struct i40e_lldp_variables *lldp_cfg) +{ + i40e_status ret = 0; + u32 offset = (2 * I40E_NVM_LLDP_CFG_PTR); + + if (!lldp_cfg) + return I40E_ERR_PARAM; + + ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ); + if (ret) + goto err_lldp_cfg; + + ret = i40e_aq_read_nvm(hw, I40E_SR_EMP_MODULE_PTR, offset, + sizeof(struct i40e_lldp_variables), + (u8 *)lldp_cfg, + true, NULL); + i40e_release_nvm(hw); + +err_lldp_cfg: + return ret; +} diff --git a/drivers/net/ethernet/intel/i40e/i40e_dcb.h b/drivers/net/ethernet/intel/i40e/i40e_dcb.h index 34cf1c30c7ff..e137e3fac8ee 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_dcb.h +++ b/drivers/net/ethernet/intel/i40e/i40e_dcb.h @@ -65,6 +65,11 @@ #define I40E_IEEE_ETS_PRIO_0_MASK (0x7 << I40E_IEEE_ETS_PRIO_0_SHIFT) #define I40E_IEEE_ETS_PRIO_1_SHIFT 4 #define I40E_IEEE_ETS_PRIO_1_MASK (0x7 << I40E_IEEE_ETS_PRIO_1_SHIFT) +#define I40E_CEE_PGID_PRIO_0_SHIFT 0 +#define I40E_CEE_PGID_PRIO_0_MASK (0xF << I40E_CEE_PGID_PRIO_0_SHIFT) +#define I40E_CEE_PGID_PRIO_1_SHIFT 4 +#define I40E_CEE_PGID_PRIO_1_MASK (0xF << I40E_CEE_PGID_PRIO_1_SHIFT) +#define I40E_CEE_PGID_STRICT 15 /* Defines for IEEE TSA types */ #define I40E_IEEE_TSA_STRICT 0 diff --git a/drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c b/drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c index 00bc0cdb3a03..183dcb63ce98 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c +++ b/drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c @@ -207,7 +207,7 @@ void i40e_dcbnl_set_all(struct i40e_vsi *vsi) * VSI **/ static int i40e_dcbnl_vsi_del_app(struct i40e_vsi *vsi, - struct i40e_ieee_app_priority_table *app) + struct i40e_dcb_app_priority_table *app) { struct net_device *dev = vsi->netdev; struct dcb_app sapp; @@ -229,7 +229,7 @@ static int i40e_dcbnl_vsi_del_app(struct i40e_vsi *vsi, * Delete given APP from all the VSIs for given PF **/ static void i40e_dcbnl_del_app(struct i40e_pf *pf, - struct i40e_ieee_app_priority_table *app) + struct i40e_dcb_app_priority_table *app) { int v, err; for (v = 0; v < pf->num_alloc_vsi; v++) { @@ -252,7 +252,7 @@ static void i40e_dcbnl_del_app(struct i40e_pf *pf, * Find given APP in the DCB configuration **/ static bool i40e_dcbnl_find_app(struct i40e_dcbx_config *cfg, - struct i40e_ieee_app_priority_table *app) + struct i40e_dcb_app_priority_table *app) { int i; @@ -277,7 +277,7 @@ static bool i40e_dcbnl_find_app(struct i40e_dcbx_config *cfg, void i40e_dcbnl_flush_apps(struct i40e_pf *pf, struct i40e_dcbx_config *new_cfg) { - struct i40e_ieee_app_priority_table app; + struct i40e_dcb_app_priority_table app; struct i40e_dcbx_config *dcbxcfg; struct i40e_hw *hw = &pf->hw; int i; diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c index 7067f4b9159c..3a3c237b76d4 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c +++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c @@ -895,90 +895,6 @@ static void i40e_dbg_dump_eth_stats(struct i40e_pf *pf, } /** - * i40e_dbg_dump_stats - handles dump stats write into command datum - * @pf: the i40e_pf created in command write - * @stats: the stats structure to be dumped - **/ -static void i40e_dbg_dump_stats(struct i40e_pf *pf, - struct i40e_hw_port_stats *stats) -{ - int i; - - dev_info(&pf->pdev->dev, " stats:\n"); - dev_info(&pf->pdev->dev, - " crc_errors = \t\t%lld \tillegal_bytes = \t%lld \terror_bytes = \t\t%lld\n", - stats->crc_errors, stats->illegal_bytes, stats->error_bytes); - dev_info(&pf->pdev->dev, - " mac_local_faults = \t%lld \tmac_remote_faults = \t%lld \trx_length_errors = \t%lld\n", - stats->mac_local_faults, stats->mac_remote_faults, - stats->rx_length_errors); - dev_info(&pf->pdev->dev, - " link_xon_rx = \t\t%lld \tlink_xoff_rx = \t\t%lld \tlink_xon_tx = \t\t%lld\n", - stats->link_xon_rx, stats->link_xoff_rx, stats->link_xon_tx); - dev_info(&pf->pdev->dev, - " link_xoff_tx = \t\t%lld \trx_size_64 = \t\t%lld \trx_size_127 = \t\t%lld\n", - stats->link_xoff_tx, stats->rx_size_64, stats->rx_size_127); - dev_info(&pf->pdev->dev, - " rx_size_255 = \t\t%lld \trx_size_511 = \t\t%lld \trx_size_1023 = \t\t%lld\n", - stats->rx_size_255, stats->rx_size_511, stats->rx_size_1023); - dev_info(&pf->pdev->dev, - " rx_size_big = \t\t%lld \trx_undersize = \t\t%lld \trx_jabber = \t\t%lld\n", - stats->rx_size_big, stats->rx_undersize, stats->rx_jabber); - dev_info(&pf->pdev->dev, - " rx_fragments = \t\t%lld \trx_oversize = \t\t%lld \ttx_size_64 = \t\t%lld\n", - stats->rx_fragments, stats->rx_oversize, stats->tx_size_64); - dev_info(&pf->pdev->dev, - " tx_size_127 = \t\t%lld \ttx_size_255 = \t\t%lld \ttx_size_511 = \t\t%lld\n", - stats->tx_size_127, stats->tx_size_255, stats->tx_size_511); - dev_info(&pf->pdev->dev, - " tx_size_1023 = \t\t%lld \ttx_size_big = \t\t%lld \tmac_short_packet_dropped = \t%lld\n", - stats->tx_size_1023, stats->tx_size_big, - stats->mac_short_packet_dropped); - for (i = 0; i < 8; i += 4) { - dev_info(&pf->pdev->dev, - " priority_xon_rx[%d] = \t%lld \t[%d] = \t%lld \t[%d] = \t%lld \t[%d] = \t%lld\n", - i, stats->priority_xon_rx[i], - i+1, stats->priority_xon_rx[i+1], - i+2, stats->priority_xon_rx[i+2], - i+3, stats->priority_xon_rx[i+3]); - } - for (i = 0; i < 8; i += 4) { - dev_info(&pf->pdev->dev, - " priority_xoff_rx[%d] = \t%lld \t[%d] = \t%lld \t[%d] = \t%lld \t[%d] = \t%lld\n", - i, stats->priority_xoff_rx[i], - i+1, stats->priority_xoff_rx[i+1], - i+2, stats->priority_xoff_rx[i+2], - i+3, stats->priority_xoff_rx[i+3]); - } - for (i = 0; i < 8; i += 4) { - dev_info(&pf->pdev->dev, - " priority_xon_tx[%d] = \t%lld \t[%d] = \t%lld \t[%d] = \t%lld \t[%d] = \t%lld\n", - i, stats->priority_xon_tx[i], - i+1, stats->priority_xon_tx[i+1], - i+2, stats->priority_xon_tx[i+2], - i+3, stats->priority_xon_rx[i+3]); - } - for (i = 0; i < 8; i += 4) { - dev_info(&pf->pdev->dev, - " priority_xoff_tx[%d] = \t%lld \t[%d] = \t%lld \t[%d] = \t%lld \t[%d] = \t%lld\n", - i, stats->priority_xoff_tx[i], - i+1, stats->priority_xoff_tx[i+1], - i+2, stats->priority_xoff_tx[i+2], - i+3, stats->priority_xoff_tx[i+3]); - } - for (i = 0; i < 8; i += 4) { - dev_info(&pf->pdev->dev, - " priority_xon_2_xoff[%d] = \t%lld \t[%d] = \t%lld \t[%d] = \t%lld \t[%d] = \t%lld\n", - i, stats->priority_xon_2_xoff[i], - i+1, stats->priority_xon_2_xoff[i+1], - i+2, stats->priority_xon_2_xoff[i+2], - i+3, stats->priority_xon_2_xoff[i+3]); - } - - i40e_dbg_dump_eth_stats(pf, &stats->eth); -} - -/** * i40e_dbg_dump_veb_seid - handles dump stats of a single given veb * @pf: the i40e_pf created in command write * @seid: the seid the user put in @@ -1342,11 +1258,6 @@ static ssize_t i40e_dbg_command_write(struct file *filp, "dump desc rx <vsi_seid> <ring_id> [<desc_n>]\n"); dev_info(&pf->pdev->dev, "dump desc aq\n"); } - } else if (strncmp(&cmd_buf[5], "stats", 5) == 0) { - dev_info(&pf->pdev->dev, "pf stats:\n"); - i40e_dbg_dump_stats(pf, &pf->stats); - dev_info(&pf->pdev->dev, "pf stats_offsets:\n"); - i40e_dbg_dump_stats(pf, &pf->stats_offsets); } else if (strncmp(&cmd_buf[5], "reset stats", 11) == 0) { dev_info(&pf->pdev->dev, "core reset count: %d\n", pf->corer_count); @@ -1402,6 +1313,8 @@ static ssize_t i40e_dbg_command_write(struct file *filp, bw_data = NULL; dev_info(&pf->pdev->dev, + "port dcbx_mode=%d\n", cfg->dcbx_mode); + dev_info(&pf->pdev->dev, "port ets_cfg: willing=%d cbs=%d, maxtcs=%d\n", cfg->etscfg.willing, cfg->etscfg.cbs, cfg->etscfg.maxtcs); @@ -1464,8 +1377,8 @@ static ssize_t i40e_dbg_command_write(struct file *filp, } else { dev_info(&pf->pdev->dev, "dump desc tx <vsi_seid> <ring_id> [<desc_n>], dump desc rx <vsi_seid> <ring_id> [<desc_n>],\n"); - dev_info(&pf->pdev->dev, "dump switch, dump vsi [seid] or\n"); - dev_info(&pf->pdev->dev, "dump stats\n"); + dev_info(&pf->pdev->dev, "dump switch\n"); + dev_info(&pf->pdev->dev, "dump vsi [seid]\n"); dev_info(&pf->pdev->dev, "dump reset stats\n"); dev_info(&pf->pdev->dev, "dump port\n"); dev_info(&pf->pdev->dev, diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 1dda467ae1ac..b2402851a9bd 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -264,6 +264,14 @@ static int i40e_get_settings(struct net_device *netdev, ecmd->supported = SUPPORTED_10000baseKR_Full; ecmd->advertising = ADVERTISED_10000baseKR_Full; break; + case I40E_DEV_ID_10G_BASE_T: + ecmd->supported = SUPPORTED_10000baseT_Full | + SUPPORTED_1000baseT_Full | + SUPPORTED_100baseT_Full; + ecmd->advertising = ADVERTISED_10000baseT_Full | + ADVERTISED_1000baseT_Full | + ADVERTISED_100baseT_Full; + break; default: /* all the rest are 10G/1G */ ecmd->supported = SUPPORTED_10000baseT_Full | @@ -322,9 +330,13 @@ static int i40e_get_settings(struct net_device *netdev, case I40E_PHY_TYPE_10GBASE_CR1: case I40E_PHY_TYPE_10GBASE_T: ecmd->supported = SUPPORTED_Autoneg | - SUPPORTED_10000baseT_Full; + SUPPORTED_10000baseT_Full | + SUPPORTED_1000baseT_Full | + SUPPORTED_100baseT_Full; ecmd->advertising = ADVERTISED_Autoneg | - ADVERTISED_10000baseT_Full; + ADVERTISED_10000baseT_Full | + ADVERTISED_1000baseT_Full | + ADVERTISED_100baseT_Full; break; case I40E_PHY_TYPE_XAUI: case I40E_PHY_TYPE_XFI: @@ -335,14 +347,22 @@ static int i40e_get_settings(struct net_device *netdev, case I40E_PHY_TYPE_1000BASE_KX: case I40E_PHY_TYPE_1000BASE_T: ecmd->supported = SUPPORTED_Autoneg | - SUPPORTED_1000baseT_Full; + SUPPORTED_10000baseT_Full | + SUPPORTED_1000baseT_Full | + SUPPORTED_100baseT_Full; ecmd->advertising = ADVERTISED_Autoneg | - ADVERTISED_1000baseT_Full; + ADVERTISED_10000baseT_Full | + ADVERTISED_1000baseT_Full | + ADVERTISED_100baseT_Full; break; case I40E_PHY_TYPE_100BASE_TX: ecmd->supported = SUPPORTED_Autoneg | + SUPPORTED_10000baseT_Full | + SUPPORTED_1000baseT_Full | SUPPORTED_100baseT_Full; ecmd->advertising = ADVERTISED_Autoneg | + ADVERTISED_10000baseT_Full | + ADVERTISED_1000baseT_Full | ADVERTISED_100baseT_Full; break; case I40E_PHY_TYPE_SGMII: @@ -426,6 +446,9 @@ no_valid_phy_type: case I40E_LINK_SPEED_1GB: ethtool_cmd_speed_set(ecmd, SPEED_1000); break; + case I40E_LINK_SPEED_100MB: + ethtool_cmd_speed_set(ecmd, SPEED_100); + break; default: break; } @@ -528,7 +551,7 @@ static int i40e_set_settings(struct net_device *netdev, } /* If autoneg is currently enabled */ if (hw->phy.link_info.an_info & I40E_AQ_AN_COMPLETED) { - config.abilities = abilities.abilities | + config.abilities = abilities.abilities & ~I40E_AQ_PHY_ENABLE_AN; change = true; } @@ -621,11 +644,19 @@ static void i40e_get_pauseparam(struct net_device *netdev, struct i40e_pf *pf = np->vsi->back; struct i40e_hw *hw = &pf->hw; struct i40e_link_status *hw_link_info = &hw->phy.link_info; + struct i40e_dcbx_config *dcbx_cfg = &hw->local_dcbx_config; pause->autoneg = ((hw_link_info->an_info & I40E_AQ_AN_COMPLETED) ? AUTONEG_ENABLE : AUTONEG_DISABLE); + /* PFC enabled so report LFC as off */ + if (dcbx_cfg->pfc.pfcenable) { + pause->rx_pause = 0; + pause->tx_pause = 0; + return; + } + if (hw->fc.current_mode == I40E_FC_RX_PAUSE) { pause->rx_pause = 1; } else if (hw->fc.current_mode == I40E_FC_TX_PAUSE) { @@ -649,6 +680,7 @@ static int i40e_set_pauseparam(struct net_device *netdev, struct i40e_vsi *vsi = np->vsi; struct i40e_hw *hw = &pf->hw; struct i40e_link_status *hw_link_info = &hw->phy.link_info; + struct i40e_dcbx_config *dcbx_cfg = &hw->local_dcbx_config; bool link_up = hw_link_info->link_info & I40E_AQ_LINK_UP; i40e_status status; u8 aq_failures; @@ -670,8 +702,9 @@ static int i40e_set_pauseparam(struct net_device *netdev, netdev_info(netdev, "Autoneg did not complete so changing settings may not result in an actual change.\n"); } - if (hw->fc.current_mode == I40E_FC_PFC) { - netdev_info(netdev, "Priority flow control enabled. Cannot set link flow control.\n"); + if (dcbx_cfg->pfc.pfcenable) { + netdev_info(netdev, + "Priority flow control enabled. Cannot set link flow control.\n"); return -EOPNOTSUPP; } @@ -1367,7 +1400,10 @@ static int i40e_intr_test(struct net_device *netdev, u64 *data) netif_info(pf, hw, netdev, "interrupt test\n"); wr32(&pf->hw, I40E_PFINT_DYN_CTL0, (I40E_PFINT_DYN_CTL0_INTENA_MASK | - I40E_PFINT_DYN_CTL0_SWINT_TRIG_MASK)); + I40E_PFINT_DYN_CTL0_SWINT_TRIG_MASK | + I40E_PFINT_DYN_CTL0_ITR_INDX_MASK | + I40E_PFINT_DYN_CTL0_SW_ITR_INDX_ENA_MASK | + I40E_PFINT_DYN_CTL0_SW_ITR_INDX_MASK)); usleep_range(1000, 2000); *data = (swc_old == pf->sw_int_count); @@ -1551,13 +1587,10 @@ static int i40e_set_coalesce(struct net_device *netdev, vsi->rx_itr_setting = ec->rx_coalesce_usecs; } else if (ec->rx_coalesce_usecs == 0) { vsi->rx_itr_setting = ec->rx_coalesce_usecs; - i40e_irq_dynamic_disable(vsi, vector); if (ec->use_adaptive_rx_coalesce) - netif_info(pf, drv, netdev, - "Rx-secs=0, need to disable adaptive-Rx for a complete disable\n"); + netif_info(pf, drv, netdev, "rx-usecs=0, need to disable adaptive-rx for a complete disable\n"); } else { - netif_info(pf, drv, netdev, - "Invalid value, Rx-usecs range is 0, 8-8160\n"); + netif_info(pf, drv, netdev, "Invalid value, rx-usecs range is 0-8160\n"); return -EINVAL; } @@ -1566,13 +1599,11 @@ static int i40e_set_coalesce(struct net_device *netdev, vsi->tx_itr_setting = ec->tx_coalesce_usecs; } else if (ec->tx_coalesce_usecs == 0) { vsi->tx_itr_setting = ec->tx_coalesce_usecs; - i40e_irq_dynamic_disable(vsi, vector); if (ec->use_adaptive_tx_coalesce) - netif_info(pf, drv, netdev, - "Tx-secs=0, need to disable adaptive-Tx for a complete disable\n"); + netif_info(pf, drv, netdev, "tx-usecs=0, need to disable adaptive-tx for a complete disable\n"); } else { netif_info(pf, drv, netdev, - "Invalid value, Tx-usecs range is 0, 8-8160\n"); + "Invalid value, tx-usecs range is 0-8160\n"); return -EINVAL; } diff --git a/drivers/net/ethernet/intel/i40e/i40e_fcoe.c b/drivers/net/ethernet/intel/i40e/i40e_fcoe.c index 5d01db1d789b..a8b8bd95108d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_fcoe.c +++ b/drivers/net/ethernet/intel/i40e/i40e_fcoe.c @@ -343,7 +343,7 @@ int i40e_init_pf_fcoe(struct i40e_pf *pf) **/ u8 i40e_get_fcoe_tc_map(struct i40e_pf *pf) { - struct i40e_ieee_app_priority_table app; + struct i40e_dcb_app_priority_table app; struct i40e_hw *hw = &pf->hw; u8 enabled_tc = 0; u8 tc, i; diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index c3a7f4a4b775..7262077ad547 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -38,8 +38,8 @@ static const char i40e_driver_string[] = #define DRV_KERN "-k" #define DRV_VERSION_MAJOR 1 -#define DRV_VERSION_MINOR 0 -#define DRV_VERSION_BUILD 11 +#define DRV_VERSION_MINOR 1 +#define DRV_VERSION_BUILD 23 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \ __stringify(DRV_VERSION_MINOR) "." \ __stringify(DRV_VERSION_BUILD) DRV_KERN @@ -74,6 +74,7 @@ static const struct pci_device_id i40e_pci_tbl[] = { {PCI_VDEVICE(INTEL, I40E_DEV_ID_QSFP_A), 0}, {PCI_VDEVICE(INTEL, I40E_DEV_ID_QSFP_B), 0}, {PCI_VDEVICE(INTEL, I40E_DEV_ID_QSFP_C), 0}, + {PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_BASE_T), 0}, /* required last entry */ {0, } }; @@ -812,7 +813,10 @@ static void i40e_update_vsi_stats(struct i40e_vsi *vsi) struct i40e_eth_stats *oes; struct i40e_eth_stats *es; /* device's eth stats */ u32 tx_restart, tx_busy; + struct i40e_ring *p; u32 rx_page, rx_buf; + u64 bytes, packets; + unsigned int start; u64 rx_p, rx_b; u64 tx_p, tx_b; u16 q; @@ -836,10 +840,6 @@ static void i40e_update_vsi_stats(struct i40e_vsi *vsi) rx_buf = 0; rcu_read_lock(); for (q = 0; q < vsi->num_queue_pairs; q++) { - struct i40e_ring *p; - u64 bytes, packets; - unsigned int start; - /* locate Tx ring */ p = ACCESS_ONCE(vsi->tx_rings[q]); @@ -2382,6 +2382,35 @@ static void i40e_vsi_free_rx_resources(struct i40e_vsi *vsi) } /** + * i40e_config_xps_tx_ring - Configure XPS for a Tx ring + * @ring: The Tx ring to configure + * + * This enables/disables XPS for a given Tx descriptor ring + * based on the TCs enabled for the VSI that ring belongs to. + **/ +static void i40e_config_xps_tx_ring(struct i40e_ring *ring) +{ + struct i40e_vsi *vsi = ring->vsi; + cpumask_var_t mask; + + if (ring->q_vector && ring->netdev) { + /* Single TC mode enable XPS */ + if (vsi->tc_config.numtc <= 1 && + !test_and_set_bit(__I40E_TX_XPS_INIT_DONE, &ring->state)) { + netif_set_xps_queue(ring->netdev, + &ring->q_vector->affinity_mask, + ring->queue_index); + } else if (alloc_cpumask_var(&mask, GFP_KERNEL)) { + /* Disable XPS to allow selection based on TC */ + bitmap_zero(cpumask_bits(mask), nr_cpumask_bits); + netif_set_xps_queue(ring->netdev, mask, + ring->queue_index); + free_cpumask_var(mask); + } + } +} + +/** * i40e_configure_tx_ring - Configure a transmit ring context and rest * @ring: The Tx ring to configure * @@ -2404,13 +2433,8 @@ static int i40e_configure_tx_ring(struct i40e_ring *ring) ring->atr_sample_rate = 0; } - /* initialize XPS */ - if (ring->q_vector && ring->netdev && - vsi->tc_config.numtc <= 1 && - !test_and_set_bit(__I40E_TX_XPS_INIT_DONE, &ring->state)) - netif_set_xps_queue(ring->netdev, - &ring->q_vector->affinity_mask, - ring->queue_index); + /* configure XPS */ + i40e_config_xps_tx_ring(ring); /* clear the context structure first */ memset(&tx_ctx, 0, sizeof(tx_ctx)); @@ -2462,10 +2486,14 @@ static int i40e_configure_tx_ring(struct i40e_ring *ring) } /* Now associate this queue with this PCI function */ - if (vsi->type == I40E_VSI_VMDQ2) + if (vsi->type == I40E_VSI_VMDQ2) { qtx_ctl = I40E_QTX_CTL_VM_QUEUE; - else + qtx_ctl |= ((vsi->id) << I40E_QTX_CTL_VFVM_INDX_SHIFT) & + I40E_QTX_CTL_VFVM_INDX_MASK; + } else { qtx_ctl = I40E_QTX_CTL_PF_QUEUE; + } + qtx_ctl |= ((hw->pf_id << I40E_QTX_CTL_PF_INDX_SHIFT) & I40E_QTX_CTL_PF_INDX_MASK); wr32(hw, I40E_QTX_CTL(pf_q), qtx_ctl); @@ -3440,7 +3468,7 @@ static int i40e_pf_txq_wait(struct i40e_pf *pf, int pf_q, bool enable) if (enable == !!(tx_reg & I40E_QTX_ENA_QENA_STAT_MASK)) break; - udelay(10); + usleep_range(10, 20); } if (i >= I40E_QUEUE_WAIT_RETRY_LIMIT) return -ETIMEDOUT; @@ -3466,7 +3494,7 @@ static int i40e_vsi_control_tx(struct i40e_vsi *vsi, bool enable) /* warn the TX unit of coming changes */ i40e_pre_tx_queue_cfg(&pf->hw, pf_q, enable); if (!enable) - udelay(10); + usleep_range(10, 20); for (j = 0; j < 50; j++) { tx_reg = rd32(hw, I40E_QTX_ENA(pf_q)); @@ -3488,6 +3516,9 @@ static int i40e_vsi_control_tx(struct i40e_vsi *vsi, bool enable) } wr32(hw, I40E_QTX_ENA(pf_q), tx_reg); + /* No waiting for the Tx queue to disable */ + if (!enable && test_bit(__I40E_PORT_TX_SUSPENDED, &pf->state)) + continue; /* wait for the change to finish */ ret = i40e_pf_txq_wait(pf, pf_q, enable); @@ -3526,7 +3557,7 @@ static int i40e_pf_rxq_wait(struct i40e_pf *pf, int pf_q, bool enable) if (enable == !!(rx_reg & I40E_QRX_ENA_QENA_STAT_MASK)) break; - udelay(10); + usleep_range(10, 20); } if (i >= I40E_QUEUE_WAIT_RETRY_LIMIT) return -ETIMEDOUT; @@ -3855,6 +3886,15 @@ static void i40e_quiesce_vsi(struct i40e_vsi *vsi) if (test_bit(__I40E_DOWN, &vsi->state)) return; + /* No need to disable FCoE VSI when Tx suspended */ + if ((test_bit(__I40E_PORT_TX_SUSPENDED, &vsi->back->state)) && + vsi->type == I40E_VSI_FCOE) { + dev_dbg(&vsi->back->pdev->dev, + "%s: VSI seid %d skipping FCoE VSI disable\n", + __func__, vsi->seid); + return; + } + set_bit(__I40E_NEEDS_RESTART, &vsi->state); if (vsi->netdev && netif_running(vsi->netdev)) { vsi->netdev->netdev_ops->ndo_stop(vsi->netdev); @@ -3907,6 +3947,57 @@ static void i40e_pf_unquiesce_all_vsi(struct i40e_pf *pf) } } +#ifdef CONFIG_I40E_DCB +/** + * i40e_vsi_wait_txq_disabled - Wait for VSI's queues to be disabled + * @vsi: the VSI being configured + * + * This function waits for the given VSI's Tx queues to be disabled. + **/ +static int i40e_vsi_wait_txq_disabled(struct i40e_vsi *vsi) +{ + struct i40e_pf *pf = vsi->back; + int i, pf_q, ret; + + pf_q = vsi->base_queue; + for (i = 0; i < vsi->num_queue_pairs; i++, pf_q++) { + /* Check and wait for the disable status of the queue */ + ret = i40e_pf_txq_wait(pf, pf_q, false); + if (ret) { + dev_info(&pf->pdev->dev, + "%s: VSI seid %d Tx ring %d disable timeout\n", + __func__, vsi->seid, pf_q); + return ret; + } + } + + return 0; +} + +/** + * i40e_pf_wait_txq_disabled - Wait for all queues of PF VSIs to be disabled + * @pf: the PF + * + * This function waits for the Tx queues to be in disabled state for all the + * VSIs that are managed by this PF. + **/ +static int i40e_pf_wait_txq_disabled(struct i40e_pf *pf) +{ + int v, ret = 0; + + for (v = 0; v < pf->hw.func_caps.num_vsis; v++) { + /* No need to wait for FCoE VSI queues */ + if (pf->vsi[v] && pf->vsi[v]->type != I40E_VSI_FCOE) { + ret = i40e_vsi_wait_txq_disabled(pf->vsi[v]); + if (ret) + break; + } + } + + return ret; +} + +#endif /** * i40e_dcb_get_num_tc - Get the number of TCs from DCBx config * @dcbcfg: the corresponding DCBx configuration structure @@ -4378,6 +4469,31 @@ static void i40e_dcb_reconfigure(struct i40e_pf *pf) } /** + * i40e_resume_port_tx - Resume port Tx + * @pf: PF struct + * + * Resume a port's Tx and issue a PF reset in case of failure to + * resume. + **/ +static int i40e_resume_port_tx(struct i40e_pf *pf) +{ + struct i40e_hw *hw = &pf->hw; + int ret; + + ret = i40e_aq_resume_port_tx(hw, NULL); + if (ret) { + dev_info(&pf->pdev->dev, + "AQ command Resume Port Tx failed = %d\n", + pf->hw.aq.asq_last_status); + /* Schedule PF reset to recover */ + set_bit(__I40E_PF_RESET_REQUESTED, &pf->state); + i40e_service_event_schedule(pf); + } + + return ret; +} + +/** * i40e_init_pf_dcb - Initialize DCB configuration * @pf: PF being configured * @@ -4413,6 +4529,8 @@ static int i40e_init_pf_dcb(struct i40e_pf *pf) /* Enable DCB tagging only when more than one TC */ if (i40e_dcb_get_num_tc(&hw->local_dcbx_config) > 1) pf->flags |= I40E_FLAG_DCB_ENABLED; + dev_dbg(&pf->pdev->dev, + "DCBX offload is supported for this PF.\n"); } } else { dev_info(&pf->pdev->dev, "AQ Querying DCB configuration failed: %d\n", @@ -4449,6 +4567,9 @@ static void i40e_print_link_message(struct i40e_vsi *vsi, bool isup) case I40E_LINK_SPEED_1GB: strlcpy(speed, "1000 Mbps", SPEED_SIZE); break; + case I40E_LINK_SPEED_100MB: + strncpy(speed, "100 Mbps", SPEED_SIZE); + break; default: break; } @@ -4479,12 +4600,8 @@ static void i40e_print_link_message(struct i40e_vsi *vsi, bool isup) static int i40e_up_complete(struct i40e_vsi *vsi) { struct i40e_pf *pf = vsi->back; - u8 set_fc_aq_fail = 0; int err; - /* force flow control off */ - i40e_set_fc(&pf->hw, &set_fc_aq_fail, true); - if (pf->flags & I40E_FLAG_MSIX_ENABLED) i40e_vsi_configure_msix(vsi); else @@ -4995,6 +5112,8 @@ bool i40e_dcb_need_reconfig(struct i40e_pf *pf, dev_dbg(&pf->pdev->dev, "APP Table change detected.\n"); } + dev_dbg(&pf->pdev->dev, "%s: need_reconfig=%d\n", __func__, + need_reconfig); return need_reconfig; } @@ -5022,11 +5141,16 @@ static int i40e_handle_lldp_event(struct i40e_pf *pf, /* Ignore if event is not for Nearest Bridge */ type = ((mib->type >> I40E_AQ_LLDP_BRIDGE_TYPE_SHIFT) & I40E_AQ_LLDP_BRIDGE_TYPE_MASK); + dev_dbg(&pf->pdev->dev, + "%s: LLDP event mib bridge type 0x%x\n", __func__, type); if (type != I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE) return ret; /* Check MIB Type and return if event for Remote MIB update */ type = mib->type & I40E_AQ_LLDP_MIB_TYPE_MASK; + dev_dbg(&pf->pdev->dev, + "%s: LLDP event mib type %s\n", __func__, + type ? "remote" : "local"); if (type == I40E_AQ_LLDP_MIB_REMOTE) { /* Update the remote cached instance and return */ ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_REMOTE, @@ -5035,12 +5159,14 @@ static int i40e_handle_lldp_event(struct i40e_pf *pf, goto exit; } - /* Convert/store the DCBX data from LLDPDU temporarily */ memset(&tmp_dcbx_cfg, 0, sizeof(tmp_dcbx_cfg)); - ret = i40e_lldp_to_dcb_config(e->msg_buf, &tmp_dcbx_cfg); + /* Store the old configuration */ + tmp_dcbx_cfg = *dcbx_cfg; + + /* Get updated DCBX data from firmware */ + ret = i40e_get_dcb_config(&pf->hw); if (ret) { - /* Error in LLDPDU parsing return */ - dev_info(&pf->pdev->dev, "Failed parsing LLDPDU from event buffer\n"); + dev_info(&pf->pdev->dev, "Failed querying DCB configuration data from firmware.\n"); goto exit; } @@ -5050,12 +5176,9 @@ static int i40e_handle_lldp_event(struct i40e_pf *pf, goto exit; } - need_reconfig = i40e_dcb_need_reconfig(pf, dcbx_cfg, &tmp_dcbx_cfg); - - i40e_dcbnl_flush_apps(pf, &tmp_dcbx_cfg); + need_reconfig = i40e_dcb_need_reconfig(pf, &tmp_dcbx_cfg, dcbx_cfg); - /* Overwrite the new configuration */ - *dcbx_cfg = tmp_dcbx_cfg; + i40e_dcbnl_flush_apps(pf, dcbx_cfg); if (!need_reconfig) goto exit; @@ -5066,13 +5189,24 @@ static int i40e_handle_lldp_event(struct i40e_pf *pf, else pf->flags &= ~I40E_FLAG_DCB_ENABLED; + set_bit(__I40E_PORT_TX_SUSPENDED, &pf->state); /* Reconfiguration needed quiesce all VSIs */ i40e_pf_quiesce_all_vsi(pf); /* Changes in configuration update VEB/VSI */ i40e_dcb_reconfigure(pf); - i40e_pf_unquiesce_all_vsi(pf); + ret = i40e_resume_port_tx(pf); + + clear_bit(__I40E_PORT_TX_SUSPENDED, &pf->state); + /* In case of error no point in resuming VSIs */ + if (ret) + goto exit; + + /* Wait for the PF's Tx queues to be disabled */ + ret = i40e_pf_wait_txq_disabled(pf); + if (!ret) + i40e_pf_unquiesce_all_vsi(pf); exit: return ret; } @@ -5212,6 +5346,9 @@ static void i40e_fdir_flush_and_replay(struct i40e_pf *pf) int flush_wait_retry = 50; int reg; + if (!(pf->flags & (I40E_FLAG_FD_SB_ENABLED | I40E_FLAG_FD_ATR_ENABLED))) + return; + if (time_after(jiffies, pf->fd_flush_timestamp + (I40E_MIN_FD_FLUSH_INTERVAL * HZ))) { set_bit(__I40E_FD_FLUSH_REQUESTED, &pf->state); @@ -5273,6 +5410,9 @@ static void i40e_fdir_reinit_subtask(struct i40e_pf *pf) if (test_bit(__I40E_DOWN, &pf->state)) return; + if (!(pf->flags & (I40E_FLAG_FD_SB_ENABLED | I40E_FLAG_FD_ATR_ENABLED))) + return; + if ((pf->fd_add_err >= I40E_MAX_FD_PROGRAM_ERROR) && (i40e_get_current_atr_cnt(pf) >= pf->fd_atr_cnt) && (i40e_get_current_atr_cnt(pf) > pf->fdir_pf_filter_count)) @@ -5353,14 +5493,21 @@ static void i40e_veb_link_event(struct i40e_veb *veb, bool link_up) static void i40e_link_event(struct i40e_pf *pf) { bool new_link, old_link; + struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi]; + + /* set this to force the get_link_status call to refresh state */ + pf->hw.phy.get_link_info = true; - new_link = (pf->hw.phy.link_info.link_info & I40E_AQ_LINK_UP); old_link = (pf->hw.phy.link_info_old.link_info & I40E_AQ_LINK_UP); + new_link = i40e_get_link_status(&pf->hw); - if (new_link == old_link) + if (new_link == old_link && + (test_bit(__I40E_DOWN, &vsi->state) || + new_link == netif_carrier_ok(vsi->netdev))) return; - if (!test_bit(__I40E_DOWN, &pf->vsi[pf->lan_vsi]->state)) - i40e_print_link_message(pf->vsi[pf->lan_vsi], new_link); + + if (!test_bit(__I40E_DOWN, &vsi->state)) + i40e_print_link_message(vsi, new_link); /* Notify the base of the switch tree connected to * the link. Floating VEBs are not notified. @@ -5368,7 +5515,7 @@ static void i40e_link_event(struct i40e_pf *pf) if (pf->lan_veb != I40E_NO_VEB && pf->veb[pf->lan_veb]) i40e_veb_link_event(pf->veb[pf->lan_veb], new_link); else - i40e_vsi_link_event(pf->vsi[pf->lan_vsi], new_link); + i40e_vsi_link_event(vsi, new_link); if (pf->vf) i40e_vc_notify_link_state(pf); @@ -5418,11 +5565,17 @@ static void i40e_check_hang_subtask(struct i40e_pf *pf) if (!(pf->flags & I40E_FLAG_MSIX_ENABLED)) { wr32(&vsi->back->hw, I40E_PFINT_DYN_CTL0, (I40E_PFINT_DYN_CTL0_INTENA_MASK | - I40E_PFINT_DYN_CTL0_SWINT_TRIG_MASK)); + I40E_PFINT_DYN_CTL0_SWINT_TRIG_MASK | + I40E_PFINT_DYN_CTL0_ITR_INDX_MASK | + I40E_PFINT_DYN_CTL0_SW_ITR_INDX_ENA_MASK | + I40E_PFINT_DYN_CTL0_SW_ITR_INDX_MASK)); } else { u16 vec = vsi->base_vector - 1; u32 val = (I40E_PFINT_DYN_CTLN_INTENA_MASK | - I40E_PFINT_DYN_CTLN_SWINT_TRIG_MASK); + I40E_PFINT_DYN_CTLN_SWINT_TRIG_MASK | + I40E_PFINT_DYN_CTLN_ITR_INDX_MASK | + I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_MASK | + I40E_PFINT_DYN_CTLN_SW_ITR_INDX_MASK); for (i = 0; i < vsi->num_q_vectors; i++, vec++) wr32(&vsi->back->hw, I40E_PFINT_DYN_CTLN(vec), val); @@ -5433,7 +5586,7 @@ static void i40e_check_hang_subtask(struct i40e_pf *pf) } /** - * i40e_watchdog_subtask - Check and bring link up + * i40e_watchdog_subtask - periodic checks not using event driven response * @pf: board private structure **/ static void i40e_watchdog_subtask(struct i40e_pf *pf) @@ -5445,6 +5598,15 @@ static void i40e_watchdog_subtask(struct i40e_pf *pf) test_bit(__I40E_CONFIG_BUSY, &pf->state)) return; + /* make sure we don't do these things too often */ + if (time_before(jiffies, (pf->service_timer_previous + + pf->service_timer_period))) + return; + pf->service_timer_previous = jiffies; + + i40e_check_hang_subtask(pf); + i40e_link_event(pf); + /* Update the stats for active netdevs so the network stack * can look at updated numbers whenever it cares to */ @@ -5525,33 +5687,20 @@ static void i40e_handle_link_event(struct i40e_pf *pf, memcpy(&pf->hw.phy.link_info_old, hw_link_info, sizeof(pf->hw.phy.link_info_old)); + /* Do a new status request to re-enable LSE reporting + * and load new status information into the hw struct + * This completely ignores any state information + * in the ARQ event info, instead choosing to always + * issue the AQ update link status command. + */ + i40e_link_event(pf); + /* check for unqualified module, if link is down */ if ((status->link_info & I40E_AQ_MEDIA_AVAILABLE) && (!(status->an_info & I40E_AQ_QUALIFIED_MODULE)) && (!(status->link_info & I40E_AQ_LINK_UP))) dev_err(&pf->pdev->dev, "The driver failed to link because an unqualified module was detected.\n"); - - /* update link status */ - hw_link_info->phy_type = (enum i40e_aq_phy_type)status->phy_type; - hw_link_info->link_speed = (enum i40e_aq_link_speed)status->link_speed; - hw_link_info->link_info = status->link_info; - hw_link_info->an_info = status->an_info; - hw_link_info->ext_info = status->ext_info; - hw_link_info->lse_enable = - le16_to_cpu(status->command_flags) & - I40E_AQ_LSE_ENABLE; - - /* process the event */ - i40e_link_event(pf); - - /* Do a new status request to re-enable LSE reporting - * and load new status information into the hw struct, - * then see if the status changed while processing the - * initial event. - */ - i40e_update_link_info(&pf->hw, true); - i40e_link_event(pf); } /** @@ -5607,13 +5756,12 @@ static void i40e_clean_adminq_subtask(struct i40e_pf *pf) if (oldval != val) wr32(&pf->hw, pf->hw.aq.asq.len, val); - event.msg_size = I40E_MAX_AQ_BUF_SIZE; - event.msg_buf = kzalloc(event.msg_size, GFP_KERNEL); + event.buf_len = I40E_MAX_AQ_BUF_SIZE; + event.msg_buf = kzalloc(event.buf_len, GFP_KERNEL); if (!event.msg_buf) return; do { - event.msg_size = I40E_MAX_AQ_BUF_SIZE; /* reinit each time */ ret = i40e_clean_arq_element(hw, &event, &pending); if (ret == I40E_ERR_ADMIN_QUEUE_NO_WORK) break; @@ -5634,7 +5782,7 @@ static void i40e_clean_adminq_subtask(struct i40e_pf *pf) le32_to_cpu(event.desc.cookie_high), le32_to_cpu(event.desc.cookie_low), event.msg_buf, - event.msg_size); + event.msg_len); break; case i40e_aqc_opc_lldp_update_mib: dev_dbg(&pf->pdev->dev, "ARQ: Update LLDP MIB event received\n"); @@ -5967,6 +6115,7 @@ static void i40e_send_version(struct i40e_pf *pf) static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit) { struct i40e_hw *hw = &pf->hw; + u8 set_fc_aq_fail = 0; i40e_status ret; u32 v; @@ -6038,6 +6187,20 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit) if (ret) goto end_core_reset; + /* driver is only interested in link up/down and module qualification + * reports from firmware + */ + ret = i40e_aq_set_phy_int_mask(&pf->hw, + I40E_AQ_EVENT_LINK_UPDOWN | + I40E_AQ_EVENT_MODULE_QUAL_FAIL, NULL); + if (ret) + dev_info(&pf->pdev->dev, "set phy mask fail, aq_err %d\n", ret); + + /* make sure our flow control settings are restored */ + ret = i40e_set_fc(&pf->hw, &set_fc_aq_fail, true); + if (ret) + dev_info(&pf->pdev->dev, "set fc fail, aq_err %d\n", ret); + /* Rebuild the VSIs and VEBs that existed before reset. * They are still in our local switch element arrays, so only * need to rebuild the switch model in the HW. @@ -6092,6 +6255,13 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit) } } + msleep(75); + ret = i40e_aq_set_link_restart_an(&pf->hw, true, NULL); + if (ret) { + dev_info(&pf->pdev->dev, "link restart failed, aq_err=%d\n", + pf->hw.aq.asq_last_status); + } + /* reinit the misc interrupt */ if (pf->flags & I40E_FLAG_MSIX_ENABLED) ret = i40e_setup_misc_vector(pf); @@ -6149,12 +6319,13 @@ static void i40e_handle_mdd_event(struct i40e_pf *pf) if (reg & I40E_GL_MDET_TX_VALID_MASK) { u8 pf_num = (reg & I40E_GL_MDET_TX_PF_NUM_MASK) >> I40E_GL_MDET_TX_PF_NUM_SHIFT; - u8 vf_num = (reg & I40E_GL_MDET_TX_VF_NUM_MASK) >> + u16 vf_num = (reg & I40E_GL_MDET_TX_VF_NUM_MASK) >> I40E_GL_MDET_TX_VF_NUM_SHIFT; u8 event = (reg & I40E_GL_MDET_TX_EVENT_MASK) >> I40E_GL_MDET_TX_EVENT_SHIFT; - u8 queue = (reg & I40E_GL_MDET_TX_QUEUE_MASK) >> - I40E_GL_MDET_TX_QUEUE_SHIFT; + u16 queue = ((reg & I40E_GL_MDET_TX_QUEUE_MASK) >> + I40E_GL_MDET_TX_QUEUE_SHIFT) - + pf->hw.func_caps.base_queue; if (netif_msg_tx_err(pf)) dev_info(&pf->pdev->dev, "Malicious Driver Detection event 0x%02x on TX queue %d pf number 0x%02x vf number 0x%02x\n", event, queue, pf_num, vf_num); @@ -6167,8 +6338,9 @@ static void i40e_handle_mdd_event(struct i40e_pf *pf) I40E_GL_MDET_RX_FUNCTION_SHIFT; u8 event = (reg & I40E_GL_MDET_RX_EVENT_MASK) >> I40E_GL_MDET_RX_EVENT_SHIFT; - u8 queue = (reg & I40E_GL_MDET_RX_QUEUE_MASK) >> - I40E_GL_MDET_RX_QUEUE_SHIFT; + u16 queue = ((reg & I40E_GL_MDET_RX_QUEUE_MASK) >> + I40E_GL_MDET_RX_QUEUE_SHIFT) - + pf->hw.func_caps.base_queue; if (netif_msg_rx_err(pf)) dev_info(&pf->pdev->dev, "Malicious Driver Detection event 0x%02x on RX queue %d of function 0x%02x\n", event, queue, func); @@ -6298,7 +6470,6 @@ static void i40e_service_task(struct work_struct *work) i40e_vc_process_vflr_event(pf); i40e_watchdog_subtask(pf); i40e_fdir_reinit_subtask(pf); - i40e_check_hang_subtask(pf); i40e_sync_filters_subtask(pf); #ifdef CONFIG_I40E_VXLAN i40e_sync_vxlan_filters_subtask(pf); @@ -6676,6 +6847,7 @@ static int i40e_init_msix(struct i40e_pf *pf) { i40e_status err = 0; struct i40e_hw *hw = &pf->hw; + int other_vecs = 0; int v_budget, i; int vec; @@ -6701,10 +6873,10 @@ static int i40e_init_msix(struct i40e_pf *pf) */ pf->num_lan_msix = pf->num_lan_qps - (pf->rss_size_max - pf->rss_size); pf->num_vmdq_msix = pf->num_vmdq_qps; - v_budget = 1 + pf->num_lan_msix; - v_budget += (pf->num_vmdq_vsis * pf->num_vmdq_msix); + other_vecs = 1; + other_vecs += (pf->num_vmdq_vsis * pf->num_vmdq_msix); if (pf->flags & I40E_FLAG_FD_SB_ENABLED) - v_budget++; + other_vecs++; #ifdef I40E_FCOE if (pf->flags & I40E_FLAG_FCOE_ENABLED) { @@ -6714,7 +6886,9 @@ static int i40e_init_msix(struct i40e_pf *pf) #endif /* Scale down if necessary, and the rings will share vectors */ - v_budget = min_t(int, v_budget, hw->func_caps.num_msix_vectors); + pf->num_lan_msix = min_t(int, pf->num_lan_msix, + (hw->func_caps.num_msix_vectors - other_vecs)); + v_budget = pf->num_lan_msix + other_vecs; pf->msix_entries = kcalloc(v_budget, sizeof(struct msix_entry), GFP_KERNEL); @@ -6964,20 +7138,16 @@ static int i40e_setup_misc_vector(struct i40e_pf *pf) **/ static int i40e_config_rss(struct i40e_pf *pf) { - /* Set of random keys generated using kernel random number generator */ - static const u32 seed[I40E_PFQF_HKEY_MAX_INDEX + 1] = {0x41b01687, - 0x183cfd8c, 0xce880440, 0x580cbc3c, 0x35897377, - 0x328b25e1, 0x4fa98922, 0xb7d90c14, 0xd5bad70d, - 0xcd15a2c1, 0xe8580225, 0x4a1e9d11, 0xfe5731be}; + u32 rss_key[I40E_PFQF_HKEY_MAX_INDEX + 1]; struct i40e_hw *hw = &pf->hw; u32 lut = 0; int i, j; u64 hena; u32 reg_val; - /* Fill out hash function seed */ + netdev_rss_key_fill(rss_key, sizeof(rss_key)); for (i = 0; i <= I40E_PFQF_HKEY_MAX_INDEX; i++) - wr32(hw, I40E_PFQF_HKEY(i), seed[i]); + wr32(hw, I40E_PFQF_HKEY(i), rss_key[i]); /* By default we enable TCP/UDP with IPv4/IPv6 ptypes */ hena = (u64)rd32(hw, I40E_PFQF_HENA(0)) | @@ -7356,18 +7526,18 @@ static int i40e_get_phys_port_id(struct net_device *netdev, return 0; } -#ifdef HAVE_FDB_OPS -#ifdef USE_CONST_DEV_UC_CHAR +/** + * i40e_ndo_fdb_add - add an entry to the hardware database + * @ndm: the input from the stack + * @tb: pointer to array of nladdr (unused) + * @dev: the net device pointer + * @addr: the MAC address entry being added + * @flags: instructions from stack about fdb operation + */ static int i40e_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], struct net_device *dev, const unsigned char *addr, u16 flags) -#else -static int i40e_ndo_fdb_add(struct ndmsg *ndm, - struct net_device *dev, - unsigned char *addr, - u16 flags) -#endif { struct i40e_netdev_priv *np = netdev_priv(dev); struct i40e_pf *pf = np->vsi->back; @@ -7398,55 +7568,6 @@ static int i40e_ndo_fdb_add(struct ndmsg *ndm, return err; } -#ifndef USE_DEFAULT_FDB_DEL_DUMP -#ifdef USE_CONST_DEV_UC_CHAR -static int i40e_ndo_fdb_del(struct ndmsg *ndm, - struct net_device *dev, - const unsigned char *addr) -#else -static int i40e_ndo_fdb_del(struct ndmsg *ndm, - struct net_device *dev, - unsigned char *addr) -#endif -{ - struct i40e_netdev_priv *np = netdev_priv(dev); - struct i40e_pf *pf = np->vsi->back; - int err = -EOPNOTSUPP; - - if (ndm->ndm_state & NUD_PERMANENT) { - netdev_info(dev, "FDB only supports static addresses\n"); - return -EINVAL; - } - - if (pf->flags & I40E_FLAG_SRIOV_ENABLED) { - if (is_unicast_ether_addr(addr)) - err = dev_uc_del(dev, addr); - else if (is_multicast_ether_addr(addr)) - err = dev_mc_del(dev, addr); - else - err = -EINVAL; - } - - return err; -} - -static int i40e_ndo_fdb_dump(struct sk_buff *skb, - struct netlink_callback *cb, - struct net_device *dev, - struct net_device *filter_dev, - int idx) -{ - struct i40e_netdev_priv *np = netdev_priv(dev); - struct i40e_pf *pf = np->vsi->back; - - if (pf->flags & I40E_FLAG_SRIOV_ENABLED) - idx = ndo_dflt_fdb_dump(skb, cb, dev, filter_dev, idx); - - return idx; -} - -#endif /* USE_DEFAULT_FDB_DEL_DUMP */ -#endif /* HAVE_FDB_OPS */ static const struct net_device_ops i40e_netdev_ops = { .ndo_open = i40e_open, .ndo_stop = i40e_close, @@ -7480,13 +7601,7 @@ static const struct net_device_ops i40e_netdev_ops = { .ndo_del_vxlan_port = i40e_del_vxlan_port, #endif .ndo_get_phys_port_id = i40e_get_phys_port_id, -#ifdef HAVE_FDB_OPS .ndo_fdb_add = i40e_ndo_fdb_add, -#ifndef USE_DEFAULT_FDB_DEL_DUMP - .ndo_fdb_del = i40e_ndo_fdb_del, - .ndo_fdb_dump = i40e_ndo_fdb_dump, -#endif -#endif }; /** @@ -7931,8 +8046,8 @@ static int i40e_vsi_setup_vectors(struct i40e_vsi *vsi) vsi->num_q_vectors, vsi->idx); if (vsi->base_vector < 0) { dev_info(&pf->pdev->dev, - "failed to get queue tracking for VSI %d, err=%d\n", - vsi->seid, vsi->base_vector); + "failed to get tracking for %d vectors for VSI %d, err=%d\n", + vsi->num_q_vectors, vsi->seid, vsi->base_vector); i40e_vsi_free_q_vectors(vsi); ret = -ENOENT; goto vector_setup_out; @@ -7968,8 +8083,9 @@ static struct i40e_vsi *i40e_vsi_reinit_setup(struct i40e_vsi *vsi) ret = i40e_get_lump(pf, pf->qp_pile, vsi->alloc_queue_pairs, vsi->idx); if (ret < 0) { - dev_info(&pf->pdev->dev, "VSI %d get_lump failed %d\n", - vsi->seid, ret); + dev_info(&pf->pdev->dev, + "failed to get tracking for %d queues for VSI %d err=%d\n", + vsi->alloc_queue_pairs, vsi->seid, ret); goto err_vsi; } vsi->base_queue = ret; @@ -8098,8 +8214,9 @@ struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type, ret = i40e_get_lump(pf, pf->qp_pile, vsi->alloc_queue_pairs, vsi->idx); if (ret < 0) { - dev_info(&pf->pdev->dev, "VSI %d get_lump failed %d\n", - vsi->seid, ret); + dev_info(&pf->pdev->dev, + "failed to get tracking for %d queues for VSI %d err=%d\n", + vsi->alloc_queue_pairs, vsi->seid, ret); goto err_vsi; } vsi->base_queue = ret; @@ -8206,6 +8323,7 @@ static int i40e_veb_get_bw_info(struct i40e_veb *veb) veb->bw_limit = le16_to_cpu(ets_data.port_bw_limit); veb->bw_max_quanta = ets_data.tc_bw_max; veb->is_abs_credits = bw_data.absolute_credits_enable; + veb->enabled_tc = ets_data.tc_valid_bits; tc_bw_max = le16_to_cpu(bw_data.tc_bw_max[0]) | (le16_to_cpu(bw_data.tc_bw_max[1]) << 16); for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { @@ -8719,6 +8837,14 @@ static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit) pf->fc_autoneg_status = ((pf->hw.phy.link_info.an_info & I40E_AQ_AN_COMPLETED) ? true : false); + /* fill in link information and enable LSE reporting */ + i40e_update_link_info(&pf->hw, true); + i40e_link_event(pf); + + /* Initialize user-specific link properties */ + pf->fc_autoneg_status = ((pf->hw.phy.link_info.an_info & + I40E_AQ_AN_COMPLETED) ? true : false); + i40e_ptp_init(pf); return ret; @@ -8987,6 +9113,11 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) hw->bus.func = PCI_FUNC(pdev->devfn); pf->instance = pfs_found; + if (debug != -1) { + pf->msg_enable = pf->hw.debug_mask; + pf->msg_enable = debug; + } + /* do a special CORER for clearing PXE mode once at init */ if (hw->revision_id == 0 && (rd32(hw, I40E_GLLAN_RCTL_0) & I40E_GLLAN_RCTL_0_PXE_MODE_MASK)) { @@ -9158,6 +9289,22 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } } + /* driver is only interested in link up/down and module qualification + * reports from firmware + */ + err = i40e_aq_set_phy_int_mask(&pf->hw, + I40E_AQ_EVENT_LINK_UPDOWN | + I40E_AQ_EVENT_MODULE_QUAL_FAIL, NULL); + if (err) + dev_info(&pf->pdev->dev, "set phy mask fail, aq_err %d\n", err); + + msleep(75); + err = i40e_aq_set_link_restart_an(&pf->hw, true, NULL); + if (err) { + dev_info(&pf->pdev->dev, "link restart failed, aq_err=%d\n", + pf->hw.aq.asq_last_status); + } + /* The main driver is (mostly) up and happy. We need to set this state * before setting up the misc vector or we get a race and the vector * ends up disabled forever. diff --git a/drivers/net/ethernet/intel/i40e/i40e_prototype.h b/drivers/net/ethernet/intel/i40e/i40e_prototype.h index 0988b5c1fe87..2fb4306597e8 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_prototype.h +++ b/drivers/net/ethernet/intel/i40e/i40e_prototype.h @@ -84,6 +84,8 @@ enum i40e_status_code i40e_aq_set_phy_config(struct i40e_hw *hw, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_set_fc(struct i40e_hw *hw, u8 *aq_failures, bool atomic_reset); +i40e_status i40e_aq_set_phy_int_mask(struct i40e_hw *hw, u16 mask, + struct i40e_asq_cmd_details *cmd_details); i40e_status i40e_aq_clear_pxe_mode(struct i40e_hw *hw, struct i40e_asq_cmd_details *cmd_details); i40e_status i40e_aq_set_link_restart_an(struct i40e_hw *hw, @@ -173,6 +175,9 @@ i40e_status i40e_aq_stop_lldp(struct i40e_hw *hw, bool shutdown_agent, struct i40e_asq_cmd_details *cmd_details); i40e_status i40e_aq_start_lldp(struct i40e_hw *hw, struct i40e_asq_cmd_details *cmd_details); +i40e_status i40e_aq_get_cee_dcb_config(struct i40e_hw *hw, + void *buff, u16 buff_size, + struct i40e_asq_cmd_details *cmd_details); i40e_status i40e_aq_add_udp_tunnel(struct i40e_hw *hw, u16 udp_port, u8 protocol_index, u8 *filter_index, @@ -228,6 +233,10 @@ i40e_status i40e_aq_query_switch_comp_bw_config(struct i40e_hw *hw, u16 seid, struct i40e_aqc_query_switching_comp_bw_config_resp *bw_data, struct i40e_asq_cmd_details *cmd_details); +i40e_status i40e_aq_resume_port_tx(struct i40e_hw *hw, + struct i40e_asq_cmd_details *cmd_details); +i40e_status i40e_read_lldp_cfg(struct i40e_hw *hw, + struct i40e_lldp_variables *lldp_cfg); /* i40e_common */ i40e_status i40e_init_shared_code(struct i40e_hw *hw); i40e_status i40e_pf_reset(struct i40e_hw *hw); diff --git a/drivers/net/ethernet/intel/i40e/i40e_ptp.c b/drivers/net/ethernet/intel/i40e/i40e_ptp.c index 537b6216971d..f91510370c35 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ptp.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ptp.c @@ -382,11 +382,17 @@ void i40e_ptp_set_increment(struct i40e_pf *pf) incval = I40E_PTP_1GB_INCVAL; break; case I40E_LINK_SPEED_100MB: - dev_warn(&pf->pdev->dev, - "%s: 1588 functionality is not supported at 100 Mbps. Stopping the PHC.\n", - __func__); + { + static int warn_once; + + if (!warn_once) { + dev_warn(&pf->pdev->dev, + "1588 functionality is not supported at 100 Mbps. Stopping the PHC.\n"); + warn_once++; + } incval = 0; break; + } case I40E_LINK_SPEED_40GB: default: incval = I40E_PTP_40GB_INCVAL; diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h index d7a625a6a14f..e60d3accb2e2 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h @@ -30,10 +30,7 @@ /* Interrupt Throttling and Rate Limiting Goodies */ #define I40E_MAX_ITR 0x0FF0 /* reg uses 2 usec resolution */ -#define I40E_MIN_ITR 0x0004 /* reg uses 2 usec resolution */ -#define I40E_MAX_IRATE 0x03F -#define I40E_MIN_IRATE 0x001 -#define I40E_IRATE_USEC_RESOLUTION 4 +#define I40E_MIN_ITR 0x0001 /* reg uses 2 usec resolution */ #define I40E_ITR_100K 0x0005 #define I40E_ITR_20K 0x0019 #define I40E_ITR_8K 0x003E diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index ce04d9093db6..c85214373a51 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -43,6 +43,7 @@ #define I40E_DEV_ID_QSFP_A 0x1583 #define I40E_DEV_ID_QSFP_B 0x1584 #define I40E_DEV_ID_QSFP_C 0x1585 +#define I40E_DEV_ID_10G_BASE_T 0x1586 #define I40E_DEV_ID_VF 0x154C #define I40E_DEV_ID_VF_HV 0x1571 @@ -380,9 +381,18 @@ struct i40e_fc_info { #define I40E_MAX_USER_PRIORITY 8 #define I40E_DCBX_MAX_APPS 32 #define I40E_LLDPDU_SIZE 1500 - -/* IEEE 802.1Qaz ETS Configuration data */ -struct i40e_ieee_ets_config { +#define I40E_TLV_STATUS_OPER 0x1 +#define I40E_TLV_STATUS_SYNC 0x2 +#define I40E_TLV_STATUS_ERR 0x4 +#define I40E_CEE_OPER_MAX_APPS 3 +#define I40E_APP_PROTOID_FCOE 0x8906 +#define I40E_APP_PROTOID_ISCSI 0x0cbc +#define I40E_APP_PROTOID_FIP 0x8914 +#define I40E_APP_SEL_ETHTYPE 0x1 +#define I40E_APP_SEL_TCPIP 0x2 + +/* CEE or IEEE 802.1Qaz ETS Configuration data */ +struct i40e_dcb_ets_config { u8 willing; u8 cbs; u8 maxtcs; @@ -391,34 +401,30 @@ struct i40e_ieee_ets_config { u8 tsatable[I40E_MAX_TRAFFIC_CLASS]; }; -/* IEEE 802.1Qaz ETS Recommendation data */ -struct i40e_ieee_ets_recommend { - u8 prioritytable[I40E_MAX_TRAFFIC_CLASS]; - u8 tcbwtable[I40E_MAX_TRAFFIC_CLASS]; - u8 tsatable[I40E_MAX_TRAFFIC_CLASS]; -}; - -/* IEEE 802.1Qaz PFC Configuration data */ -struct i40e_ieee_pfc_config { +/* CEE or IEEE 802.1Qaz PFC Configuration data */ +struct i40e_dcb_pfc_config { u8 willing; u8 mbc; u8 pfccap; u8 pfcenable; }; -/* IEEE 802.1Qaz Application Priority data */ -struct i40e_ieee_app_priority_table { +/* CEE or IEEE 802.1Qaz Application Priority data */ +struct i40e_dcb_app_priority_table { u8 priority; u8 selector; u16 protocolid; }; struct i40e_dcbx_config { + u8 dcbx_mode; +#define I40E_DCBX_MODE_CEE 0x1 +#define I40E_DCBX_MODE_IEEE 0x2 u32 numapps; - struct i40e_ieee_ets_config etscfg; - struct i40e_ieee_ets_recommend etsrec; - struct i40e_ieee_pfc_config pfc; - struct i40e_ieee_app_priority_table app[I40E_DCBX_MAX_APPS]; + struct i40e_dcb_ets_config etscfg; + struct i40e_dcb_ets_config etsrec; + struct i40e_dcb_pfc_config pfc; + struct i40e_dcb_app_priority_table app[I40E_DCBX_MAX_APPS]; }; /* Port hardware description */ @@ -1371,6 +1377,18 @@ enum i40e_reset_type { I40E_RESET_EMPR = 3, }; +/* IEEE 802.1AB LLDP Agent Variables from NVM */ +#define I40E_NVM_LLDP_CFG_PTR 0xD +struct i40e_lldp_variables { + u16 length; + u16 adminstatus; + u16 msgfasttx; + u16 msgtxinterval; + u16 txparams; + u16 timers; + u16 crc8; +}; + /* RSS Hash Table Size */ #define I40E_PFQF_CTL_0_HASHLUTSIZE_512 0x00010000 #endif /* _I40E_TYPE_H_ */ diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 4eeed267e4b7..668d860275d6 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -674,7 +674,7 @@ void i40e_reset_vf(struct i40e_vf *vf, bool flr) * that the requested op was completed * successfully */ - udelay(10); + usleep_range(10, 20); reg = rd32(hw, I40E_VPGEN_VFRSTAT(vf->vf_id)); if (reg & I40E_VPGEN_VFRSTAT_VFRD_MASK) { rsd = true; @@ -1869,6 +1869,12 @@ int i40e_vc_process_vflr_event(struct i40e_pf *pf) if (!test_bit(__I40E_VFLR_EVENT_PENDING, &pf->state)) return 0; + /* re-enable vflr interrupt cause */ + reg = rd32(hw, I40E_PFINT_ICR0_ENA); + reg |= I40E_PFINT_ICR0_ENA_VFLR_MASK; + wr32(hw, I40E_PFINT_ICR0_ENA, reg); + i40e_flush(hw); + clear_bit(__I40E_VFLR_EVENT_PENDING, &pf->state); for (vf_id = 0; vf_id < pf->num_alloc_vfs; vf_id++) { reg_idx = (hw->func_caps.vf_base_id + vf_id) / 32; @@ -1885,12 +1891,6 @@ int i40e_vc_process_vflr_event(struct i40e_pf *pf) } } - /* re-enable vflr interrupt cause */ - reg = rd32(hw, I40E_PFINT_ICR0_ENA); - reg |= I40E_PFINT_ICR0_ENA_VFLR_MASK; - wr32(hw, I40E_PFINT_ICR0_ENA, reg); - i40e_flush(hw); - return 0; } diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq.c b/drivers/net/ethernet/intel/i40evf/i40e_adminq.c index f206be917842..d7e446f3e7a4 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_adminq.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq.c @@ -801,7 +801,6 @@ i40e_status i40evf_asq_send_command(struct i40e_hw *hw, */ if (!details->async && !details->postpone) { u32 total_delay = 0; - u32 delay_len = 10; do { /* AQ designers suggest use of head for better @@ -809,9 +808,8 @@ i40e_status i40evf_asq_send_command(struct i40e_hw *hw, */ if (i40evf_asq_done(hw)) break; - /* ugh! delay while spin_lock */ - udelay(delay_len); - total_delay += delay_len; + usleep_range(1000, 2000); + total_delay++; } while (total_delay < hw->aq.asq_cmd_timeout); } @@ -931,10 +929,10 @@ i40e_status i40evf_clean_arq_element(struct i40e_hw *hw, e->desc = *desc; datalen = le16_to_cpu(desc->datalen); - e->msg_size = min(datalen, e->msg_size); - if (e->msg_buf != NULL && (e->msg_size != 0)) + e->msg_len = min(datalen, e->buf_len); + if (e->msg_buf != NULL && (e->msg_len != 0)) memcpy(e->msg_buf, hw->aq.arq.r.arq_bi[desc_idx].va, - e->msg_size); + e->msg_len); if (i40e_is_nvm_update_op(&e->desc)) hw->aq.nvm_busy = false; diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq.h index 91a5c5bd80f3..0d58378be740 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_adminq.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq.h @@ -76,7 +76,8 @@ struct i40e_asq_cmd_details { /* ARQ event information */ struct i40e_arq_event_info { struct i40e_aq_desc desc; - u16 msg_size; + u16 msg_len; + u16 buf_len; u8 *msg_buf; }; @@ -141,7 +142,7 @@ static inline int i40e_aq_rc_to_posix(u16 aq_rc) /* general information */ #define I40E_AQ_LARGE_BUF 512 -#define I40E_ASQ_CMD_TIMEOUT 100000 /* usecs */ +#define I40E_ASQ_CMD_TIMEOUT 100 /* msecs */ void i40evf_fill_default_direct_cmd_desc(struct i40e_aq_desc *desc, u16 opcode); diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h index e656ea7a7920..ff1b16370da9 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h @@ -33,8 +33,8 @@ * This file needs to comply with the Linux Kernel coding style. */ -#define I40E_FW_API_VERSION_MAJOR 0x0001 -#define I40E_FW_API_VERSION_MINOR 0x0002 +#define I40E_FW_API_VERSION_MAJOR 0x0001 +#define I40E_FW_API_VERSION_MINOR 0x0002 #define I40E_FW_API_VERSION_A0_MINOR 0x0000 struct i40e_aq_desc { @@ -67,216 +67,216 @@ struct i40e_aq_desc { */ /* command flags and offsets*/ -#define I40E_AQ_FLAG_DD_SHIFT 0 -#define I40E_AQ_FLAG_CMP_SHIFT 1 -#define I40E_AQ_FLAG_ERR_SHIFT 2 -#define I40E_AQ_FLAG_VFE_SHIFT 3 -#define I40E_AQ_FLAG_LB_SHIFT 9 -#define I40E_AQ_FLAG_RD_SHIFT 10 -#define I40E_AQ_FLAG_VFC_SHIFT 11 -#define I40E_AQ_FLAG_BUF_SHIFT 12 -#define I40E_AQ_FLAG_SI_SHIFT 13 -#define I40E_AQ_FLAG_EI_SHIFT 14 -#define I40E_AQ_FLAG_FE_SHIFT 15 - -#define I40E_AQ_FLAG_DD (1 << I40E_AQ_FLAG_DD_SHIFT) /* 0x1 */ -#define I40E_AQ_FLAG_CMP (1 << I40E_AQ_FLAG_CMP_SHIFT) /* 0x2 */ -#define I40E_AQ_FLAG_ERR (1 << I40E_AQ_FLAG_ERR_SHIFT) /* 0x4 */ -#define I40E_AQ_FLAG_VFE (1 << I40E_AQ_FLAG_VFE_SHIFT) /* 0x8 */ -#define I40E_AQ_FLAG_LB (1 << I40E_AQ_FLAG_LB_SHIFT) /* 0x200 */ -#define I40E_AQ_FLAG_RD (1 << I40E_AQ_FLAG_RD_SHIFT) /* 0x400 */ -#define I40E_AQ_FLAG_VFC (1 << I40E_AQ_FLAG_VFC_SHIFT) /* 0x800 */ -#define I40E_AQ_FLAG_BUF (1 << I40E_AQ_FLAG_BUF_SHIFT) /* 0x1000 */ -#define I40E_AQ_FLAG_SI (1 << I40E_AQ_FLAG_SI_SHIFT) /* 0x2000 */ -#define I40E_AQ_FLAG_EI (1 << I40E_AQ_FLAG_EI_SHIFT) /* 0x4000 */ -#define I40E_AQ_FLAG_FE (1 << I40E_AQ_FLAG_FE_SHIFT) /* 0x8000 */ +#define I40E_AQ_FLAG_DD_SHIFT 0 +#define I40E_AQ_FLAG_CMP_SHIFT 1 +#define I40E_AQ_FLAG_ERR_SHIFT 2 +#define I40E_AQ_FLAG_VFE_SHIFT 3 +#define I40E_AQ_FLAG_LB_SHIFT 9 +#define I40E_AQ_FLAG_RD_SHIFT 10 +#define I40E_AQ_FLAG_VFC_SHIFT 11 +#define I40E_AQ_FLAG_BUF_SHIFT 12 +#define I40E_AQ_FLAG_SI_SHIFT 13 +#define I40E_AQ_FLAG_EI_SHIFT 14 +#define I40E_AQ_FLAG_FE_SHIFT 15 + +#define I40E_AQ_FLAG_DD (1 << I40E_AQ_FLAG_DD_SHIFT) /* 0x1 */ +#define I40E_AQ_FLAG_CMP (1 << I40E_AQ_FLAG_CMP_SHIFT) /* 0x2 */ +#define I40E_AQ_FLAG_ERR (1 << I40E_AQ_FLAG_ERR_SHIFT) /* 0x4 */ +#define I40E_AQ_FLAG_VFE (1 << I40E_AQ_FLAG_VFE_SHIFT) /* 0x8 */ +#define I40E_AQ_FLAG_LB (1 << I40E_AQ_FLAG_LB_SHIFT) /* 0x200 */ +#define I40E_AQ_FLAG_RD (1 << I40E_AQ_FLAG_RD_SHIFT) /* 0x400 */ +#define I40E_AQ_FLAG_VFC (1 << I40E_AQ_FLAG_VFC_SHIFT) /* 0x800 */ +#define I40E_AQ_FLAG_BUF (1 << I40E_AQ_FLAG_BUF_SHIFT) /* 0x1000 */ +#define I40E_AQ_FLAG_SI (1 << I40E_AQ_FLAG_SI_SHIFT) /* 0x2000 */ +#define I40E_AQ_FLAG_EI (1 << I40E_AQ_FLAG_EI_SHIFT) /* 0x4000 */ +#define I40E_AQ_FLAG_FE (1 << I40E_AQ_FLAG_FE_SHIFT) /* 0x8000 */ /* error codes */ enum i40e_admin_queue_err { - I40E_AQ_RC_OK = 0, /* success */ - I40E_AQ_RC_EPERM = 1, /* Operation not permitted */ - I40E_AQ_RC_ENOENT = 2, /* No such element */ - I40E_AQ_RC_ESRCH = 3, /* Bad opcode */ - I40E_AQ_RC_EINTR = 4, /* operation interrupted */ - I40E_AQ_RC_EIO = 5, /* I/O error */ - I40E_AQ_RC_ENXIO = 6, /* No such resource */ - I40E_AQ_RC_E2BIG = 7, /* Arg too long */ - I40E_AQ_RC_EAGAIN = 8, /* Try again */ - I40E_AQ_RC_ENOMEM = 9, /* Out of memory */ - I40E_AQ_RC_EACCES = 10, /* Permission denied */ - I40E_AQ_RC_EFAULT = 11, /* Bad address */ - I40E_AQ_RC_EBUSY = 12, /* Device or resource busy */ - I40E_AQ_RC_EEXIST = 13, /* object already exists */ - I40E_AQ_RC_EINVAL = 14, /* Invalid argument */ - I40E_AQ_RC_ENOTTY = 15, /* Not a typewriter */ - I40E_AQ_RC_ENOSPC = 16, /* No space left or alloc failure */ - I40E_AQ_RC_ENOSYS = 17, /* Function not implemented */ - I40E_AQ_RC_ERANGE = 18, /* Parameter out of range */ - I40E_AQ_RC_EFLUSHED = 19, /* Cmd flushed because of prev cmd error */ - I40E_AQ_RC_BAD_ADDR = 20, /* Descriptor contains a bad pointer */ - I40E_AQ_RC_EMODE = 21, /* Op not allowed in current dev mode */ - I40E_AQ_RC_EFBIG = 22, /* File too large */ + I40E_AQ_RC_OK = 0, /* success */ + I40E_AQ_RC_EPERM = 1, /* Operation not permitted */ + I40E_AQ_RC_ENOENT = 2, /* No such element */ + I40E_AQ_RC_ESRCH = 3, /* Bad opcode */ + I40E_AQ_RC_EINTR = 4, /* operation interrupted */ + I40E_AQ_RC_EIO = 5, /* I/O error */ + I40E_AQ_RC_ENXIO = 6, /* No such resource */ + I40E_AQ_RC_E2BIG = 7, /* Arg too long */ + I40E_AQ_RC_EAGAIN = 8, /* Try again */ + I40E_AQ_RC_ENOMEM = 9, /* Out of memory */ + I40E_AQ_RC_EACCES = 10, /* Permission denied */ + I40E_AQ_RC_EFAULT = 11, /* Bad address */ + I40E_AQ_RC_EBUSY = 12, /* Device or resource busy */ + I40E_AQ_RC_EEXIST = 13, /* object already exists */ + I40E_AQ_RC_EINVAL = 14, /* Invalid argument */ + I40E_AQ_RC_ENOTTY = 15, /* Not a typewriter */ + I40E_AQ_RC_ENOSPC = 16, /* No space left or alloc failure */ + I40E_AQ_RC_ENOSYS = 17, /* Function not implemented */ + I40E_AQ_RC_ERANGE = 18, /* Parameter out of range */ + I40E_AQ_RC_EFLUSHED = 19, /* Cmd flushed due to prev cmd error */ + I40E_AQ_RC_BAD_ADDR = 20, /* Descriptor contains a bad pointer */ + I40E_AQ_RC_EMODE = 21, /* Op not allowed in current dev mode */ + I40E_AQ_RC_EFBIG = 22, /* File too large */ }; /* Admin Queue command opcodes */ enum i40e_admin_queue_opc { /* aq commands */ - i40e_aqc_opc_get_version = 0x0001, - i40e_aqc_opc_driver_version = 0x0002, - i40e_aqc_opc_queue_shutdown = 0x0003, - i40e_aqc_opc_set_pf_context = 0x0004, + i40e_aqc_opc_get_version = 0x0001, + i40e_aqc_opc_driver_version = 0x0002, + i40e_aqc_opc_queue_shutdown = 0x0003, + i40e_aqc_opc_set_pf_context = 0x0004, /* resource ownership */ - i40e_aqc_opc_request_resource = 0x0008, - i40e_aqc_opc_release_resource = 0x0009, + i40e_aqc_opc_request_resource = 0x0008, + i40e_aqc_opc_release_resource = 0x0009, - i40e_aqc_opc_list_func_capabilities = 0x000A, - i40e_aqc_opc_list_dev_capabilities = 0x000B, + i40e_aqc_opc_list_func_capabilities = 0x000A, + i40e_aqc_opc_list_dev_capabilities = 0x000B, - i40e_aqc_opc_set_cppm_configuration = 0x0103, - i40e_aqc_opc_set_arp_proxy_entry = 0x0104, - i40e_aqc_opc_set_ns_proxy_entry = 0x0105, + i40e_aqc_opc_set_cppm_configuration = 0x0103, + i40e_aqc_opc_set_arp_proxy_entry = 0x0104, + i40e_aqc_opc_set_ns_proxy_entry = 0x0105, /* LAA */ - i40e_aqc_opc_mng_laa = 0x0106, /* AQ obsolete */ - i40e_aqc_opc_mac_address_read = 0x0107, - i40e_aqc_opc_mac_address_write = 0x0108, + i40e_aqc_opc_mng_laa = 0x0106, /* AQ obsolete */ + i40e_aqc_opc_mac_address_read = 0x0107, + i40e_aqc_opc_mac_address_write = 0x0108, /* PXE */ - i40e_aqc_opc_clear_pxe_mode = 0x0110, + i40e_aqc_opc_clear_pxe_mode = 0x0110, /* internal switch commands */ - i40e_aqc_opc_get_switch_config = 0x0200, - i40e_aqc_opc_add_statistics = 0x0201, - i40e_aqc_opc_remove_statistics = 0x0202, - i40e_aqc_opc_set_port_parameters = 0x0203, - i40e_aqc_opc_get_switch_resource_alloc = 0x0204, - - i40e_aqc_opc_add_vsi = 0x0210, - i40e_aqc_opc_update_vsi_parameters = 0x0211, - i40e_aqc_opc_get_vsi_parameters = 0x0212, - - i40e_aqc_opc_add_pv = 0x0220, - i40e_aqc_opc_update_pv_parameters = 0x0221, - i40e_aqc_opc_get_pv_parameters = 0x0222, - - i40e_aqc_opc_add_veb = 0x0230, - i40e_aqc_opc_update_veb_parameters = 0x0231, - i40e_aqc_opc_get_veb_parameters = 0x0232, - - i40e_aqc_opc_delete_element = 0x0243, - - i40e_aqc_opc_add_macvlan = 0x0250, - i40e_aqc_opc_remove_macvlan = 0x0251, - i40e_aqc_opc_add_vlan = 0x0252, - i40e_aqc_opc_remove_vlan = 0x0253, - i40e_aqc_opc_set_vsi_promiscuous_modes = 0x0254, - i40e_aqc_opc_add_tag = 0x0255, - i40e_aqc_opc_remove_tag = 0x0256, - i40e_aqc_opc_add_multicast_etag = 0x0257, - i40e_aqc_opc_remove_multicast_etag = 0x0258, - i40e_aqc_opc_update_tag = 0x0259, - i40e_aqc_opc_add_control_packet_filter = 0x025A, - i40e_aqc_opc_remove_control_packet_filter = 0x025B, - i40e_aqc_opc_add_cloud_filters = 0x025C, - i40e_aqc_opc_remove_cloud_filters = 0x025D, - - i40e_aqc_opc_add_mirror_rule = 0x0260, - i40e_aqc_opc_delete_mirror_rule = 0x0261, + i40e_aqc_opc_get_switch_config = 0x0200, + i40e_aqc_opc_add_statistics = 0x0201, + i40e_aqc_opc_remove_statistics = 0x0202, + i40e_aqc_opc_set_port_parameters = 0x0203, + i40e_aqc_opc_get_switch_resource_alloc = 0x0204, + + i40e_aqc_opc_add_vsi = 0x0210, + i40e_aqc_opc_update_vsi_parameters = 0x0211, + i40e_aqc_opc_get_vsi_parameters = 0x0212, + + i40e_aqc_opc_add_pv = 0x0220, + i40e_aqc_opc_update_pv_parameters = 0x0221, + i40e_aqc_opc_get_pv_parameters = 0x0222, + + i40e_aqc_opc_add_veb = 0x0230, + i40e_aqc_opc_update_veb_parameters = 0x0231, + i40e_aqc_opc_get_veb_parameters = 0x0232, + + i40e_aqc_opc_delete_element = 0x0243, + + i40e_aqc_opc_add_macvlan = 0x0250, + i40e_aqc_opc_remove_macvlan = 0x0251, + i40e_aqc_opc_add_vlan = 0x0252, + i40e_aqc_opc_remove_vlan = 0x0253, + i40e_aqc_opc_set_vsi_promiscuous_modes = 0x0254, + i40e_aqc_opc_add_tag = 0x0255, + i40e_aqc_opc_remove_tag = 0x0256, + i40e_aqc_opc_add_multicast_etag = 0x0257, + i40e_aqc_opc_remove_multicast_etag = 0x0258, + i40e_aqc_opc_update_tag = 0x0259, + i40e_aqc_opc_add_control_packet_filter = 0x025A, + i40e_aqc_opc_remove_control_packet_filter = 0x025B, + i40e_aqc_opc_add_cloud_filters = 0x025C, + i40e_aqc_opc_remove_cloud_filters = 0x025D, + + i40e_aqc_opc_add_mirror_rule = 0x0260, + i40e_aqc_opc_delete_mirror_rule = 0x0261, /* DCB commands */ - i40e_aqc_opc_dcb_ignore_pfc = 0x0301, - i40e_aqc_opc_dcb_updated = 0x0302, + i40e_aqc_opc_dcb_ignore_pfc = 0x0301, + i40e_aqc_opc_dcb_updated = 0x0302, /* TX scheduler */ - i40e_aqc_opc_configure_vsi_bw_limit = 0x0400, - i40e_aqc_opc_configure_vsi_ets_sla_bw_limit = 0x0406, - i40e_aqc_opc_configure_vsi_tc_bw = 0x0407, - i40e_aqc_opc_query_vsi_bw_config = 0x0408, - i40e_aqc_opc_query_vsi_ets_sla_config = 0x040A, - i40e_aqc_opc_configure_switching_comp_bw_limit = 0x0410, - - i40e_aqc_opc_enable_switching_comp_ets = 0x0413, - i40e_aqc_opc_modify_switching_comp_ets = 0x0414, - i40e_aqc_opc_disable_switching_comp_ets = 0x0415, - i40e_aqc_opc_configure_switching_comp_ets_bw_limit = 0x0416, - i40e_aqc_opc_configure_switching_comp_bw_config = 0x0417, - i40e_aqc_opc_query_switching_comp_ets_config = 0x0418, - i40e_aqc_opc_query_port_ets_config = 0x0419, - i40e_aqc_opc_query_switching_comp_bw_config = 0x041A, - i40e_aqc_opc_suspend_port_tx = 0x041B, - i40e_aqc_opc_resume_port_tx = 0x041C, - i40e_aqc_opc_configure_partition_bw = 0x041D, + i40e_aqc_opc_configure_vsi_bw_limit = 0x0400, + i40e_aqc_opc_configure_vsi_ets_sla_bw_limit = 0x0406, + i40e_aqc_opc_configure_vsi_tc_bw = 0x0407, + i40e_aqc_opc_query_vsi_bw_config = 0x0408, + i40e_aqc_opc_query_vsi_ets_sla_config = 0x040A, + i40e_aqc_opc_configure_switching_comp_bw_limit = 0x0410, + + i40e_aqc_opc_enable_switching_comp_ets = 0x0413, + i40e_aqc_opc_modify_switching_comp_ets = 0x0414, + i40e_aqc_opc_disable_switching_comp_ets = 0x0415, + i40e_aqc_opc_configure_switching_comp_ets_bw_limit = 0x0416, + i40e_aqc_opc_configure_switching_comp_bw_config = 0x0417, + i40e_aqc_opc_query_switching_comp_ets_config = 0x0418, + i40e_aqc_opc_query_port_ets_config = 0x0419, + i40e_aqc_opc_query_switching_comp_bw_config = 0x041A, + i40e_aqc_opc_suspend_port_tx = 0x041B, + i40e_aqc_opc_resume_port_tx = 0x041C, + i40e_aqc_opc_configure_partition_bw = 0x041D, /* hmc */ - i40e_aqc_opc_query_hmc_resource_profile = 0x0500, - i40e_aqc_opc_set_hmc_resource_profile = 0x0501, + i40e_aqc_opc_query_hmc_resource_profile = 0x0500, + i40e_aqc_opc_set_hmc_resource_profile = 0x0501, /* phy commands*/ - i40e_aqc_opc_get_phy_abilities = 0x0600, - i40e_aqc_opc_set_phy_config = 0x0601, - i40e_aqc_opc_set_mac_config = 0x0603, - i40e_aqc_opc_set_link_restart_an = 0x0605, - i40e_aqc_opc_get_link_status = 0x0607, - i40e_aqc_opc_set_phy_int_mask = 0x0613, - i40e_aqc_opc_get_local_advt_reg = 0x0614, - i40e_aqc_opc_set_local_advt_reg = 0x0615, - i40e_aqc_opc_get_partner_advt = 0x0616, - i40e_aqc_opc_set_lb_modes = 0x0618, - i40e_aqc_opc_get_phy_wol_caps = 0x0621, - i40e_aqc_opc_set_phy_debug = 0x0622, - i40e_aqc_opc_upload_ext_phy_fm = 0x0625, + i40e_aqc_opc_get_phy_abilities = 0x0600, + i40e_aqc_opc_set_phy_config = 0x0601, + i40e_aqc_opc_set_mac_config = 0x0603, + i40e_aqc_opc_set_link_restart_an = 0x0605, + i40e_aqc_opc_get_link_status = 0x0607, + i40e_aqc_opc_set_phy_int_mask = 0x0613, + i40e_aqc_opc_get_local_advt_reg = 0x0614, + i40e_aqc_opc_set_local_advt_reg = 0x0615, + i40e_aqc_opc_get_partner_advt = 0x0616, + i40e_aqc_opc_set_lb_modes = 0x0618, + i40e_aqc_opc_get_phy_wol_caps = 0x0621, + i40e_aqc_opc_set_phy_debug = 0x0622, + i40e_aqc_opc_upload_ext_phy_fm = 0x0625, /* NVM commands */ - i40e_aqc_opc_nvm_read = 0x0701, - i40e_aqc_opc_nvm_erase = 0x0702, - i40e_aqc_opc_nvm_update = 0x0703, - i40e_aqc_opc_nvm_config_read = 0x0704, - i40e_aqc_opc_nvm_config_write = 0x0705, + i40e_aqc_opc_nvm_read = 0x0701, + i40e_aqc_opc_nvm_erase = 0x0702, + i40e_aqc_opc_nvm_update = 0x0703, + i40e_aqc_opc_nvm_config_read = 0x0704, + i40e_aqc_opc_nvm_config_write = 0x0705, /* virtualization commands */ - i40e_aqc_opc_send_msg_to_pf = 0x0801, - i40e_aqc_opc_send_msg_to_vf = 0x0802, - i40e_aqc_opc_send_msg_to_peer = 0x0803, + i40e_aqc_opc_send_msg_to_pf = 0x0801, + i40e_aqc_opc_send_msg_to_vf = 0x0802, + i40e_aqc_opc_send_msg_to_peer = 0x0803, /* alternate structure */ - i40e_aqc_opc_alternate_write = 0x0900, - i40e_aqc_opc_alternate_write_indirect = 0x0901, - i40e_aqc_opc_alternate_read = 0x0902, - i40e_aqc_opc_alternate_read_indirect = 0x0903, - i40e_aqc_opc_alternate_write_done = 0x0904, - i40e_aqc_opc_alternate_set_mode = 0x0905, - i40e_aqc_opc_alternate_clear_port = 0x0906, + i40e_aqc_opc_alternate_write = 0x0900, + i40e_aqc_opc_alternate_write_indirect = 0x0901, + i40e_aqc_opc_alternate_read = 0x0902, + i40e_aqc_opc_alternate_read_indirect = 0x0903, + i40e_aqc_opc_alternate_write_done = 0x0904, + i40e_aqc_opc_alternate_set_mode = 0x0905, + i40e_aqc_opc_alternate_clear_port = 0x0906, /* LLDP commands */ - i40e_aqc_opc_lldp_get_mib = 0x0A00, - i40e_aqc_opc_lldp_update_mib = 0x0A01, - i40e_aqc_opc_lldp_add_tlv = 0x0A02, - i40e_aqc_opc_lldp_update_tlv = 0x0A03, - i40e_aqc_opc_lldp_delete_tlv = 0x0A04, - i40e_aqc_opc_lldp_stop = 0x0A05, - i40e_aqc_opc_lldp_start = 0x0A06, + i40e_aqc_opc_lldp_get_mib = 0x0A00, + i40e_aqc_opc_lldp_update_mib = 0x0A01, + i40e_aqc_opc_lldp_add_tlv = 0x0A02, + i40e_aqc_opc_lldp_update_tlv = 0x0A03, + i40e_aqc_opc_lldp_delete_tlv = 0x0A04, + i40e_aqc_opc_lldp_stop = 0x0A05, + i40e_aqc_opc_lldp_start = 0x0A06, /* Tunnel commands */ - i40e_aqc_opc_add_udp_tunnel = 0x0B00, - i40e_aqc_opc_del_udp_tunnel = 0x0B01, - i40e_aqc_opc_tunnel_key_structure = 0x0B10, + i40e_aqc_opc_add_udp_tunnel = 0x0B00, + i40e_aqc_opc_del_udp_tunnel = 0x0B01, + i40e_aqc_opc_tunnel_key_structure = 0x0B10, /* Async Events */ - i40e_aqc_opc_event_lan_overflow = 0x1001, + i40e_aqc_opc_event_lan_overflow = 0x1001, /* OEM commands */ - i40e_aqc_opc_oem_parameter_change = 0xFE00, - i40e_aqc_opc_oem_device_status_change = 0xFE01, + i40e_aqc_opc_oem_parameter_change = 0xFE00, + i40e_aqc_opc_oem_device_status_change = 0xFE01, /* debug commands */ - i40e_aqc_opc_debug_get_deviceid = 0xFF00, - i40e_aqc_opc_debug_set_mode = 0xFF01, - i40e_aqc_opc_debug_read_reg = 0xFF03, - i40e_aqc_opc_debug_write_reg = 0xFF04, - i40e_aqc_opc_debug_modify_reg = 0xFF07, - i40e_aqc_opc_debug_dump_internals = 0xFF08, - i40e_aqc_opc_debug_modify_internals = 0xFF09, + i40e_aqc_opc_debug_get_deviceid = 0xFF00, + i40e_aqc_opc_debug_set_mode = 0xFF01, + i40e_aqc_opc_debug_read_reg = 0xFF03, + i40e_aqc_opc_debug_write_reg = 0xFF04, + i40e_aqc_opc_debug_modify_reg = 0xFF07, + i40e_aqc_opc_debug_dump_internals = 0xFF08, + i40e_aqc_opc_debug_modify_internals = 0xFF09, }; /* command structures and indirect data structures */ @@ -303,7 +303,7 @@ enum i40e_admin_queue_opc { /* This macro is used extensively to ensure that command structures are 16 * bytes in length as they have to map to the raw array of that size. */ -#define I40E_CHECK_CMD_LENGTH(X) I40E_CHECK_STRUCT_LEN(16, X) +#define I40E_CHECK_CMD_LENGTH(X) I40E_CHECK_STRUCT_LEN(16, X) /* internal (0x00XX) commands */ @@ -321,22 +321,22 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_get_version); /* Send driver version (indirect 0x0002) */ struct i40e_aqc_driver_version { - u8 driver_major_ver; - u8 driver_minor_ver; - u8 driver_build_ver; - u8 driver_subbuild_ver; - u8 reserved[4]; - __le32 address_high; - __le32 address_low; + u8 driver_major_ver; + u8 driver_minor_ver; + u8 driver_build_ver; + u8 driver_subbuild_ver; + u8 reserved[4]; + __le32 address_high; + __le32 address_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_driver_version); /* Queue Shutdown (direct 0x0003) */ struct i40e_aqc_queue_shutdown { - __le32 driver_unloading; -#define I40E_AQ_DRIVER_UNLOADING 0x1 - u8 reserved[12]; + __le32 driver_unloading; +#define I40E_AQ_DRIVER_UNLOADING 0x1 + u8 reserved[12]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_queue_shutdown); @@ -352,19 +352,19 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_set_pf_context); /* Request resource ownership (direct 0x0008) * Release resource ownership (direct 0x0009) */ -#define I40E_AQ_RESOURCE_NVM 1 -#define I40E_AQ_RESOURCE_SDP 2 -#define I40E_AQ_RESOURCE_ACCESS_READ 1 -#define I40E_AQ_RESOURCE_ACCESS_WRITE 2 -#define I40E_AQ_RESOURCE_NVM_READ_TIMEOUT 3000 -#define I40E_AQ_RESOURCE_NVM_WRITE_TIMEOUT 180000 +#define I40E_AQ_RESOURCE_NVM 1 +#define I40E_AQ_RESOURCE_SDP 2 +#define I40E_AQ_RESOURCE_ACCESS_READ 1 +#define I40E_AQ_RESOURCE_ACCESS_WRITE 2 +#define I40E_AQ_RESOURCE_NVM_READ_TIMEOUT 3000 +#define I40E_AQ_RESOURCE_NVM_WRITE_TIMEOUT 180000 struct i40e_aqc_request_resource { - __le16 resource_id; - __le16 access_type; - __le32 timeout; - __le32 resource_number; - u8 reserved[4]; + __le16 resource_id; + __le16 access_type; + __le32 timeout; + __le32 resource_number; + u8 reserved[4]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_request_resource); @@ -374,7 +374,7 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_request_resource); */ struct i40e_aqc_list_capabilites { u8 command_flags; -#define I40E_AQ_LIST_CAP_PF_INDEX_EN 1 +#define I40E_AQ_LIST_CAP_PF_INDEX_EN 1 u8 pf_index; u8 reserved[2]; __le32 count; @@ -385,123 +385,123 @@ struct i40e_aqc_list_capabilites { I40E_CHECK_CMD_LENGTH(i40e_aqc_list_capabilites); struct i40e_aqc_list_capabilities_element_resp { - __le16 id; - u8 major_rev; - u8 minor_rev; - __le32 number; - __le32 logical_id; - __le32 phys_id; - u8 reserved[16]; + __le16 id; + u8 major_rev; + u8 minor_rev; + __le32 number; + __le32 logical_id; + __le32 phys_id; + u8 reserved[16]; }; /* list of caps */ -#define I40E_AQ_CAP_ID_SWITCH_MODE 0x0001 -#define I40E_AQ_CAP_ID_MNG_MODE 0x0002 -#define I40E_AQ_CAP_ID_NPAR_ACTIVE 0x0003 -#define I40E_AQ_CAP_ID_OS2BMC_CAP 0x0004 -#define I40E_AQ_CAP_ID_FUNCTIONS_VALID 0x0005 -#define I40E_AQ_CAP_ID_ALTERNATE_RAM 0x0006 -#define I40E_AQ_CAP_ID_SRIOV 0x0012 -#define I40E_AQ_CAP_ID_VF 0x0013 -#define I40E_AQ_CAP_ID_VMDQ 0x0014 -#define I40E_AQ_CAP_ID_8021QBG 0x0015 -#define I40E_AQ_CAP_ID_8021QBR 0x0016 -#define I40E_AQ_CAP_ID_VSI 0x0017 -#define I40E_AQ_CAP_ID_DCB 0x0018 -#define I40E_AQ_CAP_ID_FCOE 0x0021 -#define I40E_AQ_CAP_ID_RSS 0x0040 -#define I40E_AQ_CAP_ID_RXQ 0x0041 -#define I40E_AQ_CAP_ID_TXQ 0x0042 -#define I40E_AQ_CAP_ID_MSIX 0x0043 -#define I40E_AQ_CAP_ID_VF_MSIX 0x0044 -#define I40E_AQ_CAP_ID_FLOW_DIRECTOR 0x0045 -#define I40E_AQ_CAP_ID_1588 0x0046 -#define I40E_AQ_CAP_ID_IWARP 0x0051 -#define I40E_AQ_CAP_ID_LED 0x0061 -#define I40E_AQ_CAP_ID_SDP 0x0062 -#define I40E_AQ_CAP_ID_MDIO 0x0063 -#define I40E_AQ_CAP_ID_FLEX10 0x00F1 -#define I40E_AQ_CAP_ID_CEM 0x00F2 +#define I40E_AQ_CAP_ID_SWITCH_MODE 0x0001 +#define I40E_AQ_CAP_ID_MNG_MODE 0x0002 +#define I40E_AQ_CAP_ID_NPAR_ACTIVE 0x0003 +#define I40E_AQ_CAP_ID_OS2BMC_CAP 0x0004 +#define I40E_AQ_CAP_ID_FUNCTIONS_VALID 0x0005 +#define I40E_AQ_CAP_ID_ALTERNATE_RAM 0x0006 +#define I40E_AQ_CAP_ID_SRIOV 0x0012 +#define I40E_AQ_CAP_ID_VF 0x0013 +#define I40E_AQ_CAP_ID_VMDQ 0x0014 +#define I40E_AQ_CAP_ID_8021QBG 0x0015 +#define I40E_AQ_CAP_ID_8021QBR 0x0016 +#define I40E_AQ_CAP_ID_VSI 0x0017 +#define I40E_AQ_CAP_ID_DCB 0x0018 +#define I40E_AQ_CAP_ID_FCOE 0x0021 +#define I40E_AQ_CAP_ID_RSS 0x0040 +#define I40E_AQ_CAP_ID_RXQ 0x0041 +#define I40E_AQ_CAP_ID_TXQ 0x0042 +#define I40E_AQ_CAP_ID_MSIX 0x0043 +#define I40E_AQ_CAP_ID_VF_MSIX 0x0044 +#define I40E_AQ_CAP_ID_FLOW_DIRECTOR 0x0045 +#define I40E_AQ_CAP_ID_1588 0x0046 +#define I40E_AQ_CAP_ID_IWARP 0x0051 +#define I40E_AQ_CAP_ID_LED 0x0061 +#define I40E_AQ_CAP_ID_SDP 0x0062 +#define I40E_AQ_CAP_ID_MDIO 0x0063 +#define I40E_AQ_CAP_ID_FLEX10 0x00F1 +#define I40E_AQ_CAP_ID_CEM 0x00F2 /* Set CPPM Configuration (direct 0x0103) */ struct i40e_aqc_cppm_configuration { - __le16 command_flags; -#define I40E_AQ_CPPM_EN_LTRC 0x0800 -#define I40E_AQ_CPPM_EN_DMCTH 0x1000 -#define I40E_AQ_CPPM_EN_DMCTLX 0x2000 -#define I40E_AQ_CPPM_EN_HPTC 0x4000 -#define I40E_AQ_CPPM_EN_DMARC 0x8000 - __le16 ttlx; - __le32 dmacr; - __le16 dmcth; - u8 hptc; - u8 reserved; - __le32 pfltrc; + __le16 command_flags; +#define I40E_AQ_CPPM_EN_LTRC 0x0800 +#define I40E_AQ_CPPM_EN_DMCTH 0x1000 +#define I40E_AQ_CPPM_EN_DMCTLX 0x2000 +#define I40E_AQ_CPPM_EN_HPTC 0x4000 +#define I40E_AQ_CPPM_EN_DMARC 0x8000 + __le16 ttlx; + __le32 dmacr; + __le16 dmcth; + u8 hptc; + u8 reserved; + __le32 pfltrc; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_cppm_configuration); /* Set ARP Proxy command / response (indirect 0x0104) */ struct i40e_aqc_arp_proxy_data { - __le16 command_flags; -#define I40E_AQ_ARP_INIT_IPV4 0x0008 -#define I40E_AQ_ARP_UNSUP_CTL 0x0010 -#define I40E_AQ_ARP_ENA 0x0020 -#define I40E_AQ_ARP_ADD_IPV4 0x0040 -#define I40E_AQ_ARP_DEL_IPV4 0x0080 - __le16 table_id; - __le32 pfpm_proxyfc; - __le32 ip_addr; - u8 mac_addr[6]; + __le16 command_flags; +#define I40E_AQ_ARP_INIT_IPV4 0x0008 +#define I40E_AQ_ARP_UNSUP_CTL 0x0010 +#define I40E_AQ_ARP_ENA 0x0020 +#define I40E_AQ_ARP_ADD_IPV4 0x0040 +#define I40E_AQ_ARP_DEL_IPV4 0x0080 + __le16 table_id; + __le32 pfpm_proxyfc; + __le32 ip_addr; + u8 mac_addr[6]; }; /* Set NS Proxy Table Entry Command (indirect 0x0105) */ struct i40e_aqc_ns_proxy_data { - __le16 table_idx_mac_addr_0; - __le16 table_idx_mac_addr_1; - __le16 table_idx_ipv6_0; - __le16 table_idx_ipv6_1; - __le16 control; -#define I40E_AQ_NS_PROXY_ADD_0 0x0100 -#define I40E_AQ_NS_PROXY_DEL_0 0x0200 -#define I40E_AQ_NS_PROXY_ADD_1 0x0400 -#define I40E_AQ_NS_PROXY_DEL_1 0x0800 -#define I40E_AQ_NS_PROXY_ADD_IPV6_0 0x1000 -#define I40E_AQ_NS_PROXY_DEL_IPV6_0 0x2000 -#define I40E_AQ_NS_PROXY_ADD_IPV6_1 0x4000 -#define I40E_AQ_NS_PROXY_DEL_IPV6_1 0x8000 -#define I40E_AQ_NS_PROXY_COMMAND_SEQ 0x0001 -#define I40E_AQ_NS_PROXY_INIT_IPV6_TBL 0x0002 -#define I40E_AQ_NS_PROXY_INIT_MAC_TBL 0x0004 - u8 mac_addr_0[6]; - u8 mac_addr_1[6]; - u8 local_mac_addr[6]; - u8 ipv6_addr_0[16]; /* Warning! spec specifies BE byte order */ - u8 ipv6_addr_1[16]; + __le16 table_idx_mac_addr_0; + __le16 table_idx_mac_addr_1; + __le16 table_idx_ipv6_0; + __le16 table_idx_ipv6_1; + __le16 control; +#define I40E_AQ_NS_PROXY_ADD_0 0x0100 +#define I40E_AQ_NS_PROXY_DEL_0 0x0200 +#define I40E_AQ_NS_PROXY_ADD_1 0x0400 +#define I40E_AQ_NS_PROXY_DEL_1 0x0800 +#define I40E_AQ_NS_PROXY_ADD_IPV6_0 0x1000 +#define I40E_AQ_NS_PROXY_DEL_IPV6_0 0x2000 +#define I40E_AQ_NS_PROXY_ADD_IPV6_1 0x4000 +#define I40E_AQ_NS_PROXY_DEL_IPV6_1 0x8000 +#define I40E_AQ_NS_PROXY_COMMAND_SEQ 0x0001 +#define I40E_AQ_NS_PROXY_INIT_IPV6_TBL 0x0002 +#define I40E_AQ_NS_PROXY_INIT_MAC_TBL 0x0004 + u8 mac_addr_0[6]; + u8 mac_addr_1[6]; + u8 local_mac_addr[6]; + u8 ipv6_addr_0[16]; /* Warning! spec specifies BE byte order */ + u8 ipv6_addr_1[16]; }; /* Manage LAA Command (0x0106) - obsolete */ struct i40e_aqc_mng_laa { __le16 command_flags; -#define I40E_AQ_LAA_FLAG_WR 0x8000 - u8 reserved[2]; - __le32 sal; - __le16 sah; - u8 reserved2[6]; +#define I40E_AQ_LAA_FLAG_WR 0x8000 + u8 reserved[2]; + __le32 sal; + __le16 sah; + u8 reserved2[6]; }; /* Manage MAC Address Read Command (indirect 0x0107) */ struct i40e_aqc_mac_address_read { __le16 command_flags; -#define I40E_AQC_LAN_ADDR_VALID 0x10 -#define I40E_AQC_SAN_ADDR_VALID 0x20 -#define I40E_AQC_PORT_ADDR_VALID 0x40 -#define I40E_AQC_WOL_ADDR_VALID 0x80 -#define I40E_AQC_ADDR_VALID_MASK 0xf0 - u8 reserved[6]; - __le32 addr_high; - __le32 addr_low; +#define I40E_AQC_LAN_ADDR_VALID 0x10 +#define I40E_AQC_SAN_ADDR_VALID 0x20 +#define I40E_AQC_PORT_ADDR_VALID 0x40 +#define I40E_AQC_WOL_ADDR_VALID 0x80 +#define I40E_AQC_ADDR_VALID_MASK 0xf0 + u8 reserved[6]; + __le32 addr_high; + __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_mac_address_read); @@ -517,14 +517,14 @@ I40E_CHECK_STRUCT_LEN(24, i40e_aqc_mac_address_read_data); /* Manage MAC Address Write Command (0x0108) */ struct i40e_aqc_mac_address_write { - __le16 command_flags; -#define I40E_AQC_WRITE_TYPE_LAA_ONLY 0x0000 -#define I40E_AQC_WRITE_TYPE_LAA_WOL 0x4000 -#define I40E_AQC_WRITE_TYPE_PORT 0x8000 -#define I40E_AQC_WRITE_TYPE_MASK 0xc000 - __le16 mac_sah; - __le32 mac_sal; - u8 reserved[8]; + __le16 command_flags; +#define I40E_AQC_WRITE_TYPE_LAA_ONLY 0x0000 +#define I40E_AQC_WRITE_TYPE_LAA_WOL 0x4000 +#define I40E_AQC_WRITE_TYPE_PORT 0x8000 +#define I40E_AQC_WRITE_TYPE_MASK 0xc000 + __le16 mac_sah; + __le32 mac_sal; + u8 reserved[8]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_mac_address_write); @@ -545,10 +545,10 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_clear_pxe); * command */ struct i40e_aqc_switch_seid { - __le16 seid; - u8 reserved[6]; - __le32 addr_high; - __le32 addr_low; + __le16 seid; + u8 reserved[6]; + __le32 addr_high; + __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_switch_seid); @@ -557,34 +557,34 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_switch_seid); * uses i40e_aqc_switch_seid for the descriptor */ struct i40e_aqc_get_switch_config_header_resp { - __le16 num_reported; - __le16 num_total; - u8 reserved[12]; + __le16 num_reported; + __le16 num_total; + u8 reserved[12]; }; struct i40e_aqc_switch_config_element_resp { - u8 element_type; -#define I40E_AQ_SW_ELEM_TYPE_MAC 1 -#define I40E_AQ_SW_ELEM_TYPE_PF 2 -#define I40E_AQ_SW_ELEM_TYPE_VF 3 -#define I40E_AQ_SW_ELEM_TYPE_EMP 4 -#define I40E_AQ_SW_ELEM_TYPE_BMC 5 -#define I40E_AQ_SW_ELEM_TYPE_PV 16 -#define I40E_AQ_SW_ELEM_TYPE_VEB 17 -#define I40E_AQ_SW_ELEM_TYPE_PA 18 -#define I40E_AQ_SW_ELEM_TYPE_VSI 19 - u8 revision; -#define I40E_AQ_SW_ELEM_REV_1 1 - __le16 seid; - __le16 uplink_seid; - __le16 downlink_seid; - u8 reserved[3]; - u8 connection_type; -#define I40E_AQ_CONN_TYPE_REGULAR 0x1 -#define I40E_AQ_CONN_TYPE_DEFAULT 0x2 -#define I40E_AQ_CONN_TYPE_CASCADED 0x3 - __le16 scheduler_id; - __le16 element_info; + u8 element_type; +#define I40E_AQ_SW_ELEM_TYPE_MAC 1 +#define I40E_AQ_SW_ELEM_TYPE_PF 2 +#define I40E_AQ_SW_ELEM_TYPE_VF 3 +#define I40E_AQ_SW_ELEM_TYPE_EMP 4 +#define I40E_AQ_SW_ELEM_TYPE_BMC 5 +#define I40E_AQ_SW_ELEM_TYPE_PV 16 +#define I40E_AQ_SW_ELEM_TYPE_VEB 17 +#define I40E_AQ_SW_ELEM_TYPE_PA 18 +#define I40E_AQ_SW_ELEM_TYPE_VSI 19 + u8 revision; +#define I40E_AQ_SW_ELEM_REV_1 1 + __le16 seid; + __le16 uplink_seid; + __le16 downlink_seid; + u8 reserved[3]; + u8 connection_type; +#define I40E_AQ_CONN_TYPE_REGULAR 0x1 +#define I40E_AQ_CONN_TYPE_DEFAULT 0x2 +#define I40E_AQ_CONN_TYPE_CASCADED 0x3 + __le16 scheduler_id; + __le16 element_info; }; /* Get Switch Configuration (indirect 0x0200) @@ -592,73 +592,73 @@ struct i40e_aqc_switch_config_element_resp { * the first in the array is the header, remainder are elements */ struct i40e_aqc_get_switch_config_resp { - struct i40e_aqc_get_switch_config_header_resp header; - struct i40e_aqc_switch_config_element_resp element[1]; + struct i40e_aqc_get_switch_config_header_resp header; + struct i40e_aqc_switch_config_element_resp element[1]; }; /* Add Statistics (direct 0x0201) * Remove Statistics (direct 0x0202) */ struct i40e_aqc_add_remove_statistics { - __le16 seid; - __le16 vlan; - __le16 stat_index; - u8 reserved[10]; + __le16 seid; + __le16 vlan; + __le16 stat_index; + u8 reserved[10]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_statistics); /* Set Port Parameters command (direct 0x0203) */ struct i40e_aqc_set_port_parameters { - __le16 command_flags; -#define I40E_AQ_SET_P_PARAMS_SAVE_BAD_PACKETS 1 -#define I40E_AQ_SET_P_PARAMS_PAD_SHORT_PACKETS 2 /* must set! */ -#define I40E_AQ_SET_P_PARAMS_DOUBLE_VLAN_ENA 4 - __le16 bad_frame_vsi; - __le16 default_seid; /* reserved for command */ - u8 reserved[10]; + __le16 command_flags; +#define I40E_AQ_SET_P_PARAMS_SAVE_BAD_PACKETS 1 +#define I40E_AQ_SET_P_PARAMS_PAD_SHORT_PACKETS 2 /* must set! */ +#define I40E_AQ_SET_P_PARAMS_DOUBLE_VLAN_ENA 4 + __le16 bad_frame_vsi; + __le16 default_seid; /* reserved for command */ + u8 reserved[10]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_set_port_parameters); /* Get Switch Resource Allocation (indirect 0x0204) */ struct i40e_aqc_get_switch_resource_alloc { - u8 num_entries; /* reserved for command */ - u8 reserved[7]; - __le32 addr_high; - __le32 addr_low; + u8 num_entries; /* reserved for command */ + u8 reserved[7]; + __le32 addr_high; + __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_get_switch_resource_alloc); /* expect an array of these structs in the response buffer */ struct i40e_aqc_switch_resource_alloc_element_resp { - u8 resource_type; -#define I40E_AQ_RESOURCE_TYPE_VEB 0x0 -#define I40E_AQ_RESOURCE_TYPE_VSI 0x1 -#define I40E_AQ_RESOURCE_TYPE_MACADDR 0x2 -#define I40E_AQ_RESOURCE_TYPE_STAG 0x3 -#define I40E_AQ_RESOURCE_TYPE_ETAG 0x4 -#define I40E_AQ_RESOURCE_TYPE_MULTICAST_HASH 0x5 -#define I40E_AQ_RESOURCE_TYPE_UNICAST_HASH 0x6 -#define I40E_AQ_RESOURCE_TYPE_VLAN 0x7 -#define I40E_AQ_RESOURCE_TYPE_VSI_LIST_ENTRY 0x8 -#define I40E_AQ_RESOURCE_TYPE_ETAG_LIST_ENTRY 0x9 -#define I40E_AQ_RESOURCE_TYPE_VLAN_STAT_POOL 0xA -#define I40E_AQ_RESOURCE_TYPE_MIRROR_RULE 0xB -#define I40E_AQ_RESOURCE_TYPE_QUEUE_SETS 0xC -#define I40E_AQ_RESOURCE_TYPE_VLAN_FILTERS 0xD -#define I40E_AQ_RESOURCE_TYPE_INNER_MAC_FILTERS 0xF -#define I40E_AQ_RESOURCE_TYPE_IP_FILTERS 0x10 -#define I40E_AQ_RESOURCE_TYPE_GRE_VN_KEYS 0x11 -#define I40E_AQ_RESOURCE_TYPE_VN2_KEYS 0x12 -#define I40E_AQ_RESOURCE_TYPE_TUNNEL_PORTS 0x13 - u8 reserved1; - __le16 guaranteed; - __le16 total; - __le16 used; - __le16 total_unalloced; - u8 reserved2[6]; + u8 resource_type; +#define I40E_AQ_RESOURCE_TYPE_VEB 0x0 +#define I40E_AQ_RESOURCE_TYPE_VSI 0x1 +#define I40E_AQ_RESOURCE_TYPE_MACADDR 0x2 +#define I40E_AQ_RESOURCE_TYPE_STAG 0x3 +#define I40E_AQ_RESOURCE_TYPE_ETAG 0x4 +#define I40E_AQ_RESOURCE_TYPE_MULTICAST_HASH 0x5 +#define I40E_AQ_RESOURCE_TYPE_UNICAST_HASH 0x6 +#define I40E_AQ_RESOURCE_TYPE_VLAN 0x7 +#define I40E_AQ_RESOURCE_TYPE_VSI_LIST_ENTRY 0x8 +#define I40E_AQ_RESOURCE_TYPE_ETAG_LIST_ENTRY 0x9 +#define I40E_AQ_RESOURCE_TYPE_VLAN_STAT_POOL 0xA +#define I40E_AQ_RESOURCE_TYPE_MIRROR_RULE 0xB +#define I40E_AQ_RESOURCE_TYPE_QUEUE_SETS 0xC +#define I40E_AQ_RESOURCE_TYPE_VLAN_FILTERS 0xD +#define I40E_AQ_RESOURCE_TYPE_INNER_MAC_FILTERS 0xF +#define I40E_AQ_RESOURCE_TYPE_IP_FILTERS 0x10 +#define I40E_AQ_RESOURCE_TYPE_GRE_VN_KEYS 0x11 +#define I40E_AQ_RESOURCE_TYPE_VN2_KEYS 0x12 +#define I40E_AQ_RESOURCE_TYPE_TUNNEL_PORTS 0x13 + u8 reserved1; + __le16 guaranteed; + __le16 total; + __le16 used; + __le16 total_unalloced; + u8 reserved2[6]; }; /* Add VSI (indirect 0x0210) @@ -672,24 +672,24 @@ struct i40e_aqc_switch_resource_alloc_element_resp { * uses the same completion and data structure as Add VSI */ struct i40e_aqc_add_get_update_vsi { - __le16 uplink_seid; - u8 connection_type; -#define I40E_AQ_VSI_CONN_TYPE_NORMAL 0x1 -#define I40E_AQ_VSI_CONN_TYPE_DEFAULT 0x2 -#define I40E_AQ_VSI_CONN_TYPE_CASCADED 0x3 - u8 reserved1; - u8 vf_id; - u8 reserved2; - __le16 vsi_flags; -#define I40E_AQ_VSI_TYPE_SHIFT 0x0 -#define I40E_AQ_VSI_TYPE_MASK (0x3 << I40E_AQ_VSI_TYPE_SHIFT) -#define I40E_AQ_VSI_TYPE_VF 0x0 -#define I40E_AQ_VSI_TYPE_VMDQ2 0x1 -#define I40E_AQ_VSI_TYPE_PF 0x2 -#define I40E_AQ_VSI_TYPE_EMP_MNG 0x3 -#define I40E_AQ_VSI_FLAG_CASCADED_PV 0x4 - __le32 addr_high; - __le32 addr_low; + __le16 uplink_seid; + u8 connection_type; +#define I40E_AQ_VSI_CONN_TYPE_NORMAL 0x1 +#define I40E_AQ_VSI_CONN_TYPE_DEFAULT 0x2 +#define I40E_AQ_VSI_CONN_TYPE_CASCADED 0x3 + u8 reserved1; + u8 vf_id; + u8 reserved2; + __le16 vsi_flags; +#define I40E_AQ_VSI_TYPE_SHIFT 0x0 +#define I40E_AQ_VSI_TYPE_MASK (0x3 << I40E_AQ_VSI_TYPE_SHIFT) +#define I40E_AQ_VSI_TYPE_VF 0x0 +#define I40E_AQ_VSI_TYPE_VMDQ2 0x1 +#define I40E_AQ_VSI_TYPE_PF 0x2 +#define I40E_AQ_VSI_TYPE_EMP_MNG 0x3 +#define I40E_AQ_VSI_FLAG_CASCADED_PV 0x4 + __le32 addr_high; + __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_get_update_vsi); @@ -707,121 +707,121 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_add_get_update_vsi_completion); struct i40e_aqc_vsi_properties_data { /* first 96 byte are written by SW */ - __le16 valid_sections; -#define I40E_AQ_VSI_PROP_SWITCH_VALID 0x0001 -#define I40E_AQ_VSI_PROP_SECURITY_VALID 0x0002 -#define I40E_AQ_VSI_PROP_VLAN_VALID 0x0004 -#define I40E_AQ_VSI_PROP_CAS_PV_VALID 0x0008 -#define I40E_AQ_VSI_PROP_INGRESS_UP_VALID 0x0010 -#define I40E_AQ_VSI_PROP_EGRESS_UP_VALID 0x0020 -#define I40E_AQ_VSI_PROP_QUEUE_MAP_VALID 0x0040 -#define I40E_AQ_VSI_PROP_QUEUE_OPT_VALID 0x0080 -#define I40E_AQ_VSI_PROP_OUTER_UP_VALID 0x0100 -#define I40E_AQ_VSI_PROP_SCHED_VALID 0x0200 + __le16 valid_sections; +#define I40E_AQ_VSI_PROP_SWITCH_VALID 0x0001 +#define I40E_AQ_VSI_PROP_SECURITY_VALID 0x0002 +#define I40E_AQ_VSI_PROP_VLAN_VALID 0x0004 +#define I40E_AQ_VSI_PROP_CAS_PV_VALID 0x0008 +#define I40E_AQ_VSI_PROP_INGRESS_UP_VALID 0x0010 +#define I40E_AQ_VSI_PROP_EGRESS_UP_VALID 0x0020 +#define I40E_AQ_VSI_PROP_QUEUE_MAP_VALID 0x0040 +#define I40E_AQ_VSI_PROP_QUEUE_OPT_VALID 0x0080 +#define I40E_AQ_VSI_PROP_OUTER_UP_VALID 0x0100 +#define I40E_AQ_VSI_PROP_SCHED_VALID 0x0200 /* switch section */ - __le16 switch_id; /* 12bit id combined with flags below */ -#define I40E_AQ_VSI_SW_ID_SHIFT 0x0000 -#define I40E_AQ_VSI_SW_ID_MASK (0xFFF << I40E_AQ_VSI_SW_ID_SHIFT) -#define I40E_AQ_VSI_SW_ID_FLAG_NOT_STAG 0x1000 -#define I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB 0x2000 -#define I40E_AQ_VSI_SW_ID_FLAG_LOCAL_LB 0x4000 - u8 sw_reserved[2]; + __le16 switch_id; /* 12bit id combined with flags below */ +#define I40E_AQ_VSI_SW_ID_SHIFT 0x0000 +#define I40E_AQ_VSI_SW_ID_MASK (0xFFF << I40E_AQ_VSI_SW_ID_SHIFT) +#define I40E_AQ_VSI_SW_ID_FLAG_NOT_STAG 0x1000 +#define I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB 0x2000 +#define I40E_AQ_VSI_SW_ID_FLAG_LOCAL_LB 0x4000 + u8 sw_reserved[2]; /* security section */ - u8 sec_flags; -#define I40E_AQ_VSI_SEC_FLAG_ALLOW_DEST_OVRD 0x01 -#define I40E_AQ_VSI_SEC_FLAG_ENABLE_VLAN_CHK 0x02 -#define I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK 0x04 - u8 sec_reserved; + u8 sec_flags; +#define I40E_AQ_VSI_SEC_FLAG_ALLOW_DEST_OVRD 0x01 +#define I40E_AQ_VSI_SEC_FLAG_ENABLE_VLAN_CHK 0x02 +#define I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK 0x04 + u8 sec_reserved; /* VLAN section */ - __le16 pvid; /* VLANS include priority bits */ - __le16 fcoe_pvid; - u8 port_vlan_flags; -#define I40E_AQ_VSI_PVLAN_MODE_SHIFT 0x00 -#define I40E_AQ_VSI_PVLAN_MODE_MASK (0x03 << \ - I40E_AQ_VSI_PVLAN_MODE_SHIFT) -#define I40E_AQ_VSI_PVLAN_MODE_TAGGED 0x01 -#define I40E_AQ_VSI_PVLAN_MODE_UNTAGGED 0x02 -#define I40E_AQ_VSI_PVLAN_MODE_ALL 0x03 -#define I40E_AQ_VSI_PVLAN_INSERT_PVID 0x04 -#define I40E_AQ_VSI_PVLAN_EMOD_SHIFT 0x03 -#define I40E_AQ_VSI_PVLAN_EMOD_MASK (0x3 << \ - I40E_AQ_VSI_PVLAN_EMOD_SHIFT) -#define I40E_AQ_VSI_PVLAN_EMOD_STR_BOTH 0x0 -#define I40E_AQ_VSI_PVLAN_EMOD_STR_UP 0x08 -#define I40E_AQ_VSI_PVLAN_EMOD_STR 0x10 -#define I40E_AQ_VSI_PVLAN_EMOD_NOTHING 0x18 - u8 pvlan_reserved[3]; + __le16 pvid; /* VLANS include priority bits */ + __le16 fcoe_pvid; + u8 port_vlan_flags; +#define I40E_AQ_VSI_PVLAN_MODE_SHIFT 0x00 +#define I40E_AQ_VSI_PVLAN_MODE_MASK (0x03 << \ + I40E_AQ_VSI_PVLAN_MODE_SHIFT) +#define I40E_AQ_VSI_PVLAN_MODE_TAGGED 0x01 +#define I40E_AQ_VSI_PVLAN_MODE_UNTAGGED 0x02 +#define I40E_AQ_VSI_PVLAN_MODE_ALL 0x03 +#define I40E_AQ_VSI_PVLAN_INSERT_PVID 0x04 +#define I40E_AQ_VSI_PVLAN_EMOD_SHIFT 0x03 +#define I40E_AQ_VSI_PVLAN_EMOD_MASK (0x3 << \ + I40E_AQ_VSI_PVLAN_EMOD_SHIFT) +#define I40E_AQ_VSI_PVLAN_EMOD_STR_BOTH 0x0 +#define I40E_AQ_VSI_PVLAN_EMOD_STR_UP 0x08 +#define I40E_AQ_VSI_PVLAN_EMOD_STR 0x10 +#define I40E_AQ_VSI_PVLAN_EMOD_NOTHING 0x18 + u8 pvlan_reserved[3]; /* ingress egress up sections */ - __le32 ingress_table; /* bitmap, 3 bits per up */ -#define I40E_AQ_VSI_UP_TABLE_UP0_SHIFT 0 -#define I40E_AQ_VSI_UP_TABLE_UP0_MASK (0x7 << \ - I40E_AQ_VSI_UP_TABLE_UP0_SHIFT) -#define I40E_AQ_VSI_UP_TABLE_UP1_SHIFT 3 -#define I40E_AQ_VSI_UP_TABLE_UP1_MASK (0x7 << \ - I40E_AQ_VSI_UP_TABLE_UP1_SHIFT) -#define I40E_AQ_VSI_UP_TABLE_UP2_SHIFT 6 -#define I40E_AQ_VSI_UP_TABLE_UP2_MASK (0x7 << \ - I40E_AQ_VSI_UP_TABLE_UP2_SHIFT) -#define I40E_AQ_VSI_UP_TABLE_UP3_SHIFT 9 -#define I40E_AQ_VSI_UP_TABLE_UP3_MASK (0x7 << \ - I40E_AQ_VSI_UP_TABLE_UP3_SHIFT) -#define I40E_AQ_VSI_UP_TABLE_UP4_SHIFT 12 -#define I40E_AQ_VSI_UP_TABLE_UP4_MASK (0x7 << \ - I40E_AQ_VSI_UP_TABLE_UP4_SHIFT) -#define I40E_AQ_VSI_UP_TABLE_UP5_SHIFT 15 -#define I40E_AQ_VSI_UP_TABLE_UP5_MASK (0x7 << \ - I40E_AQ_VSI_UP_TABLE_UP5_SHIFT) -#define I40E_AQ_VSI_UP_TABLE_UP6_SHIFT 18 -#define I40E_AQ_VSI_UP_TABLE_UP6_MASK (0x7 << \ - I40E_AQ_VSI_UP_TABLE_UP6_SHIFT) -#define I40E_AQ_VSI_UP_TABLE_UP7_SHIFT 21 -#define I40E_AQ_VSI_UP_TABLE_UP7_MASK (0x7 << \ - I40E_AQ_VSI_UP_TABLE_UP7_SHIFT) - __le32 egress_table; /* same defines as for ingress table */ + __le32 ingress_table; /* bitmap, 3 bits per up */ +#define I40E_AQ_VSI_UP_TABLE_UP0_SHIFT 0 +#define I40E_AQ_VSI_UP_TABLE_UP0_MASK (0x7 << \ + I40E_AQ_VSI_UP_TABLE_UP0_SHIFT) +#define I40E_AQ_VSI_UP_TABLE_UP1_SHIFT 3 +#define I40E_AQ_VSI_UP_TABLE_UP1_MASK (0x7 << \ + I40E_AQ_VSI_UP_TABLE_UP1_SHIFT) +#define I40E_AQ_VSI_UP_TABLE_UP2_SHIFT 6 +#define I40E_AQ_VSI_UP_TABLE_UP2_MASK (0x7 << \ + I40E_AQ_VSI_UP_TABLE_UP2_SHIFT) +#define I40E_AQ_VSI_UP_TABLE_UP3_SHIFT 9 +#define I40E_AQ_VSI_UP_TABLE_UP3_MASK (0x7 << \ + I40E_AQ_VSI_UP_TABLE_UP3_SHIFT) +#define I40E_AQ_VSI_UP_TABLE_UP4_SHIFT 12 +#define I40E_AQ_VSI_UP_TABLE_UP4_MASK (0x7 << \ + I40E_AQ_VSI_UP_TABLE_UP4_SHIFT) +#define I40E_AQ_VSI_UP_TABLE_UP5_SHIFT 15 +#define I40E_AQ_VSI_UP_TABLE_UP5_MASK (0x7 << \ + I40E_AQ_VSI_UP_TABLE_UP5_SHIFT) +#define I40E_AQ_VSI_UP_TABLE_UP6_SHIFT 18 +#define I40E_AQ_VSI_UP_TABLE_UP6_MASK (0x7 << \ + I40E_AQ_VSI_UP_TABLE_UP6_SHIFT) +#define I40E_AQ_VSI_UP_TABLE_UP7_SHIFT 21 +#define I40E_AQ_VSI_UP_TABLE_UP7_MASK (0x7 << \ + I40E_AQ_VSI_UP_TABLE_UP7_SHIFT) + __le32 egress_table; /* same defines as for ingress table */ /* cascaded PV section */ - __le16 cas_pv_tag; - u8 cas_pv_flags; -#define I40E_AQ_VSI_CAS_PV_TAGX_SHIFT 0x00 -#define I40E_AQ_VSI_CAS_PV_TAGX_MASK (0x03 << \ - I40E_AQ_VSI_CAS_PV_TAGX_SHIFT) -#define I40E_AQ_VSI_CAS_PV_TAGX_LEAVE 0x00 -#define I40E_AQ_VSI_CAS_PV_TAGX_REMOVE 0x01 -#define I40E_AQ_VSI_CAS_PV_TAGX_COPY 0x02 -#define I40E_AQ_VSI_CAS_PV_INSERT_TAG 0x10 -#define I40E_AQ_VSI_CAS_PV_ETAG_PRUNE 0x20 -#define I40E_AQ_VSI_CAS_PV_ACCEPT_HOST_TAG 0x40 - u8 cas_pv_reserved; + __le16 cas_pv_tag; + u8 cas_pv_flags; +#define I40E_AQ_VSI_CAS_PV_TAGX_SHIFT 0x00 +#define I40E_AQ_VSI_CAS_PV_TAGX_MASK (0x03 << \ + I40E_AQ_VSI_CAS_PV_TAGX_SHIFT) +#define I40E_AQ_VSI_CAS_PV_TAGX_LEAVE 0x00 +#define I40E_AQ_VSI_CAS_PV_TAGX_REMOVE 0x01 +#define I40E_AQ_VSI_CAS_PV_TAGX_COPY 0x02 +#define I40E_AQ_VSI_CAS_PV_INSERT_TAG 0x10 +#define I40E_AQ_VSI_CAS_PV_ETAG_PRUNE 0x20 +#define I40E_AQ_VSI_CAS_PV_ACCEPT_HOST_TAG 0x40 + u8 cas_pv_reserved; /* queue mapping section */ - __le16 mapping_flags; -#define I40E_AQ_VSI_QUE_MAP_CONTIG 0x0 -#define I40E_AQ_VSI_QUE_MAP_NONCONTIG 0x1 - __le16 queue_mapping[16]; -#define I40E_AQ_VSI_QUEUE_SHIFT 0x0 -#define I40E_AQ_VSI_QUEUE_MASK (0x7FF << I40E_AQ_VSI_QUEUE_SHIFT) - __le16 tc_mapping[8]; -#define I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT 0 -#define I40E_AQ_VSI_TC_QUE_OFFSET_MASK (0x1FF << \ - I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT) -#define I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT 9 -#define I40E_AQ_VSI_TC_QUE_NUMBER_MASK (0x7 << \ - I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT) + __le16 mapping_flags; +#define I40E_AQ_VSI_QUE_MAP_CONTIG 0x0 +#define I40E_AQ_VSI_QUE_MAP_NONCONTIG 0x1 + __le16 queue_mapping[16]; +#define I40E_AQ_VSI_QUEUE_SHIFT 0x0 +#define I40E_AQ_VSI_QUEUE_MASK (0x7FF << I40E_AQ_VSI_QUEUE_SHIFT) + __le16 tc_mapping[8]; +#define I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT 0 +#define I40E_AQ_VSI_TC_QUE_OFFSET_MASK (0x1FF << \ + I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT) +#define I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT 9 +#define I40E_AQ_VSI_TC_QUE_NUMBER_MASK (0x7 << \ + I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT) /* queueing option section */ - u8 queueing_opt_flags; -#define I40E_AQ_VSI_QUE_OPT_TCP_ENA 0x10 -#define I40E_AQ_VSI_QUE_OPT_FCOE_ENA 0x20 - u8 queueing_opt_reserved[3]; + u8 queueing_opt_flags; +#define I40E_AQ_VSI_QUE_OPT_TCP_ENA 0x10 +#define I40E_AQ_VSI_QUE_OPT_FCOE_ENA 0x20 + u8 queueing_opt_reserved[3]; /* scheduler section */ - u8 up_enable_bits; - u8 sched_reserved; + u8 up_enable_bits; + u8 sched_reserved; /* outer up section */ - __le32 outer_up_table; /* same structure and defines as ingress table */ - u8 cmd_reserved[8]; + __le32 outer_up_table; /* same structure and defines as ingress tbl */ + u8 cmd_reserved[8]; /* last 32 bytes are written by FW */ - __le16 qs_handle[8]; + __le16 qs_handle[8]; #define I40E_AQ_VSI_QS_HANDLE_INVALID 0xFFFF - __le16 stat_counter_idx; - __le16 sched_id; - u8 resp_reserved[12]; + __le16 stat_counter_idx; + __le16 sched_id; + u8 resp_reserved[12]; }; I40E_CHECK_STRUCT_LEN(128, i40e_aqc_vsi_properties_data); @@ -831,26 +831,26 @@ I40E_CHECK_STRUCT_LEN(128, i40e_aqc_vsi_properties_data); * (IS_CTRL_PORT only works on add PV) */ struct i40e_aqc_add_update_pv { - __le16 command_flags; -#define I40E_AQC_PV_FLAG_PV_TYPE 0x1 -#define I40E_AQC_PV_FLAG_FWD_UNKNOWN_STAG_EN 0x2 -#define I40E_AQC_PV_FLAG_FWD_UNKNOWN_ETAG_EN 0x4 -#define I40E_AQC_PV_FLAG_IS_CTRL_PORT 0x8 - __le16 uplink_seid; - __le16 connected_seid; - u8 reserved[10]; + __le16 command_flags; +#define I40E_AQC_PV_FLAG_PV_TYPE 0x1 +#define I40E_AQC_PV_FLAG_FWD_UNKNOWN_STAG_EN 0x2 +#define I40E_AQC_PV_FLAG_FWD_UNKNOWN_ETAG_EN 0x4 +#define I40E_AQC_PV_FLAG_IS_CTRL_PORT 0x8 + __le16 uplink_seid; + __le16 connected_seid; + u8 reserved[10]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_update_pv); struct i40e_aqc_add_update_pv_completion { /* reserved for update; for add also encodes error if rc == ENOSPC */ - __le16 pv_seid; -#define I40E_AQC_PV_ERR_FLAG_NO_PV 0x1 -#define I40E_AQC_PV_ERR_FLAG_NO_SCHED 0x2 -#define I40E_AQC_PV_ERR_FLAG_NO_COUNTER 0x4 -#define I40E_AQC_PV_ERR_FLAG_NO_ENTRY 0x8 - u8 reserved[14]; + __le16 pv_seid; +#define I40E_AQC_PV_ERR_FLAG_NO_PV 0x1 +#define I40E_AQC_PV_ERR_FLAG_NO_SCHED 0x2 +#define I40E_AQC_PV_ERR_FLAG_NO_COUNTER 0x4 +#define I40E_AQC_PV_ERR_FLAG_NO_ENTRY 0x8 + u8 reserved[14]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_update_pv_completion); @@ -860,48 +860,48 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_add_update_pv_completion); */ struct i40e_aqc_get_pv_params_completion { - __le16 seid; - __le16 default_stag; - __le16 pv_flags; /* same flags as add_pv */ -#define I40E_AQC_GET_PV_PV_TYPE 0x1 -#define I40E_AQC_GET_PV_FRWD_UNKNOWN_STAG 0x2 -#define I40E_AQC_GET_PV_FRWD_UNKNOWN_ETAG 0x4 - u8 reserved[8]; - __le16 default_port_seid; + __le16 seid; + __le16 default_stag; + __le16 pv_flags; /* same flags as add_pv */ +#define I40E_AQC_GET_PV_PV_TYPE 0x1 +#define I40E_AQC_GET_PV_FRWD_UNKNOWN_STAG 0x2 +#define I40E_AQC_GET_PV_FRWD_UNKNOWN_ETAG 0x4 + u8 reserved[8]; + __le16 default_port_seid; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_get_pv_params_completion); /* Add VEB (direct 0x0230) */ struct i40e_aqc_add_veb { - __le16 uplink_seid; - __le16 downlink_seid; - __le16 veb_flags; -#define I40E_AQC_ADD_VEB_FLOATING 0x1 -#define I40E_AQC_ADD_VEB_PORT_TYPE_SHIFT 1 -#define I40E_AQC_ADD_VEB_PORT_TYPE_MASK (0x3 << \ + __le16 uplink_seid; + __le16 downlink_seid; + __le16 veb_flags; +#define I40E_AQC_ADD_VEB_FLOATING 0x1 +#define I40E_AQC_ADD_VEB_PORT_TYPE_SHIFT 1 +#define I40E_AQC_ADD_VEB_PORT_TYPE_MASK (0x3 << \ I40E_AQC_ADD_VEB_PORT_TYPE_SHIFT) -#define I40E_AQC_ADD_VEB_PORT_TYPE_DEFAULT 0x2 -#define I40E_AQC_ADD_VEB_PORT_TYPE_DATA 0x4 -#define I40E_AQC_ADD_VEB_ENABLE_L2_FILTER 0x8 - u8 enable_tcs; - u8 reserved[9]; +#define I40E_AQC_ADD_VEB_PORT_TYPE_DEFAULT 0x2 +#define I40E_AQC_ADD_VEB_PORT_TYPE_DATA 0x4 +#define I40E_AQC_ADD_VEB_ENABLE_L2_FILTER 0x8 + u8 enable_tcs; + u8 reserved[9]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_veb); struct i40e_aqc_add_veb_completion { - u8 reserved[6]; - __le16 switch_seid; + u8 reserved[6]; + __le16 switch_seid; /* also encodes error if rc == ENOSPC; codes are the same as add_pv */ - __le16 veb_seid; -#define I40E_AQC_VEB_ERR_FLAG_NO_VEB 0x1 -#define I40E_AQC_VEB_ERR_FLAG_NO_SCHED 0x2 -#define I40E_AQC_VEB_ERR_FLAG_NO_COUNTER 0x4 -#define I40E_AQC_VEB_ERR_FLAG_NO_ENTRY 0x8 - __le16 statistic_index; - __le16 vebs_used; - __le16 vebs_free; + __le16 veb_seid; +#define I40E_AQC_VEB_ERR_FLAG_NO_VEB 0x1 +#define I40E_AQC_VEB_ERR_FLAG_NO_SCHED 0x2 +#define I40E_AQC_VEB_ERR_FLAG_NO_COUNTER 0x4 +#define I40E_AQC_VEB_ERR_FLAG_NO_ENTRY 0x8 + __le16 statistic_index; + __le16 vebs_used; + __le16 vebs_free; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_veb_completion); @@ -910,13 +910,13 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_add_veb_completion); * uses i40e_aqc_switch_seid for the descriptor */ struct i40e_aqc_get_veb_parameters_completion { - __le16 seid; - __le16 switch_id; - __le16 veb_flags; /* only the first/last flags from 0x0230 is valid */ - __le16 statistic_index; - __le16 vebs_used; - __le16 vebs_free; - u8 reserved[4]; + __le16 seid; + __le16 switch_id; + __le16 veb_flags; /* only the first/last flags from 0x0230 is valid */ + __le16 statistic_index; + __le16 vebs_used; + __le16 vebs_free; + u8 reserved[4]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_get_veb_parameters_completion); @@ -929,37 +929,37 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_get_veb_parameters_completion); /* used for the command for most vlan commands */ struct i40e_aqc_macvlan { - __le16 num_addresses; - __le16 seid[3]; -#define I40E_AQC_MACVLAN_CMD_SEID_NUM_SHIFT 0 -#define I40E_AQC_MACVLAN_CMD_SEID_NUM_MASK (0x3FF << \ + __le16 num_addresses; + __le16 seid[3]; +#define I40E_AQC_MACVLAN_CMD_SEID_NUM_SHIFT 0 +#define I40E_AQC_MACVLAN_CMD_SEID_NUM_MASK (0x3FF << \ I40E_AQC_MACVLAN_CMD_SEID_NUM_SHIFT) -#define I40E_AQC_MACVLAN_CMD_SEID_VALID 0x8000 - __le32 addr_high; - __le32 addr_low; +#define I40E_AQC_MACVLAN_CMD_SEID_VALID 0x8000 + __le32 addr_high; + __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_macvlan); /* indirect data for command and response */ struct i40e_aqc_add_macvlan_element_data { - u8 mac_addr[6]; - __le16 vlan_tag; - __le16 flags; -#define I40E_AQC_MACVLAN_ADD_PERFECT_MATCH 0x0001 -#define I40E_AQC_MACVLAN_ADD_HASH_MATCH 0x0002 -#define I40E_AQC_MACVLAN_ADD_IGNORE_VLAN 0x0004 -#define I40E_AQC_MACVLAN_ADD_TO_QUEUE 0x0008 - __le16 queue_number; -#define I40E_AQC_MACVLAN_CMD_QUEUE_SHIFT 0 -#define I40E_AQC_MACVLAN_CMD_QUEUE_MASK (0x7FF << \ + u8 mac_addr[6]; + __le16 vlan_tag; + __le16 flags; +#define I40E_AQC_MACVLAN_ADD_PERFECT_MATCH 0x0001 +#define I40E_AQC_MACVLAN_ADD_HASH_MATCH 0x0002 +#define I40E_AQC_MACVLAN_ADD_IGNORE_VLAN 0x0004 +#define I40E_AQC_MACVLAN_ADD_TO_QUEUE 0x0008 + __le16 queue_number; +#define I40E_AQC_MACVLAN_CMD_QUEUE_SHIFT 0 +#define I40E_AQC_MACVLAN_CMD_QUEUE_MASK (0x7FF << \ I40E_AQC_MACVLAN_CMD_SEID_NUM_SHIFT) /* response section */ - u8 match_method; -#define I40E_AQC_MM_PERFECT_MATCH 0x01 -#define I40E_AQC_MM_HASH_MATCH 0x02 -#define I40E_AQC_MM_ERR_NO_RES 0xFF - u8 reserved1[3]; + u8 match_method; +#define I40E_AQC_MM_PERFECT_MATCH 0x01 +#define I40E_AQC_MM_HASH_MATCH 0x02 +#define I40E_AQC_MM_ERR_NO_RES 0xFF + u8 reserved1[3]; }; struct i40e_aqc_add_remove_macvlan_completion { @@ -979,19 +979,19 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_macvlan_completion); */ struct i40e_aqc_remove_macvlan_element_data { - u8 mac_addr[6]; - __le16 vlan_tag; - u8 flags; -#define I40E_AQC_MACVLAN_DEL_PERFECT_MATCH 0x01 -#define I40E_AQC_MACVLAN_DEL_HASH_MATCH 0x02 -#define I40E_AQC_MACVLAN_DEL_IGNORE_VLAN 0x08 -#define I40E_AQC_MACVLAN_DEL_ALL_VSIS 0x10 - u8 reserved[3]; + u8 mac_addr[6]; + __le16 vlan_tag; + u8 flags; +#define I40E_AQC_MACVLAN_DEL_PERFECT_MATCH 0x01 +#define I40E_AQC_MACVLAN_DEL_HASH_MATCH 0x02 +#define I40E_AQC_MACVLAN_DEL_IGNORE_VLAN 0x08 +#define I40E_AQC_MACVLAN_DEL_ALL_VSIS 0x10 + u8 reserved[3]; /* reply section */ - u8 error_code; -#define I40E_AQC_REMOVE_MACVLAN_SUCCESS 0x0 -#define I40E_AQC_REMOVE_MACVLAN_FAIL 0xFF - u8 reply_reserved[3]; + u8 error_code; +#define I40E_AQC_REMOVE_MACVLAN_SUCCESS 0x0 +#define I40E_AQC_REMOVE_MACVLAN_FAIL 0xFF + u8 reply_reserved[3]; }; /* Add VLAN (indirect 0x0252) @@ -999,59 +999,58 @@ struct i40e_aqc_remove_macvlan_element_data { * use the generic i40e_aqc_macvlan for the command */ struct i40e_aqc_add_remove_vlan_element_data { - __le16 vlan_tag; - u8 vlan_flags; + __le16 vlan_tag; + u8 vlan_flags; /* flags for add VLAN */ -#define I40E_AQC_ADD_VLAN_LOCAL 0x1 -#define I40E_AQC_ADD_PVLAN_TYPE_SHIFT 1 -#define I40E_AQC_ADD_PVLAN_TYPE_MASK (0x3 << \ - I40E_AQC_ADD_PVLAN_TYPE_SHIFT) -#define I40E_AQC_ADD_PVLAN_TYPE_REGULAR 0x0 -#define I40E_AQC_ADD_PVLAN_TYPE_PRIMARY 0x2 -#define I40E_AQC_ADD_PVLAN_TYPE_SECONDARY 0x4 -#define I40E_AQC_VLAN_PTYPE_SHIFT 3 -#define I40E_AQC_VLAN_PTYPE_MASK (0x3 << I40E_AQC_VLAN_PTYPE_SHIFT) -#define I40E_AQC_VLAN_PTYPE_REGULAR_VSI 0x0 -#define I40E_AQC_VLAN_PTYPE_PROMISC_VSI 0x8 -#define I40E_AQC_VLAN_PTYPE_COMMUNITY_VSI 0x10 -#define I40E_AQC_VLAN_PTYPE_ISOLATED_VSI 0x18 +#define I40E_AQC_ADD_VLAN_LOCAL 0x1 +#define I40E_AQC_ADD_PVLAN_TYPE_SHIFT 1 +#define I40E_AQC_ADD_PVLAN_TYPE_MASK (0x3 << I40E_AQC_ADD_PVLAN_TYPE_SHIFT) +#define I40E_AQC_ADD_PVLAN_TYPE_REGULAR 0x0 +#define I40E_AQC_ADD_PVLAN_TYPE_PRIMARY 0x2 +#define I40E_AQC_ADD_PVLAN_TYPE_SECONDARY 0x4 +#define I40E_AQC_VLAN_PTYPE_SHIFT 3 +#define I40E_AQC_VLAN_PTYPE_MASK (0x3 << I40E_AQC_VLAN_PTYPE_SHIFT) +#define I40E_AQC_VLAN_PTYPE_REGULAR_VSI 0x0 +#define I40E_AQC_VLAN_PTYPE_PROMISC_VSI 0x8 +#define I40E_AQC_VLAN_PTYPE_COMMUNITY_VSI 0x10 +#define I40E_AQC_VLAN_PTYPE_ISOLATED_VSI 0x18 /* flags for remove VLAN */ -#define I40E_AQC_REMOVE_VLAN_ALL 0x1 - u8 reserved; - u8 result; +#define I40E_AQC_REMOVE_VLAN_ALL 0x1 + u8 reserved; + u8 result; /* flags for add VLAN */ -#define I40E_AQC_ADD_VLAN_SUCCESS 0x0 -#define I40E_AQC_ADD_VLAN_FAIL_REQUEST 0xFE -#define I40E_AQC_ADD_VLAN_FAIL_RESOURCE 0xFF +#define I40E_AQC_ADD_VLAN_SUCCESS 0x0 +#define I40E_AQC_ADD_VLAN_FAIL_REQUEST 0xFE +#define I40E_AQC_ADD_VLAN_FAIL_RESOURCE 0xFF /* flags for remove VLAN */ -#define I40E_AQC_REMOVE_VLAN_SUCCESS 0x0 -#define I40E_AQC_REMOVE_VLAN_FAIL 0xFF - u8 reserved1[3]; +#define I40E_AQC_REMOVE_VLAN_SUCCESS 0x0 +#define I40E_AQC_REMOVE_VLAN_FAIL 0xFF + u8 reserved1[3]; }; struct i40e_aqc_add_remove_vlan_completion { - u8 reserved[4]; - __le16 vlans_used; - __le16 vlans_free; - __le32 addr_high; - __le32 addr_low; + u8 reserved[4]; + __le16 vlans_used; + __le16 vlans_free; + __le32 addr_high; + __le32 addr_low; }; /* Set VSI Promiscuous Modes (direct 0x0254) */ struct i40e_aqc_set_vsi_promiscuous_modes { - __le16 promiscuous_flags; - __le16 valid_flags; + __le16 promiscuous_flags; + __le16 valid_flags; /* flags used for both fields above */ -#define I40E_AQC_SET_VSI_PROMISC_UNICAST 0x01 -#define I40E_AQC_SET_VSI_PROMISC_MULTICAST 0x02 -#define I40E_AQC_SET_VSI_PROMISC_BROADCAST 0x04 -#define I40E_AQC_SET_VSI_DEFAULT 0x08 -#define I40E_AQC_SET_VSI_PROMISC_VLAN 0x10 - __le16 seid; -#define I40E_AQC_VSI_PROM_CMD_SEID_MASK 0x3FF - __le16 vlan_tag; -#define I40E_AQC_SET_VSI_VLAN_VALID 0x8000 - u8 reserved[8]; +#define I40E_AQC_SET_VSI_PROMISC_UNICAST 0x01 +#define I40E_AQC_SET_VSI_PROMISC_MULTICAST 0x02 +#define I40E_AQC_SET_VSI_PROMISC_BROADCAST 0x04 +#define I40E_AQC_SET_VSI_DEFAULT 0x08 +#define I40E_AQC_SET_VSI_PROMISC_VLAN 0x10 + __le16 seid; +#define I40E_AQC_VSI_PROM_CMD_SEID_MASK 0x3FF + __le16 vlan_tag; +#define I40E_AQC_SET_VSI_VLAN_VALID 0x8000 + u8 reserved[8]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_set_vsi_promiscuous_modes); @@ -1060,23 +1059,23 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_set_vsi_promiscuous_modes); * Uses generic i40e_aqc_add_remove_tag_completion for completion */ struct i40e_aqc_add_tag { - __le16 flags; -#define I40E_AQC_ADD_TAG_FLAG_TO_QUEUE 0x0001 - __le16 seid; -#define I40E_AQC_ADD_TAG_CMD_SEID_NUM_SHIFT 0 -#define I40E_AQC_ADD_TAG_CMD_SEID_NUM_MASK (0x3FF << \ + __le16 flags; +#define I40E_AQC_ADD_TAG_FLAG_TO_QUEUE 0x0001 + __le16 seid; +#define I40E_AQC_ADD_TAG_CMD_SEID_NUM_SHIFT 0 +#define I40E_AQC_ADD_TAG_CMD_SEID_NUM_MASK (0x3FF << \ I40E_AQC_ADD_TAG_CMD_SEID_NUM_SHIFT) - __le16 tag; - __le16 queue_number; - u8 reserved[8]; + __le16 tag; + __le16 queue_number; + u8 reserved[8]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_tag); struct i40e_aqc_add_remove_tag_completion { - u8 reserved[12]; - __le16 tags_used; - __le16 tags_free; + u8 reserved[12]; + __le16 tags_used; + __le16 tags_free; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_tag_completion); @@ -1085,12 +1084,12 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_tag_completion); * Uses generic i40e_aqc_add_remove_tag_completion for completion */ struct i40e_aqc_remove_tag { - __le16 seid; -#define I40E_AQC_REMOVE_TAG_CMD_SEID_NUM_SHIFT 0 -#define I40E_AQC_REMOVE_TAG_CMD_SEID_NUM_MASK (0x3FF << \ + __le16 seid; +#define I40E_AQC_REMOVE_TAG_CMD_SEID_NUM_SHIFT 0 +#define I40E_AQC_REMOVE_TAG_CMD_SEID_NUM_MASK (0x3FF << \ I40E_AQC_REMOVE_TAG_CMD_SEID_NUM_SHIFT) - __le16 tag; - u8 reserved[12]; + __le16 tag; + u8 reserved[12]; }; /* Add multicast E-Tag (direct 0x0257) @@ -1098,22 +1097,22 @@ struct i40e_aqc_remove_tag { * and no external data */ struct i40e_aqc_add_remove_mcast_etag { - __le16 pv_seid; - __le16 etag; - u8 num_unicast_etags; - u8 reserved[3]; - __le32 addr_high; /* address of array of 2-byte s-tags */ - __le32 addr_low; + __le16 pv_seid; + __le16 etag; + u8 num_unicast_etags; + u8 reserved[3]; + __le32 addr_high; /* address of array of 2-byte s-tags */ + __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_mcast_etag); struct i40e_aqc_add_remove_mcast_etag_completion { - u8 reserved[4]; - __le16 mcast_etags_used; - __le16 mcast_etags_free; - __le32 addr_high; - __le32 addr_low; + u8 reserved[4]; + __le16 mcast_etags_used; + __le16 mcast_etags_free; + __le32 addr_high; + __le32 addr_low; }; @@ -1121,21 +1120,21 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_mcast_etag_completion); /* Update S/E-Tag (direct 0x0259) */ struct i40e_aqc_update_tag { - __le16 seid; -#define I40E_AQC_UPDATE_TAG_CMD_SEID_NUM_SHIFT 0 -#define I40E_AQC_UPDATE_TAG_CMD_SEID_NUM_MASK (0x3FF << \ + __le16 seid; +#define I40E_AQC_UPDATE_TAG_CMD_SEID_NUM_SHIFT 0 +#define I40E_AQC_UPDATE_TAG_CMD_SEID_NUM_MASK (0x3FF << \ I40E_AQC_UPDATE_TAG_CMD_SEID_NUM_SHIFT) - __le16 old_tag; - __le16 new_tag; - u8 reserved[10]; + __le16 old_tag; + __le16 new_tag; + u8 reserved[10]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_update_tag); struct i40e_aqc_update_tag_completion { - u8 reserved[12]; - __le16 tags_used; - __le16 tags_free; + u8 reserved[12]; + __le16 tags_used; + __le16 tags_free; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_update_tag_completion); @@ -1146,30 +1145,30 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_update_tag_completion); * and the generic direct completion structure */ struct i40e_aqc_add_remove_control_packet_filter { - u8 mac[6]; - __le16 etype; - __le16 flags; -#define I40E_AQC_ADD_CONTROL_PACKET_FLAGS_IGNORE_MAC 0x0001 -#define I40E_AQC_ADD_CONTROL_PACKET_FLAGS_DROP 0x0002 -#define I40E_AQC_ADD_CONTROL_PACKET_FLAGS_TO_QUEUE 0x0004 -#define I40E_AQC_ADD_CONTROL_PACKET_FLAGS_TX 0x0008 -#define I40E_AQC_ADD_CONTROL_PACKET_FLAGS_RX 0x0000 - __le16 seid; -#define I40E_AQC_ADD_CONTROL_PACKET_CMD_SEID_NUM_SHIFT 0 -#define I40E_AQC_ADD_CONTROL_PACKET_CMD_SEID_NUM_MASK (0x3FF << \ + u8 mac[6]; + __le16 etype; + __le16 flags; +#define I40E_AQC_ADD_CONTROL_PACKET_FLAGS_IGNORE_MAC 0x0001 +#define I40E_AQC_ADD_CONTROL_PACKET_FLAGS_DROP 0x0002 +#define I40E_AQC_ADD_CONTROL_PACKET_FLAGS_TO_QUEUE 0x0004 +#define I40E_AQC_ADD_CONTROL_PACKET_FLAGS_TX 0x0008 +#define I40E_AQC_ADD_CONTROL_PACKET_FLAGS_RX 0x0000 + __le16 seid; +#define I40E_AQC_ADD_CONTROL_PACKET_CMD_SEID_NUM_SHIFT 0 +#define I40E_AQC_ADD_CONTROL_PACKET_CMD_SEID_NUM_MASK (0x3FF << \ I40E_AQC_ADD_CONTROL_PACKET_CMD_SEID_NUM_SHIFT) - __le16 queue; - u8 reserved[2]; + __le16 queue; + u8 reserved[2]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_control_packet_filter); struct i40e_aqc_add_remove_control_packet_filter_completion { - __le16 mac_etype_used; - __le16 etype_used; - __le16 mac_etype_free; - __le16 etype_free; - u8 reserved[8]; + __le16 mac_etype_used; + __le16 etype_used; + __le16 mac_etype_free; + __le16 etype_free; + u8 reserved[8]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_control_packet_filter_completion); @@ -1180,23 +1179,23 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_control_packet_filter_completion); * and the generic indirect completion structure */ struct i40e_aqc_add_remove_cloud_filters { - u8 num_filters; - u8 reserved; - __le16 seid; -#define I40E_AQC_ADD_CLOUD_CMD_SEID_NUM_SHIFT 0 -#define I40E_AQC_ADD_CLOUD_CMD_SEID_NUM_MASK (0x3FF << \ + u8 num_filters; + u8 reserved; + __le16 seid; +#define I40E_AQC_ADD_CLOUD_CMD_SEID_NUM_SHIFT 0 +#define I40E_AQC_ADD_CLOUD_CMD_SEID_NUM_MASK (0x3FF << \ I40E_AQC_ADD_CLOUD_CMD_SEID_NUM_SHIFT) - u8 reserved2[4]; - __le32 addr_high; - __le32 addr_low; + u8 reserved2[4]; + __le32 addr_high; + __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_cloud_filters); struct i40e_aqc_add_remove_cloud_filters_element_data { - u8 outer_mac[6]; - u8 inner_mac[6]; - __le16 inner_vlan; + u8 outer_mac[6]; + u8 inner_mac[6]; + __le16 inner_vlan; union { struct { u8 reserved[12]; @@ -1206,52 +1205,49 @@ struct i40e_aqc_add_remove_cloud_filters_element_data { u8 data[16]; } v6; } ipaddr; - __le16 flags; -#define I40E_AQC_ADD_CLOUD_FILTER_SHIFT 0 -#define I40E_AQC_ADD_CLOUD_FILTER_MASK (0x3F << \ + __le16 flags; +#define I40E_AQC_ADD_CLOUD_FILTER_SHIFT 0 +#define I40E_AQC_ADD_CLOUD_FILTER_MASK (0x3F << \ I40E_AQC_ADD_CLOUD_FILTER_SHIFT) -#define I40E_AQC_ADD_CLOUD_FILTER_OIP_GRE 0x0002 -#define I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN_GRE 0x0004 -#define I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN_VNL 0x0007 /* 0x0000 reserved */ -#define I40E_AQC_ADD_CLOUD_FILTER_OIP 0x0001 +#define I40E_AQC_ADD_CLOUD_FILTER_OIP 0x0001 /* 0x0002 reserved */ -#define I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN 0x0003 -#define I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN_TEN_ID 0x0004 +#define I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN 0x0003 +#define I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN_TEN_ID 0x0004 /* 0x0005 reserved */ -#define I40E_AQC_ADD_CLOUD_FILTER_IMAC_TEN_ID 0x0006 +#define I40E_AQC_ADD_CLOUD_FILTER_IMAC_TEN_ID 0x0006 /* 0x0007 reserved */ /* 0x0008 reserved */ -#define I40E_AQC_ADD_CLOUD_FILTER_OMAC 0x0009 -#define I40E_AQC_ADD_CLOUD_FILTER_IMAC 0x000A -#define I40E_AQC_ADD_CLOUD_FILTER_OMAC_TEN_ID_IMAC 0x000B -#define I40E_AQC_ADD_CLOUD_FILTER_IIP 0x000C - -#define I40E_AQC_ADD_CLOUD_FLAGS_TO_QUEUE 0x0080 -#define I40E_AQC_ADD_CLOUD_VNK_SHIFT 6 -#define I40E_AQC_ADD_CLOUD_VNK_MASK 0x00C0 -#define I40E_AQC_ADD_CLOUD_FLAGS_IPV4 0 -#define I40E_AQC_ADD_CLOUD_FLAGS_IPV6 0x0100 - -#define I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT 9 -#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MASK 0x1E00 -#define I40E_AQC_ADD_CLOUD_TNL_TYPE_XVLAN 0 -#define I40E_AQC_ADD_CLOUD_TNL_TYPE_NVGRE_OMAC 1 -#define I40E_AQC_ADD_CLOUD_TNL_TYPE_NGE 2 -#define I40E_AQC_ADD_CLOUD_TNL_TYPE_IP 3 - - __le32 tenant_id; - u8 reserved[4]; - __le16 queue_number; -#define I40E_AQC_ADD_CLOUD_QUEUE_SHIFT 0 -#define I40E_AQC_ADD_CLOUD_QUEUE_MASK (0x3F << \ - I40E_AQC_ADD_CLOUD_QUEUE_SHIFT) - u8 reserved2[14]; +#define I40E_AQC_ADD_CLOUD_FILTER_OMAC 0x0009 +#define I40E_AQC_ADD_CLOUD_FILTER_IMAC 0x000A +#define I40E_AQC_ADD_CLOUD_FILTER_OMAC_TEN_ID_IMAC 0x000B +#define I40E_AQC_ADD_CLOUD_FILTER_IIP 0x000C + +#define I40E_AQC_ADD_CLOUD_FLAGS_TO_QUEUE 0x0080 +#define I40E_AQC_ADD_CLOUD_VNK_SHIFT 6 +#define I40E_AQC_ADD_CLOUD_VNK_MASK 0x00C0 +#define I40E_AQC_ADD_CLOUD_FLAGS_IPV4 0 +#define I40E_AQC_ADD_CLOUD_FLAGS_IPV6 0x0100 + +#define I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT 9 +#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MASK 0x1E00 +#define I40E_AQC_ADD_CLOUD_TNL_TYPE_XVLAN 0 +#define I40E_AQC_ADD_CLOUD_TNL_TYPE_NVGRE_OMAC 1 +#define I40E_AQC_ADD_CLOUD_TNL_TYPE_NGE 2 +#define I40E_AQC_ADD_CLOUD_TNL_TYPE_IP 3 + + __le32 tenant_id; + u8 reserved[4]; + __le16 queue_number; +#define I40E_AQC_ADD_CLOUD_QUEUE_SHIFT 0 +#define I40E_AQC_ADD_CLOUD_QUEUE_MASK (0x3F << \ + I40E_AQC_ADD_CLOUD_QUEUE_SHIFT) + u8 reserved2[14]; /* response section */ - u8 allocation_result; -#define I40E_AQC_ADD_CLOUD_FILTER_SUCCESS 0x0 -#define I40E_AQC_ADD_CLOUD_FILTER_FAIL 0xFF - u8 response_reserved[7]; + u8 allocation_result; +#define I40E_AQC_ADD_CLOUD_FILTER_SUCCESS 0x0 +#define I40E_AQC_ADD_CLOUD_FILTER_FAIL 0xFF + u8 response_reserved[7]; }; struct i40e_aqc_remove_cloud_filters_completion { @@ -1273,14 +1269,14 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_remove_cloud_filters_completion); struct i40e_aqc_add_delete_mirror_rule { __le16 seid; __le16 rule_type; -#define I40E_AQC_MIRROR_RULE_TYPE_SHIFT 0 -#define I40E_AQC_MIRROR_RULE_TYPE_MASK (0x7 << \ +#define I40E_AQC_MIRROR_RULE_TYPE_SHIFT 0 +#define I40E_AQC_MIRROR_RULE_TYPE_MASK (0x7 << \ I40E_AQC_MIRROR_RULE_TYPE_SHIFT) -#define I40E_AQC_MIRROR_RULE_TYPE_VPORT_INGRESS 1 -#define I40E_AQC_MIRROR_RULE_TYPE_VPORT_EGRESS 2 -#define I40E_AQC_MIRROR_RULE_TYPE_VLAN 3 -#define I40E_AQC_MIRROR_RULE_TYPE_ALL_INGRESS 4 -#define I40E_AQC_MIRROR_RULE_TYPE_ALL_EGRESS 5 +#define I40E_AQC_MIRROR_RULE_TYPE_VPORT_INGRESS 1 +#define I40E_AQC_MIRROR_RULE_TYPE_VPORT_EGRESS 2 +#define I40E_AQC_MIRROR_RULE_TYPE_VLAN 3 +#define I40E_AQC_MIRROR_RULE_TYPE_ALL_INGRESS 4 +#define I40E_AQC_MIRROR_RULE_TYPE_ALL_EGRESS 5 __le16 num_entries; __le16 destination; /* VSI for add, rule id for delete */ __le32 addr_high; /* address of array of 2-byte VSI or VLAN ids */ @@ -1290,12 +1286,12 @@ struct i40e_aqc_add_delete_mirror_rule { I40E_CHECK_CMD_LENGTH(i40e_aqc_add_delete_mirror_rule); struct i40e_aqc_add_delete_mirror_rule_completion { - u8 reserved[2]; - __le16 rule_id; /* only used on add */ - __le16 mirror_rules_used; - __le16 mirror_rules_free; - __le32 addr_high; - __le32 addr_low; + u8 reserved[2]; + __le16 rule_id; /* only used on add */ + __le16 mirror_rules_used; + __le16 mirror_rules_free; + __le32 addr_high; + __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_delete_mirror_rule_completion); @@ -1306,11 +1302,11 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_add_delete_mirror_rule_completion); * the command and response use the same descriptor structure */ struct i40e_aqc_pfc_ignore { - u8 tc_bitmap; - u8 command_flags; /* unused on response */ -#define I40E_AQC_PFC_IGNORE_SET 0x80 -#define I40E_AQC_PFC_IGNORE_CLEAR 0x0 - u8 reserved[14]; + u8 tc_bitmap; + u8 command_flags; /* unused on response */ +#define I40E_AQC_PFC_IGNORE_SET 0x80 +#define I40E_AQC_PFC_IGNORE_CLEAR 0x0 + u8 reserved[14]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_pfc_ignore); @@ -1325,10 +1321,10 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_pfc_ignore); * this generic struct to pass the SEID in param0 */ struct i40e_aqc_tx_sched_ind { - __le16 vsi_seid; - u8 reserved[6]; - __le32 addr_high; - __le32 addr_low; + __le16 vsi_seid; + u8 reserved[6]; + __le32 addr_high; + __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_tx_sched_ind); @@ -1340,12 +1336,12 @@ struct i40e_aqc_qs_handles_resp { /* Configure VSI BW limits (direct 0x0400) */ struct i40e_aqc_configure_vsi_bw_limit { - __le16 vsi_seid; - u8 reserved[2]; - __le16 credit; - u8 reserved1[2]; - u8 max_credit; /* 0-3, limit = 2^max */ - u8 reserved2[7]; + __le16 vsi_seid; + u8 reserved[2]; + __le16 credit; + u8 reserved1[2]; + u8 max_credit; /* 0-3, limit = 2^max */ + u8 reserved2[7]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_configure_vsi_bw_limit); @@ -1354,58 +1350,58 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_configure_vsi_bw_limit); * responds with i40e_aqc_qs_handles_resp */ struct i40e_aqc_configure_vsi_ets_sla_bw_data { - u8 tc_valid_bits; - u8 reserved[15]; - __le16 tc_bw_credits[8]; /* FW writesback QS handles here */ + u8 tc_valid_bits; + u8 reserved[15]; + __le16 tc_bw_credits[8]; /* FW writesback QS handles here */ /* 4 bits per tc 0-7, 4th bit is reserved, limit = 2^max */ - __le16 tc_bw_max[2]; - u8 reserved1[28]; + __le16 tc_bw_max[2]; + u8 reserved1[28]; }; /* Configure VSI Bandwidth Allocation per Traffic Type (indirect 0x0407) * responds with i40e_aqc_qs_handles_resp */ struct i40e_aqc_configure_vsi_tc_bw_data { - u8 tc_valid_bits; - u8 reserved[3]; - u8 tc_bw_credits[8]; - u8 reserved1[4]; - __le16 qs_handles[8]; + u8 tc_valid_bits; + u8 reserved[3]; + u8 tc_bw_credits[8]; + u8 reserved1[4]; + __le16 qs_handles[8]; }; /* Query vsi bw configuration (indirect 0x0408) */ struct i40e_aqc_query_vsi_bw_config_resp { - u8 tc_valid_bits; - u8 tc_suspended_bits; - u8 reserved[14]; - __le16 qs_handles[8]; - u8 reserved1[4]; - __le16 port_bw_limit; - u8 reserved2[2]; - u8 max_bw; /* 0-3, limit = 2^max */ - u8 reserved3[23]; + u8 tc_valid_bits; + u8 tc_suspended_bits; + u8 reserved[14]; + __le16 qs_handles[8]; + u8 reserved1[4]; + __le16 port_bw_limit; + u8 reserved2[2]; + u8 max_bw; /* 0-3, limit = 2^max */ + u8 reserved3[23]; }; /* Query VSI Bandwidth Allocation per Traffic Type (indirect 0x040A) */ struct i40e_aqc_query_vsi_ets_sla_config_resp { - u8 tc_valid_bits; - u8 reserved[3]; - u8 share_credits[8]; - __le16 credits[8]; + u8 tc_valid_bits; + u8 reserved[3]; + u8 share_credits[8]; + __le16 credits[8]; /* 4 bits per tc 0-7, 4th bit is reserved, limit = 2^max */ - __le16 tc_bw_max[2]; + __le16 tc_bw_max[2]; }; /* Configure Switching Component Bandwidth Limit (direct 0x0410) */ struct i40e_aqc_configure_switching_comp_bw_limit { - __le16 seid; - u8 reserved[2]; - __le16 credit; - u8 reserved1[2]; - u8 max_bw; /* 0-3, limit = 2^max */ - u8 reserved2[7]; + __le16 seid; + u8 reserved[2]; + __le16 credit; + u8 reserved1[2]; + u8 max_bw; /* 0-3, limit = 2^max */ + u8 reserved2[7]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_configure_switching_comp_bw_limit); @@ -1415,75 +1411,75 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_configure_switching_comp_bw_limit); * Disable Physical Port ETS (indirect 0x0415) */ struct i40e_aqc_configure_switching_comp_ets_data { - u8 reserved[4]; - u8 tc_valid_bits; - u8 seepage; -#define I40E_AQ_ETS_SEEPAGE_EN_MASK 0x1 - u8 tc_strict_priority_flags; - u8 reserved1[17]; - u8 tc_bw_share_credits[8]; - u8 reserved2[96]; + u8 reserved[4]; + u8 tc_valid_bits; + u8 seepage; +#define I40E_AQ_ETS_SEEPAGE_EN_MASK 0x1 + u8 tc_strict_priority_flags; + u8 reserved1[17]; + u8 tc_bw_share_credits[8]; + u8 reserved2[96]; }; /* Configure Switching Component Bandwidth Limits per Tc (indirect 0x0416) */ struct i40e_aqc_configure_switching_comp_ets_bw_limit_data { - u8 tc_valid_bits; - u8 reserved[15]; - __le16 tc_bw_credit[8]; + u8 tc_valid_bits; + u8 reserved[15]; + __le16 tc_bw_credit[8]; /* 4 bits per tc 0-7, 4th bit is reserved, limit = 2^max */ - __le16 tc_bw_max[2]; - u8 reserved1[28]; + __le16 tc_bw_max[2]; + u8 reserved1[28]; }; /* Configure Switching Component Bandwidth Allocation per Tc * (indirect 0x0417) */ struct i40e_aqc_configure_switching_comp_bw_config_data { - u8 tc_valid_bits; - u8 reserved[2]; - u8 absolute_credits; /* bool */ - u8 tc_bw_share_credits[8]; - u8 reserved1[20]; + u8 tc_valid_bits; + u8 reserved[2]; + u8 absolute_credits; /* bool */ + u8 tc_bw_share_credits[8]; + u8 reserved1[20]; }; /* Query Switching Component Configuration (indirect 0x0418) */ struct i40e_aqc_query_switching_comp_ets_config_resp { - u8 tc_valid_bits; - u8 reserved[35]; - __le16 port_bw_limit; - u8 reserved1[2]; - u8 tc_bw_max; /* 0-3, limit = 2^max */ - u8 reserved2[23]; + u8 tc_valid_bits; + u8 reserved[35]; + __le16 port_bw_limit; + u8 reserved1[2]; + u8 tc_bw_max; /* 0-3, limit = 2^max */ + u8 reserved2[23]; }; /* Query PhysicalPort ETS Configuration (indirect 0x0419) */ struct i40e_aqc_query_port_ets_config_resp { - u8 reserved[4]; - u8 tc_valid_bits; - u8 reserved1; - u8 tc_strict_priority_bits; - u8 reserved2; - u8 tc_bw_share_credits[8]; - __le16 tc_bw_limits[8]; + u8 reserved[4]; + u8 tc_valid_bits; + u8 reserved1; + u8 tc_strict_priority_bits; + u8 reserved2; + u8 tc_bw_share_credits[8]; + __le16 tc_bw_limits[8]; /* 4 bits per tc 0-7, 4th bit reserved, limit = 2^max */ - __le16 tc_bw_max[2]; - u8 reserved3[32]; + __le16 tc_bw_max[2]; + u8 reserved3[32]; }; /* Query Switching Component Bandwidth Allocation per Traffic Type * (indirect 0x041A) */ struct i40e_aqc_query_switching_comp_bw_config_resp { - u8 tc_valid_bits; - u8 reserved[2]; - u8 absolute_credits_enable; /* bool */ - u8 tc_bw_share_credits[8]; - __le16 tc_bw_limits[8]; + u8 tc_valid_bits; + u8 reserved[2]; + u8 absolute_credits_enable; /* bool */ + u8 tc_bw_share_credits[8]; + __le16 tc_bw_limits[8]; /* 4 bits per tc 0-7, 4th bit is reserved, limit = 2^max */ - __le16 tc_bw_max[2]; + __le16 tc_bw_max[2]; }; /* Suspend/resume port TX traffic @@ -1494,37 +1490,37 @@ struct i40e_aqc_query_switching_comp_bw_config_resp { * (indirect 0x041D) */ struct i40e_aqc_configure_partition_bw_data { - __le16 pf_valid_bits; - u8 min_bw[16]; /* guaranteed bandwidth */ - u8 max_bw[16]; /* bandwidth limit */ + __le16 pf_valid_bits; + u8 min_bw[16]; /* guaranteed bandwidth */ + u8 max_bw[16]; /* bandwidth limit */ }; /* Get and set the active HMC resource profile and status. * (direct 0x0500) and (direct 0x0501) */ struct i40e_aq_get_set_hmc_resource_profile { - u8 pm_profile; - u8 pe_vf_enabled; - u8 reserved[14]; + u8 pm_profile; + u8 pe_vf_enabled; + u8 reserved[14]; }; I40E_CHECK_CMD_LENGTH(i40e_aq_get_set_hmc_resource_profile); enum i40e_aq_hmc_profile { /* I40E_HMC_PROFILE_NO_CHANGE = 0, reserved */ - I40E_HMC_PROFILE_DEFAULT = 1, - I40E_HMC_PROFILE_FAVOR_VF = 2, - I40E_HMC_PROFILE_EQUAL = 3, + I40E_HMC_PROFILE_DEFAULT = 1, + I40E_HMC_PROFILE_FAVOR_VF = 2, + I40E_HMC_PROFILE_EQUAL = 3, }; -#define I40E_AQ_GET_HMC_RESOURCE_PROFILE_PM_MASK 0xF -#define I40E_AQ_GET_HMC_RESOURCE_PROFILE_COUNT_MASK 0x3F +#define I40E_AQ_GET_HMC_RESOURCE_PROFILE_PM_MASK 0xF +#define I40E_AQ_GET_HMC_RESOURCE_PROFILE_COUNT_MASK 0x3F /* Get PHY Abilities (indirect 0x0600) uses the generic indirect struct */ /* set in param0 for get phy abilities to report qualified modules */ -#define I40E_AQ_PHY_REPORT_QUALIFIED_MODULES 0x0001 -#define I40E_AQ_PHY_REPORT_INITIAL_VALUES 0x0002 +#define I40E_AQ_PHY_REPORT_QUALIFIED_MODULES 0x0001 +#define I40E_AQ_PHY_REPORT_INITIAL_VALUES 0x0002 enum i40e_aq_phy_type { I40E_PHY_TYPE_SGMII = 0x0, @@ -1582,147 +1578,147 @@ struct i40e_aqc_module_desc { }; struct i40e_aq_get_phy_abilities_resp { - __le32 phy_type; /* bitmap using the above enum for offsets */ - u8 link_speed; /* bitmap using the above enum bit patterns */ - u8 abilities; -#define I40E_AQ_PHY_FLAG_PAUSE_TX 0x01 -#define I40E_AQ_PHY_FLAG_PAUSE_RX 0x02 -#define I40E_AQ_PHY_FLAG_LOW_POWER 0x04 -#define I40E_AQ_PHY_LINK_ENABLED 0x08 -#define I40E_AQ_PHY_AN_ENABLED 0x10 -#define I40E_AQ_PHY_FLAG_MODULE_QUAL 0x20 - __le16 eee_capability; -#define I40E_AQ_EEE_100BASE_TX 0x0002 -#define I40E_AQ_EEE_1000BASE_T 0x0004 -#define I40E_AQ_EEE_10GBASE_T 0x0008 -#define I40E_AQ_EEE_1000BASE_KX 0x0010 -#define I40E_AQ_EEE_10GBASE_KX4 0x0020 -#define I40E_AQ_EEE_10GBASE_KR 0x0040 - __le32 eeer_val; - u8 d3_lpan; -#define I40E_AQ_SET_PHY_D3_LPAN_ENA 0x01 - u8 reserved[3]; - u8 phy_id[4]; - u8 module_type[3]; - u8 qualified_module_count; -#define I40E_AQ_PHY_MAX_QMS 16 - struct i40e_aqc_module_desc qualified_module[I40E_AQ_PHY_MAX_QMS]; + __le32 phy_type; /* bitmap using the above enum for offsets */ + u8 link_speed; /* bitmap using the above enum bit patterns */ + u8 abilities; +#define I40E_AQ_PHY_FLAG_PAUSE_TX 0x01 +#define I40E_AQ_PHY_FLAG_PAUSE_RX 0x02 +#define I40E_AQ_PHY_FLAG_LOW_POWER 0x04 +#define I40E_AQ_PHY_LINK_ENABLED 0x08 +#define I40E_AQ_PHY_AN_ENABLED 0x10 +#define I40E_AQ_PHY_FLAG_MODULE_QUAL 0x20 + __le16 eee_capability; +#define I40E_AQ_EEE_100BASE_TX 0x0002 +#define I40E_AQ_EEE_1000BASE_T 0x0004 +#define I40E_AQ_EEE_10GBASE_T 0x0008 +#define I40E_AQ_EEE_1000BASE_KX 0x0010 +#define I40E_AQ_EEE_10GBASE_KX4 0x0020 +#define I40E_AQ_EEE_10GBASE_KR 0x0040 + __le32 eeer_val; + u8 d3_lpan; +#define I40E_AQ_SET_PHY_D3_LPAN_ENA 0x01 + u8 reserved[3]; + u8 phy_id[4]; + u8 module_type[3]; + u8 qualified_module_count; +#define I40E_AQ_PHY_MAX_QMS 16 + struct i40e_aqc_module_desc qualified_module[I40E_AQ_PHY_MAX_QMS]; }; /* Set PHY Config (direct 0x0601) */ struct i40e_aq_set_phy_config { /* same bits as above in all */ - __le32 phy_type; - u8 link_speed; - u8 abilities; + __le32 phy_type; + u8 link_speed; + u8 abilities; /* bits 0-2 use the values from get_phy_abilities_resp */ #define I40E_AQ_PHY_ENABLE_LINK 0x08 #define I40E_AQ_PHY_ENABLE_AN 0x10 #define I40E_AQ_PHY_ENABLE_ATOMIC_LINK 0x20 - __le16 eee_capability; - __le32 eeer; - u8 low_power_ctrl; - u8 reserved[3]; + __le16 eee_capability; + __le32 eeer; + u8 low_power_ctrl; + u8 reserved[3]; }; I40E_CHECK_CMD_LENGTH(i40e_aq_set_phy_config); /* Set MAC Config command data structure (direct 0x0603) */ struct i40e_aq_set_mac_config { - __le16 max_frame_size; - u8 params; -#define I40E_AQ_SET_MAC_CONFIG_CRC_EN 0x04 -#define I40E_AQ_SET_MAC_CONFIG_PACING_MASK 0x78 -#define I40E_AQ_SET_MAC_CONFIG_PACING_SHIFT 3 -#define I40E_AQ_SET_MAC_CONFIG_PACING_NONE 0x0 -#define I40E_AQ_SET_MAC_CONFIG_PACING_1B_13TX 0xF -#define I40E_AQ_SET_MAC_CONFIG_PACING_1DW_9TX 0x9 -#define I40E_AQ_SET_MAC_CONFIG_PACING_1DW_4TX 0x8 -#define I40E_AQ_SET_MAC_CONFIG_PACING_3DW_7TX 0x7 -#define I40E_AQ_SET_MAC_CONFIG_PACING_2DW_3TX 0x6 -#define I40E_AQ_SET_MAC_CONFIG_PACING_1DW_1TX 0x5 -#define I40E_AQ_SET_MAC_CONFIG_PACING_3DW_2TX 0x4 -#define I40E_AQ_SET_MAC_CONFIG_PACING_7DW_3TX 0x3 -#define I40E_AQ_SET_MAC_CONFIG_PACING_4DW_1TX 0x2 -#define I40E_AQ_SET_MAC_CONFIG_PACING_9DW_1TX 0x1 - u8 tx_timer_priority; /* bitmap */ - __le16 tx_timer_value; - __le16 fc_refresh_threshold; - u8 reserved[8]; + __le16 max_frame_size; + u8 params; +#define I40E_AQ_SET_MAC_CONFIG_CRC_EN 0x04 +#define I40E_AQ_SET_MAC_CONFIG_PACING_MASK 0x78 +#define I40E_AQ_SET_MAC_CONFIG_PACING_SHIFT 3 +#define I40E_AQ_SET_MAC_CONFIG_PACING_NONE 0x0 +#define I40E_AQ_SET_MAC_CONFIG_PACING_1B_13TX 0xF +#define I40E_AQ_SET_MAC_CONFIG_PACING_1DW_9TX 0x9 +#define I40E_AQ_SET_MAC_CONFIG_PACING_1DW_4TX 0x8 +#define I40E_AQ_SET_MAC_CONFIG_PACING_3DW_7TX 0x7 +#define I40E_AQ_SET_MAC_CONFIG_PACING_2DW_3TX 0x6 +#define I40E_AQ_SET_MAC_CONFIG_PACING_1DW_1TX 0x5 +#define I40E_AQ_SET_MAC_CONFIG_PACING_3DW_2TX 0x4 +#define I40E_AQ_SET_MAC_CONFIG_PACING_7DW_3TX 0x3 +#define I40E_AQ_SET_MAC_CONFIG_PACING_4DW_1TX 0x2 +#define I40E_AQ_SET_MAC_CONFIG_PACING_9DW_1TX 0x1 + u8 tx_timer_priority; /* bitmap */ + __le16 tx_timer_value; + __le16 fc_refresh_threshold; + u8 reserved[8]; }; I40E_CHECK_CMD_LENGTH(i40e_aq_set_mac_config); /* Restart Auto-Negotiation (direct 0x605) */ struct i40e_aqc_set_link_restart_an { - u8 command; -#define I40E_AQ_PHY_RESTART_AN 0x02 -#define I40E_AQ_PHY_LINK_ENABLE 0x04 - u8 reserved[15]; + u8 command; +#define I40E_AQ_PHY_RESTART_AN 0x02 +#define I40E_AQ_PHY_LINK_ENABLE 0x04 + u8 reserved[15]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_set_link_restart_an); /* Get Link Status cmd & response data structure (direct 0x0607) */ struct i40e_aqc_get_link_status { - __le16 command_flags; /* only field set on command */ -#define I40E_AQ_LSE_MASK 0x3 -#define I40E_AQ_LSE_NOP 0x0 -#define I40E_AQ_LSE_DISABLE 0x2 -#define I40E_AQ_LSE_ENABLE 0x3 + __le16 command_flags; /* only field set on command */ +#define I40E_AQ_LSE_MASK 0x3 +#define I40E_AQ_LSE_NOP 0x0 +#define I40E_AQ_LSE_DISABLE 0x2 +#define I40E_AQ_LSE_ENABLE 0x3 /* only response uses this flag */ -#define I40E_AQ_LSE_IS_ENABLED 0x1 - u8 phy_type; /* i40e_aq_phy_type */ - u8 link_speed; /* i40e_aq_link_speed */ - u8 link_info; -#define I40E_AQ_LINK_UP 0x01 -#define I40E_AQ_LINK_FAULT 0x02 -#define I40E_AQ_LINK_FAULT_TX 0x04 -#define I40E_AQ_LINK_FAULT_RX 0x08 -#define I40E_AQ_LINK_FAULT_REMOTE 0x10 -#define I40E_AQ_MEDIA_AVAILABLE 0x40 -#define I40E_AQ_SIGNAL_DETECT 0x80 - u8 an_info; -#define I40E_AQ_AN_COMPLETED 0x01 -#define I40E_AQ_LP_AN_ABILITY 0x02 -#define I40E_AQ_PD_FAULT 0x04 -#define I40E_AQ_FEC_EN 0x08 -#define I40E_AQ_PHY_LOW_POWER 0x10 -#define I40E_AQ_LINK_PAUSE_TX 0x20 -#define I40E_AQ_LINK_PAUSE_RX 0x40 -#define I40E_AQ_QUALIFIED_MODULE 0x80 - u8 ext_info; -#define I40E_AQ_LINK_PHY_TEMP_ALARM 0x01 -#define I40E_AQ_LINK_XCESSIVE_ERRORS 0x02 -#define I40E_AQ_LINK_TX_SHIFT 0x02 -#define I40E_AQ_LINK_TX_MASK (0x03 << I40E_AQ_LINK_TX_SHIFT) -#define I40E_AQ_LINK_TX_ACTIVE 0x00 -#define I40E_AQ_LINK_TX_DRAINED 0x01 -#define I40E_AQ_LINK_TX_FLUSHED 0x03 -#define I40E_AQ_LINK_FORCED_40G 0x10 - u8 loopback; /* use defines from i40e_aqc_set_lb_mode */ - __le16 max_frame_size; - u8 config; -#define I40E_AQ_CONFIG_CRC_ENA 0x04 -#define I40E_AQ_CONFIG_PACING_MASK 0x78 - u8 reserved[5]; +#define I40E_AQ_LSE_IS_ENABLED 0x1 + u8 phy_type; /* i40e_aq_phy_type */ + u8 link_speed; /* i40e_aq_link_speed */ + u8 link_info; +#define I40E_AQ_LINK_UP 0x01 +#define I40E_AQ_LINK_FAULT 0x02 +#define I40E_AQ_LINK_FAULT_TX 0x04 +#define I40E_AQ_LINK_FAULT_RX 0x08 +#define I40E_AQ_LINK_FAULT_REMOTE 0x10 +#define I40E_AQ_MEDIA_AVAILABLE 0x40 +#define I40E_AQ_SIGNAL_DETECT 0x80 + u8 an_info; +#define I40E_AQ_AN_COMPLETED 0x01 +#define I40E_AQ_LP_AN_ABILITY 0x02 +#define I40E_AQ_PD_FAULT 0x04 +#define I40E_AQ_FEC_EN 0x08 +#define I40E_AQ_PHY_LOW_POWER 0x10 +#define I40E_AQ_LINK_PAUSE_TX 0x20 +#define I40E_AQ_LINK_PAUSE_RX 0x40 +#define I40E_AQ_QUALIFIED_MODULE 0x80 + u8 ext_info; +#define I40E_AQ_LINK_PHY_TEMP_ALARM 0x01 +#define I40E_AQ_LINK_XCESSIVE_ERRORS 0x02 +#define I40E_AQ_LINK_TX_SHIFT 0x02 +#define I40E_AQ_LINK_TX_MASK (0x03 << I40E_AQ_LINK_TX_SHIFT) +#define I40E_AQ_LINK_TX_ACTIVE 0x00 +#define I40E_AQ_LINK_TX_DRAINED 0x01 +#define I40E_AQ_LINK_TX_FLUSHED 0x03 +#define I40E_AQ_LINK_FORCED_40G 0x10 + u8 loopback; /* use defines from i40e_aqc_set_lb_mode */ + __le16 max_frame_size; + u8 config; +#define I40E_AQ_CONFIG_CRC_ENA 0x04 +#define I40E_AQ_CONFIG_PACING_MASK 0x78 + u8 reserved[5]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_get_link_status); /* Set event mask command (direct 0x613) */ struct i40e_aqc_set_phy_int_mask { - u8 reserved[8]; - __le16 event_mask; -#define I40E_AQ_EVENT_LINK_UPDOWN 0x0002 -#define I40E_AQ_EVENT_MEDIA_NA 0x0004 -#define I40E_AQ_EVENT_LINK_FAULT 0x0008 -#define I40E_AQ_EVENT_PHY_TEMP_ALARM 0x0010 -#define I40E_AQ_EVENT_EXCESSIVE_ERRORS 0x0020 -#define I40E_AQ_EVENT_SIGNAL_DETECT 0x0040 -#define I40E_AQ_EVENT_AN_COMPLETED 0x0080 -#define I40E_AQ_EVENT_MODULE_QUAL_FAIL 0x0100 -#define I40E_AQ_EVENT_PORT_TX_SUSPENDED 0x0200 - u8 reserved1[6]; + u8 reserved[8]; + __le16 event_mask; +#define I40E_AQ_EVENT_LINK_UPDOWN 0x0002 +#define I40E_AQ_EVENT_MEDIA_NA 0x0004 +#define I40E_AQ_EVENT_LINK_FAULT 0x0008 +#define I40E_AQ_EVENT_PHY_TEMP_ALARM 0x0010 +#define I40E_AQ_EVENT_EXCESSIVE_ERRORS 0x0020 +#define I40E_AQ_EVENT_SIGNAL_DETECT 0x0040 +#define I40E_AQ_EVENT_AN_COMPLETED 0x0080 +#define I40E_AQ_EVENT_MODULE_QUAL_FAIL 0x0100 +#define I40E_AQ_EVENT_PORT_TX_SUSPENDED 0x0200 + u8 reserved1[6]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_set_phy_int_mask); @@ -1732,27 +1728,27 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_set_phy_int_mask); * Get Link Partner AN advt register (direct 0x0616) */ struct i40e_aqc_an_advt_reg { - __le32 local_an_reg0; - __le16 local_an_reg1; - u8 reserved[10]; + __le32 local_an_reg0; + __le16 local_an_reg1; + u8 reserved[10]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_an_advt_reg); /* Set Loopback mode (0x0618) */ struct i40e_aqc_set_lb_mode { - __le16 lb_mode; -#define I40E_AQ_LB_PHY_LOCAL 0x01 -#define I40E_AQ_LB_PHY_REMOTE 0x02 -#define I40E_AQ_LB_MAC_LOCAL 0x04 - u8 reserved[14]; + __le16 lb_mode; +#define I40E_AQ_LB_PHY_LOCAL 0x01 +#define I40E_AQ_LB_PHY_REMOTE 0x02 +#define I40E_AQ_LB_MAC_LOCAL 0x04 + u8 reserved[14]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_set_lb_mode); /* Set PHY Debug command (0x0622) */ struct i40e_aqc_set_phy_debug { - u8 command_flags; + u8 command_flags; #define I40E_AQ_PHY_DEBUG_RESET_INTERNAL 0x02 #define I40E_AQ_PHY_DEBUG_RESET_EXTERNAL_SHIFT 2 #define I40E_AQ_PHY_DEBUG_RESET_EXTERNAL_MASK (0x03 << \ @@ -1761,15 +1757,15 @@ struct i40e_aqc_set_phy_debug { #define I40E_AQ_PHY_DEBUG_RESET_EXTERNAL_HARD 0x01 #define I40E_AQ_PHY_DEBUG_RESET_EXTERNAL_SOFT 0x02 #define I40E_AQ_PHY_DEBUG_DISABLE_LINK_FW 0x10 - u8 reserved[15]; + u8 reserved[15]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_set_phy_debug); enum i40e_aq_phy_reg_type { - I40E_AQC_PHY_REG_INTERNAL = 0x1, - I40E_AQC_PHY_REG_EXERNAL_BASET = 0x2, - I40E_AQC_PHY_REG_EXERNAL_MODULE = 0x3 + I40E_AQC_PHY_REG_INTERNAL = 0x1, + I40E_AQC_PHY_REG_EXERNAL_BASET = 0x2, + I40E_AQC_PHY_REG_EXERNAL_MODULE = 0x3 }; /* NVM Read command (indirect 0x0701) @@ -1777,40 +1773,40 @@ enum i40e_aq_phy_reg_type { * NVM Update commands (indirect 0x0703) */ struct i40e_aqc_nvm_update { - u8 command_flags; -#define I40E_AQ_NVM_LAST_CMD 0x01 -#define I40E_AQ_NVM_FLASH_ONLY 0x80 - u8 module_pointer; - __le16 length; - __le32 offset; - __le32 addr_high; - __le32 addr_low; + u8 command_flags; +#define I40E_AQ_NVM_LAST_CMD 0x01 +#define I40E_AQ_NVM_FLASH_ONLY 0x80 + u8 module_pointer; + __le16 length; + __le32 offset; + __le32 addr_high; + __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_nvm_update); /* NVM Config Read (indirect 0x0704) */ struct i40e_aqc_nvm_config_read { - __le16 cmd_flags; + __le16 cmd_flags; #define ANVM_SINGLE_OR_MULTIPLE_FEATURES_MASK 1 #define ANVM_READ_SINGLE_FEATURE 0 #define ANVM_READ_MULTIPLE_FEATURES 1 - __le16 element_count; - __le16 element_id; /* Feature/field ID */ - u8 reserved[2]; - __le32 address_high; - __le32 address_low; + __le16 element_count; + __le16 element_id; /* Feature/field ID */ + u8 reserved[2]; + __le32 address_high; + __le32 address_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_nvm_config_read); /* NVM Config Write (indirect 0x0705) */ struct i40e_aqc_nvm_config_write { - __le16 cmd_flags; - __le16 element_count; - u8 reserved[4]; - __le32 address_high; - __le32 address_low; + __le16 cmd_flags; + __le16 element_count; + u8 reserved[4]; + __le32 address_high; + __le32 address_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_nvm_config_write); @@ -1835,10 +1831,10 @@ struct i40e_aqc_nvm_config_data_immediate_field { * Send to Peer PF command (indirect 0x0803) */ struct i40e_aqc_pf_vf_message { - __le32 id; - u8 reserved[4]; - __le32 addr_high; - __le32 addr_low; + __le32 id; + u8 reserved[4]; + __le32 addr_high; + __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_pf_vf_message); @@ -1874,22 +1870,22 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_alternate_ind_write); * uses i40e_aq_desc */ struct i40e_aqc_alternate_write_done { - __le16 cmd_flags; + __le16 cmd_flags; #define I40E_AQ_ALTERNATE_MODE_BIOS_MASK 1 #define I40E_AQ_ALTERNATE_MODE_BIOS_LEGACY 0 #define I40E_AQ_ALTERNATE_MODE_BIOS_UEFI 1 #define I40E_AQ_ALTERNATE_RESET_NEEDED 2 - u8 reserved[14]; + u8 reserved[14]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_alternate_write_done); /* Set OEM mode (direct 0x0905) */ struct i40e_aqc_alternate_set_mode { - __le32 mode; + __le32 mode; #define I40E_AQ_ALTERNATE_MODE_NONE 0 #define I40E_AQ_ALTERNATE_MODE_OEM 1 - u8 reserved[12]; + u8 reserved[12]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_alternate_set_mode); @@ -1900,33 +1896,33 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_alternate_set_mode); /* Lan Queue Overflow Event (direct, 0x1001) */ struct i40e_aqc_lan_overflow { - __le32 prtdcb_rupto; - __le32 otx_ctl; - u8 reserved[8]; + __le32 prtdcb_rupto; + __le32 otx_ctl; + u8 reserved[8]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_lan_overflow); /* Get LLDP MIB (indirect 0x0A00) */ struct i40e_aqc_lldp_get_mib { - u8 type; - u8 reserved1; -#define I40E_AQ_LLDP_MIB_TYPE_MASK 0x3 -#define I40E_AQ_LLDP_MIB_LOCAL 0x0 -#define I40E_AQ_LLDP_MIB_REMOTE 0x1 -#define I40E_AQ_LLDP_MIB_LOCAL_AND_REMOTE 0x2 -#define I40E_AQ_LLDP_BRIDGE_TYPE_MASK 0xC -#define I40E_AQ_LLDP_BRIDGE_TYPE_SHIFT 0x2 -#define I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE 0x0 -#define I40E_AQ_LLDP_BRIDGE_TYPE_NON_TPMR 0x1 -#define I40E_AQ_LLDP_TX_SHIFT 0x4 -#define I40E_AQ_LLDP_TX_MASK (0x03 << I40E_AQ_LLDP_TX_SHIFT) + u8 type; + u8 reserved1; +#define I40E_AQ_LLDP_MIB_TYPE_MASK 0x3 +#define I40E_AQ_LLDP_MIB_LOCAL 0x0 +#define I40E_AQ_LLDP_MIB_REMOTE 0x1 +#define I40E_AQ_LLDP_MIB_LOCAL_AND_REMOTE 0x2 +#define I40E_AQ_LLDP_BRIDGE_TYPE_MASK 0xC +#define I40E_AQ_LLDP_BRIDGE_TYPE_SHIFT 0x2 +#define I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE 0x0 +#define I40E_AQ_LLDP_BRIDGE_TYPE_NON_TPMR 0x1 +#define I40E_AQ_LLDP_TX_SHIFT 0x4 +#define I40E_AQ_LLDP_TX_MASK (0x03 << I40E_AQ_LLDP_TX_SHIFT) /* TX pause flags use I40E_AQ_LINK_TX_* above */ - __le16 local_len; - __le16 remote_len; - u8 reserved2[2]; - __le32 addr_high; - __le32 addr_low; + __le16 local_len; + __le16 remote_len; + u8 reserved2[2]; + __le32 addr_high; + __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_get_mib); @@ -1935,12 +1931,12 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_get_mib); * also used for the event (with type in the command field) */ struct i40e_aqc_lldp_update_mib { - u8 command; -#define I40E_AQ_LLDP_MIB_UPDATE_ENABLE 0x0 -#define I40E_AQ_LLDP_MIB_UPDATE_DISABLE 0x1 - u8 reserved[7]; - __le32 addr_high; - __le32 addr_low; + u8 command; +#define I40E_AQ_LLDP_MIB_UPDATE_ENABLE 0x0 +#define I40E_AQ_LLDP_MIB_UPDATE_DISABLE 0x1 + u8 reserved[7]; + __le32 addr_high; + __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_update_mib); @@ -1949,35 +1945,35 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_update_mib); * Delete LLDP TLV (indirect 0x0A04) */ struct i40e_aqc_lldp_add_tlv { - u8 type; /* only nearest bridge and non-TPMR from 0x0A00 */ - u8 reserved1[1]; - __le16 len; - u8 reserved2[4]; - __le32 addr_high; - __le32 addr_low; + u8 type; /* only nearest bridge and non-TPMR from 0x0A00 */ + u8 reserved1[1]; + __le16 len; + u8 reserved2[4]; + __le32 addr_high; + __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_add_tlv); /* Update LLDP TLV (indirect 0x0A03) */ struct i40e_aqc_lldp_update_tlv { - u8 type; /* only nearest bridge and non-TPMR from 0x0A00 */ - u8 reserved; - __le16 old_len; - __le16 new_offset; - __le16 new_len; - __le32 addr_high; - __le32 addr_low; + u8 type; /* only nearest bridge and non-TPMR from 0x0A00 */ + u8 reserved; + __le16 old_len; + __le16 new_offset; + __le16 new_len; + __le32 addr_high; + __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_update_tlv); /* Stop LLDP (direct 0x0A05) */ struct i40e_aqc_lldp_stop { - u8 command; -#define I40E_AQ_LLDP_AGENT_STOP 0x0 -#define I40E_AQ_LLDP_AGENT_SHUTDOWN 0x1 - u8 reserved[15]; + u8 command; +#define I40E_AQ_LLDP_AGENT_STOP 0x0 +#define I40E_AQ_LLDP_AGENT_SHUTDOWN 0x1 + u8 reserved[15]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_stop); @@ -1985,9 +1981,9 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_stop); /* Start LLDP (direct 0x0A06) */ struct i40e_aqc_lldp_start { - u8 command; -#define I40E_AQ_LLDP_AGENT_START 0x1 - u8 reserved[15]; + u8 command; +#define I40E_AQ_LLDP_AGENT_START 0x1 + u8 reserved[15]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_start); @@ -1998,13 +1994,13 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_start); /* Add Udp Tunnel command and completion (direct 0x0B00) */ struct i40e_aqc_add_udp_tunnel { - __le16 udp_port; - u8 reserved0[3]; - u8 protocol_type; + __le16 udp_port; + u8 reserved0[3]; + u8 protocol_type; #define I40E_AQC_TUNNEL_TYPE_VXLAN 0x00 #define I40E_AQC_TUNNEL_TYPE_NGE 0x01 #define I40E_AQC_TUNNEL_TYPE_TEREDO 0x10 - u8 reserved1[10]; + u8 reserved1[10]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_udp_tunnel); @@ -2013,8 +2009,8 @@ struct i40e_aqc_add_udp_tunnel_completion { __le16 udp_port; u8 filter_entry_index; u8 multiple_pfs; -#define I40E_AQC_SINGLE_PF 0x0 -#define I40E_AQC_MULTIPLE_PFS 0x1 +#define I40E_AQC_SINGLE_PF 0x0 +#define I40E_AQC_MULTIPLE_PFS 0x1 u8 total_filters; u8 reserved[11]; }; @@ -2023,23 +2019,19 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_add_udp_tunnel_completion); /* remove UDP Tunnel command (0x0B01) */ struct i40e_aqc_remove_udp_tunnel { - u8 reserved[2]; - u8 index; /* 0 to 15 */ - u8 pf_filters; - u8 total_filters; - u8 reserved2[11]; + u8 reserved[2]; + u8 index; /* 0 to 15 */ + u8 reserved2[13]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_remove_udp_tunnel); struct i40e_aqc_del_udp_tunnel_completion { - __le16 udp_port; - u8 index; /* 0 to 15 */ - u8 multiple_pfs; - u8 total_filters_used; - u8 reserved; - u8 tunnels_free; - u8 reserved1[9]; + __le16 udp_port; + u8 index; /* 0 to 15 */ + u8 multiple_pfs; + u8 total_filters_used; + u8 reserved1[11]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_del_udp_tunnel_completion); @@ -2068,11 +2060,11 @@ struct i40e_aqc_tunnel_key_structure { u8 key1_len; /* 0 to 15 */ u8 key2_len; /* 0 to 15 */ u8 flags; -#define I40E_AQC_TUNNEL_KEY_STRUCT_OVERRIDE 0x01 +#define I40E_AQC_TUNNEL_KEY_STRUCT_OVERRIDE 0x01 /* response flags */ -#define I40E_AQC_TUNNEL_KEY_STRUCT_SUCCESS 0x01 -#define I40E_AQC_TUNNEL_KEY_STRUCT_MODIFIED 0x02 -#define I40E_AQC_TUNNEL_KEY_STRUCT_OVERRIDDEN 0x03 +#define I40E_AQC_TUNNEL_KEY_STRUCT_SUCCESS 0x01 +#define I40E_AQC_TUNNEL_KEY_STRUCT_MODIFIED 0x02 +#define I40E_AQC_TUNNEL_KEY_STRUCT_OVERRIDDEN 0x03 u8 network_key_index; #define I40E_AQC_NETWORK_KEY_INDEX_VXLAN 0x0 #define I40E_AQC_NETWORK_KEY_INDEX_NGE 0x1 @@ -2085,21 +2077,21 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_tunnel_key_structure); /* OEM mode commands (direct 0xFE0x) */ struct i40e_aqc_oem_param_change { - __le32 param_type; -#define I40E_AQ_OEM_PARAM_TYPE_PF_CTL 0 -#define I40E_AQ_OEM_PARAM_TYPE_BW_CTL 1 -#define I40E_AQ_OEM_PARAM_MAC 2 - __le32 param_value1; - u8 param_value2[8]; + __le32 param_type; +#define I40E_AQ_OEM_PARAM_TYPE_PF_CTL 0 +#define I40E_AQ_OEM_PARAM_TYPE_BW_CTL 1 +#define I40E_AQ_OEM_PARAM_MAC 2 + __le32 param_value1; + u8 param_value2[8]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_oem_param_change); struct i40e_aqc_oem_state_change { - __le32 state; -#define I40E_AQ_OEM_STATE_LINK_DOWN 0x0 -#define I40E_AQ_OEM_STATE_LINK_UP 0x1 - u8 reserved[12]; + __le32 state; +#define I40E_AQ_OEM_STATE_LINK_DOWN 0x0 +#define I40E_AQ_OEM_STATE_LINK_UP 0x1 + u8 reserved[12]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_oem_state_change); @@ -2111,18 +2103,18 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_oem_state_change); /* set test more (0xFF01, internal) */ struct i40e_acq_set_test_mode { - u8 mode; -#define I40E_AQ_TEST_PARTIAL 0 -#define I40E_AQ_TEST_FULL 1 -#define I40E_AQ_TEST_NVM 2 - u8 reserved[3]; - u8 command; -#define I40E_AQ_TEST_OPEN 0 -#define I40E_AQ_TEST_CLOSE 1 -#define I40E_AQ_TEST_INC 2 - u8 reserved2[3]; - __le32 address_high; - __le32 address_low; + u8 mode; +#define I40E_AQ_TEST_PARTIAL 0 +#define I40E_AQ_TEST_FULL 1 +#define I40E_AQ_TEST_NVM 2 + u8 reserved[3]; + u8 command; +#define I40E_AQ_TEST_OPEN 0 +#define I40E_AQ_TEST_CLOSE 1 +#define I40E_AQ_TEST_INC 2 + u8 reserved2[3]; + __le32 address_high; + __le32 address_low; }; I40E_CHECK_CMD_LENGTH(i40e_acq_set_test_mode); @@ -2175,21 +2167,21 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_debug_modify_reg); #define I40E_AQ_CLUSTER_ID_ALTRAM 11 struct i40e_aqc_debug_dump_internals { - u8 cluster_id; - u8 table_id; - __le16 data_size; - __le32 idx; - __le32 address_high; - __le32 address_low; + u8 cluster_id; + u8 table_id; + __le16 data_size; + __le32 idx; + __le32 address_high; + __le32 address_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_debug_dump_internals); struct i40e_aqc_debug_modify_internals { - u8 cluster_id; - u8 cluster_specific_params[7]; - __le32 address_high; - __le32 address_low; + u8 cluster_id; + u8 cluster_specific_params[7]; + __le32 address_high; + __le32 address_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_debug_modify_internals); diff --git a/drivers/net/ethernet/intel/i40evf/i40e_common.c b/drivers/net/ethernet/intel/i40evf/i40e_common.c index 952560551964..28c40c57d4f5 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_common.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_common.c @@ -50,6 +50,7 @@ i40e_status i40e_set_mac_type(struct i40e_hw *hw) case I40E_DEV_ID_QSFP_A: case I40E_DEV_ID_QSFP_B: case I40E_DEV_ID_QSFP_C: + case I40E_DEV_ID_10G_BASE_T: hw->mac.type = I40E_MAC_XL710; break; case I40E_DEV_ID_VF: diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h index f6dcf9dd9290..c7f29626eada 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h @@ -30,10 +30,7 @@ /* Interrupt Throttling and Rate Limiting Goodies */ #define I40E_MAX_ITR 0x0FF0 /* reg uses 2 usec resolution */ -#define I40E_MIN_ITR 0x0004 /* reg uses 2 usec resolution */ -#define I40E_MAX_IRATE 0x03F -#define I40E_MIN_IRATE 0x001 -#define I40E_IRATE_USEC_RESOLUTION 4 +#define I40E_MIN_ITR 0x0001 /* reg uses 2 usec resolution */ #define I40E_ITR_100K 0x0005 #define I40E_ITR_20K 0x0019 #define I40E_ITR_8K 0x003E diff --git a/drivers/net/ethernet/intel/i40evf/i40e_type.h b/drivers/net/ethernet/intel/i40evf/i40e_type.h index 15376436cead..8fe34fc5c469 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_type.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_type.h @@ -43,6 +43,7 @@ #define I40E_DEV_ID_QSFP_A 0x1583 #define I40E_DEV_ID_QSFP_B 0x1584 #define I40E_DEV_ID_QSFP_C 0x1585 +#define I40E_DEV_ID_10G_BASE_T 0x1586 #define I40E_DEV_ID_VF 0x154C #define I40E_DEV_ID_VF_HV 0x1571 diff --git a/drivers/net/ethernet/intel/i40evf/i40evf.h b/drivers/net/ethernet/intel/i40evf/i40evf.h index 30ef519d4b91..981224743c73 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf.h +++ b/drivers/net/ethernet/intel/i40evf/i40evf.h @@ -191,6 +191,7 @@ struct i40evf_adapter { struct i40e_q_vector *q_vector[MAX_MSIX_Q_VECTORS]; struct list_head vlan_filter_list; char misc_vector_name[IFNAMSIZ + 9]; + int num_active_queues; /* TX */ struct i40e_ring *tx_rings[I40E_MAX_VSI_QP]; @@ -243,7 +244,7 @@ struct i40evf_adapter { struct i40e_hw hw; /* defined in i40e_type.h */ enum i40evf_state_t state; - volatile unsigned long crit_section; + unsigned long crit_section; struct work_struct watchdog_task; bool netdev_registered; diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c index efee6b290c0f..69a269b23be6 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c @@ -58,8 +58,8 @@ static const struct i40evf_stats i40evf_gstrings_stats[] = { #define I40EVF_GLOBAL_STATS_LEN ARRAY_SIZE(i40evf_gstrings_stats) #define I40EVF_QUEUE_STATS_LEN(_dev) \ - (((struct i40evf_adapter *) \ - netdev_priv(_dev))->vsi_res->num_queue_pairs \ + (((struct i40evf_adapter *)\ + netdev_priv(_dev))->num_active_queues \ * 2 * (sizeof(struct i40e_queue_stats) / sizeof(u64))) #define I40EVF_STATS_LEN(_dev) \ (I40EVF_GLOBAL_STATS_LEN + I40EVF_QUEUE_STATS_LEN(_dev)) @@ -121,11 +121,11 @@ static void i40evf_get_ethtool_stats(struct net_device *netdev, p = (char *)adapter + i40evf_gstrings_stats[i].stat_offset; data[i] = *(u64 *)p; } - for (j = 0; j < adapter->vsi_res->num_queue_pairs; j++) { + for (j = 0; j < adapter->num_active_queues; j++) { data[i++] = adapter->tx_rings[j]->stats.packets; data[i++] = adapter->tx_rings[j]->stats.bytes; } - for (j = 0; j < adapter->vsi_res->num_queue_pairs; j++) { + for (j = 0; j < adapter->num_active_queues; j++) { data[i++] = adapter->rx_rings[j]->stats.packets; data[i++] = adapter->rx_rings[j]->stats.bytes; } @@ -151,13 +151,13 @@ static void i40evf_get_strings(struct net_device *netdev, u32 sset, u8 *data) ETH_GSTRING_LEN); p += ETH_GSTRING_LEN; } - for (i = 0; i < adapter->vsi_res->num_queue_pairs; i++) { + for (i = 0; i < adapter->num_active_queues; i++) { snprintf(p, ETH_GSTRING_LEN, "tx-%u.packets", i); p += ETH_GSTRING_LEN; snprintf(p, ETH_GSTRING_LEN, "tx-%u.bytes", i); p += ETH_GSTRING_LEN; } - for (i = 0; i < adapter->vsi_res->num_queue_pairs; i++) { + for (i = 0; i < adapter->num_active_queues; i++) { snprintf(p, ETH_GSTRING_LEN, "rx-%u.packets", i); p += ETH_GSTRING_LEN; snprintf(p, ETH_GSTRING_LEN, "rx-%u.bytes", i); @@ -175,6 +175,7 @@ static void i40evf_get_strings(struct net_device *netdev, u32 sset, u8 *data) static u32 i40evf_get_msglevel(struct net_device *netdev) { struct i40evf_adapter *adapter = netdev_priv(netdev); + return adapter->msg_enable; } @@ -189,6 +190,7 @@ static u32 i40evf_get_msglevel(struct net_device *netdev) static void i40evf_set_msglevel(struct net_device *netdev, u32 data) { struct i40evf_adapter *adapter = netdev_priv(netdev); + adapter->msg_enable = data; } @@ -219,7 +221,7 @@ static void i40evf_get_drvinfo(struct net_device *netdev, * but the number of rings is not reported. **/ static void i40evf_get_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) + struct ethtool_ringparam *ring) { struct i40evf_adapter *adapter = netdev_priv(netdev); @@ -280,7 +282,7 @@ static int i40evf_set_ringparam(struct net_device *netdev, * this functionality. **/ static int i40evf_get_coalesce(struct net_device *netdev, - struct ethtool_coalesce *ec) + struct ethtool_coalesce *ec) { struct i40evf_adapter *adapter = netdev_priv(netdev); struct i40e_vsi *vsi = &adapter->vsi; @@ -308,7 +310,7 @@ static int i40evf_get_coalesce(struct net_device *netdev, * Change current coalescing settings. **/ static int i40evf_set_coalesce(struct net_device *netdev, - struct ethtool_coalesce *ec) + struct ethtool_coalesce *ec) { struct i40evf_adapter *adapter = netdev_priv(netdev); struct i40e_hw *hw = &adapter->hw; @@ -430,7 +432,7 @@ static int i40evf_get_rxnfc(struct net_device *netdev, switch (cmd->cmd) { case ETHTOOL_GRXRINGS: - cmd->data = adapter->vsi_res->num_queue_pairs; + cmd->data = adapter->num_active_queues; ret = 0; break; case ETHTOOL_GRXFH: @@ -598,12 +600,12 @@ static void i40evf_get_channels(struct net_device *netdev, struct i40evf_adapter *adapter = netdev_priv(netdev); /* Report maximum channels */ - ch->max_combined = adapter->vsi_res->num_queue_pairs; + ch->max_combined = adapter->num_active_queues; ch->max_other = NONQ_VECS; ch->other_count = NONQ_VECS; - ch->combined_count = adapter->vsi_res->num_queue_pairs; + ch->combined_count = adapter->num_active_queues; } /** @@ -621,7 +623,7 @@ static u32 i40evf_get_rxfh_indir_size(struct net_device *netdev) * i40evf_get_rxfh - get the rx flow hash indirection table * @netdev: network interface device structure * @indir: indirection table - * @key: hash key (will be %NULL until get_rxfh_key_size is implemented) + * @key: hash key * * Reads the indirection table directly from the hardware. Always returns 0. **/ @@ -646,7 +648,7 @@ static int i40evf_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key) * i40evf_set_rxfh - set the rx flow hash indirection table * @netdev: network interface device structure * @indir: indirection table - * @key: hash key (will be %NULL until get_rxfh_key_size is implemented) + * @key: hash key * * Returns -EINVAL if the table specifies an inavlid queue id, otherwise * returns 0 after programming the table. diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index c51bc7a33bc5..8e01009695da 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -185,6 +185,7 @@ static void i40evf_tx_timeout(struct net_device *netdev) static void i40evf_misc_irq_disable(struct i40evf_adapter *adapter) { struct i40e_hw *hw = &adapter->hw; + wr32(hw, I40E_VFINT_DYN_CTL01, 0); /* read flush */ @@ -200,6 +201,7 @@ static void i40evf_misc_irq_disable(struct i40evf_adapter *adapter) static void i40evf_misc_irq_enable(struct i40evf_adapter *adapter) { struct i40e_hw *hw = &adapter->hw; + wr32(hw, I40E_VFINT_DYN_CTL01, I40E_VFINT_DYN_CTL01_INTENA_MASK | I40E_VFINT_DYN_CTL01_ITR_INDX_MASK); wr32(hw, I40E_VFINT_ICR0_ENA1, I40E_VFINT_ICR0_ENA_ADMINQ_MASK); @@ -226,7 +228,6 @@ static void i40evf_irq_disable(struct i40evf_adapter *adapter) } /* read flush */ rd32(hw, I40E_VFGEN_RSTAT); - } /** @@ -253,8 +254,7 @@ void i40evf_irq_enable_queues(struct i40evf_adapter *adapter, u32 mask) * @adapter: board private structure * @mask: bitmap of vectors to trigger **/ -static void i40evf_fire_sw_int(struct i40evf_adapter *adapter, - u32 mask) +static void i40evf_fire_sw_int(struct i40evf_adapter *adapter, u32 mask) { struct i40e_hw *hw = &adapter->hw; int i; @@ -397,8 +397,8 @@ static int i40evf_map_rings_to_vectors(struct i40evf_adapter *adapter) int q_vectors; int v_start = 0; int rxr_idx = 0, txr_idx = 0; - int rxr_remaining = adapter->vsi_res->num_queue_pairs; - int txr_remaining = adapter->vsi_res->num_queue_pairs; + int rxr_remaining = adapter->num_active_queues; + int txr_remaining = adapter->num_active_queues; int i, j; int rqpv, tqpv; int err = 0; @@ -551,6 +551,7 @@ static void i40evf_free_traffic_irqs(struct i40evf_adapter *adapter) { int i; int q_vectors; + q_vectors = adapter->num_msix_vectors - NONQ_VECS; for (i = 0; i < q_vectors; i++) { @@ -584,7 +585,8 @@ static void i40evf_configure_tx(struct i40evf_adapter *adapter) { struct i40e_hw *hw = &adapter->hw; int i; - for (i = 0; i < adapter->vsi_res->num_queue_pairs; i++) + + for (i = 0; i < adapter->num_active_queues; i++) adapter->tx_rings[i]->tail = hw->hw_addr + I40E_QTX_TAIL1(i); } @@ -629,7 +631,7 @@ static void i40evf_configure_rx(struct i40evf_adapter *adapter) rx_buf_len = ALIGN(max_frame, 1024); } - for (i = 0; i < adapter->vsi_res->num_queue_pairs; i++) { + for (i = 0; i < adapter->num_active_queues; i++) { adapter->rx_rings[i]->tail = hw->hw_addr + I40E_QRX_TAIL1(i); adapter->rx_rings[i]->rx_buf_len = rx_buf_len; } @@ -667,9 +669,9 @@ i40evf_vlan_filter *i40evf_add_vlan(struct i40evf_adapter *adapter, u16 vlan) struct i40evf_vlan_filter *f; f = i40evf_find_vlan(adapter, vlan); - if (NULL == f) { + if (!f) { f = kzalloc(sizeof(*f), GFP_ATOMIC); - if (NULL == f) + if (!f) return NULL; f->vlan = vlan; @@ -705,7 +707,7 @@ static void i40evf_del_vlan(struct i40evf_adapter *adapter, u16 vlan) * @vid: VLAN tag **/ static int i40evf_vlan_rx_add_vid(struct net_device *netdev, - __always_unused __be16 proto, u16 vid) + __always_unused __be16 proto, u16 vid) { struct i40evf_adapter *adapter = netdev_priv(netdev); @@ -720,7 +722,7 @@ static int i40evf_vlan_rx_add_vid(struct net_device *netdev, * @vid: VLAN tag **/ static int i40evf_vlan_rx_kill_vid(struct net_device *netdev, - __always_unused __be16 proto, u16 vid) + __always_unused __be16 proto, u16 vid) { struct i40evf_adapter *adapter = netdev_priv(netdev); @@ -772,9 +774,9 @@ i40evf_mac_filter *i40evf_add_filter(struct i40evf_adapter *adapter, udelay(1); f = i40evf_find_filter(adapter, macaddr); - if (NULL == f) { + if (!f) { f = kzalloc(sizeof(*f), GFP_ATOMIC); - if (NULL == f) { + if (!f) { clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section); return NULL; @@ -881,6 +883,7 @@ static void i40evf_napi_enable_all(struct i40evf_adapter *adapter) for (q_idx = 0; q_idx < q_vectors; q_idx++) { struct napi_struct *napi; + q_vector = adapter->q_vector[q_idx]; napi = &q_vector->napi; napi_enable(napi); @@ -918,8 +921,9 @@ static void i40evf_configure(struct i40evf_adapter *adapter) i40evf_configure_rx(adapter); adapter->aq_required |= I40EVF_FLAG_AQ_CONFIGURE_QUEUES; - for (i = 0; i < adapter->vsi_res->num_queue_pairs; i++) { + for (i = 0; i < adapter->num_active_queues; i++) { struct i40e_ring *ring = adapter->rx_rings[i]; + i40evf_alloc_rx_buffers(ring, ring->count); ring->next_to_use = ring->count - 1; writel(ring->next_to_use, ring->tail); @@ -950,7 +954,7 @@ static void i40evf_clean_all_rx_rings(struct i40evf_adapter *adapter) { int i; - for (i = 0; i < adapter->vsi_res->num_queue_pairs; i++) + for (i = 0; i < adapter->num_active_queues; i++) i40evf_clean_rx_ring(adapter->rx_rings[i]); } @@ -962,7 +966,7 @@ static void i40evf_clean_all_tx_rings(struct i40evf_adapter *adapter) { int i; - for (i = 0; i < adapter->vsi_res->num_queue_pairs; i++) + for (i = 0; i < adapter->num_active_queues; i++) i40evf_clean_tx_ring(adapter->tx_rings[i]); } @@ -1064,7 +1068,7 @@ static void i40evf_free_queues(struct i40evf_adapter *adapter) if (!adapter->vsi_res) return; - for (i = 0; i < adapter->vsi_res->num_queue_pairs; i++) { + for (i = 0; i < adapter->num_active_queues; i++) { if (adapter->tx_rings[i]) kfree_rcu(adapter->tx_rings[i], rcu); adapter->tx_rings[i] = NULL; @@ -1084,11 +1088,11 @@ static int i40evf_alloc_queues(struct i40evf_adapter *adapter) { int i; - for (i = 0; i < adapter->vsi_res->num_queue_pairs; i++) { + for (i = 0; i < adapter->num_active_queues; i++) { struct i40e_ring *tx_ring; struct i40e_ring *rx_ring; - tx_ring = kzalloc(sizeof(struct i40e_ring) * 2, GFP_KERNEL); + tx_ring = kzalloc(sizeof(*tx_ring) * 2, GFP_KERNEL); if (!tx_ring) goto err_out; @@ -1130,7 +1134,7 @@ static int i40evf_set_interrupt_capability(struct i40evf_adapter *adapter) err = -EIO; goto out; } - pairs = adapter->vsi_res->num_queue_pairs; + pairs = adapter->num_active_queues; /* It's easy to be greedy for MSI-X vectors, but it really * doesn't do us much good if we have a lot more vectors @@ -1172,14 +1176,14 @@ static int i40evf_alloc_q_vectors(struct i40evf_adapter *adapter) num_q_vectors = adapter->num_msix_vectors - NONQ_VECS; for (q_idx = 0; q_idx < num_q_vectors; q_idx++) { - q_vector = kzalloc(sizeof(struct i40e_q_vector), GFP_KERNEL); + q_vector = kzalloc(sizeof(*q_vector), GFP_KERNEL); if (!q_vector) goto err_out; q_vector->adapter = adapter; q_vector->vsi = &adapter->vsi; q_vector->v_idx = q_idx; netif_napi_add(adapter->netdev, &q_vector->napi, - i40evf_napi_poll, NAPI_POLL_WEIGHT); + i40evf_napi_poll, NAPI_POLL_WEIGHT); adapter->q_vector[q_idx] = q_vector; } @@ -1210,7 +1214,7 @@ static void i40evf_free_q_vectors(struct i40evf_adapter *adapter) int napi_vectors; num_q_vectors = adapter->num_msix_vectors - NONQ_VECS; - napi_vectors = adapter->vsi_res->num_queue_pairs; + napi_vectors = adapter->num_active_queues; for (q_idx = 0; q_idx < num_q_vectors; q_idx++) { struct i40e_q_vector *q_vector = adapter->q_vector[q_idx]; @@ -1265,8 +1269,8 @@ int i40evf_init_interrupt_scheme(struct i40evf_adapter *adapter) } dev_info(&adapter->pdev->dev, "Multiqueue %s: Queue pair count = %u", - (adapter->vsi_res->num_queue_pairs > 1) ? "Enabled" : - "Disabled", adapter->vsi_res->num_queue_pairs); + (adapter->num_active_queues > 1) ? "Enabled" : "Disabled", + adapter->num_active_queues); return 0; err_alloc_queues: @@ -1284,6 +1288,7 @@ err_set_interrupt: static void i40evf_watchdog_timer(unsigned long data) { struct i40evf_adapter *adapter = (struct i40evf_adapter *)data; + schedule_work(&adapter->watchdog_task); /* timer will be rescheduled in watchdog task */ } @@ -1295,8 +1300,8 @@ static void i40evf_watchdog_timer(unsigned long data) static void i40evf_watchdog_task(struct work_struct *work) { struct i40evf_adapter *adapter = container_of(work, - struct i40evf_adapter, - watchdog_task); + struct i40evf_adapter, + watchdog_task); struct i40e_hw *hw = &adapter->hw; uint32_t rstat_val; @@ -1334,7 +1339,7 @@ static void i40evf_watchdog_task(struct work_struct *work) /* check for reset */ rstat_val = rd32(hw, I40E_VFGEN_RSTAT) & - I40E_VFGEN_RSTAT_VFR_STATE_MASK; + I40E_VFGEN_RSTAT_VFR_STATE_MASK; if (!(adapter->flags & I40EVF_FLAG_RESET_PENDING) && (rstat_val != I40E_VFR_VFACTIVE) && (rstat_val != I40E_VFR_COMPLETED)) { @@ -1425,7 +1430,7 @@ static int next_queue(struct i40evf_adapter *adapter, int j) { j += 1; - return j >= adapter->vsi_res->num_queue_pairs ? 0 : j; + return j >= adapter->num_active_queues ? 0 : j; } /** @@ -1434,23 +1439,23 @@ static int next_queue(struct i40evf_adapter *adapter, int j) **/ static void i40evf_configure_rss(struct i40evf_adapter *adapter) { + u32 rss_key[I40E_VFQF_HKEY_MAX_INDEX + 1]; struct i40e_hw *hw = &adapter->hw; u32 lut = 0; int i, j; u64 hena; - /* Set of random keys generated using kernel random number generator */ - static const u32 seed[I40E_VFQF_HKEY_MAX_INDEX + 1] = { - 0x794221b4, 0xbca0c5ab, 0x6cd5ebd9, 0x1ada6127, - 0x983b3aa1, 0x1c4e71eb, 0x7f6328b2, 0xfcdc0da0, - 0xc135cafa, 0x7a6f7e2d, 0xe7102d28, 0x163cd12e, - 0x4954b126 }; + /* No RSS for single queue. */ + if (adapter->num_active_queues == 1) { + wr32(hw, I40E_VFQF_HENA(0), 0); + wr32(hw, I40E_VFQF_HENA(1), 0); + return; + } /* Hash type is configured by the PF - we just supply the key */ - - /* Fill out hash function seed */ + netdev_rss_key_fill(rss_key, sizeof(rss_key)); for (i = 0; i <= I40E_VFQF_HKEY_MAX_INDEX; i++) - wr32(hw, I40E_VFQF_HKEY(i), seed[i]); + wr32(hw, I40E_VFQF_HKEY(i), rss_key[i]); /* Enable PCTYPES for RSS, TCP/UDP with IPv4/IPv6 */ hena = I40E_DEFAULT_RSS_HENA; @@ -1458,7 +1463,7 @@ static void i40evf_configure_rss(struct i40evf_adapter *adapter) wr32(hw, I40E_VFQF_HENA(1), (u32)(hena >> 32)); /* Populate the LUT with max no. of queues in round robin fashion */ - j = adapter->vsi_res->num_queue_pairs; + j = adapter->num_active_queues; for (i = 0; i <= I40E_VFQF_HLUT_MAX_INDEX; i++) { j = next_queue(adapter, j); lut = j; @@ -1494,7 +1499,7 @@ static void i40evf_reset_task(struct work_struct *work) while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section)) - udelay(500); + usleep_range(500, 1000); if (adapter->flags & I40EVF_FLAG_RESET_NEEDED) { dev_info(&adapter->pdev->dev, "Requesting reset from PF\n"); @@ -1508,8 +1513,7 @@ static void i40evf_reset_task(struct work_struct *work) if ((rstat_val != I40E_VFR_VFACTIVE) && (rstat_val != I40E_VFR_COMPLETED)) break; - else - msleep(I40EVF_RESET_WAIT_MS); + msleep(I40EVF_RESET_WAIT_MS); } if (i == I40EVF_RESET_WAIT_COUNT) { adapter->flags &= ~I40EVF_FLAG_RESET_PENDING; @@ -1523,8 +1527,7 @@ static void i40evf_reset_task(struct work_struct *work) if ((rstat_val == I40E_VFR_VFACTIVE) || (rstat_val == I40E_VFR_COMPLETED)) break; - else - msleep(I40EVF_RESET_WAIT_MS); + msleep(I40EVF_RESET_WAIT_MS); } if (i == I40EVF_RESET_WAIT_COUNT) { struct i40evf_mac_filter *f, *ftmp; @@ -1575,12 +1578,12 @@ continue_reset: /* kill and reinit the admin queue */ if (i40evf_shutdown_adminq(hw)) dev_warn(&adapter->pdev->dev, - "%s: Failed to destroy the Admin Queue resources\n", - __func__); + "%s: Failed to destroy the Admin Queue resources\n", + __func__); err = i40evf_init_adminq(hw); if (err) dev_info(&adapter->pdev->dev, "%s: init_adminq failed: %d\n", - __func__, err); + __func__, err); adapter->aq_pending = 0; adapter->aq_required = 0; @@ -1632,8 +1635,8 @@ static void i40evf_adminq_task(struct work_struct *work) if (adapter->flags & I40EVF_FLAG_PF_COMMS_FAILED) return; - event.msg_size = I40EVF_MAX_AQ_BUF_SIZE; - event.msg_buf = kzalloc(event.msg_size, GFP_KERNEL); + event.buf_len = I40EVF_MAX_AQ_BUF_SIZE; + event.msg_buf = kzalloc(event.buf_len, GFP_KERNEL); if (!event.msg_buf) return; @@ -1645,13 +1648,9 @@ static void i40evf_adminq_task(struct work_struct *work) i40evf_virtchnl_completion(adapter, v_msg->v_opcode, v_msg->v_retval, event.msg_buf, - event.msg_size); - if (pending != 0) { - dev_info(&adapter->pdev->dev, - "%s: ARQ: Pending events %d\n", - __func__, pending); + event.msg_len); + if (pending != 0) memset(event.msg_buf, 0, I40EVF_MAX_AQ_BUF_SIZE); - } } while (pending); /* check for error indications */ @@ -1705,10 +1704,9 @@ static void i40evf_free_all_tx_resources(struct i40evf_adapter *adapter) { int i; - for (i = 0; i < adapter->vsi_res->num_queue_pairs; i++) + for (i = 0; i < adapter->num_active_queues; i++) if (adapter->tx_rings[i]->desc) i40evf_free_tx_resources(adapter->tx_rings[i]); - } /** @@ -1725,7 +1723,7 @@ static int i40evf_setup_all_tx_resources(struct i40evf_adapter *adapter) { int i, err = 0; - for (i = 0; i < adapter->vsi_res->num_queue_pairs; i++) { + for (i = 0; i < adapter->num_active_queues; i++) { adapter->tx_rings[i]->count = adapter->tx_desc_count; err = i40evf_setup_tx_descriptors(adapter->tx_rings[i]); if (!err) @@ -1753,7 +1751,7 @@ static int i40evf_setup_all_rx_resources(struct i40evf_adapter *adapter) { int i, err = 0; - for (i = 0; i < adapter->vsi_res->num_queue_pairs; i++) { + for (i = 0; i < adapter->num_active_queues; i++) { adapter->rx_rings[i]->count = adapter->rx_desc_count; err = i40evf_setup_rx_descriptors(adapter->rx_rings[i]); if (!err) @@ -1776,7 +1774,7 @@ static void i40evf_free_all_rx_resources(struct i40evf_adapter *adapter) { int i; - for (i = 0; i < adapter->vsi_res->num_queue_pairs; i++) + for (i = 0; i < adapter->num_active_queues; i++) if (adapter->rx_rings[i]->desc) i40evf_free_rx_resources(adapter->rx_rings[i]); } @@ -1980,7 +1978,7 @@ static int i40evf_check_reset_complete(struct i40e_hw *hw) if ((rstat == I40E_VFR_VFACTIVE) || (rstat == I40E_VFR_COMPLETED)) return 0; - udelay(10); + usleep_range(10, 20); } return -EBUSY; } @@ -2022,7 +2020,7 @@ static void i40evf_init_task(struct work_struct *work) err = i40evf_check_reset_complete(hw); if (err) { dev_info(&pdev->dev, "Device is still in reset (%d), retrying\n", - err); + err); goto err; } hw->aq.num_arq_entries = I40EVF_AQ_LEN; @@ -2054,7 +2052,7 @@ static void i40evf_init_task(struct work_struct *work) err = i40evf_verify_api_ver(adapter); if (err) { dev_info(&pdev->dev, "Unable to verify API version (%d), retrying\n", - err); + err); if (err == I40E_ERR_ADMIN_QUEUE_NO_WORK) { dev_info(&pdev->dev, "Resending request\n"); err = i40evf_send_api_ver(adapter); @@ -2138,7 +2136,7 @@ static void i40evf_init_task(struct work_struct *work) ether_addr_copy(netdev->perm_addr, adapter->hw.mac.addr); f = kzalloc(sizeof(*f), GFP_ATOMIC); - if (NULL == f) + if (!f) goto err_sw_init; ether_addr_copy(f->macaddr, adapter->hw.mac.addr); @@ -2152,6 +2150,9 @@ static void i40evf_init_task(struct work_struct *work) adapter->watchdog_timer.data = (unsigned long)adapter; mod_timer(&adapter->watchdog_timer, jiffies + 1); + adapter->num_active_queues = min_t(int, + adapter->vsi_res->num_queue_pairs, + (int)(num_online_cpus())); adapter->tx_desc_count = I40EVF_DEFAULT_TXD; adapter->rx_desc_count = I40EVF_DEFAULT_RXD; err = i40evf_init_interrupt_scheme(adapter); @@ -2500,8 +2501,9 @@ static struct pci_driver i40evf_driver = { static int __init i40evf_init_module(void) { int ret; + pr_info("i40evf: %s - version %s\n", i40evf_driver_string, - i40evf_driver_version); + i40evf_driver_version); pr_info("%s\n", i40evf_copyright); diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c index 66d12f5b4ca8..07c13b039181 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c @@ -89,27 +89,37 @@ int i40evf_verify_api_ver(struct i40evf_adapter *adapter) struct i40e_virtchnl_version_info *pf_vvi; struct i40e_hw *hw = &adapter->hw; struct i40e_arq_event_info event; + enum i40e_virtchnl_ops op; i40e_status err; - event.msg_size = I40EVF_MAX_AQ_BUF_SIZE; - event.msg_buf = kzalloc(event.msg_size, GFP_KERNEL); + event.buf_len = I40EVF_MAX_AQ_BUF_SIZE; + event.msg_buf = kzalloc(event.buf_len, GFP_KERNEL); if (!event.msg_buf) { err = -ENOMEM; goto out; } - err = i40evf_clean_arq_element(hw, &event, NULL); - if (err == I40E_ERR_ADMIN_QUEUE_NO_WORK) - goto out_alloc; + while (1) { + err = i40evf_clean_arq_element(hw, &event, NULL); + /* When the AQ is empty, i40evf_clean_arq_element will return + * nonzero and this loop will terminate. + */ + if (err) + goto out_alloc; + op = + (enum i40e_virtchnl_ops)le32_to_cpu(event.desc.cookie_high); + if (op == I40E_VIRTCHNL_OP_VERSION) + break; + } + err = (i40e_status)le32_to_cpu(event.desc.cookie_low); if (err) goto out_alloc; - if ((enum i40e_virtchnl_ops)le32_to_cpu(event.desc.cookie_high) != - I40E_VIRTCHNL_OP_VERSION) { + if (op != I40E_VIRTCHNL_OP_VERSION) { dev_info(&adapter->pdev->dev, "Invalid reply type %d from PF\n", - le32_to_cpu(event.desc.cookie_high)); + op); err = -EIO; goto out_alloc; } @@ -153,42 +163,34 @@ int i40evf_get_vf_config(struct i40evf_adapter *adapter) { struct i40e_hw *hw = &adapter->hw; struct i40e_arq_event_info event; - u16 len; + enum i40e_virtchnl_ops op; i40e_status err; + u16 len; len = sizeof(struct i40e_virtchnl_vf_resource) + I40E_MAX_VF_VSI * sizeof(struct i40e_virtchnl_vsi_resource); - event.msg_size = len; - event.msg_buf = kzalloc(event.msg_size, GFP_KERNEL); + event.buf_len = len; + event.msg_buf = kzalloc(event.buf_len, GFP_KERNEL); if (!event.msg_buf) { err = -ENOMEM; goto out; } - err = i40evf_clean_arq_element(hw, &event, NULL); - if (err == I40E_ERR_ADMIN_QUEUE_NO_WORK) - goto out_alloc; - - err = (i40e_status)le32_to_cpu(event.desc.cookie_low); - if (err) { - dev_err(&adapter->pdev->dev, - "%s: Error returned from PF, %d, %d\n", __func__, - le32_to_cpu(event.desc.cookie_high), - le32_to_cpu(event.desc.cookie_low)); - err = -EIO; - goto out_alloc; + while (1) { + /* When the AQ is empty, i40evf_clean_arq_element will return + * nonzero and this loop will terminate. + */ + err = i40evf_clean_arq_element(hw, &event, NULL); + if (err) + goto out_alloc; + op = + (enum i40e_virtchnl_ops)le32_to_cpu(event.desc.cookie_high); + if (op == I40E_VIRTCHNL_OP_GET_VF_RESOURCES) + break; } - if ((enum i40e_virtchnl_ops)le32_to_cpu(event.desc.cookie_high) != - I40E_VIRTCHNL_OP_GET_VF_RESOURCES) { - dev_err(&adapter->pdev->dev, - "%s: Invalid response from PF, %d, %d\n", __func__, - le32_to_cpu(event.desc.cookie_high), - le32_to_cpu(event.desc.cookie_low)); - err = -EIO; - goto out_alloc; - } - memcpy(adapter->vf_res, event.msg_buf, min(event.msg_size, len)); + err = (i40e_status)le32_to_cpu(event.desc.cookie_low); + memcpy(adapter->vf_res, event.msg_buf, min(event.msg_len, len)); i40e_vf_parse_hw_config(hw, adapter->vf_res); out_alloc: @@ -207,7 +209,7 @@ void i40evf_configure_queues(struct i40evf_adapter *adapter) { struct i40e_virtchnl_vsi_queue_config_info *vqci; struct i40e_virtchnl_queue_pair_info *vqpi; - int pairs = adapter->vsi_res->num_queue_pairs; + int pairs = adapter->num_active_queues; int i, len; if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) { @@ -273,7 +275,7 @@ void i40evf_enable_queues(struct i40evf_adapter *adapter) } adapter->current_op = I40E_VIRTCHNL_OP_ENABLE_QUEUES; vqs.vsi_id = adapter->vsi_res->vsi_id; - vqs.tx_queues = (1 << adapter->vsi_res->num_queue_pairs) - 1; + vqs.tx_queues = (1 << adapter->num_active_queues) - 1; vqs.rx_queues = vqs.tx_queues; adapter->aq_pending |= I40EVF_FLAG_AQ_ENABLE_QUEUES; adapter->aq_required &= ~I40EVF_FLAG_AQ_ENABLE_QUEUES; @@ -299,7 +301,7 @@ void i40evf_disable_queues(struct i40evf_adapter *adapter) } adapter->current_op = I40E_VIRTCHNL_OP_DISABLE_QUEUES; vqs.vsi_id = adapter->vsi_res->vsi_id; - vqs.tx_queues = (1 << adapter->vsi_res->num_queue_pairs) - 1; + vqs.tx_queues = (1 << adapter->num_active_queues) - 1; vqs.rx_queues = vqs.tx_queues; adapter->aq_pending |= I40EVF_FLAG_AQ_DISABLE_QUEUES; adapter->aq_required &= ~I40EVF_FLAG_AQ_DISABLE_QUEUES; @@ -393,7 +395,7 @@ void i40evf_add_ether_addrs(struct i40evf_adapter *adapter) (count * sizeof(struct i40e_virtchnl_ether_addr)); if (len > I40EVF_MAX_AQ_BUF_SIZE) { dev_warn(&adapter->pdev->dev, "%s: Too many MAC address changes in one request\n", - __func__); + __func__); count = (I40EVF_MAX_AQ_BUF_SIZE - sizeof(struct i40e_virtchnl_ether_addr_list)) / sizeof(struct i40e_virtchnl_ether_addr); @@ -454,7 +456,7 @@ void i40evf_del_ether_addrs(struct i40evf_adapter *adapter) (count * sizeof(struct i40e_virtchnl_ether_addr)); if (len > I40EVF_MAX_AQ_BUF_SIZE) { dev_warn(&adapter->pdev->dev, "%s: Too many MAC address changes in one request\n", - __func__); + __func__); count = (I40EVF_MAX_AQ_BUF_SIZE - sizeof(struct i40e_virtchnl_ether_addr_list)) / sizeof(struct i40e_virtchnl_ether_addr); @@ -516,7 +518,7 @@ void i40evf_add_vlans(struct i40evf_adapter *adapter) (count * sizeof(u16)); if (len > I40EVF_MAX_AQ_BUF_SIZE) { dev_warn(&adapter->pdev->dev, "%s: Too many VLAN changes in one request\n", - __func__); + __func__); count = (I40EVF_MAX_AQ_BUF_SIZE - sizeof(struct i40e_virtchnl_vlan_filter_list)) / sizeof(u16); @@ -576,7 +578,7 @@ void i40evf_del_vlans(struct i40evf_adapter *adapter) (count * sizeof(u16)); if (len > I40EVF_MAX_AQ_BUF_SIZE) { dev_warn(&adapter->pdev->dev, "%s: Too many VLAN changes in one request\n", - __func__); + __func__); count = (I40EVF_MAX_AQ_BUF_SIZE - sizeof(struct i40e_virtchnl_vlan_filter_list)) / sizeof(u16); @@ -635,6 +637,7 @@ void i40evf_set_promiscuous(struct i40evf_adapter *adapter, int flags) void i40evf_request_stats(struct i40evf_adapter *adapter) { struct i40e_virtchnl_queue_select vqs; + if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) { /* no error message, this isn't crucial */ return; @@ -709,7 +712,6 @@ void i40evf_virtchnl_completion(struct i40evf_adapter *adapter, "%s: Unknown event %d from pf\n", __func__, vpe->event); break; - } return; } @@ -774,7 +776,7 @@ void i40evf_virtchnl_completion(struct i40evf_adapter *adapter, break; default: dev_warn(&adapter->pdev->dev, "%s: Received unexpected message %d from PF\n", - __func__, v_opcode); + __func__, v_opcode); break; } /* switch v_opcode */ adapter->current_op = I40E_VIRTCHNL_OP_UNKNOWN; diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 487cd9c4ac0d..3c0221620c9d 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -3375,14 +3375,11 @@ static void igb_setup_mrqc(struct igb_adapter *adapter) struct e1000_hw *hw = &adapter->hw; u32 mrqc, rxcsum; u32 j, num_rx_queues; - static const u32 rsskey[10] = { 0xDA565A6D, 0xC20E5B25, 0x3D256741, - 0xB08FA343, 0xCB2BCAD0, 0xB4307BAE, - 0xA32DCB77, 0x0CF23080, 0x3BB7426A, - 0xFA01ACBE }; + u32 rss_key[10]; - /* Fill out hash function seeds */ + netdev_rss_key_fill(rss_key, sizeof(rss_key)); for (j = 0; j < 10; j++) - wr32(E1000_RSSRK(j), rsskey[j]); + wr32(E1000_RSSRK(j), rss_key[j]); num_rx_queues = adapter->rss_queues; @@ -6995,7 +6992,7 @@ static bool igb_alloc_mapped_page(struct igb_ring *rx_ring, return true; /* alloc new page for storage */ - page = __skb_alloc_page(GFP_ATOMIC | __GFP_COLD, NULL); + page = dev_alloc_page(); if (unlikely(!page)) { rx_ring->rx_stats.alloc_failed++; return false; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c index b5f484bf3fda..0e754b4c4220 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c @@ -2799,6 +2799,8 @@ u16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw) break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: pcie_offset = IXGBE_PCIE_MSIX_82599_CAPS; max_msix_count = IXGBE_MAX_MSIX_VECTORS_82599; break; @@ -3192,17 +3194,27 @@ s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed, *link_up = false; } - if ((links_reg & IXGBE_LINKS_SPEED_82599) == - IXGBE_LINKS_SPEED_10G_82599) - *speed = IXGBE_LINK_SPEED_10GB_FULL; - else if ((links_reg & IXGBE_LINKS_SPEED_82599) == - IXGBE_LINKS_SPEED_1G_82599) + switch (links_reg & IXGBE_LINKS_SPEED_82599) { + case IXGBE_LINKS_SPEED_10G_82599: + if ((hw->mac.type >= ixgbe_mac_X550) && + (links_reg & IXGBE_LINKS_SPEED_NON_STD)) + *speed = IXGBE_LINK_SPEED_2_5GB_FULL; + else + *speed = IXGBE_LINK_SPEED_10GB_FULL; + break; + case IXGBE_LINKS_SPEED_1G_82599: *speed = IXGBE_LINK_SPEED_1GB_FULL; - else if ((links_reg & IXGBE_LINKS_SPEED_82599) == - IXGBE_LINKS_SPEED_100_82599) - *speed = IXGBE_LINK_SPEED_100_FULL; - else + break; + case IXGBE_LINKS_SPEED_100_82599: + if ((hw->mac.type >= ixgbe_mac_X550) && + (links_reg & IXGBE_LINKS_SPEED_NON_STD)) + *speed = IXGBE_LINK_SPEED_5GB_FULL; + else + *speed = IXGBE_LINK_SPEED_100_FULL; + break; + default: *speed = IXGBE_LINK_SPEED_UNKNOWN; + } return 0; } @@ -3583,7 +3595,8 @@ s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min, **/ void ixgbe_clear_tx_pending(struct ixgbe_hw *hw) { - u32 gcr_ext, hlreg0; + u32 gcr_ext, hlreg0, i, poll; + u16 value; /* * If double reset is not requested then all transactions should @@ -3600,6 +3613,23 @@ void ixgbe_clear_tx_pending(struct ixgbe_hw *hw) hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0 | IXGBE_HLREG0_LPBK); + /* wait for a last completion before clearing buffers */ + IXGBE_WRITE_FLUSH(hw); + usleep_range(3000, 6000); + + /* Before proceeding, make sure that the PCIe block does not have + * transactions pending. + */ + poll = ixgbe_pcie_timeout_poll(hw); + for (i = 0; i < poll; i++) { + usleep_range(100, 200); + value = ixgbe_read_pci_cfg_word(hw, IXGBE_PCI_DEVICE_STATUS); + if (ixgbe_removed(hw->hw_addr)) + break; + if (!(value & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING)) + break; + } + /* initiate cleaning flow for buffers in the PCIe transaction layer */ gcr_ext = IXGBE_READ_REG(hw, IXGBE_GCR_EXT); IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c index 48f35fc963f8..a507a6fe3624 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c @@ -286,6 +286,8 @@ s32 ixgbe_dcb_hw_config(struct ixgbe_hw *hw, bwgid, ptype); case ixgbe_mac_82599EB: case ixgbe_mac_X540: + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: return ixgbe_dcb_hw_config_82599(hw, pfc_en, refill, max, bwgid, ptype, prio_tc); default: @@ -302,6 +304,8 @@ s32 ixgbe_dcb_hw_pfc_config(struct ixgbe_hw *hw, u8 pfc_en, u8 *prio_tc) return ixgbe_dcb_config_pfc_82598(hw, pfc_en); case ixgbe_mac_82599EB: case ixgbe_mac_X540: + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: return ixgbe_dcb_config_pfc_82599(hw, pfc_en, prio_tc); default: break; @@ -357,6 +361,8 @@ s32 ixgbe_dcb_hw_ets_config(struct ixgbe_hw *hw, break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: ixgbe_dcb_config_rx_arbiter_82599(hw, refill, max, bwg_id, prio_type, prio_tc); ixgbe_dcb_config_tx_desc_arbiter_82599(hw, refill, max, @@ -385,6 +391,8 @@ void ixgbe_dcb_read_rtrup2tc(struct ixgbe_hw *hw, u8 *map) switch (hw->mac.type) { case ixgbe_mac_82599EB: case ixgbe_mac_X540: + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: ixgbe_dcb_read_rtrup2tc_82599(hw, map); break; default: diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c index 58a7f5312a96..2707bda37418 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c @@ -180,6 +180,7 @@ static void ixgbe_dcbnl_get_perm_hw_addr(struct net_device *netdev, switch (adapter->hw.mac.type) { case ixgbe_mac_82599EB: case ixgbe_mac_X540: + case ixgbe_mac_X550: for (j = 0; j < netdev->addr_len; j++, i++) perm_addr[i] = adapter->hw.mac.san_addr[j]; break; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c index 0ae038b9af90..26fd85e2bca5 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c @@ -511,6 +511,8 @@ static void ixgbe_get_regs(struct net_device *netdev, break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: regs_buff[35 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTL_82599(i)); regs_buff[43 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTH_82599(i)); break; @@ -622,6 +624,8 @@ static void ixgbe_get_regs(struct net_device *netdev, break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: regs_buff[830] = IXGBE_READ_REG(hw, IXGBE_RTTDCS); regs_buff[832] = IXGBE_READ_REG(hw, IXGBE_RTRPCS); for (i = 0; i < 8; i++) @@ -1406,6 +1410,8 @@ static int ixgbe_reg_test(struct ixgbe_adapter *adapter, u64 *data) break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: toggle = 0x7FFFF30F; test = reg_test_82599; break; @@ -1644,6 +1650,8 @@ static void ixgbe_free_desc_rings(struct ixgbe_adapter *adapter) switch (hw->mac.type) { case ixgbe_mac_82599EB: case ixgbe_mac_X540: + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: reg_ctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL); reg_ctl &= ~IXGBE_DMATXCTL_TE; IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, reg_ctl); @@ -1680,6 +1688,8 @@ static int ixgbe_setup_desc_rings(struct ixgbe_adapter *adapter) switch (adapter->hw.mac.type) { case ixgbe_mac_82599EB: case ixgbe_mac_X540: + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_DMATXCTL); reg_data |= IXGBE_DMATXCTL_TE; IXGBE_WRITE_REG(&adapter->hw, IXGBE_DMATXCTL, reg_data); @@ -1733,12 +1743,16 @@ static int ixgbe_setup_loopback_test(struct ixgbe_adapter *adapter) reg_data |= IXGBE_FCTRL_BAM | IXGBE_FCTRL_SBP | IXGBE_FCTRL_MPE; IXGBE_WRITE_REG(hw, IXGBE_FCTRL, reg_data); - /* X540 needs to set the MACC.FLU bit to force link up */ - if (adapter->hw.mac.type == ixgbe_mac_X540) { + /* X540 and X550 needs to set the MACC.FLU bit to force link up */ + switch (adapter->hw.mac.type) { + case ixgbe_mac_X540: + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: reg_data = IXGBE_READ_REG(hw, IXGBE_MACC); reg_data |= IXGBE_MACC_FLU; IXGBE_WRITE_REG(hw, IXGBE_MACC, reg_data); - } else { + break; + default: if (hw->mac.orig_autoc) { reg_data = hw->mac.orig_autoc | IXGBE_AUTOC_FLU; IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_data); @@ -2776,7 +2790,14 @@ static int ixgbe_set_rss_hash_opt(struct ixgbe_adapter *adapter, /* if we changed something we need to update flags */ if (flags2 != adapter->flags2) { struct ixgbe_hw *hw = &adapter->hw; - u32 mrqc = IXGBE_READ_REG(hw, IXGBE_MRQC); + u32 mrqc; + unsigned int pf_pool = adapter->num_vfs; + + if ((hw->mac.type >= ixgbe_mac_X550) && + (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)) + mrqc = IXGBE_READ_REG(hw, IXGBE_PFVFMRQC(pf_pool)); + else + mrqc = IXGBE_READ_REG(hw, IXGBE_MRQC); if ((flags2 & UDP_RSS_FLAGS) && !(adapter->flags2 & UDP_RSS_FLAGS)) @@ -2799,7 +2820,11 @@ static int ixgbe_set_rss_hash_opt(struct ixgbe_adapter *adapter, if (flags2 & IXGBE_FLAG2_RSS_FIELD_IPV6_UDP) mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_UDP; - IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc); + if ((hw->mac.type >= ixgbe_mac_X550) && + (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)) + IXGBE_WRITE_REG(hw, IXGBE_PFVFMRQC(pf_pool), mrqc); + else + IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc); } return 0; @@ -2833,6 +2858,8 @@ static int ixgbe_get_ts_info(struct net_device *dev, struct ixgbe_adapter *adapter = netdev_priv(dev); switch (adapter->hw.mac.type) { + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: case ixgbe_mac_X540: case ixgbe_mac_82599EB: info->so_timestamping = diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c index ce40c77381e9..68e1e757ecef 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c @@ -126,6 +126,8 @@ static void ixgbe_get_first_reg_idx(struct ixgbe_adapter *adapter, u8 tc, break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: if (num_tcs > 4) { /* * TCs : TC0/1 TC2/3 TC4-7 diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index cc51554c9e99..52776f9e1f71 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -835,6 +835,8 @@ static void ixgbe_set_ivar(struct ixgbe_adapter *adapter, s8 direction, break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: if (direction == -1) { /* other causes */ msix_vector |= IXGBE_IVAR_ALLOC_VAL; @@ -871,6 +873,8 @@ static inline void ixgbe_irq_rearm_queues(struct ixgbe_adapter *adapter, break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: mask = (qmask & 0xFFFFFFFF); IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS_EX(0), mask); mask = (qmask >> 32); @@ -1440,8 +1444,7 @@ static bool ixgbe_alloc_mapped_page(struct ixgbe_ring *rx_ring, /* alloc new page for storage */ if (likely(!page)) { - page = __skb_alloc_pages(GFP_ATOMIC | __GFP_COLD | __GFP_COMP, - bi->skb, ixgbe_rx_pg_order(rx_ring)); + page = dev_alloc_pages(ixgbe_rx_pg_order(rx_ring)); if (unlikely(!page)) { rx_ring->rx_stats.alloc_rx_page_failed++; return false; @@ -2155,6 +2158,8 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter) break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: ixgbe_set_ivar(adapter, -1, 1, v_idx); break; default: @@ -2264,6 +2269,8 @@ void ixgbe_write_eitr(struct ixgbe_q_vector *q_vector) break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: /* * set the WDIS bit to not clear the timer bits and cause an * immediate assertion of the interrupt @@ -2467,6 +2474,8 @@ static inline void ixgbe_irq_enable_queues(struct ixgbe_adapter *adapter, break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: mask = (qmask & 0xFFFFFFFF); if (mask) IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(0), mask); @@ -2493,6 +2502,8 @@ static inline void ixgbe_irq_disable_queues(struct ixgbe_adapter *adapter, break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: mask = (qmask & 0xFFFFFFFF); if (mask) IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(0), mask); @@ -2525,6 +2536,8 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues, mask |= IXGBE_EIMS_GPI_SDP0; break; case ixgbe_mac_X540: + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: mask |= IXGBE_EIMS_TS; break; default: @@ -2536,7 +2549,10 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues, case ixgbe_mac_82599EB: mask |= IXGBE_EIMS_GPI_SDP1; mask |= IXGBE_EIMS_GPI_SDP2; + /* fall through */ case ixgbe_mac_X540: + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: mask |= IXGBE_EIMS_ECC; mask |= IXGBE_EIMS_MAILBOX; break; @@ -2544,9 +2560,6 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues, break; } - if (adapter->hw.mac.type == ixgbe_mac_X540) - mask |= IXGBE_EIMS_TIMESYNC; - if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) && !(adapter->flags2 & IXGBE_FLAG2_FDIR_REQUIRES_REINIT)) mask |= IXGBE_EIMS_FLOW_DIR; @@ -2592,6 +2605,8 @@ static irqreturn_t ixgbe_msix_other(int irq, void *data) switch (hw->mac.type) { case ixgbe_mac_82599EB: case ixgbe_mac_X540: + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: if (eicr & IXGBE_EICR_ECC) { e_info(link, "Received ECC Err, initiating reset\n"); adapter->flags2 |= IXGBE_FLAG2_RESET_REQUESTED; @@ -2811,6 +2826,8 @@ static irqreturn_t ixgbe_intr(int irq, void *data) ixgbe_check_sfp_event(adapter, eicr); /* Fall through */ case ixgbe_mac_X540: + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: if (eicr & IXGBE_EICR_ECC) { e_info(link, "Received ECC Err, initiating reset\n"); adapter->flags2 |= IXGBE_FLAG2_RESET_REQUESTED; @@ -2905,6 +2922,8 @@ static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter) break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFF0000); IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(0), ~0); IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(1), ~0); @@ -3190,14 +3209,10 @@ static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter, IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(reg_idx), srrctl); } -static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter) +static void ixgbe_setup_reta(struct ixgbe_adapter *adapter, const u32 *seed) { struct ixgbe_hw *hw = &adapter->hw; - static const u32 seed[10] = { 0xE291D73D, 0x1805EC6C, 0x2A94B30D, - 0xA54F2BEC, 0xEA49AF7C, 0xE214AD3D, 0xB855AABE, - 0x6A3E67EA, 0x14364D17, 0x3BED200D}; - u32 mrqc = 0, reta = 0; - u32 rxcsum; + u32 reta = 0; int i, j; u16 rss_i = adapter->ring_feature[RING_F_RSS].indices; @@ -3223,6 +3238,14 @@ static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter) if ((i & 3) == 3) IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2), reta); } +} + +static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter) +{ + struct ixgbe_hw *hw = &adapter->hw; + u32 mrqc = 0, rss_field = 0; + u32 rss_key[10]; + u32 rxcsum; /* Disable indicating checksum in descriptor, enables RSS hash */ rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM); @@ -3255,16 +3278,19 @@ static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter) } /* Perform hash on these packet types */ - mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4 | - IXGBE_MRQC_RSS_FIELD_IPV4_TCP | - IXGBE_MRQC_RSS_FIELD_IPV6 | - IXGBE_MRQC_RSS_FIELD_IPV6_TCP; + rss_field |= IXGBE_MRQC_RSS_FIELD_IPV4 | + IXGBE_MRQC_RSS_FIELD_IPV4_TCP | + IXGBE_MRQC_RSS_FIELD_IPV6 | + IXGBE_MRQC_RSS_FIELD_IPV6_TCP; if (adapter->flags2 & IXGBE_FLAG2_RSS_FIELD_IPV4_UDP) - mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_UDP; + rss_field |= IXGBE_MRQC_RSS_FIELD_IPV4_UDP; if (adapter->flags2 & IXGBE_FLAG2_RSS_FIELD_IPV6_UDP) - mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_UDP; + rss_field |= IXGBE_MRQC_RSS_FIELD_IPV6_UDP; + netdev_rss_key_fill(rss_key, sizeof(rss_key)); + ixgbe_setup_reta(adapter, rss_key); + mrqc |= rss_field; IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc); } @@ -3534,6 +3560,8 @@ static void ixgbe_setup_rdrxctl(struct ixgbe_adapter *adapter) u32 rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL); switch (hw->mac.type) { + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: case ixgbe_mac_82598EB: /* * For VMDq support of different descriptor types or @@ -3657,6 +3685,8 @@ static void ixgbe_vlan_strip_disable(struct ixgbe_adapter *adapter) break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: for (i = 0; i < adapter->num_rx_queues; i++) { struct ixgbe_ring *ring = adapter->rx_ring[i]; @@ -3691,6 +3721,8 @@ static void ixgbe_vlan_strip_enable(struct ixgbe_adapter *adapter) break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: for (i = 0; i < adapter->num_rx_queues; i++) { struct ixgbe_ring *ring = adapter->rx_ring[i]; @@ -4112,6 +4144,8 @@ static int ixgbe_hpbthresh(struct ixgbe_adapter *adapter, int pb) /* Calculate delay value for device */ switch (hw->mac.type) { case ixgbe_mac_X540: + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: dv_id = IXGBE_DV_X540(link, tc); break; default: @@ -4170,6 +4204,8 @@ static int ixgbe_lpbthresh(struct ixgbe_adapter *adapter, int pb) /* Calculate delay value for device */ switch (hw->mac.type) { case ixgbe_mac_X540: + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: dv_id = IXGBE_LOW_DV_X540(tc); break; default: @@ -4606,6 +4642,8 @@ static void ixgbe_setup_gpie(struct ixgbe_adapter *adapter) break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: default: IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(0), 0xFFFFFFFF); IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(1), 0xFFFFFFFF); @@ -4948,10 +4986,12 @@ void ixgbe_down(struct ixgbe_adapter *adapter) IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(reg_idx), IXGBE_TXDCTL_SWFLSH); } - /* Disable the Tx DMA engine on 82599 and X540 */ + /* Disable the Tx DMA engine on 82599 and later MAC */ switch (hw->mac.type) { case ixgbe_mac_82599EB: case ixgbe_mac_X540: + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, (IXGBE_READ_REG(hw, IXGBE_DMATXCTL) & ~IXGBE_DMATXCTL_TE)); @@ -5071,6 +5111,12 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter) if (fwsm & IXGBE_FWSM_TS_ENABLED) adapter->flags2 |= IXGBE_FLAG2_TEMP_SENSOR_CAPABLE; break; + case ixgbe_mac_X550EM_x: + case ixgbe_mac_X550: +#ifdef CONFIG_IXGBE_DCA + adapter->flags &= ~IXGBE_FLAG_DCA_CAPABLE; +#endif + break; default: break; } @@ -5086,6 +5132,8 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter) #ifdef CONFIG_IXGBE_DCB switch (hw->mac.type) { case ixgbe_mac_X540: + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: adapter->dcb_cfg.num_tcs.pg_tcs = X540_TRAFFIC_CLASS; adapter->dcb_cfg.num_tcs.pfc_tcs = X540_TRAFFIC_CLASS; break; @@ -5675,6 +5723,8 @@ static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake) break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: pci_wake_from_d3(pdev, !!wufc); break; default: @@ -5806,6 +5856,8 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter) break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: hwstats->pxonrxc[i] += IXGBE_READ_REG(hw, IXGBE_PXONRXCNT(i)); break; @@ -5819,7 +5871,9 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter) hwstats->qptc[i] += IXGBE_READ_REG(hw, IXGBE_QPTC(i)); hwstats->qprc[i] += IXGBE_READ_REG(hw, IXGBE_QPRC(i)); if ((hw->mac.type == ixgbe_mac_82599EB) || - (hw->mac.type == ixgbe_mac_X540)) { + (hw->mac.type == ixgbe_mac_X540) || + (hw->mac.type == ixgbe_mac_X550) || + (hw->mac.type == ixgbe_mac_X550EM_x)) { hwstats->qbtc[i] += IXGBE_READ_REG(hw, IXGBE_QBTC_L(i)); IXGBE_READ_REG(hw, IXGBE_QBTC_H(i)); /* to clear */ hwstats->qbrc[i] += IXGBE_READ_REG(hw, IXGBE_QBRC_L(i)); @@ -5842,7 +5896,9 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter) hwstats->tor += IXGBE_READ_REG(hw, IXGBE_TORH); break; case ixgbe_mac_X540: - /* OS2BMC stats are X540 only*/ + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: + /* OS2BMC stats are X540 and later */ hwstats->o2bgptc += IXGBE_READ_REG(hw, IXGBE_O2BGPTC); hwstats->o2bspc += IXGBE_READ_REG(hw, IXGBE_O2BSPC); hwstats->b2ospc += IXGBE_READ_REG(hw, IXGBE_B2OSPC); @@ -6110,6 +6166,8 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter) } break; case ixgbe_mac_X540: + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: case ixgbe_mac_82599EB: { u32 mflcn = IXGBE_READ_REG(hw, IXGBE_MFLCN); u32 fccfg = IXGBE_READ_REG(hw, IXGBE_FCCFG); @@ -6221,6 +6279,10 @@ static bool ixgbe_vf_tx_pending(struct ixgbe_adapter *adapter) if (!adapter->num_vfs) return false; + /* resetting the PF is only needed for MAC before X550 */ + if (hw->mac.type >= ixgbe_mac_X550) + return false; + for (i = 0; i < adapter->num_vfs; i++) { for (j = 0; j < q_per_pool; j++) { u32 h, t; @@ -6430,11 +6492,11 @@ static void ixgbe_check_for_bad_vf(struct ixgbe_adapter *adapter) ciaa = (vf << 16) | 0x80000000; /* 32 bit read so align, we really want status at offset 6 */ ciaa |= PCI_COMMAND; - IXGBE_WRITE_REG(hw, IXGBE_CIAA_82599, ciaa); - ciad = IXGBE_READ_REG(hw, IXGBE_CIAD_82599); + IXGBE_WRITE_REG(hw, IXGBE_CIAA_BY_MAC(hw), ciaa); + ciad = IXGBE_READ_REG(hw, IXGBE_CIAD_BY_MAC(hw)); ciaa &= 0x7FFFFFFF; /* disable debug mode asap after reading data */ - IXGBE_WRITE_REG(hw, IXGBE_CIAA_82599, ciaa); + IXGBE_WRITE_REG(hw, IXGBE_CIAA_BY_MAC(hw), ciaa); /* Get the upper 16 bits which will be the PCI status reg */ ciad >>= 16; if (ciad & PCI_STATUS_REC_MASTER_ABORT) { @@ -6442,11 +6504,11 @@ static void ixgbe_check_for_bad_vf(struct ixgbe_adapter *adapter) /* Issue VFLR */ ciaa = (vf << 16) | 0x80000000; ciaa |= 0xA8; - IXGBE_WRITE_REG(hw, IXGBE_CIAA_82599, ciaa); + IXGBE_WRITE_REG(hw, IXGBE_CIAA_BY_MAC(hw), ciaa); ciad = 0x00008000; /* VFLR */ - IXGBE_WRITE_REG(hw, IXGBE_CIAD_82599, ciad); + IXGBE_WRITE_REG(hw, IXGBE_CIAD_BY_MAC(hw), ciad); ciaa &= 0x7FFFFFFF; - IXGBE_WRITE_REG(hw, IXGBE_CIAA_82599, ciaa); + IXGBE_WRITE_REG(hw, IXGBE_CIAA_BY_MAC(hw), ciaa); } } } @@ -8104,6 +8166,8 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent) switch (adapter->hw.mac.type) { case ixgbe_mac_82599EB: case ixgbe_mac_X540: + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: IXGBE_WRITE_REG(&adapter->hw, IXGBE_WUS, ~0); break; default: @@ -8167,6 +8231,8 @@ skip_sriov: switch (adapter->hw.mac.type) { case ixgbe_mac_82599EB: case ixgbe_mac_X540: + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: netdev->features |= NETIF_F_SCTP_CSUM; netdev->hw_features |= NETIF_F_SCTP_CSUM | NETIF_F_NTUPLE; @@ -8523,6 +8589,12 @@ static pci_ers_result_t ixgbe_io_error_detected(struct pci_dev *pdev, case ixgbe_mac_X540: device_id = IXGBE_X540_VF_DEVICE_ID; break; + case ixgbe_mac_X550: + device_id = IXGBE_DEV_ID_X550_VF; + break; + case ixgbe_mac_X550EM_x: + device_id = IXGBE_DEV_ID_X550EM_X_VF; + break; default: device_id = 0; break; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c index cc8f0128286c..9993a471d668 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c @@ -305,6 +305,8 @@ static s32 ixgbe_check_for_rst_pf(struct ixgbe_hw *hw, u16 vf_number) vflre = IXGBE_READ_REG(hw, IXGBE_VFLRE(reg_offset)); break; case ixgbe_mac_X540: + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: vflre = IXGBE_READ_REG(hw, IXGBE_VFLREC(reg_offset)); break; default: @@ -426,6 +428,8 @@ void ixgbe_init_mbx_params_pf(struct ixgbe_hw *hw) struct ixgbe_mbx_info *mbx = &hw->mbx; if (hw->mac.type != ixgbe_mac_82599EB && + hw->mac.type != ixgbe_mac_X550 && + hw->mac.type != ixgbe_mac_X550EM_x && hw->mac.type != ixgbe_mac_X540) return; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c index 28b81ae09b5a..acafe391f0a3 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c @@ -43,7 +43,7 @@ static s32 ixgbe_clock_out_i2c_bit(struct ixgbe_hw *hw, bool data); static void ixgbe_raise_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl); static void ixgbe_lower_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl); static s32 ixgbe_set_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl, bool data); -static bool ixgbe_get_i2c_data(u32 *i2cctl); +static bool ixgbe_get_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl); static void ixgbe_i2c_bus_clear(struct ixgbe_hw *hw); static enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id); static s32 ixgbe_get_phy_id(struct ixgbe_hw *hw); @@ -576,6 +576,10 @@ s32 ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw, *speed |= IXGBE_LINK_SPEED_100_FULL; } + /* Internal PHY does not support 100 Mbps */ + if (hw->mac.type == ixgbe_mac_X550EM_x) + *speed &= ~IXGBE_LINK_SPEED_100_FULL; + return status; } @@ -632,6 +636,9 @@ s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw, ixgbe_link_speed *speed, * @hw: pointer to hardware structure * * Restart autonegotiation and PHY and waits for completion. + * This function always returns success, this is nessary since + * it is called via a function pointer that could call other + * functions that could return an error. **/ s32 ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw) { @@ -1610,7 +1617,7 @@ fail: **/ static void ixgbe_i2c_start(struct ixgbe_hw *hw) { - u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL); + u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL_BY_MAC(hw)); /* Start condition must begin with data and clock high */ ixgbe_set_i2c_data(hw, &i2cctl, 1); @@ -1639,7 +1646,7 @@ static void ixgbe_i2c_start(struct ixgbe_hw *hw) **/ static void ixgbe_i2c_stop(struct ixgbe_hw *hw) { - u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL); + u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL_BY_MAC(hw)); /* Stop condition must begin with data low and clock high */ ixgbe_set_i2c_data(hw, &i2cctl, 0); @@ -1697,9 +1704,9 @@ static s32 ixgbe_clock_out_i2c_byte(struct ixgbe_hw *hw, u8 data) } /* Release SDA line (set high) */ - i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL); - i2cctl |= IXGBE_I2C_DATA_OUT; - IXGBE_WRITE_REG(hw, IXGBE_I2CCTL, i2cctl); + i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL_BY_MAC(hw)); + i2cctl |= IXGBE_I2C_DATA_OUT_BY_MAC(hw); + IXGBE_WRITE_REG(hw, IXGBE_I2CCTL_BY_MAC(hw), i2cctl); IXGBE_WRITE_FLUSH(hw); return status; @@ -1715,7 +1722,7 @@ static s32 ixgbe_get_i2c_ack(struct ixgbe_hw *hw) { s32 status = 0; u32 i = 0; - u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL); + u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL_BY_MAC(hw)); u32 timeout = 10; bool ack = true; @@ -1728,8 +1735,8 @@ static s32 ixgbe_get_i2c_ack(struct ixgbe_hw *hw) /* Poll for ACK. Note that ACK in I2C spec is * transition from 1 to 0 */ for (i = 0; i < timeout; i++) { - i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL); - ack = ixgbe_get_i2c_data(&i2cctl); + i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL_BY_MAC(hw)); + ack = ixgbe_get_i2c_data(hw, &i2cctl); udelay(1); if (ack == 0) @@ -1758,15 +1765,15 @@ static s32 ixgbe_get_i2c_ack(struct ixgbe_hw *hw) **/ static s32 ixgbe_clock_in_i2c_bit(struct ixgbe_hw *hw, bool *data) { - u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL); + u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL_BY_MAC(hw)); ixgbe_raise_i2c_clk(hw, &i2cctl); /* Minimum high period of clock is 4us */ udelay(IXGBE_I2C_T_HIGH); - i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL); - *data = ixgbe_get_i2c_data(&i2cctl); + i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL_BY_MAC(hw)); + *data = ixgbe_get_i2c_data(hw, &i2cctl); ixgbe_lower_i2c_clk(hw, &i2cctl); @@ -1786,7 +1793,7 @@ static s32 ixgbe_clock_in_i2c_bit(struct ixgbe_hw *hw, bool *data) static s32 ixgbe_clock_out_i2c_bit(struct ixgbe_hw *hw, bool data) { s32 status; - u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL); + u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL_BY_MAC(hw)); status = ixgbe_set_i2c_data(hw, &i2cctl, data); if (status == 0) { @@ -1822,14 +1829,14 @@ static void ixgbe_raise_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl) u32 i2cctl_r = 0; for (i = 0; i < timeout; i++) { - *i2cctl |= IXGBE_I2C_CLK_OUT; - IXGBE_WRITE_REG(hw, IXGBE_I2CCTL, *i2cctl); + *i2cctl |= IXGBE_I2C_CLK_OUT_BY_MAC(hw); + IXGBE_WRITE_REG(hw, IXGBE_I2CCTL_BY_MAC(hw), *i2cctl); IXGBE_WRITE_FLUSH(hw); /* SCL rise time (1000ns) */ udelay(IXGBE_I2C_T_RISE); - i2cctl_r = IXGBE_READ_REG(hw, IXGBE_I2CCTL); - if (i2cctl_r & IXGBE_I2C_CLK_IN) + i2cctl_r = IXGBE_READ_REG(hw, IXGBE_I2CCTL_BY_MAC(hw)); + if (i2cctl_r & IXGBE_I2C_CLK_IN_BY_MAC(hw)) break; } } @@ -1844,9 +1851,9 @@ static void ixgbe_raise_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl) static void ixgbe_lower_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl) { - *i2cctl &= ~IXGBE_I2C_CLK_OUT; + *i2cctl &= ~IXGBE_I2C_CLK_OUT_BY_MAC(hw); - IXGBE_WRITE_REG(hw, IXGBE_I2CCTL, *i2cctl); + IXGBE_WRITE_REG(hw, IXGBE_I2CCTL_BY_MAC(hw), *i2cctl); IXGBE_WRITE_FLUSH(hw); /* SCL fall time (300ns) */ @@ -1864,19 +1871,19 @@ static void ixgbe_lower_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl) static s32 ixgbe_set_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl, bool data) { if (data) - *i2cctl |= IXGBE_I2C_DATA_OUT; + *i2cctl |= IXGBE_I2C_DATA_OUT_BY_MAC(hw); else - *i2cctl &= ~IXGBE_I2C_DATA_OUT; + *i2cctl &= ~IXGBE_I2C_DATA_OUT_BY_MAC(hw); - IXGBE_WRITE_REG(hw, IXGBE_I2CCTL, *i2cctl); + IXGBE_WRITE_REG(hw, IXGBE_I2CCTL_BY_MAC(hw), *i2cctl); IXGBE_WRITE_FLUSH(hw); /* Data rise/fall (1000ns/300ns) and set-up time (250ns) */ udelay(IXGBE_I2C_T_RISE + IXGBE_I2C_T_FALL + IXGBE_I2C_T_SU_DATA); /* Verify data was set correctly */ - *i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL); - if (data != ixgbe_get_i2c_data(i2cctl)) { + *i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL_BY_MAC(hw)); + if (data != ixgbe_get_i2c_data(hw, i2cctl)) { hw_dbg(hw, "Error - I2C data was not set to %X.\n", data); return IXGBE_ERR_I2C; } @@ -1891,9 +1898,9 @@ static s32 ixgbe_set_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl, bool data) * * Returns the I2C data bit value **/ -static bool ixgbe_get_i2c_data(u32 *i2cctl) +static bool ixgbe_get_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl) { - if (*i2cctl & IXGBE_I2C_DATA_IN) + if (*i2cctl & IXGBE_I2C_DATA_IN_BY_MAC(hw)) return true; return false; } @@ -1907,7 +1914,7 @@ static bool ixgbe_get_i2c_data(u32 *i2cctl) **/ static void ixgbe_i2c_bus_clear(struct ixgbe_hw *hw) { - u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL); + u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL_BY_MAC(hw)); u32 i; ixgbe_i2c_start(hw); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c index 97c85b859536..04eee7c7b653 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c @@ -618,6 +618,27 @@ int ixgbe_vf_configuration(struct pci_dev *pdev, unsigned int event_mask) return 0; } +static inline void ixgbe_write_qde(struct ixgbe_adapter *adapter, u32 vf, + u32 qde) +{ + struct ixgbe_hw *hw = &adapter->hw; + struct ixgbe_ring_feature *vmdq = &adapter->ring_feature[RING_F_VMDQ]; + u32 q_per_pool = __ALIGN_MASK(1, ~vmdq->mask); + int i; + + for (i = vf * q_per_pool; i < ((vf + 1) * q_per_pool); i++) { + u32 reg; + + /* flush previous write */ + IXGBE_WRITE_FLUSH(hw); + + /* indicate to hardware that we want to set drop enable */ + reg = IXGBE_QDE_WRITE | IXGBE_QDE_ENABLE; + reg |= i << IXGBE_QDE_IDX_SHIFT; + IXGBE_WRITE_REG(hw, IXGBE_QDE, reg); + } +} + static int ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf) { struct ixgbe_ring_feature *vmdq = &adapter->ring_feature[RING_F_VMDQ]; @@ -647,15 +668,7 @@ static int ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf) IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset), reg); /* force drop enable for all VF Rx queues */ - for (i = vf * q_per_pool; i < ((vf + 1) * q_per_pool); i++) { - /* flush previous write */ - IXGBE_WRITE_FLUSH(hw); - - /* indicate to hardware that we want to set drop enable */ - reg = IXGBE_QDE_WRITE | IXGBE_QDE_ENABLE; - reg |= i << IXGBE_QDE_IDX_SHIFT; - IXGBE_WRITE_REG(hw, IXGBE_QDE, reg); - } + ixgbe_write_qde(adapter, vf, IXGBE_QDE_ENABLE); /* enable receive for vf */ reg = IXGBE_READ_REG(hw, IXGBE_VFRE(reg_offset)); @@ -1079,52 +1092,86 @@ int ixgbe_ndo_set_vf_mac(struct net_device *netdev, int vf, u8 *mac) return ixgbe_set_vf_mac(adapter, vf, mac); } +static int ixgbe_enable_port_vlan(struct ixgbe_adapter *adapter, int vf, + u16 vlan, u8 qos) +{ + struct ixgbe_hw *hw = &adapter->hw; + int err = 0; + + if (adapter->vfinfo[vf].pf_vlan) + err = ixgbe_set_vf_vlan(adapter, false, + adapter->vfinfo[vf].pf_vlan, + vf); + if (err) + goto out; + ixgbe_set_vmvir(adapter, vlan, qos, vf); + ixgbe_set_vmolr(hw, vf, false); + if (adapter->vfinfo[vf].spoofchk_enabled) + hw->mac.ops.set_vlan_anti_spoofing(hw, true, vf); + adapter->vfinfo[vf].vlan_count++; + + /* enable hide vlan on X550 */ + if (hw->mac.type >= ixgbe_mac_X550) + ixgbe_write_qde(adapter, vf, IXGBE_QDE_ENABLE | + IXGBE_QDE_HIDE_VLAN); + + adapter->vfinfo[vf].pf_vlan = vlan; + adapter->vfinfo[vf].pf_qos = qos; + dev_info(&adapter->pdev->dev, + "Setting VLAN %d, QOS 0x%x on VF %d\n", vlan, qos, vf); + if (test_bit(__IXGBE_DOWN, &adapter->state)) { + dev_warn(&adapter->pdev->dev, + "The VF VLAN has been set, but the PF device is not up.\n"); + dev_warn(&adapter->pdev->dev, + "Bring the PF device up before attempting to use the VF device.\n"); + } + +out: + return err; +} + +static int ixgbe_disable_port_vlan(struct ixgbe_adapter *adapter, int vf) +{ + struct ixgbe_hw *hw = &adapter->hw; + int err; + + err = ixgbe_set_vf_vlan(adapter, false, + adapter->vfinfo[vf].pf_vlan, vf); + ixgbe_clear_vmvir(adapter, vf); + ixgbe_set_vmolr(hw, vf, true); + hw->mac.ops.set_vlan_anti_spoofing(hw, false, vf); + if (adapter->vfinfo[vf].vlan_count) + adapter->vfinfo[vf].vlan_count--; + adapter->vfinfo[vf].pf_vlan = 0; + adapter->vfinfo[vf].pf_qos = 0; + + return err; +} + int ixgbe_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos) { int err = 0; struct ixgbe_adapter *adapter = netdev_priv(netdev); - struct ixgbe_hw *hw = &adapter->hw; if ((vf >= adapter->num_vfs) || (vlan > 4095) || (qos > 7)) return -EINVAL; if (vlan || qos) { + /* Check if there is already a port VLAN set, if so + * we have to delete the old one first before we + * can set the new one. The usage model had + * previously assumed the user would delete the + * old port VLAN before setting a new one but this + * is not necessarily the case. + */ if (adapter->vfinfo[vf].pf_vlan) - err = ixgbe_set_vf_vlan(adapter, false, - adapter->vfinfo[vf].pf_vlan, - vf); - if (err) - goto out; - err = ixgbe_set_vf_vlan(adapter, true, vlan, vf); + err = ixgbe_disable_port_vlan(adapter, vf); if (err) goto out; - ixgbe_set_vmvir(adapter, vlan, qos, vf); - ixgbe_set_vmolr(hw, vf, false); - if (adapter->vfinfo[vf].spoofchk_enabled) - hw->mac.ops.set_vlan_anti_spoofing(hw, true, vf); - adapter->vfinfo[vf].vlan_count++; - adapter->vfinfo[vf].pf_vlan = vlan; - adapter->vfinfo[vf].pf_qos = qos; - dev_info(&adapter->pdev->dev, - "Setting VLAN %d, QOS 0x%x on VF %d\n", vlan, qos, vf); - if (test_bit(__IXGBE_DOWN, &adapter->state)) { - dev_warn(&adapter->pdev->dev, - "The VF VLAN has been set," - " but the PF device is not up.\n"); - dev_warn(&adapter->pdev->dev, - "Bring the PF device up before" - " attempting to use the VF device.\n"); - } + err = ixgbe_enable_port_vlan(adapter, vf, vlan, qos); } else { - err = ixgbe_set_vf_vlan(adapter, false, - adapter->vfinfo[vf].pf_vlan, vf); - ixgbe_clear_vmvir(adapter, vf); - ixgbe_set_vmolr(hw, vf, true); - hw->mac.ops.set_vlan_anti_spoofing(hw, false, vf); - if (adapter->vfinfo[vf].vlan_count) - adapter->vfinfo[vf].vlan_count--; - adapter->vfinfo[vf].pf_vlan = 0; - adapter->vfinfo[vf].pf_qos = 0; + err = ixgbe_disable_port_vlan(adapter, vf); } + out: return err; } diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index dfd55d83bc03..64de20d1de56 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -77,6 +77,8 @@ /* VF Device IDs */ #define IXGBE_DEV_ID_82599_VF 0x10ED #define IXGBE_DEV_ID_X540_VF 0x1515 +#define IXGBE_DEV_ID_X550_VF 0x1565 +#define IXGBE_DEV_ID_X550EM_X_VF 0x15A8 /* General Registers */ #define IXGBE_CTRL 0x00000 @@ -84,7 +86,8 @@ #define IXGBE_CTRL_EXT 0x00018 #define IXGBE_ESDP 0x00020 #define IXGBE_EODSDP 0x00028 -#define IXGBE_I2CCTL 0x00028 +#define IXGBE_I2CCTL_BY_MAC(_hw)((((_hw)->mac.type >= ixgbe_mac_X550) ? \ + 0x15F5C : 0x00028)) #define IXGBE_LEDCTL 0x00200 #define IXGBE_FRTIMER 0x00048 #define IXGBE_TCPTIMER 0x0004C @@ -112,10 +115,14 @@ #define IXGBE_VPDDIAG1 0x10208 /* I2CCTL Bit Masks */ -#define IXGBE_I2C_CLK_IN 0x00000001 -#define IXGBE_I2C_CLK_OUT 0x00000002 -#define IXGBE_I2C_DATA_IN 0x00000004 -#define IXGBE_I2C_DATA_OUT 0x00000008 +#define IXGBE_I2C_CLK_IN_BY_MAC(_hw)(((_hw)->mac.type) >= ixgbe_mac_X550 ? \ + 0x00004000 : 0x00000001) +#define IXGBE_I2C_CLK_OUT_BY_MAC(_hw)(((_hw)->mac.type) >= ixgbe_mac_X550 ? \ + 0x00000200 : 0x00000002) +#define IXGBE_I2C_DATA_IN_BY_MAC(_hw)(((_hw)->mac.type) >= ixgbe_mac_X550 ? \ + 0x00001000 : 0x00000004) +#define IXGBE_I2C_DATA_OUT_BY_MAC(_hw)(((_hw)->mac.type) >= ixgbe_mac_X550 ? \ + 0x00000400 : 0x00000008) #define IXGBE_I2C_CLOCK_STRETCHING_TIMEOUT 500 #define IXGBE_I2C_THERMAL_SENSOR_ADDR 0xF8 @@ -292,6 +299,14 @@ struct ixgbe_thermal_sensor_data { #define IXGBE_RETA(_i) (0x05C00 + ((_i) * 4)) /* 32 of these (0-31) */ #define IXGBE_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* 10 of these (0-9) */ +/* Registers for setting up RSS on X550 with SRIOV + * _p - pool number (0..63) + * _i - index (0..10 for PFVFRSSRK, 0..15 for PFVFRETA) + */ +#define IXGBE_PFVFMRQC(_p) (0x03400 + ((_p) * 4)) +#define IXGBE_PFVFRSSRK(_i, _p) (0x018000 + ((_i) * 4) + ((_p) * 0x40)) +#define IXGBE_PFVFRETA(_i, _p) (0x019000 + ((_i) * 4) + ((_p) * 0x40)) + /* Flow Director registers */ #define IXGBE_FDIRCTRL 0x0EE00 #define IXGBE_FDIRHKEY 0x0EE68 @@ -798,6 +813,12 @@ struct ixgbe_thermal_sensor_data { #define IXGBE_PBACLR_82599 0x11068 #define IXGBE_CIAA_82599 0x11088 #define IXGBE_CIAD_82599 0x1108C +#define IXGBE_CIAA_X550 0x11508 +#define IXGBE_CIAD_X550 0x11510 +#define IXGBE_CIAA_BY_MAC(_hw) ((((_hw)->mac.type >= ixgbe_mac_X550) ? \ + IXGBE_CIAA_X550 : IXGBE_CIAA_82599)) +#define IXGBE_CIAD_BY_MAC(_hw) ((((_hw)->mac.type >= ixgbe_mac_X550) ? \ + IXGBE_CIAD_X550 : IXGBE_CIAD_82599)) #define IXGBE_PICAUSE 0x110B0 #define IXGBE_PIENA 0x110B8 #define IXGBE_CDQ_MBR_82599 0x110B4 @@ -1632,6 +1653,7 @@ enum { #define IXGBE_LINKS_TL_FAULT 0x00001000 #define IXGBE_LINKS_SIGNAL 0x00000F00 +#define IXGBE_LINKS_SPEED_NON_STD 0x08000000 #define IXGBE_LINKS_SPEED_82599 0x30000000 #define IXGBE_LINKS_SPEED_10G_82599 0x30000000 #define IXGBE_LINKS_SPEED_1G_82599 0x20000000 @@ -2000,6 +2022,7 @@ enum { /* Queue Drop Enable */ #define IXGBE_QDE_ENABLE 0x00000001 +#define IXGBE_QDE_HIDE_VLAN 0x00000002 #define IXGBE_QDE_IDX_MASK 0x00007F00 #define IXGBE_QDE_IDX_SHIFT 8 #define IXGBE_QDE_WRITE 0x00010000 @@ -2437,10 +2460,12 @@ struct ixgbe_adv_tx_context_desc { typedef u32 ixgbe_autoneg_advertised; /* Link speed */ typedef u32 ixgbe_link_speed; -#define IXGBE_LINK_SPEED_UNKNOWN 0 -#define IXGBE_LINK_SPEED_100_FULL 0x0008 -#define IXGBE_LINK_SPEED_1GB_FULL 0x0020 -#define IXGBE_LINK_SPEED_10GB_FULL 0x0080 +#define IXGBE_LINK_SPEED_UNKNOWN 0 +#define IXGBE_LINK_SPEED_100_FULL 0x0008 +#define IXGBE_LINK_SPEED_1GB_FULL 0x0020 +#define IXGBE_LINK_SPEED_2_5GB_FULL 0x0400 +#define IXGBE_LINK_SPEED_5GB_FULL 0x0800 +#define IXGBE_LINK_SPEED_10GB_FULL 0x0080 #define IXGBE_LINK_SPEED_82598_AUTONEG (IXGBE_LINK_SPEED_1GB_FULL | \ IXGBE_LINK_SPEED_10GB_FULL) #define IXGBE_LINK_SPEED_82599_AUTONEG (IXGBE_LINK_SPEED_100_FULL | \ @@ -2588,6 +2613,8 @@ enum ixgbe_mac_type { ixgbe_mac_82598EB, ixgbe_mac_82599EB, ixgbe_mac_X540, + ixgbe_mac_X550, + ixgbe_mac_X550EM_x, ixgbe_num_macs }; diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h index ba96cb5b886d..bb6726cbeb86 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h @@ -58,8 +58,9 @@ struct ixgbevf_tx_buffer { }; struct ixgbevf_rx_buffer { - struct sk_buff *skb; dma_addr_t dma; + struct page *page; + unsigned int page_offset; }; struct ixgbevf_stats { @@ -79,7 +80,6 @@ struct ixgbevf_tx_queue_stats { }; struct ixgbevf_rx_queue_stats { - u64 non_eop_descs; u64 alloc_rx_page_failed; u64 alloc_rx_buff_failed; u64 csum_err; @@ -92,9 +92,10 @@ struct ixgbevf_ring { void *desc; /* descriptor ring memory */ dma_addr_t dma; /* phys. address of descriptor ring */ unsigned int size; /* length in bytes */ - unsigned int count; /* amount of descriptors */ - unsigned int next_to_use; - unsigned int next_to_clean; + u16 count; /* amount of descriptors */ + u16 next_to_use; + u16 next_to_clean; + u16 next_to_alloc; union { struct ixgbevf_tx_buffer *tx_buffer_info; @@ -110,12 +111,11 @@ struct ixgbevf_ring { u64 hw_csum_rx_error; u8 __iomem *tail; + struct sk_buff *skb; u16 reg_idx; /* holds the special value that gets the hardware register * offset associated with this ring, which is different * for DCB and RSS modes */ - - u16 rx_buf_len; int queue_index; /* needed for multiqueue queue management */ }; @@ -134,12 +134,10 @@ struct ixgbevf_ring { /* Supported Rx Buffer Sizes */ #define IXGBEVF_RXBUFFER_256 256 /* Used for packet split */ -#define IXGBEVF_RXBUFFER_2K 2048 -#define IXGBEVF_RXBUFFER_4K 4096 -#define IXGBEVF_RXBUFFER_8K 8192 -#define IXGBEVF_RXBUFFER_10K 10240 +#define IXGBEVF_RXBUFFER_2048 2048 #define IXGBEVF_RX_HDR_SIZE IXGBEVF_RXBUFFER_256 +#define IXGBEVF_RX_BUFSZ IXGBEVF_RXBUFFER_2048 #define MAXIMUM_ETHERNET_VLAN_SIZE (VLAN_ETH_FRAME_LEN + ETH_FCS_LEN) @@ -307,6 +305,13 @@ static inline bool ixgbevf_qv_disable(struct ixgbevf_q_vector *q_vector) ((_eitr) ? (1000000000 / ((_eitr) * 256)) : 8) #define EITR_REG_TO_INTS_PER_SEC EITR_INTS_PER_SEC_TO_REG +/* ixgbevf_test_staterr - tests bits in Rx descriptor status and error fields */ +static inline __le32 ixgbevf_test_staterr(union ixgbe_adv_rx_desc *rx_desc, + const u32 stat_err_bits) +{ + return rx_desc->wb.upper.status_error & cpu_to_le32(stat_err_bits); +} + static inline u16 ixgbevf_desc_unused(struct ixgbevf_ring *ring) { u16 ntc = ring->next_to_clean; @@ -339,8 +344,10 @@ static inline void ixgbevf_write_tail(struct ixgbevf_ring *ring, u32 value) /* board specific private data structure */ struct ixgbevf_adapter { - struct timer_list watchdog_timer; + /* this field must be first, see ixgbevf_process_skb_fields */ unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; + + struct timer_list watchdog_timer; struct work_struct reset_task; struct ixgbevf_q_vector *q_vector[MAX_MSIX_Q_VECTORS]; @@ -363,7 +370,6 @@ struct ixgbevf_adapter { struct ixgbevf_ring *rx_ring[MAX_TX_QUEUES]; /* One per active queue */ u64 hw_csum_rx_error; u64 hw_rx_no_dma_resources; - u64 non_eop_descs; int num_msix_vectors; u32 alloc_rx_page_failed; u32 alloc_rx_buff_failed; @@ -373,7 +379,7 @@ struct ixgbevf_adapter { */ u32 flags; #define IXGBE_FLAG_IN_WATCHDOG_TASK (u32)(1) -#define IXGBE_FLAG_IN_NETPOLL (u32)(1 << 1) + #define IXGBEVF_FLAG_QUEUE_RESET_REQUESTED (u32)(1 << 2) struct msix_entry *msix_entries; @@ -423,11 +429,6 @@ enum ixbgevf_state_t { __IXGBEVF_WORK_INIT, }; -struct ixgbevf_cb { - struct sk_buff *prev; -}; -#define IXGBE_CB(skb) ((struct ixgbevf_cb *)(skb)->cb) - enum ixgbevf_boards { board_82599_vf, board_X540_vf, diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index 030a219c85e3..755f71f07ae1 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -143,21 +143,6 @@ u32 ixgbevf_read_reg(struct ixgbe_hw *hw, u32 reg) return value; } -static inline void ixgbevf_release_rx_desc(struct ixgbevf_ring *rx_ring, - u32 val) -{ - rx_ring->next_to_use = val; - - /* - * Force memory writes to complete before letting h/w - * know there are new descriptors to fetch. (Only - * applicable for weak-ordered memory model archs, - * such as IA-64). - */ - wmb(); - ixgbevf_write_tail(rx_ring, val); -} - /** * ixgbevf_set_ivar - set IVAR registers - maps interrupt causes to vectors * @adapter: pointer to adapter struct @@ -343,39 +328,12 @@ static bool ixgbevf_clean_tx_irq(struct ixgbevf_q_vector *q_vector, } /** - * ixgbevf_receive_skb - Send a completed packet up the stack - * @q_vector: structure containing interrupt and ring information - * @skb: packet to send up - * @status: hardware indication of status of receive - * @rx_desc: rx descriptor - **/ -static void ixgbevf_receive_skb(struct ixgbevf_q_vector *q_vector, - struct sk_buff *skb, u8 status, - union ixgbe_adv_rx_desc *rx_desc) -{ - struct ixgbevf_adapter *adapter = q_vector->adapter; - bool is_vlan = (status & IXGBE_RXD_STAT_VP); - u16 tag = le16_to_cpu(rx_desc->wb.upper.vlan); - - if (is_vlan && test_bit(tag & VLAN_VID_MASK, adapter->active_vlans)) - __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), tag); - - if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) - napi_gro_receive(&q_vector->napi, skb); - else - netif_rx(skb); -} - -/** * ixgbevf_rx_skb - Helper function to determine proper Rx method * @q_vector: structure containing interrupt and ring information * @skb: packet to send up - * @status: hardware indication of status of receive - * @rx_desc: rx descriptor **/ static void ixgbevf_rx_skb(struct ixgbevf_q_vector *q_vector, - struct sk_buff *skb, u8 status, - union ixgbe_adv_rx_desc *rx_desc) + struct sk_buff *skb) { #ifdef CONFIG_NET_RX_BUSY_POLL skb_mark_napi_id(skb, &q_vector->napi); @@ -387,17 +345,17 @@ static void ixgbevf_rx_skb(struct ixgbevf_q_vector *q_vector, } #endif /* CONFIG_NET_RX_BUSY_POLL */ - ixgbevf_receive_skb(q_vector, skb, status, rx_desc); + napi_gro_receive(&q_vector->napi, skb); } -/** - * ixgbevf_rx_checksum - indicate in skb if hw indicated a good cksum - * @ring: pointer to Rx descriptor ring structure - * @status_err: hardware indication of status of receive +/* ixgbevf_rx_checksum - indicate in skb if hw indicated a good cksum + * @ring: structure containig ring specific data + * @rx_desc: current Rx descriptor being processed * @skb: skb currently being received and modified - **/ + */ static inline void ixgbevf_rx_checksum(struct ixgbevf_ring *ring, - u32 status_err, struct sk_buff *skb) + union ixgbe_adv_rx_desc *rx_desc, + struct sk_buff *skb) { skb_checksum_none_assert(skb); @@ -406,16 +364,16 @@ static inline void ixgbevf_rx_checksum(struct ixgbevf_ring *ring, return; /* if IP and error */ - if ((status_err & IXGBE_RXD_STAT_IPCS) && - (status_err & IXGBE_RXDADV_ERR_IPE)) { + if (ixgbevf_test_staterr(rx_desc, IXGBE_RXD_STAT_IPCS) && + ixgbevf_test_staterr(rx_desc, IXGBE_RXDADV_ERR_IPE)) { ring->rx_stats.csum_err++; return; } - if (!(status_err & IXGBE_RXD_STAT_L4CS)) + if (!ixgbevf_test_staterr(rx_desc, IXGBE_RXD_STAT_L4CS)) return; - if (status_err & IXGBE_RXDADV_ERR_TCPE) { + if (ixgbevf_test_staterr(rx_desc, IXGBE_RXDADV_ERR_TCPE)) { ring->rx_stats.csum_err++; return; } @@ -424,52 +382,413 @@ static inline void ixgbevf_rx_checksum(struct ixgbevf_ring *ring, skb->ip_summed = CHECKSUM_UNNECESSARY; } +/* ixgbevf_process_skb_fields - Populate skb header fields from Rx descriptor + * @rx_ring: rx descriptor ring packet is being transacted on + * @rx_desc: pointer to the EOP Rx descriptor + * @skb: pointer to current skb being populated + * + * This function checks the ring, descriptor, and packet information in + * order to populate the checksum, VLAN, protocol, and other fields within + * the skb. + */ +static void ixgbevf_process_skb_fields(struct ixgbevf_ring *rx_ring, + union ixgbe_adv_rx_desc *rx_desc, + struct sk_buff *skb) +{ + ixgbevf_rx_checksum(rx_ring, rx_desc, skb); + + if (ixgbevf_test_staterr(rx_desc, IXGBE_RXD_STAT_VP)) { + u16 vid = le16_to_cpu(rx_desc->wb.upper.vlan); + unsigned long *active_vlans = netdev_priv(rx_ring->netdev); + + if (test_bit(vid & VLAN_VID_MASK, active_vlans)) + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid); + } + + skb->protocol = eth_type_trans(skb, rx_ring->netdev); +} + +/** + * ixgbevf_is_non_eop - process handling of non-EOP buffers + * @rx_ring: Rx ring being processed + * @rx_desc: Rx descriptor for current buffer + * @skb: current socket buffer containing buffer in progress + * + * This function updates next to clean. If the buffer is an EOP buffer + * this function exits returning false, otherwise it will place the + * sk_buff in the next buffer to be chained and return true indicating + * that this is in fact a non-EOP buffer. + **/ +static bool ixgbevf_is_non_eop(struct ixgbevf_ring *rx_ring, + union ixgbe_adv_rx_desc *rx_desc) +{ + u32 ntc = rx_ring->next_to_clean + 1; + + /* fetch, update, and store next to clean */ + ntc = (ntc < rx_ring->count) ? ntc : 0; + rx_ring->next_to_clean = ntc; + + prefetch(IXGBEVF_RX_DESC(rx_ring, ntc)); + + if (likely(ixgbevf_test_staterr(rx_desc, IXGBE_RXD_STAT_EOP))) + return false; + + return true; +} + +static bool ixgbevf_alloc_mapped_page(struct ixgbevf_ring *rx_ring, + struct ixgbevf_rx_buffer *bi) +{ + struct page *page = bi->page; + dma_addr_t dma = bi->dma; + + /* since we are recycling buffers we should seldom need to alloc */ + if (likely(page)) + return true; + + /* alloc new page for storage */ + page = dev_alloc_page(); + if (unlikely(!page)) { + rx_ring->rx_stats.alloc_rx_page_failed++; + return false; + } + + /* map page for use */ + dma = dma_map_page(rx_ring->dev, page, 0, + PAGE_SIZE, DMA_FROM_DEVICE); + + /* if mapping failed free memory back to system since + * there isn't much point in holding memory we can't use + */ + if (dma_mapping_error(rx_ring->dev, dma)) { + __free_page(page); + + rx_ring->rx_stats.alloc_rx_buff_failed++; + return false; + } + + bi->dma = dma; + bi->page = page; + bi->page_offset = 0; + + return true; +} + /** * ixgbevf_alloc_rx_buffers - Replace used receive buffers; packet split * @rx_ring: rx descriptor ring (for a specific queue) to setup buffers on + * @cleaned_count: number of buffers to replace **/ static void ixgbevf_alloc_rx_buffers(struct ixgbevf_ring *rx_ring, - int cleaned_count) + u16 cleaned_count) { union ixgbe_adv_rx_desc *rx_desc; struct ixgbevf_rx_buffer *bi; unsigned int i = rx_ring->next_to_use; - while (cleaned_count--) { - rx_desc = IXGBEVF_RX_DESC(rx_ring, i); - bi = &rx_ring->rx_buffer_info[i]; + /* nothing to do or no valid netdev defined */ + if (!cleaned_count || !rx_ring->netdev) + return; - if (!bi->skb) { - struct sk_buff *skb; + rx_desc = IXGBEVF_RX_DESC(rx_ring, i); + bi = &rx_ring->rx_buffer_info[i]; + i -= rx_ring->count; - skb = netdev_alloc_skb_ip_align(rx_ring->netdev, - rx_ring->rx_buf_len); - if (!skb) - goto no_buffers; + do { + if (!ixgbevf_alloc_mapped_page(rx_ring, bi)) + break; - bi->skb = skb; + /* Refresh the desc even if pkt_addr didn't change + * because each write-back erases this info. + */ + rx_desc->read.pkt_addr = cpu_to_le64(bi->dma + bi->page_offset); - bi->dma = dma_map_single(rx_ring->dev, skb->data, - rx_ring->rx_buf_len, - DMA_FROM_DEVICE); - if (dma_mapping_error(rx_ring->dev, bi->dma)) { - dev_kfree_skb(skb); - bi->skb = NULL; - dev_err(rx_ring->dev, "Rx DMA map failed\n"); - break; - } + rx_desc++; + bi++; + i++; + if (unlikely(!i)) { + rx_desc = IXGBEVF_RX_DESC(rx_ring, 0); + bi = rx_ring->rx_buffer_info; + i -= rx_ring->count; } - rx_desc->read.pkt_addr = cpu_to_le64(bi->dma); - i++; - if (i == rx_ring->count) - i = 0; + /* clear the hdr_addr for the next_to_use descriptor */ + rx_desc->read.hdr_addr = 0; + + cleaned_count--; + } while (cleaned_count); + + i += rx_ring->count; + + if (rx_ring->next_to_use != i) { + /* record the next descriptor to use */ + rx_ring->next_to_use = i; + + /* update next to alloc since we have filled the ring */ + rx_ring->next_to_alloc = i; + + /* Force memory writes to complete before letting h/w + * know there are new descriptors to fetch. (Only + * applicable for weak-ordered memory model archs, + * such as IA-64). + */ + wmb(); + ixgbevf_write_tail(rx_ring, i); } +} -no_buffers: - rx_ring->rx_stats.alloc_rx_buff_failed++; - if (rx_ring->next_to_use != i) - ixgbevf_release_rx_desc(rx_ring, i); +/* ixgbevf_pull_tail - ixgbevf specific version of skb_pull_tail + * @rx_ring: rx descriptor ring packet is being transacted on + * @skb: pointer to current skb being adjusted + * + * This function is an ixgbevf specific version of __pskb_pull_tail. The + * main difference between this version and the original function is that + * this function can make several assumptions about the state of things + * that allow for significant optimizations versus the standard function. + * As a result we can do things like drop a frag and maintain an accurate + * truesize for the skb. + */ +static void ixgbevf_pull_tail(struct ixgbevf_ring *rx_ring, + struct sk_buff *skb) +{ + struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[0]; + unsigned char *va; + unsigned int pull_len; + + /* it is valid to use page_address instead of kmap since we are + * working with pages allocated out of the lomem pool per + * alloc_page(GFP_ATOMIC) + */ + va = skb_frag_address(frag); + + /* we need the header to contain the greater of either ETH_HLEN or + * 60 bytes if the skb->len is less than 60 for skb_pad. + */ + pull_len = eth_get_headlen(va, IXGBEVF_RX_HDR_SIZE); + + /* align pull length to size of long to optimize memcpy performance */ + skb_copy_to_linear_data(skb, va, ALIGN(pull_len, sizeof(long))); + + /* update all of the pointers */ + skb_frag_size_sub(frag, pull_len); + frag->page_offset += pull_len; + skb->data_len -= pull_len; + skb->tail += pull_len; +} + +/* ixgbevf_cleanup_headers - Correct corrupted or empty headers + * @rx_ring: rx descriptor ring packet is being transacted on + * @rx_desc: pointer to the EOP Rx descriptor + * @skb: pointer to current skb being fixed + * + * Check for corrupted packet headers caused by senders on the local L2 + * embedded NIC switch not setting up their Tx Descriptors right. These + * should be very rare. + * + * Also address the case where we are pulling data in on pages only + * and as such no data is present in the skb header. + * + * In addition if skb is not at least 60 bytes we need to pad it so that + * it is large enough to qualify as a valid Ethernet frame. + * + * Returns true if an error was encountered and skb was freed. + */ +static bool ixgbevf_cleanup_headers(struct ixgbevf_ring *rx_ring, + union ixgbe_adv_rx_desc *rx_desc, + struct sk_buff *skb) +{ + /* verify that the packet does not have any known errors */ + if (unlikely(ixgbevf_test_staterr(rx_desc, + IXGBE_RXDADV_ERR_FRAME_ERR_MASK))) { + struct net_device *netdev = rx_ring->netdev; + + if (!(netdev->features & NETIF_F_RXALL)) { + dev_kfree_skb_any(skb); + return true; + } + } + + /* place header in linear portion of buffer */ + if (skb_is_nonlinear(skb)) + ixgbevf_pull_tail(rx_ring, skb); + + /* if skb_pad returns an error the skb was freed */ + if (unlikely(skb->len < 60)) { + int pad_len = 60 - skb->len; + + if (skb_pad(skb, pad_len)) + return true; + __skb_put(skb, pad_len); + } + + return false; +} + +/* ixgbevf_reuse_rx_page - page flip buffer and store it back on the ring + * @rx_ring: rx descriptor ring to store buffers on + * @old_buff: donor buffer to have page reused + * + * Synchronizes page for reuse by the adapter + */ +static void ixgbevf_reuse_rx_page(struct ixgbevf_ring *rx_ring, + struct ixgbevf_rx_buffer *old_buff) +{ + struct ixgbevf_rx_buffer *new_buff; + u16 nta = rx_ring->next_to_alloc; + + new_buff = &rx_ring->rx_buffer_info[nta]; + + /* update, and store next to alloc */ + nta++; + rx_ring->next_to_alloc = (nta < rx_ring->count) ? nta : 0; + + /* transfer page from old buffer to new buffer */ + new_buff->page = old_buff->page; + new_buff->dma = old_buff->dma; + new_buff->page_offset = old_buff->page_offset; + + /* sync the buffer for use by the device */ + dma_sync_single_range_for_device(rx_ring->dev, new_buff->dma, + new_buff->page_offset, + IXGBEVF_RX_BUFSZ, + DMA_FROM_DEVICE); +} + +static inline bool ixgbevf_page_is_reserved(struct page *page) +{ + return (page_to_nid(page) != numa_mem_id()) || page->pfmemalloc; +} + +/* ixgbevf_add_rx_frag - Add contents of Rx buffer to sk_buff + * @rx_ring: rx descriptor ring to transact packets on + * @rx_buffer: buffer containing page to add + * @rx_desc: descriptor containing length of buffer written by hardware + * @skb: sk_buff to place the data into + * + * This function will add the data contained in rx_buffer->page to the skb. + * This is done either through a direct copy if the data in the buffer is + * less than the skb header size, otherwise it will just attach the page as + * a frag to the skb. + * + * The function will then update the page offset if necessary and return + * true if the buffer can be reused by the adapter. + */ +static bool ixgbevf_add_rx_frag(struct ixgbevf_ring *rx_ring, + struct ixgbevf_rx_buffer *rx_buffer, + union ixgbe_adv_rx_desc *rx_desc, + struct sk_buff *skb) +{ + struct page *page = rx_buffer->page; + unsigned int size = le16_to_cpu(rx_desc->wb.upper.length); +#if (PAGE_SIZE < 8192) + unsigned int truesize = IXGBEVF_RX_BUFSZ; +#else + unsigned int truesize = ALIGN(size, L1_CACHE_BYTES); +#endif + + if ((size <= IXGBEVF_RX_HDR_SIZE) && !skb_is_nonlinear(skb)) { + unsigned char *va = page_address(page) + rx_buffer->page_offset; + + memcpy(__skb_put(skb, size), va, ALIGN(size, sizeof(long))); + + /* page is not reserved, we can reuse buffer as is */ + if (likely(!ixgbevf_page_is_reserved(page))) + return true; + + /* this page cannot be reused so discard it */ + put_page(page); + return false; + } + + skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, + rx_buffer->page_offset, size, truesize); + + /* avoid re-using remote pages */ + if (unlikely(ixgbevf_page_is_reserved(page))) + return false; + +#if (PAGE_SIZE < 8192) + /* if we are only owner of page we can reuse it */ + if (unlikely(page_count(page) != 1)) + return false; + + /* flip page offset to other buffer */ + rx_buffer->page_offset ^= IXGBEVF_RX_BUFSZ; + +#else + /* move offset up to the next cache line */ + rx_buffer->page_offset += truesize; + + if (rx_buffer->page_offset > (PAGE_SIZE - IXGBEVF_RX_BUFSZ)) + return false; + +#endif + /* Even if we own the page, we are not allowed to use atomic_set() + * This would break get_page_unless_zero() users. + */ + atomic_inc(&page->_count); + + return true; +} + +static struct sk_buff *ixgbevf_fetch_rx_buffer(struct ixgbevf_ring *rx_ring, + union ixgbe_adv_rx_desc *rx_desc, + struct sk_buff *skb) +{ + struct ixgbevf_rx_buffer *rx_buffer; + struct page *page; + + rx_buffer = &rx_ring->rx_buffer_info[rx_ring->next_to_clean]; + page = rx_buffer->page; + prefetchw(page); + + if (likely(!skb)) { + void *page_addr = page_address(page) + + rx_buffer->page_offset; + + /* prefetch first cache line of first page */ + prefetch(page_addr); +#if L1_CACHE_BYTES < 128 + prefetch(page_addr + L1_CACHE_BYTES); +#endif + + /* allocate a skb to store the frags */ + skb = netdev_alloc_skb_ip_align(rx_ring->netdev, + IXGBEVF_RX_HDR_SIZE); + if (unlikely(!skb)) { + rx_ring->rx_stats.alloc_rx_buff_failed++; + return NULL; + } + + /* we will be copying header into skb->data in + * pskb_may_pull so it is in our interest to prefetch + * it now to avoid a possible cache miss + */ + prefetchw(skb->data); + } + + /* we are reusing so sync this buffer for CPU use */ + dma_sync_single_range_for_cpu(rx_ring->dev, + rx_buffer->dma, + rx_buffer->page_offset, + IXGBEVF_RX_BUFSZ, + DMA_FROM_DEVICE); + + /* pull page into skb */ + if (ixgbevf_add_rx_frag(rx_ring, rx_buffer, rx_desc, skb)) { + /* hand second half of page back to the ring */ + ixgbevf_reuse_rx_page(rx_ring, rx_buffer); + } else { + /* we are not reusing the buffer so unmap it */ + dma_unmap_page(rx_ring->dev, rx_buffer->dma, + PAGE_SIZE, DMA_FROM_DEVICE); + } + + /* clear contents of buffer_info */ + rx_buffer->dma = 0; + rx_buffer->page = NULL; + + return skb; } static inline void ixgbevf_irq_enable_queues(struct ixgbevf_adapter *adapter, @@ -484,78 +803,51 @@ static int ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector, struct ixgbevf_ring *rx_ring, int budget) { - union ixgbe_adv_rx_desc *rx_desc, *next_rxd; - struct ixgbevf_rx_buffer *rx_buffer_info, *next_buffer; - struct sk_buff *skb; - unsigned int i; - u32 len, staterr; - int cleaned_count = 0; unsigned int total_rx_bytes = 0, total_rx_packets = 0; + u16 cleaned_count = ixgbevf_desc_unused(rx_ring); + struct sk_buff *skb = rx_ring->skb; - i = rx_ring->next_to_clean; - rx_desc = IXGBEVF_RX_DESC(rx_ring, i); - staterr = le32_to_cpu(rx_desc->wb.upper.status_error); - rx_buffer_info = &rx_ring->rx_buffer_info[i]; + while (likely(total_rx_packets < budget)) { + union ixgbe_adv_rx_desc *rx_desc; - while (staterr & IXGBE_RXD_STAT_DD) { - if (!budget) - break; - budget--; + /* return some buffers to hardware, one at a time is too slow */ + if (cleaned_count >= IXGBEVF_RX_BUFFER_WRITE) { + ixgbevf_alloc_rx_buffers(rx_ring, cleaned_count); + cleaned_count = 0; + } - rmb(); /* read descriptor and rx_buffer_info after status DD */ - len = le16_to_cpu(rx_desc->wb.upper.length); - skb = rx_buffer_info->skb; - prefetch(skb->data - NET_IP_ALIGN); - rx_buffer_info->skb = NULL; + rx_desc = IXGBEVF_RX_DESC(rx_ring, rx_ring->next_to_clean); - if (rx_buffer_info->dma) { - dma_unmap_single(rx_ring->dev, rx_buffer_info->dma, - rx_ring->rx_buf_len, - DMA_FROM_DEVICE); - rx_buffer_info->dma = 0; - skb_put(skb, len); - } + if (!ixgbevf_test_staterr(rx_desc, IXGBE_RXD_STAT_DD)) + break; - i++; - if (i == rx_ring->count) - i = 0; + /* This memory barrier is needed to keep us from reading + * any other fields out of the rx_desc until we know the + * RXD_STAT_DD bit is set + */ + rmb(); - next_rxd = IXGBEVF_RX_DESC(rx_ring, i); - prefetch(next_rxd); - cleaned_count++; + /* retrieve a buffer from the ring */ + skb = ixgbevf_fetch_rx_buffer(rx_ring, rx_desc, skb); - next_buffer = &rx_ring->rx_buffer_info[i]; + /* exit if we failed to retrieve a buffer */ + if (!skb) + break; - if (!(staterr & IXGBE_RXD_STAT_EOP)) { - skb->next = next_buffer->skb; - IXGBE_CB(skb->next)->prev = skb; - rx_ring->rx_stats.non_eop_descs++; - goto next_desc; - } + cleaned_count++; - /* we should not be chaining buffers, if we did drop the skb */ - if (IXGBE_CB(skb)->prev) { - do { - struct sk_buff *this = skb; - skb = IXGBE_CB(skb)->prev; - dev_kfree_skb(this); - } while (skb); - goto next_desc; - } + /* fetch next buffer in frame if non-eop */ + if (ixgbevf_is_non_eop(rx_ring, rx_desc)) + continue; - /* ERR_MASK will only have valid bits if EOP set */ - if (unlikely(staterr & IXGBE_RXDADV_ERR_FRAME_ERR_MASK)) { - dev_kfree_skb_irq(skb); - goto next_desc; + /* verify the packet layout is correct */ + if (ixgbevf_cleanup_headers(rx_ring, rx_desc, skb)) { + skb = NULL; + continue; } - ixgbevf_rx_checksum(rx_ring, staterr, skb); - /* probably a little skewed due to removing CRC */ total_rx_bytes += skb->len; - total_rx_packets++; - - skb->protocol = eth_type_trans(skb, rx_ring->netdev); /* Workaround hardware that can't do proper VEPA multicast * source pruning. @@ -565,32 +857,23 @@ static int ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector, ether_addr_equal(rx_ring->netdev->dev_addr, eth_hdr(skb)->h_source)) { dev_kfree_skb_irq(skb); - goto next_desc; + continue; } - ixgbevf_rx_skb(q_vector, skb, staterr, rx_desc); + /* populate checksum, VLAN, and protocol */ + ixgbevf_process_skb_fields(rx_ring, rx_desc, skb); -next_desc: - rx_desc->wb.upper.status_error = 0; + ixgbevf_rx_skb(q_vector, skb); - /* return some buffers to hardware, one at a time is too slow */ - if (cleaned_count >= IXGBEVF_RX_BUFFER_WRITE) { - ixgbevf_alloc_rx_buffers(rx_ring, cleaned_count); - cleaned_count = 0; - } + /* reset skb pointer */ + skb = NULL; - /* use prefetched values */ - rx_desc = next_rxd; - rx_buffer_info = &rx_ring->rx_buffer_info[i]; - - staterr = le32_to_cpu(rx_desc->wb.upper.status_error); + /* update budget accounting */ + total_rx_packets++; } - rx_ring->next_to_clean = i; - cleaned_count = ixgbevf_desc_unused(rx_ring); - - if (cleaned_count) - ixgbevf_alloc_rx_buffers(rx_ring, cleaned_count); + /* place incomplete frames back on ring for completion */ + rx_ring->skb = skb; u64_stats_update_begin(&rx_ring->syncp); rx_ring->stats.packets += total_rx_packets; @@ -634,12 +917,10 @@ static int ixgbevf_poll(struct napi_struct *napi, int budget) else per_ring_budget = budget; - adapter->flags |= IXGBE_FLAG_IN_NETPOLL; ixgbevf_for_each_ring(ring, q_vector->rx) clean_complete &= (ixgbevf_clean_rx_irq(q_vector, ring, per_ring_budget) < per_ring_budget); - adapter->flags &= ~IXGBE_FLAG_IN_NETPOLL; #ifdef CONFIG_NET_RX_BUSY_POLL ixgbevf_qv_unlock_napi(q_vector); @@ -1229,19 +1510,15 @@ static void ixgbevf_configure_tx(struct ixgbevf_adapter *adapter) static void ixgbevf_configure_srrctl(struct ixgbevf_adapter *adapter, int index) { - struct ixgbevf_ring *rx_ring; struct ixgbe_hw *hw = &adapter->hw; u32 srrctl; - rx_ring = adapter->rx_ring[index]; - srrctl = IXGBE_SRRCTL_DROP_EN; + srrctl |= IXGBEVF_RX_HDR_SIZE << IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT; + srrctl |= IXGBEVF_RX_BUFSZ >> IXGBE_SRRCTL_BSIZEPKT_SHIFT; srrctl |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF; - srrctl |= ALIGN(rx_ring->rx_buf_len, 1024) >> - IXGBE_SRRCTL_BSIZEPKT_SHIFT; - IXGBE_WRITE_REG(hw, IXGBE_VFSRRCTL(index), srrctl); } @@ -1260,40 +1537,6 @@ static void ixgbevf_setup_psrtype(struct ixgbevf_adapter *adapter) IXGBE_WRITE_REG(hw, IXGBE_VFPSRTYPE, psrtype); } -static void ixgbevf_set_rx_buffer_len(struct ixgbevf_adapter *adapter) -{ - struct ixgbe_hw *hw = &adapter->hw; - struct net_device *netdev = adapter->netdev; - int max_frame = netdev->mtu + ETH_HLEN + ETH_FCS_LEN; - int i; - u16 rx_buf_len; - - /* notify the PF of our intent to use this size of frame */ - ixgbevf_rlpml_set_vf(hw, max_frame); - - /* PF will allow an extra 4 bytes past for vlan tagged frames */ - max_frame += VLAN_HLEN; - - /* - * Allocate buffer sizes that fit well into 32K and - * take into account max frame size of 9.5K - */ - if ((hw->mac.type == ixgbe_mac_X540_vf) && - (max_frame <= MAXIMUM_ETHERNET_VLAN_SIZE)) - rx_buf_len = MAXIMUM_ETHERNET_VLAN_SIZE; - else if (max_frame <= IXGBEVF_RXBUFFER_2K) - rx_buf_len = IXGBEVF_RXBUFFER_2K; - else if (max_frame <= IXGBEVF_RXBUFFER_4K) - rx_buf_len = IXGBEVF_RXBUFFER_4K; - else if (max_frame <= IXGBEVF_RXBUFFER_8K) - rx_buf_len = IXGBEVF_RXBUFFER_8K; - else - rx_buf_len = IXGBEVF_RXBUFFER_10K; - - for (i = 0; i < adapter->num_rx_queues; i++) - adapter->rx_ring[i]->rx_buf_len = rx_buf_len; -} - #define IXGBEVF_MAX_RX_DESC_POLL 10 static void ixgbevf_disable_rx_queue(struct ixgbevf_adapter *adapter, struct ixgbevf_ring *ring) @@ -1371,12 +1614,13 @@ static void ixgbevf_configure_rx_ring(struct ixgbevf_adapter *adapter, /* reset ntu and ntc to place SW in sync with hardwdare */ ring->next_to_clean = 0; ring->next_to_use = 0; + ring->next_to_alloc = 0; ixgbevf_configure_srrctl(adapter, reg_idx); - /* prevent DMA from exceeding buffer space available */ - rxdctl &= ~IXGBE_RXDCTL_RLPMLMASK; - rxdctl |= ring->rx_buf_len | IXGBE_RXDCTL_RLPML_EN; + /* allow any size packet since we can handle overflow */ + rxdctl &= ~IXGBE_RXDCTL_RLPML_EN; + rxdctl |= IXGBE_RXDCTL_ENABLE | IXGBE_RXDCTL_VME; IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(reg_idx), rxdctl); @@ -1393,11 +1637,13 @@ static void ixgbevf_configure_rx_ring(struct ixgbevf_adapter *adapter, static void ixgbevf_configure_rx(struct ixgbevf_adapter *adapter) { int i; + struct ixgbe_hw *hw = &adapter->hw; + struct net_device *netdev = adapter->netdev; ixgbevf_setup_psrtype(adapter); - /* set_rx_buffer_len must be called before ring initialization */ - ixgbevf_set_rx_buffer_len(adapter); + /* notify the PF of our intent to use this size of frame */ + ixgbevf_rlpml_set_vf(hw, netdev->mtu + ETH_HLEN + ETH_FCS_LEN); /* Setup the HW Rx Head and Tail Descriptor Pointers and * the Base and Length of the Rx Descriptor Ring */ @@ -1702,32 +1948,32 @@ void ixgbevf_up(struct ixgbevf_adapter *adapter) **/ static void ixgbevf_clean_rx_ring(struct ixgbevf_ring *rx_ring) { + struct device *dev = rx_ring->dev; unsigned long size; unsigned int i; + /* Free Rx ring sk_buff */ + if (rx_ring->skb) { + dev_kfree_skb(rx_ring->skb); + rx_ring->skb = NULL; + } + + /* ring already cleared, nothing to do */ if (!rx_ring->rx_buffer_info) return; - /* Free all the Rx ring sk_buffs */ + /* Free all the Rx ring pages */ for (i = 0; i < rx_ring->count; i++) { - struct ixgbevf_rx_buffer *rx_buffer_info; + struct ixgbevf_rx_buffer *rx_buffer; - rx_buffer_info = &rx_ring->rx_buffer_info[i]; - if (rx_buffer_info->dma) { - dma_unmap_single(rx_ring->dev, rx_buffer_info->dma, - rx_ring->rx_buf_len, - DMA_FROM_DEVICE); - rx_buffer_info->dma = 0; - } - if (rx_buffer_info->skb) { - struct sk_buff *skb = rx_buffer_info->skb; - rx_buffer_info->skb = NULL; - do { - struct sk_buff *this = skb; - skb = IXGBE_CB(skb)->prev; - dev_kfree_skb(this); - } while (skb); - } + rx_buffer = &rx_ring->rx_buffer_info[i]; + if (rx_buffer->dma) + dma_unmap_page(dev, rx_buffer->dma, + PAGE_SIZE, DMA_FROM_DEVICE); + rx_buffer->dma = 0; + if (rx_buffer->page) + __free_page(rx_buffer->page); + rx_buffer->page = NULL; } size = sizeof(struct ixgbevf_rx_buffer) * rx_ring->count; @@ -3274,6 +3520,7 @@ static int ixgbevf_set_mac(struct net_device *netdev, void *p) static int ixgbevf_change_mtu(struct net_device *netdev, int new_mtu) { struct ixgbevf_adapter *adapter = netdev_priv(netdev); + struct ixgbe_hw *hw = &adapter->hw; int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN; int max_possible_frame = MAXIMUM_ETHERNET_VLAN_SIZE; @@ -3291,17 +3538,35 @@ static int ixgbevf_change_mtu(struct net_device *netdev, int new_mtu) if ((new_mtu < 68) || (max_frame > max_possible_frame)) return -EINVAL; - hw_dbg(&adapter->hw, "changing MTU from %d to %d\n", + hw_dbg(hw, "changing MTU from %d to %d\n", netdev->mtu, new_mtu); /* must set new MTU before calling down or up */ netdev->mtu = new_mtu; - if (netif_running(netdev)) - ixgbevf_reinit_locked(adapter); + /* notify the PF of our intent to use this size of frame */ + ixgbevf_rlpml_set_vf(hw, max_frame); return 0; } +#ifdef CONFIG_NET_POLL_CONTROLLER +/* Polling 'interrupt' - used by things like netconsole to send skbs + * without having to re-enable interrupts. It's not called while + * the interrupt routine is executing. + */ +static void ixgbevf_netpoll(struct net_device *netdev) +{ + struct ixgbevf_adapter *adapter = netdev_priv(netdev); + int i; + + /* if interface is down do nothing */ + if (test_bit(__IXGBEVF_DOWN, &adapter->state)) + return; + for (i = 0; i < adapter->num_rx_queues; i++) + ixgbevf_msix_clean_rings(0, adapter->q_vector[i]); +} +#endif /* CONFIG_NET_POLL_CONTROLLER */ + static int ixgbevf_suspend(struct pci_dev *pdev, pm_message_t state) { struct net_device *netdev = pci_get_drvdata(pdev); @@ -3438,6 +3703,9 @@ static const struct net_device_ops ixgbevf_netdev_ops = { #ifdef CONFIG_NET_RX_BUSY_POLL .ndo_busy_poll = ixgbevf_busy_poll_recv, #endif +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = ixgbevf_netpoll, +#endif }; static void ixgbevf_assign_netdev_ops(struct net_device *dev) diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index ade067de1689..ccc3ce2e8c8c 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -2558,11 +2558,10 @@ static void mvneta_adjust_link(struct net_device *ndev) MVNETA_GMAC_FORCE_LINK_DOWN); mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); mvneta_port_up(pp); - netdev_info(pp->dev, "link up\n"); } else { mvneta_port_down(pp); - netdev_info(pp->dev, "link down\n"); } + phy_print_status(phydev); } } diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c index c3b209cd0660..38f7ceee77d2 100644 --- a/drivers/net/ethernet/marvell/pxa168_eth.c +++ b/drivers/net/ethernet/marvell/pxa168_eth.c @@ -106,6 +106,7 @@ #define SDMA_CMD_ERD (1 << 7) /* Bit definitions of the Port Config Reg */ +#define PCR_DUPLEX_FULL (1 << 15) #define PCR_HS (1 << 12) #define PCR_EN (1 << 7) #define PCR_PM (1 << 0) @@ -113,11 +114,17 @@ /* Bit definitions of the Port Config Extend Reg */ #define PCXR_2BSM (1 << 28) #define PCXR_DSCP_EN (1 << 21) +#define PCXR_RMII_EN (1 << 20) +#define PCXR_AN_SPEED_DIS (1 << 19) +#define PCXR_SPEED_100 (1 << 18) #define PCXR_MFL_1518 (0 << 14) #define PCXR_MFL_1536 (1 << 14) #define PCXR_MFL_2048 (2 << 14) #define PCXR_MFL_64K (3 << 14) +#define PCXR_FLOWCTL_DIS (1 << 12) #define PCXR_FLP (1 << 11) +#define PCXR_AN_FLOWCTL_DIS (1 << 10) +#define PCXR_AN_DUPLEX_DIS (1 << 9) #define PCXR_PRIO_TX_OFF 3 #define PCXR_TX_HIGH_PRI (7 << PCXR_PRIO_TX_OFF) @@ -170,7 +177,6 @@ #define LINK_UP (1 << 3) /* Bit definitions for work to be done */ -#define WORK_LINK (1 << 0) #define WORK_TX_DONE (1 << 1) /* @@ -197,6 +203,9 @@ struct tx_desc { struct pxa168_eth_private { int port_num; /* User Ethernet port number */ int phy_addr; + int phy_speed; + int phy_duplex; + phy_interface_t phy_intf; int rx_resource_err; /* Rx ring resource error flag */ @@ -269,11 +278,11 @@ enum hash_table_entry { static int pxa168_get_settings(struct net_device *dev, struct ethtool_cmd *cmd); static int pxa168_set_settings(struct net_device *dev, struct ethtool_cmd *cmd); static int pxa168_init_hw(struct pxa168_eth_private *pep); +static int pxa168_init_phy(struct net_device *dev); static void eth_port_reset(struct net_device *dev); static void eth_port_start(struct net_device *dev); static int pxa168_eth_open(struct net_device *dev); static int pxa168_eth_stop(struct net_device *dev); -static int ethernet_phy_setup(struct net_device *dev); static inline u32 rdl(struct pxa168_eth_private *pep, int offset) { @@ -305,26 +314,6 @@ static void abort_dma(struct pxa168_eth_private *pep) netdev_err(pep->dev, "%s : DMA Stuck\n", __func__); } -static int ethernet_phy_get(struct pxa168_eth_private *pep) -{ - unsigned int reg_data; - - reg_data = rdl(pep, PHY_ADDRESS); - - return (reg_data >> (5 * pep->port_num)) & 0x1f; -} - -static void ethernet_phy_set_addr(struct pxa168_eth_private *pep, int phy_addr) -{ - u32 reg_data; - int addr_shift = 5 * pep->port_num; - - reg_data = rdl(pep, PHY_ADDRESS); - reg_data &= ~(0x1f << addr_shift); - reg_data |= (phy_addr & 0x1f) << addr_shift; - wrl(pep, PHY_ADDRESS, reg_data); -} - static void rxq_refill(struct net_device *dev) { struct pxa168_eth_private *pep = netdev_priv(dev); @@ -655,14 +644,7 @@ static void eth_port_start(struct net_device *dev) struct pxa168_eth_private *pep = netdev_priv(dev); int tx_curr_desc, rx_curr_desc; - /* Perform PHY reset, if there is a PHY. */ - if (pep->phy != NULL) { - struct ethtool_cmd cmd; - - pxa168_get_settings(pep->dev, &cmd); - phy_init_hw(pep->phy); - pxa168_set_settings(pep->dev, &cmd); - } + phy_start(pep->phy); /* Assignment of Tx CTRP of given queue */ tx_curr_desc = pep->tx_curr_desc_q; @@ -717,6 +699,8 @@ static void eth_port_reset(struct net_device *dev) val = rdl(pep, PORT_CONFIG); val &= ~PCR_EN; wrl(pep, PORT_CONFIG, val); + + phy_stop(pep->phy); } /* @@ -884,43 +868,9 @@ static int pxa168_eth_collect_events(struct pxa168_eth_private *pep, } if (icr & ICR_RXBUF) ret = 1; - if (icr & ICR_MII_CH) { - pep->work_todo |= WORK_LINK; - ret = 1; - } return ret; } -static void handle_link_event(struct pxa168_eth_private *pep) -{ - struct net_device *dev = pep->dev; - u32 port_status; - int speed; - int duplex; - int fc; - - port_status = rdl(pep, PORT_STATUS); - if (!(port_status & LINK_UP)) { - if (netif_carrier_ok(dev)) { - netdev_info(dev, "link down\n"); - netif_carrier_off(dev); - txq_reclaim(dev, 1); - } - return; - } - if (port_status & PORT_SPEED_100) - speed = 100; - else - speed = 10; - - duplex = (port_status & FULL_DUPLEX) ? 1 : 0; - fc = (port_status & FLOW_CONTROL_DISABLED) ? 0 : 1; - netdev_info(dev, "link up, %d Mb/s, %s duplex, flow control %sabled\n", - speed, duplex ? "full" : "half", fc ? "en" : "dis"); - if (!netif_carrier_ok(dev)) - netif_carrier_on(dev); -} - static irqreturn_t pxa168_eth_int_handler(int irq, void *dev_id) { struct net_device *dev = (struct net_device *)dev_id; @@ -978,8 +928,11 @@ static int set_port_config_ext(struct pxa168_eth_private *pep) skb_size = PCXR_MFL_64K; /* Extended Port Configuration */ - wrl(pep, - PORT_CONFIG_EXT, PCXR_2BSM | /* Two byte prefix aligns IP hdr */ + wrl(pep, PORT_CONFIG_EXT, + PCXR_AN_SPEED_DIS | /* Disable HW AN */ + PCXR_AN_DUPLEX_DIS | + PCXR_AN_FLOWCTL_DIS | + PCXR_2BSM | /* Two byte prefix aligns IP hdr */ PCXR_DSCP_EN | /* Enable DSCP in IP */ skb_size | PCXR_FLP | /* do not force link pass */ PCXR_TX_HIGH_PRI); /* Transmit - high priority queue */ @@ -987,6 +940,69 @@ static int set_port_config_ext(struct pxa168_eth_private *pep) return 0; } +static void pxa168_eth_adjust_link(struct net_device *dev) +{ + struct pxa168_eth_private *pep = netdev_priv(dev); + struct phy_device *phy = pep->phy; + u32 cfg, cfg_o = rdl(pep, PORT_CONFIG); + u32 cfgext, cfgext_o = rdl(pep, PORT_CONFIG_EXT); + + cfg = cfg_o & ~PCR_DUPLEX_FULL; + cfgext = cfgext_o & ~(PCXR_SPEED_100 | PCXR_FLOWCTL_DIS | PCXR_RMII_EN); + + if (phy->interface == PHY_INTERFACE_MODE_RMII) + cfgext |= PCXR_RMII_EN; + if (phy->speed == SPEED_100) + cfgext |= PCXR_SPEED_100; + if (phy->duplex) + cfg |= PCR_DUPLEX_FULL; + if (!phy->pause) + cfgext |= PCXR_FLOWCTL_DIS; + + /* Bail out if there has nothing changed */ + if (cfg == cfg_o && cfgext == cfgext_o) + return; + + wrl(pep, PORT_CONFIG, cfg); + wrl(pep, PORT_CONFIG_EXT, cfgext); + + phy_print_status(phy); +} + +static int pxa168_init_phy(struct net_device *dev) +{ + struct pxa168_eth_private *pep = netdev_priv(dev); + struct ethtool_cmd cmd; + int err; + + if (pep->phy) + return 0; + + pep->phy = mdiobus_scan(pep->smi_bus, pep->phy_addr); + if (!pep->phy) + return -ENODEV; + + err = phy_connect_direct(dev, pep->phy, pxa168_eth_adjust_link, + pep->phy_intf); + if (err) + return err; + + err = pxa168_get_settings(dev, &cmd); + if (err) + return err; + + cmd.phy_address = pep->phy_addr; + cmd.speed = pep->phy_speed; + cmd.duplex = pep->phy_duplex; + cmd.advertising = PHY_BASIC_FEATURES; + cmd.autoneg = AUTONEG_ENABLE; + + if (cmd.speed != 0) + cmd.autoneg = AUTONEG_DISABLE; + + return pxa168_set_settings(dev, &cmd); +} + static int pxa168_init_hw(struct pxa168_eth_private *pep) { int err = 0; @@ -1133,6 +1149,10 @@ static int pxa168_eth_open(struct net_device *dev) struct pxa168_eth_private *pep = netdev_priv(dev); int err; + err = pxa168_init_phy(dev); + if (err) + return err; + err = request_irq(dev->irq, pxa168_eth_int_handler, 0, dev->name, dev); if (err) { dev_err(&dev->dev, "can't assign irq\n"); @@ -1231,10 +1251,6 @@ static int pxa168_rx_poll(struct napi_struct *napi, int budget) struct net_device *dev = pep->dev; int work_done = 0; - if (unlikely(pep->work_todo & WORK_LINK)) { - pep->work_todo &= ~(WORK_LINK); - handle_link_event(pep); - } /* * We call txq_reclaim every time since in NAPI interupts are disabled * and due to this we miss the TX_DONE interrupt,which is not updated in @@ -1357,77 +1373,6 @@ static int pxa168_eth_do_ioctl(struct net_device *dev, struct ifreq *ifr, return -EOPNOTSUPP; } -static struct phy_device *phy_scan(struct pxa168_eth_private *pep, int phy_addr) -{ - struct mii_bus *bus = pep->smi_bus; - struct phy_device *phydev; - int start; - int num; - int i; - - if (phy_addr == PXA168_ETH_PHY_ADDR_DEFAULT) { - /* Scan entire range */ - start = ethernet_phy_get(pep); - num = 32; - } else { - /* Use phy addr specific to platform */ - start = phy_addr & 0x1f; - num = 1; - } - phydev = NULL; - for (i = 0; i < num; i++) { - int addr = (start + i) & 0x1f; - if (bus->phy_map[addr] == NULL) - mdiobus_scan(bus, addr); - - if (phydev == NULL) { - phydev = bus->phy_map[addr]; - if (phydev != NULL) - ethernet_phy_set_addr(pep, addr); - } - } - - return phydev; -} - -static void phy_init(struct pxa168_eth_private *pep) -{ - struct phy_device *phy = pep->phy; - - phy_attach(pep->dev, dev_name(&phy->dev), PHY_INTERFACE_MODE_MII); - - if (pep->pd && pep->pd->speed != 0) { - phy->autoneg = AUTONEG_DISABLE; - phy->advertising = 0; - phy->speed = pep->pd->speed; - phy->duplex = pep->pd->duplex; - } else { - phy->autoneg = AUTONEG_ENABLE; - phy->speed = 0; - phy->duplex = 0; - phy->supported &= PHY_BASIC_FEATURES; - phy->advertising = phy->supported | ADVERTISED_Autoneg; - } - - phy_start_aneg(phy); -} - -static int ethernet_phy_setup(struct net_device *dev) -{ - struct pxa168_eth_private *pep = netdev_priv(dev); - - if (pep->pd && pep->pd->init) - pep->pd->init(); - - pep->phy = phy_scan(pep, pep->phy_addr & 0x1f); - if (pep->phy != NULL) - phy_init(pep); - - update_hash_table_mac_address(pep, NULL, dev->dev_addr); - - return 0; -} - static int pxa168_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct pxa168_eth_private *pep = netdev_priv(dev); @@ -1505,16 +1450,14 @@ static int pxa168_eth_probe(struct platform_device *pdev) pep = netdev_priv(dev); pep->dev = dev; pep->clk = clk; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res == NULL) { - err = -ENODEV; - goto err_netdev; - } pep->base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(pep->base)) { err = -ENOMEM; goto err_netdev; } + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); BUG_ON(!res); dev->irq = res->start; @@ -1552,13 +1495,23 @@ static int pxa168_eth_probe(struct platform_device *pdev) pep->port_num = pep->pd->port_number; pep->phy_addr = pep->pd->phy_addr; + pep->phy_speed = pep->pd->speed; + pep->phy_duplex = pep->pd->duplex; + pep->phy_intf = pep->pd->intf; + + if (pep->pd->init) + pep->pd->init(); } else if (pdev->dev.of_node) { of_property_read_u32(pdev->dev.of_node, "port-id", &pep->port_num); np = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0); - if (np) - of_property_read_u32(np, "reg", &pep->phy_addr); + if (!np) { + dev_err(&pdev->dev, "missing phy-handle\n"); + return -EINVAL; + } + of_property_read_u32(np, "reg", &pep->phy_addr); + pep->phy_intf = of_get_phy_mode(pdev->dev.of_node); } /* Hardware supports only 3 ports */ @@ -1587,11 +1540,8 @@ static int pxa168_eth_probe(struct platform_device *pdev) if (err) goto err_free_mdio; - pxa168_init_hw(pep); - err = ethernet_phy_setup(dev); - if (err) - goto err_mdiobus; SET_NETDEV_DEV(dev, &pdev->dev); + pxa168_init_hw(pep); err = register_netdev(dev); if (err) goto err_mdiobus; @@ -1621,13 +1571,13 @@ static int pxa168_eth_remove(struct platform_device *pdev) pep->htpr, pep->htpr_dma); pep->htpr = NULL; } + if (pep->phy) + phy_disconnect(pep->phy); if (pep->clk) { clk_disable(pep->clk); clk_put(pep->clk); pep->clk = NULL; } - if (pep->phy != NULL) - phy_detach(pep->phy); iounmap(pep->base); pep->base = NULL; diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index bd3366267039..f8ab220bd72c 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c @@ -1290,14 +1290,6 @@ static void rx_set_checksum(struct sky2_port *sky2) ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM); } -/* - * Fixed initial key as seed to RSS. - */ -static const uint32_t rss_init_key[10] = { - 0x7c3351da, 0x51c5cf4e, 0x44adbdd1, 0xe8d38d18, 0x48897c43, - 0xb1d60e7e, 0x6a3dd760, 0x01a2e453, 0x16f46f13, 0x1a0e7b30 -}; - /* Enable/disable receive hash calculation (RSS) */ static void rx_set_rss(struct net_device *dev, netdev_features_t features) { @@ -1313,9 +1305,12 @@ static void rx_set_rss(struct net_device *dev, netdev_features_t features) /* Program RSS initial values */ if (features & NETIF_F_RXHASH) { + u32 rss_key[10]; + + netdev_rss_key_fill(rss_key, sizeof(rss_key)); for (i = 0; i < nkeys; i++) sky2_write32(hw, SK_REG(sky2->port, RSS_KEY + i * 4), - rss_init_key[i]); + rss_key[i]); /* Need to turn on (undocumented) flag to make hashing work */ sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), @@ -1366,7 +1361,9 @@ static void sky2_rx_clean(struct sky2_port *sky2) { unsigned i; - memset(sky2->rx_le, 0, RX_LE_BYTES); + if (sky2->rx_le) + memset(sky2->rx_le, 0, RX_LE_BYTES); + for (i = 0; i < sky2->rx_pending; i++) { struct rx_ring_info *re = sky2->rx_ring + i; diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c index b16e1b95566f..5c93d1451c44 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c @@ -990,11 +990,11 @@ static struct mlx4_cmd_info cmd_info[] = { { .opcode = MLX4_CMD_CONFIG_DEV, .has_inbox = false, - .has_outbox = false, + .has_outbox = true, .out_is_imm = false, .encode_slave_id = false, .verify = NULL, - .wrapper = mlx4_CMD_EPERM_wrapper + .wrapper = mlx4_CONFIG_DEV_wrapper }, { .opcode = MLX4_CMD_ALLOC_RES, @@ -1338,6 +1338,15 @@ static struct mlx4_cmd_info cmd_info[] = { .verify = NULL, .wrapper = mlx4_QUERY_IF_STAT_wrapper }, + { + .opcode = MLX4_CMD_ACCESS_REG, + .has_inbox = true, + .has_outbox = true, + .out_is_imm = false, + .encode_slave_id = false, + .verify = NULL, + .wrapper = mlx4_ACCESS_REG_wrapper, + }, /* Native multicast commands are not available for guests */ { .opcode = MLX4_CMD_QP_ATTACH, @@ -2108,50 +2117,52 @@ err_vhcr: int mlx4_cmd_init(struct mlx4_dev *dev) { struct mlx4_priv *priv = mlx4_priv(dev); + int flags = 0; + + if (!priv->cmd.initialized) { + mutex_init(&priv->cmd.hcr_mutex); + mutex_init(&priv->cmd.slave_cmd_mutex); + sema_init(&priv->cmd.poll_sem, 1); + priv->cmd.use_events = 0; + priv->cmd.toggle = 1; + priv->cmd.initialized = 1; + flags |= MLX4_CMD_CLEANUP_STRUCT; + } - mutex_init(&priv->cmd.hcr_mutex); - mutex_init(&priv->cmd.slave_cmd_mutex); - sema_init(&priv->cmd.poll_sem, 1); - priv->cmd.use_events = 0; - priv->cmd.toggle = 1; - - priv->cmd.hcr = NULL; - priv->mfunc.vhcr = NULL; - - if (!mlx4_is_slave(dev)) { + if (!mlx4_is_slave(dev) && !priv->cmd.hcr) { priv->cmd.hcr = ioremap(pci_resource_start(dev->pdev, 0) + MLX4_HCR_BASE, MLX4_HCR_SIZE); if (!priv->cmd.hcr) { mlx4_err(dev, "Couldn't map command register\n"); - return -ENOMEM; + goto err; } + flags |= MLX4_CMD_CLEANUP_HCR; } - if (mlx4_is_mfunc(dev)) { + if (mlx4_is_mfunc(dev) && !priv->mfunc.vhcr) { priv->mfunc.vhcr = dma_alloc_coherent(&(dev->pdev->dev), PAGE_SIZE, &priv->mfunc.vhcr_dma, GFP_KERNEL); if (!priv->mfunc.vhcr) - goto err_hcr; + goto err; + + flags |= MLX4_CMD_CLEANUP_VHCR; } - priv->cmd.pool = pci_pool_create("mlx4_cmd", dev->pdev, - MLX4_MAILBOX_SIZE, - MLX4_MAILBOX_SIZE, 0); - if (!priv->cmd.pool) - goto err_vhcr; + if (!priv->cmd.pool) { + priv->cmd.pool = pci_pool_create("mlx4_cmd", dev->pdev, + MLX4_MAILBOX_SIZE, + MLX4_MAILBOX_SIZE, 0); + if (!priv->cmd.pool) + goto err; - return 0; + flags |= MLX4_CMD_CLEANUP_POOL; + } -err_vhcr: - if (mlx4_is_mfunc(dev)) - dma_free_coherent(&(dev->pdev->dev), PAGE_SIZE, - priv->mfunc.vhcr, priv->mfunc.vhcr_dma); - priv->mfunc.vhcr = NULL; + return 0; -err_hcr: - if (!mlx4_is_slave(dev)) - iounmap(priv->cmd.hcr); +err: + mlx4_cmd_cleanup(dev, flags); return -ENOMEM; } @@ -2175,18 +2186,28 @@ void mlx4_multi_func_cleanup(struct mlx4_dev *dev) iounmap(priv->mfunc.comm); } -void mlx4_cmd_cleanup(struct mlx4_dev *dev) +void mlx4_cmd_cleanup(struct mlx4_dev *dev, int cleanup_mask) { struct mlx4_priv *priv = mlx4_priv(dev); - pci_pool_destroy(priv->cmd.pool); + if (priv->cmd.pool && (cleanup_mask & MLX4_CMD_CLEANUP_POOL)) { + pci_pool_destroy(priv->cmd.pool); + priv->cmd.pool = NULL; + } - if (!mlx4_is_slave(dev)) + if (!mlx4_is_slave(dev) && priv->cmd.hcr && + (cleanup_mask & MLX4_CMD_CLEANUP_HCR)) { iounmap(priv->cmd.hcr); - if (mlx4_is_mfunc(dev)) + priv->cmd.hcr = NULL; + } + if (mlx4_is_mfunc(dev) && priv->mfunc.vhcr && + (cleanup_mask & MLX4_CMD_CLEANUP_VHCR)) { dma_free_coherent(&(dev->pdev->dev), PAGE_SIZE, priv->mfunc.vhcr, priv->mfunc.vhcr_dma); - priv->mfunc.vhcr = NULL; + priv->mfunc.vhcr = NULL; + } + if (priv->cmd.initialized && (cleanup_mask & MLX4_CMD_CLEANUP_STRUCT)) + priv->cmd.initialized = 0; } /* diff --git a/drivers/net/ethernet/mellanox/mlx4/en_clock.c b/drivers/net/ethernet/mellanox/mlx4/en_clock.c index 57dda95b67d8..999014413b1a 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_clock.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_clock.c @@ -35,52 +35,6 @@ #include "mlx4_en.h" -int mlx4_en_timestamp_config(struct net_device *dev, int tx_type, int rx_filter) -{ - struct mlx4_en_priv *priv = netdev_priv(dev); - struct mlx4_en_dev *mdev = priv->mdev; - int port_up = 0; - int err = 0; - - if (priv->hwtstamp_config.tx_type == tx_type && - priv->hwtstamp_config.rx_filter == rx_filter) - return 0; - - mutex_lock(&mdev->state_lock); - if (priv->port_up) { - port_up = 1; - mlx4_en_stop_port(dev, 1); - } - - mlx4_en_free_resources(priv); - - en_warn(priv, "Changing Time Stamp configuration\n"); - - priv->hwtstamp_config.tx_type = tx_type; - priv->hwtstamp_config.rx_filter = rx_filter; - - if (rx_filter != HWTSTAMP_FILTER_NONE) - dev->features &= ~NETIF_F_HW_VLAN_CTAG_RX; - else - dev->features |= NETIF_F_HW_VLAN_CTAG_RX; - - err = mlx4_en_alloc_resources(priv); - if (err) { - en_err(priv, "Failed reallocating port resources\n"); - goto out; - } - if (port_up) { - err = mlx4_en_start_port(dev); - if (err) - en_err(priv, "Failed starting port\n"); - } - -out: - mutex_unlock(&mdev->state_lock); - netdev_features_change(dev); - return err; -} - /* mlx4_en_read_clock - read raw cycle counter (to be used by time counter) */ static cycle_t mlx4_en_read_clock(const struct cyclecounter *tc) diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c index ae83da9cd18a..c45e06abc073 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c @@ -35,6 +35,7 @@ #include <linux/ethtool.h> #include <linux/netdevice.h> #include <linux/mlx4/driver.h> +#include <linux/mlx4/device.h> #include <linux/in.h> #include <net/ip.h> @@ -114,7 +115,7 @@ static const char main_strings[][ETH_GSTRING_LEN] = { "tso_packets", "xmit_more", "queue_stopped", "wake_queue", "tx_timeout", "rx_alloc_failed", - "rx_csum_good", "rx_csum_none", "tx_chksum_offload", + "rx_csum_good", "rx_csum_none", "rx_csum_complete", "tx_chksum_offload", /* packet statistics */ "broadcast", "rx_prio_0", "rx_prio_1", "rx_prio_2", "rx_prio_3", @@ -374,7 +375,302 @@ static void mlx4_en_get_strings(struct net_device *dev, } } -static int mlx4_en_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +static u32 mlx4_en_autoneg_get(struct net_device *dev) +{ + struct mlx4_en_priv *priv = netdev_priv(dev); + struct mlx4_en_dev *mdev = priv->mdev; + u32 autoneg = AUTONEG_DISABLE; + + if ((mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_ETH_BACKPL_AN_REP) && + (priv->port_state.flags & MLX4_EN_PORT_ANE)) + autoneg = AUTONEG_ENABLE; + + return autoneg; +} + +static u32 ptys_get_supported_port(struct mlx4_ptys_reg *ptys_reg) +{ + u32 eth_proto = be32_to_cpu(ptys_reg->eth_proto_cap); + + if (eth_proto & (MLX4_PROT_MASK(MLX4_10GBASE_T) + | MLX4_PROT_MASK(MLX4_1000BASE_T) + | MLX4_PROT_MASK(MLX4_100BASE_TX))) { + return SUPPORTED_TP; + } + + if (eth_proto & (MLX4_PROT_MASK(MLX4_10GBASE_CR) + | MLX4_PROT_MASK(MLX4_10GBASE_SR) + | MLX4_PROT_MASK(MLX4_56GBASE_SR4) + | MLX4_PROT_MASK(MLX4_40GBASE_CR4) + | MLX4_PROT_MASK(MLX4_40GBASE_SR4) + | MLX4_PROT_MASK(MLX4_1000BASE_CX_SGMII))) { + return SUPPORTED_FIBRE; + } + + if (eth_proto & (MLX4_PROT_MASK(MLX4_56GBASE_KR4) + | MLX4_PROT_MASK(MLX4_40GBASE_KR4) + | MLX4_PROT_MASK(MLX4_20GBASE_KR2) + | MLX4_PROT_MASK(MLX4_10GBASE_KR) + | MLX4_PROT_MASK(MLX4_10GBASE_KX4) + | MLX4_PROT_MASK(MLX4_1000BASE_KX))) { + return SUPPORTED_Backplane; + } + return 0; +} + +static u32 ptys_get_active_port(struct mlx4_ptys_reg *ptys_reg) +{ + u32 eth_proto = be32_to_cpu(ptys_reg->eth_proto_oper); + + if (!eth_proto) /* link down */ + eth_proto = be32_to_cpu(ptys_reg->eth_proto_cap); + + if (eth_proto & (MLX4_PROT_MASK(MLX4_10GBASE_T) + | MLX4_PROT_MASK(MLX4_1000BASE_T) + | MLX4_PROT_MASK(MLX4_100BASE_TX))) { + return PORT_TP; + } + + if (eth_proto & (MLX4_PROT_MASK(MLX4_10GBASE_SR) + | MLX4_PROT_MASK(MLX4_56GBASE_SR4) + | MLX4_PROT_MASK(MLX4_40GBASE_SR4) + | MLX4_PROT_MASK(MLX4_1000BASE_CX_SGMII))) { + return PORT_FIBRE; + } + + if (eth_proto & (MLX4_PROT_MASK(MLX4_10GBASE_CR) + | MLX4_PROT_MASK(MLX4_56GBASE_CR4) + | MLX4_PROT_MASK(MLX4_40GBASE_CR4))) { + return PORT_DA; + } + + if (eth_proto & (MLX4_PROT_MASK(MLX4_56GBASE_KR4) + | MLX4_PROT_MASK(MLX4_40GBASE_KR4) + | MLX4_PROT_MASK(MLX4_20GBASE_KR2) + | MLX4_PROT_MASK(MLX4_10GBASE_KR) + | MLX4_PROT_MASK(MLX4_10GBASE_KX4) + | MLX4_PROT_MASK(MLX4_1000BASE_KX))) { + return PORT_NONE; + } + return PORT_OTHER; +} + +#define MLX4_LINK_MODES_SZ \ + (FIELD_SIZEOF(struct mlx4_ptys_reg, eth_proto_cap) * 8) + +enum ethtool_report { + SUPPORTED = 0, + ADVERTISED = 1, + SPEED = 2 +}; + +/* Translates mlx4 link mode to equivalent ethtool Link modes/speed */ +static u32 ptys2ethtool_map[MLX4_LINK_MODES_SZ][3] = { + [MLX4_100BASE_TX] = { + SUPPORTED_100baseT_Full, + ADVERTISED_100baseT_Full, + SPEED_100 + }, + + [MLX4_1000BASE_T] = { + SUPPORTED_1000baseT_Full, + ADVERTISED_1000baseT_Full, + SPEED_1000 + }, + [MLX4_1000BASE_CX_SGMII] = { + SUPPORTED_1000baseKX_Full, + ADVERTISED_1000baseKX_Full, + SPEED_1000 + }, + [MLX4_1000BASE_KX] = { + SUPPORTED_1000baseKX_Full, + ADVERTISED_1000baseKX_Full, + SPEED_1000 + }, + + [MLX4_10GBASE_T] = { + SUPPORTED_10000baseT_Full, + ADVERTISED_10000baseT_Full, + SPEED_10000 + }, + [MLX4_10GBASE_CX4] = { + SUPPORTED_10000baseKX4_Full, + ADVERTISED_10000baseKX4_Full, + SPEED_10000 + }, + [MLX4_10GBASE_KX4] = { + SUPPORTED_10000baseKX4_Full, + ADVERTISED_10000baseKX4_Full, + SPEED_10000 + }, + [MLX4_10GBASE_KR] = { + SUPPORTED_10000baseKR_Full, + ADVERTISED_10000baseKR_Full, + SPEED_10000 + }, + [MLX4_10GBASE_CR] = { + SUPPORTED_10000baseKR_Full, + ADVERTISED_10000baseKR_Full, + SPEED_10000 + }, + [MLX4_10GBASE_SR] = { + SUPPORTED_10000baseKR_Full, + ADVERTISED_10000baseKR_Full, + SPEED_10000 + }, + + [MLX4_20GBASE_KR2] = { + SUPPORTED_20000baseMLD2_Full | SUPPORTED_20000baseKR2_Full, + ADVERTISED_20000baseMLD2_Full | ADVERTISED_20000baseKR2_Full, + SPEED_20000 + }, + + [MLX4_40GBASE_CR4] = { + SUPPORTED_40000baseCR4_Full, + ADVERTISED_40000baseCR4_Full, + SPEED_40000 + }, + [MLX4_40GBASE_KR4] = { + SUPPORTED_40000baseKR4_Full, + ADVERTISED_40000baseKR4_Full, + SPEED_40000 + }, + [MLX4_40GBASE_SR4] = { + SUPPORTED_40000baseSR4_Full, + ADVERTISED_40000baseSR4_Full, + SPEED_40000 + }, + + [MLX4_56GBASE_KR4] = { + SUPPORTED_56000baseKR4_Full, + ADVERTISED_56000baseKR4_Full, + SPEED_56000 + }, + [MLX4_56GBASE_CR4] = { + SUPPORTED_56000baseCR4_Full, + ADVERTISED_56000baseCR4_Full, + SPEED_56000 + }, + [MLX4_56GBASE_SR4] = { + SUPPORTED_56000baseSR4_Full, + ADVERTISED_56000baseSR4_Full, + SPEED_56000 + }, +}; + +static u32 ptys2ethtool_link_modes(u32 eth_proto, enum ethtool_report report) +{ + int i; + u32 link_modes = 0; + + for (i = 0; i < MLX4_LINK_MODES_SZ; i++) { + if (eth_proto & MLX4_PROT_MASK(i)) + link_modes |= ptys2ethtool_map[i][report]; + } + return link_modes; +} + +static u32 ethtool2ptys_link_modes(u32 link_modes, enum ethtool_report report) +{ + int i; + u32 ptys_modes = 0; + + for (i = 0; i < MLX4_LINK_MODES_SZ; i++) { + if (ptys2ethtool_map[i][report] & link_modes) + ptys_modes |= 1 << i; + } + return ptys_modes; +} + +/* Convert actual speed (SPEED_XXX) to ptys link modes */ +static u32 speed2ptys_link_modes(u32 speed) +{ + int i; + u32 ptys_modes = 0; + + for (i = 0; i < MLX4_LINK_MODES_SZ; i++) { + if (ptys2ethtool_map[i][SPEED] == speed) + ptys_modes |= 1 << i; + } + return ptys_modes; +} + +static int ethtool_get_ptys_settings(struct net_device *dev, + struct ethtool_cmd *cmd) +{ + struct mlx4_en_priv *priv = netdev_priv(dev); + struct mlx4_ptys_reg ptys_reg; + u32 eth_proto; + int ret; + + memset(&ptys_reg, 0, sizeof(ptys_reg)); + ptys_reg.local_port = priv->port; + ptys_reg.proto_mask = MLX4_PTYS_EN; + ret = mlx4_ACCESS_PTYS_REG(priv->mdev->dev, + MLX4_ACCESS_REG_QUERY, &ptys_reg); + if (ret) { + en_warn(priv, "Failed to run mlx4_ACCESS_PTYS_REG status(%x)", + ret); + return ret; + } + en_dbg(DRV, priv, "ptys_reg.proto_mask %x\n", + ptys_reg.proto_mask); + en_dbg(DRV, priv, "ptys_reg.eth_proto_cap %x\n", + be32_to_cpu(ptys_reg.eth_proto_cap)); + en_dbg(DRV, priv, "ptys_reg.eth_proto_admin %x\n", + be32_to_cpu(ptys_reg.eth_proto_admin)); + en_dbg(DRV, priv, "ptys_reg.eth_proto_oper %x\n", + be32_to_cpu(ptys_reg.eth_proto_oper)); + en_dbg(DRV, priv, "ptys_reg.eth_proto_lp_adv %x\n", + be32_to_cpu(ptys_reg.eth_proto_lp_adv)); + + cmd->supported = 0; + cmd->advertising = 0; + + cmd->supported |= ptys_get_supported_port(&ptys_reg); + + eth_proto = be32_to_cpu(ptys_reg.eth_proto_cap); + cmd->supported |= ptys2ethtool_link_modes(eth_proto, SUPPORTED); + + eth_proto = be32_to_cpu(ptys_reg.eth_proto_admin); + cmd->advertising |= ptys2ethtool_link_modes(eth_proto, ADVERTISED); + + cmd->supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; + cmd->advertising |= (priv->prof->tx_pause) ? ADVERTISED_Pause : 0; + + cmd->advertising |= (priv->prof->tx_pause ^ priv->prof->rx_pause) ? + ADVERTISED_Asym_Pause : 0; + + cmd->port = ptys_get_active_port(&ptys_reg); + cmd->transceiver = (SUPPORTED_TP & cmd->supported) ? + XCVR_EXTERNAL : XCVR_INTERNAL; + + if (mlx4_en_autoneg_get(dev)) { + cmd->supported |= SUPPORTED_Autoneg; + cmd->advertising |= ADVERTISED_Autoneg; + } + + cmd->autoneg = (priv->port_state.flags & MLX4_EN_PORT_ANC) ? + AUTONEG_ENABLE : AUTONEG_DISABLE; + + eth_proto = be32_to_cpu(ptys_reg.eth_proto_lp_adv); + cmd->lp_advertising = ptys2ethtool_link_modes(eth_proto, ADVERTISED); + + cmd->lp_advertising |= (priv->port_state.flags & MLX4_EN_PORT_ANC) ? + ADVERTISED_Autoneg : 0; + + cmd->phy_address = 0; + cmd->mdio_support = 0; + cmd->maxtxpkt = 0; + cmd->maxrxpkt = 0; + cmd->eth_tp_mdix = ETH_TP_MDI_INVALID; + cmd->eth_tp_mdix_ctrl = ETH_TP_MDI_AUTO; + + return ret; +} + +static void ethtool_get_default_settings(struct net_device *dev, + struct ethtool_cmd *cmd) { struct mlx4_en_priv *priv = netdev_priv(dev); int trans_type; @@ -382,18 +678,7 @@ static int mlx4_en_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) cmd->autoneg = AUTONEG_DISABLE; cmd->supported = SUPPORTED_10000baseT_Full; cmd->advertising = ADVERTISED_10000baseT_Full; - - if (mlx4_en_QUERY_PORT(priv->mdev, priv->port)) - return -ENOMEM; - - trans_type = priv->port_state.transciver; - if (netif_carrier_ok(dev)) { - ethtool_cmd_speed_set(cmd, priv->port_state.link_speed); - cmd->duplex = DUPLEX_FULL; - } else { - ethtool_cmd_speed_set(cmd, SPEED_UNKNOWN); - cmd->duplex = DUPLEX_UNKNOWN; - } + trans_type = priv->port_state.transceiver; if (trans_type > 0 && trans_type <= 0xC) { cmd->port = PORT_FIBRE; @@ -409,17 +694,118 @@ static int mlx4_en_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) cmd->port = -1; cmd->transceiver = -1; } +} + +static int mlx4_en_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct mlx4_en_priv *priv = netdev_priv(dev); + int ret = -EINVAL; + + if (mlx4_en_QUERY_PORT(priv->mdev, priv->port)) + return -ENOMEM; + + en_dbg(DRV, priv, "query port state.flags ANC(%x) ANE(%x)\n", + priv->port_state.flags & MLX4_EN_PORT_ANC, + priv->port_state.flags & MLX4_EN_PORT_ANE); + + if (priv->mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_ETH_PROT_CTRL) + ret = ethtool_get_ptys_settings(dev, cmd); + if (ret) /* ETH PROT CRTL is not supported or PTYS CMD failed */ + ethtool_get_default_settings(dev, cmd); + + if (netif_carrier_ok(dev)) { + ethtool_cmd_speed_set(cmd, priv->port_state.link_speed); + cmd->duplex = DUPLEX_FULL; + } else { + ethtool_cmd_speed_set(cmd, SPEED_UNKNOWN); + cmd->duplex = DUPLEX_UNKNOWN; + } return 0; } +/* Calculate PTYS admin according ethtool speed (SPEED_XXX) */ +static __be32 speed_set_ptys_admin(struct mlx4_en_priv *priv, u32 speed, + __be32 proto_cap) +{ + __be32 proto_admin = 0; + + if (!speed) { /* Speed = 0 ==> Reset Link modes */ + proto_admin = proto_cap; + en_info(priv, "Speed was set to 0, Reset advertised Link Modes to default (%x)\n", + be32_to_cpu(proto_cap)); + } else { + u32 ptys_link_modes = speed2ptys_link_modes(speed); + + proto_admin = cpu_to_be32(ptys_link_modes) & proto_cap; + en_info(priv, "Setting Speed to %d\n", speed); + } + return proto_admin; +} + static int mlx4_en_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { - if ((cmd->autoneg == AUTONEG_ENABLE) || - (ethtool_cmd_speed(cmd) != SPEED_10000) || - (cmd->duplex != DUPLEX_FULL)) + struct mlx4_en_priv *priv = netdev_priv(dev); + struct mlx4_ptys_reg ptys_reg; + __be32 proto_admin; + int ret; + + u32 ptys_adv = ethtool2ptys_link_modes(cmd->advertising, ADVERTISED); + int speed = ethtool_cmd_speed(cmd); + + en_dbg(DRV, priv, "Set Speed=%d adv=0x%x autoneg=%d duplex=%d\n", + speed, cmd->advertising, cmd->autoneg, cmd->duplex); + + if (!(priv->mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_ETH_PROT_CTRL) || + (cmd->duplex == DUPLEX_HALF)) return -EINVAL; - /* Nothing to change */ + memset(&ptys_reg, 0, sizeof(ptys_reg)); + ptys_reg.local_port = priv->port; + ptys_reg.proto_mask = MLX4_PTYS_EN; + ret = mlx4_ACCESS_PTYS_REG(priv->mdev->dev, + MLX4_ACCESS_REG_QUERY, &ptys_reg); + if (ret) { + en_warn(priv, "Failed to QUERY mlx4_ACCESS_PTYS_REG status(%x)\n", + ret); + return 0; + } + + proto_admin = cpu_to_be32(ptys_adv); + if (speed >= 0 && speed != priv->port_state.link_speed) + /* If speed was set then speed decides :-) */ + proto_admin = speed_set_ptys_admin(priv, speed, + ptys_reg.eth_proto_cap); + + proto_admin &= ptys_reg.eth_proto_cap; + + if (proto_admin == ptys_reg.eth_proto_admin) + return 0; /* Nothing to change */ + + if (!proto_admin) { + en_warn(priv, "Not supported link mode(s) requested, check supported link modes.\n"); + return -EINVAL; /* nothing to change due to bad input */ + } + + en_dbg(DRV, priv, "mlx4_ACCESS_PTYS_REG SET: ptys_reg.eth_proto_admin = 0x%x\n", + be32_to_cpu(proto_admin)); + + ptys_reg.eth_proto_admin = proto_admin; + ret = mlx4_ACCESS_PTYS_REG(priv->mdev->dev, MLX4_ACCESS_REG_WRITE, + &ptys_reg); + if (ret) { + en_warn(priv, "Failed to write mlx4_ACCESS_PTYS_REG eth_proto_admin(0x%x) status(0x%x)", + be32_to_cpu(ptys_reg.eth_proto_admin), ret); + return ret; + } + + en_warn(priv, "Port link mode changed, restarting port...\n"); + mutex_lock(&priv->mdev->state_lock); + if (priv->port_up) { + mlx4_en_stop_port(dev, 1); + if (mlx4_en_start_port(dev)) + en_err(priv, "Failed restarting port %d\n", priv->port); + } + mutex_unlock(&priv->mdev->state_lock); return 0; } @@ -587,6 +973,11 @@ static u32 mlx4_en_get_rxfh_indir_size(struct net_device *dev) return priv->rx_ring_num; } +static u32 mlx4_en_get_rxfh_key_size(struct net_device *netdev) +{ + return MLX4_EN_RSS_KEY_SIZE; +} + static int mlx4_en_get_rxfh(struct net_device *dev, u32 *ring_index, u8 *key) { struct mlx4_en_priv *priv = netdev_priv(dev); @@ -596,12 +987,14 @@ static int mlx4_en_get_rxfh(struct net_device *dev, u32 *ring_index, u8 *key) int err = 0; rss_rings = priv->prof->rss_rings ?: priv->rx_ring_num; + rss_rings = 1 << ilog2(rss_rings); while (n--) { ring_index[n] = rss_map->qps[n % rss_rings].qpn - rss_map->base_qpn; } - + if (key) + memcpy(key, priv->rss_key, MLX4_EN_RSS_KEY_SIZE); return err; } @@ -619,6 +1012,8 @@ static int mlx4_en_set_rxfh(struct net_device *dev, const u32 *ring_index, * between rings */ for (i = 0; i < priv->rx_ring_num; i++) { + if (!ring_index) + continue; if (i > 0 && !ring_index[i] && !rss_rings) rss_rings = i; @@ -639,8 +1034,10 @@ static int mlx4_en_set_rxfh(struct net_device *dev, const u32 *ring_index, mlx4_en_stop_port(dev, 1); } - priv->prof->rss_rings = rss_rings; - + if (ring_index) + priv->prof->rss_rings = rss_rings; + if (key) + memcpy(priv->rss_key, key, MLX4_EN_RSS_KEY_SIZE); if (port_up) { err = mlx4_en_start_port(dev); if (err) @@ -1309,6 +1706,86 @@ static int mlx4_en_set_tunable(struct net_device *dev, return ret; } +static int mlx4_en_get_module_info(struct net_device *dev, + struct ethtool_modinfo *modinfo) +{ + struct mlx4_en_priv *priv = netdev_priv(dev); + struct mlx4_en_dev *mdev = priv->mdev; + int ret; + u8 data[4]; + + /* Read first 2 bytes to get Module & REV ID */ + ret = mlx4_get_module_info(mdev->dev, priv->port, + 0/*offset*/, 2/*size*/, data); + if (ret < 2) + return -EIO; + + switch (data[0] /* identifier */) { + case MLX4_MODULE_ID_QSFP: + modinfo->type = ETH_MODULE_SFF_8436; + modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN; + break; + case MLX4_MODULE_ID_QSFP_PLUS: + if (data[1] >= 0x3) { /* revision id */ + modinfo->type = ETH_MODULE_SFF_8636; + modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN; + } else { + modinfo->type = ETH_MODULE_SFF_8436; + modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN; + } + break; + case MLX4_MODULE_ID_QSFP28: + modinfo->type = ETH_MODULE_SFF_8636; + modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN; + break; + case MLX4_MODULE_ID_SFP: + modinfo->type = ETH_MODULE_SFF_8472; + modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN; + break; + default: + return -ENOSYS; + } + + return 0; +} + +static int mlx4_en_get_module_eeprom(struct net_device *dev, + struct ethtool_eeprom *ee, + u8 *data) +{ + struct mlx4_en_priv *priv = netdev_priv(dev); + struct mlx4_en_dev *mdev = priv->mdev; + int offset = ee->offset; + int i = 0, ret; + + if (ee->len == 0) + return -EINVAL; + + memset(data, 0, ee->len); + + while (i < ee->len) { + en_dbg(DRV, priv, + "mlx4_get_module_info i(%d) offset(%d) len(%d)\n", + i, offset, ee->len - i); + + ret = mlx4_get_module_info(mdev->dev, priv->port, + offset, ee->len - i, data + i); + + if (!ret) /* Done reading */ + return 0; + + if (ret < 0) { + en_err(priv, + "mlx4_get_module_info i(%d) offset(%d) bytes_to_read(%d) - FAILED (0x%x)\n", + i, offset, ee->len - i, ret); + return 0; + } + + i += ret; + offset += ret; + } + return 0; +} const struct ethtool_ops mlx4_en_ethtool_ops = { .get_drvinfo = mlx4_en_get_drvinfo, @@ -1332,6 +1809,7 @@ const struct ethtool_ops mlx4_en_ethtool_ops = { .get_rxnfc = mlx4_en_get_rxnfc, .set_rxnfc = mlx4_en_set_rxnfc, .get_rxfh_indir_size = mlx4_en_get_rxfh_indir_size, + .get_rxfh_key_size = mlx4_en_get_rxfh_key_size, .get_rxfh = mlx4_en_get_rxfh, .set_rxfh = mlx4_en_set_rxfh, .get_channels = mlx4_en_get_channels, @@ -1341,6 +1819,8 @@ const struct ethtool_ops mlx4_en_ethtool_ops = { .get_priv_flags = mlx4_en_get_priv_flags, .get_tunable = mlx4_en_get_tunable, .set_tunable = mlx4_en_set_tunable, + .get_module_info = mlx4_en_get_module_info, + .get_module_eeprom = mlx4_en_get_module_eeprom }; diff --git a/drivers/net/ethernet/mellanox/mlx4/en_main.c b/drivers/net/ethernet/mellanox/mlx4/en_main.c index 2091ae88615d..9f16f754137b 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_main.c @@ -221,15 +221,12 @@ static void *mlx4_en_add(struct mlx4_dev *dev) { struct mlx4_en_dev *mdev; int i; - int err; printk_once(KERN_INFO "%s", mlx4_en_version); mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); - if (!mdev) { - err = -ENOMEM; + if (!mdev) goto err_free_res; - } if (mlx4_pd_alloc(dev, &mdev->priv_pdn)) goto err_free_dev; @@ -264,8 +261,7 @@ static void *mlx4_en_add(struct mlx4_dev *dev) } /* Build device profile according to supplied module parameters */ - err = mlx4_en_get_profile(mdev); - if (err) { + if (mlx4_en_get_profile(mdev)) { mlx4_err(mdev, "Bad module parameters, aborting\n"); goto err_mr; } @@ -286,10 +282,8 @@ static void *mlx4_en_add(struct mlx4_dev *dev) * Note: we cannot use the shared workqueue because of deadlocks caused * by the rtnl lock */ mdev->workqueue = create_singlethread_workqueue("mlx4_en"); - if (!mdev->workqueue) { - err = -ENOMEM; + if (!mdev->workqueue) goto err_mr; - } /* At this stage all non-port specific tasks are complete: * mark the card state as up */ diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index 4d69e382b4e5..b7c99780aef3 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -575,7 +575,7 @@ static int mlx4_en_get_qp(struct mlx4_en_priv *priv) struct mlx4_mac_entry *entry; int index = 0; int err = 0; - u64 reg_id; + u64 reg_id = 0; int *qpn = &priv->base_qpn; u64 mac = mlx4_mac_to_u64(priv->dev->dev_addr); @@ -1843,8 +1843,7 @@ void mlx4_en_stop_port(struct net_device *dev, int detach) } local_bh_enable(); - while (test_bit(NAPI_STATE_SCHED, &cq->napi.state)) - msleep(1); + napi_synchronize(&cq->napi); mlx4_en_deactivate_rx_ring(priv, priv->rx_ring[i]); mlx4_en_deactivate_cq(priv, cq); @@ -1894,6 +1893,7 @@ static void mlx4_en_clear_stats(struct net_device *dev) priv->rx_ring[i]->packets = 0; priv->rx_ring[i]->csum_ok = 0; priv->rx_ring[i]->csum_none = 0; + priv->rx_ring[i]->csum_complete = 0; } } @@ -2157,7 +2157,7 @@ static int mlx4_en_hwtstamp_set(struct net_device *dev, struct ifreq *ifr) return -ERANGE; } - if (mlx4_en_timestamp_config(dev, config.tx_type, config.rx_filter)) { + if (mlx4_en_reset_config(dev, config, dev->features)) { config.tx_type = HWTSTAMP_TX_OFF; config.rx_filter = HWTSTAMP_FILTER_NONE; } @@ -2190,6 +2190,16 @@ static int mlx4_en_set_features(struct net_device *netdev, netdev_features_t features) { struct mlx4_en_priv *priv = netdev_priv(netdev); + int ret = 0; + + if (DEV_FEATURE_CHANGED(netdev, features, NETIF_F_HW_VLAN_CTAG_RX)) { + en_info(priv, "Turn %s RX vlan strip offload\n", + (features & NETIF_F_HW_VLAN_CTAG_RX) ? "ON" : "OFF"); + ret = mlx4_en_reset_config(netdev, priv->hwtstamp_config, + features); + if (ret) + return ret; + } if (features & NETIF_F_LOOPBACK) priv->ctrl_flags |= cpu_to_be32(MLX4_WQE_CTRL_FORCE_LOOPBACK); @@ -2455,6 +2465,21 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, priv = netdev_priv(dev); memset(priv, 0, sizeof(struct mlx4_en_priv)); + spin_lock_init(&priv->stats_lock); + INIT_WORK(&priv->rx_mode_task, mlx4_en_do_set_rx_mode); + INIT_WORK(&priv->watchdog_task, mlx4_en_restart); + INIT_WORK(&priv->linkstate_task, mlx4_en_linkstate); + INIT_DELAYED_WORK(&priv->stats_task, mlx4_en_do_get_stats); + INIT_DELAYED_WORK(&priv->service_task, mlx4_en_service_task); +#ifdef CONFIG_MLX4_EN_VXLAN + INIT_WORK(&priv->vxlan_add_task, mlx4_en_add_vxlan_offloads); + INIT_WORK(&priv->vxlan_del_task, mlx4_en_del_vxlan_offloads); +#endif +#ifdef CONFIG_RFS_ACCEL + INIT_LIST_HEAD(&priv->filters); + spin_lock_init(&priv->filters_lock); +#endif + priv->dev = dev; priv->mdev = mdev; priv->ddev = &mdev->pdev->dev; @@ -2468,6 +2493,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, priv->num_tx_rings_p_up = mdev->profile.num_tx_rings_p_up; priv->tx_ring_num = prof->tx_ring_num; priv->tx_work_limit = MLX4_EN_DEFAULT_TX_WORK; + netdev_rss_key_fill(priv->rss_key, sizeof(priv->rss_key)); priv->tx_ring = kzalloc(sizeof(struct mlx4_en_tx_ring *) * MAX_TX_RINGS, GFP_KERNEL); @@ -2486,16 +2512,6 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, priv->cqe_size = mdev->dev->caps.cqe_size; priv->mac_index = -1; priv->msg_enable = MLX4_EN_MSG_LEVEL; - spin_lock_init(&priv->stats_lock); - INIT_WORK(&priv->rx_mode_task, mlx4_en_do_set_rx_mode); - INIT_WORK(&priv->watchdog_task, mlx4_en_restart); - INIT_WORK(&priv->linkstate_task, mlx4_en_linkstate); - INIT_DELAYED_WORK(&priv->stats_task, mlx4_en_do_get_stats); - INIT_DELAYED_WORK(&priv->service_task, mlx4_en_service_task); -#ifdef CONFIG_MLX4_EN_VXLAN - INIT_WORK(&priv->vxlan_add_task, mlx4_en_add_vxlan_offloads); - INIT_WORK(&priv->vxlan_del_task, mlx4_en_del_vxlan_offloads); -#endif #ifdef CONFIG_MLX4_EN_DCB if (!mlx4_is_slave(priv->mdev->dev)) { if (mdev->dev->caps.flags & MLX4_DEV_CAP_FLAG_SET_ETH_SCHED) { @@ -2513,6 +2529,10 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, /* Query for default mac and max mtu */ priv->max_mtu = mdev->dev->caps.eth_mtu_cap[priv->port]; + if (mdev->dev->caps.rx_checksum_flags_port[priv->port] & + MLX4_RX_CSUM_MODE_VAL_NON_TCP_UDP) + priv->flags |= MLX4_EN_FLAG_RX_CSUM_NON_TCP_UDP; + /* Set default MAC */ dev->addr_len = ETH_ALEN; mlx4_en_u64_to_mac(dev->dev_addr, mdev->dev->caps.def_mac[priv->port]); @@ -2538,11 +2558,6 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, if (err) goto out; -#ifdef CONFIG_RFS_ACCEL - INIT_LIST_HEAD(&priv->filters); - spin_lock_init(&priv->filters_lock); -#endif - /* Initialize time stamping config */ priv->hwtstamp_config.flags = 0; priv->hwtstamp_config.tx_type = HWTSTAMP_TX_OFF; @@ -2583,7 +2598,8 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, dev->features = dev->hw_features | NETIF_F_HIGHDMA | NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_FILTER; - dev->hw_features |= NETIF_F_LOOPBACK; + dev->hw_features |= NETIF_F_LOOPBACK | + NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX; if (mdev->dev->caps.steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED) @@ -2650,3 +2666,79 @@ out: return err; } +int mlx4_en_reset_config(struct net_device *dev, + struct hwtstamp_config ts_config, + netdev_features_t features) +{ + struct mlx4_en_priv *priv = netdev_priv(dev); + struct mlx4_en_dev *mdev = priv->mdev; + int port_up = 0; + int err = 0; + + if (priv->hwtstamp_config.tx_type == ts_config.tx_type && + priv->hwtstamp_config.rx_filter == ts_config.rx_filter && + !DEV_FEATURE_CHANGED(dev, features, NETIF_F_HW_VLAN_CTAG_RX)) + return 0; /* Nothing to change */ + + if (DEV_FEATURE_CHANGED(dev, features, NETIF_F_HW_VLAN_CTAG_RX) && + (features & NETIF_F_HW_VLAN_CTAG_RX) && + (priv->hwtstamp_config.rx_filter != HWTSTAMP_FILTER_NONE)) { + en_warn(priv, "Can't turn ON rx vlan offload while time-stamping rx filter is ON\n"); + return -EINVAL; + } + + mutex_lock(&mdev->state_lock); + if (priv->port_up) { + port_up = 1; + mlx4_en_stop_port(dev, 1); + } + + mlx4_en_free_resources(priv); + + en_warn(priv, "Changing device configuration rx filter(%x) rx vlan(%x)\n", + ts_config.rx_filter, !!(features & NETIF_F_HW_VLAN_CTAG_RX)); + + priv->hwtstamp_config.tx_type = ts_config.tx_type; + priv->hwtstamp_config.rx_filter = ts_config.rx_filter; + + if (DEV_FEATURE_CHANGED(dev, features, NETIF_F_HW_VLAN_CTAG_RX)) { + if (features & NETIF_F_HW_VLAN_CTAG_RX) + dev->features |= NETIF_F_HW_VLAN_CTAG_RX; + else + dev->features &= ~NETIF_F_HW_VLAN_CTAG_RX; + } else if (ts_config.rx_filter == HWTSTAMP_FILTER_NONE) { + /* RX time-stamping is OFF, update the RX vlan offload + * to the latest wanted state + */ + if (dev->wanted_features & NETIF_F_HW_VLAN_CTAG_RX) + dev->features |= NETIF_F_HW_VLAN_CTAG_RX; + else + dev->features &= ~NETIF_F_HW_VLAN_CTAG_RX; + } + + /* RX vlan offload and RX time-stamping can't co-exist ! + * Regardless of the caller's choice, + * Turn Off RX vlan offload in case of time-stamping is ON + */ + if (ts_config.rx_filter != HWTSTAMP_FILTER_NONE) { + if (dev->features & NETIF_F_HW_VLAN_CTAG_RX) + en_warn(priv, "Turning off RX vlan offload since RX time-stamping is ON\n"); + dev->features &= ~NETIF_F_HW_VLAN_CTAG_RX; + } + + err = mlx4_en_alloc_resources(priv); + if (err) { + en_err(priv, "Failed reallocating port resources\n"); + goto out; + } + if (port_up) { + err = mlx4_en_start_port(dev); + if (err) + en_err(priv, "Failed starting port\n"); + } + +out: + mutex_unlock(&mdev->state_lock); + netdev_features_change(dev); + return err; +} diff --git a/drivers/net/ethernet/mellanox/mlx4/en_port.c b/drivers/net/ethernet/mellanox/mlx4/en_port.c index 0a0261d128b9..6cb80072af6c 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_port.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_port.c @@ -91,21 +91,37 @@ int mlx4_en_QUERY_PORT(struct mlx4_en_dev *mdev, u8 port) * already synchronized, no need in locking */ state->link_state = !!(qport_context->link_up & MLX4_EN_LINK_UP_MASK); switch (qport_context->link_speed & MLX4_EN_SPEED_MASK) { + case MLX4_EN_100M_SPEED: + state->link_speed = SPEED_100; + break; case MLX4_EN_1G_SPEED: - state->link_speed = 1000; + state->link_speed = SPEED_1000; break; case MLX4_EN_10G_SPEED_XAUI: case MLX4_EN_10G_SPEED_XFI: - state->link_speed = 10000; + state->link_speed = SPEED_10000; + break; + case MLX4_EN_20G_SPEED: + state->link_speed = SPEED_20000; break; case MLX4_EN_40G_SPEED: - state->link_speed = 40000; + state->link_speed = SPEED_40000; + break; + case MLX4_EN_56G_SPEED: + state->link_speed = SPEED_56000; break; default: state->link_speed = -1; break; } - state->transciver = qport_context->transceiver; + + state->transceiver = qport_context->transceiver; + + state->flags = 0; /* Reset and recalculate the port flags */ + state->flags |= (qport_context->link_up & MLX4_EN_ANC_MASK) ? + MLX4_EN_PORT_ANC : 0; + state->flags |= (qport_context->autoneg & MLX4_EN_AUTONEG_MASK) ? + MLX4_EN_PORT_ANE : 0; out: mlx4_free_cmd_mailbox(mdev->dev, mailbox); @@ -139,11 +155,13 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset) stats->rx_bytes = 0; priv->port_stats.rx_chksum_good = 0; priv->port_stats.rx_chksum_none = 0; + priv->port_stats.rx_chksum_complete = 0; for (i = 0; i < priv->rx_ring_num; i++) { stats->rx_packets += priv->rx_ring[i]->packets; stats->rx_bytes += priv->rx_ring[i]->bytes; priv->port_stats.rx_chksum_good += priv->rx_ring[i]->csum_ok; priv->port_stats.rx_chksum_none += priv->rx_ring[i]->csum_none; + priv->port_stats.rx_chksum_complete += priv->rx_ring[i]->csum_complete; } stats->tx_packets = 0; stats->tx_bytes = 0; diff --git a/drivers/net/ethernet/mellanox/mlx4/en_port.h b/drivers/net/ethernet/mellanox/mlx4/en_port.h index 745090b49d9e..040da4b16b1c 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_port.h +++ b/drivers/net/ethernet/mellanox/mlx4/en_port.h @@ -53,22 +53,49 @@ enum { MLX4_MCAST_ENABLE = 2, }; +enum mlx4_link_mode { + MLX4_1000BASE_CX_SGMII = 0, + MLX4_1000BASE_KX = 1, + MLX4_10GBASE_CX4 = 2, + MLX4_10GBASE_KX4 = 3, + MLX4_10GBASE_KR = 4, + MLX4_20GBASE_KR2 = 5, + MLX4_40GBASE_CR4 = 6, + MLX4_40GBASE_KR4 = 7, + MLX4_56GBASE_KR4 = 8, + MLX4_10GBASE_CR = 12, + MLX4_10GBASE_SR = 13, + MLX4_40GBASE_SR4 = 15, + MLX4_56GBASE_CR4 = 17, + MLX4_56GBASE_SR4 = 18, + MLX4_100BASE_TX = 24, + MLX4_1000BASE_T = 25, + MLX4_10GBASE_T = 26, +}; + +#define MLX4_PROT_MASK(link_mode) (1<<link_mode) + enum { - MLX4_EN_1G_SPEED = 0x02, - MLX4_EN_10G_SPEED_XFI = 0x01, + MLX4_EN_100M_SPEED = 0x04, MLX4_EN_10G_SPEED_XAUI = 0x00, + MLX4_EN_10G_SPEED_XFI = 0x01, + MLX4_EN_1G_SPEED = 0x02, + MLX4_EN_20G_SPEED = 0x08, MLX4_EN_40G_SPEED = 0x40, + MLX4_EN_56G_SPEED = 0x20, MLX4_EN_OTHER_SPEED = 0x0f, }; struct mlx4_en_query_port_context { u8 link_up; #define MLX4_EN_LINK_UP_MASK 0x80 - u8 reserved; +#define MLX4_EN_ANC_MASK 0x40 + u8 autoneg; +#define MLX4_EN_AUTONEG_MASK 0x80 __be16 mtu; u8 reserved2; u8 link_speed; -#define MLX4_EN_SPEED_MASK 0x43 +#define MLX4_EN_SPEED_MASK 0x6f u16 reserved3[5]; __be64 mac; u8 transceiver; diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c index 01660c595f5c..946d35280abc 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c @@ -42,6 +42,10 @@ #include <linux/vmalloc.h> #include <linux/irq.h> +#if IS_ENABLED(CONFIG_IPV6) +#include <net/ip6_checksum.h> +#endif + #include "mlx4_en.h" static int mlx4_alloc_pages(struct mlx4_en_priv *priv, @@ -74,7 +78,7 @@ static int mlx4_alloc_pages(struct mlx4_en_priv *priv, page_alloc->page_size = PAGE_SIZE << order; page_alloc->page = page; page_alloc->dma = dma; - page_alloc->page_offset = frag_info->frag_align; + page_alloc->page_offset = 0; /* Not doing get_page() for each frag is a big win * on asymetric workloads. Note we can not use atomic_set(). */ @@ -119,7 +123,6 @@ static int mlx4_en_alloc_frags(struct mlx4_en_priv *priv, out: while (i--) { - frag_info = &priv->frag_info[i]; if (page_alloc[i].page != ring_alloc[i].page) { dma_unmap_page(priv->ddev, page_alloc[i].dma, page_alloc[i].page_size, PCI_DMA_FROMDEVICE); @@ -157,7 +160,7 @@ static int mlx4_en_init_allocator(struct mlx4_en_priv *priv, const struct mlx4_en_frag_info *frag_info = &priv->frag_info[i]; if (mlx4_alloc_pages(priv, &ring->page_alloc[i], - frag_info, GFP_KERNEL)) + frag_info, GFP_KERNEL | __GFP_COLD)) goto out; } return 0; @@ -269,7 +272,7 @@ static int mlx4_en_fill_rx_buffers(struct mlx4_en_priv *priv) if (mlx4_en_prepare_rx_desc(priv, ring, ring->actual_size, - GFP_KERNEL)) { + GFP_KERNEL | __GFP_COLD)) { if (ring->actual_size < MLX4_EN_MIN_RX_SIZE) { en_err(priv, "Failed to allocate enough rx buffers\n"); return -ENOMEM; @@ -636,13 +639,94 @@ static void mlx4_en_refill_rx_buffers(struct mlx4_en_priv *priv, int index = ring->prod & ring->size_mask; while ((u32) (ring->prod - ring->cons) < ring->actual_size) { - if (mlx4_en_prepare_rx_desc(priv, ring, index, GFP_ATOMIC)) + if (mlx4_en_prepare_rx_desc(priv, ring, index, + GFP_ATOMIC | __GFP_COLD)) break; ring->prod++; index = ring->prod & ring->size_mask; } } +/* When hardware doesn't strip the vlan, we need to calculate the checksum + * over it and add it to the hardware's checksum calculation + */ +static inline __wsum get_fixed_vlan_csum(__wsum hw_checksum, + struct vlan_hdr *vlanh) +{ + return csum_add(hw_checksum, *(__wsum *)vlanh); +} + +/* Although the stack expects checksum which doesn't include the pseudo + * header, the HW adds it. To address that, we are subtracting the pseudo + * header checksum from the checksum value provided by the HW. + */ +static void get_fixed_ipv4_csum(__wsum hw_checksum, struct sk_buff *skb, + struct iphdr *iph) +{ + __u16 length_for_csum = 0; + __wsum csum_pseudo_header = 0; + + length_for_csum = (be16_to_cpu(iph->tot_len) - (iph->ihl << 2)); + csum_pseudo_header = csum_tcpudp_nofold(iph->saddr, iph->daddr, + length_for_csum, iph->protocol, 0); + skb->csum = csum_sub(hw_checksum, csum_pseudo_header); +} + +#if IS_ENABLED(CONFIG_IPV6) +/* In IPv6 packets, besides subtracting the pseudo header checksum, + * we also compute/add the IP header checksum which + * is not added by the HW. + */ +static int get_fixed_ipv6_csum(__wsum hw_checksum, struct sk_buff *skb, + struct ipv6hdr *ipv6h) +{ + __wsum csum_pseudo_hdr = 0; + + if (ipv6h->nexthdr == IPPROTO_FRAGMENT || ipv6h->nexthdr == IPPROTO_HOPOPTS) + return -1; + hw_checksum = csum_add(hw_checksum, (__force __wsum)(ipv6h->nexthdr << 8)); + + csum_pseudo_hdr = csum_partial(&ipv6h->saddr, + sizeof(ipv6h->saddr) + sizeof(ipv6h->daddr), 0); + csum_pseudo_hdr = csum_add(csum_pseudo_hdr, (__force __wsum)ipv6h->payload_len); + csum_pseudo_hdr = csum_add(csum_pseudo_hdr, (__force __wsum)ntohs(ipv6h->nexthdr)); + + skb->csum = csum_sub(hw_checksum, csum_pseudo_hdr); + skb->csum = csum_add(skb->csum, csum_partial(ipv6h, sizeof(struct ipv6hdr), 0)); + return 0; +} +#endif +static int check_csum(struct mlx4_cqe *cqe, struct sk_buff *skb, void *va, + int hwtstamp_rx_filter) +{ + __wsum hw_checksum = 0; + + void *hdr = (u8 *)va + sizeof(struct ethhdr); + + hw_checksum = csum_unfold((__force __sum16)cqe->checksum); + + if (((struct ethhdr *)va)->h_proto == htons(ETH_P_8021Q) && + hwtstamp_rx_filter != HWTSTAMP_FILTER_NONE) { + /* next protocol non IPv4 or IPv6 */ + if (((struct vlan_hdr *)hdr)->h_vlan_encapsulated_proto + != htons(ETH_P_IP) && + ((struct vlan_hdr *)hdr)->h_vlan_encapsulated_proto + != htons(ETH_P_IPV6)) + return -1; + hw_checksum = get_fixed_vlan_csum(hw_checksum, hdr); + hdr += sizeof(struct vlan_hdr); + } + + if (cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPV4)) + get_fixed_ipv4_csum(hw_checksum, skb, hdr); +#if IS_ENABLED(CONFIG_IPV6) + else if (cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPV6)) + if (get_fixed_ipv6_csum(hw_checksum, skb, hdr)) + return -1; +#endif + return 0; +} + int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int budget) { struct mlx4_en_priv *priv = netdev_priv(dev); @@ -744,73 +828,95 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud (cqe->vlan_my_qpn & cpu_to_be32(MLX4_CQE_L2_TUNNEL)); if (likely(dev->features & NETIF_F_RXCSUM)) { - if ((cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPOK)) && - (cqe->checksum == cpu_to_be16(0xffff))) { - ring->csum_ok++; - /* This packet is eligible for GRO if it is: - * - DIX Ethernet (type interpretation) - * - TCP/IP (v4) - * - without IP options - * - not an IP fragment - * - no LLS polling in progress - */ - if (!mlx4_en_cq_busy_polling(cq) && - (dev->features & NETIF_F_GRO)) { - struct sk_buff *gro_skb = napi_get_frags(&cq->napi); - if (!gro_skb) - goto next; - - nr = mlx4_en_complete_rx_desc(priv, - rx_desc, frags, gro_skb, - length); - if (!nr) - goto next; - - skb_shinfo(gro_skb)->nr_frags = nr; - gro_skb->len = length; - gro_skb->data_len = length; - gro_skb->ip_summed = CHECKSUM_UNNECESSARY; + if (cqe->status & cpu_to_be16(MLX4_CQE_STATUS_TCP | + MLX4_CQE_STATUS_UDP)) { + if ((cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPOK)) && + cqe->checksum == cpu_to_be16(0xffff)) { + ip_summed = CHECKSUM_UNNECESSARY; + ring->csum_ok++; + } else { + ip_summed = CHECKSUM_NONE; + ring->csum_none++; + } + } else { + if (priv->flags & MLX4_EN_FLAG_RX_CSUM_NON_TCP_UDP && + (cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPV4 | + MLX4_CQE_STATUS_IPV6))) { + ip_summed = CHECKSUM_COMPLETE; + ring->csum_complete++; + } else { + ip_summed = CHECKSUM_NONE; + ring->csum_none++; + } + } + } else { + ip_summed = CHECKSUM_NONE; + ring->csum_none++; + } - if (l2_tunnel) - gro_skb->csum_level = 1; - if ((cqe->vlan_my_qpn & - cpu_to_be32(MLX4_CQE_VLAN_PRESENT_MASK)) && - (dev->features & NETIF_F_HW_VLAN_CTAG_RX)) { - u16 vid = be16_to_cpu(cqe->sl_vid); + /* This packet is eligible for GRO if it is: + * - DIX Ethernet (type interpretation) + * - TCP/IP (v4) + * - without IP options + * - not an IP fragment + * - no LLS polling in progress + */ + if (!mlx4_en_cq_busy_polling(cq) && + (dev->features & NETIF_F_GRO)) { + struct sk_buff *gro_skb = napi_get_frags(&cq->napi); + if (!gro_skb) + goto next; + + nr = mlx4_en_complete_rx_desc(priv, + rx_desc, frags, gro_skb, + length); + if (!nr) + goto next; + + if (ip_summed == CHECKSUM_COMPLETE) { + void *va = skb_frag_address(skb_shinfo(gro_skb)->frags); + if (check_csum(cqe, gro_skb, va, ring->hwtstamp_rx_filter)) { + ip_summed = CHECKSUM_NONE; + ring->csum_none++; + ring->csum_complete--; + } + } - __vlan_hwaccel_put_tag(gro_skb, htons(ETH_P_8021Q), vid); - } + skb_shinfo(gro_skb)->nr_frags = nr; + gro_skb->len = length; + gro_skb->data_len = length; + gro_skb->ip_summed = ip_summed; - if (dev->features & NETIF_F_RXHASH) - skb_set_hash(gro_skb, - be32_to_cpu(cqe->immed_rss_invalid), - PKT_HASH_TYPE_L3); + if (l2_tunnel && ip_summed == CHECKSUM_UNNECESSARY) + gro_skb->encapsulation = 1; + if ((cqe->vlan_my_qpn & + cpu_to_be32(MLX4_CQE_VLAN_PRESENT_MASK)) && + (dev->features & NETIF_F_HW_VLAN_CTAG_RX)) { + u16 vid = be16_to_cpu(cqe->sl_vid); - skb_record_rx_queue(gro_skb, cq->ring); - skb_mark_napi_id(gro_skb, &cq->napi); + __vlan_hwaccel_put_tag(gro_skb, htons(ETH_P_8021Q), vid); + } - if (ring->hwtstamp_rx_filter == HWTSTAMP_FILTER_ALL) { - timestamp = mlx4_en_get_cqe_ts(cqe); - mlx4_en_fill_hwtstamps(mdev, - skb_hwtstamps(gro_skb), - timestamp); - } + if (dev->features & NETIF_F_RXHASH) + skb_set_hash(gro_skb, + be32_to_cpu(cqe->immed_rss_invalid), + PKT_HASH_TYPE_L3); - napi_gro_frags(&cq->napi); - goto next; - } + skb_record_rx_queue(gro_skb, cq->ring); + skb_mark_napi_id(gro_skb, &cq->napi); - /* GRO not possible, complete processing here */ - ip_summed = CHECKSUM_UNNECESSARY; - } else { - ip_summed = CHECKSUM_NONE; - ring->csum_none++; + if (ring->hwtstamp_rx_filter == HWTSTAMP_FILTER_ALL) { + timestamp = mlx4_en_get_cqe_ts(cqe); + mlx4_en_fill_hwtstamps(mdev, + skb_hwtstamps(gro_skb), + timestamp); } - } else { - ip_summed = CHECKSUM_NONE; - ring->csum_none++; + + napi_gro_frags(&cq->napi); + goto next; } + /* GRO not possible, complete processing here */ skb = mlx4_en_rx_skb(priv, rx_desc, frags, length); if (!skb) { priv->stats.rx_dropped++; @@ -822,6 +928,14 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud goto next; } + if (ip_summed == CHECKSUM_COMPLETE) { + if (check_csum(cqe, skb, skb->data, ring->hwtstamp_rx_filter)) { + ip_summed = CHECKSUM_NONE; + ring->csum_complete--; + ring->csum_none++; + } + } + skb->ip_summed = ip_summed; skb->protocol = eth_type_trans(skb, dev); skb_record_rx_queue(skb, cq->ring); @@ -879,8 +993,8 @@ void mlx4_en_rx_irq(struct mlx4_cq *mcq) struct mlx4_en_cq *cq = container_of(mcq, struct mlx4_en_cq, mcq); struct mlx4_en_priv *priv = netdev_priv(cq->dev); - if (priv->port_up) - napi_schedule(&cq->napi); + if (likely(priv->port_up)) + napi_schedule_irqoff(&cq->napi); else mlx4_en_arm_cq(priv, cq); } @@ -910,20 +1024,18 @@ int mlx4_en_poll_rx_cq(struct napi_struct *napi, int budget) cpu_curr = smp_processor_id(); aff = irq_desc_get_irq_data(cq->irq_desc)->affinity; - if (unlikely(!cpumask_test_cpu(cpu_curr, aff))) { - /* Current cpu is not according to smp_irq_affinity - - * probably affinity changed. need to stop this NAPI - * poll, and restart it on the right CPU - */ - napi_complete(napi); - mlx4_en_arm_cq(priv, cq); - return 0; - } - } else { - /* Done for now */ - napi_complete(napi); - mlx4_en_arm_cq(priv, cq); + if (likely(cpumask_test_cpu(cpu_curr, aff))) + return budget; + + /* Current cpu is not according to smp_irq_affinity - + * probably affinity changed. need to stop this NAPI + * poll, and restart it on the right CPU + */ + done = 0; } + /* Done for now */ + napi_complete_done(napi, done); + mlx4_en_arm_cq(priv, cq); return done; } @@ -946,15 +1058,8 @@ void mlx4_en_calc_rx_buf(struct net_device *dev) (eff_mtu > buf_size + frag_sizes[i]) ? frag_sizes[i] : eff_mtu - buf_size; priv->frag_info[i].frag_prefix_size = buf_size; - if (!i) { - priv->frag_info[i].frag_align = NET_IP_ALIGN; - priv->frag_info[i].frag_stride = - ALIGN(frag_sizes[i] + NET_IP_ALIGN, SMP_CACHE_BYTES); - } else { - priv->frag_info[i].frag_align = 0; - priv->frag_info[i].frag_stride = - ALIGN(frag_sizes[i], SMP_CACHE_BYTES); - } + priv->frag_info[i].frag_stride = ALIGN(frag_sizes[i], + SMP_CACHE_BYTES); buf_size += priv->frag_info[i].frag_size; i++; } @@ -967,11 +1072,10 @@ void mlx4_en_calc_rx_buf(struct net_device *dev) eff_mtu, priv->num_frags); for (i = 0; i < priv->num_frags; i++) { en_err(priv, - " frag:%d - size:%d prefix:%d align:%d stride:%d\n", + " frag:%d - size:%d prefix:%d stride:%d\n", i, priv->frag_info[i].frag_size, priv->frag_info[i].frag_prefix_size, - priv->frag_info[i].frag_align, priv->frag_info[i].frag_stride); } } @@ -1065,9 +1169,6 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv) int i, qpn; int err = 0; int good_qps = 0; - static const u32 rsskey[10] = { 0xD181C62C, 0xF7F4DB5B, 0x1983A2FC, - 0x943E1ADB, 0xD9389E6B, 0xD1039C2C, 0xA74499AD, - 0x593D56D9, 0xF3253C06, 0x2ADC1FFC}; en_dbg(DRV, priv, "Configuring rss steering\n"); err = mlx4_qp_reserve_range(mdev->dev, priv->rx_ring_num, @@ -1122,9 +1223,7 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv) rss_context->flags = rss_mask; rss_context->hash_fn = MLX4_RSS_HASH_TOP; - for (i = 0; i < 10; i++) - rss_context->rss_key[i] = cpu_to_be32(rsskey[i]); - + memcpy(rss_context->rss_key, priv->rss_key, MLX4_EN_RSS_KEY_SIZE); err = mlx4_qp_to_ready(mdev->dev, &priv->res.mtt, &context, &rss_map->indir_qp, &rss_map->indir_state); if (err) diff --git a/drivers/net/ethernet/mellanox/mlx4/en_selftest.c b/drivers/net/ethernet/mellanox/mlx4/en_selftest.c index 49d5afc7cfb8..2d8ee66138e8 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_selftest.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_selftest.c @@ -129,11 +129,15 @@ static int mlx4_en_test_speed(struct mlx4_en_priv *priv) if (mlx4_en_QUERY_PORT(priv->mdev, priv->port)) return -ENOMEM; - /* The device supports 1G, 10G and 40G speeds */ - if (priv->port_state.link_speed != 1000 && - priv->port_state.link_speed != 10000 && - priv->port_state.link_speed != 40000) + /* The device supports 100M, 1G, 10G, 20G, 40G and 56G speed */ + if (priv->port_state.link_speed != SPEED_100 && + priv->port_state.link_speed != SPEED_1000 && + priv->port_state.link_speed != SPEED_10000 && + priv->port_state.link_speed != SPEED_20000 && + priv->port_state.link_speed != SPEED_40000 && + priv->port_state.link_speed != SPEED_56000) return priv->port_state.link_speed; + return 0; } diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c index 454d9fea640e..d0cecbdd9ba8 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c @@ -479,8 +479,8 @@ void mlx4_en_tx_irq(struct mlx4_cq *mcq) struct mlx4_en_cq *cq = container_of(mcq, struct mlx4_en_cq, mcq); struct mlx4_en_priv *priv = netdev_priv(cq->dev); - if (priv->port_up) - napi_schedule(&cq->napi); + if (likely(priv->port_up)) + napi_schedule_irqoff(&cq->napi); else mlx4_en_arm_cq(priv, cq); } diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c index 49290a405903..d68b264cee4d 100644 --- a/drivers/net/ethernet/mellanox/mlx4/eq.c +++ b/drivers/net/ethernet/mellanox/mlx4/eq.c @@ -1123,8 +1123,12 @@ int mlx4_init_eq_table(struct mlx4_dev *dev) goto err_out_free; } - err = mlx4_bitmap_init(&priv->eq_table.bitmap, dev->caps.num_eqs, - dev->caps.num_eqs - 1, dev->caps.reserved_eqs, 0); + err = mlx4_bitmap_init(&priv->eq_table.bitmap, + roundup_pow_of_two(dev->caps.num_eqs), + dev->caps.num_eqs - 1, + dev->caps.reserved_eqs, + roundup_pow_of_two(dev->caps.num_eqs) - + dev->caps.num_eqs); if (err) goto err_out_free; diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c index 2e88a235e26b..4251f81a0275 100644 --- a/drivers/net/ethernet/mellanox/mlx4/fw.c +++ b/drivers/net/ethernet/mellanox/mlx4/fw.c @@ -139,7 +139,12 @@ static void dump_dev_cap_flags2(struct mlx4_dev *dev, u64 flags) [10] = "TCP/IP offloads/flow-steering for VXLAN support", [11] = "MAD DEMUX (Secure-Host) support", [12] = "Large cache line (>64B) CQE stride support", - [13] = "Large cache line (>64B) EQE stride support" + [13] = "Large cache line (>64B) EQE stride support", + [14] = "Ethernet protocol control support", + [15] = "Ethernet Backplane autoneg support", + [16] = "CONFIG DEV support", + [17] = "Asymmetric EQs support", + [18] = "More than 80 VFs support" }; int i; @@ -174,6 +179,61 @@ int mlx4_MOD_STAT_CFG(struct mlx4_dev *dev, struct mlx4_mod_stat_cfg *cfg) return err; } +int mlx4_QUERY_FUNC(struct mlx4_dev *dev, struct mlx4_func *func, int slave) +{ + struct mlx4_cmd_mailbox *mailbox; + u32 *outbox; + u8 in_modifier; + u8 field; + u16 field16; + int err; + +#define QUERY_FUNC_BUS_OFFSET 0x00 +#define QUERY_FUNC_DEVICE_OFFSET 0x01 +#define QUERY_FUNC_FUNCTION_OFFSET 0x01 +#define QUERY_FUNC_PHYSICAL_FUNCTION_OFFSET 0x03 +#define QUERY_FUNC_RSVD_EQS_OFFSET 0x04 +#define QUERY_FUNC_MAX_EQ_OFFSET 0x06 +#define QUERY_FUNC_RSVD_UARS_OFFSET 0x0b + + mailbox = mlx4_alloc_cmd_mailbox(dev); + if (IS_ERR(mailbox)) + return PTR_ERR(mailbox); + outbox = mailbox->buf; + + in_modifier = slave; + + err = mlx4_cmd_box(dev, 0, mailbox->dma, in_modifier, 0, + MLX4_CMD_QUERY_FUNC, + MLX4_CMD_TIME_CLASS_A, + MLX4_CMD_NATIVE); + if (err) + goto out; + + MLX4_GET(field, outbox, QUERY_FUNC_BUS_OFFSET); + func->bus = field & 0xf; + MLX4_GET(field, outbox, QUERY_FUNC_DEVICE_OFFSET); + func->device = field & 0xf1; + MLX4_GET(field, outbox, QUERY_FUNC_FUNCTION_OFFSET); + func->function = field & 0x7; + MLX4_GET(field, outbox, QUERY_FUNC_PHYSICAL_FUNCTION_OFFSET); + func->physical_function = field & 0xf; + MLX4_GET(field16, outbox, QUERY_FUNC_RSVD_EQS_OFFSET); + func->rsvd_eqs = field16 & 0xffff; + MLX4_GET(field16, outbox, QUERY_FUNC_MAX_EQ_OFFSET); + func->max_eq = field16 & 0xffff; + MLX4_GET(field, outbox, QUERY_FUNC_RSVD_UARS_OFFSET); + func->rsvd_uars = field & 0x0f; + + mlx4_dbg(dev, "Bus: %d, Device: %d, Function: %d, Physical function: %d, Max EQs: %d, Reserved EQs: %d, Reserved UARs: %d\n", + func->bus, func->device, func->function, func->physical_function, + func->max_eq, func->rsvd_eqs, func->rsvd_uars); + +out: + mlx4_free_cmd_mailbox(dev, mailbox); + return err; +} + int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr, struct mlx4_cmd_mailbox *inbox, @@ -184,6 +244,7 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave, u8 field, port; u32 size, proxy_qp, qkey; int err = 0; + struct mlx4_func func; #define QUERY_FUNC_CAP_FLAGS_OFFSET 0x0 #define QUERY_FUNC_CAP_NUM_PORTS_OFFSET 0x1 @@ -228,6 +289,7 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave, #define QUERY_FUNC_CAP_VF_ENABLE_QP0 0x08 #define QUERY_FUNC_CAP_FLAGS0_FORCE_PHY_WQE_GID 0x80 +#define QUERY_FUNC_CAP_SUPPORTS_NON_POWER_OF_2_NUM_EQS (1 << 31) if (vhcr->op_modifier == 1) { struct mlx4_active_ports actv_ports = @@ -306,11 +368,24 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave, size = dev->caps.num_cqs; MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET_DEP); - size = dev->caps.num_eqs; - MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MAX_EQ_OFFSET); - - size = dev->caps.reserved_eqs; - MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_RESERVED_EQ_OFFSET); + if (!(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_SYS_EQS) || + mlx4_QUERY_FUNC(dev, &func, slave)) { + size = vhcr->in_modifier & + QUERY_FUNC_CAP_SUPPORTS_NON_POWER_OF_2_NUM_EQS ? + dev->caps.num_eqs : + rounddown_pow_of_two(dev->caps.num_eqs); + MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MAX_EQ_OFFSET); + size = dev->caps.reserved_eqs; + MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_RESERVED_EQ_OFFSET); + } else { + size = vhcr->in_modifier & + QUERY_FUNC_CAP_SUPPORTS_NON_POWER_OF_2_NUM_EQS ? + func.max_eq : + rounddown_pow_of_two(func.max_eq); + MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MAX_EQ_OFFSET); + size = func.rsvd_eqs; + MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_RESERVED_EQ_OFFSET); + } size = priv->mfunc.master.res_tracker.res_alloc[RES_MPT].quota[slave]; MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET); @@ -332,7 +407,7 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave, return err; } -int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u32 gen_or_port, +int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u8 gen_or_port, struct mlx4_func_cap *func_cap) { struct mlx4_cmd_mailbox *mailbox; @@ -340,14 +415,17 @@ int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u32 gen_or_port, u8 field, op_modifier; u32 size, qkey; int err = 0, quotas = 0; + u32 in_modifier; op_modifier = !!gen_or_port; /* 0 = general, 1 = logical port */ + in_modifier = op_modifier ? gen_or_port : + QUERY_FUNC_CAP_SUPPORTS_NON_POWER_OF_2_NUM_EQS; mailbox = mlx4_alloc_cmd_mailbox(dev); if (IS_ERR(mailbox)) return PTR_ERR(mailbox); - err = mlx4_cmd_box(dev, 0, mailbox->dma, gen_or_port, op_modifier, + err = mlx4_cmd_box(dev, 0, mailbox->dma, in_modifier, op_modifier, MLX4_CMD_QUERY_FUNC_CAP, MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); if (err) @@ -519,6 +597,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) #define QUERY_DEV_CAP_MAX_MRW_SZ_OFFSET 0x21 #define QUERY_DEV_CAP_RSVD_MRW_OFFSET 0x22 #define QUERY_DEV_CAP_MAX_MTT_SEG_OFFSET 0x23 +#define QUERY_DEV_CAP_NUM_SYS_EQ_OFFSET 0x26 #define QUERY_DEV_CAP_MAX_AV_OFFSET 0x27 #define QUERY_DEV_CAP_MAX_REQ_QP_OFFSET 0x29 #define QUERY_DEV_CAP_MAX_RES_QP_OFFSET 0x2b @@ -560,6 +639,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) #define QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET 0x76 #define QUERY_DEV_CAP_FLOW_STEERING_MAX_QP_OFFSET 0x77 #define QUERY_DEV_CAP_CQ_EQ_CACHE_LINE_STRIDE 0x7a +#define QUERY_DEV_CAP_ETH_PROT_CTRL_OFFSET 0x7a #define QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET 0x80 #define QUERY_DEV_CAP_QPC_ENTRY_SZ_OFFSET 0x82 #define QUERY_DEV_CAP_AUX_ENTRY_SZ_OFFSET 0x84 @@ -571,8 +651,10 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) #define QUERY_DEV_CAP_MTT_ENTRY_SZ_OFFSET 0x90 #define QUERY_DEV_CAP_D_MPT_ENTRY_SZ_OFFSET 0x92 #define QUERY_DEV_CAP_BMME_FLAGS_OFFSET 0x94 +#define QUERY_DEV_CAP_CONFIG_DEV_OFFSET 0x94 #define QUERY_DEV_CAP_RSVD_LKEY_OFFSET 0x98 #define QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET 0xa0 +#define QUERY_DEV_CAP_ETH_BACKPL_OFFSET 0x9c #define QUERY_DEV_CAP_FW_REASSIGN_MAC 0x9d #define QUERY_DEV_CAP_VXLAN 0x9e #define QUERY_DEV_CAP_MAD_DEMUX_OFFSET 0xb0 @@ -605,7 +687,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MPT_OFFSET); dev_cap->max_mpts = 1 << (field & 0x3f); MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_EQ_OFFSET); - dev_cap->reserved_eqs = field & 0xf; + dev_cap->reserved_eqs = 1 << (field & 0xf); MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_EQ_OFFSET); dev_cap->max_eqs = 1 << (field & 0xf); MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_MTT_OFFSET); @@ -616,6 +698,8 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) dev_cap->reserved_mrws = 1 << (field & 0xf); MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MTT_SEG_OFFSET); dev_cap->max_mtt_seg = 1 << (field & 0x3f); + MLX4_GET(size, outbox, QUERY_DEV_CAP_NUM_SYS_EQ_OFFSET); + dev_cap->num_sys_eqs = size & 0xfff; MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_REQ_QP_OFFSET); dev_cap->max_requester_per_qp = 1 << (field & 0x3f); MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_RES_QP_OFFSET); @@ -737,15 +821,22 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) MLX4_GET(size, outbox, QUERY_DEV_CAP_MAX_DESC_SZ_RQ_OFFSET); dev_cap->max_rq_desc_sz = size; MLX4_GET(field, outbox, QUERY_DEV_CAP_CQ_EQ_CACHE_LINE_STRIDE); + if (field & (1 << 5)) + dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_ETH_PROT_CTRL; if (field & (1 << 6)) dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_CQE_STRIDE; if (field & (1 << 7)) dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_EQE_STRIDE; - MLX4_GET(dev_cap->bmme_flags, outbox, QUERY_DEV_CAP_BMME_FLAGS_OFFSET); + MLX4_GET(field, outbox, QUERY_DEV_CAP_CONFIG_DEV_OFFSET); + if (field & 0x20) + dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_CONFIG_DEV; MLX4_GET(dev_cap->reserved_lkey, outbox, QUERY_DEV_CAP_RSVD_LKEY_OFFSET); + MLX4_GET(field32, outbox, QUERY_DEV_CAP_ETH_BACKPL_OFFSET); + if (field32 & (1 << 0)) + dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_ETH_BACKPL_AN_REP; MLX4_GET(field, outbox, QUERY_DEV_CAP_FW_REASSIGN_MAC); if (field & 1<<6) dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_REASSIGN_MAC_EN; @@ -770,6 +861,8 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_VLAN_CONTROL; if (field32 & (1 << 20)) dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_FSM; + if (field32 & (1 << 21)) + dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_80_VFS; if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) { for (i = 1; i <= dev_cap->num_ports; ++i) { @@ -836,8 +929,11 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) * we can't use any EQs whose doorbell falls on that page, * even if the EQ itself isn't reserved. */ - dev_cap->reserved_eqs = max(dev_cap->reserved_uars * 4, - dev_cap->reserved_eqs); + if (dev_cap->num_sys_eqs == 0) + dev_cap->reserved_eqs = max(dev_cap->reserved_uars * 4, + dev_cap->reserved_eqs); + else + dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_SYS_EQS; mlx4_dbg(dev, "Max ICM size %lld MB\n", (unsigned long long) dev_cap->max_icm_sz >> 20); @@ -847,8 +943,9 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) dev_cap->max_srqs, dev_cap->reserved_srqs, dev_cap->srq_entry_sz); mlx4_dbg(dev, "Max CQs: %d, reserved CQs: %d, entry size: %d\n", dev_cap->max_cqs, dev_cap->reserved_cqs, dev_cap->cqc_entry_sz); - mlx4_dbg(dev, "Max EQs: %d, reserved EQs: %d, entry size: %d\n", - dev_cap->max_eqs, dev_cap->reserved_eqs, dev_cap->eqc_entry_sz); + mlx4_dbg(dev, "Num sys EQs: %d, max EQs: %d, reserved EQs: %d, entry size: %d\n", + dev_cap->num_sys_eqs, dev_cap->max_eqs, dev_cap->reserved_eqs, + dev_cap->eqc_entry_sz); mlx4_dbg(dev, "reserved MPTs: %d, reserved MTTs: %d\n", dev_cap->reserved_mrws, dev_cap->reserved_mtts); mlx4_dbg(dev, "Max PDs: %d, reserved PDs: %d, reserved UARs: %d\n", @@ -1394,6 +1491,7 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param) #define INIT_HCA_AUXC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x50) #define INIT_HCA_EQC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x60) #define INIT_HCA_LOG_EQ_OFFSET (INIT_HCA_QPC_OFFSET + 0x67) +#define INIT_HCA_NUM_SYS_EQS_OFFSET (INIT_HCA_QPC_OFFSET + 0x6a) #define INIT_HCA_RDMARC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x70) #define INIT_HCA_LOG_RD_OFFSET (INIT_HCA_QPC_OFFSET + 0x77) #define INIT_HCA_MCAST_OFFSET 0x0c0 @@ -1497,6 +1595,7 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param) MLX4_PUT(inbox, param->auxc_base, INIT_HCA_AUXC_BASE_OFFSET); MLX4_PUT(inbox, param->eqc_base, INIT_HCA_EQC_BASE_OFFSET); MLX4_PUT(inbox, param->log_num_eqs, INIT_HCA_LOG_EQ_OFFSET); + MLX4_PUT(inbox, param->num_sys_eqs, INIT_HCA_NUM_SYS_EQS_OFFSET); MLX4_PUT(inbox, param->rdmarc_base, INIT_HCA_RDMARC_BASE_OFFSET); MLX4_PUT(inbox, param->log_rd_per_qp, INIT_HCA_LOG_RD_OFFSET); @@ -1607,6 +1706,7 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev, MLX4_GET(param->auxc_base, outbox, INIT_HCA_AUXC_BASE_OFFSET); MLX4_GET(param->eqc_base, outbox, INIT_HCA_EQC_BASE_OFFSET); MLX4_GET(param->log_num_eqs, outbox, INIT_HCA_LOG_EQ_OFFSET); + MLX4_GET(param->num_sys_eqs, outbox, INIT_HCA_NUM_SYS_EQS_OFFSET); MLX4_GET(param->rdmarc_base, outbox, INIT_HCA_RDMARC_BASE_OFFSET); MLX4_GET(param->log_rd_per_qp, outbox, INIT_HCA_LOG_RD_OFFSET); @@ -1841,14 +1941,18 @@ int mlx4_CLOSE_HCA(struct mlx4_dev *dev, int panic) struct mlx4_config_dev { __be32 update_flags; - __be32 rsdv1[3]; + __be32 rsvd1[3]; __be16 vxlan_udp_dport; __be16 rsvd2; + __be32 rsvd3[27]; + __be16 rsvd4; + u8 rsvd5; + u8 rx_checksum_val; }; #define MLX4_VXLAN_UDP_DPORT (1 << 0) -static int mlx4_CONFIG_DEV(struct mlx4_dev *dev, struct mlx4_config_dev *config_dev) +static int mlx4_CONFIG_DEV_set(struct mlx4_dev *dev, struct mlx4_config_dev *config_dev) { int err; struct mlx4_cmd_mailbox *mailbox; @@ -1866,6 +1970,77 @@ static int mlx4_CONFIG_DEV(struct mlx4_dev *dev, struct mlx4_config_dev *config_ return err; } +static int mlx4_CONFIG_DEV_get(struct mlx4_dev *dev, struct mlx4_config_dev *config_dev) +{ + int err; + struct mlx4_cmd_mailbox *mailbox; + + mailbox = mlx4_alloc_cmd_mailbox(dev); + if (IS_ERR(mailbox)) + return PTR_ERR(mailbox); + + err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 1, MLX4_CMD_CONFIG_DEV, + MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); + + if (!err) + memcpy(config_dev, mailbox->buf, sizeof(*config_dev)); + + mlx4_free_cmd_mailbox(dev, mailbox); + return err; +} + +/* Conversion between the HW values and the actual functionality. + * The value represented by the array index, + * and the functionality determined by the flags. + */ +static const u8 config_dev_csum_flags[] = { + [0] = 0, + [1] = MLX4_RX_CSUM_MODE_VAL_NON_TCP_UDP, + [2] = MLX4_RX_CSUM_MODE_VAL_NON_TCP_UDP | + MLX4_RX_CSUM_MODE_L4, + [3] = MLX4_RX_CSUM_MODE_L4 | + MLX4_RX_CSUM_MODE_IP_OK_IP_NON_TCP_UDP | + MLX4_RX_CSUM_MODE_MULTI_VLAN +}; + +int mlx4_config_dev_retrieval(struct mlx4_dev *dev, + struct mlx4_config_dev_params *params) +{ + struct mlx4_config_dev config_dev; + int err; + u8 csum_mask; + +#define CONFIG_DEV_RX_CSUM_MODE_MASK 0x7 +#define CONFIG_DEV_RX_CSUM_MODE_PORT1_BIT_OFFSET 0 +#define CONFIG_DEV_RX_CSUM_MODE_PORT2_BIT_OFFSET 4 + + if (!(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_CONFIG_DEV)) + return -ENOTSUPP; + + err = mlx4_CONFIG_DEV_get(dev, &config_dev); + if (err) + return err; + + csum_mask = (config_dev.rx_checksum_val >> CONFIG_DEV_RX_CSUM_MODE_PORT1_BIT_OFFSET) & + CONFIG_DEV_RX_CSUM_MODE_MASK; + + if (csum_mask >= sizeof(config_dev_csum_flags)/sizeof(config_dev_csum_flags[0])) + return -EINVAL; + params->rx_csum_flags_port_1 = config_dev_csum_flags[csum_mask]; + + csum_mask = (config_dev.rx_checksum_val >> CONFIG_DEV_RX_CSUM_MODE_PORT2_BIT_OFFSET) & + CONFIG_DEV_RX_CSUM_MODE_MASK; + + if (csum_mask >= sizeof(config_dev_csum_flags)/sizeof(config_dev_csum_flags[0])) + return -EINVAL; + params->rx_csum_flags_port_2 = config_dev_csum_flags[csum_mask]; + + params->vxlan_udp_dport = be16_to_cpu(config_dev.vxlan_udp_dport); + + return 0; +} +EXPORT_SYMBOL_GPL(mlx4_config_dev_retrieval); + int mlx4_config_vxlan_port(struct mlx4_dev *dev, __be16 udp_port) { struct mlx4_config_dev config_dev; @@ -1874,7 +2049,7 @@ int mlx4_config_vxlan_port(struct mlx4_dev *dev, __be16 udp_port) config_dev.update_flags = cpu_to_be32(MLX4_VXLAN_UDP_DPORT); config_dev.vxlan_udp_dport = udp_port; - return mlx4_CONFIG_DEV(dev, &config_dev); + return mlx4_CONFIG_DEV_set(dev, &config_dev); } EXPORT_SYMBOL_GPL(mlx4_config_vxlan_port); @@ -2144,3 +2319,142 @@ out: mlx4_free_cmd_mailbox(dev, mailbox); return err; } + +/* Access Reg commands */ +enum mlx4_access_reg_masks { + MLX4_ACCESS_REG_STATUS_MASK = 0x7f, + MLX4_ACCESS_REG_METHOD_MASK = 0x7f, + MLX4_ACCESS_REG_LEN_MASK = 0x7ff +}; + +struct mlx4_access_reg { + __be16 constant1; + u8 status; + u8 resrvd1; + __be16 reg_id; + u8 method; + u8 constant2; + __be32 resrvd2[2]; + __be16 len_const; + __be16 resrvd3; +#define MLX4_ACCESS_REG_HEADER_SIZE (20) + u8 reg_data[MLX4_MAILBOX_SIZE-MLX4_ACCESS_REG_HEADER_SIZE]; +} __attribute__((__packed__)); + +/** + * mlx4_ACCESS_REG - Generic access reg command. + * @dev: mlx4_dev. + * @reg_id: register ID to access. + * @method: Access method Read/Write. + * @reg_len: register length to Read/Write in bytes. + * @reg_data: reg_data pointer to Read/Write From/To. + * + * Access ConnectX registers FW command. + * Returns 0 on success and copies outbox mlx4_access_reg data + * field into reg_data or a negative error code. + */ +static int mlx4_ACCESS_REG(struct mlx4_dev *dev, u16 reg_id, + enum mlx4_access_reg_method method, + u16 reg_len, void *reg_data) +{ + struct mlx4_cmd_mailbox *inbox, *outbox; + struct mlx4_access_reg *inbuf, *outbuf; + int err; + + inbox = mlx4_alloc_cmd_mailbox(dev); + if (IS_ERR(inbox)) + return PTR_ERR(inbox); + + outbox = mlx4_alloc_cmd_mailbox(dev); + if (IS_ERR(outbox)) { + mlx4_free_cmd_mailbox(dev, inbox); + return PTR_ERR(outbox); + } + + inbuf = inbox->buf; + outbuf = outbox->buf; + + inbuf->constant1 = cpu_to_be16(0x1<<11 | 0x4); + inbuf->constant2 = 0x1; + inbuf->reg_id = cpu_to_be16(reg_id); + inbuf->method = method & MLX4_ACCESS_REG_METHOD_MASK; + + reg_len = min(reg_len, (u16)(sizeof(inbuf->reg_data))); + inbuf->len_const = + cpu_to_be16(((reg_len/4 + 1) & MLX4_ACCESS_REG_LEN_MASK) | + ((0x3) << 12)); + + memcpy(inbuf->reg_data, reg_data, reg_len); + err = mlx4_cmd_box(dev, inbox->dma, outbox->dma, 0, 0, + MLX4_CMD_ACCESS_REG, MLX4_CMD_TIME_CLASS_C, + MLX4_CMD_WRAPPED); + if (err) + goto out; + + if (outbuf->status & MLX4_ACCESS_REG_STATUS_MASK) { + err = outbuf->status & MLX4_ACCESS_REG_STATUS_MASK; + mlx4_err(dev, + "MLX4_CMD_ACCESS_REG(%x) returned REG status (%x)\n", + reg_id, err); + goto out; + } + + memcpy(reg_data, outbuf->reg_data, reg_len); +out: + mlx4_free_cmd_mailbox(dev, inbox); + mlx4_free_cmd_mailbox(dev, outbox); + return err; +} + +/* ConnectX registers IDs */ +enum mlx4_reg_id { + MLX4_REG_ID_PTYS = 0x5004, +}; + +/** + * mlx4_ACCESS_PTYS_REG - Access PTYs (Port Type and Speed) + * register + * @dev: mlx4_dev. + * @method: Access method Read/Write. + * @ptys_reg: PTYS register data pointer. + * + * Access ConnectX PTYS register, to Read/Write Port Type/Speed + * configuration + * Returns 0 on success or a negative error code. + */ +int mlx4_ACCESS_PTYS_REG(struct mlx4_dev *dev, + enum mlx4_access_reg_method method, + struct mlx4_ptys_reg *ptys_reg) +{ + return mlx4_ACCESS_REG(dev, MLX4_REG_ID_PTYS, + method, sizeof(*ptys_reg), ptys_reg); +} +EXPORT_SYMBOL_GPL(mlx4_ACCESS_PTYS_REG); + +int mlx4_ACCESS_REG_wrapper(struct mlx4_dev *dev, int slave, + struct mlx4_vhcr *vhcr, + struct mlx4_cmd_mailbox *inbox, + struct mlx4_cmd_mailbox *outbox, + struct mlx4_cmd_info *cmd) +{ + struct mlx4_access_reg *inbuf = inbox->buf; + u8 method = inbuf->method & MLX4_ACCESS_REG_METHOD_MASK; + u16 reg_id = be16_to_cpu(inbuf->reg_id); + + if (slave != mlx4_master_func_num(dev) && + method == MLX4_ACCESS_REG_WRITE) + return -EPERM; + + if (reg_id == MLX4_REG_ID_PTYS) { + struct mlx4_ptys_reg *ptys_reg = + (struct mlx4_ptys_reg *)inbuf->reg_data; + + ptys_reg->local_port = + mlx4_slave_convert_port(dev, slave, + ptys_reg->local_port); + } + + return mlx4_cmd_box(dev, inbox->dma, outbox->dma, vhcr->in_modifier, + 0, MLX4_CMD_ACCESS_REG, MLX4_CMD_TIME_CLASS_C, + MLX4_CMD_NATIVE); +} diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.h b/drivers/net/ethernet/mellanox/mlx4/fw.h index 9b835aecac96..475215ee370f 100644 --- a/drivers/net/ethernet/mellanox/mlx4/fw.h +++ b/drivers/net/ethernet/mellanox/mlx4/fw.h @@ -56,6 +56,7 @@ struct mlx4_dev_cap { int max_mpts; int reserved_eqs; int max_eqs; + int num_sys_eqs; int reserved_mtts; int max_mrw_sz; int reserved_mrws; @@ -145,6 +146,16 @@ struct mlx4_func_cap { u64 phys_port_id; }; +struct mlx4_func { + int bus; + int device; + int function; + int physical_function; + int rsvd_eqs; + int max_eq; + int rsvd_uars; +}; + struct mlx4_adapter { char board_id[MLX4_BOARD_ID_LEN]; u8 inta_pin; @@ -170,6 +181,7 @@ struct mlx4_init_hca_param { u8 log_num_srqs; u8 log_num_cqs; u8 log_num_eqs; + u16 num_sys_eqs; u8 log_rd_per_qp; u8 log_mc_table_sz; u8 log_mpt_sz; @@ -204,13 +216,14 @@ struct mlx4_set_ib_param { }; int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap); -int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u32 gen_or_port, +int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u8 gen_or_port, struct mlx4_func_cap *func_cap); int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr, struct mlx4_cmd_mailbox *inbox, struct mlx4_cmd_mailbox *outbox, struct mlx4_cmd_info *cmd); +int mlx4_QUERY_FUNC(struct mlx4_dev *dev, struct mlx4_func *func, int slave); int mlx4_MAP_FA(struct mlx4_dev *dev, struct mlx4_icm *icm); int mlx4_UNMAP_FA(struct mlx4_dev *dev); int mlx4_RUN_FW(struct mlx4_dev *dev); diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 90de6e1ad06e..3044f9e623cb 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -197,6 +197,29 @@ static void mlx4_set_port_mask(struct mlx4_dev *dev) dev->caps.port_mask[i] = dev->caps.port_type[i]; } +enum { + MLX4_QUERY_FUNC_NUM_SYS_EQS = 1 << 0, +}; + +static int mlx4_query_func(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) +{ + int err = 0; + struct mlx4_func func; + + if (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_SYS_EQS) { + err = mlx4_QUERY_FUNC(dev, &func, 0); + if (err) { + mlx4_err(dev, "QUERY_DEV_CAP command failed, aborting.\n"); + return err; + } + dev_cap->max_eqs = func.max_eq; + dev_cap->reserved_eqs = func.rsvd_eqs; + dev_cap->reserved_uars = func.rsvd_uars; + err |= MLX4_QUERY_FUNC_NUM_SYS_EQS; + } + return err; +} + static void mlx4_enable_cqe_eqe_stride(struct mlx4_dev *dev) { struct mlx4_caps *dev_cap = &dev->caps; @@ -261,7 +284,10 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) } dev->caps.num_ports = dev_cap->num_ports; - dev->phys_caps.num_phys_eqs = MLX4_MAX_EQ_NUM; + dev->caps.num_sys_eqs = dev_cap->num_sys_eqs; + dev->phys_caps.num_phys_eqs = dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_SYS_EQS ? + dev->caps.num_sys_eqs : + MLX4_MAX_EQ_NUM; for (i = 1; i <= dev->caps.num_ports; ++i) { dev->caps.vl_cap[i] = dev_cap->max_vl[i]; dev->caps.ib_mtu_cap[i] = dev_cap->ib_mtu[i]; @@ -631,7 +657,7 @@ static int mlx4_slave_cap(struct mlx4_dev *dev) struct mlx4_dev_cap dev_cap; struct mlx4_func_cap func_cap; struct mlx4_init_hca_param hca_param; - int i; + u8 i; memset(&hca_param, 0, sizeof(hca_param)); err = mlx4_QUERY_HCA(dev, &hca_param); @@ -732,7 +758,7 @@ static int mlx4_slave_cap(struct mlx4_dev *dev) } for (i = 1; i <= dev->caps.num_ports; ++i) { - err = mlx4_QUERY_FUNC_CAP(dev, (u32) i, &func_cap); + err = mlx4_QUERY_FUNC_CAP(dev, i, &func_cap); if (err) { mlx4_err(dev, "QUERY_FUNC_CAP port command failed for port %d, aborting (%d)\n", i, err); @@ -901,9 +927,12 @@ static ssize_t set_port_type(struct device *dev, struct mlx4_priv *priv = mlx4_priv(mdev); enum mlx4_port_type types[MLX4_MAX_PORTS]; enum mlx4_port_type new_types[MLX4_MAX_PORTS]; + static DEFINE_MUTEX(set_port_type_mutex); int i; int err = 0; + mutex_lock(&set_port_type_mutex); + if (!strcmp(buf, "ib\n")) info->tmp_type = MLX4_PORT_TYPE_IB; else if (!strcmp(buf, "eth\n")) @@ -912,7 +941,8 @@ static ssize_t set_port_type(struct device *dev, info->tmp_type = MLX4_PORT_TYPE_AUTO; else { mlx4_err(mdev, "%s is not supported port type\n", buf); - return -EINVAL; + err = -EINVAL; + goto err_out; } mlx4_stop_sense(mdev); @@ -958,6 +988,9 @@ static ssize_t set_port_type(struct device *dev, out: mlx4_start_sense(mdev); mutex_unlock(&priv->port_mutex); +err_out: + mutex_unlock(&set_port_type_mutex); + return err ? err : count; } @@ -1123,8 +1156,7 @@ static int mlx4_init_cmpt_table(struct mlx4_dev *dev, u64 cmpt_base, if (err) goto err_srq; - num_eqs = (mlx4_is_master(dev)) ? dev->phys_caps.num_phys_eqs : - dev->caps.num_eqs; + num_eqs = dev->phys_caps.num_phys_eqs; err = mlx4_init_icm_table(dev, &priv->eq_table.cmpt_table, cmpt_base + ((u64) (MLX4_CMPT_TYPE_EQ * @@ -1186,8 +1218,7 @@ static int mlx4_init_icm(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap, } - num_eqs = (mlx4_is_master(dev)) ? dev->phys_caps.num_phys_eqs : - dev->caps.num_eqs; + num_eqs = dev->phys_caps.num_phys_eqs; err = mlx4_init_icm_table(dev, &priv->eq_table.table, init_hca->eqc_base, dev_cap->eqc_entry_sz, num_eqs, num_eqs, 0, 0); @@ -1466,6 +1497,12 @@ static void mlx4_close_hca(struct mlx4_dev *dev) else { mlx4_CLOSE_HCA(dev, 0); mlx4_free_icms(dev); + } +} + +static void mlx4_close_fw(struct mlx4_dev *dev) +{ + if (!mlx4_is_slave(dev)) { mlx4_UNMAP_FA(dev); mlx4_free_icm(dev, mlx4_priv(dev)->fw.fw_icm, 0); } @@ -1612,16 +1649,10 @@ static void choose_tunnel_offload_mode(struct mlx4_dev *dev, == MLX4_TUNNEL_OFFLOAD_MODE_VXLAN) ? "vxlan" : "none"); } -static int mlx4_init_hca(struct mlx4_dev *dev) +static int mlx4_init_fw(struct mlx4_dev *dev) { - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_adapter adapter; - struct mlx4_dev_cap dev_cap; struct mlx4_mod_stat_cfg mlx4_cfg; - struct mlx4_profile profile; - struct mlx4_init_hca_param init_hca; - u64 icm_size; - int err; + int err = 0; if (!mlx4_is_slave(dev)) { err = mlx4_QUERY_FW(dev); @@ -1644,7 +1675,23 @@ static int mlx4_init_hca(struct mlx4_dev *dev) err = mlx4_MOD_STAT_CFG(dev, &mlx4_cfg); if (err) mlx4_warn(dev, "Failed to override log_pg_sz parameter\n"); + } + + return err; +} + +static int mlx4_init_hca(struct mlx4_dev *dev) +{ + struct mlx4_priv *priv = mlx4_priv(dev); + struct mlx4_adapter adapter; + struct mlx4_dev_cap dev_cap; + struct mlx4_profile profile; + struct mlx4_init_hca_param init_hca; + u64 icm_size; + struct mlx4_config_dev_params params; + int err; + if (!mlx4_is_slave(dev)) { err = mlx4_dev_cap(dev, &dev_cap); if (err) { mlx4_err(dev, "QUERY_DEV_CAP command failed, aborting\n"); @@ -1696,6 +1743,19 @@ static int mlx4_init_hca(struct mlx4_dev *dev) mlx4_err(dev, "INIT_HCA command failed, aborting\n"); goto err_free_icm; } + + if (dev_cap.flags2 & MLX4_DEV_CAP_FLAG2_SYS_EQS) { + err = mlx4_query_func(dev, &dev_cap); + if (err < 0) { + mlx4_err(dev, "QUERY_FUNC command failed, aborting.\n"); + goto err_stop_fw; + } else if (err & MLX4_QUERY_FUNC_NUM_SYS_EQS) { + dev->caps.num_eqs = dev_cap.max_eqs; + dev->caps.reserved_eqs = dev_cap.reserved_eqs; + dev->caps.reserved_uars = dev_cap.reserved_uars; + } + } + /* * If TS is supported by FW * read HCA frequency by QUERY_HCA command @@ -1755,6 +1815,14 @@ static int mlx4_init_hca(struct mlx4_dev *dev) goto unmap_bf; } + /* Query CONFIG_DEV parameters */ + err = mlx4_config_dev_retrieval(dev, ¶ms); + if (err && err != -ENOTSUPP) { + mlx4_err(dev, "Failed to query CONFIG_DEV parameters\n"); + } else if (!err) { + dev->caps.rx_checksum_flags_port[1] = params.rx_csum_flags_port_1; + dev->caps.rx_checksum_flags_port[2] = params.rx_csum_flags_port_2; + } priv->eq_table.inta_pin = adapter.inta_pin; memcpy(dev->board_id, adapter.board_id, sizeof dev->board_id); @@ -2054,12 +2122,11 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev) { struct mlx4_priv *priv = mlx4_priv(dev); struct msix_entry *entries; - int nreq = min_t(int, dev->caps.num_ports * - min_t(int, num_online_cpus() + 1, - MAX_MSIX_P_PORT) + MSIX_LEGACY_SZ, MAX_MSIX); int i; if (msi_x) { + int nreq = dev->caps.num_ports * num_online_cpus() + MSIX_LEGACY_SZ; + nreq = min_t(int, dev->caps.num_eqs - dev->caps.reserved_eqs, nreq); @@ -2259,6 +2326,71 @@ static void mlx4_free_ownership(struct mlx4_dev *dev) iounmap(owner); } +#define SRIOV_VALID_STATE(flags) (!!((flags) & MLX4_FLAG_SRIOV) ==\ + !!((flags) & MLX4_FLAG_MASTER)) + +static u64 mlx4_enable_sriov(struct mlx4_dev *dev, struct pci_dev *pdev, + u8 total_vfs, int existing_vfs) +{ + u64 dev_flags = dev->flags; + + dev->dev_vfs = kzalloc( + total_vfs * sizeof(*dev->dev_vfs), + GFP_KERNEL); + if (NULL == dev->dev_vfs) { + mlx4_err(dev, "Failed to allocate memory for VFs\n"); + goto disable_sriov; + } else if (!(dev->flags & MLX4_FLAG_SRIOV)) { + int err = 0; + + atomic_inc(&pf_loading); + if (existing_vfs) { + if (existing_vfs != total_vfs) + mlx4_err(dev, "SR-IOV was already enabled, but with num_vfs (%d) different than requested (%d)\n", + existing_vfs, total_vfs); + } else { + mlx4_warn(dev, "Enabling SR-IOV with %d VFs\n", total_vfs); + err = pci_enable_sriov(pdev, total_vfs); + } + if (err) { + mlx4_err(dev, "Failed to enable SR-IOV, continuing without SR-IOV (err = %d)\n", + err); + atomic_dec(&pf_loading); + goto disable_sriov; + } else { + mlx4_warn(dev, "Running in master mode\n"); + dev_flags |= MLX4_FLAG_SRIOV | + MLX4_FLAG_MASTER; + dev_flags &= ~MLX4_FLAG_SLAVE; + dev->num_vfs = total_vfs; + } + } + return dev_flags; + +disable_sriov: + dev->num_vfs = 0; + kfree(dev->dev_vfs); + return dev_flags & ~MLX4_FLAG_MASTER; +} + +enum { + MLX4_DEV_CAP_CHECK_NUM_VFS_ABOVE_64 = -1, +}; + +static int mlx4_check_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap, + int *nvfs) +{ + int requested_vfs = nvfs[0] + nvfs[1] + nvfs[2]; + /* Checking for 64 VFs as a limitation of CX2 */ + if (!(dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_80_VFS) && + requested_vfs >= 64) { + mlx4_err(dev, "Requested %d VFs, but FW does not support more than 64\n", + requested_vfs); + return MLX4_DEV_CAP_CHECK_NUM_VFS_ABOVE_64; + } + return 0; +} + static int mlx4_load_one(struct pci_dev *pdev, int pci_dev_data, int total_vfs, int *nvfs, struct mlx4_priv *priv) { @@ -2267,6 +2399,7 @@ static int mlx4_load_one(struct pci_dev *pdev, int pci_dev_data, int err; int port; int i; + struct mlx4_dev_cap *dev_cap = NULL; int existing_vfs = 0; dev = &priv->dev; @@ -2303,40 +2436,6 @@ static int mlx4_load_one(struct pci_dev *pdev, int pci_dev_data, } } - if (total_vfs) { - mlx4_warn(dev, "Enabling SR-IOV with %d VFs\n", - total_vfs); - dev->dev_vfs = kzalloc( - total_vfs * sizeof(*dev->dev_vfs), - GFP_KERNEL); - if (NULL == dev->dev_vfs) { - mlx4_err(dev, "Failed to allocate memory for VFs\n"); - err = -ENOMEM; - goto err_free_own; - } else { - atomic_inc(&pf_loading); - existing_vfs = pci_num_vf(pdev); - if (existing_vfs) { - err = 0; - if (existing_vfs != total_vfs) - mlx4_err(dev, "SR-IOV was already enabled, but with num_vfs (%d) different than requested (%d)\n", - existing_vfs, total_vfs); - } else { - err = pci_enable_sriov(pdev, total_vfs); - } - if (err) { - mlx4_err(dev, "Failed to enable SR-IOV, continuing without SR-IOV (err = %d)\n", - err); - atomic_dec(&pf_loading); - } else { - mlx4_warn(dev, "Running in master mode\n"); - dev->flags |= MLX4_FLAG_SRIOV | - MLX4_FLAG_MASTER; - dev->num_vfs = total_vfs; - } - } - } - atomic_set(&priv->opreq_count, 0); INIT_WORK(&priv->opreq_task, mlx4_opreq_action); @@ -2350,6 +2449,12 @@ static int mlx4_load_one(struct pci_dev *pdev, int pci_dev_data, mlx4_err(dev, "Failed to reset HCA, aborting\n"); goto err_sriov; } + + if (total_vfs) { + existing_vfs = pci_num_vf(pdev); + dev->flags = MLX4_FLAG_MASTER; + dev->num_vfs = total_vfs; + } } slave_start: @@ -2363,9 +2468,10 @@ slave_start: * before posting commands. Also, init num_slaves before calling * mlx4_init_hca */ if (mlx4_is_mfunc(dev)) { - if (mlx4_is_master(dev)) + if (mlx4_is_master(dev)) { dev->num_slaves = MLX4_MAX_NUM_SLAVES; - else { + + } else { dev->num_slaves = 0; err = mlx4_multi_func_init(dev); if (err) { @@ -2375,17 +2481,109 @@ slave_start: } } + err = mlx4_init_fw(dev); + if (err) { + mlx4_err(dev, "Failed to init fw, aborting.\n"); + goto err_mfunc; + } + + if (mlx4_is_master(dev)) { + if (!dev_cap) { + dev_cap = kzalloc(sizeof(*dev_cap), GFP_KERNEL); + + if (!dev_cap) { + err = -ENOMEM; + goto err_fw; + } + + err = mlx4_QUERY_DEV_CAP(dev, dev_cap); + if (err) { + mlx4_err(dev, "QUERY_DEV_CAP command failed, aborting.\n"); + goto err_fw; + } + + if (mlx4_check_dev_cap(dev, dev_cap, nvfs)) + goto err_fw; + + if (!(dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_SYS_EQS)) { + u64 dev_flags = mlx4_enable_sriov(dev, pdev, total_vfs, + existing_vfs); + + mlx4_cmd_cleanup(dev, MLX4_CMD_CLEANUP_ALL); + dev->flags = dev_flags; + if (!SRIOV_VALID_STATE(dev->flags)) { + mlx4_err(dev, "Invalid SRIOV state\n"); + goto err_sriov; + } + err = mlx4_reset(dev); + if (err) { + mlx4_err(dev, "Failed to reset HCA, aborting.\n"); + goto err_sriov; + } + goto slave_start; + } + } else { + /* Legacy mode FW requires SRIOV to be enabled before + * doing QUERY_DEV_CAP, since max_eq's value is different if + * SRIOV is enabled. + */ + memset(dev_cap, 0, sizeof(*dev_cap)); + err = mlx4_QUERY_DEV_CAP(dev, dev_cap); + if (err) { + mlx4_err(dev, "QUERY_DEV_CAP command failed, aborting.\n"); + goto err_fw; + } + + if (mlx4_check_dev_cap(dev, dev_cap, nvfs)) + goto err_fw; + } + } + err = mlx4_init_hca(dev); if (err) { if (err == -EACCES) { /* Not primary Physical function * Running in slave mode */ - mlx4_cmd_cleanup(dev); + mlx4_cmd_cleanup(dev, MLX4_CMD_CLEANUP_ALL); + /* We're not a PF */ + if (dev->flags & MLX4_FLAG_SRIOV) { + if (!existing_vfs) + pci_disable_sriov(pdev); + if (mlx4_is_master(dev)) + atomic_dec(&pf_loading); + dev->flags &= ~MLX4_FLAG_SRIOV; + } + if (!mlx4_is_slave(dev)) + mlx4_free_ownership(dev); dev->flags |= MLX4_FLAG_SLAVE; dev->flags &= ~MLX4_FLAG_MASTER; goto slave_start; } else - goto err_mfunc; + goto err_fw; + } + + if (mlx4_is_master(dev) && (dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_SYS_EQS)) { + u64 dev_flags = mlx4_enable_sriov(dev, pdev, total_vfs, existing_vfs); + + if ((dev->flags ^ dev_flags) & (MLX4_FLAG_MASTER | MLX4_FLAG_SLAVE)) { + mlx4_cmd_cleanup(dev, MLX4_CMD_CLEANUP_VHCR); + dev->flags = dev_flags; + err = mlx4_cmd_init(dev); + if (err) { + /* Only VHCR is cleaned up, so could still + * send FW commands + */ + mlx4_err(dev, "Failed to init VHCR command interface, aborting\n"); + goto err_close; + } + } else { + dev->flags = dev_flags; + } + + if (!SRIOV_VALID_STATE(dev->flags)) { + mlx4_err(dev, "Invalid SRIOV state\n"); + goto err_close; + } } /* check if the device is functioning at its maximum possible speed. @@ -2540,12 +2738,15 @@ err_master_mfunc: err_close: mlx4_close_hca(dev); +err_fw: + mlx4_close_fw(dev); + err_mfunc: if (mlx4_is_slave(dev)) mlx4_multi_func_cleanup(dev); err_cmd: - mlx4_cmd_cleanup(dev); + mlx4_cmd_cleanup(dev, MLX4_CMD_CLEANUP_ALL); err_sriov: if (dev->flags & MLX4_FLAG_SRIOV && !existing_vfs) @@ -2556,10 +2757,10 @@ err_sriov: kfree(priv->dev.dev_vfs); -err_free_own: if (!mlx4_is_slave(dev)) mlx4_free_ownership(dev); + kfree(dev_cap); return err; } @@ -2787,15 +2988,17 @@ static void mlx4_unload_one(struct pci_dev *pdev) if (mlx4_is_master(dev)) mlx4_multi_func_cleanup(dev); mlx4_close_hca(dev); + mlx4_close_fw(dev); if (mlx4_is_slave(dev)) mlx4_multi_func_cleanup(dev); - mlx4_cmd_cleanup(dev); + mlx4_cmd_cleanup(dev, MLX4_CMD_CLEANUP_ALL); if (dev->flags & MLX4_FLAG_MSI_X) pci_disable_msix(pdev); if (dev->flags & MLX4_FLAG_SRIOV && !active_vfs) { mlx4_warn(dev, "Disabling SR-IOV\n"); pci_disable_sriov(pdev); + dev->flags &= ~MLX4_FLAG_SRIOV; dev->num_vfs = 0; } diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index de10dbb2e6ed..f48e7c3eecf8 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h @@ -606,6 +606,7 @@ struct mlx4_cmd { u8 use_events; u8 toggle; u8 comm_toggle; + u8 initialized; }; enum { @@ -947,6 +948,11 @@ int mlx4_SW2HW_EQ_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_cmd_mailbox *inbox, struct mlx4_cmd_mailbox *outbox, struct mlx4_cmd_info *cmd); +int mlx4_CONFIG_DEV_wrapper(struct mlx4_dev *dev, int slave, + struct mlx4_vhcr *vhcr, + struct mlx4_cmd_mailbox *inbox, + struct mlx4_cmd_mailbox *outbox, + struct mlx4_cmd_info *cmd); int mlx4_DMA_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr, struct mlx4_cmd_mailbox *inbox, @@ -1121,8 +1127,16 @@ int mlx4_QUERY_QP_wrapper(struct mlx4_dev *dev, int slave, int mlx4_GEN_EQE(struct mlx4_dev *dev, int slave, struct mlx4_eqe *eqe); +enum { + MLX4_CMD_CLEANUP_STRUCT = 1UL << 0, + MLX4_CMD_CLEANUP_POOL = 1UL << 1, + MLX4_CMD_CLEANUP_HCR = 1UL << 2, + MLX4_CMD_CLEANUP_VHCR = 1UL << 3, + MLX4_CMD_CLEANUP_ALL = (MLX4_CMD_CLEANUP_VHCR << 1) - 1 +}; + int mlx4_cmd_init(struct mlx4_dev *dev); -void mlx4_cmd_cleanup(struct mlx4_dev *dev); +void mlx4_cmd_cleanup(struct mlx4_dev *dev, int cleanup_mask); int mlx4_multi_func_init(struct mlx4_dev *dev); void mlx4_multi_func_cleanup(struct mlx4_dev *dev); void mlx4_cmd_event(struct mlx4_dev *dev, u16 token, u8 status, u64 out_param); @@ -1273,6 +1287,11 @@ int mlx4_QP_FLOW_STEERING_DETACH_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_cmd_mailbox *inbox, struct mlx4_cmd_mailbox *outbox, struct mlx4_cmd_info *cmd); +int mlx4_ACCESS_REG_wrapper(struct mlx4_dev *dev, int slave, + struct mlx4_vhcr *vhcr, + struct mlx4_cmd_mailbox *inbox, + struct mlx4_cmd_mailbox *outbox, + struct mlx4_cmd_info *cmd); int mlx4_get_mgm_entry_size(struct mlx4_dev *dev); int mlx4_get_qp_per_mgm(struct mlx4_dev *dev); diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h index 8fef65840b3b..aaa7efbb9664 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h @@ -326,6 +326,7 @@ struct mlx4_en_rx_ring { #endif unsigned long csum_ok; unsigned long csum_none; + unsigned long csum_complete; int hwtstamp_rx_filter; cpumask_var_t affinity_mask; }; @@ -421,10 +422,16 @@ struct mlx4_en_rss_map { enum mlx4_qp_state indir_state; }; +enum mlx4_en_port_flag { + MLX4_EN_PORT_ANC = 1<<0, /* Auto-negotiation complete */ + MLX4_EN_PORT_ANE = 1<<1, /* Auto-negotiation enabled */ +}; + struct mlx4_en_port_state { int link_state; int link_speed; - int transciver; + int transceiver; + u32 flags; }; struct mlx4_en_pkt_stats { @@ -443,6 +450,7 @@ struct mlx4_en_port_stats { unsigned long rx_alloc_failed; unsigned long rx_chksum_good; unsigned long rx_chksum_none; + unsigned long rx_chksum_complete; unsigned long tx_chksum_offload; #define NUM_PORT_STATS 9 }; @@ -475,7 +483,6 @@ struct mlx4_en_frag_info { u16 frag_size; u16 frag_prefix_size; u16 frag_stride; - u16 frag_align; }; #ifdef CONFIG_MLX4_EN_DCB @@ -502,7 +509,8 @@ enum { MLX4_EN_FLAG_ENABLE_HW_LOOPBACK = (1 << 2), /* whether we need to drop packets that hardware loopback-ed */ MLX4_EN_FLAG_RX_FILTER_NEEDED = (1 << 3), - MLX4_EN_FLAG_FORCE_PROMISC = (1 << 4) + MLX4_EN_FLAG_FORCE_PROMISC = (1 << 4), + MLX4_EN_FLAG_RX_CSUM_NON_TCP_UDP = (1 << 5), }; #define MLX4_EN_MAC_HASH_SIZE (1 << BITS_PER_BYTE) @@ -610,6 +618,7 @@ struct mlx4_en_priv { __be16 vxlan_port; u32 pflags; + u8 rss_key[MLX4_EN_RSS_KEY_SIZE]; }; enum mlx4_en_wol { @@ -829,6 +838,13 @@ void mlx4_en_cleanup_filters(struct mlx4_en_priv *priv); void mlx4_en_ex_selftest(struct net_device *dev, u32 *flags, u64 *buf); void mlx4_en_ptp_overflow_check(struct mlx4_en_dev *mdev); +#define DEV_FEATURE_CHANGED(dev, new_features, feature) \ + ((dev->features & feature) ^ (new_features & feature)) + +int mlx4_en_reset_config(struct net_device *dev, + struct hwtstamp_config ts_config, + netdev_features_t new_features); + /* * Functions for time stamping */ @@ -838,9 +854,6 @@ void mlx4_en_fill_hwtstamps(struct mlx4_en_dev *mdev, u64 timestamp); void mlx4_en_init_timestamp(struct mlx4_en_dev *mdev); void mlx4_en_remove_timestamp(struct mlx4_en_dev *mdev); -int mlx4_en_timestamp_config(struct net_device *dev, - int tx_type, - int rx_filter); /* Globals */ diff --git a/drivers/net/ethernet/mellanox/mlx4/mr.c b/drivers/net/ethernet/mellanox/mlx4/mr.c index 193a6adb5d04..d6f549685c0f 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mr.c +++ b/drivers/net/ethernet/mellanox/mlx4/mr.c @@ -130,10 +130,7 @@ static int mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order) err_out_free: for (i = 0; i <= buddy->max_order; ++i) - if (buddy->bits[i] && is_vmalloc_addr(buddy->bits[i])) - vfree(buddy->bits[i]); - else - kfree(buddy->bits[i]); + kvfree(buddy->bits[i]); err_out: kfree(buddy->bits); @@ -147,10 +144,7 @@ static void mlx4_buddy_cleanup(struct mlx4_buddy *buddy) int i; for (i = 0; i <= buddy->max_order; ++i) - if (is_vmalloc_addr(buddy->bits[i])) - vfree(buddy->bits[i]); - else - kfree(buddy->bits[i]); + kvfree(buddy->bits[i]); kfree(buddy->bits); kfree(buddy->num_free); diff --git a/drivers/net/ethernet/mellanox/mlx4/port.c b/drivers/net/ethernet/mellanox/mlx4/port.c index 94eeb2c7d7e4..30eb1ead0fe6 100644 --- a/drivers/net/ethernet/mellanox/mlx4/port.c +++ b/drivers/net/ethernet/mellanox/mlx4/port.c @@ -1311,3 +1311,159 @@ int mlx4_get_roce_gid_from_slave(struct mlx4_dev *dev, int port, int slave_id, return 0; } EXPORT_SYMBOL(mlx4_get_roce_gid_from_slave); + +/* Cable Module Info */ +#define MODULE_INFO_MAX_READ 48 + +#define I2C_ADDR_LOW 0x50 +#define I2C_ADDR_HIGH 0x51 +#define I2C_PAGE_SIZE 256 + +/* Module Info Data */ +struct mlx4_cable_info { + u8 i2c_addr; + u8 page_num; + __be16 dev_mem_address; + __be16 reserved1; + __be16 size; + __be32 reserved2[2]; + u8 data[MODULE_INFO_MAX_READ]; +}; + +enum cable_info_err { + CABLE_INF_INV_PORT = 0x1, + CABLE_INF_OP_NOSUP = 0x2, + CABLE_INF_NOT_CONN = 0x3, + CABLE_INF_NO_EEPRM = 0x4, + CABLE_INF_PAGE_ERR = 0x5, + CABLE_INF_INV_ADDR = 0x6, + CABLE_INF_I2C_ADDR = 0x7, + CABLE_INF_QSFP_VIO = 0x8, + CABLE_INF_I2C_BUSY = 0x9, +}; + +#define MAD_STATUS_2_CABLE_ERR(mad_status) ((mad_status >> 8) & 0xFF) + +static inline const char *cable_info_mad_err_str(u16 mad_status) +{ + u8 err = MAD_STATUS_2_CABLE_ERR(mad_status); + + switch (err) { + case CABLE_INF_INV_PORT: + return "invalid port selected"; + case CABLE_INF_OP_NOSUP: + return "operation not supported for this port (the port is of type CX4 or internal)"; + case CABLE_INF_NOT_CONN: + return "cable is not connected"; + case CABLE_INF_NO_EEPRM: + return "the connected cable has no EPROM (passive copper cable)"; + case CABLE_INF_PAGE_ERR: + return "page number is greater than 15"; + case CABLE_INF_INV_ADDR: + return "invalid device_address or size (that is, size equals 0 or address+size is greater than 256)"; + case CABLE_INF_I2C_ADDR: + return "invalid I2C slave address"; + case CABLE_INF_QSFP_VIO: + return "at least one cable violates the QSFP specification and ignores the modsel signal"; + case CABLE_INF_I2C_BUSY: + return "I2C bus is constantly busy"; + } + return "Unknown Error"; +} + +/** + * mlx4_get_module_info - Read cable module eeprom data + * @dev: mlx4_dev. + * @port: port number. + * @offset: byte offset in eeprom to start reading data from. + * @size: num of bytes to read. + * @data: output buffer to put the requested data into. + * + * Reads cable module eeprom data, puts the outcome data into + * data pointer paramer. + * Returns num of read bytes on success or a negative error + * code. + */ +int mlx4_get_module_info(struct mlx4_dev *dev, u8 port, + u16 offset, u16 size, u8 *data) +{ + struct mlx4_cmd_mailbox *inbox, *outbox; + struct mlx4_mad_ifc *inmad, *outmad; + struct mlx4_cable_info *cable_info; + u16 i2c_addr; + int ret; + + if (size > MODULE_INFO_MAX_READ) + size = MODULE_INFO_MAX_READ; + + inbox = mlx4_alloc_cmd_mailbox(dev); + if (IS_ERR(inbox)) + return PTR_ERR(inbox); + + outbox = mlx4_alloc_cmd_mailbox(dev); + if (IS_ERR(outbox)) { + mlx4_free_cmd_mailbox(dev, inbox); + return PTR_ERR(outbox); + } + + inmad = (struct mlx4_mad_ifc *)(inbox->buf); + outmad = (struct mlx4_mad_ifc *)(outbox->buf); + + inmad->method = 0x1; /* Get */ + inmad->class_version = 0x1; + inmad->mgmt_class = 0x1; + inmad->base_version = 0x1; + inmad->attr_id = cpu_to_be16(0xFF60); /* Module Info */ + + if (offset < I2C_PAGE_SIZE && offset + size > I2C_PAGE_SIZE) + /* Cross pages reads are not allowed + * read until offset 256 in low page + */ + size -= offset + size - I2C_PAGE_SIZE; + + i2c_addr = I2C_ADDR_LOW; + if (offset >= I2C_PAGE_SIZE) { + /* Reset offset to high page */ + i2c_addr = I2C_ADDR_HIGH; + offset -= I2C_PAGE_SIZE; + } + + cable_info = (struct mlx4_cable_info *)inmad->data; + cable_info->dev_mem_address = cpu_to_be16(offset); + cable_info->page_num = 0; + cable_info->i2c_addr = i2c_addr; + cable_info->size = cpu_to_be16(size); + + ret = mlx4_cmd_box(dev, inbox->dma, outbox->dma, port, 3, + MLX4_CMD_MAD_IFC, MLX4_CMD_TIME_CLASS_C, + MLX4_CMD_NATIVE); + if (ret) + goto out; + + if (be16_to_cpu(outmad->status)) { + /* Mad returned with bad status */ + ret = be16_to_cpu(outmad->status); + mlx4_warn(dev, + "MLX4_CMD_MAD_IFC Get Module info attr(%x) port(%d) i2c_addr(%x) offset(%d) size(%d): Response Mad Status(%x) - %s\n", + 0xFF60, port, i2c_addr, offset, size, + ret, cable_info_mad_err_str(ret)); + + if (i2c_addr == I2C_ADDR_HIGH && + MAD_STATUS_2_CABLE_ERR(ret) == CABLE_INF_I2C_ADDR) + /* Some SFP cables do not support i2c slave + * address 0x51 (high page), abort silently. + */ + ret = 0; + else + ret = -ret; + goto out; + } + cable_info = (struct mlx4_cable_info *)outmad->data; + memcpy(data, cable_info->data, size); + ret = size; +out: + mlx4_free_cmd_mailbox(dev, inbox); + mlx4_free_cmd_mailbox(dev, outbox); + return ret; +} +EXPORT_SYMBOL(mlx4_get_module_info); diff --git a/drivers/net/ethernet/mellanox/mlx4/profile.c b/drivers/net/ethernet/mellanox/mlx4/profile.c index 14089d9e1667..2bf437aafc53 100644 --- a/drivers/net/ethernet/mellanox/mlx4/profile.c +++ b/drivers/net/ethernet/mellanox/mlx4/profile.c @@ -126,8 +126,7 @@ u64 mlx4_make_profile(struct mlx4_dev *dev, profile[MLX4_RES_AUXC].num = request->num_qp; profile[MLX4_RES_SRQ].num = request->num_srq; profile[MLX4_RES_CQ].num = request->num_cq; - profile[MLX4_RES_EQ].num = mlx4_is_mfunc(dev) ? - dev->phys_caps.num_phys_eqs : + profile[MLX4_RES_EQ].num = mlx4_is_mfunc(dev) ? dev->phys_caps.num_phys_eqs : min_t(unsigned, dev_cap->max_eqs, MAX_MSIX); profile[MLX4_RES_DMPT].num = request->num_mpt; profile[MLX4_RES_CMPT].num = MLX4_NUM_CMPTS; @@ -216,10 +215,18 @@ u64 mlx4_make_profile(struct mlx4_dev *dev, init_hca->log_num_cqs = profile[i].log_num; break; case MLX4_RES_EQ: - dev->caps.num_eqs = roundup_pow_of_two(min_t(unsigned, dev_cap->max_eqs, - MAX_MSIX)); - init_hca->eqc_base = profile[i].start; - init_hca->log_num_eqs = ilog2(dev->caps.num_eqs); + if (dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_SYS_EQS) { + init_hca->log_num_eqs = 0x1f; + init_hca->eqc_base = profile[i].start; + init_hca->num_sys_eqs = dev_cap->num_sys_eqs; + } else { + dev->caps.num_eqs = roundup_pow_of_two( + min_t(unsigned, + dev_cap->max_eqs, + MAX_MSIX)); + init_hca->eqc_base = profile[i].start; + init_hca->log_num_eqs = ilog2(dev->caps.num_eqs); + } break; case MLX4_RES_DMPT: dev->caps.num_mpts = profile[i].num; diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index cd5cf6d957c7..16f617b5749e 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c @@ -2872,6 +2872,23 @@ out_add: return err; } +int mlx4_CONFIG_DEV_wrapper(struct mlx4_dev *dev, int slave, + struct mlx4_vhcr *vhcr, + struct mlx4_cmd_mailbox *inbox, + struct mlx4_cmd_mailbox *outbox, + struct mlx4_cmd_info *cmd) +{ + int err; + u8 get = vhcr->op_modifier; + + if (get != 1) + return -EPERM; + + err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); + + return err; +} + static int get_containing_mtt(struct mlx4_dev *dev, int slave, int start, int len, struct res_mtt **res) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c index ad2c96a02a53..dfd3ad0a39c1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c @@ -390,7 +390,7 @@ int mlx5_create_map_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq, u8 vecidx, */ eq_update_ci(eq, 1); - mlx5_vfree(in); + kvfree(in); return 0; err_irq: @@ -400,7 +400,7 @@ err_eq: mlx5_cmd_destroy_eq(dev, eq->eqn); err_in: - mlx5_vfree(in); + kvfree(in); err_buf: mlx5_buf_free(dev, &eq->buf); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c index d476918ef269..4fdaae9b54d9 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c @@ -349,7 +349,7 @@ out_4k: for (i--; i >= 0; i--) free_4k(dev, be64_to_cpu(in->pas[i])); out_free: - mlx5_vfree(in); + kvfree(in); return err; } @@ -400,7 +400,7 @@ static int reclaim_pages(struct mlx5_core_dev *dev, u32 func_id, int npages, } out_free: - mlx5_vfree(out); + kvfree(out); return err; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c b/drivers/net/ethernet/mellanox/mlx5/core/port.c index 313965853e10..72c2d002c3b8 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c @@ -68,9 +68,9 @@ int mlx5_core_access_reg(struct mlx5_core_dev *dev, void *data_in, memcpy(data_out, out->data, size_out); ex2: - mlx5_vfree(out); + kvfree(out); ex1: - mlx5_vfree(in); + kvfree(in); return err; } EXPORT_SYMBOL_GPL(mlx5_core_access_reg); diff --git a/drivers/net/ethernet/natsemi/macsonic.c b/drivers/net/ethernet/natsemi/macsonic.c index 9e4ddbba7036..66c2d50d5b8d 100644 --- a/drivers/net/ethernet/natsemi/macsonic.c +++ b/drivers/net/ethernet/natsemi/macsonic.c @@ -326,13 +326,9 @@ static int mac_onboard_sonic_probe(struct net_device *dev) macintosh_config->ident == MAC_MODEL_P588 || macintosh_config->ident == MAC_MODEL_P575 || macintosh_config->ident == MAC_MODEL_C610) { - unsigned long flags; int card_present; - local_irq_save(flags); card_present = hwreg_present((void*)ONBOARD_SONIC_REGISTERS); - local_irq_restore(flags); - if (!card_present) { printk("none.\n"); return -ENODEV; diff --git a/drivers/net/ethernet/realtek/8139too.c b/drivers/net/ethernet/realtek/8139too.c index 007b38cce69a..63dc0f95d050 100644 --- a/drivers/net/ethernet/realtek/8139too.c +++ b/drivers/net/ethernet/realtek/8139too.c @@ -112,6 +112,7 @@ #include <linux/io.h> #include <linux/uaccess.h> #include <linux/gfp.h> +#include <linux/if_vlan.h> #include <asm/irq.h> #define RTL8139_DRIVER_NAME DRV_NAME " Fast Ethernet driver " DRV_VERSION @@ -182,10 +183,13 @@ static int debug = -1; /* Number of Tx descriptor registers. */ #define NUM_TX_DESC 4 -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 +/* max supported ethernet frame size -- must be at least (dev->mtu+18+4).*/ +#define MAX_ETH_FRAME_SIZE 1792 -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ +/* max supported payload size */ +#define MAX_ETH_DATA_SIZE (MAX_ETH_FRAME_SIZE - VLAN_ETH_HLEN - ETH_FCS_LEN) + +/* Size of the Tx bounce buffers -- must be at least (dev->mtu+18+4). */ #define TX_BUF_SIZE MAX_ETH_FRAME_SIZE #define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) @@ -920,11 +924,19 @@ static int rtl8139_set_features(struct net_device *dev, netdev_features_t featur return 0; } +static int rtl8139_change_mtu(struct net_device *dev, int new_mtu) +{ + if (new_mtu < 68 || new_mtu > MAX_ETH_DATA_SIZE) + return -EINVAL; + dev->mtu = new_mtu; + return 0; +} + static const struct net_device_ops rtl8139_netdev_ops = { .ndo_open = rtl8139_open, .ndo_stop = rtl8139_close, .ndo_get_stats64 = rtl8139_get_stats64, - .ndo_change_mtu = eth_change_mtu, + .ndo_change_mtu = rtl8139_change_mtu, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = rtl8139_set_mac_address, .ndo_start_xmit = rtl8139_start_xmit, diff --git a/drivers/net/ethernet/realtek/atp.h b/drivers/net/ethernet/realtek/atp.h index 040b13739947..32497f0e537c 100644 --- a/drivers/net/ethernet/realtek/atp.h +++ b/drivers/net/ethernet/realtek/atp.h @@ -6,10 +6,10 @@ /* The header prepended to received packets. */ struct rx_header { - ushort pad; /* Pad. */ - ushort rx_count; - ushort rx_status; /* Unknown bit assignments :-<. */ - ushort cur_addr; /* Apparently the current buffer address(?) */ + ushort pad; /* Pad. */ + ushort rx_count; + ushort rx_status; /* Unknown bit assignments :-<. */ + ushort cur_addr; /* Apparently the current buffer address(?) */ }; #define PAR_DATA 0 @@ -29,22 +29,25 @@ struct rx_header { #define RdAddr 0xC0 #define HNib 0x10 -enum page0_regs -{ - /* The first six registers hold the ethernet physical station address. */ - PAR0 = 0, PAR1 = 1, PAR2 = 2, PAR3 = 3, PAR4 = 4, PAR5 = 5, - TxCNT0 = 6, TxCNT1 = 7, /* The transmit byte count. */ - TxSTAT = 8, RxSTAT = 9, /* Tx and Rx status. */ - ISR = 10, IMR = 11, /* Interrupt status and mask. */ - CMR1 = 12, /* Command register 1. */ - CMR2 = 13, /* Command register 2. */ - MODSEL = 14, /* Mode select register. */ - MAR = 14, /* Memory address register (?). */ - CMR2_h = 0x1d, }; - -enum eepage_regs -{ PROM_CMD = 6, PROM_DATA = 7 }; /* Note that PROM_CMD is in the "high" bits. */ +enum page0_regs { + /* The first six registers hold + * the ethernet physical station address. + */ + PAR0 = 0, PAR1 = 1, PAR2 = 2, PAR3 = 3, PAR4 = 4, PAR5 = 5, + TxCNT0 = 6, TxCNT1 = 7, /* The transmit byte count. */ + TxSTAT = 8, RxSTAT = 9, /* Tx and Rx status. */ + ISR = 10, IMR = 11, /* Interrupt status and mask. */ + CMR1 = 12, /* Command register 1. */ + CMR2 = 13, /* Command register 2. */ + MODSEL = 14, /* Mode select register. */ + MAR = 14, /* Memory address register (?). */ + CMR2_h = 0x1d, +}; +enum eepage_regs { + PROM_CMD = 6, + PROM_DATA = 7 /* Note that PROM_CMD is in the "high" bits. */ +}; #define ISR_TxOK 0x01 #define ISR_RxOK 0x04 @@ -72,141 +75,146 @@ enum eepage_regs #define CMR2h_Normal 2 /* Accept physical and broadcast address. */ #define CMR2h_PROMISC 3 /* Promiscuous mode. */ -/* An inline function used below: it differs from inb() by explicitly return an unsigned - char, saving a truncation. */ +/* An inline function used below: it differs from inb() by explicitly + * return an unsigned char, saving a truncation. + */ static inline unsigned char inbyte(unsigned short port) { - unsigned char _v; - __asm__ __volatile__ ("inb %w1,%b0" :"=a" (_v):"d" (port)); - return _v; + unsigned char _v; + + __asm__ __volatile__ ("inb %w1,%b0" : "=a" (_v) : "d" (port)); + return _v; } /* Read register OFFSET. - This command should always be terminated with read_end(). */ + * This command should always be terminated with read_end(). + */ static inline unsigned char read_nibble(short port, unsigned char offset) { - unsigned char retval; - outb(EOC+offset, port + PAR_DATA); - outb(RdAddr+offset, port + PAR_DATA); - inbyte(port + PAR_STATUS); /* Settling time delay */ - retval = inbyte(port + PAR_STATUS); - outb(EOC+offset, port + PAR_DATA); - - return retval; + unsigned char retval; + + outb(EOC+offset, port + PAR_DATA); + outb(RdAddr+offset, port + PAR_DATA); + inbyte(port + PAR_STATUS); /* Settling time delay */ + retval = inbyte(port + PAR_STATUS); + outb(EOC+offset, port + PAR_DATA); + + return retval; } /* Functions for bulk data read. The interrupt line is always disabled. */ /* Get a byte using read mode 0, reading data from the control lines. */ static inline unsigned char read_byte_mode0(short ioaddr) { - unsigned char low_nib; - - outb(Ctrl_LNibRead, ioaddr + PAR_CONTROL); - inbyte(ioaddr + PAR_STATUS); - low_nib = (inbyte(ioaddr + PAR_STATUS) >> 3) & 0x0f; - outb(Ctrl_HNibRead, ioaddr + PAR_CONTROL); - inbyte(ioaddr + PAR_STATUS); /* Settling time delay -- needed! */ - inbyte(ioaddr + PAR_STATUS); /* Settling time delay -- needed! */ - return low_nib | ((inbyte(ioaddr + PAR_STATUS) << 1) & 0xf0); + unsigned char low_nib; + + outb(Ctrl_LNibRead, ioaddr + PAR_CONTROL); + inbyte(ioaddr + PAR_STATUS); + low_nib = (inbyte(ioaddr + PAR_STATUS) >> 3) & 0x0f; + outb(Ctrl_HNibRead, ioaddr + PAR_CONTROL); + inbyte(ioaddr + PAR_STATUS); /* Settling time delay -- needed! */ + inbyte(ioaddr + PAR_STATUS); /* Settling time delay -- needed! */ + return low_nib | ((inbyte(ioaddr + PAR_STATUS) << 1) & 0xf0); } /* The same as read_byte_mode0(), but does multiple inb()s for stability. */ static inline unsigned char read_byte_mode2(short ioaddr) { - unsigned char low_nib; - - outb(Ctrl_LNibRead, ioaddr + PAR_CONTROL); - inbyte(ioaddr + PAR_STATUS); - low_nib = (inbyte(ioaddr + PAR_STATUS) >> 3) & 0x0f; - outb(Ctrl_HNibRead, ioaddr + PAR_CONTROL); - inbyte(ioaddr + PAR_STATUS); /* Settling time delay -- needed! */ - return low_nib | ((inbyte(ioaddr + PAR_STATUS) << 1) & 0xf0); + unsigned char low_nib; + + outb(Ctrl_LNibRead, ioaddr + PAR_CONTROL); + inbyte(ioaddr + PAR_STATUS); + low_nib = (inbyte(ioaddr + PAR_STATUS) >> 3) & 0x0f; + outb(Ctrl_HNibRead, ioaddr + PAR_CONTROL); + inbyte(ioaddr + PAR_STATUS); /* Settling time delay -- needed! */ + return low_nib | ((inbyte(ioaddr + PAR_STATUS) << 1) & 0xf0); } /* Read a byte through the data register. */ static inline unsigned char read_byte_mode4(short ioaddr) { - unsigned char low_nib; + unsigned char low_nib; - outb(RdAddr | MAR, ioaddr + PAR_DATA); - low_nib = (inbyte(ioaddr + PAR_STATUS) >> 3) & 0x0f; - outb(RdAddr | HNib | MAR, ioaddr + PAR_DATA); - return low_nib | ((inbyte(ioaddr + PAR_STATUS) << 1) & 0xf0); + outb(RdAddr | MAR, ioaddr + PAR_DATA); + low_nib = (inbyte(ioaddr + PAR_STATUS) >> 3) & 0x0f; + outb(RdAddr | HNib | MAR, ioaddr + PAR_DATA); + return low_nib | ((inbyte(ioaddr + PAR_STATUS) << 1) & 0xf0); } /* Read a byte through the data register, double reading to allow settling. */ static inline unsigned char read_byte_mode6(short ioaddr) { - unsigned char low_nib; - - outb(RdAddr | MAR, ioaddr + PAR_DATA); - inbyte(ioaddr + PAR_STATUS); - low_nib = (inbyte(ioaddr + PAR_STATUS) >> 3) & 0x0f; - outb(RdAddr | HNib | MAR, ioaddr + PAR_DATA); - inbyte(ioaddr + PAR_STATUS); - return low_nib | ((inbyte(ioaddr + PAR_STATUS) << 1) & 0xf0); + unsigned char low_nib; + + outb(RdAddr | MAR, ioaddr + PAR_DATA); + inbyte(ioaddr + PAR_STATUS); + low_nib = (inbyte(ioaddr + PAR_STATUS) >> 3) & 0x0f; + outb(RdAddr | HNib | MAR, ioaddr + PAR_DATA); + inbyte(ioaddr + PAR_STATUS); + return low_nib | ((inbyte(ioaddr + PAR_STATUS) << 1) & 0xf0); } static inline void write_reg(short port, unsigned char reg, unsigned char value) { - unsigned char outval; - outb(EOC | reg, port + PAR_DATA); - outval = WrAddr | reg; - outb(outval, port + PAR_DATA); - outb(outval, port + PAR_DATA); /* Double write for PS/2. */ - - outval &= 0xf0; - outval |= value; - outb(outval, port + PAR_DATA); - outval &= 0x1f; - outb(outval, port + PAR_DATA); - outb(outval, port + PAR_DATA); - - outb(EOC | outval, port + PAR_DATA); + unsigned char outval; + + outb(EOC | reg, port + PAR_DATA); + outval = WrAddr | reg; + outb(outval, port + PAR_DATA); + outb(outval, port + PAR_DATA); /* Double write for PS/2. */ + + outval &= 0xf0; + outval |= value; + outb(outval, port + PAR_DATA); + outval &= 0x1f; + outb(outval, port + PAR_DATA); + outb(outval, port + PAR_DATA); + + outb(EOC | outval, port + PAR_DATA); } static inline void write_reg_high(short port, unsigned char reg, unsigned char value) { - unsigned char outval = EOC | HNib | reg; + unsigned char outval = EOC | HNib | reg; - outb(outval, port + PAR_DATA); - outval &= WrAddr | HNib | 0x0f; - outb(outval, port + PAR_DATA); - outb(outval, port + PAR_DATA); /* Double write for PS/2. */ + outb(outval, port + PAR_DATA); + outval &= WrAddr | HNib | 0x0f; + outb(outval, port + PAR_DATA); + outb(outval, port + PAR_DATA); /* Double write for PS/2. */ - outval = WrAddr | HNib | value; - outb(outval, port + PAR_DATA); - outval &= HNib | 0x0f; /* HNib | value */ - outb(outval, port + PAR_DATA); - outb(outval, port + PAR_DATA); + outval = WrAddr | HNib | value; + outb(outval, port + PAR_DATA); + outval &= HNib | 0x0f; /* HNib | value */ + outb(outval, port + PAR_DATA); + outb(outval, port + PAR_DATA); - outb(EOC | HNib | outval, port + PAR_DATA); + outb(EOC | HNib | outval, port + PAR_DATA); } /* Write a byte out using nibble mode. The low nibble is written first. */ static inline void write_reg_byte(short port, unsigned char reg, unsigned char value) { - unsigned char outval; - outb(EOC | reg, port + PAR_DATA); /* Reset the address register. */ - outval = WrAddr | reg; - outb(outval, port + PAR_DATA); - outb(outval, port + PAR_DATA); /* Double write for PS/2. */ - - outb((outval & 0xf0) | (value & 0x0f), port + PAR_DATA); - outb(value & 0x0f, port + PAR_DATA); - value >>= 4; - outb(value, port + PAR_DATA); - outb(0x10 | value, port + PAR_DATA); - outb(0x10 | value, port + PAR_DATA); - - outb(EOC | value, port + PAR_DATA); /* Reset the address register. */ + unsigned char outval; + + outb(EOC | reg, port + PAR_DATA); /* Reset the address register. */ + outval = WrAddr | reg; + outb(outval, port + PAR_DATA); + outb(outval, port + PAR_DATA); /* Double write for PS/2. */ + + outb((outval & 0xf0) | (value & 0x0f), port + PAR_DATA); + outb(value & 0x0f, port + PAR_DATA); + value >>= 4; + outb(value, port + PAR_DATA); + outb(0x10 | value, port + PAR_DATA); + outb(0x10 | value, port + PAR_DATA); + + outb(EOC | value, port + PAR_DATA); /* Reset the address register. */ } -/* - * Bulk data writes to the packet buffer. The interrupt line remains enabled. +/* Bulk data writes to the packet buffer. The interrupt line remains enabled. * The first, faster method uses only the dataport (data modes 0, 2 & 4). * The second (backup) method uses data and control regs (modes 1, 3 & 5). * It should only be needed when there is skew between the individual data @@ -214,28 +222,28 @@ write_reg_byte(short port, unsigned char reg, unsigned char value) */ static inline void write_byte_mode0(short ioaddr, unsigned char value) { - outb(value & 0x0f, ioaddr + PAR_DATA); - outb((value>>4) | 0x10, ioaddr + PAR_DATA); + outb(value & 0x0f, ioaddr + PAR_DATA); + outb((value>>4) | 0x10, ioaddr + PAR_DATA); } static inline void write_byte_mode1(short ioaddr, unsigned char value) { - outb(value & 0x0f, ioaddr + PAR_DATA); - outb(Ctrl_IRQEN | Ctrl_LNibWrite, ioaddr + PAR_CONTROL); - outb((value>>4) | 0x10, ioaddr + PAR_DATA); - outb(Ctrl_IRQEN | Ctrl_HNibWrite, ioaddr + PAR_CONTROL); + outb(value & 0x0f, ioaddr + PAR_DATA); + outb(Ctrl_IRQEN | Ctrl_LNibWrite, ioaddr + PAR_CONTROL); + outb((value>>4) | 0x10, ioaddr + PAR_DATA); + outb(Ctrl_IRQEN | Ctrl_HNibWrite, ioaddr + PAR_CONTROL); } /* Write 16bit VALUE to the packet buffer: the same as above just doubled. */ static inline void write_word_mode0(short ioaddr, unsigned short value) { - outb(value & 0x0f, ioaddr + PAR_DATA); - value >>= 4; - outb((value & 0x0f) | 0x10, ioaddr + PAR_DATA); - value >>= 4; - outb(value & 0x0f, ioaddr + PAR_DATA); - value >>= 4; - outb((value & 0x0f) | 0x10, ioaddr + PAR_DATA); + outb(value & 0x0f, ioaddr + PAR_DATA); + value >>= 4; + outb((value & 0x0f) | 0x10, ioaddr + PAR_DATA); + value >>= 4; + outb(value & 0x0f, ioaddr + PAR_DATA); + value >>= 4; + outb((value & 0x0f) | 0x10, ioaddr + PAR_DATA); } /* EEPROM_Ctrl bits. */ @@ -248,10 +256,10 @@ static inline void write_word_mode0(short ioaddr, unsigned short value) /* Delay between EEPROM clock transitions. */ #define eeprom_delay(ticks) \ -do { int _i = 40; while (--_i > 0) { __SLOW_DOWN_IO; }} while (0) +do { int _i = 40; while (--_i > 0) { __SLOW_DOWN_IO; } } while (0) /* The EEPROM commands include the alway-set leading bit. */ #define EE_WRITE_CMD(offset) (((5 << 6) + (offset)) << 17) -#define EE_READ(offset) (((6 << 6) + (offset)) << 17) +#define EE_READ(offset) (((6 << 6) + (offset)) << 17) #define EE_ERASE(offset) (((7 << 6) + (offset)) << 17) #define EE_CMD_SIZE 27 /* The command+address+data size. */ diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 60e9c2cd051e..71f59ee51304 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -1,5 +1,6 @@ /* SuperH Ethernet device driver * + * Copyright (C) 2014 Renesas Electronics Corporation * Copyright (C) 2006-2012 Nobuhiro Iwamatsu * Copyright (C) 2008-2014 Renesas Solutions Corp. * Copyright (C) 2013-2014 Cogent Embedded, Inc. @@ -2746,6 +2747,7 @@ static const struct of_device_id sh_eth_match_table[] = { { .compatible = "renesas,ether-r8a7779", .data = &r8a777x_data }, { .compatible = "renesas,ether-r8a7790", .data = &r8a779x_data }, { .compatible = "renesas,ether-r8a7791", .data = &r8a779x_data }, + { .compatible = "renesas,ether-r8a7793", .data = &r8a779x_data }, { .compatible = "renesas,ether-r8a7794", .data = &r8a779x_data }, { .compatible = "renesas,ether-r7s72100", .data = &r7s72100_data }, { } @@ -2769,10 +2771,6 @@ static int sh_eth_drv_probe(struct platform_device *pdev) /* get base addr */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (unlikely(res == NULL)) { - dev_err(&pdev->dev, "invalid resource\n"); - return -EINVAL; - } ndev = alloc_etherdev(sizeof(struct sh_eth_private)); if (!ndev) @@ -2781,8 +2779,6 @@ static int sh_eth_drv_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); pm_runtime_get_sync(&pdev->dev); - /* The sh Ether-specific entries in the device structure. */ - ndev->base_addr = res->start; devno = pdev->id; if (devno < 0) devno = 0; @@ -2806,6 +2802,8 @@ static int sh_eth_drv_probe(struct platform_device *pdev) goto out_release; } + ndev->base_addr = res->start; + spin_lock_init(&mdp->lock); mdp->pdev = pdev; @@ -2887,6 +2885,9 @@ static int sh_eth_drv_probe(struct platform_device *pdev) } } + if (mdp->cd->rmiimode) + sh_eth_write(ndev, 0x1, RMIIMODE); + /* MDIO bus init */ ret = sh_mdio_init(mdp, pd); if (ret) { @@ -2973,6 +2974,7 @@ static struct platform_device_id sh_eth_id_table[] = { { "r8a777x-ether", (kernel_ulong_t)&r8a777x_data }, { "r8a7790-ether", (kernel_ulong_t)&r8a779x_data }, { "r8a7791-ether", (kernel_ulong_t)&r8a779x_data }, + { "r8a7793-ether", (kernel_ulong_t)&r8a779x_data }, { "r8a7794-ether", (kernel_ulong_t)&r8a779x_data }, { } }; diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c index b147d469a799..7fd6e275d1c2 100644 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c @@ -90,9 +90,6 @@ static int sxgbe_platform_probe(struct platform_device *pdev) /* Get memory resource */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - goto err_out; - addr = devm_ioremap_resource(dev, res); if (IS_ERR(addr)) return PTR_ERR(addr); diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index a77f05ce8325..fbb6cfa0f5f1 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -3689,6 +3689,11 @@ const struct efx_nic_type efx_hunt_a0_nic_type = { .ptp_write_host_time = efx_ef10_ptp_write_host_time, .ptp_set_ts_sync_events = efx_ef10_ptp_set_ts_sync_events, .ptp_set_ts_config = efx_ef10_ptp_set_ts_config, + .sriov_init = efx_ef10_sriov_init, + .sriov_fini = efx_ef10_sriov_fini, + .sriov_mac_address_changed = efx_ef10_sriov_mac_address_changed, + .sriov_wanted = efx_ef10_sriov_wanted, + .sriov_reset = efx_ef10_sriov_reset, .revision = EFX_REV_HUNT_A0, .max_dma_mask = DMA_BIT_MASK(ESF_DZ_TX_KER_BUF_ADDR_WIDTH), diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index b2cc590dd1dd..238482495e81 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -1314,7 +1314,7 @@ static unsigned int efx_wanted_parallelism(struct efx_nic *efx) /* If RSS is requested for the PF *and* VFs then we can't write RSS * table entries that are inaccessible to VFs */ - if (efx_sriov_wanted(efx) && efx_vf_size(efx) > 1 && + if (efx->type->sriov_wanted(efx) && efx_vf_size(efx) > 1 && count > efx_vf_size(efx)) { netif_warn(efx, probe, efx->net_dev, "Reducing number of RSS channels from %u to %u for " @@ -1426,7 +1426,9 @@ static int efx_probe_interrupts(struct efx_nic *efx) } /* RSS might be usable on VFs even if it is disabled on the PF */ - efx->rss_spread = ((efx->n_rx_channels > 1 || !efx_sriov_wanted(efx)) ? + + efx->rss_spread = ((efx->n_rx_channels > 1 || + !efx->type->sriov_wanted(efx)) ? efx->n_rx_channels : efx_vf_size(efx)); return 0; @@ -1614,7 +1616,7 @@ static int efx_probe_nic(struct efx_nic *efx) goto fail2; if (efx->n_channels > 1) - get_random_bytes(&efx->rx_hash_key, sizeof(efx->rx_hash_key)); + netdev_rss_key_fill(&efx->rx_hash_key, sizeof(efx->rx_hash_key)); for (i = 0; i < ARRAY_SIZE(efx->rx_indir_table); i++) efx->rx_indir_table[i] = ethtool_rxfh_indir_default(i, efx->rss_spread); @@ -2166,7 +2168,7 @@ static int efx_set_mac_address(struct net_device *net_dev, void *data) } ether_addr_copy(net_dev->dev_addr, new_addr); - efx_sriov_mac_address_changed(efx); + efx->type->sriov_mac_address_changed(efx); /* Reconfigure the MAC */ mutex_lock(&efx->mac_lock); @@ -2210,10 +2212,10 @@ static const struct net_device_ops efx_farch_netdev_ops = { .ndo_set_rx_mode = efx_set_rx_mode, .ndo_set_features = efx_set_features, #ifdef CONFIG_SFC_SRIOV - .ndo_set_vf_mac = efx_sriov_set_vf_mac, - .ndo_set_vf_vlan = efx_sriov_set_vf_vlan, - .ndo_set_vf_spoofchk = efx_sriov_set_vf_spoofchk, - .ndo_get_vf_config = efx_sriov_get_vf_config, + .ndo_set_vf_mac = efx_siena_sriov_set_vf_mac, + .ndo_set_vf_vlan = efx_siena_sriov_set_vf_vlan, + .ndo_set_vf_spoofchk = efx_siena_sriov_set_vf_spoofchk, + .ndo_get_vf_config = efx_siena_sriov_get_vf_config, #endif #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = efx_netpoll, @@ -2433,7 +2435,7 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok) if (rc) goto fail; efx_restore_filters(efx); - efx_sriov_reset(efx); + efx->type->sriov_reset(efx); mutex_unlock(&efx->mac_lock); @@ -2826,7 +2828,7 @@ static void efx_pci_remove(struct pci_dev *pci_dev) efx_disable_interrupts(efx); rtnl_unlock(); - efx_sriov_fini(efx); + efx->type->sriov_fini(efx); efx_unregister_netdev(efx); efx_mtd_remove(efx); @@ -3023,7 +3025,7 @@ static int efx_pci_probe(struct pci_dev *pci_dev, if (rc) goto fail4; - rc = efx_sriov_init(efx); + rc = efx->type->sriov_init(efx); if (rc) netif_err(efx, probe, efx->net_dev, "SR-IOV can't be enabled rc %d\n", rc); diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c index 157037546d30..f166c8ef38a3 100644 --- a/drivers/net/ethernet/sfc/falcon.c +++ b/drivers/net/ethernet/sfc/falcon.c @@ -2766,6 +2766,11 @@ const struct efx_nic_type falcon_a1_nic_type = { .mtd_write = falcon_mtd_write, .mtd_sync = falcon_mtd_sync, #endif + .sriov_init = efx_falcon_sriov_init, + .sriov_fini = efx_falcon_sriov_fini, + .sriov_mac_address_changed = efx_falcon_sriov_mac_address_changed, + .sriov_wanted = efx_falcon_sriov_wanted, + .sriov_reset = efx_falcon_sriov_reset, .revision = EFX_REV_FALCON_A1, .txd_ptr_tbl_base = FR_AA_TX_DESC_PTR_TBL_KER, @@ -2862,6 +2867,11 @@ const struct efx_nic_type falcon_b0_nic_type = { .mtd_write = falcon_mtd_write, .mtd_sync = falcon_mtd_sync, #endif + .sriov_init = efx_falcon_sriov_init, + .sriov_fini = efx_falcon_sriov_fini, + .sriov_mac_address_changed = efx_falcon_sriov_mac_address_changed, + .sriov_wanted = efx_falcon_sriov_wanted, + .sriov_reset = efx_falcon_sriov_reset, .revision = EFX_REV_FALCON_B0, .txd_ptr_tbl_base = FR_BZ_TX_DESC_PTR_TBL, diff --git a/drivers/net/ethernet/sfc/farch.c b/drivers/net/ethernet/sfc/farch.c index 6859437b59fb..75975328e020 100644 --- a/drivers/net/ethernet/sfc/farch.c +++ b/drivers/net/ethernet/sfc/farch.c @@ -226,6 +226,9 @@ static int efx_alloc_special_buffer(struct efx_nic *efx, struct efx_special_buffer *buffer, unsigned int len) { +#ifdef CONFIG_SFC_SRIOV + struct siena_nic_data *nic_data = efx->nic_data; +#endif len = ALIGN(len, EFX_BUF_SIZE); if (efx_nic_alloc_buffer(efx, &buffer->buf, len, GFP_KERNEL)) @@ -237,8 +240,8 @@ static int efx_alloc_special_buffer(struct efx_nic *efx, buffer->index = efx->next_buffer_table; efx->next_buffer_table += buffer->entries; #ifdef CONFIG_SFC_SRIOV - BUG_ON(efx_sriov_enabled(efx) && - efx->vf_buftbl_base < efx->next_buffer_table); + BUG_ON(efx_siena_sriov_enabled(efx) && + nic_data->vf_buftbl_base < efx->next_buffer_table); #endif netif_dbg(efx, probe, efx->net_dev, @@ -667,7 +670,7 @@ static int efx_farch_do_flush(struct efx_nic *efx) * the firmware (though we will still have to poll for * completion). If that fails, fall back to the old scheme. */ - if (efx_sriov_enabled(efx)) { + if (efx_siena_sriov_enabled(efx)) { rc = efx_mcdi_flush_rxqs(efx); if (!rc) goto wait; @@ -1195,13 +1198,13 @@ efx_farch_handle_driver_event(struct efx_channel *channel, efx_qword_t *event) netif_vdbg(efx, hw, efx->net_dev, "channel %d TXQ %d flushed\n", channel->channel, ev_sub_data); efx_farch_handle_tx_flush_done(efx, event); - efx_sriov_tx_flush_done(efx, event); + efx_siena_sriov_tx_flush_done(efx, event); break; case FSE_AZ_RX_DESCQ_FLS_DONE_EV: netif_vdbg(efx, hw, efx->net_dev, "channel %d RXQ %d flushed\n", channel->channel, ev_sub_data); efx_farch_handle_rx_flush_done(efx, event); - efx_sriov_rx_flush_done(efx, event); + efx_siena_sriov_rx_flush_done(efx, event); break; case FSE_AZ_EVQ_INIT_DONE_EV: netif_dbg(efx, hw, efx->net_dev, @@ -1240,7 +1243,7 @@ efx_farch_handle_driver_event(struct efx_channel *channel, efx_qword_t *event) ev_sub_data); efx_schedule_reset(efx, RESET_TYPE_DMA_ERROR); } else - efx_sriov_desc_fetch_err(efx, ev_sub_data); + efx_siena_sriov_desc_fetch_err(efx, ev_sub_data); break; case FSE_BZ_TX_DSC_ERROR_EV: if (ev_sub_data < EFX_VI_BASE) { @@ -1250,7 +1253,7 @@ efx_farch_handle_driver_event(struct efx_channel *channel, efx_qword_t *event) ev_sub_data); efx_schedule_reset(efx, RESET_TYPE_DMA_ERROR); } else - efx_sriov_desc_fetch_err(efx, ev_sub_data); + efx_siena_sriov_desc_fetch_err(efx, ev_sub_data); break; default: netif_vdbg(efx, hw, efx->net_dev, @@ -1315,7 +1318,7 @@ int efx_farch_ev_process(struct efx_channel *channel, int budget) efx_farch_handle_driver_event(channel, &event); break; case FSE_CZ_EV_CODE_USER_EV: - efx_sriov_event(channel, &event); + efx_siena_sriov_event(channel, &event); break; case FSE_CZ_EV_CODE_MCDI_EV: efx_mcdi_process_event(channel, &event); @@ -1668,6 +1671,10 @@ void efx_farch_dimension_resources(struct efx_nic *efx, unsigned sram_lim_qw) { unsigned vi_count, buftbl_min; +#ifdef CONFIG_SFC_SRIOV + struct siena_nic_data *nic_data = efx->nic_data; +#endif + /* Account for the buffer table entries backing the datapath channels * and the descriptor caches for those channels. */ @@ -1678,10 +1685,10 @@ void efx_farch_dimension_resources(struct efx_nic *efx, unsigned sram_lim_qw) vi_count = max(efx->n_channels, efx->n_tx_channels * EFX_TXQ_TYPES); #ifdef CONFIG_SFC_SRIOV - if (efx_sriov_wanted(efx)) { + if (efx->type->sriov_wanted(efx)) { unsigned vi_dc_entries, buftbl_free, entries_per_vf, vf_limit; - efx->vf_buftbl_base = buftbl_min; + nic_data->vf_buftbl_base = buftbl_min; vi_dc_entries = RX_DC_ENTRIES + TX_DC_ENTRIES; vi_count = max(vi_count, EFX_VI_BASE); diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c index 5239cf9bdc56..d37928f01949 100644 --- a/drivers/net/ethernet/sfc/mcdi.c +++ b/drivers/net/ethernet/sfc/mcdi.c @@ -1035,7 +1035,7 @@ void efx_mcdi_process_event(struct efx_channel *channel, /* MAC stats are gather lazily. We can ignore this. */ break; case MCDI_EVENT_CODE_FLR: - efx_sriov_flr(efx, MCDI_EVENT_FIELD(*event, FLR_VF)); + efx_siena_sriov_flr(efx, MCDI_EVENT_FIELD(*event, FLR_VF)); break; case MCDI_EVENT_CODE_PTP_RX: case MCDI_EVENT_CODE_PTP_FAULT: diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index 9ede32064685..325dd94bca46 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -913,13 +913,6 @@ struct vfdi_status; * @vf_count: Number of VFs intended to be enabled. * @vf_init_count: Number of VFs that have been fully initialised. * @vi_scale: log2 number of vnics per VF. - * @vf_buftbl_base: The zeroth buffer table index used to back VF queues. - * @vfdi_status: Common VFDI status page to be dmad to VF address space. - * @local_addr_list: List of local addresses. Protected by %local_lock. - * @local_page_list: List of DMA addressable pages used to broadcast - * %local_addr_list. Protected by %local_lock. - * @local_lock: Mutex protecting %local_addr_list and %local_page_list. - * @peer_work: Work item to broadcast peer addresses to VMs. * @ptp_data: PTP state data * @vpd_sn: Serial number read from VPD * @monitor_work: Hardware monitor workitem @@ -1060,17 +1053,10 @@ struct efx_nic { wait_queue_head_t flush_wq; #ifdef CONFIG_SFC_SRIOV - struct efx_channel *vfdi_channel; struct efx_vf *vf; unsigned vf_count; unsigned vf_init_count; unsigned vi_scale; - unsigned vf_buftbl_base; - struct efx_buffer vfdi_status; - struct list_head local_addr_list; - struct list_head local_page_list; - struct mutex local_lock; - struct work_struct peer_work; #endif struct efx_ptp_data *ptp_data; @@ -1344,6 +1330,11 @@ struct efx_nic_type { int (*ptp_set_ts_sync_events)(struct efx_nic *efx, bool en, bool temp); int (*ptp_set_ts_config)(struct efx_nic *efx, struct hwtstamp_config *init); + int (*sriov_init)(struct efx_nic *efx); + void (*sriov_fini)(struct efx_nic *efx); + void (*sriov_mac_address_changed)(struct efx_nic *efx); + bool (*sriov_wanted)(struct efx_nic *efx); + void (*sriov_reset)(struct efx_nic *efx); int revision; unsigned int txd_ptr_tbl_base; diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h index f77cce034ad4..93d10cbbd1cf 100644 --- a/drivers/net/ethernet/sfc/nic.h +++ b/drivers/net/ethernet/sfc/nic.h @@ -378,12 +378,30 @@ enum { /** * struct siena_nic_data - Siena NIC state + * @efx: Pointer back to main interface structure * @wol_filter_id: Wake-on-LAN packet filter id * @stats: Hardware statistics + * @vf_buftbl_base: The zeroth buffer table index used to back VF queues. + * @vfdi_status: Common VFDI status page to be dmad to VF address space. + * @local_addr_list: List of local addresses. Protected by %local_lock. + * @local_page_list: List of DMA addressable pages used to broadcast + * %local_addr_list. Protected by %local_lock. + * @local_lock: Mutex protecting %local_addr_list and %local_page_list. + * @peer_work: Work item to broadcast peer addresses to VMs. */ struct siena_nic_data { + struct efx_nic *efx; int wol_filter_id; u64 stats[SIENA_STAT_COUNT]; +#ifdef CONFIG_SFC_SRIOV + struct efx_channel *vfdi_channel; + unsigned vf_buftbl_base; + struct efx_buffer vfdi_status; + struct list_head local_addr_list; + struct list_head local_page_list; + struct mutex local_lock; + struct work_struct peer_work; +#endif }; enum { @@ -522,62 +540,88 @@ struct efx_ef10_nic_data { #ifdef CONFIG_SFC_SRIOV -static inline bool efx_sriov_wanted(struct efx_nic *efx) +/* SIENA */ +static inline bool efx_siena_sriov_wanted(struct efx_nic *efx) { return efx->vf_count != 0; } -static inline bool efx_sriov_enabled(struct efx_nic *efx) + +static inline bool efx_siena_sriov_enabled(struct efx_nic *efx) { return efx->vf_init_count != 0; } + static inline unsigned int efx_vf_size(struct efx_nic *efx) { return 1 << efx->vi_scale; } int efx_init_sriov(void); -void efx_sriov_probe(struct efx_nic *efx); -int efx_sriov_init(struct efx_nic *efx); -void efx_sriov_mac_address_changed(struct efx_nic *efx); -void efx_sriov_tx_flush_done(struct efx_nic *efx, efx_qword_t *event); -void efx_sriov_rx_flush_done(struct efx_nic *efx, efx_qword_t *event); -void efx_sriov_event(struct efx_channel *channel, efx_qword_t *event); -void efx_sriov_desc_fetch_err(struct efx_nic *efx, unsigned dmaq); -void efx_sriov_flr(struct efx_nic *efx, unsigned flr); -void efx_sriov_reset(struct efx_nic *efx); -void efx_sriov_fini(struct efx_nic *efx); +void efx_siena_sriov_probe(struct efx_nic *efx); +int efx_siena_sriov_init(struct efx_nic *efx); +void efx_siena_sriov_mac_address_changed(struct efx_nic *efx); +void efx_siena_sriov_tx_flush_done(struct efx_nic *efx, efx_qword_t *event); +void efx_siena_sriov_rx_flush_done(struct efx_nic *efx, efx_qword_t *event); +void efx_siena_sriov_event(struct efx_channel *channel, efx_qword_t *event); +void efx_siena_sriov_desc_fetch_err(struct efx_nic *efx, unsigned dmaq); +void efx_siena_sriov_flr(struct efx_nic *efx, unsigned flr); +void efx_siena_sriov_reset(struct efx_nic *efx); +void efx_siena_sriov_fini(struct efx_nic *efx); void efx_fini_sriov(void); +/* EF10 */ +static inline bool efx_ef10_sriov_wanted(struct efx_nic *efx) { return false; } +static inline int efx_ef10_sriov_init(struct efx_nic *efx) { return -EOPNOTSUPP; } +static inline void efx_ef10_sriov_mac_address_changed(struct efx_nic *efx) {} +static inline void efx_ef10_sriov_reset(struct efx_nic *efx) {} +static inline void efx_ef10_sriov_fini(struct efx_nic *efx) {} + #else -static inline bool efx_sriov_wanted(struct efx_nic *efx) { return false; } -static inline bool efx_sriov_enabled(struct efx_nic *efx) { return false; } +/* SIENA */ +static inline bool efx_siena_sriov_wanted(struct efx_nic *efx) { return false; } +static inline bool efx_siena_sriov_enabled(struct efx_nic *efx) { return false; } static inline unsigned int efx_vf_size(struct efx_nic *efx) { return 0; } - static inline int efx_init_sriov(void) { return 0; } -static inline void efx_sriov_probe(struct efx_nic *efx) {} -static inline int efx_sriov_init(struct efx_nic *efx) { return -EOPNOTSUPP; } -static inline void efx_sriov_mac_address_changed(struct efx_nic *efx) {} -static inline void efx_sriov_tx_flush_done(struct efx_nic *efx, - efx_qword_t *event) {} -static inline void efx_sriov_rx_flush_done(struct efx_nic *efx, - efx_qword_t *event) {} -static inline void efx_sriov_event(struct efx_channel *channel, - efx_qword_t *event) {} -static inline void efx_sriov_desc_fetch_err(struct efx_nic *efx, unsigned dmaq) {} -static inline void efx_sriov_flr(struct efx_nic *efx, unsigned flr) {} -static inline void efx_sriov_reset(struct efx_nic *efx) {} -static inline void efx_sriov_fini(struct efx_nic *efx) {} +static inline void efx_siena_sriov_probe(struct efx_nic *efx) {} +static inline int efx_siena_sriov_init(struct efx_nic *efx) { return -EOPNOTSUPP; } +static inline void efx_siena_sriov_mac_address_changed(struct efx_nic *efx) {} +static inline void efx_siena_sriov_tx_flush_done(struct efx_nic *efx, + efx_qword_t *event) {} +static inline void efx_siena_sriov_rx_flush_done(struct efx_nic *efx, + efx_qword_t *event) {} +static inline void efx_siena_sriov_event(struct efx_channel *channel, + efx_qword_t *event) {} +static inline void efx_siena_sriov_desc_fetch_err(struct efx_nic *efx, + unsigned dmaq) {} +static inline void efx_siena_sriov_flr(struct efx_nic *efx, unsigned flr) {} +static inline void efx_siena_sriov_reset(struct efx_nic *efx) {} +static inline void efx_siena_sriov_fini(struct efx_nic *efx) {} static inline void efx_fini_sriov(void) {} +/* EF10 */ +static inline bool efx_ef10_sriov_wanted(struct efx_nic *efx) { return false; } +static inline int efx_ef10_sriov_init(struct efx_nic *efx) { return -EOPNOTSUPP; } +static inline void efx_ef10_sriov_mac_address_changed(struct efx_nic *efx) {} +static inline void efx_ef10_sriov_reset(struct efx_nic *efx) {} +static inline void efx_ef10_sriov_fini(struct efx_nic *efx) {} + #endif -int efx_sriov_set_vf_mac(struct net_device *dev, int vf, u8 *mac); -int efx_sriov_set_vf_vlan(struct net_device *dev, int vf, u16 vlan, u8 qos); -int efx_sriov_get_vf_config(struct net_device *dev, int vf, - struct ifla_vf_info *ivf); -int efx_sriov_set_vf_spoofchk(struct net_device *net_dev, int vf, - bool spoofchk); +/* FALCON */ +static inline bool efx_falcon_sriov_wanted(struct efx_nic *efx) { return false; } +static inline int efx_falcon_sriov_init(struct efx_nic *efx) { return -EOPNOTSUPP; } +static inline void efx_falcon_sriov_mac_address_changed(struct efx_nic *efx) {} +static inline void efx_falcon_sriov_reset(struct efx_nic *efx) {} +static inline void efx_falcon_sriov_fini(struct efx_nic *efx) {} + +int efx_siena_sriov_set_vf_mac(struct net_device *dev, int vf, u8 *mac); +int efx_siena_sriov_set_vf_vlan(struct net_device *dev, int vf, + u16 vlan, u8 qos); +int efx_siena_sriov_get_vf_config(struct net_device *dev, int vf, + struct ifla_vf_info *ivf); +int efx_siena_sriov_set_vf_spoofchk(struct net_device *net_dev, int vf, + bool spoofchk); struct ethtool_ts_info; int efx_ptp_probe(struct efx_nic *efx, struct efx_channel *channel); diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c index ae696855f21a..3583f0208a6e 100644 --- a/drivers/net/ethernet/sfc/siena.c +++ b/drivers/net/ethernet/sfc/siena.c @@ -251,6 +251,7 @@ static int siena_probe_nic(struct efx_nic *efx) nic_data = kzalloc(sizeof(struct siena_nic_data), GFP_KERNEL); if (!nic_data) return -ENOMEM; + nic_data->efx = efx; efx->nic_data = nic_data; if (efx_farch_fpga_ver(efx) != 0) { @@ -306,7 +307,7 @@ static int siena_probe_nic(struct efx_nic *efx) if (rc) goto fail5; - efx_sriov_probe(efx); + efx_siena_sriov_probe(efx); efx_ptp_defer_probe_with_channel(efx); return 0; @@ -996,6 +997,11 @@ const struct efx_nic_type siena_a0_nic_type = { #endif .ptp_write_host_time = siena_ptp_write_host_time, .ptp_set_ts_config = siena_ptp_set_ts_config, + .sriov_init = efx_siena_sriov_init, + .sriov_fini = efx_siena_sriov_fini, + .sriov_mac_address_changed = efx_siena_sriov_mac_address_changed, + .sriov_wanted = efx_siena_sriov_wanted, + .sriov_reset = efx_siena_sriov_reset, .revision = EFX_REV_SIENA_A0, .txd_ptr_tbl_base = FR_BZ_TX_DESC_PTR_TBL, diff --git a/drivers/net/ethernet/sfc/siena_sriov.c b/drivers/net/ethernet/sfc/siena_sriov.c index 43d2e64546ed..a8bbbad68a88 100644 --- a/drivers/net/ethernet/sfc/siena_sriov.c +++ b/drivers/net/ethernet/sfc/siena_sriov.c @@ -66,7 +66,7 @@ enum efx_vf_tx_filter_mode { * @status_lock: Mutex protecting @msg_seqno, @status_addr, @addr, * @peer_page_addrs and @peer_page_count from simultaneous * updates by the VM and consumption by - * efx_sriov_update_vf_addr() + * efx_siena_sriov_update_vf_addr() * @peer_page_addrs: Pointer to an array of guest pages for local addresses. * @peer_page_count: Number of entries in @peer_page_count. * @evq0_addrs: Array of guest pages backing evq0. @@ -194,8 +194,8 @@ static unsigned abs_index(struct efx_vf *vf, unsigned index) return EFX_VI_BASE + vf->index * efx_vf_size(vf->efx) + index; } -static int efx_sriov_cmd(struct efx_nic *efx, bool enable, - unsigned *vi_scale_out, unsigned *vf_total_out) +static int efx_siena_sriov_cmd(struct efx_nic *efx, bool enable, + unsigned *vi_scale_out, unsigned *vf_total_out) { MCDI_DECLARE_BUF(inbuf, MC_CMD_SRIOV_IN_LEN); MCDI_DECLARE_BUF(outbuf, MC_CMD_SRIOV_OUT_LEN); @@ -227,18 +227,20 @@ static int efx_sriov_cmd(struct efx_nic *efx, bool enable, return 0; } -static void efx_sriov_usrev(struct efx_nic *efx, bool enabled) +static void efx_siena_sriov_usrev(struct efx_nic *efx, bool enabled) { + struct siena_nic_data *nic_data = efx->nic_data; efx_oword_t reg; EFX_POPULATE_OWORD_2(reg, FRF_CZ_USREV_DIS, enabled ? 0 : 1, - FRF_CZ_DFLT_EVQ, efx->vfdi_channel->channel); + FRF_CZ_DFLT_EVQ, nic_data->vfdi_channel->channel); efx_writeo(efx, ®, FR_CZ_USR_EV_CFG); } -static int efx_sriov_memcpy(struct efx_nic *efx, struct efx_memcpy_req *req, - unsigned int count) +static int efx_siena_sriov_memcpy(struct efx_nic *efx, + struct efx_memcpy_req *req, + unsigned int count) { MCDI_DECLARE_BUF(inbuf, MCDI_CTL_SDU_LEN_MAX_V1); MCDI_DECLARE_STRUCT_PTR(record); @@ -297,7 +299,7 @@ out: /* The TX filter is entirely controlled by this driver, and is modified * underneath the feet of the VF */ -static void efx_sriov_reset_tx_filter(struct efx_vf *vf) +static void efx_siena_sriov_reset_tx_filter(struct efx_vf *vf) { struct efx_nic *efx = vf->efx; struct efx_filter_spec filter; @@ -341,7 +343,7 @@ static void efx_sriov_reset_tx_filter(struct efx_vf *vf) } /* The RX filter is managed here on behalf of the VF driver */ -static void efx_sriov_reset_rx_filter(struct efx_vf *vf) +static void efx_siena_sriov_reset_rx_filter(struct efx_vf *vf) { struct efx_nic *efx = vf->efx; struct efx_filter_spec filter; @@ -380,22 +382,26 @@ static void efx_sriov_reset_rx_filter(struct efx_vf *vf) } } -static void __efx_sriov_update_vf_addr(struct efx_vf *vf) +static void __efx_siena_sriov_update_vf_addr(struct efx_vf *vf) { - efx_sriov_reset_tx_filter(vf); - efx_sriov_reset_rx_filter(vf); - queue_work(vfdi_workqueue, &vf->efx->peer_work); + struct efx_nic *efx = vf->efx; + struct siena_nic_data *nic_data = efx->nic_data; + + efx_siena_sriov_reset_tx_filter(vf); + efx_siena_sriov_reset_rx_filter(vf); + queue_work(vfdi_workqueue, &nic_data->peer_work); } /* Push the peer list to this VF. The caller must hold status_lock to interlock * with VFDI requests, and they must be serialised against manipulation of * local_page_list, either by acquiring local_lock or by running from - * efx_sriov_peer_work() + * efx_siena_sriov_peer_work() */ -static void __efx_sriov_push_vf_status(struct efx_vf *vf) +static void __efx_siena_sriov_push_vf_status(struct efx_vf *vf) { struct efx_nic *efx = vf->efx; - struct vfdi_status *status = efx->vfdi_status.addr; + struct siena_nic_data *nic_data = efx->nic_data; + struct vfdi_status *status = nic_data->vfdi_status.addr; struct efx_memcpy_req copy[4]; struct efx_endpoint_page *epp; unsigned int pos, count; @@ -421,7 +427,7 @@ static void __efx_sriov_push_vf_status(struct efx_vf *vf) */ data_offset = offsetof(struct vfdi_status, version); copy[1].from_rid = efx->pci_dev->devfn; - copy[1].from_addr = efx->vfdi_status.dma_addr + data_offset; + copy[1].from_addr = nic_data->vfdi_status.dma_addr + data_offset; copy[1].to_rid = vf->pci_rid; copy[1].to_addr = vf->status_addr + data_offset; copy[1].length = status->length - data_offset; @@ -429,7 +435,7 @@ static void __efx_sriov_push_vf_status(struct efx_vf *vf) /* Copy the peer pages */ pos = 2; count = 0; - list_for_each_entry(epp, &efx->local_page_list, link) { + list_for_each_entry(epp, &nic_data->local_page_list, link) { if (count == vf->peer_page_count) { /* The VF driver will know they need to provide more * pages because peer_addr_count is too large. @@ -444,7 +450,7 @@ static void __efx_sriov_push_vf_status(struct efx_vf *vf) copy[pos].length = EFX_PAGE_SIZE; if (++pos == ARRAY_SIZE(copy)) { - efx_sriov_memcpy(efx, copy, ARRAY_SIZE(copy)); + efx_siena_sriov_memcpy(efx, copy, ARRAY_SIZE(copy)); pos = 0; } ++count; @@ -456,7 +462,7 @@ static void __efx_sriov_push_vf_status(struct efx_vf *vf) copy[pos].to_addr = vf->status_addr + offsetof(struct vfdi_status, generation_end); copy[pos].length = sizeof(status->generation_end); - efx_sriov_memcpy(efx, copy, pos + 1); + efx_siena_sriov_memcpy(efx, copy, pos + 1); /* Notify the guest */ EFX_POPULATE_QWORD_3(event, @@ -469,8 +475,8 @@ static void __efx_sriov_push_vf_status(struct efx_vf *vf) &event); } -static void efx_sriov_bufs(struct efx_nic *efx, unsigned offset, - u64 *addr, unsigned count) +static void efx_siena_sriov_bufs(struct efx_nic *efx, unsigned offset, + u64 *addr, unsigned count) { efx_qword_t buf; unsigned pos; @@ -539,7 +545,7 @@ static int efx_vfdi_init_evq(struct efx_vf *vf) return VFDI_RC_EINVAL; } - efx_sriov_bufs(efx, buftbl, req->u.init_evq.addr, buf_count); + efx_siena_sriov_bufs(efx, buftbl, req->u.init_evq.addr, buf_count); EFX_POPULATE_OWORD_3(reg, FRF_CZ_TIMER_Q_EN, 1, @@ -584,7 +590,7 @@ static int efx_vfdi_init_rxq(struct efx_vf *vf) } if (__test_and_set_bit(req->u.init_rxq.index, vf->rxq_mask)) ++vf->rxq_count; - efx_sriov_bufs(efx, buftbl, req->u.init_rxq.addr, buf_count); + efx_siena_sriov_bufs(efx, buftbl, req->u.init_rxq.addr, buf_count); label = req->u.init_rxq.label & EFX_FIELD_MASK(FRF_AZ_RX_DESCQ_LABEL); EFX_POPULATE_OWORD_6(reg, @@ -628,7 +634,7 @@ static int efx_vfdi_init_txq(struct efx_vf *vf) if (__test_and_set_bit(req->u.init_txq.index, vf->txq_mask)) ++vf->txq_count; mutex_unlock(&vf->txq_lock); - efx_sriov_bufs(efx, buftbl, req->u.init_txq.addr, buf_count); + efx_siena_sriov_bufs(efx, buftbl, req->u.init_txq.addr, buf_count); eth_filt_en = vf->tx_filter_mode == VF_TX_FILTER_ON; @@ -742,8 +748,8 @@ static int efx_vfdi_fini_all_queues(struct efx_vf *vf) efx_writeo_table(efx, ®, FR_BZ_TIMER_TBL, vf_offset + index); } - efx_sriov_bufs(efx, vf->buftbl_base, NULL, - EFX_VF_BUFTBL_PER_VI * efx_vf_size(efx)); + efx_siena_sriov_bufs(efx, vf->buftbl_base, NULL, + EFX_VF_BUFTBL_PER_VI * efx_vf_size(efx)); efx_vfdi_flush_clear(vf); vf->evq0_count = 0; @@ -754,6 +760,7 @@ static int efx_vfdi_fini_all_queues(struct efx_vf *vf) static int efx_vfdi_insert_filter(struct efx_vf *vf) { struct efx_nic *efx = vf->efx; + struct siena_nic_data *nic_data = efx->nic_data; struct vfdi_req *req = vf->buf.addr; unsigned vf_rxq = req->u.mac_filter.rxq; unsigned flags; @@ -776,17 +783,20 @@ static int efx_vfdi_insert_filter(struct efx_vf *vf) vf->rx_filter_qid = vf_rxq; vf->rx_filtering = true; - efx_sriov_reset_rx_filter(vf); - queue_work(vfdi_workqueue, &efx->peer_work); + efx_siena_sriov_reset_rx_filter(vf); + queue_work(vfdi_workqueue, &nic_data->peer_work); return VFDI_RC_SUCCESS; } static int efx_vfdi_remove_all_filters(struct efx_vf *vf) { + struct efx_nic *efx = vf->efx; + struct siena_nic_data *nic_data = efx->nic_data; + vf->rx_filtering = false; - efx_sriov_reset_rx_filter(vf); - queue_work(vfdi_workqueue, &vf->efx->peer_work); + efx_siena_sriov_reset_rx_filter(vf); + queue_work(vfdi_workqueue, &nic_data->peer_work); return VFDI_RC_SUCCESS; } @@ -794,6 +804,7 @@ static int efx_vfdi_remove_all_filters(struct efx_vf *vf) static int efx_vfdi_set_status_page(struct efx_vf *vf) { struct efx_nic *efx = vf->efx; + struct siena_nic_data *nic_data = efx->nic_data; struct vfdi_req *req = vf->buf.addr; u64 page_count = req->u.set_status_page.peer_page_count; u64 max_page_count = @@ -809,7 +820,7 @@ static int efx_vfdi_set_status_page(struct efx_vf *vf) return VFDI_RC_EINVAL; } - mutex_lock(&efx->local_lock); + mutex_lock(&nic_data->local_lock); mutex_lock(&vf->status_lock); vf->status_addr = req->u.set_status_page.dma_addr; @@ -828,9 +839,9 @@ static int efx_vfdi_set_status_page(struct efx_vf *vf) } } - __efx_sriov_push_vf_status(vf); + __efx_siena_sriov_push_vf_status(vf); mutex_unlock(&vf->status_lock); - mutex_unlock(&efx->local_lock); + mutex_unlock(&nic_data->local_lock); return VFDI_RC_SUCCESS; } @@ -857,7 +868,7 @@ static const efx_vfdi_op_t vfdi_ops[VFDI_OP_LIMIT] = { [VFDI_OP_CLEAR_STATUS_PAGE] = efx_vfdi_clear_status_page, }; -static void efx_sriov_vfdi(struct work_struct *work) +static void efx_siena_sriov_vfdi(struct work_struct *work) { struct efx_vf *vf = container_of(work, struct efx_vf, req); struct efx_nic *efx = vf->efx; @@ -872,7 +883,7 @@ static void efx_sriov_vfdi(struct work_struct *work) copy[0].to_rid = efx->pci_dev->devfn; copy[0].to_addr = vf->buf.dma_addr; copy[0].length = EFX_PAGE_SIZE; - rc = efx_sriov_memcpy(efx, copy, 1); + rc = efx_siena_sriov_memcpy(efx, copy, 1); if (rc) { /* If we can't get the request, we can't reply to the caller */ if (net_ratelimit()) @@ -916,7 +927,7 @@ static void efx_sriov_vfdi(struct work_struct *work) copy[1].to_addr = vf->req_addr + offsetof(struct vfdi_req, op); copy[1].length = sizeof(req->op); - (void) efx_sriov_memcpy(efx, copy, ARRAY_SIZE(copy)); + (void)efx_siena_sriov_memcpy(efx, copy, ARRAY_SIZE(copy)); } @@ -925,7 +936,8 @@ static void efx_sriov_vfdi(struct work_struct *work) * event ring in guest memory with VFDI reset events, then (re-initialise) the * event queue to raise an interrupt. The guest driver will then recover. */ -static void efx_sriov_reset_vf(struct efx_vf *vf, struct efx_buffer *buffer) +static void efx_siena_sriov_reset_vf(struct efx_vf *vf, + struct efx_buffer *buffer) { struct efx_nic *efx = vf->efx; struct efx_memcpy_req copy_req[4]; @@ -961,7 +973,7 @@ static void efx_sriov_reset_vf(struct efx_vf *vf, struct efx_buffer *buffer) copy_req[k].to_addr = vf->evq0_addrs[pos + k]; copy_req[k].length = EFX_PAGE_SIZE; } - rc = efx_sriov_memcpy(efx, copy_req, count); + rc = efx_siena_sriov_memcpy(efx, copy_req, count); if (rc) { if (net_ratelimit()) netif_err(efx, hw, efx->net_dev, @@ -974,7 +986,7 @@ static void efx_sriov_reset_vf(struct efx_vf *vf, struct efx_buffer *buffer) /* Reinitialise, arm and trigger evq0 */ abs_evq = abs_index(vf, 0); buftbl = EFX_BUFTBL_EVQ_BASE(vf, 0); - efx_sriov_bufs(efx, buftbl, vf->evq0_addrs, vf->evq0_count); + efx_siena_sriov_bufs(efx, buftbl, vf->evq0_addrs, vf->evq0_count); EFX_POPULATE_OWORD_3(reg, FRF_CZ_TIMER_Q_EN, 1, @@ -992,19 +1004,19 @@ static void efx_sriov_reset_vf(struct efx_vf *vf, struct efx_buffer *buffer) mutex_unlock(&vf->status_lock); } -static void efx_sriov_reset_vf_work(struct work_struct *work) +static void efx_siena_sriov_reset_vf_work(struct work_struct *work) { struct efx_vf *vf = container_of(work, struct efx_vf, req); struct efx_nic *efx = vf->efx; struct efx_buffer buf; if (!efx_nic_alloc_buffer(efx, &buf, EFX_PAGE_SIZE, GFP_NOIO)) { - efx_sriov_reset_vf(vf, &buf); + efx_siena_sriov_reset_vf(vf, &buf); efx_nic_free_buffer(efx, &buf); } } -static void efx_sriov_handle_no_channel(struct efx_nic *efx) +static void efx_siena_sriov_handle_no_channel(struct efx_nic *efx) { netif_err(efx, drv, efx->net_dev, "ERROR: IOV requires MSI-X and 1 additional interrupt" @@ -1012,35 +1024,38 @@ static void efx_sriov_handle_no_channel(struct efx_nic *efx) efx->vf_count = 0; } -static int efx_sriov_probe_channel(struct efx_channel *channel) +static int efx_siena_sriov_probe_channel(struct efx_channel *channel) { - channel->efx->vfdi_channel = channel; + struct siena_nic_data *nic_data = channel->efx->nic_data; + nic_data->vfdi_channel = channel; + return 0; } static void -efx_sriov_get_channel_name(struct efx_channel *channel, char *buf, size_t len) +efx_siena_sriov_get_channel_name(struct efx_channel *channel, + char *buf, size_t len) { snprintf(buf, len, "%s-iov", channel->efx->name); } -static const struct efx_channel_type efx_sriov_channel_type = { - .handle_no_channel = efx_sriov_handle_no_channel, - .pre_probe = efx_sriov_probe_channel, +static const struct efx_channel_type efx_siena_sriov_channel_type = { + .handle_no_channel = efx_siena_sriov_handle_no_channel, + .pre_probe = efx_siena_sriov_probe_channel, .post_remove = efx_channel_dummy_op_void, - .get_name = efx_sriov_get_channel_name, + .get_name = efx_siena_sriov_get_channel_name, /* no copy operation; channel must not be reallocated */ .keep_eventq = true, }; -void efx_sriov_probe(struct efx_nic *efx) +void efx_siena_sriov_probe(struct efx_nic *efx) { unsigned count; if (!max_vfs) return; - if (efx_sriov_cmd(efx, false, &efx->vi_scale, &count)) + if (efx_siena_sriov_cmd(efx, false, &efx->vi_scale, &count)) return; if (count > 0 && count > max_vfs) count = max_vfs; @@ -1048,17 +1063,20 @@ void efx_sriov_probe(struct efx_nic *efx) /* efx_nic_dimension_resources() will reduce vf_count as appopriate */ efx->vf_count = count; - efx->extra_channel_type[EFX_EXTRA_CHANNEL_IOV] = &efx_sriov_channel_type; + efx->extra_channel_type[EFX_EXTRA_CHANNEL_IOV] = &efx_siena_sriov_channel_type; } /* Copy the list of individual addresses into the vfdi_status.peers * array and auxillary pages, protected by %local_lock. Drop that lock * and then broadcast the address list to every VF. */ -static void efx_sriov_peer_work(struct work_struct *data) +static void efx_siena_sriov_peer_work(struct work_struct *data) { - struct efx_nic *efx = container_of(data, struct efx_nic, peer_work); - struct vfdi_status *vfdi_status = efx->vfdi_status.addr; + struct siena_nic_data *nic_data = container_of(data, + struct siena_nic_data, + peer_work); + struct efx_nic *efx = nic_data->efx; + struct vfdi_status *vfdi_status = nic_data->vfdi_status.addr; struct efx_vf *vf; struct efx_local_addr *local_addr; struct vfdi_endpoint *peer; @@ -1068,11 +1086,11 @@ static void efx_sriov_peer_work(struct work_struct *data) unsigned int peer_count; unsigned int pos; - mutex_lock(&efx->local_lock); + mutex_lock(&nic_data->local_lock); /* Move the existing peer pages off %local_page_list */ INIT_LIST_HEAD(&pages); - list_splice_tail_init(&efx->local_page_list, &pages); + list_splice_tail_init(&nic_data->local_page_list, &pages); /* Populate the VF addresses starting from entry 1 (entry 0 is * the PF address) @@ -1094,7 +1112,7 @@ static void efx_sriov_peer_work(struct work_struct *data) } /* Fill the remaining addresses */ - list_for_each_entry(local_addr, &efx->local_addr_list, link) { + list_for_each_entry(local_addr, &nic_data->local_addr_list, link) { ether_addr_copy(peer->mac_addr, local_addr->addr); peer->tci = 0; ++peer; @@ -1117,13 +1135,13 @@ static void efx_sriov_peer_work(struct work_struct *data) list_del(&epp->link); } - list_add_tail(&epp->link, &efx->local_page_list); + list_add_tail(&epp->link, &nic_data->local_page_list); peer = (struct vfdi_endpoint *)epp->ptr; peer_space = EFX_PAGE_SIZE / sizeof(struct vfdi_endpoint); } } vfdi_status->peer_count = peer_count; - mutex_unlock(&efx->local_lock); + mutex_unlock(&nic_data->local_lock); /* Free any now unused endpoint pages */ while (!list_empty(&pages)) { @@ -1141,25 +1159,26 @@ static void efx_sriov_peer_work(struct work_struct *data) mutex_lock(&vf->status_lock); if (vf->status_addr) - __efx_sriov_push_vf_status(vf); + __efx_siena_sriov_push_vf_status(vf); mutex_unlock(&vf->status_lock); } } -static void efx_sriov_free_local(struct efx_nic *efx) +static void efx_siena_sriov_free_local(struct efx_nic *efx) { + struct siena_nic_data *nic_data = efx->nic_data; struct efx_local_addr *local_addr; struct efx_endpoint_page *epp; - while (!list_empty(&efx->local_addr_list)) { - local_addr = list_first_entry(&efx->local_addr_list, + while (!list_empty(&nic_data->local_addr_list)) { + local_addr = list_first_entry(&nic_data->local_addr_list, struct efx_local_addr, link); list_del(&local_addr->link); kfree(local_addr); } - while (!list_empty(&efx->local_page_list)) { - epp = list_first_entry(&efx->local_page_list, + while (!list_empty(&nic_data->local_page_list)) { + epp = list_first_entry(&nic_data->local_page_list, struct efx_endpoint_page, link); list_del(&epp->link); dma_free_coherent(&efx->pci_dev->dev, EFX_PAGE_SIZE, @@ -1168,7 +1187,7 @@ static void efx_sriov_free_local(struct efx_nic *efx) } } -static int efx_sriov_vf_alloc(struct efx_nic *efx) +static int efx_siena_sriov_vf_alloc(struct efx_nic *efx) { unsigned index; struct efx_vf *vf; @@ -1185,8 +1204,8 @@ static int efx_sriov_vf_alloc(struct efx_nic *efx) vf->rx_filter_id = -1; vf->tx_filter_mode = VF_TX_FILTER_AUTO; vf->tx_filter_id = -1; - INIT_WORK(&vf->req, efx_sriov_vfdi); - INIT_WORK(&vf->reset_work, efx_sriov_reset_vf_work); + INIT_WORK(&vf->req, efx_siena_sriov_vfdi); + INIT_WORK(&vf->reset_work, efx_siena_sriov_reset_vf_work); init_waitqueue_head(&vf->flush_waitq); mutex_init(&vf->status_lock); mutex_init(&vf->txq_lock); @@ -1195,7 +1214,7 @@ static int efx_sriov_vf_alloc(struct efx_nic *efx) return 0; } -static void efx_sriov_vfs_fini(struct efx_nic *efx) +static void efx_siena_sriov_vfs_fini(struct efx_nic *efx) { struct efx_vf *vf; unsigned int pos; @@ -1212,9 +1231,10 @@ static void efx_sriov_vfs_fini(struct efx_nic *efx) } } -static int efx_sriov_vfs_init(struct efx_nic *efx) +static int efx_siena_sriov_vfs_init(struct efx_nic *efx) { struct pci_dev *pci_dev = efx->pci_dev; + struct siena_nic_data *nic_data = efx->nic_data; unsigned index, devfn, sriov, buftbl_base; u16 offset, stride; struct efx_vf *vf; @@ -1227,7 +1247,7 @@ static int efx_sriov_vfs_init(struct efx_nic *efx) pci_read_config_word(pci_dev, sriov + PCI_SRIOV_VF_OFFSET, &offset); pci_read_config_word(pci_dev, sriov + PCI_SRIOV_VF_STRIDE, &stride); - buftbl_base = efx->vf_buftbl_base; + buftbl_base = nic_data->vf_buftbl_base; devfn = pci_dev->devfn + offset; for (index = 0; index < efx->vf_count; ++index) { vf = efx->vf + index; @@ -1253,13 +1273,14 @@ static int efx_sriov_vfs_init(struct efx_nic *efx) return 0; fail: - efx_sriov_vfs_fini(efx); + efx_siena_sriov_vfs_fini(efx); return rc; } -int efx_sriov_init(struct efx_nic *efx) +int efx_siena_sriov_init(struct efx_nic *efx) { struct net_device *net_dev = efx->net_dev; + struct siena_nic_data *nic_data = efx->nic_data; struct vfdi_status *vfdi_status; int rc; @@ -1271,15 +1292,15 @@ int efx_sriov_init(struct efx_nic *efx) if (efx->vf_count == 0) return 0; - rc = efx_sriov_cmd(efx, true, NULL, NULL); + rc = efx_siena_sriov_cmd(efx, true, NULL, NULL); if (rc) goto fail_cmd; - rc = efx_nic_alloc_buffer(efx, &efx->vfdi_status, sizeof(*vfdi_status), - GFP_KERNEL); + rc = efx_nic_alloc_buffer(efx, &nic_data->vfdi_status, + sizeof(*vfdi_status), GFP_KERNEL); if (rc) goto fail_status; - vfdi_status = efx->vfdi_status.addr; + vfdi_status = nic_data->vfdi_status.addr; memset(vfdi_status, 0, sizeof(*vfdi_status)); vfdi_status->version = 1; vfdi_status->length = sizeof(*vfdi_status); @@ -1289,16 +1310,16 @@ int efx_sriov_init(struct efx_nic *efx) vfdi_status->peer_count = 1 + efx->vf_count; vfdi_status->timer_quantum_ns = efx->timer_quantum_ns; - rc = efx_sriov_vf_alloc(efx); + rc = efx_siena_sriov_vf_alloc(efx); if (rc) goto fail_alloc; - mutex_init(&efx->local_lock); - INIT_WORK(&efx->peer_work, efx_sriov_peer_work); - INIT_LIST_HEAD(&efx->local_addr_list); - INIT_LIST_HEAD(&efx->local_page_list); + mutex_init(&nic_data->local_lock); + INIT_WORK(&nic_data->peer_work, efx_siena_sriov_peer_work); + INIT_LIST_HEAD(&nic_data->local_addr_list); + INIT_LIST_HEAD(&nic_data->local_page_list); - rc = efx_sriov_vfs_init(efx); + rc = efx_siena_sriov_vfs_init(efx); if (rc) goto fail_vfs; @@ -1307,7 +1328,7 @@ int efx_sriov_init(struct efx_nic *efx) efx->vf_init_count = efx->vf_count; rtnl_unlock(); - efx_sriov_usrev(efx, true); + efx_siena_sriov_usrev(efx, true); /* At this point we must be ready to accept VFDI requests */ @@ -1321,34 +1342,35 @@ int efx_sriov_init(struct efx_nic *efx) return 0; fail_pci: - efx_sriov_usrev(efx, false); + efx_siena_sriov_usrev(efx, false); rtnl_lock(); efx->vf_init_count = 0; rtnl_unlock(); - efx_sriov_vfs_fini(efx); + efx_siena_sriov_vfs_fini(efx); fail_vfs: - cancel_work_sync(&efx->peer_work); - efx_sriov_free_local(efx); + cancel_work_sync(&nic_data->peer_work); + efx_siena_sriov_free_local(efx); kfree(efx->vf); fail_alloc: - efx_nic_free_buffer(efx, &efx->vfdi_status); + efx_nic_free_buffer(efx, &nic_data->vfdi_status); fail_status: - efx_sriov_cmd(efx, false, NULL, NULL); + efx_siena_sriov_cmd(efx, false, NULL, NULL); fail_cmd: return rc; } -void efx_sriov_fini(struct efx_nic *efx) +void efx_siena_sriov_fini(struct efx_nic *efx) { struct efx_vf *vf; unsigned int pos; + struct siena_nic_data *nic_data = efx->nic_data; if (efx->vf_init_count == 0) return; /* Disable all interfaces to reconfiguration */ - BUG_ON(efx->vfdi_channel->enabled); - efx_sriov_usrev(efx, false); + BUG_ON(nic_data->vfdi_channel->enabled); + efx_siena_sriov_usrev(efx, false); rtnl_lock(); efx->vf_init_count = 0; rtnl_unlock(); @@ -1359,19 +1381,19 @@ void efx_sriov_fini(struct efx_nic *efx) cancel_work_sync(&vf->req); cancel_work_sync(&vf->reset_work); } - cancel_work_sync(&efx->peer_work); + cancel_work_sync(&nic_data->peer_work); pci_disable_sriov(efx->pci_dev); /* Tear down back-end state */ - efx_sriov_vfs_fini(efx); - efx_sriov_free_local(efx); + efx_siena_sriov_vfs_fini(efx); + efx_siena_sriov_free_local(efx); kfree(efx->vf); - efx_nic_free_buffer(efx, &efx->vfdi_status); - efx_sriov_cmd(efx, false, NULL, NULL); + efx_nic_free_buffer(efx, &nic_data->vfdi_status); + efx_siena_sriov_cmd(efx, false, NULL, NULL); } -void efx_sriov_event(struct efx_channel *channel, efx_qword_t *event) +void efx_siena_sriov_event(struct efx_channel *channel, efx_qword_t *event) { struct efx_nic *efx = channel->efx; struct efx_vf *vf; @@ -1428,7 +1450,7 @@ error: vf->req_seqno = seq + 1; } -void efx_sriov_flr(struct efx_nic *efx, unsigned vf_i) +void efx_siena_sriov_flr(struct efx_nic *efx, unsigned vf_i) { struct efx_vf *vf; @@ -1445,18 +1467,19 @@ void efx_sriov_flr(struct efx_nic *efx, unsigned vf_i) vf->evq0_count = 0; } -void efx_sriov_mac_address_changed(struct efx_nic *efx) +void efx_siena_sriov_mac_address_changed(struct efx_nic *efx) { - struct vfdi_status *vfdi_status = efx->vfdi_status.addr; + struct siena_nic_data *nic_data = efx->nic_data; + struct vfdi_status *vfdi_status = nic_data->vfdi_status.addr; if (!efx->vf_init_count) return; ether_addr_copy(vfdi_status->peers[0].mac_addr, efx->net_dev->dev_addr); - queue_work(vfdi_workqueue, &efx->peer_work); + queue_work(vfdi_workqueue, &nic_data->peer_work); } -void efx_sriov_tx_flush_done(struct efx_nic *efx, efx_qword_t *event) +void efx_siena_sriov_tx_flush_done(struct efx_nic *efx, efx_qword_t *event) { struct efx_vf *vf; unsigned queue, qid; @@ -1475,7 +1498,7 @@ void efx_sriov_tx_flush_done(struct efx_nic *efx, efx_qword_t *event) wake_up(&vf->flush_waitq); } -void efx_sriov_rx_flush_done(struct efx_nic *efx, efx_qword_t *event) +void efx_siena_sriov_rx_flush_done(struct efx_nic *efx, efx_qword_t *event) { struct efx_vf *vf; unsigned ev_failed, queue, qid; @@ -1500,7 +1523,7 @@ void efx_sriov_rx_flush_done(struct efx_nic *efx, efx_qword_t *event) } /* Called from napi. Schedule the reset work item */ -void efx_sriov_desc_fetch_err(struct efx_nic *efx, unsigned dmaq) +void efx_siena_sriov_desc_fetch_err(struct efx_nic *efx, unsigned dmaq) { struct efx_vf *vf; unsigned int rel; @@ -1516,7 +1539,7 @@ void efx_sriov_desc_fetch_err(struct efx_nic *efx, unsigned dmaq) } /* Reset all VFs */ -void efx_sriov_reset(struct efx_nic *efx) +void efx_siena_sriov_reset(struct efx_nic *efx) { unsigned int vf_i; struct efx_buffer buf; @@ -1527,15 +1550,15 @@ void efx_sriov_reset(struct efx_nic *efx) if (efx->vf_init_count == 0) return; - efx_sriov_usrev(efx, true); - (void)efx_sriov_cmd(efx, true, NULL, NULL); + efx_siena_sriov_usrev(efx, true); + (void)efx_siena_sriov_cmd(efx, true, NULL, NULL); if (efx_nic_alloc_buffer(efx, &buf, EFX_PAGE_SIZE, GFP_NOIO)) return; for (vf_i = 0; vf_i < efx->vf_init_count; ++vf_i) { vf = efx->vf + vf_i; - efx_sriov_reset_vf(vf, &buf); + efx_siena_sriov_reset_vf(vf, &buf); } efx_nic_free_buffer(efx, &buf); @@ -1543,8 +1566,8 @@ void efx_sriov_reset(struct efx_nic *efx) int efx_init_sriov(void) { - /* A single threaded workqueue is sufficient. efx_sriov_vfdi() and - * efx_sriov_peer_work() spend almost all their time sleeping for + /* A single threaded workqueue is sufficient. efx_siena_sriov_vfdi() and + * efx_siena_sriov_peer_work() spend almost all their time sleeping for * MCDI to complete anyway */ vfdi_workqueue = create_singlethread_workqueue("sfc_vfdi"); @@ -1559,7 +1582,7 @@ void efx_fini_sriov(void) destroy_workqueue(vfdi_workqueue); } -int efx_sriov_set_vf_mac(struct net_device *net_dev, int vf_i, u8 *mac) +int efx_siena_sriov_set_vf_mac(struct net_device *net_dev, int vf_i, u8 *mac) { struct efx_nic *efx = netdev_priv(net_dev); struct efx_vf *vf; @@ -1570,14 +1593,14 @@ int efx_sriov_set_vf_mac(struct net_device *net_dev, int vf_i, u8 *mac) mutex_lock(&vf->status_lock); ether_addr_copy(vf->addr.mac_addr, mac); - __efx_sriov_update_vf_addr(vf); + __efx_siena_sriov_update_vf_addr(vf); mutex_unlock(&vf->status_lock); return 0; } -int efx_sriov_set_vf_vlan(struct net_device *net_dev, int vf_i, - u16 vlan, u8 qos) +int efx_siena_sriov_set_vf_vlan(struct net_device *net_dev, int vf_i, + u16 vlan, u8 qos) { struct efx_nic *efx = netdev_priv(net_dev); struct efx_vf *vf; @@ -1590,14 +1613,14 @@ int efx_sriov_set_vf_vlan(struct net_device *net_dev, int vf_i, mutex_lock(&vf->status_lock); tci = (vlan & VLAN_VID_MASK) | ((qos & 0x7) << VLAN_PRIO_SHIFT); vf->addr.tci = htons(tci); - __efx_sriov_update_vf_addr(vf); + __efx_siena_sriov_update_vf_addr(vf); mutex_unlock(&vf->status_lock); return 0; } -int efx_sriov_set_vf_spoofchk(struct net_device *net_dev, int vf_i, - bool spoofchk) +int efx_siena_sriov_set_vf_spoofchk(struct net_device *net_dev, int vf_i, + bool spoofchk) { struct efx_nic *efx = netdev_priv(net_dev); struct efx_vf *vf; @@ -1620,8 +1643,8 @@ int efx_sriov_set_vf_spoofchk(struct net_device *net_dev, int vf_i, return rc; } -int efx_sriov_get_vf_config(struct net_device *net_dev, int vf_i, - struct ifla_vf_info *ivi) +int efx_siena_sriov_get_vf_config(struct net_device *net_dev, int vf_i, + struct ifla_vf_info *ivi) { struct efx_nic *efx = netdev_priv(net_dev); struct efx_vf *vf; diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c index 77ed74561e5f..f9c87624a0af 100644 --- a/drivers/net/ethernet/smsc/smsc911x.c +++ b/drivers/net/ethernet/smsc/smsc911x.c @@ -59,6 +59,8 @@ #include <linux/of_device.h> #include <linux/of_gpio.h> #include <linux/of_net.h> +#include <linux/pm_runtime.h> + #include "smsc911x.h" #define SMSC_CHIPNAME "smsc911x" @@ -2338,6 +2340,9 @@ static int smsc911x_drv_remove(struct platform_device *pdev) free_netdev(dev); + pm_runtime_put(&pdev->dev); + pm_runtime_disable(&pdev->dev); + return 0; } @@ -2491,6 +2496,9 @@ static int smsc911x_drv_probe(struct platform_device *pdev) if (pdata->config.shift) pdata->ops = &shifted_smsc911x_ops; + pm_runtime_enable(&pdev->dev); + pm_runtime_get_sync(&pdev->dev); + retval = smsc911x_init(dev); if (retval < 0) goto out_disable_resources; @@ -2572,6 +2580,8 @@ out_unregister_netdev_5: out_free_irq: free_irq(dev->irq, dev); out_disable_resources: + pm_runtime_put(&pdev->dev); + pm_runtime_disable(&pdev->dev); (void)smsc911x_disable_resources(pdev); out_enable_resources_fail: smsc911x_free_resources(pdev); diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig index b02d4a3ffa37..7d3af190be55 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig @@ -14,62 +14,20 @@ config STMMAC_ETH if STMMAC_ETH config STMMAC_PLATFORM - bool "STMMAC Platform bus support" + tristate "STMMAC Platform bus support" depends on STMMAC_ETH default y ---help--- - This selects the platform specific bus support for - the stmmac device driver. This is the driver used - on many embedded STM platforms based on ARM and SuperH - processors. + This selects the platform specific bus support for the stmmac driver. + This is the driver used on several SoCs: + STi, Allwinner, Amlogic Meson, Altera SOCFPGA. + If you have a controller with this interface, say Y or M here. If unsure, say N. -config DWMAC_MESON - bool "Amlogic Meson dwmac support" - depends on STMMAC_PLATFORM && ARCH_MESON - help - Support for Ethernet controller on Amlogic Meson SoCs. - - This selects the Amlogic Meson SoC glue layer support for - the stmmac device driver. This driver is used for Meson6 and - Meson8 SoCs. - -config DWMAC_SOCFPGA - bool "SOCFPGA dwmac support" - depends on STMMAC_PLATFORM && MFD_SYSCON && (ARCH_SOCFPGA || COMPILE_TEST) - help - Support for ethernet controller on Altera SOCFPGA - - This selects the Altera SOCFPGA SoC glue layer support - for the stmmac device driver. This driver is used for - arria5 and cyclone5 FPGA SoCs. - -config DWMAC_SUNXI - bool "Allwinner GMAC support" - depends on STMMAC_PLATFORM && ARCH_SUNXI - default y - ---help--- - Support for Allwinner A20/A31 GMAC ethernet controllers. - - This selects Allwinner SoC glue layer support for the - stmmac device driver. This driver is used for A20/A31 - GMAC ethernet controller. - -config DWMAC_STI - bool "STi GMAC support" - depends on STMMAC_PLATFORM && ARCH_STI - default y - ---help--- - Support for ethernet controller on STi SOCs. - - This selects STi SoC glue layer support for the stmmac - device driver. This driver is used on for the STi series - SOCs GMAC ethernet controller. - config STMMAC_PCI - bool "STMMAC PCI bus support" + tristate "STMMAC PCI bus support" depends on STMMAC_ETH && PCI ---help--- This is to select the Synopsys DWMAC available on PCI devices, @@ -79,22 +37,4 @@ config STMMAC_PCI D1215994A VIRTEX FPGA board. If unsure, say N. - -config STMMAC_DEBUG_FS - bool "Enable monitoring via sysFS " - default n - depends on STMMAC_ETH && DEBUG_FS - ---help--- - The stmmac entry in /sys reports DMA TX/RX rings - or (if supported) the HW cap register. - -config STMMAC_DA - bool "STMMAC DMA arbitration scheme" - default n - ---help--- - Selecting this option, rx has priority over Tx (only for Giga - Ethernet device). - By default, the DMA arbitration scheme is based on Round-robin - (rx:tx priority is 1:1). - endif diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile index 0533d0ba783d..ac4d5629d905 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Makefile +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile @@ -1,11 +1,12 @@ obj-$(CONFIG_STMMAC_ETH) += stmmac.o -stmmac-$(CONFIG_STMMAC_PLATFORM) += stmmac_platform.o -stmmac-$(CONFIG_STMMAC_PCI) += stmmac_pci.o -stmmac-$(CONFIG_DWMAC_MESON) += dwmac-meson.o -stmmac-$(CONFIG_DWMAC_SUNXI) += dwmac-sunxi.o -stmmac-$(CONFIG_DWMAC_STI) += dwmac-sti.o -stmmac-$(CONFIG_DWMAC_SOCFPGA) += dwmac-socfpga.o stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \ - chain_mode.o dwmac_lib.o dwmac1000_core.o dwmac1000_dma.o \ - dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o \ + chain_mode.o dwmac_lib.o dwmac1000_core.o dwmac1000_dma.o \ + dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o \ mmc_core.o stmmac_hwtstamp.o stmmac_ptp.o $(stmmac-y) + +obj-$(CONFIG_STMMAC_PLATFORM) += stmmac-platform.o +stmmac-platform-objs:= stmmac_platform.o dwmac-meson.o dwmac-sunxi.o \ + dwmac-sti.o dwmac-socfpga.o + +obj-$(CONFIG_STMMAC_PCI) += stmmac-pci.o +stmmac-pci-objs:= stmmac_pci.o diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index 593e6c4144a7..cd77289c3cfe 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -44,6 +44,7 @@ #undef FRAME_FILTER_DEBUG /* #define FRAME_FILTER_DEBUG */ +/* Extra statistic and debug information exposed by ethtool */ struct stmmac_extra_stats { /* Transmit errors */ unsigned long tx_underflow ____cacheline_aligned; @@ -220,6 +221,7 @@ enum dma_irq_status { handle_tx = 0x8, }; +/* EEE and LPI defines */ #define CORE_IRQ_TX_PATH_IN_LPI_MODE (1 << 0) #define CORE_IRQ_TX_PATH_EXIT_LPI_MODE (1 << 1) #define CORE_IRQ_RX_PATH_IN_LPI_MODE (1 << 2) @@ -229,6 +231,7 @@ enum dma_irq_status { #define CORE_PCS_LINK_STATUS (1 << 6) #define CORE_RGMII_IRQ (1 << 7) +/* Physical Coding Sublayer */ struct rgmii_adv { unsigned int pause; unsigned int duplex; @@ -294,6 +297,7 @@ struct dma_features { #define JUMBO_LEN 9000 +/* Descriptors helpers */ struct stmmac_desc_ops { /* DMA RX descriptor ring initialization */ void (*init_rx_desc) (struct dma_desc *p, int disable_rx_ic, int mode, @@ -341,6 +345,10 @@ struct stmmac_desc_ops { int (*get_rx_timestamp_status) (void *desc, u32 ats); }; +extern const struct stmmac_desc_ops enh_desc_ops; +extern const struct stmmac_desc_ops ndesc_ops; + +/* Specific DMA helpers */ struct stmmac_dma_ops { /* DMA core initialization */ int (*init) (void __iomem *ioaddr, int pbl, int fb, int mb, @@ -370,6 +378,7 @@ struct stmmac_dma_ops { struct mac_device_info; +/* Helpers to program the MAC core */ struct stmmac_ops { /* MAC core initialization */ void (*core_init)(struct mac_device_info *hw, int mtu); @@ -400,6 +409,7 @@ struct stmmac_ops { void (*get_adv)(struct mac_device_info *hw, struct rgmii_adv *adv); }; +/* PTP and HW Timer helpers */ struct stmmac_hwtimestamp { void (*config_hw_tstamping) (void __iomem *ioaddr, u32 data); void (*config_sub_second_increment) (void __iomem *ioaddr); @@ -410,6 +420,8 @@ struct stmmac_hwtimestamp { u64(*get_systime) (void __iomem *ioaddr); }; +extern const struct stmmac_hwtimestamp stmmac_ptp; + struct mac_link { int port; int duplex; @@ -421,6 +433,7 @@ struct mii_regs { unsigned int data; /* MII Data */ }; +/* Helpers to manage the descriptors for chain and ring modes */ struct stmmac_mode_ops { void (*init) (void *des, dma_addr_t phy_addr, unsigned int size, unsigned int extend_desc); diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c index d225a603e604..cca028d632f6 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c @@ -18,6 +18,8 @@ #include <linux/platform_device.h> #include <linux/stmmac.h> +#include "stmmac_platform.h" + #define ETHMAC_SPEED_100 BIT(1) struct meson_dwmac { @@ -56,7 +58,7 @@ static void *meson6_dwmac_setup(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 1); dwmac->reg = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(dwmac->reg)) - return dwmac->reg; + return ERR_CAST(dwmac->reg); return dwmac; } diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c index 3aad413e74b4..e97074cd5800 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c @@ -23,7 +23,9 @@ #include <linux/regmap.h> #include <linux/reset.h> #include <linux/stmmac.h> + #include "stmmac.h" +#include "stmmac_platform.h" #define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII 0x0 #define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII 0x1 diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c index ccfe7e510418..0e137751e76e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c @@ -1,4 +1,4 @@ -/** +/* * dwmac-sti.c - STMicroelectronics DWMAC Specific Glue layer * * Copyright (C) 2003-2014 STMicroelectronics (R&D) Limited @@ -22,6 +22,8 @@ #include <linux/of.h> #include <linux/of_net.h> +#include "stmmac_platform.h" + #define DWMAC_125MHZ 125000000 #define DWMAC_50MHZ 50000000 #define DWMAC_25MHZ 25000000 @@ -35,9 +37,8 @@ #define IS_PHY_IF_MODE_GBIT(iface) (IS_PHY_IF_MODE_RGMII(iface) || \ iface == PHY_INTERFACE_MODE_GMII) -/* STiH4xx register definitions (STiH415/STiH416/STiH407/STiH410 families) */ - -/** +/* STiH4xx register definitions (STiH415/STiH416/STiH407/STiH410 families) + * * Below table summarizes the clock requirement and clock sources for * supported phy interface modes with link speeds. * ________________________________________________ @@ -76,9 +77,7 @@ #define STIH4XX_ETH_SEL_INTERNAL_NOTEXT_PHYCLK BIT(7) #define STIH4XX_ETH_SEL_TXCLK_NOT_CLK125 BIT(6) -/* STiD127 register definitions */ - -/** +/* STiD127 register definitions *----------------------- * src |BIT(6)| BIT(7)| *----------------------- @@ -104,13 +103,13 @@ #define EN_MASK GENMASK(1, 1) #define EN BIT(1) -/** +/* * 3 bits [4:2] * 000-GMII/MII * 001-RGMII * 010-SGMII * 100-RMII -*/ + */ #define MII_PHY_SEL_MASK GENMASK(4, 2) #define ETH_PHY_SEL_RMII BIT(4) #define ETH_PHY_SEL_SGMII BIT(3) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c index 771cd15fca18..c5ea9ab75b03 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c @@ -1,4 +1,4 @@ -/** +/* * dwmac-sunxi.c - Allwinner sunxi DWMAC specific glue layer * * Copyright (C) 2013 Chen-Yu Tsai @@ -22,6 +22,8 @@ #include <linux/of_net.h> #include <linux/regulator/consumer.h> +#include "stmmac_platform.h" + struct sunxi_priv_data { int interface; int clk_enabled; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c index 0c2058a69fd2..59d92e811750 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c @@ -70,10 +70,6 @@ static int dwmac1000_dma_init(void __iomem *ioaddr, int pbl, int fb, int mb, if (mb) value |= DMA_BUS_MODE_MB; -#ifdef CONFIG_STMMAC_DA - value |= DMA_BUS_MODE_DA; /* Rx has priority over tx */ -#endif - if (atds) value |= DMA_BUS_MODE_ATDS; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index c3c40650b309..c0a391983372 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -122,9 +122,7 @@ int stmmac_mdio_unregister(struct net_device *ndev); int stmmac_mdio_register(struct net_device *ndev); int stmmac_mdio_reset(struct mii_bus *mii); void stmmac_set_ethtool_ops(struct net_device *netdev); -extern const struct stmmac_desc_ops enh_desc_ops; -extern const struct stmmac_desc_ops ndesc_ops; -extern const struct stmmac_hwtimestamp stmmac_ptp; + int stmmac_ptp_register(struct stmmac_priv *priv); void stmmac_ptp_unregister(struct stmmac_priv *priv); int stmmac_resume(struct net_device *ndev); @@ -136,77 +134,4 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device, void stmmac_disable_eee_mode(struct stmmac_priv *priv); bool stmmac_eee_init(struct stmmac_priv *priv); -#ifdef CONFIG_STMMAC_PLATFORM -#ifdef CONFIG_DWMAC_MESON -extern const struct stmmac_of_data meson6_dwmac_data; -#endif -#ifdef CONFIG_DWMAC_SUNXI -extern const struct stmmac_of_data sun7i_gmac_data; -#endif -#ifdef CONFIG_DWMAC_STI -extern const struct stmmac_of_data stih4xx_dwmac_data; -extern const struct stmmac_of_data stid127_dwmac_data; -#endif -#ifdef CONFIG_DWMAC_SOCFPGA -extern const struct stmmac_of_data socfpga_gmac_data; -#endif -extern struct platform_driver stmmac_pltfr_driver; -static inline int stmmac_register_platform(void) -{ - int err; - - err = platform_driver_register(&stmmac_pltfr_driver); - if (err) - pr_err("stmmac: failed to register the platform driver\n"); - - return err; -} - -static inline void stmmac_unregister_platform(void) -{ - platform_driver_unregister(&stmmac_pltfr_driver); -} -#else -static inline int stmmac_register_platform(void) -{ - pr_debug("stmmac: do not register the platf driver\n"); - - return 0; -} - -static inline void stmmac_unregister_platform(void) -{ -} -#endif /* CONFIG_STMMAC_PLATFORM */ - -#ifdef CONFIG_STMMAC_PCI -extern struct pci_driver stmmac_pci_driver; -static inline int stmmac_register_pci(void) -{ - int err; - - err = pci_register_driver(&stmmac_pci_driver); - if (err) - pr_err("stmmac: failed to register the PCI driver\n"); - - return err; -} - -static inline void stmmac_unregister_pci(void) -{ - pci_unregister_driver(&stmmac_pci_driver); -} -#else -static inline int stmmac_register_pci(void) -{ - pr_debug("stmmac: do not register the PCI driver\n"); - - return 0; -} - -static inline void stmmac_unregister_pci(void) -{ -} -#endif /* CONFIG_STMMAC_PCI */ - #endif /* __STMMAC_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 18c46bb0f3bf..118a427d1942 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -44,10 +44,10 @@ #include <linux/slab.h> #include <linux/prefetch.h> #include <linux/pinctrl/consumer.h> -#ifdef CONFIG_STMMAC_DEBUG_FS +#ifdef CONFIG_DEBUG_FS #include <linux/debugfs.h> #include <linux/seq_file.h> -#endif /* CONFIG_STMMAC_DEBUG_FS */ +#endif /* CONFIG_DEBUG_FS */ #include <linux/net_tstamp.h> #include "stmmac_ptp.h" #include "stmmac.h" @@ -116,7 +116,7 @@ MODULE_PARM_DESC(chain_mode, "To use chain instead of ring mode"); static irqreturn_t stmmac_interrupt(int irq, void *dev_id); -#ifdef CONFIG_STMMAC_DEBUG_FS +#ifdef CONFIG_DEBUG_FS static int stmmac_init_fs(struct net_device *dev); static void stmmac_exit_fs(void); #endif @@ -125,8 +125,8 @@ static void stmmac_exit_fs(void); /** * stmmac_verify_args - verify the driver parameters. - * Description: it verifies if some wrong parameter is passed to the driver. - * Note that wrong parameters are replaced with the default values. + * Description: it checks the driver parameters and set a default in case of + * errors. */ static void stmmac_verify_args(void) { @@ -191,14 +191,8 @@ static void stmmac_clk_csr_set(struct stmmac_priv *priv) static void print_pkt(unsigned char *buf, int len) { - int j; - pr_debug("len = %d byte, buf addr: 0x%p", len, buf); - for (j = 0; j < len; j++) { - if ((j % 16) == 0) - pr_debug("\n %03x:", j); - pr_debug(" %02x", buf[j]); - } - pr_debug("\n"); + pr_debug("len = %d byte, buf addr: 0x%p\n", len, buf); + print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf, len); } /* minimum number of free TX descriptors required to wake up TX process */ @@ -210,7 +204,7 @@ static inline u32 stmmac_tx_avail(struct stmmac_priv *priv) } /** - * stmmac_hw_fix_mac_speed: callback for speed selection + * stmmac_hw_fix_mac_speed - callback for speed selection * @priv: driver private structure * Description: on some platforms (e.g. ST), some HW system configuraton * registers have to be set according to the link speed negotiated. @@ -224,9 +218,10 @@ static inline void stmmac_hw_fix_mac_speed(struct stmmac_priv *priv) } /** - * stmmac_enable_eee_mode: Check and enter in LPI mode + * stmmac_enable_eee_mode - check and enter in LPI mode * @priv: driver private structure - * Description: this function is to verify and enter in LPI mode for EEE. + * Description: this function is to verify and enter in LPI mode in case of + * EEE. */ static void stmmac_enable_eee_mode(struct stmmac_priv *priv) { @@ -237,7 +232,7 @@ static void stmmac_enable_eee_mode(struct stmmac_priv *priv) } /** - * stmmac_disable_eee_mode: disable/exit from EEE + * stmmac_disable_eee_mode - disable and exit from LPI mode * @priv: driver private structure * Description: this function is to exit and disable EEE in case of * LPI state is true. This is called by the xmit. @@ -250,7 +245,7 @@ void stmmac_disable_eee_mode(struct stmmac_priv *priv) } /** - * stmmac_eee_ctrl_timer: EEE TX SW timer. + * stmmac_eee_ctrl_timer - EEE TX SW timer. * @arg : data hook * Description: * if there is no data transfer and if we are not in LPI state, @@ -265,13 +260,12 @@ static void stmmac_eee_ctrl_timer(unsigned long arg) } /** - * stmmac_eee_init: init EEE + * stmmac_eee_init - init EEE * @priv: driver private structure * Description: - * If the EEE support has been enabled while configuring the driver, - * if the GMAC actually supports the EEE (from the HW cap reg) and the - * phy can also manage EEE, so enable the LPI state and start the timer - * to verify if the tx path can enter in LPI state. + * if the GMAC supports the EEE (from the HW cap reg) and the phy device + * can also manage EEE, this function enable the LPI state and start related + * timer. */ bool stmmac_eee_init(struct stmmac_priv *priv) { @@ -338,7 +332,7 @@ out: return ret; } -/* stmmac_get_tx_hwtstamp: get HW TX timestamps +/* stmmac_get_tx_hwtstamp - get HW TX timestamps * @priv: driver private structure * @entry : descriptor index to be used. * @skb : the socket buffer @@ -380,7 +374,7 @@ static void stmmac_get_tx_hwtstamp(struct stmmac_priv *priv, return; } -/* stmmac_get_rx_hwtstamp: get HW RX timestamps +/* stmmac_get_rx_hwtstamp - get HW RX timestamps * @priv: driver private structure * @entry : descriptor index to be used. * @skb : the socket buffer @@ -636,11 +630,11 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr) } /** - * stmmac_init_ptp: init PTP + * stmmac_init_ptp - init PTP * @priv: driver private structure - * Description: this is to verify if the HW supports the PTPv1 or v2. + * Description: this is to verify if the HW supports the PTPv1 or PTPv2. * This is done by looking at the HW cap. register. - * Also it registers the ptp driver. + * This function also registers the ptp driver. */ static int stmmac_init_ptp(struct stmmac_priv *priv) { @@ -682,9 +676,13 @@ static void stmmac_release_ptp(struct stmmac_priv *priv) } /** - * stmmac_adjust_link + * stmmac_adjust_link - adjusts the link parameters * @dev: net device structure - * Description: it adjusts the link parameters. + * Description: this is the helper called by the physical abstraction layer + * drivers to communicate the phy link status. According the speed and duplex + * this driver can invoke registered glue-logic as well. + * It also invoke the eee initialization because it could happen when switch + * on different networks (that are eee capable). */ static void stmmac_adjust_link(struct net_device *dev) { @@ -774,7 +772,7 @@ static void stmmac_adjust_link(struct net_device *dev) } /** - * stmmac_check_pcs_mode: verify if RGMII/SGMII is supported + * stmmac_check_pcs_mode - verify if RGMII/SGMII is supported * @priv: driver private structure * Description: this is to verify if the HW supports the PCS. * Physical Coding Sublayer (PCS) interface that can be used when the MAC is @@ -863,7 +861,7 @@ static int stmmac_init_phy(struct net_device *dev) } /** - * stmmac_display_ring: display ring + * stmmac_display_ring - display ring * @head: pointer to the head of the ring passed. * @size: size of the ring. * @extend_desc: to verify if extended descriptors are used. @@ -931,7 +929,7 @@ static int stmmac_set_bfsize(int mtu, int bufsize) } /** - * stmmac_clear_descriptors: clear descriptors + * stmmac_clear_descriptors - clear descriptors * @priv: driver private structure * Description: this function is called to clear the tx and rx descriptors * in case of both basic and extended descriptors are used. @@ -963,6 +961,15 @@ static void stmmac_clear_descriptors(struct stmmac_priv *priv) (i == txsize - 1)); } +/** + * stmmac_init_rx_buffers - init the RX descriptor buffer. + * @priv: driver private structure + * @p: descriptor pointer + * @i: descriptor index + * @flags: gfp flag. + * Description: this function is called to allocate a receive buffer, perform + * the DMA mapping and init the descriptor. + */ static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p, int i, gfp_t flags) { @@ -1007,7 +1014,8 @@ static void stmmac_free_rx_buffers(struct stmmac_priv *priv, int i) /** * init_dma_desc_rings - init the RX/TX descriptor rings * @dev: net device structure - * Description: this function initializes the DMA RX/TX descriptors + * @flags: gfp flag. + * Description: this function initializes the DMA RX/TX descriptors * and allocates the socket buffers. It suppors the chained and ring * modes. */ @@ -1144,6 +1152,14 @@ static void dma_free_tx_skbufs(struct stmmac_priv *priv) } } +/** + * alloc_dma_desc_resources - alloc TX/RX resources. + * @priv: private structure + * Description: according to which descriptor can be used (extend or basic) + * this function allocates the resources for TX and RX paths. In case of + * reception, for example, it pre-allocated the RX socket buffer in order to + * allow zero-copy mechanism. + */ static int alloc_dma_desc_resources(struct stmmac_priv *priv) { unsigned int txsize = priv->dma_tx_size; @@ -1255,8 +1271,8 @@ static void free_dma_desc_resources(struct stmmac_priv *priv) /** * stmmac_dma_operation_mode - HW DMA operation mode * @priv: driver private structure - * Description: it sets the DMA operation mode: tx/rx DMA thresholds - * or Store-And-Forward capability. + * Description: it is used for configuring the DMA operation mode register in + * order to program the tx/rx DMA thresholds or Store-And-Forward mode. */ static void stmmac_dma_operation_mode(struct stmmac_priv *priv) { @@ -1277,9 +1293,9 @@ static void stmmac_dma_operation_mode(struct stmmac_priv *priv) } /** - * stmmac_tx_clean: + * stmmac_tx_clean - to manage the transmission completion * @priv: driver private structure - * Description: it reclaims resources after transmission completes. + * Description: it reclaims the transmit resources after transmission completes. */ static void stmmac_tx_clean(struct stmmac_priv *priv) { @@ -1378,10 +1394,10 @@ static inline void stmmac_disable_dma_irq(struct stmmac_priv *priv) } /** - * stmmac_tx_err: irq tx error mng function + * stmmac_tx_err - to manage the tx error * @priv: driver private structure * Description: it cleans the descriptors and restarts the transmission - * in case of errors. + * in case of transmission errors. */ static void stmmac_tx_err(struct stmmac_priv *priv) { @@ -1409,12 +1425,11 @@ static void stmmac_tx_err(struct stmmac_priv *priv) } /** - * stmmac_dma_interrupt: DMA ISR + * stmmac_dma_interrupt - DMA ISR * @priv: driver private structure * Description: this is the DMA ISR. It is called by the main ISR. - * It calls the dwmac dma routine to understand which type of interrupt - * happened. In case of there is a Normal interrupt and either TX or RX - * interrupt happened so the NAPI is scheduled. + * It calls the dwmac dma routine and schedule poll method in case of some + * work can be done. */ static void stmmac_dma_interrupt(struct stmmac_priv *priv) { @@ -1457,6 +1472,12 @@ static void stmmac_mmc_setup(struct stmmac_priv *priv) pr_info(" No MAC Management Counters available\n"); } +/** + * stmmac_get_synopsys_id - return the SYINID. + * @priv: driver private structure + * Description: this simple function is to decode and return the SYINID + * starting from the HW core register. + */ static u32 stmmac_get_synopsys_id(struct stmmac_priv *priv) { u32 hwid = priv->hw->synopsys_uid; @@ -1475,11 +1496,11 @@ static u32 stmmac_get_synopsys_id(struct stmmac_priv *priv) } /** - * stmmac_selec_desc_mode: to select among: normal/alternate/extend descriptors + * stmmac_selec_desc_mode - to select among: normal/alternate/extend descriptors * @priv: driver private structure * Description: select the Enhanced/Alternate or Normal descriptors. - * In case of Enhanced/Alternate, it looks at the extended descriptors are - * supported by the HW cap. register. + * In case of Enhanced/Alternate, it checks if the extended descriptors are + * supported by the HW capability register. */ static void stmmac_selec_desc_mode(struct stmmac_priv *priv) { @@ -1501,7 +1522,7 @@ static void stmmac_selec_desc_mode(struct stmmac_priv *priv) } /** - * stmmac_get_hw_features: get MAC capabilities from the HW cap. register. + * stmmac_get_hw_features - get MAC capabilities from the HW cap. register. * @priv: driver private structure * Description: * new GMAC chip generations have a new register to indicate the @@ -1559,7 +1580,7 @@ static int stmmac_get_hw_features(struct stmmac_priv *priv) } /** - * stmmac_check_ether_addr: check if the MAC addr is valid + * stmmac_check_ether_addr - check if the MAC addr is valid * @priv: driver private structure * Description: * it is to verify if the MAC address is valid, in case of failures it @@ -1578,7 +1599,7 @@ static void stmmac_check_ether_addr(struct stmmac_priv *priv) } /** - * stmmac_init_dma_engine: DMA init. + * stmmac_init_dma_engine - DMA init. * @priv: driver private structure * Description: * It inits the DMA invoking the specific MAC/GMAC callback. @@ -1607,7 +1628,7 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv) } /** - * stmmac_tx_timer: mitigation sw timer for tx. + * stmmac_tx_timer - mitigation sw timer for tx. * @data: data pointer * Description: * This is the timer handler to directly invoke the stmmac_tx_clean. @@ -1620,7 +1641,7 @@ static void stmmac_tx_timer(unsigned long data) } /** - * stmmac_init_tx_coalesce: init tx mitigation options. + * stmmac_init_tx_coalesce - init tx mitigation options. * @priv: driver private structure * Description: * This inits the transmit coalesce parameters: i.e. timer rate, @@ -1639,10 +1660,13 @@ static void stmmac_init_tx_coalesce(struct stmmac_priv *priv) } /** - * stmmac_hw_setup: setup mac in a usable state. + * stmmac_hw_setup - setup mac in a usable state. * @dev : pointer to the device structure. * Description: - * This function sets up the ip in a usable state. + * this is the main function to setup the HW in a usable state because the + * dma engine is reset, the core registers are configured (e.g. AXI, + * Checksum features, timers). The DMA is ready to start receiving and + * transmitting. * Return value: * 0 on success and an appropriate (-)ve integer as defined in errno.h * file on failure. @@ -1688,7 +1712,7 @@ static int stmmac_hw_setup(struct net_device *dev) if (ret && ret != -EOPNOTSUPP) pr_warn("%s: failed PTP initialisation\n", __func__); -#ifdef CONFIG_STMMAC_DEBUG_FS +#ifdef CONFIG_DEBUG_FS ret = stmmac_init_fs(dev); if (ret < 0) pr_warn("%s: failed debugFS registration\n", __func__); @@ -1870,7 +1894,7 @@ static int stmmac_release(struct net_device *dev) netif_carrier_off(dev); -#ifdef CONFIG_STMMAC_DEBUG_FS +#ifdef CONFIG_DEBUG_FS stmmac_exit_fs(); #endif @@ -1880,7 +1904,7 @@ static int stmmac_release(struct net_device *dev) } /** - * stmmac_xmit: Tx entry point of the driver + * stmmac_xmit - Tx entry point of the driver * @skb : the socket buffer * @dev : device pointer * Description : this is the tx entry point of the driver. @@ -2055,7 +2079,7 @@ static void stmmac_rx_vlan(struct net_device *dev, struct sk_buff *skb) /** - * stmmac_rx_refill: refill used skb preallocated buffers + * stmmac_rx_refill - refill used skb preallocated buffers * @priv: driver private structure * Description : this is to reallocate the skb for the reception process * that is based on zero-copy. @@ -2106,7 +2130,7 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv) } /** - * stmmac_rx_refill: refill used skb preallocated buffers + * stmmac_rx - manage the receive process * @priv: driver private structure * @limit: napi bugget. * Description : this the function called by the napi poll method. @@ -2375,8 +2399,11 @@ static int stmmac_set_features(struct net_device *netdev, * @irq: interrupt number. * @dev_id: to pass the net device pointer. * Description: this is the main driver interrupt service routine. - * It calls the DMA ISR and also the core ISR to manage PMT, MMC, LPI - * interrupts. + * It can call: + * o DMA service routine (to manage incoming frame reception and transmission + * status) + * o Core interrupts to manage: remote wake-up, management counter, LPI + * interrupts. */ static irqreturn_t stmmac_interrupt(int irq, void *dev_id) { @@ -2457,7 +2484,7 @@ static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) return ret; } -#ifdef CONFIG_STMMAC_DEBUG_FS +#ifdef CONFIG_DEBUG_FS static struct dentry *stmmac_fs_dir; static struct dentry *stmmac_rings_status; static struct dentry *stmmac_dma_cap; @@ -2642,7 +2669,7 @@ static void stmmac_exit_fs(void) debugfs_remove(stmmac_dma_cap); debugfs_remove(stmmac_fs_dir); } -#endif /* CONFIG_STMMAC_DEBUG_FS */ +#endif /* CONFIG_DEBUG_FS */ static const struct net_device_ops stmmac_netdev_ops = { .ndo_open = stmmac_open, @@ -2663,11 +2690,10 @@ static const struct net_device_ops stmmac_netdev_ops = { /** * stmmac_hw_init - Init the MAC device * @priv: driver private structure - * Description: this function detects which MAC device - * (GMAC/MAC10-100) has to attached, checks the HW capability - * (if supported) and sets the driver's features (for example - * to use the ring or chaine mode or support the normal/enh - * descriptor structure). + * Description: this function is to configure the MAC device according to + * some platform parameters or the HW capability register. It prepares the + * driver to use either ring or chain modes and to setup either enhanced or + * normal descriptors. */ static int stmmac_hw_init(struct stmmac_priv *priv) { @@ -2891,6 +2917,7 @@ error_clk_get: return ERR_PTR(ret); } +EXPORT_SYMBOL_GPL(stmmac_dvr_probe); /** * stmmac_dvr_remove @@ -2920,8 +2947,15 @@ int stmmac_dvr_remove(struct net_device *ndev) return 0; } +EXPORT_SYMBOL_GPL(stmmac_dvr_remove); -#ifdef CONFIG_PM +/** + * stmmac_suspend - suspend callback + * @ndev: net device pointer + * Description: this is the function to suspend the device and it is called + * by the platform driver to stop the network queue, release the resources, + * program the PMT register (for WoL), clean and release driver resources. + */ int stmmac_suspend(struct net_device *ndev) { struct stmmac_priv *priv = netdev_priv(ndev); @@ -2963,7 +2997,14 @@ int stmmac_suspend(struct net_device *ndev) priv->oldduplex = -1; return 0; } +EXPORT_SYMBOL_GPL(stmmac_suspend); +/** + * stmmac_resume - resume callback + * @ndev: net device pointer + * Description: when resume this function is invoked to setup the DMA and CORE + * in a usable state. + */ int stmmac_resume(struct net_device *ndev) { struct stmmac_priv *priv = netdev_priv(ndev); @@ -3009,37 +3050,7 @@ int stmmac_resume(struct net_device *ndev) return 0; } -#endif /* CONFIG_PM */ - -/* Driver can be configured w/ and w/ both PCI and Platf drivers - * depending on the configuration selected. - */ -static int __init stmmac_init(void) -{ - int ret; - - ret = stmmac_register_platform(); - if (ret) - goto err; - ret = stmmac_register_pci(); - if (ret) - goto err_pci; - return 0; -err_pci: - stmmac_unregister_platform(); -err: - pr_err("stmmac: driver registration failed\n"); - return ret; -} - -static void __exit stmmac_exit(void) -{ - stmmac_unregister_platform(); - stmmac_unregister_pci(); -} - -module_init(stmmac_init); -module_exit(stmmac_exit); +EXPORT_SYMBOL_GPL(stmmac_resume); #ifndef MODULE static int __init stmmac_cmdline_opt(char *str) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c index e17a970eaf2b..77a6d68f7189 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c @@ -71,64 +71,46 @@ static void stmmac_default_data(void) static int stmmac_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { - int ret = 0; - void __iomem *addr = NULL; - struct stmmac_priv *priv = NULL; + struct stmmac_priv *priv; int i; + int ret; /* Enable pci device */ - ret = pci_enable_device(pdev); + ret = pcim_enable_device(pdev); if (ret) { - pr_err("%s : ERROR: failed to enable %s device\n", __func__, - pci_name(pdev)); + dev_err(&pdev->dev, "%s: ERROR: failed to enable device\n", + __func__); return ret; } - if (pci_request_regions(pdev, STMMAC_RESOURCE_NAME)) { - pr_err("%s: ERROR: failed to get PCI region\n", __func__); - ret = -ENODEV; - goto err_out_req_reg_failed; - } /* Get the base address of device */ - for (i = 0; i <= 5; i++) { + for (i = 0; i <= PCI_STD_RESOURCE_END; i++) { if (pci_resource_len(pdev, i) == 0) continue; - addr = pci_iomap(pdev, i, 0); - if (addr == NULL) { - pr_err("%s: ERROR: cannot map register memory aborting", - __func__); - ret = -EIO; - goto err_out_map_failed; - } + ret = pcim_iomap_regions(pdev, BIT(i), pci_name(pdev)); + if (ret) + return ret; break; } + pci_set_master(pdev); stmmac_default_data(); - priv = stmmac_dvr_probe(&(pdev->dev), &plat_dat, addr); + priv = stmmac_dvr_probe(&pdev->dev, &plat_dat, + pcim_iomap_table(pdev)[i]); if (IS_ERR(priv)) { - pr_err("%s: main driver probe failed", __func__); - ret = PTR_ERR(priv); - goto err_out; + dev_err(&pdev->dev, "%s: main driver probe failed\n", __func__); + return PTR_ERR(priv); } priv->dev->irq = pdev->irq; priv->wol_irq = pdev->irq; pci_set_drvdata(pdev, priv->dev); - pr_debug("STMMAC platform driver registration completed"); + dev_dbg(&pdev->dev, "STMMAC PCI driver registration completed\n"); return 0; - -err_out: - pci_clear_master(pdev); -err_out_map_failed: - pci_release_regions(pdev); -err_out_req_reg_failed: - pci_disable_device(pdev); - - return ret; } /** @@ -141,39 +123,30 @@ err_out_req_reg_failed: static void stmmac_pci_remove(struct pci_dev *pdev) { struct net_device *ndev = pci_get_drvdata(pdev); - struct stmmac_priv *priv = netdev_priv(ndev); stmmac_dvr_remove(ndev); - - pci_iounmap(pdev, priv->ioaddr); - pci_release_regions(pdev); - pci_disable_device(pdev); } -#ifdef CONFIG_PM -static int stmmac_pci_suspend(struct pci_dev *pdev, pm_message_t state) +#ifdef CONFIG_PM_SLEEP +static int stmmac_pci_suspend(struct device *dev) { + struct pci_dev *pdev = to_pci_dev(dev); struct net_device *ndev = pci_get_drvdata(pdev); - int ret; - - ret = stmmac_suspend(ndev); - pci_save_state(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - return ret; + return stmmac_suspend(ndev); } -static int stmmac_pci_resume(struct pci_dev *pdev) +static int stmmac_pci_resume(struct device *dev) { + struct pci_dev *pdev = to_pci_dev(dev); struct net_device *ndev = pci_get_drvdata(pdev); - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - return stmmac_resume(ndev); } #endif +static SIMPLE_DEV_PM_OPS(stmmac_pm_ops, stmmac_pci_suspend, stmmac_pci_resume); + #define STMMAC_VENDOR_ID 0x700 #define STMMAC_DEVICE_ID 0x1108 @@ -185,17 +158,18 @@ static const struct pci_device_id stmmac_id_table[] = { MODULE_DEVICE_TABLE(pci, stmmac_id_table); -struct pci_driver stmmac_pci_driver = { +static struct pci_driver stmmac_pci_driver = { .name = STMMAC_RESOURCE_NAME, .id_table = stmmac_id_table, .probe = stmmac_pci_probe, .remove = stmmac_pci_remove, -#ifdef CONFIG_PM - .suspend = stmmac_pci_suspend, - .resume = stmmac_pci_resume, -#endif + .driver = { + .pm = &stmmac_pm_ops, + }, }; +module_pci_driver(stmmac_pci_driver); + MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet PCI driver"); MODULE_AUTHOR("Rayagond Kokatanur <rayagond.kokatanur@vayavyalabs.com>"); MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>"); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index 5b0da3986216..07054ce84ba8 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -27,25 +27,19 @@ #include <linux/of.h> #include <linux/of_net.h> #include <linux/of_device.h> + #include "stmmac.h" +#include "stmmac_platform.h" static const struct of_device_id stmmac_dt_ids[] = { -#ifdef CONFIG_DWMAC_MESON + /* SoC specific glue layers should come before generic bindings */ { .compatible = "amlogic,meson6-dwmac", .data = &meson6_dwmac_data}, -#endif -#ifdef CONFIG_DWMAC_SUNXI { .compatible = "allwinner,sun7i-a20-gmac", .data = &sun7i_gmac_data}, -#endif -#ifdef CONFIG_DWMAC_STI { .compatible = "st,stih415-dwmac", .data = &stih4xx_dwmac_data}, { .compatible = "st,stih416-dwmac", .data = &stih4xx_dwmac_data}, { .compatible = "st,stid127-dwmac", .data = &stid127_dwmac_data}, { .compatible = "st,stih407-dwmac", .data = &stih4xx_dwmac_data}, -#endif -#ifdef CONFIG_DWMAC_SOCFPGA { .compatible = "altr,socfpga-stmmac", .data = &socfpga_gmac_data }, -#endif - /* SoC specific glue layers should come before generic bindings */ { .compatible = "st,spear600-gmac"}, { .compatible = "snps,dwmac-3.610"}, { .compatible = "snps,dwmac-3.70a"}, @@ -57,7 +51,11 @@ MODULE_DEVICE_TABLE(of, stmmac_dt_ids); #ifdef CONFIG_OF -/* This function validates the number of Multicast filtering bins specified +/** + * dwmac1000_validate_mcast_bins - validates the number of Multicast filter bins + * @mcast_bins: Multicast filtering bins + * Description: + * this function validates the number of Multicast filtering bins specified * by the configuration through the device tree. The Synopsys GMAC supports * 64 bins, 128 bins, or 256 bins. "bins" refer to the division of CRC * number space. 64 bins correspond to 6 bits of the CRC, 128 corresponds @@ -83,7 +81,11 @@ static int dwmac1000_validate_mcast_bins(int mcast_bins) return x; } -/* This function validates the number of Unicast address entries supported +/** + * dwmac1000_validate_ucast_entries - validate the Unicast address entries + * @ucast_entries: number of Unicast address entries + * Description: + * This function validates the number of Unicast address entries supported * by a particular Synopsys 10/100/1000 controller. The Synopsys controller * supports 1, 32, 64, or 128 Unicast filter entries for it's Unicast filter * logic. This function validates a valid, supported configuration is @@ -109,6 +111,15 @@ static int dwmac1000_validate_ucast_entries(int ucast_entries) return x; } +/** + * stmmac_probe_config_dt - parse device-tree driver parameters + * @pdev: platform_device structure + * @plat: driver data platform structure + * @mac: MAC address to use + * Description: + * this function is to read the driver parameters from device-tree and + * set some private fields that will be used by the main at runtime. + */ static int stmmac_probe_config_dt(struct platform_device *pdev, struct plat_stmmacenet_data *plat, const char **mac) @@ -242,11 +253,11 @@ static int stmmac_probe_config_dt(struct platform_device *pdev, #endif /* CONFIG_OF */ /** - * stmmac_pltfr_probe + * stmmac_pltfr_probe - platform driver probe. * @pdev: platform device pointer - * Description: platform_device probe function. It allocates - * the necessary resources and invokes the main to init - * the net device, register the mdio bus etc. + * Description: platform_device probe function. It is to allocate + * the necessary platform resources, invoke custom helper (if required) and + * invoke the main probe function. */ static int stmmac_pltfr_probe(struct platform_device *pdev) { @@ -369,7 +380,14 @@ static int stmmac_pltfr_remove(struct platform_device *pdev) return ret; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP +/** + * stmmac_pltfr_suspend + * @dev: device pointer + * Description: this function is invoked when suspend the driver and it direcly + * call the main suspend function and then, if required, on some platform, it + * can call an exit helper. + */ static int stmmac_pltfr_suspend(struct device *dev) { int ret; @@ -384,6 +402,13 @@ static int stmmac_pltfr_suspend(struct device *dev) return ret; } +/** + * stmmac_pltfr_resume + * @dev: device pointer + * Description: this function is invoked when resume the driver before calling + * the main resume function, on some platforms, it can call own init helper + * if required. + */ static int stmmac_pltfr_resume(struct device *dev) { struct net_device *ndev = dev_get_drvdata(dev); @@ -395,13 +420,12 @@ static int stmmac_pltfr_resume(struct device *dev) return stmmac_resume(ndev); } - -#endif /* CONFIG_PM */ +#endif /* CONFIG_PM_SLEEP */ static SIMPLE_DEV_PM_OPS(stmmac_pltfr_pm_ops, - stmmac_pltfr_suspend, stmmac_pltfr_resume); + stmmac_pltfr_suspend, stmmac_pltfr_resume); -struct platform_driver stmmac_pltfr_driver = { +static struct platform_driver stmmac_pltfr_driver = { .probe = stmmac_pltfr_probe, .remove = stmmac_pltfr_remove, .driver = { @@ -409,9 +433,11 @@ struct platform_driver stmmac_pltfr_driver = { .owner = THIS_MODULE, .pm = &stmmac_pltfr_pm_ops, .of_match_table = of_match_ptr(stmmac_dt_ids), - }, + }, }; +module_platform_driver(stmmac_pltfr_driver); + MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet PLATFORM driver"); MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>"); MODULE_LICENSE("GPL"); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h new file mode 100644 index 000000000000..25dd1f7ace02 --- /dev/null +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h @@ -0,0 +1,28 @@ +/******************************************************************************* + Copyright (C) 2007-2009 STMicroelectronics Ltd + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> +*******************************************************************************/ + +#ifndef __STMMAC_PLATFORM_H__ +#define __STMMAC_PLATFORM_H__ + +extern const struct stmmac_of_data meson6_dwmac_data; +extern const struct stmmac_of_data sun7i_gmac_data; +extern const struct stmmac_of_data stih4xx_dwmac_data; +extern const struct stmmac_of_data stid127_dwmac_data; +extern const struct stmmac_of_data socfpga_gmac_data; + +#endif /* __STMMAC_PLATFORM_H__ */ diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c index 3652afd3ec78..a556eba8eeed 100644 --- a/drivers/net/ethernet/sun/sunvnet.c +++ b/drivers/net/ethernet/sun/sunvnet.c @@ -40,6 +40,8 @@ MODULE_DESCRIPTION("Sun LDOM virtual network driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_MODULE_VERSION); +#define VNET_MAX_TXQS 16 + /* Heuristic for the number of times to exponentially backoff and * retry sending an LDC trigger when EAGAIN is encountered */ @@ -311,9 +313,7 @@ static int vnet_rx_one(struct vnet_port *port, unsigned int len, dev->stats.rx_packets++; dev->stats.rx_bytes += len; - - netif_rx(skb); - + napi_gro_receive(&port->napi, skb); return 0; out_free_skb: @@ -430,6 +430,7 @@ static int vnet_walk_rx_one(struct vnet_port *port, struct vio_driver_state *vio = &port->vio; int err; + BUG_ON(desc == NULL); if (IS_ERR(desc)) return PTR_ERR(desc); @@ -456,10 +457,11 @@ static int vnet_walk_rx_one(struct vnet_port *port, } static int vnet_walk_rx(struct vnet_port *port, struct vio_dring_state *dr, - u32 start, u32 end) + u32 start, u32 end, int *npkts, int budget) { struct vio_driver_state *vio = &port->vio; int ack_start = -1, ack_end = -1; + bool send_ack = true; end = (end == (u32) -1) ? prev_idx(start, dr) : next_idx(end, dr); @@ -471,6 +473,7 @@ static int vnet_walk_rx(struct vnet_port *port, struct vio_dring_state *dr, return err; if (err != 0) break; + (*npkts)++; if (ack_start == -1) ack_start = start; ack_end = start; @@ -482,13 +485,26 @@ static int vnet_walk_rx(struct vnet_port *port, struct vio_dring_state *dr, return err; ack_start = -1; } + if ((*npkts) >= budget) { + send_ack = false; + break; + } } if (unlikely(ack_start == -1)) ack_start = ack_end = prev_idx(start, dr); - return vnet_send_ack(port, dr, ack_start, ack_end, VIO_DRING_STOPPED); + if (send_ack) { + port->napi_resume = false; + return vnet_send_ack(port, dr, ack_start, ack_end, + VIO_DRING_STOPPED); + } else { + port->napi_resume = true; + port->napi_stop_idx = ack_end; + return 1; + } } -static int vnet_rx(struct vnet_port *port, void *msgbuf) +static int vnet_rx(struct vnet_port *port, void *msgbuf, int *npkts, + int budget) { struct vio_dring_data *pkt = msgbuf; struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_RX_RING]; @@ -505,11 +521,13 @@ static int vnet_rx(struct vnet_port *port, void *msgbuf) return 0; } - dr->rcv_nxt++; + if (!port->napi_resume) + dr->rcv_nxt++; /* XXX Validate pkt->start_idx and pkt->end_idx XXX */ - return vnet_walk_rx(port, dr, pkt->start_idx, pkt->end_idx); + return vnet_walk_rx(port, dr, pkt->start_idx, pkt->end_idx, + npkts, budget); } static int idx_is_pending(struct vio_dring_state *dr, u32 end) @@ -535,19 +553,26 @@ static int vnet_ack(struct vnet_port *port, void *msgbuf) struct vnet *vp; u32 end; struct vio_net_desc *desc; + struct netdev_queue *txq; + if (unlikely(pkt->tag.stype_env != VIO_DRING_DATA)) return 0; end = pkt->end_idx; - if (unlikely(!idx_is_pending(dr, end))) + vp = port->vp; + dev = vp->dev; + netif_tx_lock(dev); + if (unlikely(!idx_is_pending(dr, end))) { + netif_tx_unlock(dev); return 0; + } /* sync for race conditions with vnet_start_xmit() and tell xmit it * is time to send a trigger. */ dr->cons = next_idx(end, dr); desc = vio_dring_entry(dr, dr->cons); - if (desc->hdr.state == VIO_DESC_READY && port->start_cons) { + if (desc->hdr.state == VIO_DESC_READY && !port->start_cons) { /* vnet_start_xmit() just populated this dring but missed * sending the "start" LDC message to the consumer. * Send a "start" trigger on its behalf. @@ -559,11 +584,10 @@ static int vnet_ack(struct vnet_port *port, void *msgbuf) } else { port->start_cons = true; } + netif_tx_unlock(dev); - - vp = port->vp; - dev = vp->dev; - if (unlikely(netif_queue_stopped(dev) && + txq = netdev_get_tx_queue(dev, port->q_index); + if (unlikely(netif_tx_queue_stopped(txq) && vnet_tx_dring_avail(dr) >= VNET_TX_WAKEUP_THRESH(dr))) return 1; @@ -591,58 +615,62 @@ static int handle_mcast(struct vnet_port *port, void *msgbuf) return 0; } -static void maybe_tx_wakeup(unsigned long param) +/* Got back a STOPPED LDC message on port. If the queue is stopped, + * wake it up so that we'll send out another START message at the + * next TX. + */ +static void maybe_tx_wakeup(struct vnet_port *port) { - struct vnet *vp = (struct vnet *)param; - struct net_device *dev = vp->dev; - - netif_tx_lock(dev); - if (likely(netif_queue_stopped(dev))) { - struct vnet_port *port; - int wake = 1; + struct netdev_queue *txq; - list_for_each_entry(port, &vp->port_list, list) { - struct vio_dring_state *dr; + txq = netdev_get_tx_queue(port->vp->dev, port->q_index); + __netif_tx_lock(txq, smp_processor_id()); + if (likely(netif_tx_queue_stopped(txq))) { + struct vio_dring_state *dr; - dr = &port->vio.drings[VIO_DRIVER_TX_RING]; - if (vnet_tx_dring_avail(dr) < - VNET_TX_WAKEUP_THRESH(dr)) { - wake = 0; - break; - } - } - if (wake) - netif_wake_queue(dev); + dr = &port->vio.drings[VIO_DRIVER_TX_RING]; + netif_tx_wake_queue(txq); } - netif_tx_unlock(dev); + __netif_tx_unlock(txq); } -static void vnet_event(void *arg, int event) +static inline bool port_is_up(struct vnet_port *vnet) +{ + struct vio_driver_state *vio = &vnet->vio; + + return !!(vio->hs_state & VIO_HS_COMPLETE); +} + +static int vnet_event_napi(struct vnet_port *port, int budget) { - struct vnet_port *port = arg; struct vio_driver_state *vio = &port->vio; - unsigned long flags; int tx_wakeup, err; + int npkts = 0; + int event = (port->rx_event & LDC_EVENT_RESET); - spin_lock_irqsave(&vio->lock, flags); - +ldc_ctrl: if (unlikely(event == LDC_EVENT_RESET || event == LDC_EVENT_UP)) { vio_link_state_change(vio, event); - spin_unlock_irqrestore(&vio->lock, flags); if (event == LDC_EVENT_RESET) { port->rmtu = 0; vio_port_up(vio); } - return; + port->rx_event = 0; + return 0; } + /* We may have multiple LDC events in rx_event. Unroll send_events() */ + event = (port->rx_event & LDC_EVENT_UP); + port->rx_event &= ~(LDC_EVENT_RESET|LDC_EVENT_UP); + if (event == LDC_EVENT_UP) + goto ldc_ctrl; + event = port->rx_event; + if (!(event & LDC_EVENT_DATA_READY)) + return 0; - if (unlikely(event != LDC_EVENT_DATA_READY)) { - pr_warn("Unexpected LDC event %d\n", event); - spin_unlock_irqrestore(&vio->lock, flags); - return; - } + /* we dont expect any other bits than RESET, UP, DATA_READY */ + BUG_ON(event != LDC_EVENT_DATA_READY); tx_wakeup = err = 0; while (1) { @@ -651,6 +679,20 @@ static void vnet_event(void *arg, int event) u64 raw[8]; } msgbuf; + if (port->napi_resume) { + struct vio_dring_data *pkt = + (struct vio_dring_data *)&msgbuf; + struct vio_dring_state *dr = + &port->vio.drings[VIO_DRIVER_RX_RING]; + + pkt->tag.type = VIO_TYPE_DATA; + pkt->tag.stype = VIO_SUBTYPE_INFO; + pkt->tag.stype_env = VIO_DRING_DATA; + pkt->seq = dr->rcv_nxt; + pkt->start_idx = next_idx(port->napi_stop_idx, dr); + pkt->end_idx = -1; + goto napi_resume; + } err = ldc_read(vio->lp, &msgbuf, sizeof(msgbuf)); if (unlikely(err < 0)) { if (err == -ECONNRESET) @@ -667,10 +709,22 @@ static void vnet_event(void *arg, int event) err = vio_validate_sid(vio, &msgbuf.tag); if (err < 0) break; - +napi_resume: if (likely(msgbuf.tag.type == VIO_TYPE_DATA)) { if (msgbuf.tag.stype == VIO_SUBTYPE_INFO) { - err = vnet_rx(port, &msgbuf); + if (!port_is_up(port)) { + /* failures like handshake_failure() + * may have cleaned up dring, but + * NAPI polling may bring us here. + */ + err = -ECONNRESET; + break; + } + err = vnet_rx(port, &msgbuf, &npkts, budget); + if (npkts >= budget) + break; + if (npkts == 0) + break; } else if (msgbuf.tag.stype == VIO_SUBTYPE_ACK) { err = vnet_ack(port, &msgbuf); if (err > 0) @@ -691,15 +745,34 @@ static void vnet_event(void *arg, int event) if (err == -ECONNRESET) break; } - spin_unlock(&vio->lock); - /* Kick off a tasklet to wake the queue. We cannot call - * maybe_tx_wakeup directly here because we could deadlock on - * netif_tx_lock() with dev_watchdog() - */ if (unlikely(tx_wakeup && err != -ECONNRESET)) - tasklet_schedule(&port->vp->vnet_tx_wakeup); + maybe_tx_wakeup(port); + return npkts; +} + +static int vnet_poll(struct napi_struct *napi, int budget) +{ + struct vnet_port *port = container_of(napi, struct vnet_port, napi); + struct vio_driver_state *vio = &port->vio; + int processed = vnet_event_napi(port, budget); + + if (processed < budget) { + napi_complete(napi); + port->rx_event &= ~LDC_EVENT_DATA_READY; + vio_set_intr(vio->vdev->rx_ino, HV_INTR_ENABLED); + } + return processed; +} + +static void vnet_event(void *arg, int event) +{ + struct vnet_port *port = arg; + struct vio_driver_state *vio = &port->vio; + + port->rx_event |= event; + vio_set_intr(vio->vdev->rx_ino, HV_INTR_DISABLED); + napi_schedule(&port->napi); - local_irq_restore(flags); } static int __vnet_tx_trigger(struct vnet_port *port, u32 start) @@ -746,26 +819,19 @@ static int __vnet_tx_trigger(struct vnet_port *port, u32 start) return err; } -static inline bool port_is_up(struct vnet_port *vnet) -{ - struct vio_driver_state *vio = &vnet->vio; - - return !!(vio->hs_state & VIO_HS_COMPLETE); -} - struct vnet_port *__tx_port_find(struct vnet *vp, struct sk_buff *skb) { unsigned int hash = vnet_hashfn(skb->data); struct hlist_head *hp = &vp->port_hash[hash]; struct vnet_port *port; - hlist_for_each_entry(port, hp, hash) { + hlist_for_each_entry_rcu(port, hp, hash) { if (!port_is_up(port)) continue; if (ether_addr_equal(port->raddr, skb->data)) return port; } - list_for_each_entry(port, &vp->port_list, list) { + list_for_each_entry_rcu(port, &vp->port_list, list) { if (!port->switch_port) continue; if (!port_is_up(port)) @@ -775,18 +841,6 @@ struct vnet_port *__tx_port_find(struct vnet *vp, struct sk_buff *skb) return NULL; } -struct vnet_port *tx_port_find(struct vnet *vp, struct sk_buff *skb) -{ - struct vnet_port *ret; - unsigned long flags; - - spin_lock_irqsave(&vp->lock, flags); - ret = __tx_port_find(vp, skb); - spin_unlock_irqrestore(&vp->lock, flags); - - return ret; -} - static struct sk_buff *vnet_clean_tx_ring(struct vnet_port *port, unsigned *pending) { @@ -847,11 +901,10 @@ static void vnet_clean_timer_expire(unsigned long port0) struct vnet_port *port = (struct vnet_port *)port0; struct sk_buff *freeskbs; unsigned pending; - unsigned long flags; - spin_lock_irqsave(&port->vio.lock, flags); + netif_tx_lock(port->vp->dev); freeskbs = vnet_clean_tx_ring(port, &pending); - spin_unlock_irqrestore(&port->vio.lock, flags); + netif_tx_unlock(port->vp->dev); vnet_free_skbs(freeskbs); @@ -898,28 +951,43 @@ static inline struct sk_buff *vnet_skb_shape(struct sk_buff *skb, void **pstart, return skb; } +static u16 +vnet_select_queue(struct net_device *dev, struct sk_buff *skb, + void *accel_priv, select_queue_fallback_t fallback) +{ + struct vnet *vp = netdev_priv(dev); + struct vnet_port *port = __tx_port_find(vp, skb); + + if (port == NULL) + return 0; + return port->q_index; +} + static int vnet_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct vnet *vp = netdev_priv(dev); - struct vnet_port *port = tx_port_find(vp, skb); + struct vnet_port *port = NULL; struct vio_dring_state *dr; struct vio_net_desc *d; - unsigned long flags; unsigned int len; struct sk_buff *freeskbs = NULL; int i, err, txi; void *start = NULL; int nlen = 0; unsigned pending = 0; - - if (unlikely(!port)) - goto out_dropped; + struct netdev_queue *txq; skb = vnet_skb_shape(skb, &start, &nlen); - if (unlikely(!skb)) goto out_dropped; + rcu_read_lock(); + port = __tx_port_find(vp, skb); + if (unlikely(!port)) { + rcu_read_unlock(); + goto out_dropped; + } + if (skb->len > port->rmtu) { unsigned long localmtu = port->rmtu - ETH_HLEN; @@ -937,6 +1005,7 @@ static int vnet_start_xmit(struct sk_buff *skb, struct net_device *dev) fl4.saddr = ip_hdr(skb)->saddr; rt = ip_route_output_key(dev_net(dev), &fl4); + rcu_read_unlock(); if (!IS_ERR(rt)) { skb_dst_set(skb, &rt->dst); icmp_send(skb, ICMP_DEST_UNREACH, @@ -951,18 +1020,18 @@ static int vnet_start_xmit(struct sk_buff *skb, struct net_device *dev) goto out_dropped; } - spin_lock_irqsave(&port->vio.lock, flags); - dr = &port->vio.drings[VIO_DRIVER_TX_RING]; + i = skb_get_queue_mapping(skb); + txq = netdev_get_tx_queue(dev, i); if (unlikely(vnet_tx_dring_avail(dr) < 1)) { - if (!netif_queue_stopped(dev)) { - netif_stop_queue(dev); + if (!netif_tx_queue_stopped(txq)) { + netif_tx_stop_queue(txq); /* This is a hard error, log it. */ netdev_err(dev, "BUG! Tx Ring full when queue awake!\n"); dev->stats.tx_errors++; } - spin_unlock_irqrestore(&port->vio.lock, flags); + rcu_read_unlock(); return NETDEV_TX_BUSY; } @@ -986,7 +1055,7 @@ static int vnet_start_xmit(struct sk_buff *skb, struct net_device *dev) (LDC_MAP_SHADOW | LDC_MAP_DIRECT | LDC_MAP_RW)); if (err < 0) { netdev_info(dev, "tx buffer map error %d\n", err); - goto out_dropped_unlock; + goto out_dropped; } port->tx_bufs[txi].ncookies = err; @@ -1039,7 +1108,7 @@ static int vnet_start_xmit(struct sk_buff *skb, struct net_device *dev) netdev_info(dev, "TX trigger error %d\n", err); d->hdr.state = VIO_DESC_FREE; dev->stats.tx_carrier_errors++; - goto out_dropped_unlock; + goto out_dropped; } ldc_start_done: @@ -1050,31 +1119,29 @@ ldc_start_done: dr->prod = (dr->prod + 1) & (VNET_TX_RING_SIZE - 1); if (unlikely(vnet_tx_dring_avail(dr) < 1)) { - netif_stop_queue(dev); + netif_tx_stop_queue(txq); if (vnet_tx_dring_avail(dr) > VNET_TX_WAKEUP_THRESH(dr)) - netif_wake_queue(dev); + netif_tx_wake_queue(txq); } - spin_unlock_irqrestore(&port->vio.lock, flags); + (void)mod_timer(&port->clean_timer, jiffies + VNET_CLEAN_TIMEOUT); + rcu_read_unlock(); vnet_free_skbs(freeskbs); - (void)mod_timer(&port->clean_timer, jiffies + VNET_CLEAN_TIMEOUT); - return NETDEV_TX_OK; -out_dropped_unlock: - spin_unlock_irqrestore(&port->vio.lock, flags); - out_dropped: - if (skb) - dev_kfree_skb(skb); - vnet_free_skbs(freeskbs); if (pending) (void)mod_timer(&port->clean_timer, jiffies + VNET_CLEAN_TIMEOUT); else if (port) del_timer(&port->clean_timer); + if (port) + rcu_read_unlock(); + if (skb) + dev_kfree_skb(skb); + vnet_free_skbs(freeskbs); dev->stats.tx_dropped++; return NETDEV_TX_OK; } @@ -1087,14 +1154,14 @@ static void vnet_tx_timeout(struct net_device *dev) static int vnet_open(struct net_device *dev) { netif_carrier_on(dev); - netif_start_queue(dev); + netif_tx_start_all_queues(dev); return 0; } static int vnet_close(struct net_device *dev) { - netif_stop_queue(dev); + netif_tx_stop_all_queues(dev); netif_carrier_off(dev); return 0; @@ -1204,18 +1271,17 @@ static void vnet_set_rx_mode(struct net_device *dev) { struct vnet *vp = netdev_priv(dev); struct vnet_port *port; - unsigned long flags; - spin_lock_irqsave(&vp->lock, flags); - if (!list_empty(&vp->port_list)) { - port = list_entry(vp->port_list.next, struct vnet_port, list); + rcu_read_lock(); + list_for_each_entry_rcu(port, &vp->port_list, list) { if (port->switch_port) { __update_mc_list(vp, dev); __send_mc_list(vp, port); + break; } } - spin_unlock_irqrestore(&vp->lock, flags); + rcu_read_unlock(); } static int vnet_change_mtu(struct net_device *dev, int new_mtu) @@ -1342,6 +1408,21 @@ err_out: return err; } +#ifdef CONFIG_NET_POLL_CONTROLLER +static void vnet_poll_controller(struct net_device *dev) +{ + struct vnet *vp = netdev_priv(dev); + struct vnet_port *port; + unsigned long flags; + + spin_lock_irqsave(&vp->lock, flags); + if (!list_empty(&vp->port_list)) { + port = list_entry(vp->port_list.next, struct vnet_port, list); + napi_schedule(&port->napi); + } + spin_unlock_irqrestore(&vp->lock, flags); +} +#endif static LIST_HEAD(vnet_list); static DEFINE_MUTEX(vnet_list_mutex); @@ -1354,6 +1435,10 @@ static const struct net_device_ops vnet_ops = { .ndo_tx_timeout = vnet_tx_timeout, .ndo_change_mtu = vnet_change_mtu, .ndo_start_xmit = vnet_start_xmit, + .ndo_select_queue = vnet_select_queue, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = vnet_poll_controller, +#endif }; static struct vnet *vnet_new(const u64 *local_mac) @@ -1362,7 +1447,7 @@ static struct vnet *vnet_new(const u64 *local_mac) struct vnet *vp; int err, i; - dev = alloc_etherdev(sizeof(*vp)); + dev = alloc_etherdev_mqs(sizeof(*vp), VNET_MAX_TXQS, 1); if (!dev) return ERR_PTR(-ENOMEM); dev->needed_headroom = VNET_PACKET_SKIP + 8; @@ -1374,7 +1459,6 @@ static struct vnet *vnet_new(const u64 *local_mac) vp = netdev_priv(dev); spin_lock_init(&vp->lock); - tasklet_init(&vp->vnet_tx_wakeup, maybe_tx_wakeup, (unsigned long)vp); vp->dev = dev; INIT_LIST_HEAD(&vp->port_list); @@ -1434,7 +1518,6 @@ static void vnet_cleanup(void) vp = list_first_entry(&vnet_list, struct vnet, list); list_del(&vp->list); dev = vp->dev; - tasklet_kill(&vp->vnet_tx_wakeup); /* vio_unregister_driver() should have cleaned up port_list */ BUG_ON(!list_empty(&vp->port_list)); unregister_netdev(dev); @@ -1489,6 +1572,25 @@ static void print_version(void) const char *remote_macaddr_prop = "remote-mac-address"; +static void +vnet_port_add_txq(struct vnet_port *port) +{ + struct vnet *vp = port->vp; + int n; + + n = vp->nports++; + n = n & (VNET_MAX_TXQS - 1); + port->q_index = n; + netif_tx_wake_queue(netdev_get_tx_queue(vp->dev, port->q_index)); +} + +static void +vnet_port_rm_txq(struct vnet_port *port) +{ + port->vp->nports--; + netif_tx_stop_queue(netdev_get_tx_queue(port->vp->dev, port->q_index)); +} + static int vnet_port_probe(struct vio_dev *vdev, const struct vio_device_id *id) { struct mdesc_handle *hp; @@ -1536,6 +1638,8 @@ static int vnet_port_probe(struct vio_dev *vdev, const struct vio_device_id *id) if (err) goto err_out_free_port; + netif_napi_add(port->vp->dev, &port->napi, vnet_poll, NAPI_POLL_WEIGHT); + err = vnet_port_alloc_tx_bufs(port); if (err) goto err_out_free_ldc; @@ -1550,10 +1654,12 @@ static int vnet_port_probe(struct vio_dev *vdev, const struct vio_device_id *id) spin_lock_irqsave(&vp->lock, flags); if (switch_port) - list_add(&port->list, &vp->port_list); + list_add_rcu(&port->list, &vp->port_list); else - list_add_tail(&port->list, &vp->port_list); - hlist_add_head(&port->hash, &vp->port_hash[vnet_hashfn(port->raddr)]); + list_add_tail_rcu(&port->list, &vp->port_list); + hlist_add_head_rcu(&port->hash, + &vp->port_hash[vnet_hashfn(port->raddr)]); + vnet_port_add_txq(port); spin_unlock_irqrestore(&vp->lock, flags); dev_set_drvdata(&vdev->dev, port); @@ -1564,6 +1670,7 @@ static int vnet_port_probe(struct vio_dev *vdev, const struct vio_device_id *id) setup_timer(&port->clean_timer, vnet_clean_timer_expire, (unsigned long)port); + napi_enable(&port->napi); vio_port_up(&port->vio); mdesc_release(hp); @@ -1571,6 +1678,7 @@ static int vnet_port_probe(struct vio_dev *vdev, const struct vio_device_id *id) return 0; err_out_free_ldc: + netif_napi_del(&port->napi); vio_ldc_free(&port->vio); err_out_free_port: @@ -1586,17 +1694,18 @@ static int vnet_port_remove(struct vio_dev *vdev) struct vnet_port *port = dev_get_drvdata(&vdev->dev); if (port) { - struct vnet *vp = port->vp; - unsigned long flags; del_timer_sync(&port->vio.timer); - del_timer_sync(&port->clean_timer); - spin_lock_irqsave(&vp->lock, flags); - list_del(&port->list); - hlist_del(&port->hash); - spin_unlock_irqrestore(&vp->lock, flags); + napi_disable(&port->napi); + + list_del_rcu(&port->list); + hlist_del_rcu(&port->hash); + synchronize_rcu(); + del_timer_sync(&port->clean_timer); + vnet_port_rm_txq(port); + netif_napi_del(&port->napi); vnet_port_free_tx_bufs(port); vio_ldc_free(&port->vio); diff --git a/drivers/net/ethernet/sun/sunvnet.h b/drivers/net/ethernet/sun/sunvnet.h index c91104542619..cd5d343ea232 100644 --- a/drivers/net/ethernet/sun/sunvnet.h +++ b/drivers/net/ethernet/sun/sunvnet.h @@ -56,6 +56,12 @@ struct vnet_port { struct timer_list clean_timer; u64 rmtu; + + struct napi_struct napi; + u32 napi_stop_idx; + bool napi_resume; + int rx_event; + u16 q_index; }; static inline struct vnet_port *to_vnet_port(struct vio_driver_state *vio) @@ -97,7 +103,7 @@ struct vnet { struct list_head list; u64 local_mac; - struct tasklet_struct vnet_tx_wakeup; + int nports; }; #endif /* _SUNVNET_H */ diff --git a/drivers/net/ethernet/wiznet/w5100.c b/drivers/net/ethernet/wiznet/w5100.c index 0f56b1c0e082..70a930ac4fa9 100644 --- a/drivers/net/ethernet/wiznet/w5100.c +++ b/drivers/net/ethernet/wiznet/w5100.c @@ -638,14 +638,12 @@ static int w5100_hw_probe(struct platform_device *pdev) } mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem) - return -ENXIO; - mem_size = resource_size(mem); - priv->base = devm_ioremap_resource(&pdev->dev, mem); if (IS_ERR(priv->base)) return PTR_ERR(priv->base); + mem_size = resource_size(mem); + spin_lock_init(&priv->reg_lock); priv->indirect = mem_size < W5100_BUS_DIRECT_SIZE; if (priv->indirect) { diff --git a/drivers/net/ethernet/wiznet/w5300.c b/drivers/net/ethernet/wiznet/w5300.c index f961f14a0473..7974b7d90fcc 100644 --- a/drivers/net/ethernet/wiznet/w5300.c +++ b/drivers/net/ethernet/wiznet/w5300.c @@ -558,14 +558,12 @@ static int w5300_hw_probe(struct platform_device *pdev) } mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem) - return -ENXIO; - mem_size = resource_size(mem); - priv->base = devm_ioremap_resource(&pdev->dev, mem); if (IS_ERR(priv->base)) return PTR_ERR(priv->base); + mem_size = resource_size(mem); + spin_lock_init(&priv->reg_lock); priv->indirect = mem_size < W5300_BUS_DIRECT_SIZE; if (priv->indirect) { diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c index 629077050fce..9c2d91ea0af4 100644 --- a/drivers/net/ethernet/xilinx/ll_temac_main.c +++ b/drivers/net/ethernet/xilinx/ll_temac_main.c @@ -224,8 +224,7 @@ static void temac_dma_bd_release(struct net_device *ndev) dma_free_coherent(ndev->dev.parent, sizeof(*lp->tx_bd_v) * TX_BD_NUM, lp->tx_bd_v, lp->tx_bd_p); - if (lp->rx_skb) - kfree(lp->rx_skb); + kfree(lp->rx_skb); } /** diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c index 28dbbdc393eb..24858799c204 100644 --- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c +++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c @@ -1200,8 +1200,7 @@ static int xemaclite_of_remove(struct platform_device *of_dev) unregister_netdev(ndev); - if (lp->phy_node) - of_node_put(lp->phy_node); + of_node_put(lp->phy_node); lp->phy_node = NULL; xemaclite_remove_ndev(ndev); diff --git a/drivers/net/fddi/defxx.c b/drivers/net/fddi/defxx.c index caed6eee289c..7f975a2c8990 100644 --- a/drivers/net/fddi/defxx.c +++ b/drivers/net/fddi/defxx.c @@ -414,7 +414,7 @@ static void dfx_port_read_long(DFX_board_t *bp, int offset, u32 *data) * ================ * * Overview: - * Retrieves the address range used to access control and status + * Retrieves the address ranges used to access control and status * registers. * * Returns: @@ -422,8 +422,8 @@ static void dfx_port_read_long(DFX_board_t *bp, int offset, u32 *data) * * Arguments: * bdev - pointer to device information - * bar_start - pointer to store the start address - * bar_len - pointer to store the length of the area + * bar_start - pointer to store the start addresses + * bar_len - pointer to store the lengths of the areas * * Assumptions: * I am sure there are some. @@ -442,38 +442,47 @@ static void dfx_get_bars(struct device *bdev, if (dfx_bus_pci) { int num = dfx_use_mmio ? 0 : 1; - *bar_start = pci_resource_start(to_pci_dev(bdev), num); - *bar_len = pci_resource_len(to_pci_dev(bdev), num); + bar_start[0] = pci_resource_start(to_pci_dev(bdev), num); + bar_len[0] = pci_resource_len(to_pci_dev(bdev), num); + bar_start[2] = bar_start[1] = 0; + bar_len[2] = bar_len[1] = 0; } if (dfx_bus_eisa) { unsigned long base_addr = to_eisa_device(bdev)->base_addr; - resource_size_t bar; + resource_size_t bar_lo; + resource_size_t bar_hi; if (dfx_use_mmio) { - bar = inb(base_addr + PI_ESIC_K_MEM_ADD_CMP_2); - bar <<= 8; - bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_CMP_1); - bar <<= 8; - bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_CMP_0); - bar <<= 16; - *bar_start = bar; - bar = inb(base_addr + PI_ESIC_K_MEM_ADD_MASK_2); - bar <<= 8; - bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_MASK_1); - bar <<= 8; - bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_MASK_0); - bar <<= 16; - *bar_len = (bar | PI_MEM_ADD_MASK_M) + 1; + bar_lo = inb(base_addr + PI_ESIC_K_MEM_ADD_LO_CMP_2); + bar_lo <<= 8; + bar_lo |= inb(base_addr + PI_ESIC_K_MEM_ADD_LO_CMP_1); + bar_lo <<= 8; + bar_lo |= inb(base_addr + PI_ESIC_K_MEM_ADD_LO_CMP_0); + bar_lo <<= 8; + bar_start[0] = bar_lo; + bar_hi = inb(base_addr + PI_ESIC_K_MEM_ADD_HI_CMP_2); + bar_hi <<= 8; + bar_hi |= inb(base_addr + PI_ESIC_K_MEM_ADD_HI_CMP_1); + bar_hi <<= 8; + bar_hi |= inb(base_addr + PI_ESIC_K_MEM_ADD_HI_CMP_0); + bar_hi <<= 8; + bar_len[0] = ((bar_hi - bar_lo) | PI_MEM_ADD_MASK_M) + + 1; } else { - *bar_start = base_addr; - *bar_len = PI_ESIC_K_CSR_IO_LEN + - PI_ESIC_K_BURST_HOLDOFF_LEN; + bar_start[0] = base_addr; + bar_len[0] = PI_ESIC_K_CSR_IO_LEN; } + bar_start[1] = base_addr + PI_DEFEA_K_BURST_HOLDOFF; + bar_len[1] = PI_ESIC_K_BURST_HOLDOFF_LEN; + bar_start[2] = base_addr + PI_ESIC_K_ESIC_CSR; + bar_len[2] = PI_ESIC_K_ESIC_CSR_LEN; } if (dfx_bus_tc) { - *bar_start = to_tc_dev(bdev)->resource.start + - PI_TC_K_CSR_OFFSET; - *bar_len = PI_TC_K_CSR_LEN; + bar_start[0] = to_tc_dev(bdev)->resource.start + + PI_TC_K_CSR_OFFSET; + bar_len[0] = PI_TC_K_CSR_LEN; + bar_start[2] = bar_start[1] = 0; + bar_len[2] = bar_len[1] = 0; } } @@ -518,13 +527,14 @@ static int dfx_register(struct device *bdev) { static int version_disp; int dfx_bus_pci = dev_is_pci(bdev); + int dfx_bus_eisa = DFX_BUS_EISA(bdev); int dfx_bus_tc = DFX_BUS_TC(bdev); int dfx_use_mmio = DFX_MMIO || dfx_bus_tc; const char *print_name = dev_name(bdev); struct net_device *dev; DFX_board_t *bp; /* board pointer */ - resource_size_t bar_start = 0; /* pointer to port */ - resource_size_t bar_len = 0; /* resource length */ + resource_size_t bar_start[3]; /* pointers to ports */ + resource_size_t bar_len[3]; /* resource length */ int alloc_size; /* total buffer size used */ struct resource *region; int err = 0; @@ -542,10 +552,13 @@ static int dfx_register(struct device *bdev) } /* Enable PCI device. */ - if (dfx_bus_pci && pci_enable_device(to_pci_dev(bdev))) { - printk(KERN_ERR "%s: Cannot enable PCI device, aborting\n", - print_name); - goto err_out; + if (dfx_bus_pci) { + err = pci_enable_device(to_pci_dev(bdev)); + if (err) { + pr_err("%s: Cannot enable PCI device, aborting\n", + print_name); + goto err_out; + } } SET_NETDEV_DEV(dev, bdev); @@ -554,31 +567,62 @@ static int dfx_register(struct device *bdev) bp->bus_dev = bdev; dev_set_drvdata(bdev, dev); - dfx_get_bars(bdev, &bar_start, &bar_len); + dfx_get_bars(bdev, bar_start, bar_len); + if (dfx_bus_eisa && dfx_use_mmio && bar_start[0] == 0) { + pr_err("%s: Cannot use MMIO, no address set, aborting\n", + print_name); + pr_err("%s: Run ECU and set adapter's MMIO location\n", + print_name); + pr_err("%s: Or recompile driver with \"CONFIG_DEFXX_MMIO=n\"" + "\n", print_name); + err = -ENXIO; + goto err_out; + } if (dfx_use_mmio) - region = request_mem_region(bar_start, bar_len, print_name); + region = request_mem_region(bar_start[0], bar_len[0], + print_name); else - region = request_region(bar_start, bar_len, print_name); + region = request_region(bar_start[0], bar_len[0], print_name); if (!region) { - printk(KERN_ERR "%s: Cannot reserve I/O resource " - "0x%lx @ 0x%lx, aborting\n", - print_name, (long)bar_len, (long)bar_start); + pr_err("%s: Cannot reserve %s resource 0x%lx @ 0x%lx, " + "aborting\n", dfx_use_mmio ? "MMIO" : "I/O", print_name, + (long)bar_len[0], (long)bar_start[0]); err = -EBUSY; goto err_out_disable; } + if (bar_start[1] != 0) { + region = request_region(bar_start[1], bar_len[1], print_name); + if (!region) { + pr_err("%s: Cannot reserve I/O resource " + "0x%lx @ 0x%lx, aborting\n", print_name, + (long)bar_len[1], (long)bar_start[1]); + err = -EBUSY; + goto err_out_csr_region; + } + } + if (bar_start[2] != 0) { + region = request_region(bar_start[2], bar_len[2], print_name); + if (!region) { + pr_err("%s: Cannot reserve I/O resource " + "0x%lx @ 0x%lx, aborting\n", print_name, + (long)bar_len[2], (long)bar_start[2]); + err = -EBUSY; + goto err_out_bh_region; + } + } /* Set up I/O base address. */ if (dfx_use_mmio) { - bp->base.mem = ioremap_nocache(bar_start, bar_len); + bp->base.mem = ioremap_nocache(bar_start[0], bar_len[0]); if (!bp->base.mem) { printk(KERN_ERR "%s: Cannot map MMIO\n", print_name); err = -ENOMEM; - goto err_out_region; + goto err_out_esic_region; } } else { - bp->base.port = bar_start; - dev->base_addr = bar_start; + bp->base.port = bar_start[0]; + dev->base_addr = bar_start[0]; } /* Initialize new device structure */ @@ -587,7 +631,7 @@ static int dfx_register(struct device *bdev) if (dfx_bus_pci) pci_set_master(to_pci_dev(bdev)); - if (dfx_driver_init(dev, print_name, bar_start) != DFX_K_SUCCESS) { + if (dfx_driver_init(dev, print_name, bar_start[0]) != DFX_K_SUCCESS) { err = -ENODEV; goto err_out_unmap; } @@ -615,11 +659,19 @@ err_out_unmap: if (dfx_use_mmio) iounmap(bp->base.mem); -err_out_region: +err_out_esic_region: + if (bar_start[2] != 0) + release_region(bar_start[2], bar_len[2]); + +err_out_bh_region: + if (bar_start[1] != 0) + release_region(bar_start[1], bar_len[1]); + +err_out_csr_region: if (dfx_use_mmio) - release_mem_region(bar_start, bar_len); + release_mem_region(bar_start[0], bar_len[0]); else - release_region(bar_start, bar_len); + release_region(bar_start[0], bar_len[0]); err_out_disable: if (dfx_bus_pci) @@ -711,13 +763,14 @@ static void dfx_bus_init(struct net_device *dev) } /* - * Enable memory decoding (MEMCS0) and/or port decoding + * Enable memory decoding (MEMCS1) and/or port decoding * (IOCS1/IOCS0) as appropriate in Function Control - * Register. IOCS0 is used for PDQ registers, taking 16 - * 32-bit words, while IOCS1 is used for the Burst Holdoff - * register, taking a single 32-bit word only. We use the - * slot-specific I/O range as per the ESIC spec, that is - * set bits 15:12 in the mask registers to mask them out. + * Register. MEMCS1 or IOCS0 is used for PDQ registers, + * taking 16 32-bit words, while IOCS1 is used for the + * Burst Holdoff register, taking a single 32-bit word + * only. We use the slot-specific I/O range as per the + * ESIC spec, that is set bits 15:12 in the mask registers + * to mask them out. */ /* Set the decode range of the board. */ @@ -742,9 +795,11 @@ static void dfx_bus_init(struct net_device *dev) outb(val, base_addr + PI_ESIC_K_IO_ADD_MASK_1_0); /* Enable the decoders. */ - val = PI_FUNCTION_CNTRL_M_IOCS1 | PI_FUNCTION_CNTRL_M_IOCS0; + val = PI_FUNCTION_CNTRL_M_IOCS1; if (dfx_use_mmio) - val |= PI_FUNCTION_CNTRL_M_MEMCS0; + val |= PI_FUNCTION_CNTRL_M_MEMCS1; + else + val |= PI_FUNCTION_CNTRL_M_IOCS0; outb(val, base_addr + PI_ESIC_K_FUNCTION_CNTRL); /* @@ -838,6 +893,12 @@ static void dfx_bus_uninit(struct net_device *dev) val = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0); val &= ~PI_CONFIG_STAT_0_M_INT_ENB; outb(val, base_addr + PI_ESIC_K_IO_CONFIG_STAT_0); + + /* Disable the board. */ + outb(0, base_addr + PI_ESIC_K_SLOT_CNTRL); + + /* Disable memory and port decoders. */ + outb(0, base_addr + PI_ESIC_K_FUNCTION_CNTRL); } if (dfx_bus_pci) { /* Disable interrupts at PCI bus interface chip (PFI) */ @@ -1061,8 +1122,8 @@ static int dfx_driver_init(struct net_device *dev, const char *print_name, board_name = "DEFEA"; if (dfx_bus_pci) board_name = "DEFPA"; - pr_info("%s: %s at %saddr = 0x%llx, IRQ = %d, Hardware addr = %pMF\n", - print_name, board_name, dfx_use_mmio ? "" : "I/O ", + pr_info("%s: %s at %s addr = 0x%llx, IRQ = %d, Hardware addr = %pMF\n", + print_name, board_name, dfx_use_mmio ? "MMIO" : "I/O", (long long)bar_start, dev->irq, dev->dev_addr); /* @@ -3636,8 +3697,8 @@ static void dfx_unregister(struct device *bdev) int dfx_bus_pci = dev_is_pci(bdev); int dfx_bus_tc = DFX_BUS_TC(bdev); int dfx_use_mmio = DFX_MMIO || dfx_bus_tc; - resource_size_t bar_start = 0; /* pointer to port */ - resource_size_t bar_len = 0; /* resource length */ + resource_size_t bar_start[3]; /* pointers to ports */ + resource_size_t bar_len[3]; /* resource lengths */ int alloc_size; /* total buffer size used */ unregister_netdev(dev); @@ -3655,12 +3716,16 @@ static void dfx_unregister(struct device *bdev) dfx_bus_uninit(dev); - dfx_get_bars(bdev, &bar_start, &bar_len); + dfx_get_bars(bdev, bar_start, bar_len); + if (bar_start[2] != 0) + release_region(bar_start[2], bar_len[2]); + if (bar_start[1] != 0) + release_region(bar_start[1], bar_len[1]); if (dfx_use_mmio) { iounmap(bp->base.mem); - release_mem_region(bar_start, bar_len); + release_mem_region(bar_start[0], bar_len[0]); } else - release_region(bar_start, bar_len); + release_region(bar_start[0], bar_len[0]); if (dfx_bus_pci) pci_disable_device(to_pci_dev(bdev)); diff --git a/drivers/net/fddi/defxx.h b/drivers/net/fddi/defxx.h index 9527f0182fd4..9d30fde2ef3c 100644 --- a/drivers/net/fddi/defxx.h +++ b/drivers/net/fddi/defxx.h @@ -1481,9 +1481,11 @@ typedef union #define PI_ESIC_K_CSR_IO_LEN 0x40 /* 64 bytes */ #define PI_ESIC_K_BURST_HOLDOFF_LEN 0x04 /* 4 bytes */ +#define PI_ESIC_K_ESIC_CSR_LEN 0x40 /* 64 bytes */ #define PI_DEFEA_K_CSR_IO 0x000 #define PI_DEFEA_K_BURST_HOLDOFF 0x040 +#define PI_ESIC_K_ESIC_CSR 0xC80 #define PI_ESIC_K_SLOT_ID 0xC80 #define PI_ESIC_K_SLOT_CNTRL 0xC84 @@ -1556,7 +1558,7 @@ typedef union #define PI_BURST_HOLDOFF_V_RESERVED 1 #define PI_BURST_HOLDOFF_V_MEM_MAP 0 -/* Define the implicit mask of the Memory Address Mask Register. */ +/* Define the implicit mask of the Memory Address Compare registers. */ #define PI_MEM_ADD_MASK_M 0x3ff diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index c3c4051a089d..daca0dee88f3 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c @@ -675,8 +675,7 @@ out_free: kfree(xbuff); kfree(rbuff); - if (dev) - free_netdev(dev); + free_netdev(dev); out: return err; diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c index 7d76c9523395..6fc834e4306d 100644 --- a/drivers/net/hyperv/netvsc.c +++ b/drivers/net/hyperv/netvsc.c @@ -440,7 +440,8 @@ static int negotiate_nvsp_ver(struct hv_device *device, /* NVSPv2 only: Send NDIS config */ memset(init_packet, 0, sizeof(struct nvsp_message)); init_packet->hdr.msg_type = NVSP_MSG2_TYPE_SEND_NDIS_CONFIG; - init_packet->msg.v2_msg.send_ndis_config.mtu = net_device->ndev->mtu; + init_packet->msg.v2_msg.send_ndis_config.mtu = net_device->ndev->mtu + + ETH_HLEN; init_packet->msg.v2_msg.send_ndis_config.capability.ieee8021q = 1; ret = vmbus_sendpacket(device->channel, init_packet, @@ -560,9 +561,7 @@ int netvsc_device_remove(struct hv_device *device) vmbus_close(device->channel); /* Release all resources */ - if (net_device->sub_cb_buf) - vfree(net_device->sub_cb_buf); - + vfree(net_device->sub_cb_buf); free_netvsc_device(net_device); return 0; } diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 78ec33f5100b..15d82eda0baf 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -193,7 +193,9 @@ static bool netvsc_set_hash(u32 *hash, struct sk_buff *skb) struct flow_keys flow; int data_len; - if (!skb_flow_dissect(skb, &flow) || flow.n_proto != htons(ETH_P_IP)) + if (!skb_flow_dissect(skb, &flow) || + !(flow.n_proto == htons(ETH_P_IP) || + flow.n_proto == htons(ETH_P_IPV6))) return false; if (flow.ip_proto == IPPROTO_TCP) @@ -697,9 +699,10 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu) return -ENODEV; if (nvdev->nvsp_version >= NVSP_PROTOCOL_VERSION_2) - limit = NETVSC_MTU; + limit = NETVSC_MTU - ETH_HLEN; - if (mtu < 68 || mtu > limit) + /* Hyper-V hosts don't support MTU < ETH_DATA_LEN (1500) */ + if (mtu < ETH_DATA_LEN || mtu > limit) return -EINVAL; nvdev->start_remove = true; diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c index 2b86f0b6f6d1..7b2c5d1e9bad 100644 --- a/drivers/net/hyperv/rndis_filter.c +++ b/drivers/net/hyperv/rndis_filter.c @@ -728,7 +728,8 @@ int rndis_filter_set_rss_param(struct rndis_device *rdev, int num_queue) rssp->hdr.size = sizeof(struct ndis_recv_scale_param); rssp->flag = 0; rssp->hashinfo = NDIS_HASH_FUNC_TOEPLITZ | NDIS_HASH_IPV4 | - NDIS_HASH_TCP_IPV4; + NDIS_HASH_TCP_IPV4 | NDIS_HASH_IPV6 | + NDIS_HASH_TCP_IPV6; rssp->indirect_tabsize = 4*ITAB_NUM; rssp->indirect_taboffset = sizeof(struct ndis_recv_scale_param); rssp->hashkey_size = HASH_KEYLEN; @@ -997,6 +998,7 @@ int rndis_filter_device_add(struct hv_device *dev, int t; struct ndis_recv_scale_cap rsscap; u32 rsscap_size = sizeof(struct ndis_recv_scale_cap); + u32 mtu, size; rndis_device = get_rndis_device(); if (!rndis_device) @@ -1028,6 +1030,14 @@ int rndis_filter_device_add(struct hv_device *dev, return ret; } + /* Get the MTU from the host */ + size = sizeof(u32); + ret = rndis_filter_query_device(rndis_device, + RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE, + &mtu, &size); + if (ret == 0 && size == sizeof(u32)) + net_device->ndev->mtu = mtu; + /* Get the mac address */ ret = rndis_filter_query_device_mac(rndis_device); if (ret != 0) { diff --git a/drivers/net/ieee802154/Kconfig b/drivers/net/ieee802154/Kconfig index 391a916622a9..1a3c3e57aa0b 100644 --- a/drivers/net/ieee802154/Kconfig +++ b/drivers/net/ieee802154/Kconfig @@ -10,16 +10,6 @@ menuconfig IEEE802154_DRIVERS If you say N, all options in this submenu will be skipped and disabled. -config IEEE802154_FAKEHARD - tristate "Fake LR-WPAN driver with several interconnected devices" - depends on IEEE802154_DRIVERS - ---help--- - Say Y here to enable the fake driver that serves as an example - of HardMAC device driver. - - This driver can also be built as a module. To do so say M here. - The module will be called 'fakehard'. - config IEEE802154_FAKELB depends on IEEE802154_DRIVERS && MAC802154 tristate "IEEE 802.15.4 loopback driver" diff --git a/drivers/net/ieee802154/Makefile b/drivers/net/ieee802154/Makefile index 655cb95e6e24..d77fa4d77e27 100644 --- a/drivers/net/ieee802154/Makefile +++ b/drivers/net/ieee802154/Makefile @@ -1,4 +1,3 @@ -obj-$(CONFIG_IEEE802154_FAKEHARD) += fakehard.o obj-$(CONFIG_IEEE802154_FAKELB) += fakelb.o obj-$(CONFIG_IEEE802154_AT86RF230) += at86rf230.o obj-$(CONFIG_IEEE802154_MRF24J40) += mrf24j40.o diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c index c9d2a752abd7..1c0135620c62 100644 --- a/drivers/net/ieee802154/at86rf230.c +++ b/drivers/net/ieee802154/at86rf230.c @@ -12,10 +12,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * * Written by: * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> * Alexander Smirnov <alex.bluesman.smirnov@gmail.com> @@ -33,10 +29,10 @@ #include <linux/regmap.h> #include <linux/skbuff.h> #include <linux/of_gpio.h> +#include <linux/ieee802154.h> -#include <net/ieee802154.h> #include <net/mac802154.h> -#include <net/wpan-phy.h> +#include <net/cfg802154.h> struct at86rf230_local; /* at86rf2xx chip depend data. @@ -50,15 +46,11 @@ struct at86rf2xx_chip_data { u16 t_off_to_tx_on; u16 t_frame; u16 t_p_ack; - /* short interframe spacing time */ - u16 t_sifs; - /* long interframe spacing time */ - u16 t_lifs; /* completion timeout for tx in msecs */ u16 t_tx_timeout; int rssi_base_val; - int (*set_channel)(struct at86rf230_local *, int, int); + int (*set_channel)(struct at86rf230_local *, u8, u8); int (*get_desense_steps)(struct at86rf230_local *, s32); }; @@ -74,12 +66,14 @@ struct at86rf230_state_change { void (*complete)(void *context); u8 from_state; u8 to_state; + + bool irq_enable; }; struct at86rf230_local { struct spi_device *spi; - struct ieee802154_dev *dev; + struct ieee802154_hw *hw; struct at86rf2xx_chip_data *data; struct regmap *regmap; @@ -89,10 +83,10 @@ struct at86rf230_local { struct at86rf230_state_change irq; bool tx_aret; + s8 max_frame_retries; bool is_tx; /* spinlock for is_tx protection */ spinlock_t lock; - struct completion tx_complete; struct sk_buff *tx_skb; struct at86rf230_state_change tx; }; @@ -291,10 +285,11 @@ struct at86rf230_local { #define AT86RF2XX_NUMREGS 0x3F -static int +static void at86rf230_async_state_change(struct at86rf230_local *lp, struct at86rf230_state_change *ctx, - const u8 state, void (*complete)(void *context)); + const u8 state, void (*complete)(void *context), + const bool irq_enable); static inline int __at86rf230_write(struct at86rf230_local *lp, @@ -451,7 +446,8 @@ at86rf230_async_error_recover(void *context) struct at86rf230_state_change *ctx = context; struct at86rf230_local *lp = ctx->lp; - at86rf230_async_state_change(lp, ctx, STATE_RX_AACK_ON, NULL); + at86rf230_async_state_change(lp, ctx, STATE_RX_AACK_ON, NULL, false); + ieee802154_wake_queue(lp->hw); } static void @@ -461,21 +457,31 @@ at86rf230_async_error(struct at86rf230_local *lp, dev_err(&lp->spi->dev, "spi_async error %d\n", rc); at86rf230_async_state_change(lp, ctx, STATE_FORCE_TRX_OFF, - at86rf230_async_error_recover); + at86rf230_async_error_recover, false); } /* Generic function to get some register value in async mode */ -static int +static void at86rf230_async_read_reg(struct at86rf230_local *lp, const u8 reg, struct at86rf230_state_change *ctx, - void (*complete)(void *context)) + void (*complete)(void *context), + const bool irq_enable) { + int rc; + u8 *tx_buf = ctx->buf; tx_buf[0] = (reg & CMD_REG_MASK) | CMD_REG; ctx->trx.len = 2; ctx->msg.complete = complete; - return spi_async(lp->spi, &ctx->msg); + ctx->irq_enable = irq_enable; + rc = spi_async(lp->spi, &ctx->msg); + if (rc) { + if (irq_enable) + enable_irq(lp->spi->irq); + + at86rf230_async_error(lp, ctx, rc); + } } static void @@ -512,7 +518,8 @@ at86rf230_async_state_assert(void *context) if (ctx->to_state == STATE_TX_ON) { at86rf230_async_state_change(lp, ctx, STATE_FORCE_TX_ON, - ctx->complete); + ctx->complete, + ctx->irq_enable); return; } } @@ -535,7 +542,6 @@ at86rf230_async_state_delay(void *context) struct at86rf230_local *lp = ctx->lp; struct at86rf2xx_chip_data *c = lp->data; bool force = false; - int rc; /* The force state changes are will show as normal states in the * state status subregister. We change the to_state to the @@ -604,10 +610,9 @@ at86rf230_async_state_delay(void *context) udelay(1); change: - rc = at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx, - at86rf230_async_state_assert); - if (rc) - dev_err(&lp->spi->dev, "spi_async error %d\n", rc); + at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx, + at86rf230_async_state_assert, + ctx->irq_enable); } static void @@ -622,10 +627,9 @@ at86rf230_async_state_change_start(void *context) /* Check for "possible" STATE_TRANSITION_IN_PROGRESS */ if (trx_state == STATE_TRANSITION_IN_PROGRESS) { udelay(1); - rc = at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx, - at86rf230_async_state_change_start); - if (rc) - dev_err(&lp->spi->dev, "spi_async error %d\n", rc); + at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx, + at86rf230_async_state_change_start, + ctx->irq_enable); return; } @@ -647,20 +651,27 @@ at86rf230_async_state_change_start(void *context) ctx->trx.len = 2; ctx->msg.complete = at86rf230_async_state_delay; rc = spi_async(lp->spi, &ctx->msg); - if (rc) - dev_err(&lp->spi->dev, "spi_async error %d\n", rc); + if (rc) { + if (ctx->irq_enable) + enable_irq(lp->spi->irq); + + at86rf230_async_error(lp, &lp->state, rc); + } } -static int +static void at86rf230_async_state_change(struct at86rf230_local *lp, struct at86rf230_state_change *ctx, - const u8 state, void (*complete)(void *context)) + const u8 state, void (*complete)(void *context), + const bool irq_enable) { /* Initialization for the state change context */ ctx->to_state = state; ctx->complete = complete; - return at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx, - at86rf230_async_state_change_start); + ctx->irq_enable = irq_enable; + at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx, + at86rf230_async_state_change_start, + irq_enable); } static void @@ -681,17 +692,16 @@ at86rf230_sync_state_change(struct at86rf230_local *lp, unsigned int state) { int rc; - rc = at86rf230_async_state_change(lp, &lp->state, state, - at86rf230_sync_state_change_complete); - if (rc) { - at86rf230_async_error(lp, &lp->state, rc); - return rc; - } + at86rf230_async_state_change(lp, &lp->state, state, + at86rf230_sync_state_change_complete, + false); rc = wait_for_completion_timeout(&lp->state_complete, msecs_to_jiffies(100)); - if (!rc) + if (!rc) { + at86rf230_async_error(lp, &lp->state, -ETIMEDOUT); return -ETIMEDOUT; + } return 0; } @@ -701,8 +711,14 @@ at86rf230_tx_complete(void *context) { struct at86rf230_state_change *ctx = context; struct at86rf230_local *lp = ctx->lp; + struct sk_buff *skb = lp->tx_skb; + + enable_irq(lp->spi->irq); - complete(&lp->tx_complete); + if (lp->max_frame_retries <= 0) + ieee802154_xmit_complete(lp->hw, skb, true); + else + ieee802154_xmit_complete(lp->hw, skb, false); } static void @@ -710,12 +726,9 @@ at86rf230_tx_on(void *context) { struct at86rf230_state_change *ctx = context; struct at86rf230_local *lp = ctx->lp; - int rc; - rc = at86rf230_async_state_change(lp, &lp->irq, STATE_RX_AACK_ON, - at86rf230_tx_complete); - if (rc) - at86rf230_async_error(lp, ctx, rc); + at86rf230_async_state_change(lp, &lp->irq, STATE_RX_AACK_ON, + at86rf230_tx_complete, true); } static void @@ -723,12 +736,9 @@ at86rf230_tx_trac_error(void *context) { struct at86rf230_state_change *ctx = context; struct at86rf230_local *lp = ctx->lp; - int rc; - rc = at86rf230_async_state_change(lp, ctx, STATE_TX_ON, - at86rf230_tx_on); - if (rc) - at86rf230_async_error(lp, ctx, rc); + at86rf230_async_state_change(lp, ctx, STATE_TX_ON, + at86rf230_tx_on, true); } static void @@ -738,17 +748,14 @@ at86rf230_tx_trac_check(void *context) struct at86rf230_local *lp = ctx->lp; const u8 *buf = ctx->buf; const u8 trac = (buf[1] & 0xe0) >> 5; - int rc; /* If trac status is different than zero we need to do a state change * to STATE_FORCE_TRX_OFF then STATE_TX_ON to recover the transceiver * state to TX_ON. */ if (trac) { - rc = at86rf230_async_state_change(lp, ctx, STATE_FORCE_TRX_OFF, - at86rf230_tx_trac_error); - if (rc) - at86rf230_async_error(lp, ctx, rc); + at86rf230_async_state_change(lp, ctx, STATE_FORCE_TRX_OFF, + at86rf230_tx_trac_error, true); return; } @@ -761,51 +768,29 @@ at86rf230_tx_trac_status(void *context) { struct at86rf230_state_change *ctx = context; struct at86rf230_local *lp = ctx->lp; - int rc; - rc = at86rf230_async_read_reg(lp, RG_TRX_STATE, ctx, - at86rf230_tx_trac_check); - if (rc) - at86rf230_async_error(lp, ctx, rc); + at86rf230_async_read_reg(lp, RG_TRX_STATE, ctx, + at86rf230_tx_trac_check, true); } static void at86rf230_rx(struct at86rf230_local *lp, - const u8 *data, u8 len) + const u8 *data, const u8 len, const u8 lqi) { - u8 lqi; struct sk_buff *skb; u8 rx_local_buf[AT86RF2XX_MAX_BUF]; - if (len < 2) - return; - - /* read full frame buffer and invalid lqi value to lowest - * indicator if frame was is in a corrupted state. - */ - if (len > IEEE802154_MTU) { - lqi = 0; - len = IEEE802154_MTU; - dev_vdbg(&lp->spi->dev, "corrupted frame received\n"); - } else { - lqi = data[len]; - } - memcpy(rx_local_buf, data, len); enable_irq(lp->spi->irq); - skb = alloc_skb(IEEE802154_MTU, GFP_ATOMIC); + skb = dev_alloc_skb(IEEE802154_MTU); if (!skb) { dev_vdbg(&lp->spi->dev, "failed to allocate sk_buff\n"); return; } memcpy(skb_put(skb, len), rx_local_buf, len); - - /* We do not put CRC into the frame */ - skb_trim(skb, len - 2); - - ieee802154_rx_irqsafe(lp->dev, skb, lqi); + ieee802154_rx_irqsafe(lp->hw, skb, lqi); } static void @@ -814,20 +799,31 @@ at86rf230_rx_read_frame_complete(void *context) struct at86rf230_state_change *ctx = context; struct at86rf230_local *lp = ctx->lp; const u8 *buf = lp->irq.buf; - const u8 len = buf[1]; + u8 len = buf[1]; + + if (!ieee802154_is_valid_psdu_len(len)) { + dev_vdbg(&lp->spi->dev, "corrupted frame received\n"); + len = IEEE802154_MTU; + } - at86rf230_rx(lp, buf + 2, len); + at86rf230_rx(lp, buf + 2, len, buf[2 + len]); } -static int +static void at86rf230_rx_read_frame(struct at86rf230_local *lp) { + int rc; + u8 *buf = lp->irq.buf; buf[0] = CMD_FB; lp->irq.trx.len = AT86RF2XX_MAX_BUF; lp->irq.msg.complete = at86rf230_rx_read_frame_complete; - return spi_async(lp->spi, &lp->irq.msg); + rc = spi_async(lp->spi, &lp->irq.msg); + if (rc) { + enable_irq(lp->spi->irq); + at86rf230_async_error(lp, &lp->irq, rc); + } } static void @@ -835,7 +831,6 @@ at86rf230_rx_trac_check(void *context) { struct at86rf230_state_change *ctx = context; struct at86rf230_local *lp = ctx->lp; - int rc; /* Possible check on trac status here. This could be useful to make * some stats why receive is failed. Not used at the moment, but it's @@ -843,34 +838,31 @@ at86rf230_rx_trac_check(void *context) * The programming guide say do it so. */ - rc = at86rf230_rx_read_frame(lp); - if (rc) { - enable_irq(lp->spi->irq); - at86rf230_async_error(lp, ctx, rc); - } + at86rf230_rx_read_frame(lp); } -static int +static void at86rf230_irq_trx_end(struct at86rf230_local *lp) { spin_lock(&lp->lock); if (lp->is_tx) { lp->is_tx = 0; spin_unlock(&lp->lock); - enable_irq(lp->spi->irq); if (lp->tx_aret) - return at86rf230_async_state_change(lp, &lp->irq, - STATE_FORCE_TX_ON, - at86rf230_tx_trac_status); + at86rf230_async_state_change(lp, &lp->irq, + STATE_FORCE_TX_ON, + at86rf230_tx_trac_status, + true); else - return at86rf230_async_state_change(lp, &lp->irq, - STATE_RX_AACK_ON, - at86rf230_tx_complete); + at86rf230_async_state_change(lp, &lp->irq, + STATE_RX_AACK_ON, + at86rf230_tx_complete, + true); } else { spin_unlock(&lp->lock); - return at86rf230_async_read_reg(lp, RG_TRX_STATE, &lp->irq, - at86rf230_rx_trac_check); + at86rf230_async_read_reg(lp, RG_TRX_STATE, &lp->irq, + at86rf230_rx_trac_check, true); } } @@ -881,12 +873,9 @@ at86rf230_irq_status(void *context) struct at86rf230_local *lp = ctx->lp; const u8 *buf = lp->irq.buf; const u8 irq = buf[1]; - int rc; if (irq & IRQ_TRX_END) { - rc = at86rf230_irq_trx_end(lp); - if (rc) - at86rf230_async_error(lp, ctx, rc); + at86rf230_irq_trx_end(lp); } else { enable_irq(lp->spi->irq); dev_err(&lp->spi->dev, "not supported irq %02x received\n", @@ -901,13 +890,14 @@ static irqreturn_t at86rf230_isr(int irq, void *data) u8 *buf = ctx->buf; int rc; - disable_irq_nosync(lp->spi->irq); + disable_irq_nosync(irq); buf[0] = (RG_IRQ_STATUS & CMD_REG_MASK) | CMD_REG; ctx->trx.len = 2; ctx->msg.complete = at86rf230_irq_status; rc = spi_async(lp->spi, &ctx->msg); if (rc) { + enable_irq(irq); at86rf230_async_error(lp, ctx, rc); return IRQ_NONE; } @@ -960,22 +950,18 @@ at86rf230_xmit_tx_on(void *context) { struct at86rf230_state_change *ctx = context; struct at86rf230_local *lp = ctx->lp; - int rc; - rc = at86rf230_async_state_change(lp, ctx, STATE_TX_ARET_ON, - at86rf230_write_frame); - if (rc) - at86rf230_async_error(lp, ctx, rc); + at86rf230_async_state_change(lp, ctx, STATE_TX_ARET_ON, + at86rf230_write_frame, false); } static int -at86rf230_xmit(struct ieee802154_dev *dev, struct sk_buff *skb) +at86rf230_xmit(struct ieee802154_hw *hw, struct sk_buff *skb) { - struct at86rf230_local *lp = dev->priv; + struct at86rf230_local *lp = hw->priv; struct at86rf230_state_change *ctx = &lp->tx; void (*tx_complete)(void *context) = at86rf230_write_frame; - int rc; lp->tx_skb = skb; @@ -986,61 +972,39 @@ at86rf230_xmit(struct ieee802154_dev *dev, struct sk_buff *skb) if (lp->tx_aret) tx_complete = at86rf230_xmit_tx_on; - rc = at86rf230_async_state_change(lp, ctx, STATE_TX_ON, - tx_complete); - if (rc) { - at86rf230_async_error(lp, ctx, rc); - return rc; - } - rc = wait_for_completion_interruptible_timeout(&lp->tx_complete, - msecs_to_jiffies(lp->data->t_tx_timeout)); - if (!rc) { - at86rf230_async_error(lp, ctx, rc); - return -ETIMEDOUT; - } - - /* Interfame spacing time, which is phy depend. - * TODO - * Move this handling in MAC 802.15.4 layer. - * This is currently a workaround to avoid fragmenation issues. - */ - if (skb->len > 18) - usleep_range(lp->data->t_lifs, lp->data->t_lifs + 10); - else - usleep_range(lp->data->t_sifs, lp->data->t_sifs + 10); + at86rf230_async_state_change(lp, ctx, STATE_TX_ON, tx_complete, false); return 0; } static int -at86rf230_ed(struct ieee802154_dev *dev, u8 *level) +at86rf230_ed(struct ieee802154_hw *hw, u8 *level) { - might_sleep(); BUG_ON(!level); *level = 0xbe; return 0; } static int -at86rf230_start(struct ieee802154_dev *dev) +at86rf230_start(struct ieee802154_hw *hw) { - return at86rf230_sync_state_change(dev->priv, STATE_RX_AACK_ON); + return at86rf230_sync_state_change(hw->priv, STATE_RX_AACK_ON); } static void -at86rf230_stop(struct ieee802154_dev *dev) +at86rf230_stop(struct ieee802154_hw *hw) { - at86rf230_sync_state_change(dev->priv, STATE_FORCE_TRX_OFF); + at86rf230_sync_state_change(hw->priv, STATE_FORCE_TRX_OFF); } static int -at86rf23x_set_channel(struct at86rf230_local *lp, int page, int channel) +at86rf23x_set_channel(struct at86rf230_local *lp, u8 page, u8 channel) { return at86rf230_write_subreg(lp, SR_CHANNEL, channel); } static int -at86rf212_set_channel(struct at86rf230_local *lp, int page, int channel) +at86rf212_set_channel(struct at86rf230_local *lp, u8 page, u8 channel) { int rc; @@ -1061,44 +1025,60 @@ at86rf212_set_channel(struct at86rf230_local *lp, int page, int channel) if (rc < 0) return rc; + /* This sets the symbol_duration according frequency on the 212. + * TODO move this handling while set channel and page in cfg802154. + * We can do that, this timings are according 802.15.4 standard. + * If we do that in cfg802154, this is a more generic calculation. + * + * This should also protected from ifs_timer. Means cancel timer and + * init with a new value. For now, this is okay. + */ + if (channel == 0) { + if (page == 0) { + /* SUB:0 and BPSK:0 -> BPSK-20 */ + lp->hw->phy->symbol_duration = 50; + } else { + /* SUB:1 and BPSK:0 -> BPSK-40 */ + lp->hw->phy->symbol_duration = 25; + } + } else { + if (page == 0) + /* SUB:0 and BPSK:1 -> OQPSK-100/200/400 */ + lp->hw->phy->symbol_duration = 40; + else + /* SUB:1 and BPSK:1 -> OQPSK-250/500/1000 */ + lp->hw->phy->symbol_duration = 16; + } + + lp->hw->phy->lifs_period = IEEE802154_LIFS_PERIOD * + lp->hw->phy->symbol_duration; + lp->hw->phy->sifs_period = IEEE802154_SIFS_PERIOD * + lp->hw->phy->symbol_duration; + return at86rf230_write_subreg(lp, SR_CHANNEL, channel); } static int -at86rf230_channel(struct ieee802154_dev *dev, int page, int channel) +at86rf230_channel(struct ieee802154_hw *hw, u8 page, u8 channel) { - struct at86rf230_local *lp = dev->priv; + struct at86rf230_local *lp = hw->priv; int rc; - might_sleep(); - - if (page < 0 || page > 31 || - !(lp->dev->phy->channels_supported[page] & BIT(channel))) { - WARN_ON(1); - return -EINVAL; - } - rc = lp->data->set_channel(lp, page, channel); - if (rc < 0) - return rc; - /* Wait for PLL */ usleep_range(lp->data->t_channel_switch, lp->data->t_channel_switch + 10); - dev->phy->current_channel = channel; - dev->phy->current_page = page; - - return 0; + return rc; } static int -at86rf230_set_hw_addr_filt(struct ieee802154_dev *dev, +at86rf230_set_hw_addr_filt(struct ieee802154_hw *hw, struct ieee802154_hw_addr_filt *filt, unsigned long changed) { - struct at86rf230_local *lp = dev->priv; + struct at86rf230_local *lp = hw->priv; - if (changed & IEEE802515_AFILT_SADDR_CHANGED) { + if (changed & IEEE802154_AFILT_SADDR_CHANGED) { u16 addr = le16_to_cpu(filt->short_addr); dev_vdbg(&lp->spi->dev, @@ -1107,7 +1087,7 @@ at86rf230_set_hw_addr_filt(struct ieee802154_dev *dev, __at86rf230_write(lp, RG_SHORT_ADDR_1, addr >> 8); } - if (changed & IEEE802515_AFILT_PANID_CHANGED) { + if (changed & IEEE802154_AFILT_PANID_CHANGED) { u16 pan = le16_to_cpu(filt->pan_id); dev_vdbg(&lp->spi->dev, @@ -1116,7 +1096,7 @@ at86rf230_set_hw_addr_filt(struct ieee802154_dev *dev, __at86rf230_write(lp, RG_PAN_ID_1, pan >> 8); } - if (changed & IEEE802515_AFILT_IEEEADDR_CHANGED) { + if (changed & IEEE802154_AFILT_IEEEADDR_CHANGED) { u8 i, addr[8]; memcpy(addr, &filt->ieee_addr, 8); @@ -1126,7 +1106,7 @@ at86rf230_set_hw_addr_filt(struct ieee802154_dev *dev, __at86rf230_write(lp, RG_IEEE_ADDR_0 + i, addr[i]); } - if (changed & IEEE802515_AFILT_PANC_CHANGED) { + if (changed & IEEE802154_AFILT_PANC_CHANGED) { dev_vdbg(&lp->spi->dev, "at86rf230_set_hw_addr_filt called for panc change\n"); if (filt->pan_coord) @@ -1139,9 +1119,9 @@ at86rf230_set_hw_addr_filt(struct ieee802154_dev *dev, } static int -at86rf230_set_txpower(struct ieee802154_dev *dev, int db) +at86rf230_set_txpower(struct ieee802154_hw *hw, int db) { - struct at86rf230_local *lp = dev->priv; + struct at86rf230_local *lp = hw->priv; /* typical maximum output is 5dBm with RG_PHY_TX_PWR 0x60, lower five * bits decrease power in 1dB steps. 0x60 represents extra PA gain of @@ -1158,17 +1138,17 @@ at86rf230_set_txpower(struct ieee802154_dev *dev, int db) } static int -at86rf230_set_lbt(struct ieee802154_dev *dev, bool on) +at86rf230_set_lbt(struct ieee802154_hw *hw, bool on) { - struct at86rf230_local *lp = dev->priv; + struct at86rf230_local *lp = hw->priv; return at86rf230_write_subreg(lp, SR_CSMA_LBT_MODE, on); } static int -at86rf230_set_cca_mode(struct ieee802154_dev *dev, u8 mode) +at86rf230_set_cca_mode(struct ieee802154_hw *hw, u8 mode) { - struct at86rf230_local *lp = dev->priv; + struct at86rf230_local *lp = hw->priv; return at86rf230_write_subreg(lp, SR_CCA_MODE, mode); } @@ -1186,9 +1166,9 @@ at86rf23x_get_desens_steps(struct at86rf230_local *lp, s32 level) } static int -at86rf230_set_cca_ed_level(struct ieee802154_dev *dev, s32 level) +at86rf230_set_cca_ed_level(struct ieee802154_hw *hw, s32 level) { - struct at86rf230_local *lp = dev->priv; + struct at86rf230_local *lp = hw->priv; if (level < lp->data->rssi_base_val || level > 30) return -EINVAL; @@ -1198,15 +1178,12 @@ at86rf230_set_cca_ed_level(struct ieee802154_dev *dev, s32 level) } static int -at86rf230_set_csma_params(struct ieee802154_dev *dev, u8 min_be, u8 max_be, +at86rf230_set_csma_params(struct ieee802154_hw *hw, u8 min_be, u8 max_be, u8 retries) { - struct at86rf230_local *lp = dev->priv; + struct at86rf230_local *lp = hw->priv; int rc; - if (min_be > max_be || max_be > 8 || retries > 5) - return -EINVAL; - rc = at86rf230_write_subreg(lp, SR_MIN_BE, min_be); if (rc) return rc; @@ -1219,15 +1196,13 @@ at86rf230_set_csma_params(struct ieee802154_dev *dev, u8 min_be, u8 max_be, } static int -at86rf230_set_frame_retries(struct ieee802154_dev *dev, s8 retries) +at86rf230_set_frame_retries(struct ieee802154_hw *hw, s8 retries) { - struct at86rf230_local *lp = dev->priv; + struct at86rf230_local *lp = hw->priv; int rc = 0; - if (retries < -1 || retries > 15) - return -EINVAL; - lp->tx_aret = retries >= 0; + lp->max_frame_retries = retries; if (retries >= 0) rc = at86rf230_write_subreg(lp, SR_MAX_FRAME_RETRIES, retries); @@ -1235,9 +1210,36 @@ at86rf230_set_frame_retries(struct ieee802154_dev *dev, s8 retries) return rc; } -static struct ieee802154_ops at86rf230_ops = { +static int +at86rf230_set_promiscuous_mode(struct ieee802154_hw *hw, const bool on) +{ + struct at86rf230_local *lp = hw->priv; + int rc; + + if (on) { + rc = at86rf230_write_subreg(lp, SR_AACK_DIS_ACK, 1); + if (rc < 0) + return rc; + + rc = at86rf230_write_subreg(lp, SR_AACK_PROM_MODE, 1); + if (rc < 0) + return rc; + } else { + rc = at86rf230_write_subreg(lp, SR_AACK_PROM_MODE, 0); + if (rc < 0) + return rc; + + rc = at86rf230_write_subreg(lp, SR_AACK_DIS_ACK, 0); + if (rc < 0) + return rc; + } + + return 0; +} + +static const struct ieee802154_ops at86rf230_ops = { .owner = THIS_MODULE, - .xmit = at86rf230_xmit, + .xmit_async = at86rf230_xmit, .ed = at86rf230_ed, .set_channel = at86rf230_channel, .start = at86rf230_start, @@ -1249,6 +1251,7 @@ static struct ieee802154_ops at86rf230_ops = { .set_cca_ed_level = at86rf230_set_cca_ed_level, .set_csma_params = at86rf230_set_csma_params, .set_frame_retries = at86rf230_set_frame_retries, + .set_promiscuous_mode = at86rf230_set_promiscuous_mode, }; static struct at86rf2xx_chip_data at86rf233_data = { @@ -1259,8 +1262,6 @@ static struct at86rf2xx_chip_data at86rf233_data = { .t_off_to_tx_on = 80, .t_frame = 4096, .t_p_ack = 545, - .t_sifs = 192, - .t_lifs = 480, .t_tx_timeout = 2000, .rssi_base_val = -91, .set_channel = at86rf23x_set_channel, @@ -1275,8 +1276,6 @@ static struct at86rf2xx_chip_data at86rf231_data = { .t_off_to_tx_on = 110, .t_frame = 4096, .t_p_ack = 545, - .t_sifs = 192, - .t_lifs = 480, .t_tx_timeout = 2000, .rssi_base_val = -91, .set_channel = at86rf23x_set_channel, @@ -1291,8 +1290,6 @@ static struct at86rf2xx_chip_data at86rf212_data = { .t_off_to_tx_on = 200, .t_frame = 4096, .t_p_ack = 545, - .t_sifs = 192, - .t_lifs = 480, .t_tx_timeout = 2000, .rssi_base_val = -100, .set_channel = at86rf212_set_channel, @@ -1354,7 +1351,11 @@ static int at86rf230_hw_init(struct at86rf230_local *lp) return -EINVAL; } - return 0; + /* Force setting slotted operation bit to 0. Sometimes the atben + * sets this bit and I don't know why. We set this always force + * to zero while probing. + */ + return at86rf230_write_subreg(lp, SR_SLOTTED_OPERATION, 0); } static struct at86rf230_platform_data * @@ -1409,9 +1410,10 @@ at86rf230_detect_device(struct at86rf230_local *lp) return -EINVAL; } - lp->dev->extra_tx_headroom = 0; - lp->dev->flags = IEEE802154_HW_OMIT_CKSUM | IEEE802154_HW_AACK | - IEEE802154_HW_TXPOWER | IEEE802154_HW_CSMA; + lp->hw->extra_tx_headroom = 0; + lp->hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | IEEE802154_HW_AACK | + IEEE802154_HW_TXPOWER | IEEE802154_HW_ARET | + IEEE802154_HW_AFILT | IEEE802154_HW_PROMISCUOUS; switch (part) { case 2: @@ -1421,15 +1423,19 @@ at86rf230_detect_device(struct at86rf230_local *lp) case 3: chip = "at86rf231"; lp->data = &at86rf231_data; - lp->dev->phy->channels_supported[0] = 0x7FFF800; + lp->hw->phy->channels_supported[0] = 0x7FFF800; + lp->hw->phy->current_channel = 11; + lp->hw->phy->symbol_duration = 16; break; case 7: chip = "at86rf212"; if (version == 1) { lp->data = &at86rf212_data; - lp->dev->flags |= IEEE802154_HW_LBT; - lp->dev->phy->channels_supported[0] = 0x00007FF; - lp->dev->phy->channels_supported[2] = 0x00007FF; + lp->hw->flags |= IEEE802154_HW_LBT; + lp->hw->phy->channels_supported[0] = 0x00007FF; + lp->hw->phy->channels_supported[2] = 0x00007FF; + lp->hw->phy->current_channel = 5; + lp->hw->phy->symbol_duration = 25; } else { rc = -ENOTSUPP; } @@ -1437,7 +1443,9 @@ at86rf230_detect_device(struct at86rf230_local *lp) case 11: chip = "at86rf233"; lp->data = &at86rf233_data; - lp->dev->phy->channels_supported[0] = 0x7FFF800; + lp->hw->phy->channels_supported[0] = 0x7FFF800; + lp->hw->phy->current_channel = 13; + lp->hw->phy->symbol_duration = 16; break; default: chip = "unkown"; @@ -1478,7 +1486,7 @@ at86rf230_setup_spi_messages(struct at86rf230_local *lp) static int at86rf230_probe(struct spi_device *spi) { struct at86rf230_platform_data *pdata; - struct ieee802154_dev *dev; + struct ieee802154_hw *hw; struct at86rf230_local *lp; unsigned int status; int rc, irq_type; @@ -1517,14 +1525,16 @@ static int at86rf230_probe(struct spi_device *spi) usleep_range(120, 240); } - dev = ieee802154_alloc_device(sizeof(*lp), &at86rf230_ops); - if (!dev) + hw = ieee802154_alloc_hw(sizeof(*lp), &at86rf230_ops); + if (!hw) return -ENOMEM; - lp = dev->priv; - lp->dev = dev; + lp = hw->priv; + lp->hw = hw; lp->spi = spi; - dev->parent = &spi->dev; + hw->parent = &spi->dev; + hw->vif_data_size = sizeof(*lp); + ieee802154_random_extended_addr(&hw->phy->perm_extended_addr); lp->regmap = devm_regmap_init_spi(spi, &at86rf230_regmap_spi_config); if (IS_ERR(lp->regmap)) { @@ -1541,7 +1551,6 @@ static int at86rf230_probe(struct spi_device *spi) goto free_dev; spin_lock_init(&lp->lock); - init_completion(&lp->tx_complete); init_completion(&lp->state_complete); spi_set_drvdata(spi, lp); @@ -1564,14 +1573,14 @@ static int at86rf230_probe(struct spi_device *spi) if (rc) goto free_dev; - rc = ieee802154_register_device(lp->dev); + rc = ieee802154_register_hw(lp->hw); if (rc) goto free_dev; return rc; free_dev: - ieee802154_free_device(lp->dev); + ieee802154_free_hw(lp->hw); return rc; } @@ -1582,8 +1591,8 @@ static int at86rf230_remove(struct spi_device *spi) /* mask all at86rf230 irq's */ at86rf230_write_subreg(lp, SR_IRQ_MASK, 0); - ieee802154_unregister_device(lp->dev); - ieee802154_free_device(lp->dev); + ieee802154_unregister_hw(lp->hw); + ieee802154_free_hw(lp->hw); dev_dbg(&spi->dev, "unregistered at86rf230\n"); return 0; diff --git a/drivers/net/ieee802154/cc2520.c b/drivers/net/ieee802154/cc2520.c index 8a5ac7ab2300..ccbb082f3391 100644 --- a/drivers/net/ieee802154/cc2520.c +++ b/drivers/net/ieee802154/cc2520.c @@ -21,10 +21,10 @@ #include <linux/skbuff.h> #include <linux/pinctrl/consumer.h> #include <linux/of_gpio.h> +#include <linux/ieee802154.h> #include <net/mac802154.h> -#include <net/wpan-phy.h> -#include <net/ieee802154.h> +#include <net/cfg802154.h> #define SPI_COMMAND_BUFFER 3 #define HIGH 1 @@ -193,7 +193,7 @@ /* Driver private information */ struct cc2520_private { struct spi_device *spi; /* SPI device structure */ - struct ieee802154_dev *dev; /* IEEE-802.15.4 device */ + struct ieee802154_hw *hw; /* IEEE-802.15.4 device */ u8 *buf; /* SPI TX/Rx data buffer */ struct mutex buffer_mutex; /* SPI buffer mutex */ bool is_tx; /* Flag for sync b/w Tx and Rx */ @@ -453,20 +453,20 @@ cc2520_read_rxfifo(struct cc2520_private *priv, u8 *data, u8 len, u8 *lqi) return status; } -static int cc2520_start(struct ieee802154_dev *dev) +static int cc2520_start(struct ieee802154_hw *hw) { - return cc2520_cmd_strobe(dev->priv, CC2520_CMD_SRXON); + return cc2520_cmd_strobe(hw->priv, CC2520_CMD_SRXON); } -static void cc2520_stop(struct ieee802154_dev *dev) +static void cc2520_stop(struct ieee802154_hw *hw) { - cc2520_cmd_strobe(dev->priv, CC2520_CMD_SRFOFF); + cc2520_cmd_strobe(hw->priv, CC2520_CMD_SRFOFF); } static int -cc2520_tx(struct ieee802154_dev *dev, struct sk_buff *skb) +cc2520_tx(struct ieee802154_hw *hw, struct sk_buff *skb) { - struct cc2520_private *priv = dev->priv; + struct cc2520_private *priv = hw->priv; unsigned long flags; int rc; u8 status = 0; @@ -524,7 +524,7 @@ static int cc2520_rx(struct cc2520_private *priv) if (len < 2 || len > IEEE802154_MTU) return -EINVAL; - skb = alloc_skb(len, GFP_KERNEL); + skb = dev_alloc_skb(len); if (!skb) return -ENOMEM; @@ -536,7 +536,7 @@ static int cc2520_rx(struct cc2520_private *priv) skb_trim(skb, skb->len - 2); - ieee802154_rx_irqsafe(priv->dev, skb, lqi); + ieee802154_rx_irqsafe(priv->hw, skb, lqi); dev_vdbg(&priv->spi->dev, "RXFIFO: %x %x\n", len, lqi); @@ -544,9 +544,9 @@ static int cc2520_rx(struct cc2520_private *priv) } static int -cc2520_ed(struct ieee802154_dev *dev, u8 *level) +cc2520_ed(struct ieee802154_hw *hw, u8 *level) { - struct cc2520_private *priv = dev->priv; + struct cc2520_private *priv = hw->priv; u8 status = 0xff; u8 rssi; int ret; @@ -569,12 +569,11 @@ cc2520_ed(struct ieee802154_dev *dev, u8 *level) } static int -cc2520_set_channel(struct ieee802154_dev *dev, int page, int channel) +cc2520_set_channel(struct ieee802154_hw *hw, u8 page, u8 channel) { - struct cc2520_private *priv = dev->priv; + struct cc2520_private *priv = hw->priv; int ret; - might_sleep(); dev_dbg(&priv->spi->dev, "trying to set channel\n"); BUG_ON(page != 0); @@ -588,12 +587,12 @@ cc2520_set_channel(struct ieee802154_dev *dev, int page, int channel) } static int -cc2520_filter(struct ieee802154_dev *dev, +cc2520_filter(struct ieee802154_hw *hw, struct ieee802154_hw_addr_filt *filt, unsigned long changed) { - struct cc2520_private *priv = dev->priv; + struct cc2520_private *priv = hw->priv; - if (changed & IEEE802515_AFILT_PANID_CHANGED) { + if (changed & IEEE802154_AFILT_PANID_CHANGED) { u16 panid = le16_to_cpu(filt->pan_id); dev_vdbg(&priv->spi->dev, @@ -602,7 +601,7 @@ cc2520_filter(struct ieee802154_dev *dev, sizeof(panid), (u8 *)&panid); } - if (changed & IEEE802515_AFILT_IEEEADDR_CHANGED) { + if (changed & IEEE802154_AFILT_IEEEADDR_CHANGED) { dev_vdbg(&priv->spi->dev, "cc2520_filter called for IEEE addr\n"); cc2520_write_ram(priv, CC2520RAM_IEEEADDR, @@ -610,7 +609,7 @@ cc2520_filter(struct ieee802154_dev *dev, (u8 *)&filt->ieee_addr); } - if (changed & IEEE802515_AFILT_SADDR_CHANGED) { + if (changed & IEEE802154_AFILT_SADDR_CHANGED) { u16 addr = le16_to_cpu(filt->short_addr); dev_vdbg(&priv->spi->dev, @@ -619,7 +618,7 @@ cc2520_filter(struct ieee802154_dev *dev, sizeof(addr), (u8 *)&addr); } - if (changed & IEEE802515_AFILT_PANC_CHANGED) { + if (changed & IEEE802154_AFILT_PANC_CHANGED) { dev_vdbg(&priv->spi->dev, "cc2520_filter called for panc change\n"); if (filt->pan_coord) @@ -631,11 +630,11 @@ cc2520_filter(struct ieee802154_dev *dev, return 0; } -static struct ieee802154_ops cc2520_ops = { +static const struct ieee802154_ops cc2520_ops = { .owner = THIS_MODULE, .start = cc2520_start, .stop = cc2520_stop, - .xmit = cc2520_tx, + .xmit_sync = cc2520_tx, .ed = cc2520_ed, .set_channel = cc2520_set_channel, .set_hw_addr_filt = cc2520_filter, @@ -645,27 +644,29 @@ static int cc2520_register(struct cc2520_private *priv) { int ret = -ENOMEM; - priv->dev = ieee802154_alloc_device(sizeof(*priv), &cc2520_ops); - if (!priv->dev) + priv->hw = ieee802154_alloc_hw(sizeof(*priv), &cc2520_ops); + if (!priv->hw) goto err_ret; - priv->dev->priv = priv; - priv->dev->parent = &priv->spi->dev; - priv->dev->extra_tx_headroom = 0; + priv->hw->priv = priv; + priv->hw->parent = &priv->spi->dev; + priv->hw->extra_tx_headroom = 0; + priv->hw->vif_data_size = sizeof(*priv); /* We do support only 2.4 Ghz */ - priv->dev->phy->channels_supported[0] = 0x7FFF800; - priv->dev->flags = IEEE802154_HW_OMIT_CKSUM | IEEE802154_HW_AACK; + priv->hw->phy->channels_supported[0] = 0x7FFF800; + priv->hw->flags = IEEE802154_HW_OMIT_CKSUM | IEEE802154_HW_AACK | + IEEE802154_HW_AFILT; dev_vdbg(&priv->spi->dev, "registered cc2520\n"); - ret = ieee802154_register_device(priv->dev); + ret = ieee802154_register_hw(priv->hw); if (ret) goto err_free_device; return 0; err_free_device: - ieee802154_free_device(priv->dev); + ieee802154_free_hw(priv->hw); err_ret: return ret; } @@ -1002,8 +1003,8 @@ static int cc2520_remove(struct spi_device *spi) mutex_destroy(&priv->buffer_mutex); flush_work(&priv->fifop_irqwork); - ieee802154_unregister_device(priv->dev); - ieee802154_free_device(priv->dev); + ieee802154_unregister_hw(priv->hw); + ieee802154_free_hw(priv->hw); return 0; } diff --git a/drivers/net/ieee802154/fakehard.c b/drivers/net/ieee802154/fakehard.c deleted file mode 100644 index 6cbc56ad9ff4..000000000000 --- a/drivers/net/ieee802154/fakehard.c +++ /dev/null @@ -1,430 +0,0 @@ -/* - * Sample driver for HardMAC IEEE 802.15.4 devices - * - * Copyright (C) 2009 Siemens AG - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Written by: - * Dmitry Eremin-Solenikov <dmitry.baryshkov@siemens.com> - */ -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/netdevice.h> -#include <linux/skbuff.h> -#include <linux/if_arp.h> - -#include <net/af_ieee802154.h> -#include <net/ieee802154_netdev.h> -#include <net/ieee802154.h> -#include <net/nl802154.h> -#include <net/wpan-phy.h> - -struct fakehard_priv { - struct wpan_phy *phy; -}; - -static struct wpan_phy *fake_to_phy(const struct net_device *dev) -{ - struct fakehard_priv *priv = netdev_priv(dev); - return priv->phy; -} - -/** - * fake_get_phy - Return a phy corresponding to this device. - * @dev: The network device for which to return the wan-phy object - * - * This function returns a wpan-phy object corresponding to the passed - * network device. Reference counter for wpan-phy object is incremented, - * so when the wpan-phy isn't necessary, you should drop the reference - * via @wpan_phy_put() call. - */ -static struct wpan_phy *fake_get_phy(const struct net_device *dev) -{ - struct wpan_phy *phy = fake_to_phy(dev); - return to_phy(get_device(&phy->dev)); -} - -/** - * fake_get_pan_id - Retrieve the PAN ID of the device. - * @dev: The network device to retrieve the PAN of. - * - * Return the ID of the PAN from the PIB. - */ -static __le16 fake_get_pan_id(const struct net_device *dev) -{ - BUG_ON(dev->type != ARPHRD_IEEE802154); - - return cpu_to_le16(0xeba1); -} - -/** - * fake_get_short_addr - Retrieve the short address of the device. - * @dev: The network device to retrieve the short address of. - * - * Returns the IEEE 802.15.4 short-form address cached for this - * device. If the device has not yet had a short address assigned - * then this should return 0xFFFF to indicate a lack of association. - */ -static __le16 fake_get_short_addr(const struct net_device *dev) -{ - BUG_ON(dev->type != ARPHRD_IEEE802154); - - return cpu_to_le16(0x1); -} - -/** - * fake_get_dsn - Retrieve the DSN of the device. - * @dev: The network device to retrieve the DSN for. - * - * Returns the IEEE 802.15.4 DSN for the network device. - * The DSN is the sequence number which will be added to each - * packet or MAC command frame by the MAC during transmission. - * - * DSN means 'Data Sequence Number'. - * - * Note: This is in section 7.2.1.2 of the IEEE 802.15.4-2006 - * document. - */ -static u8 fake_get_dsn(const struct net_device *dev) -{ - BUG_ON(dev->type != ARPHRD_IEEE802154); - - return 0x00; /* DSN are implemented in HW, so return just 0 */ -} - -/** - * fake_assoc_req - Make an association request to the HW. - * @dev: The network device which we are associating to a network. - * @addr: The coordinator with which we wish to associate. - * @channel: The channel on which to associate. - * @cap: The capability information field to use in the association. - * - * Start an association with a coordinator. The coordinator's address - * and PAN ID can be found in @addr. - * - * Note: This is in section 7.3.1 and 7.5.3.1 of the IEEE - * 802.15.4-2006 document. - */ -static int fake_assoc_req(struct net_device *dev, - struct ieee802154_addr *addr, u8 channel, u8 page, u8 cap) -{ - struct wpan_phy *phy = fake_to_phy(dev); - - mutex_lock(&phy->pib_lock); - phy->current_channel = channel; - phy->current_page = page; - mutex_unlock(&phy->pib_lock); - - /* We simply emulate it here */ - return ieee802154_nl_assoc_confirm(dev, fake_get_short_addr(dev), - IEEE802154_SUCCESS); -} - -/** - * fake_assoc_resp - Send an association response to a device. - * @dev: The network device on which to send the response. - * @addr: The address of the device to respond to. - * @short_addr: The assigned short address for the device (if any). - * @status: The result of the association request. - * - * Queue the association response of the coordinator to another - * device's attempt to associate with the network which we - * coordinate. This is then added to the indirect-send queue to be - * transmitted to the end device when it polls for data. - * - * Note: This is in section 7.3.2 and 7.5.3.1 of the IEEE - * 802.15.4-2006 document. - */ -static int fake_assoc_resp(struct net_device *dev, - struct ieee802154_addr *addr, __le16 short_addr, u8 status) -{ - return 0; -} - -/** - * fake_disassoc_req - Disassociate a device from a network. - * @dev: The network device on which we're disassociating a device. - * @addr: The device to disassociate from the network. - * @reason: The reason to give to the device for being disassociated. - * - * This sends a disassociation notification to the device being - * disassociated from the network. - * - * Note: This is in section 7.5.3.2 of the IEEE 802.15.4-2006 - * document, with the reason described in 7.3.3.2. - */ -static int fake_disassoc_req(struct net_device *dev, - struct ieee802154_addr *addr, u8 reason) -{ - return ieee802154_nl_disassoc_confirm(dev, IEEE802154_SUCCESS); -} - -/** - * fake_start_req - Start an IEEE 802.15.4 PAN. - * @dev: The network device on which to start the PAN. - * @addr: The coordinator address to use when starting the PAN. - * @channel: The channel on which to start the PAN. - * @bcn_ord: Beacon order. - * @sf_ord: Superframe order. - * @pan_coord: Whether or not we are the PAN coordinator or just - * requesting a realignment perhaps? - * @blx: Battery Life Extension feature bitfield. - * @coord_realign: Something to realign something else. - * - * If pan_coord is non-zero then this starts a network with the - * provided parameters, otherwise it attempts a coordinator - * realignment of the stated network instead. - * - * Note: This is in section 7.5.2.3 of the IEEE 802.15.4-2006 - * document, with 7.3.8 describing coordinator realignment. - */ -static int fake_start_req(struct net_device *dev, - struct ieee802154_addr *addr, u8 channel, u8 page, - u8 bcn_ord, u8 sf_ord, u8 pan_coord, u8 blx, - u8 coord_realign) -{ - struct wpan_phy *phy = fake_to_phy(dev); - - mutex_lock(&phy->pib_lock); - phy->current_channel = channel; - phy->current_page = page; - mutex_unlock(&phy->pib_lock); - - /* We don't emulate beacons here at all, so START should fail */ - ieee802154_nl_start_confirm(dev, IEEE802154_INVALID_PARAMETER); - return 0; -} - -/** - * fake_scan_req - Start a channel scan. - * @dev: The network device on which to perform a channel scan. - * @type: The type of scan to perform. - * @channels: The channel bitmask to scan. - * @duration: How long to spend on each channel. - * - * This starts either a passive (energy) scan or an active (PAN) scan - * on the channels indicated in the @channels bitmask. The duration of - * the scan is measured in terms of superframe duration. Specifically, - * the scan will spend aBaseSuperFrameDuration * ((2^n) + 1) on each - * channel. - * - * Note: This is in section 7.5.2.1 of the IEEE 802.15.4-2006 document. - */ -static int fake_scan_req(struct net_device *dev, u8 type, u32 channels, - u8 page, u8 duration) -{ - u8 edl[27] = {}; - return ieee802154_nl_scan_confirm(dev, IEEE802154_SUCCESS, type, - channels, page, - type == IEEE802154_MAC_SCAN_ED ? edl : NULL); -} - -static struct ieee802154_mlme_ops fake_mlme = { - .assoc_req = fake_assoc_req, - .assoc_resp = fake_assoc_resp, - .disassoc_req = fake_disassoc_req, - .start_req = fake_start_req, - .scan_req = fake_scan_req, - - .get_phy = fake_get_phy, - - .get_pan_id = fake_get_pan_id, - .get_short_addr = fake_get_short_addr, - .get_dsn = fake_get_dsn, -}; - -static int ieee802154_fake_open(struct net_device *dev) -{ - netif_start_queue(dev); - return 0; -} - -static int ieee802154_fake_close(struct net_device *dev) -{ - netif_stop_queue(dev); - return 0; -} - -static netdev_tx_t ieee802154_fake_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - dev->stats.tx_packets++; - dev->stats.tx_bytes += skb->len; - - /* FIXME: do hardware work here ... */ - - dev_kfree_skb(skb); - return NETDEV_TX_OK; -} - - -static int ieee802154_fake_ioctl(struct net_device *dev, struct ifreq *ifr, - int cmd) -{ - struct sockaddr_ieee802154 *sa = - (struct sockaddr_ieee802154 *)&ifr->ifr_addr; - u16 pan_id, short_addr; - - switch (cmd) { - case SIOCGIFADDR: - /* FIXME: fixed here, get from device IRL */ - pan_id = le16_to_cpu(fake_get_pan_id(dev)); - short_addr = le16_to_cpu(fake_get_short_addr(dev)); - if (pan_id == IEEE802154_PANID_BROADCAST || - short_addr == IEEE802154_ADDR_BROADCAST) - return -EADDRNOTAVAIL; - - sa->family = AF_IEEE802154; - sa->addr.addr_type = IEEE802154_ADDR_SHORT; - sa->addr.pan_id = pan_id; - sa->addr.short_addr = short_addr; - return 0; - } - return -ENOIOCTLCMD; -} - -static int ieee802154_fake_mac_addr(struct net_device *dev, void *p) -{ - return -EBUSY; /* HW address is built into the device */ -} - -static const struct net_device_ops fake_ops = { - .ndo_open = ieee802154_fake_open, - .ndo_stop = ieee802154_fake_close, - .ndo_start_xmit = ieee802154_fake_xmit, - .ndo_do_ioctl = ieee802154_fake_ioctl, - .ndo_set_mac_address = ieee802154_fake_mac_addr, -}; - -static void ieee802154_fake_destruct(struct net_device *dev) -{ - struct wpan_phy *phy = fake_to_phy(dev); - - wpan_phy_unregister(phy); - free_netdev(dev); - wpan_phy_free(phy); -} - -static void ieee802154_fake_setup(struct net_device *dev) -{ - dev->addr_len = IEEE802154_ADDR_LEN; - memset(dev->broadcast, 0xff, IEEE802154_ADDR_LEN); - dev->features = NETIF_F_HW_CSUM; - dev->needed_tailroom = 2; /* FCS */ - dev->mtu = 127; - dev->tx_queue_len = 10; - dev->type = ARPHRD_IEEE802154; - dev->flags = IFF_NOARP | IFF_BROADCAST; - dev->watchdog_timeo = 0; - dev->destructor = ieee802154_fake_destruct; -} - - -static int ieee802154fake_probe(struct platform_device *pdev) -{ - struct net_device *dev; - struct fakehard_priv *priv; - struct wpan_phy *phy = wpan_phy_alloc(0); - int err; - - if (!phy) - return -ENOMEM; - - dev = alloc_netdev(sizeof(struct fakehard_priv), "hardwpan%d", - NET_NAME_UNKNOWN, ieee802154_fake_setup); - if (!dev) { - wpan_phy_free(phy); - return -ENOMEM; - } - - memcpy(dev->dev_addr, "\xba\xbe\xca\xfe\xde\xad\xbe\xef", - dev->addr_len); - - /* - * For now we'd like to emulate 2.4 GHz-only device, - * both O-QPSK and CSS - */ - /* 2.4 GHz O-QPSK 802.15.4-2003 */ - phy->channels_supported[0] |= 0x7FFF800; - /* 2.4 GHz CSS 802.15.4a-2007 */ - phy->channels_supported[3] |= 0x3fff; - - phy->transmit_power = 0xbf; - - dev->netdev_ops = &fake_ops; - dev->ml_priv = &fake_mlme; - - priv = netdev_priv(dev); - priv->phy = phy; - - wpan_phy_set_dev(phy, &pdev->dev); - SET_NETDEV_DEV(dev, &phy->dev); - - platform_set_drvdata(pdev, dev); - - err = wpan_phy_register(phy); - if (err) - goto err_phy_reg; - - err = register_netdev(dev); - if (err) - goto err_netdev_reg; - - dev_info(&pdev->dev, "Added ieee802154 HardMAC hardware\n"); - return 0; - -err_netdev_reg: - wpan_phy_unregister(phy); -err_phy_reg: - free_netdev(dev); - wpan_phy_free(phy); - return err; -} - -static int ieee802154fake_remove(struct platform_device *pdev) -{ - struct net_device *dev = platform_get_drvdata(pdev); - unregister_netdev(dev); - return 0; -} - -static struct platform_device *ieee802154fake_dev; - -static struct platform_driver ieee802154fake_driver = { - .probe = ieee802154fake_probe, - .remove = ieee802154fake_remove, - .driver = { - .name = "ieee802154hardmac", - .owner = THIS_MODULE, - }, -}; - -static __init int fake_init(void) -{ - ieee802154fake_dev = platform_device_register_simple( - "ieee802154hardmac", -1, NULL, 0); - return platform_driver_register(&ieee802154fake_driver); -} - -static __exit void fake_exit(void) -{ - platform_driver_unregister(&ieee802154fake_driver); - platform_device_unregister(ieee802154fake_dev); -} - -module_init(fake_init); -module_exit(fake_exit); -MODULE_LICENSE("GPL"); diff --git a/drivers/net/ieee802154/fakelb.c b/drivers/net/ieee802154/fakelb.c index 27d83207d24c..96947d724189 100644 --- a/drivers/net/ieee802154/fakelb.c +++ b/drivers/net/ieee802154/fakelb.c @@ -12,10 +12,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * * Written by: * Sergey Lapin <slapin@ossfans.org> * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> @@ -29,12 +25,12 @@ #include <linux/device.h> #include <linux/spinlock.h> #include <net/mac802154.h> -#include <net/wpan-phy.h> +#include <net/cfg802154.h> static int numlbs = 1; struct fakelb_dev_priv { - struct ieee802154_dev *dev; + struct ieee802154_hw *hw; struct list_head list; struct fakelb_priv *fake; @@ -49,9 +45,8 @@ struct fakelb_priv { }; static int -fakelb_hw_ed(struct ieee802154_dev *dev, u8 *level) +fakelb_hw_ed(struct ieee802154_hw *hw, u8 *level) { - might_sleep(); BUG_ON(!level); *level = 0xbe; @@ -59,14 +54,10 @@ fakelb_hw_ed(struct ieee802154_dev *dev, u8 *level) } static int -fakelb_hw_channel(struct ieee802154_dev *dev, int page, int channel) +fakelb_hw_channel(struct ieee802154_hw *hw, u8 page, u8 channel) { pr_debug("set channel to %d\n", channel); - might_sleep(); - dev->phy->current_page = page; - dev->phy->current_channel = channel; - return 0; } @@ -78,19 +69,17 @@ fakelb_hw_deliver(struct fakelb_dev_priv *priv, struct sk_buff *skb) spin_lock(&priv->lock); if (priv->working) { newskb = pskb_copy(skb, GFP_ATOMIC); - ieee802154_rx_irqsafe(priv->dev, newskb, 0xcc); + ieee802154_rx_irqsafe(priv->hw, newskb, 0xcc); } spin_unlock(&priv->lock); } static int -fakelb_hw_xmit(struct ieee802154_dev *dev, struct sk_buff *skb) +fakelb_hw_xmit(struct ieee802154_hw *hw, struct sk_buff *skb) { - struct fakelb_dev_priv *priv = dev->priv; + struct fakelb_dev_priv *priv = hw->priv; struct fakelb_priv *fake = priv->fake; - might_sleep(); - read_lock_bh(&fake->lock); if (priv->list.next == priv->list.prev) { /* we are the only one device */ @@ -99,8 +88,8 @@ fakelb_hw_xmit(struct ieee802154_dev *dev, struct sk_buff *skb) struct fakelb_dev_priv *dp; list_for_each_entry(dp, &priv->fake->list, list) { if (dp != priv && - (dp->dev->phy->current_channel == - priv->dev->phy->current_channel)) + (dp->hw->phy->current_channel == + priv->hw->phy->current_channel)) fakelb_hw_deliver(dp, skb); } } @@ -110,8 +99,8 @@ fakelb_hw_xmit(struct ieee802154_dev *dev, struct sk_buff *skb) } static int -fakelb_hw_start(struct ieee802154_dev *dev) { - struct fakelb_dev_priv *priv = dev->priv; +fakelb_hw_start(struct ieee802154_hw *hw) { + struct fakelb_dev_priv *priv = hw->priv; int ret = 0; spin_lock(&priv->lock); @@ -125,17 +114,17 @@ fakelb_hw_start(struct ieee802154_dev *dev) { } static void -fakelb_hw_stop(struct ieee802154_dev *dev) { - struct fakelb_dev_priv *priv = dev->priv; +fakelb_hw_stop(struct ieee802154_hw *hw) { + struct fakelb_dev_priv *priv = hw->priv; spin_lock(&priv->lock); priv->working = 0; spin_unlock(&priv->lock); } -static struct ieee802154_ops fakelb_ops = { +static const struct ieee802154_ops fakelb_ops = { .owner = THIS_MODULE, - .xmit = fakelb_hw_xmit, + .xmit_sync = fakelb_hw_xmit, .ed = fakelb_hw_ed, .set_channel = fakelb_hw_channel, .start = fakelb_hw_start, @@ -150,54 +139,54 @@ static int fakelb_add_one(struct device *dev, struct fakelb_priv *fake) { struct fakelb_dev_priv *priv; int err; - struct ieee802154_dev *ieee; + struct ieee802154_hw *hw; - ieee = ieee802154_alloc_device(sizeof(*priv), &fakelb_ops); - if (!ieee) + hw = ieee802154_alloc_hw(sizeof(*priv), &fakelb_ops); + if (!hw) return -ENOMEM; - priv = ieee->priv; - priv->dev = ieee; + priv = hw->priv; + priv->hw = hw; /* 868 MHz BPSK 802.15.4-2003 */ - ieee->phy->channels_supported[0] |= 1; + hw->phy->channels_supported[0] |= 1; /* 915 MHz BPSK 802.15.4-2003 */ - ieee->phy->channels_supported[0] |= 0x7fe; + hw->phy->channels_supported[0] |= 0x7fe; /* 2.4 GHz O-QPSK 802.15.4-2003 */ - ieee->phy->channels_supported[0] |= 0x7FFF800; + hw->phy->channels_supported[0] |= 0x7FFF800; /* 868 MHz ASK 802.15.4-2006 */ - ieee->phy->channels_supported[1] |= 1; + hw->phy->channels_supported[1] |= 1; /* 915 MHz ASK 802.15.4-2006 */ - ieee->phy->channels_supported[1] |= 0x7fe; + hw->phy->channels_supported[1] |= 0x7fe; /* 868 MHz O-QPSK 802.15.4-2006 */ - ieee->phy->channels_supported[2] |= 1; + hw->phy->channels_supported[2] |= 1; /* 915 MHz O-QPSK 802.15.4-2006 */ - ieee->phy->channels_supported[2] |= 0x7fe; + hw->phy->channels_supported[2] |= 0x7fe; /* 2.4 GHz CSS 802.15.4a-2007 */ - ieee->phy->channels_supported[3] |= 0x3fff; + hw->phy->channels_supported[3] |= 0x3fff; /* UWB Sub-gigahertz 802.15.4a-2007 */ - ieee->phy->channels_supported[4] |= 1; + hw->phy->channels_supported[4] |= 1; /* UWB Low band 802.15.4a-2007 */ - ieee->phy->channels_supported[4] |= 0x1e; + hw->phy->channels_supported[4] |= 0x1e; /* UWB High band 802.15.4a-2007 */ - ieee->phy->channels_supported[4] |= 0xffe0; + hw->phy->channels_supported[4] |= 0xffe0; /* 750 MHz O-QPSK 802.15.4c-2009 */ - ieee->phy->channels_supported[5] |= 0xf; + hw->phy->channels_supported[5] |= 0xf; /* 750 MHz MPSK 802.15.4c-2009 */ - ieee->phy->channels_supported[5] |= 0xf0; + hw->phy->channels_supported[5] |= 0xf0; /* 950 MHz BPSK 802.15.4d-2009 */ - ieee->phy->channels_supported[6] |= 0x3ff; + hw->phy->channels_supported[6] |= 0x3ff; /* 950 MHz GFSK 802.15.4d-2009 */ - ieee->phy->channels_supported[6] |= 0x3ffc00; + hw->phy->channels_supported[6] |= 0x3ffc00; INIT_LIST_HEAD(&priv->list); priv->fake = fake; spin_lock_init(&priv->lock); - ieee->parent = dev; + hw->parent = dev; - err = ieee802154_register_device(ieee); + err = ieee802154_register_hw(hw); if (err) goto err_reg; @@ -208,7 +197,7 @@ static int fakelb_add_one(struct device *dev, struct fakelb_priv *fake) return 0; err_reg: - ieee802154_free_device(priv->dev); + ieee802154_free_hw(priv->hw); return err; } @@ -218,8 +207,8 @@ static void fakelb_del(struct fakelb_dev_priv *priv) list_del(&priv->list); write_unlock_bh(&priv->fake->lock); - ieee802154_unregister_device(priv->dev); - ieee802154_free_device(priv->dev); + ieee802154_unregister_hw(priv->hw); + ieee802154_free_hw(priv->hw); } static int fakelb_probe(struct platform_device *pdev) diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c index 07e0b887c350..a200fa16beae 100644 --- a/drivers/net/ieee802154/mrf24j40.c +++ b/drivers/net/ieee802154/mrf24j40.c @@ -13,18 +13,14 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <linux/spi/spi.h> #include <linux/interrupt.h> #include <linux/module.h> -#include <net/wpan-phy.h> +#include <linux/ieee802154.h> +#include <net/cfg802154.h> #include <net/mac802154.h> -#include <net/ieee802154.h> /* MRF24J40 Short Address Registers */ #define REG_RXMCR 0x00 /* Receive MAC control */ @@ -43,6 +39,8 @@ #define REG_TXSTBL 0x2E /* TX Stabilization */ #define REG_INTSTAT 0x31 /* Interrupt Status */ #define REG_INTCON 0x32 /* Interrupt Control */ +#define REG_GPIO 0x33 /* GPIO */ +#define REG_TRISGPIO 0x34 /* GPIO direction */ #define REG_RFCTL 0x36 /* RF Control Mode Register */ #define REG_BBREG1 0x39 /* Baseband Registers */ #define REG_BBREG2 0x3A /* */ @@ -63,6 +61,7 @@ #define REG_SLPCON1 0x220 #define REG_WAKETIMEL 0x222 /* Wake-up Time Match Value Low */ #define REG_WAKETIMEH 0x223 /* Wake-up Time Match Value High */ +#define REG_TESTMODE 0x22F /* Test mode */ #define REG_RX_FIFO 0x300 /* Receive FIFO */ /* Device configuration: Only channels 11-26 on page 0 are supported. */ @@ -75,10 +74,12 @@ #define RX_FIFO_SIZE 144 /* From datasheet */ #define SET_CHANNEL_DELAY_US 192 /* From datasheet */ +enum mrf24j40_modules { MRF24J40, MRF24J40MA, MRF24J40MC }; + /* Device Private Data */ struct mrf24j40 { struct spi_device *spi; - struct ieee802154_dev *dev; + struct ieee802154_hw *hw; struct mutex buffer_mutex; /* only used to protect buf */ struct completion tx_complete; @@ -331,9 +332,9 @@ out: return ret; } -static int mrf24j40_tx(struct ieee802154_dev *dev, struct sk_buff *skb) +static int mrf24j40_tx(struct ieee802154_hw *hw, struct sk_buff *skb) { - struct mrf24j40 *devrec = dev->priv; + struct mrf24j40 *devrec = hw->priv; u8 val; int ret = 0; @@ -382,7 +383,7 @@ err: return ret; } -static int mrf24j40_ed(struct ieee802154_dev *dev, u8 *level) +static int mrf24j40_ed(struct ieee802154_hw *hw, u8 *level) { /* TODO: */ pr_warn("mrf24j40: ed not implemented\n"); @@ -390,9 +391,9 @@ static int mrf24j40_ed(struct ieee802154_dev *dev, u8 *level) return 0; } -static int mrf24j40_start(struct ieee802154_dev *dev) +static int mrf24j40_start(struct ieee802154_hw *hw) { - struct mrf24j40 *devrec = dev->priv; + struct mrf24j40 *devrec = hw->priv; u8 val; int ret; @@ -407,9 +408,9 @@ static int mrf24j40_start(struct ieee802154_dev *dev) return 0; } -static void mrf24j40_stop(struct ieee802154_dev *dev) +static void mrf24j40_stop(struct ieee802154_hw *hw) { - struct mrf24j40 *devrec = dev->priv; + struct mrf24j40 *devrec = hw->priv; u8 val; int ret; @@ -422,10 +423,9 @@ static void mrf24j40_stop(struct ieee802154_dev *dev) write_short_reg(devrec, REG_INTCON, val); } -static int mrf24j40_set_channel(struct ieee802154_dev *dev, - int page, int channel) +static int mrf24j40_set_channel(struct ieee802154_hw *hw, u8 page, u8 channel) { - struct mrf24j40 *devrec = dev->priv; + struct mrf24j40 *devrec = hw->priv; u8 val; int ret; @@ -453,15 +453,15 @@ static int mrf24j40_set_channel(struct ieee802154_dev *dev, return 0; } -static int mrf24j40_filter(struct ieee802154_dev *dev, +static int mrf24j40_filter(struct ieee802154_hw *hw, struct ieee802154_hw_addr_filt *filt, unsigned long changed) { - struct mrf24j40 *devrec = dev->priv; + struct mrf24j40 *devrec = hw->priv; dev_dbg(printdev(devrec), "filter\n"); - if (changed & IEEE802515_AFILT_SADDR_CHANGED) { + if (changed & IEEE802154_AFILT_SADDR_CHANGED) { /* Short Addr */ u8 addrh, addrl; @@ -474,7 +474,7 @@ static int mrf24j40_filter(struct ieee802154_dev *dev, "Set short addr to %04hx\n", filt->short_addr); } - if (changed & IEEE802515_AFILT_IEEEADDR_CHANGED) { + if (changed & IEEE802154_AFILT_IEEEADDR_CHANGED) { /* Device Address */ u8 i, addr[8]; @@ -490,7 +490,7 @@ static int mrf24j40_filter(struct ieee802154_dev *dev, #endif } - if (changed & IEEE802515_AFILT_PANID_CHANGED) { + if (changed & IEEE802154_AFILT_PANID_CHANGED) { /* PAN ID */ u8 panidl, panidh; @@ -502,7 +502,7 @@ static int mrf24j40_filter(struct ieee802154_dev *dev, dev_dbg(printdev(devrec), "Set PANID to %04hx\n", filt->pan_id); } - if (changed & IEEE802515_AFILT_PANC_CHANGED) { + if (changed & IEEE802154_AFILT_PANC_CHANGED) { /* Pan Coordinator */ u8 val; int ret; @@ -543,7 +543,7 @@ static int mrf24j40_handle_rx(struct mrf24j40 *devrec) val |= 4; /* SET RXDECINV */ write_short_reg(devrec, REG_BBREG1, val); - skb = alloc_skb(len, GFP_KERNEL); + skb = dev_alloc_skb(len); if (!skb) { ret = -ENOMEM; goto out; @@ -563,7 +563,7 @@ static int mrf24j40_handle_rx(struct mrf24j40 *devrec) /* TODO: Other drivers call ieee20154_rx_irqsafe() here (eg: cc2040, * also from a workqueue). I think irqsafe is not necessary here. * Can someone confirm? */ - ieee802154_rx_irqsafe(devrec->dev, skb, lqi); + ieee802154_rx_irqsafe(devrec->hw, skb, lqi); dev_dbg(printdev(devrec), "RX Handled\n"); @@ -578,9 +578,9 @@ out: return ret; } -static struct ieee802154_ops mrf24j40_ops = { +static const struct ieee802154_ops mrf24j40_ops = { .owner = THIS_MODULE, - .xmit = mrf24j40_tx, + .xmit_sync = mrf24j40_tx, .ed = mrf24j40_ed, .start = mrf24j40_start, .stop = mrf24j40_stop, @@ -691,6 +691,28 @@ static int mrf24j40_hw_init(struct mrf24j40 *devrec) if (ret) goto err_ret; + if (spi_get_device_id(devrec->spi)->driver_data == MRF24J40MC) { + /* Enable external amplifier. + * From MRF24J40MC datasheet section 1.3: Operation. + */ + read_long_reg(devrec, REG_TESTMODE, &val); + val |= 0x7; /* Configure GPIO 0-2 to control amplifier */ + write_long_reg(devrec, REG_TESTMODE, val); + + read_short_reg(devrec, REG_TRISGPIO, &val); + val |= 0x8; /* Set GPIO3 as output. */ + write_short_reg(devrec, REG_TRISGPIO, val); + + read_short_reg(devrec, REG_GPIO, &val); + val |= 0x8; /* Set GPIO3 HIGH to enable U5 voltage regulator */ + write_short_reg(devrec, REG_GPIO, val); + + /* Reduce TX pwr to meet FCC requirements. + * From MRF24J40MC datasheet section 3.1.1 + */ + write_long_reg(devrec, REG_RFCON3, 0x28); + } + return 0; err_ret: @@ -722,17 +744,18 @@ static int mrf24j40_probe(struct spi_device *spi) /* Register with the 802154 subsystem */ - devrec->dev = ieee802154_alloc_device(0, &mrf24j40_ops); - if (!devrec->dev) + devrec->hw = ieee802154_alloc_hw(0, &mrf24j40_ops); + if (!devrec->hw) goto err_ret; - devrec->dev->priv = devrec; - devrec->dev->parent = &devrec->spi->dev; - devrec->dev->phy->channels_supported[0] = CHANNEL_MASK; - devrec->dev->flags = IEEE802154_HW_OMIT_CKSUM|IEEE802154_HW_AACK; + devrec->hw->priv = devrec; + devrec->hw->parent = &devrec->spi->dev; + devrec->hw->phy->channels_supported[0] = CHANNEL_MASK; + devrec->hw->flags = IEEE802154_HW_OMIT_CKSUM | IEEE802154_HW_AACK | + IEEE802154_HW_AFILT; dev_dbg(printdev(devrec), "registered mrf24j40\n"); - ret = ieee802154_register_device(devrec->dev); + ret = ieee802154_register_hw(devrec->hw); if (ret) goto err_register_device; @@ -757,9 +780,9 @@ static int mrf24j40_probe(struct spi_device *spi) err_irq: err_hw_init: - ieee802154_unregister_device(devrec->dev); + ieee802154_unregister_hw(devrec->hw); err_register_device: - ieee802154_free_device(devrec->dev); + ieee802154_free_hw(devrec->hw); err_ret: return ret; } @@ -770,8 +793,8 @@ static int mrf24j40_remove(struct spi_device *spi) dev_dbg(printdev(devrec), "remove\n"); - ieee802154_unregister_device(devrec->dev); - ieee802154_free_device(devrec->dev); + ieee802154_unregister_hw(devrec->hw); + ieee802154_free_hw(devrec->hw); /* TODO: Will ieee802154_free_device() wait until ->xmit() is * complete? */ @@ -779,8 +802,9 @@ static int mrf24j40_remove(struct spi_device *spi) } static const struct spi_device_id mrf24j40_ids[] = { - { "mrf24j40", 0 }, - { "mrf24j40ma", 0 }, + { "mrf24j40", MRF24J40 }, + { "mrf24j40ma", MRF24J40MA }, + { "mrf24j40mc", MRF24J40MC }, { }, }; MODULE_DEVICE_TABLE(spi, mrf24j40_ids); diff --git a/drivers/net/ipvlan/Makefile b/drivers/net/ipvlan/Makefile new file mode 100644 index 000000000000..df79910192d6 --- /dev/null +++ b/drivers/net/ipvlan/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for the Ethernet Ipvlan driver +# + +obj-$(CONFIG_IPVLAN) += ipvlan.o + +ipvlan-objs := ipvlan_core.o ipvlan_main.o diff --git a/drivers/net/ipvlan/ipvlan.h b/drivers/net/ipvlan/ipvlan.h new file mode 100644 index 000000000000..ab3e7614ed71 --- /dev/null +++ b/drivers/net/ipvlan/ipvlan.h @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2014 Mahesh Bandewar <maheshb@google.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + */ +#ifndef __IPVLAN_H +#define __IPVLAN_H + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/rculist.h> +#include <linux/notifier.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/if_arp.h> +#include <linux/if_link.h> +#include <linux/if_vlan.h> +#include <linux/ip.h> +#include <linux/inetdevice.h> +#include <net/rtnetlink.h> +#include <net/gre.h> +#include <net/route.h> +#include <net/addrconf.h> + +#define IPVLAN_DRV "ipvlan" +#define IPV_DRV_VER "0.1" + +#define IPVLAN_HASH_SIZE (1 << BITS_PER_BYTE) +#define IPVLAN_HASH_MASK (IPVLAN_HASH_SIZE - 1) + +#define IPVLAN_MAC_FILTER_BITS 8 +#define IPVLAN_MAC_FILTER_SIZE (1 << IPVLAN_MAC_FILTER_BITS) +#define IPVLAN_MAC_FILTER_MASK (IPVLAN_MAC_FILTER_SIZE - 1) + +typedef enum { + IPVL_IPV6 = 0, + IPVL_ICMPV6, + IPVL_IPV4, + IPVL_ARP, +} ipvl_hdr_type; + +struct ipvl_pcpu_stats { + u64 rx_pkts; + u64 rx_bytes; + u64 rx_mcast; + u64 tx_pkts; + u64 tx_bytes; + struct u64_stats_sync syncp; + u32 rx_errs; + u32 tx_drps; +}; + +struct ipvl_port; + +struct ipvl_dev { + struct net_device *dev; + struct list_head pnode; + struct ipvl_port *port; + struct net_device *phy_dev; + struct list_head addrs; + int ipv4cnt; + int ipv6cnt; + struct ipvl_pcpu_stats *pcpu_stats; + DECLARE_BITMAP(mac_filters, IPVLAN_MAC_FILTER_SIZE); + netdev_features_t sfeatures; + u32 msg_enable; + u16 mtu_adj; +}; + +struct ipvl_addr { + struct ipvl_dev *master; /* Back pointer to master */ + union { + struct in6_addr ip6; /* IPv6 address on logical interface */ + struct in_addr ip4; /* IPv4 address on logical interface */ + } ipu; +#define ip6addr ipu.ip6 +#define ip4addr ipu.ip4 + struct hlist_node hlnode; /* Hash-table linkage */ + struct list_head anode; /* logical-interface linkage */ + struct rcu_head rcu; + ipvl_hdr_type atype; +}; + +struct ipvl_port { + struct net_device *dev; + struct hlist_head hlhead[IPVLAN_HASH_SIZE]; + struct list_head ipvlans; + struct rcu_head rcu; + int count; + u16 mode; +}; + +static inline struct ipvl_port *ipvlan_port_get_rcu(const struct net_device *d) +{ + return rcu_dereference(d->rx_handler_data); +} + +static inline struct ipvl_port *ipvlan_port_get_rtnl(const struct net_device *d) +{ + return rtnl_dereference(d->rx_handler_data); +} + +static inline bool ipvlan_dev_master(struct net_device *d) +{ + return d->priv_flags & IFF_IPVLAN_MASTER; +} + +static inline bool ipvlan_dev_slave(struct net_device *d) +{ + return d->priv_flags & IFF_IPVLAN_SLAVE; +} + +void ipvlan_adjust_mtu(struct ipvl_dev *ipvlan, struct net_device *dev); +void ipvlan_set_port_mode(struct ipvl_port *port, u32 nval); +void ipvlan_init_secret(void); +unsigned int ipvlan_mac_hash(const unsigned char *addr); +rx_handler_result_t ipvlan_handle_frame(struct sk_buff **pskb); +int ipvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev); +void ipvlan_ht_addr_add(struct ipvl_dev *ipvlan, struct ipvl_addr *addr); +bool ipvlan_addr_busy(struct ipvl_dev *ipvlan, void *iaddr, bool is_v6); +struct ipvl_addr *ipvlan_ht_addr_lookup(const struct ipvl_port *port, + const void *iaddr, bool is_v6); +void ipvlan_ht_addr_del(struct ipvl_addr *addr, bool sync); +#endif /* __IPVLAN_H */ diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c new file mode 100644 index 000000000000..a14d87783245 --- /dev/null +++ b/drivers/net/ipvlan/ipvlan_core.c @@ -0,0 +1,607 @@ +/* Copyright (c) 2014 Mahesh Bandewar <maheshb@google.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + */ + +#include "ipvlan.h" + +static u32 ipvlan_jhash_secret; + +void ipvlan_init_secret(void) +{ + net_get_random_once(&ipvlan_jhash_secret, sizeof(ipvlan_jhash_secret)); +} + +static void ipvlan_count_rx(const struct ipvl_dev *ipvlan, + unsigned int len, bool success, bool mcast) +{ + if (!ipvlan) + return; + + if (likely(success)) { + struct ipvl_pcpu_stats *pcptr; + + pcptr = this_cpu_ptr(ipvlan->pcpu_stats); + u64_stats_update_begin(&pcptr->syncp); + pcptr->rx_pkts++; + pcptr->rx_bytes += len; + if (mcast) + pcptr->rx_mcast++; + u64_stats_update_end(&pcptr->syncp); + } else { + this_cpu_inc(ipvlan->pcpu_stats->rx_errs); + } +} + +static u8 ipvlan_get_v6_hash(const void *iaddr) +{ + const struct in6_addr *ip6_addr = iaddr; + + return __ipv6_addr_jhash(ip6_addr, ipvlan_jhash_secret) & + IPVLAN_HASH_MASK; +} + +static u8 ipvlan_get_v4_hash(const void *iaddr) +{ + const struct in_addr *ip4_addr = iaddr; + + return jhash_1word(ip4_addr->s_addr, ipvlan_jhash_secret) & + IPVLAN_HASH_MASK; +} + +struct ipvl_addr *ipvlan_ht_addr_lookup(const struct ipvl_port *port, + const void *iaddr, bool is_v6) +{ + struct ipvl_addr *addr; + u8 hash; + + hash = is_v6 ? ipvlan_get_v6_hash(iaddr) : + ipvlan_get_v4_hash(iaddr); + hlist_for_each_entry_rcu(addr, &port->hlhead[hash], hlnode) { + if (is_v6 && addr->atype == IPVL_IPV6 && + ipv6_addr_equal(&addr->ip6addr, iaddr)) + return addr; + else if (!is_v6 && addr->atype == IPVL_IPV4 && + addr->ip4addr.s_addr == + ((struct in_addr *)iaddr)->s_addr) + return addr; + } + return NULL; +} + +void ipvlan_ht_addr_add(struct ipvl_dev *ipvlan, struct ipvl_addr *addr) +{ + struct ipvl_port *port = ipvlan->port; + u8 hash; + + hash = (addr->atype == IPVL_IPV6) ? + ipvlan_get_v6_hash(&addr->ip6addr) : + ipvlan_get_v4_hash(&addr->ip4addr); + hlist_add_head_rcu(&addr->hlnode, &port->hlhead[hash]); +} + +void ipvlan_ht_addr_del(struct ipvl_addr *addr, bool sync) +{ + hlist_del_rcu(&addr->hlnode); + if (sync) + synchronize_rcu(); +} + +bool ipvlan_addr_busy(struct ipvl_dev *ipvlan, void *iaddr, bool is_v6) +{ + struct ipvl_port *port = ipvlan->port; + struct ipvl_addr *addr; + + list_for_each_entry(addr, &ipvlan->addrs, anode) { + if ((is_v6 && addr->atype == IPVL_IPV6 && + ipv6_addr_equal(&addr->ip6addr, iaddr)) || + (!is_v6 && addr->atype == IPVL_IPV4 && + addr->ip4addr.s_addr == ((struct in_addr *)iaddr)->s_addr)) + return true; + } + + if (ipvlan_ht_addr_lookup(port, iaddr, is_v6)) + return true; + + return false; +} + +static void *ipvlan_get_L3_hdr(struct sk_buff *skb, int *type) +{ + void *lyr3h = NULL; + + switch (skb->protocol) { + case htons(ETH_P_ARP): { + struct arphdr *arph; + + if (unlikely(!pskb_may_pull(skb, sizeof(*arph)))) + return NULL; + + arph = arp_hdr(skb); + *type = IPVL_ARP; + lyr3h = arph; + break; + } + case htons(ETH_P_IP): { + u32 pktlen; + struct iphdr *ip4h; + + if (unlikely(!pskb_may_pull(skb, sizeof(*ip4h)))) + return NULL; + + ip4h = ip_hdr(skb); + pktlen = ntohs(ip4h->tot_len); + if (ip4h->ihl < 5 || ip4h->version != 4) + return NULL; + if (skb->len < pktlen || pktlen < (ip4h->ihl * 4)) + return NULL; + + *type = IPVL_IPV4; + lyr3h = ip4h; + break; + } + case htons(ETH_P_IPV6): { + struct ipv6hdr *ip6h; + + if (unlikely(!pskb_may_pull(skb, sizeof(*ip6h)))) + return NULL; + + ip6h = ipv6_hdr(skb); + if (ip6h->version != 6) + return NULL; + + *type = IPVL_IPV6; + lyr3h = ip6h; + /* Only Neighbour Solicitation pkts need different treatment */ + if (ipv6_addr_any(&ip6h->saddr) && + ip6h->nexthdr == NEXTHDR_ICMP) { + *type = IPVL_ICMPV6; + lyr3h = ip6h + 1; + } + break; + } + default: + return NULL; + } + + return lyr3h; +} + +unsigned int ipvlan_mac_hash(const unsigned char *addr) +{ + u32 hash = jhash_1word(__get_unaligned_cpu32(addr+2), + ipvlan_jhash_secret); + + return hash & IPVLAN_MAC_FILTER_MASK; +} + +static void ipvlan_multicast_frame(struct ipvl_port *port, struct sk_buff *skb, + const struct ipvl_dev *in_dev, bool local) +{ + struct ethhdr *eth = eth_hdr(skb); + struct ipvl_dev *ipvlan; + struct sk_buff *nskb; + unsigned int len; + unsigned int mac_hash; + int ret; + + if (skb->protocol == htons(ETH_P_PAUSE)) + return; + + list_for_each_entry(ipvlan, &port->ipvlans, pnode) { + if (local && (ipvlan == in_dev)) + continue; + + mac_hash = ipvlan_mac_hash(eth->h_dest); + if (!test_bit(mac_hash, ipvlan->mac_filters)) + continue; + + ret = NET_RX_DROP; + len = skb->len + ETH_HLEN; + nskb = skb_clone(skb, GFP_ATOMIC); + if (!nskb) + goto mcast_acct; + + if (ether_addr_equal(eth->h_dest, ipvlan->phy_dev->broadcast)) + nskb->pkt_type = PACKET_BROADCAST; + else + nskb->pkt_type = PACKET_MULTICAST; + + nskb->dev = ipvlan->dev; + if (local) + ret = dev_forward_skb(ipvlan->dev, nskb); + else + ret = netif_rx(nskb); +mcast_acct: + ipvlan_count_rx(ipvlan, len, ret == NET_RX_SUCCESS, true); + } + + /* Locally generated? ...Forward a copy to the main-device as + * well. On the RX side we'll ignore it (wont give it to any + * of the virtual devices. + */ + if (local) { + nskb = skb_clone(skb, GFP_ATOMIC); + if (nskb) { + if (ether_addr_equal(eth->h_dest, port->dev->broadcast)) + nskb->pkt_type = PACKET_BROADCAST; + else + nskb->pkt_type = PACKET_MULTICAST; + + dev_forward_skb(port->dev, nskb); + } + } +} + +static int ipvlan_rcv_frame(struct ipvl_addr *addr, struct sk_buff *skb, + bool local) +{ + struct ipvl_dev *ipvlan = addr->master; + struct net_device *dev = ipvlan->dev; + unsigned int len; + rx_handler_result_t ret = RX_HANDLER_CONSUMED; + bool success = false; + + len = skb->len + ETH_HLEN; + if (unlikely(!(dev->flags & IFF_UP))) { + kfree_skb(skb); + goto out; + } + + skb = skb_share_check(skb, GFP_ATOMIC); + if (!skb) + goto out; + + skb->dev = dev; + skb->pkt_type = PACKET_HOST; + + if (local) { + if (dev_forward_skb(ipvlan->dev, skb) == NET_RX_SUCCESS) + success = true; + } else { + ret = RX_HANDLER_ANOTHER; + success = true; + } + +out: + ipvlan_count_rx(ipvlan, len, success, false); + return ret; +} + +static struct ipvl_addr *ipvlan_addr_lookup(struct ipvl_port *port, + void *lyr3h, int addr_type, + bool use_dest) +{ + struct ipvl_addr *addr = NULL; + + if (addr_type == IPVL_IPV6) { + struct ipv6hdr *ip6h; + struct in6_addr *i6addr; + + ip6h = (struct ipv6hdr *)lyr3h; + i6addr = use_dest ? &ip6h->daddr : &ip6h->saddr; + addr = ipvlan_ht_addr_lookup(port, i6addr, true); + } else if (addr_type == IPVL_ICMPV6) { + struct nd_msg *ndmh; + struct in6_addr *i6addr; + + /* Make sure that the NeighborSolicitation ICMPv6 packets + * are handled to avoid DAD issue. + */ + ndmh = (struct nd_msg *)lyr3h; + if (ndmh->icmph.icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) { + i6addr = &ndmh->target; + addr = ipvlan_ht_addr_lookup(port, i6addr, true); + } + } else if (addr_type == IPVL_IPV4) { + struct iphdr *ip4h; + __be32 *i4addr; + + ip4h = (struct iphdr *)lyr3h; + i4addr = use_dest ? &ip4h->daddr : &ip4h->saddr; + addr = ipvlan_ht_addr_lookup(port, i4addr, false); + } else if (addr_type == IPVL_ARP) { + struct arphdr *arph; + unsigned char *arp_ptr; + __be32 dip; + + arph = (struct arphdr *)lyr3h; + arp_ptr = (unsigned char *)(arph + 1); + if (use_dest) + arp_ptr += (2 * port->dev->addr_len) + 4; + else + arp_ptr += port->dev->addr_len; + + memcpy(&dip, arp_ptr, 4); + addr = ipvlan_ht_addr_lookup(port, &dip, false); + } + + return addr; +} + +static int ipvlan_process_v4_outbound(struct sk_buff *skb) +{ + const struct iphdr *ip4h = ip_hdr(skb); + struct net_device *dev = skb->dev; + struct rtable *rt; + int err, ret = NET_XMIT_DROP; + struct flowi4 fl4 = { + .flowi4_oif = dev->iflink, + .flowi4_tos = RT_TOS(ip4h->tos), + .flowi4_flags = FLOWI_FLAG_ANYSRC, + .daddr = ip4h->daddr, + .saddr = ip4h->saddr, + }; + + rt = ip_route_output_flow(dev_net(dev), &fl4, NULL); + if (IS_ERR(rt)) + goto err; + + if (rt->rt_type != RTN_UNICAST && rt->rt_type != RTN_LOCAL) { + ip_rt_put(rt); + goto err; + } + skb_dst_drop(skb); + skb_dst_set(skb, &rt->dst); + err = ip_local_out(skb); + if (unlikely(net_xmit_eval(err))) + dev->stats.tx_errors++; + else + ret = NET_XMIT_SUCCESS; + goto out; +err: + dev->stats.tx_errors++; + kfree_skb(skb); +out: + return ret; +} + +static int ipvlan_process_v6_outbound(struct sk_buff *skb) +{ + const struct ipv6hdr *ip6h = ipv6_hdr(skb); + struct net_device *dev = skb->dev; + struct dst_entry *dst; + int err, ret = NET_XMIT_DROP; + struct flowi6 fl6 = { + .flowi6_iif = skb->dev->ifindex, + .daddr = ip6h->daddr, + .saddr = ip6h->saddr, + .flowi6_flags = FLOWI_FLAG_ANYSRC, + .flowlabel = ip6_flowinfo(ip6h), + .flowi6_mark = skb->mark, + .flowi6_proto = ip6h->nexthdr, + }; + + dst = ip6_route_output(dev_net(dev), NULL, &fl6); + if (IS_ERR(dst)) + goto err; + + skb_dst_drop(skb); + skb_dst_set(skb, dst); + err = ip6_local_out(skb); + if (unlikely(net_xmit_eval(err))) + dev->stats.tx_errors++; + else + ret = NET_XMIT_SUCCESS; + goto out; +err: + dev->stats.tx_errors++; + kfree_skb(skb); +out: + return ret; +} + +static int ipvlan_process_outbound(struct sk_buff *skb, + const struct ipvl_dev *ipvlan) +{ + struct ethhdr *ethh = eth_hdr(skb); + int ret = NET_XMIT_DROP; + + /* In this mode we dont care about multicast and broadcast traffic */ + if (is_multicast_ether_addr(ethh->h_dest)) { + pr_warn_ratelimited("Dropped {multi|broad}cast of type= [%x]\n", + ntohs(skb->protocol)); + kfree_skb(skb); + goto out; + } + + /* The ipvlan is a pseudo-L2 device, so the packets that we receive + * will have L2; which need to discarded and processed further + * in the net-ns of the main-device. + */ + if (skb_mac_header_was_set(skb)) { + skb_pull(skb, sizeof(*ethh)); + skb->mac_header = (typeof(skb->mac_header))~0U; + skb_reset_network_header(skb); + } + + if (skb->protocol == htons(ETH_P_IPV6)) + ret = ipvlan_process_v6_outbound(skb); + else if (skb->protocol == htons(ETH_P_IP)) + ret = ipvlan_process_v4_outbound(skb); + else { + pr_warn_ratelimited("Dropped outbound packet type=%x\n", + ntohs(skb->protocol)); + kfree_skb(skb); + } +out: + return ret; +} + +static int ipvlan_xmit_mode_l3(struct sk_buff *skb, struct net_device *dev) +{ + const struct ipvl_dev *ipvlan = netdev_priv(dev); + void *lyr3h; + struct ipvl_addr *addr; + int addr_type; + + lyr3h = ipvlan_get_L3_hdr(skb, &addr_type); + if (!lyr3h) + goto out; + + addr = ipvlan_addr_lookup(ipvlan->port, lyr3h, addr_type, true); + if (addr) + return ipvlan_rcv_frame(addr, skb, true); + +out: + skb->dev = ipvlan->phy_dev; + return ipvlan_process_outbound(skb, ipvlan); +} + +static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev) +{ + const struct ipvl_dev *ipvlan = netdev_priv(dev); + struct ethhdr *eth = eth_hdr(skb); + struct ipvl_addr *addr; + void *lyr3h; + int addr_type; + + if (ether_addr_equal(eth->h_dest, eth->h_source)) { + lyr3h = ipvlan_get_L3_hdr(skb, &addr_type); + if (lyr3h) { + addr = ipvlan_addr_lookup(ipvlan->port, lyr3h, addr_type, true); + if (addr) + return ipvlan_rcv_frame(addr, skb, true); + } + skb = skb_share_check(skb, GFP_ATOMIC); + if (!skb) + return NET_XMIT_DROP; + + /* Packet definitely does not belong to any of the + * virtual devices, but the dest is local. So forward + * 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); + + } else if (is_multicast_ether_addr(eth->h_dest)) { + u8 ip_summed = skb->ip_summed; + + skb->ip_summed = CHECKSUM_UNNECESSARY; + ipvlan_multicast_frame(ipvlan->port, skb, ipvlan, true); + skb->ip_summed = ip_summed; + } + + skb->dev = ipvlan->phy_dev; + return dev_queue_xmit(skb); +} + +int ipvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct ipvl_dev *ipvlan = netdev_priv(dev); + struct ipvl_port *port = ipvlan_port_get_rcu(ipvlan->phy_dev); + + if (!port) + goto out; + + if (unlikely(!pskb_may_pull(skb, sizeof(struct ethhdr)))) + goto out; + + switch(port->mode) { + case IPVLAN_MODE_L2: + return ipvlan_xmit_mode_l2(skb, dev); + case IPVLAN_MODE_L3: + return ipvlan_xmit_mode_l3(skb, dev); + } + + /* Should not reach here */ + WARN_ONCE(true, "ipvlan_queue_xmit() called for mode = [%hx]\n", + port->mode); +out: + kfree_skb(skb); + return NET_XMIT_DROP; +} + +static bool ipvlan_external_frame(struct sk_buff *skb, struct ipvl_port *port) +{ + struct ethhdr *eth = eth_hdr(skb); + struct ipvl_addr *addr; + void *lyr3h; + int addr_type; + + if (ether_addr_equal(eth->h_source, skb->dev->dev_addr)) { + lyr3h = ipvlan_get_L3_hdr(skb, &addr_type); + if (!lyr3h) + return true; + + addr = ipvlan_addr_lookup(port, lyr3h, addr_type, false); + if (addr) + return false; + } + + return true; +} + +static rx_handler_result_t ipvlan_handle_mode_l3(struct sk_buff **pskb, + struct ipvl_port *port) +{ + void *lyr3h; + int addr_type; + struct ipvl_addr *addr; + struct sk_buff *skb = *pskb; + rx_handler_result_t ret = RX_HANDLER_PASS; + + lyr3h = ipvlan_get_L3_hdr(skb, &addr_type); + if (!lyr3h) + goto out; + + addr = ipvlan_addr_lookup(port, lyr3h, addr_type, true); + if (addr) + ret = ipvlan_rcv_frame(addr, skb, false); + +out: + return ret; +} + +static rx_handler_result_t ipvlan_handle_mode_l2(struct sk_buff **pskb, + struct ipvl_port *port) +{ + struct sk_buff *skb = *pskb; + struct ethhdr *eth = eth_hdr(skb); + rx_handler_result_t ret = RX_HANDLER_PASS; + void *lyr3h; + int addr_type; + + if (is_multicast_ether_addr(eth->h_dest)) { + if (ipvlan_external_frame(skb, port)) + ipvlan_multicast_frame(port, skb, NULL, false); + } else { + struct ipvl_addr *addr; + + lyr3h = ipvlan_get_L3_hdr(skb, &addr_type); + if (!lyr3h) + return ret; + + addr = ipvlan_addr_lookup(port, lyr3h, addr_type, true); + if (addr) + ret = ipvlan_rcv_frame(addr, skb, false); + } + + return ret; +} + +rx_handler_result_t ipvlan_handle_frame(struct sk_buff **pskb) +{ + struct sk_buff *skb = *pskb; + struct ipvl_port *port = ipvlan_port_get_rcu(skb->dev); + + if (!port) + return RX_HANDLER_PASS; + + switch (port->mode) { + case IPVLAN_MODE_L2: + return ipvlan_handle_mode_l2(pskb, port); + case IPVLAN_MODE_L3: + return ipvlan_handle_mode_l3(pskb, port); + } + + /* Should not reach here */ + WARN_ONCE(true, "ipvlan_handle_frame() called for mode = [%hx]\n", + port->mode); + kfree_skb(skb); + return NET_RX_DROP; +} diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c new file mode 100644 index 000000000000..96b71b0d78f6 --- /dev/null +++ b/drivers/net/ipvlan/ipvlan_main.c @@ -0,0 +1,790 @@ +/* Copyright (c) 2014 Mahesh Bandewar <maheshb@google.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + */ + +#include "ipvlan.h" + +void ipvlan_adjust_mtu(struct ipvl_dev *ipvlan, struct net_device *dev) +{ + ipvlan->dev->mtu = dev->mtu - ipvlan->mtu_adj; +} + +void ipvlan_set_port_mode(struct ipvl_port *port, u32 nval) +{ + struct ipvl_dev *ipvlan; + + if (port->mode != nval) { + list_for_each_entry(ipvlan, &port->ipvlans, pnode) { + if (nval == IPVLAN_MODE_L3) + ipvlan->dev->flags |= IFF_NOARP; + else + ipvlan->dev->flags &= ~IFF_NOARP; + } + port->mode = nval; + } +} + +static int ipvlan_port_create(struct net_device *dev) +{ + struct ipvl_port *port; + int err, idx; + + if (dev->type != ARPHRD_ETHER || dev->flags & IFF_LOOPBACK) { + netdev_err(dev, "Master is either lo or non-ether device\n"); + return -EINVAL; + } + port = kzalloc(sizeof(struct ipvl_port), GFP_KERNEL); + if (!port) + return -ENOMEM; + + port->dev = dev; + port->mode = IPVLAN_MODE_L3; + INIT_LIST_HEAD(&port->ipvlans); + for (idx = 0; idx < IPVLAN_HASH_SIZE; idx++) + INIT_HLIST_HEAD(&port->hlhead[idx]); + + err = netdev_rx_handler_register(dev, ipvlan_handle_frame, port); + if (err) + goto err; + + dev->priv_flags |= IFF_IPVLAN_MASTER; + return 0; + +err: + kfree_rcu(port, rcu); + return err; +} + +static void ipvlan_port_destroy(struct net_device *dev) +{ + struct ipvl_port *port = ipvlan_port_get_rtnl(dev); + + dev->priv_flags &= ~IFF_IPVLAN_MASTER; + netdev_rx_handler_unregister(dev); + kfree_rcu(port, rcu); +} + +/* ipvlan network devices have devices nesting below it and are a special + * "super class" of normal network devices; split their locks off into a + * separate class since they always nest. + */ +static struct lock_class_key ipvlan_netdev_xmit_lock_key; +static struct lock_class_key ipvlan_netdev_addr_lock_key; + +#define IPVLAN_FEATURES \ + (NETIF_F_SG | NETIF_F_ALL_CSUM | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \ + NETIF_F_GSO | NETIF_F_TSO | NETIF_F_UFO | NETIF_F_GSO_ROBUST | \ + NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_GRO | NETIF_F_RXCSUM | \ + NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_STAG_FILTER) + +#define IPVLAN_STATE_MASK \ + ((1<<__LINK_STATE_NOCARRIER) | (1<<__LINK_STATE_DORMANT)) + +static void ipvlan_set_lockdep_class_one(struct net_device *dev, + struct netdev_queue *txq, + void *_unused) +{ + lockdep_set_class(&txq->_xmit_lock, &ipvlan_netdev_xmit_lock_key); +} + +static void ipvlan_set_lockdep_class(struct net_device *dev) +{ + lockdep_set_class(&dev->addr_list_lock, &ipvlan_netdev_addr_lock_key); + netdev_for_each_tx_queue(dev, ipvlan_set_lockdep_class_one, NULL); +} + +static int ipvlan_init(struct net_device *dev) +{ + struct ipvl_dev *ipvlan = netdev_priv(dev); + const struct net_device *phy_dev = ipvlan->phy_dev; + + dev->state = (dev->state & ~IPVLAN_STATE_MASK) | + (phy_dev->state & IPVLAN_STATE_MASK); + dev->features = phy_dev->features & IPVLAN_FEATURES; + dev->features |= NETIF_F_LLTX; + dev->gso_max_size = phy_dev->gso_max_size; + dev->iflink = phy_dev->ifindex; + dev->hard_header_len = phy_dev->hard_header_len; + + ipvlan_set_lockdep_class(dev); + + ipvlan->pcpu_stats = alloc_percpu(struct ipvl_pcpu_stats); + if (!ipvlan->pcpu_stats) + return -ENOMEM; + + return 0; +} + +static void ipvlan_uninit(struct net_device *dev) +{ + struct ipvl_dev *ipvlan = netdev_priv(dev); + struct ipvl_port *port = ipvlan->port; + + if (ipvlan->pcpu_stats) + free_percpu(ipvlan->pcpu_stats); + + port->count -= 1; + if (!port->count) + ipvlan_port_destroy(port->dev); +} + +static int ipvlan_open(struct net_device *dev) +{ + struct ipvl_dev *ipvlan = netdev_priv(dev); + struct net_device *phy_dev = ipvlan->phy_dev; + struct ipvl_addr *addr; + + if (ipvlan->port->mode == IPVLAN_MODE_L3) + dev->flags |= IFF_NOARP; + else + dev->flags &= ~IFF_NOARP; + + if (ipvlan->ipv6cnt > 0 || ipvlan->ipv4cnt > 0) { + list_for_each_entry(addr, &ipvlan->addrs, anode) + ipvlan_ht_addr_add(ipvlan, addr); + } + return dev_uc_add(phy_dev, phy_dev->dev_addr); +} + +static int ipvlan_stop(struct net_device *dev) +{ + struct ipvl_dev *ipvlan = netdev_priv(dev); + struct net_device *phy_dev = ipvlan->phy_dev; + struct ipvl_addr *addr; + + dev_uc_unsync(phy_dev, dev); + dev_mc_unsync(phy_dev, dev); + + dev_uc_del(phy_dev, phy_dev->dev_addr); + + if (ipvlan->ipv6cnt > 0 || ipvlan->ipv4cnt > 0) { + list_for_each_entry(addr, &ipvlan->addrs, anode) + ipvlan_ht_addr_del(addr, !dev->dismantle); + } + return 0; +} + +static netdev_tx_t ipvlan_start_xmit(struct sk_buff *skb, + struct net_device *dev) +{ + const struct ipvl_dev *ipvlan = netdev_priv(dev); + int skblen = skb->len; + int ret; + + ret = ipvlan_queue_xmit(skb, dev); + if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) { + struct ipvl_pcpu_stats *pcptr; + + pcptr = this_cpu_ptr(ipvlan->pcpu_stats); + + u64_stats_update_begin(&pcptr->syncp); + pcptr->tx_pkts++; + pcptr->tx_bytes += skblen; + u64_stats_update_end(&pcptr->syncp); + } else { + this_cpu_inc(ipvlan->pcpu_stats->tx_drps); + } + return ret; +} + +static netdev_features_t ipvlan_fix_features(struct net_device *dev, + netdev_features_t features) +{ + struct ipvl_dev *ipvlan = netdev_priv(dev); + + return features & (ipvlan->sfeatures | ~IPVLAN_FEATURES); +} + +static void ipvlan_change_rx_flags(struct net_device *dev, int change) +{ + struct ipvl_dev *ipvlan = netdev_priv(dev); + struct net_device *phy_dev = ipvlan->phy_dev; + + if (change & IFF_ALLMULTI) + dev_set_allmulti(phy_dev, dev->flags & IFF_ALLMULTI? 1 : -1); +} + +static void ipvlan_set_broadcast_mac_filter(struct ipvl_dev *ipvlan, bool set) +{ + struct net_device *dev = ipvlan->dev; + unsigned int hashbit = ipvlan_mac_hash(dev->broadcast); + + if (set && !test_bit(hashbit, ipvlan->mac_filters)) + __set_bit(hashbit, ipvlan->mac_filters); + else if (!set && test_bit(hashbit, ipvlan->mac_filters)) + __clear_bit(hashbit, ipvlan->mac_filters); +} + +static void ipvlan_set_multicast_mac_filter(struct net_device *dev) +{ + struct ipvl_dev *ipvlan = netdev_priv(dev); + + if (dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) { + bitmap_fill(ipvlan->mac_filters, IPVLAN_MAC_FILTER_SIZE); + } else { + struct netdev_hw_addr *ha; + DECLARE_BITMAP(mc_filters, IPVLAN_MAC_FILTER_SIZE); + + bitmap_zero(mc_filters, IPVLAN_MAC_FILTER_SIZE); + netdev_for_each_mc_addr(ha, dev) + __set_bit(ipvlan_mac_hash(ha->addr), mc_filters); + + bitmap_copy(ipvlan->mac_filters, mc_filters, + IPVLAN_MAC_FILTER_SIZE); + } + dev_uc_sync(ipvlan->phy_dev, dev); + dev_mc_sync(ipvlan->phy_dev, dev); +} + +static struct rtnl_link_stats64 *ipvlan_get_stats64(struct net_device *dev, + struct rtnl_link_stats64 *s) +{ + struct ipvl_dev *ipvlan = netdev_priv(dev); + + if (ipvlan->pcpu_stats) { + struct ipvl_pcpu_stats *pcptr; + u64 rx_pkts, rx_bytes, rx_mcast, tx_pkts, tx_bytes; + u32 rx_errs = 0, tx_drps = 0; + u32 strt; + int idx; + + for_each_possible_cpu(idx) { + pcptr = per_cpu_ptr(ipvlan->pcpu_stats, idx); + do { + strt= u64_stats_fetch_begin_irq(&pcptr->syncp); + rx_pkts = pcptr->rx_pkts; + rx_bytes = pcptr->rx_bytes; + rx_mcast = pcptr->rx_mcast; + tx_pkts = pcptr->tx_pkts; + tx_bytes = pcptr->tx_bytes; + } while (u64_stats_fetch_retry_irq(&pcptr->syncp, + strt)); + + s->rx_packets += rx_pkts; + s->rx_bytes += rx_bytes; + s->multicast += rx_mcast; + s->tx_packets += tx_pkts; + s->tx_bytes += tx_bytes; + + /* u32 values are updated without syncp protection. */ + rx_errs += pcptr->rx_errs; + tx_drps += pcptr->tx_drps; + } + s->rx_errors = rx_errs; + s->rx_dropped = rx_errs; + s->tx_dropped = tx_drps; + } + return s; +} + +static int ipvlan_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid) +{ + struct ipvl_dev *ipvlan = netdev_priv(dev); + struct net_device *phy_dev = ipvlan->phy_dev; + + return vlan_vid_add(phy_dev, proto, vid); +} + +static int ipvlan_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, + u16 vid) +{ + struct ipvl_dev *ipvlan = netdev_priv(dev); + struct net_device *phy_dev = ipvlan->phy_dev; + + vlan_vid_del(phy_dev, proto, vid); + return 0; +} + +static const struct net_device_ops ipvlan_netdev_ops = { + .ndo_init = ipvlan_init, + .ndo_uninit = ipvlan_uninit, + .ndo_open = ipvlan_open, + .ndo_stop = ipvlan_stop, + .ndo_start_xmit = ipvlan_start_xmit, + .ndo_fix_features = ipvlan_fix_features, + .ndo_change_rx_flags = ipvlan_change_rx_flags, + .ndo_set_rx_mode = ipvlan_set_multicast_mac_filter, + .ndo_get_stats64 = ipvlan_get_stats64, + .ndo_vlan_rx_add_vid = ipvlan_vlan_rx_add_vid, + .ndo_vlan_rx_kill_vid = ipvlan_vlan_rx_kill_vid, +}; + +static int ipvlan_hard_header(struct sk_buff *skb, struct net_device *dev, + unsigned short type, const void *daddr, + const void *saddr, unsigned len) +{ + const struct ipvl_dev *ipvlan = netdev_priv(dev); + struct net_device *phy_dev = ipvlan->phy_dev; + + /* TODO Probably use a different field than dev_addr so that the + * mac-address on the virtual device is portable and can be carried + * while the packets use the mac-addr on the physical device. + */ + return dev_hard_header(skb, phy_dev, type, daddr, + saddr ? : dev->dev_addr, len); +} + +static const struct header_ops ipvlan_header_ops = { + .create = ipvlan_hard_header, + .rebuild = eth_rebuild_header, + .parse = eth_header_parse, + .cache = eth_header_cache, + .cache_update = eth_header_cache_update, +}; + +static int ipvlan_ethtool_get_settings(struct net_device *dev, + struct ethtool_cmd *cmd) +{ + const struct ipvl_dev *ipvlan = netdev_priv(dev); + + return __ethtool_get_settings(ipvlan->phy_dev, cmd); +} + +static void ipvlan_ethtool_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *drvinfo) +{ + strlcpy(drvinfo->driver, IPVLAN_DRV, sizeof(drvinfo->driver)); + strlcpy(drvinfo->version, IPV_DRV_VER, sizeof(drvinfo->version)); +} + +static u32 ipvlan_ethtool_get_msglevel(struct net_device *dev) +{ + const struct ipvl_dev *ipvlan = netdev_priv(dev); + + return ipvlan->msg_enable; +} + +static void ipvlan_ethtool_set_msglevel(struct net_device *dev, u32 value) +{ + struct ipvl_dev *ipvlan = netdev_priv(dev); + + ipvlan->msg_enable = value; +} + +static const struct ethtool_ops ipvlan_ethtool_ops = { + .get_link = ethtool_op_get_link, + .get_settings = ipvlan_ethtool_get_settings, + .get_drvinfo = ipvlan_ethtool_get_drvinfo, + .get_msglevel = ipvlan_ethtool_get_msglevel, + .set_msglevel = ipvlan_ethtool_set_msglevel, +}; + +static int ipvlan_nl_changelink(struct net_device *dev, + struct nlattr *tb[], struct nlattr *data[]) +{ + struct ipvl_dev *ipvlan = netdev_priv(dev); + struct ipvl_port *port = ipvlan_port_get_rtnl(ipvlan->phy_dev); + + if (data && data[IFLA_IPVLAN_MODE]) { + u16 nmode = nla_get_u16(data[IFLA_IPVLAN_MODE]); + + ipvlan_set_port_mode(port, nmode); + } + return 0; +} + +static size_t ipvlan_nl_getsize(const struct net_device *dev) +{ + return (0 + + nla_total_size(2) /* IFLA_IPVLAN_MODE */ + ); +} + +static int ipvlan_nl_validate(struct nlattr *tb[], struct nlattr *data[]) +{ + if (data && data[IFLA_IPVLAN_MODE]) { + u16 mode = nla_get_u16(data[IFLA_IPVLAN_MODE]); + + if (mode < IPVLAN_MODE_L2 || mode >= IPVLAN_MODE_MAX) + return -EINVAL; + } + return 0; +} + +static int ipvlan_nl_fillinfo(struct sk_buff *skb, + const struct net_device *dev) +{ + struct ipvl_dev *ipvlan = netdev_priv(dev); + struct ipvl_port *port = ipvlan_port_get_rtnl(ipvlan->phy_dev); + int ret = -EINVAL; + + if (!port) + goto err; + + ret = -EMSGSIZE; + if (nla_put_u16(skb, IFLA_IPVLAN_MODE, port->mode)) + goto err; + + return 0; + +err: + return ret; +} + +static int ipvlan_link_new(struct net *src_net, struct net_device *dev, + struct nlattr *tb[], struct nlattr *data[]) +{ + struct ipvl_dev *ipvlan = netdev_priv(dev); + struct ipvl_port *port; + struct net_device *phy_dev; + int err; + + if (!tb[IFLA_LINK]) + return -EINVAL; + + phy_dev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK])); + if (!phy_dev) + return -ENODEV; + + if (ipvlan_dev_slave(phy_dev)) { + struct ipvl_dev *tmp = netdev_priv(phy_dev); + + phy_dev = tmp->phy_dev; + } else if (!ipvlan_dev_master(phy_dev)) { + err = ipvlan_port_create(phy_dev); + if (err < 0) + return err; + } + + port = ipvlan_port_get_rtnl(phy_dev); + if (data && data[IFLA_IPVLAN_MODE]) + port->mode = nla_get_u16(data[IFLA_IPVLAN_MODE]); + + ipvlan->phy_dev = phy_dev; + ipvlan->dev = dev; + ipvlan->port = port; + ipvlan->sfeatures = IPVLAN_FEATURES; + INIT_LIST_HEAD(&ipvlan->addrs); + ipvlan->ipv4cnt = 0; + ipvlan->ipv6cnt = 0; + + /* TODO Probably put random address here to be presented to the + * world but keep using the physical-dev address for the outgoing + * packets. + */ + memcpy(dev->dev_addr, phy_dev->dev_addr, ETH_ALEN); + + dev->priv_flags |= IFF_IPVLAN_SLAVE; + + port->count += 1; + err = register_netdevice(dev); + if (err < 0) + goto ipvlan_destroy_port; + + err = netdev_upper_dev_link(phy_dev, dev); + if (err) + goto ipvlan_destroy_port; + + list_add_tail_rcu(&ipvlan->pnode, &port->ipvlans); + netif_stacked_transfer_operstate(phy_dev, dev); + return 0; + +ipvlan_destroy_port: + port->count -= 1; + if (!port->count) + ipvlan_port_destroy(phy_dev); + + return err; +} + +static void ipvlan_link_delete(struct net_device *dev, struct list_head *head) +{ + struct ipvl_dev *ipvlan = netdev_priv(dev); + struct ipvl_addr *addr, *next; + + if (ipvlan->ipv6cnt > 0 || ipvlan->ipv4cnt > 0) { + list_for_each_entry_safe(addr, next, &ipvlan->addrs, anode) { + ipvlan_ht_addr_del(addr, !dev->dismantle); + list_del_rcu(&addr->anode); + } + } + list_del_rcu(&ipvlan->pnode); + unregister_netdevice_queue(dev, head); + netdev_upper_dev_unlink(ipvlan->phy_dev, dev); +} + +static void ipvlan_link_setup(struct net_device *dev) +{ + ether_setup(dev); + + dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING); + dev->priv_flags |= IFF_UNICAST_FLT; + dev->netdev_ops = &ipvlan_netdev_ops; + dev->destructor = free_netdev; + dev->header_ops = &ipvlan_header_ops; + dev->ethtool_ops = &ipvlan_ethtool_ops; + dev->tx_queue_len = 0; +} + +static const struct nla_policy ipvlan_nl_policy[IFLA_IPVLAN_MAX + 1] = +{ + [IFLA_IPVLAN_MODE] = { .type = NLA_U16 }, +}; + +static struct rtnl_link_ops ipvlan_link_ops = { + .kind = "ipvlan", + .priv_size = sizeof(struct ipvl_dev), + + .get_size = ipvlan_nl_getsize, + .policy = ipvlan_nl_policy, + .validate = ipvlan_nl_validate, + .fill_info = ipvlan_nl_fillinfo, + .changelink = ipvlan_nl_changelink, + .maxtype = IFLA_IPVLAN_MAX, + + .setup = ipvlan_link_setup, + .newlink = ipvlan_link_new, + .dellink = ipvlan_link_delete, +}; + +static int ipvlan_link_register(struct rtnl_link_ops *ops) +{ + return rtnl_link_register(ops); +} + +static int ipvlan_device_event(struct notifier_block *unused, + unsigned long event, void *ptr) +{ + struct net_device *dev = netdev_notifier_info_to_dev(ptr); + struct ipvl_dev *ipvlan, *next; + struct ipvl_port *port; + LIST_HEAD(lst_kill); + + if (!ipvlan_dev_master(dev)) + return NOTIFY_DONE; + + port = ipvlan_port_get_rtnl(dev); + + switch (event) { + case NETDEV_CHANGE: + list_for_each_entry(ipvlan, &port->ipvlans, pnode) + netif_stacked_transfer_operstate(ipvlan->phy_dev, + ipvlan->dev); + break; + + case NETDEV_UNREGISTER: + if (dev->reg_state != NETREG_UNREGISTERING) + break; + + list_for_each_entry_safe(ipvlan, next, &port->ipvlans, + pnode) + ipvlan->dev->rtnl_link_ops->dellink(ipvlan->dev, + &lst_kill); + unregister_netdevice_many(&lst_kill); + break; + + case NETDEV_FEAT_CHANGE: + list_for_each_entry(ipvlan, &port->ipvlans, pnode) { + ipvlan->dev->features = dev->features & IPVLAN_FEATURES; + ipvlan->dev->gso_max_size = dev->gso_max_size; + netdev_features_change(ipvlan->dev); + } + break; + + case NETDEV_CHANGEMTU: + list_for_each_entry(ipvlan, &port->ipvlans, pnode) + ipvlan_adjust_mtu(ipvlan, dev); + break; + + case NETDEV_PRE_TYPE_CHANGE: + /* Forbid underlying device to change its type. */ + return NOTIFY_BAD; + } + return NOTIFY_DONE; +} + +static int ipvlan_add_addr6(struct ipvl_dev *ipvlan, struct in6_addr *ip6_addr) +{ + struct ipvl_addr *addr; + + if (ipvlan_addr_busy(ipvlan, ip6_addr, true)) { + netif_err(ipvlan, ifup, ipvlan->dev, + "Failed to add IPv6=%pI6c addr for %s intf\n", + ip6_addr, ipvlan->dev->name); + return -EINVAL; + } + addr = kzalloc(sizeof(struct ipvl_addr), GFP_ATOMIC); + if (!addr) + return -ENOMEM; + + addr->master = ipvlan; + memcpy(&addr->ip6addr, ip6_addr, sizeof(struct in6_addr)); + addr->atype = IPVL_IPV6; + list_add_tail_rcu(&addr->anode, &ipvlan->addrs); + ipvlan->ipv6cnt++; + ipvlan_ht_addr_add(ipvlan, addr); + + return 0; +} + +static void ipvlan_del_addr6(struct ipvl_dev *ipvlan, struct in6_addr *ip6_addr) +{ + struct ipvl_addr *addr; + + addr = ipvlan_ht_addr_lookup(ipvlan->port, ip6_addr, true); + if (!addr) + return; + + ipvlan_ht_addr_del(addr, true); + list_del_rcu(&addr->anode); + ipvlan->ipv6cnt--; + WARN_ON(ipvlan->ipv6cnt < 0); + kfree_rcu(addr, rcu); + + return; +} + +static int ipvlan_addr6_event(struct notifier_block *unused, + unsigned long event, void *ptr) +{ + struct inet6_ifaddr *if6 = (struct inet6_ifaddr *)ptr; + struct net_device *dev = (struct net_device *)if6->idev->dev; + struct ipvl_dev *ipvlan = netdev_priv(dev); + + if (!ipvlan_dev_slave(dev)) + return NOTIFY_DONE; + + if (!ipvlan || !ipvlan->port) + return NOTIFY_DONE; + + switch (event) { + case NETDEV_UP: + if (ipvlan_add_addr6(ipvlan, &if6->addr)) + return NOTIFY_BAD; + break; + + case NETDEV_DOWN: + ipvlan_del_addr6(ipvlan, &if6->addr); + break; + } + + return NOTIFY_OK; +} + +static int ipvlan_add_addr4(struct ipvl_dev *ipvlan, struct in_addr *ip4_addr) +{ + struct ipvl_addr *addr; + + if (ipvlan_addr_busy(ipvlan, ip4_addr, false)) { + netif_err(ipvlan, ifup, ipvlan->dev, + "Failed to add IPv4=%pI4 on %s intf.\n", + ip4_addr, ipvlan->dev->name); + return -EINVAL; + } + addr = kzalloc(sizeof(struct ipvl_addr), GFP_KERNEL); + if (!addr) + return -ENOMEM; + + addr->master = ipvlan; + memcpy(&addr->ip4addr, ip4_addr, sizeof(struct in_addr)); + addr->atype = IPVL_IPV4; + list_add_tail_rcu(&addr->anode, &ipvlan->addrs); + ipvlan->ipv4cnt++; + ipvlan_ht_addr_add(ipvlan, addr); + ipvlan_set_broadcast_mac_filter(ipvlan, true); + + return 0; +} + +static void ipvlan_del_addr4(struct ipvl_dev *ipvlan, struct in_addr *ip4_addr) +{ + struct ipvl_addr *addr; + + addr = ipvlan_ht_addr_lookup(ipvlan->port, ip4_addr, false); + if (!addr) + return; + + ipvlan_ht_addr_del(addr, true); + list_del_rcu(&addr->anode); + ipvlan->ipv4cnt--; + WARN_ON(ipvlan->ipv4cnt < 0); + if (!ipvlan->ipv4cnt) + ipvlan_set_broadcast_mac_filter(ipvlan, false); + kfree_rcu(addr, rcu); + + return; +} + +static int ipvlan_addr4_event(struct notifier_block *unused, + unsigned long event, void *ptr) +{ + struct in_ifaddr *if4 = (struct in_ifaddr *)ptr; + struct net_device *dev = (struct net_device *)if4->ifa_dev->dev; + struct ipvl_dev *ipvlan = netdev_priv(dev); + struct in_addr ip4_addr; + + if (!ipvlan_dev_slave(dev)) + return NOTIFY_DONE; + + if (!ipvlan || !ipvlan->port) + return NOTIFY_DONE; + + switch (event) { + case NETDEV_UP: + ip4_addr.s_addr = if4->ifa_address; + if (ipvlan_add_addr4(ipvlan, &ip4_addr)) + return NOTIFY_BAD; + break; + + case NETDEV_DOWN: + ip4_addr.s_addr = if4->ifa_address; + ipvlan_del_addr4(ipvlan, &ip4_addr); + break; + } + + return NOTIFY_OK; +} + +static struct notifier_block ipvlan_addr4_notifier_block __read_mostly = { + .notifier_call = ipvlan_addr4_event, +}; + +static struct notifier_block ipvlan_notifier_block __read_mostly = { + .notifier_call = ipvlan_device_event, +}; + +static struct notifier_block ipvlan_addr6_notifier_block __read_mostly = { + .notifier_call = ipvlan_addr6_event, +}; + +static int __init ipvlan_init_module(void) +{ + int err; + + ipvlan_init_secret(); + register_netdevice_notifier(&ipvlan_notifier_block); + register_inet6addr_notifier(&ipvlan_addr6_notifier_block); + register_inetaddr_notifier(&ipvlan_addr4_notifier_block); + + err = ipvlan_link_register(&ipvlan_link_ops); + if (err < 0) + goto error; + + return 0; +error: + unregister_inetaddr_notifier(&ipvlan_addr4_notifier_block); + unregister_inet6addr_notifier(&ipvlan_addr6_notifier_block); + unregister_netdevice_notifier(&ipvlan_notifier_block); + return err; +} + +static void __exit ipvlan_cleanup_module(void) +{ + rtnl_link_unregister(&ipvlan_link_ops); + unregister_netdevice_notifier(&ipvlan_notifier_block); + unregister_inetaddr_notifier(&ipvlan_addr4_notifier_block); + unregister_inet6addr_notifier(&ipvlan_addr6_notifier_block); +} + +module_init(ipvlan_init_module); +module_exit(ipvlan_cleanup_module); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mahesh Bandewar <maheshb@google.com>"); +MODULE_DESCRIPTION("Driver for L3 (IPv6/IPv4) based VLANs"); +MODULE_ALIAS_RTNL_LINK("ipvlan"); diff --git a/drivers/net/irda/act200l-sir.c b/drivers/net/irda/act200l-sir.c index 8ff084f1d236..e8917511e1aa 100644 --- a/drivers/net/irda/act200l-sir.c +++ b/drivers/net/irda/act200l-sir.c @@ -107,8 +107,6 @@ static int act200l_open(struct sir_dev *dev) { struct qos_info *qos = &dev->qos; - IRDA_DEBUG(2, "%s()\n", __func__ ); - /* Power on the dongle */ sirdev_set_dtr_rts(dev, TRUE, TRUE); @@ -124,8 +122,6 @@ static int act200l_open(struct sir_dev *dev) static int act200l_close(struct sir_dev *dev) { - IRDA_DEBUG(2, "%s()\n", __func__ ); - /* Power off the dongle */ sirdev_set_dtr_rts(dev, FALSE, FALSE); @@ -143,8 +139,6 @@ static int act200l_change_speed(struct sir_dev *dev, unsigned speed) u8 control[3]; int ret = 0; - IRDA_DEBUG(2, "%s()\n", __func__ ); - /* Clear DTR and set RTS to enter command mode */ sirdev_set_dtr_rts(dev, FALSE, TRUE); @@ -212,8 +206,6 @@ static int act200l_reset(struct sir_dev *dev) }; int ret = 0; - IRDA_DEBUG(2, "%s()\n", __func__ ); - switch (state) { case SIRDEV_STATE_DONGLE_RESET: /* Reset the dongle : set RTS low for 25 ms */ @@ -240,7 +232,8 @@ static int act200l_reset(struct sir_dev *dev) dev->speed = 9600; break; default: - IRDA_ERROR("%s(), unknown state %d\n", __func__, state); + net_err_ratelimited("%s(), unknown state %d\n", + __func__, state); ret = -1; break; } diff --git a/drivers/net/irda/actisys-sir.c b/drivers/net/irda/actisys-sir.c index 50b2141a6103..e224b8b99517 100644 --- a/drivers/net/irda/actisys-sir.c +++ b/drivers/net/irda/actisys-sir.c @@ -165,8 +165,7 @@ static int actisys_change_speed(struct sir_dev *dev, unsigned speed) int ret = 0; int i = 0; - IRDA_DEBUG(4, "%s(), speed=%d (was %d)\n", __func__, - speed, dev->speed); + pr_debug("%s(), speed=%d (was %d)\n", __func__, speed, dev->speed); /* dongle was already resetted from irda_request state machine, * we are in known state (dongle default) diff --git a/drivers/net/irda/ali-ircc.c b/drivers/net/irda/ali-ircc.c index befa45f809c3..588680a72fa1 100644 --- a/drivers/net/irda/ali-ircc.c +++ b/drivers/net/irda/ali-ircc.c @@ -154,12 +154,10 @@ static int __init ali_ircc_init(void) int reg, revision; int i = 0; - IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __func__); - ret = platform_driver_register(&ali_ircc_driver); if (ret) { - IRDA_ERROR("%s, Can't register driver!\n", - ALI_IRCC_DRIVER_NAME); + net_err_ratelimited("%s, Can't register driver!\n", + ALI_IRCC_DRIVER_NAME); return ret; } @@ -168,7 +166,7 @@ static int __init ali_ircc_init(void) /* Probe for all the ALi chipsets we know about */ for (chip= chips; chip->name; chip++, i++) { - IRDA_DEBUG(2, "%s(), Probing for %s ...\n", __func__, chip->name); + pr_debug("%s(), Probing for %s ...\n", __func__, chip->name); /* Try all config registers for this chip */ for (cfg=0; cfg<2; cfg++) @@ -198,12 +196,13 @@ static int __init ali_ircc_init(void) if (reg == chip->cid_value) { - IRDA_DEBUG(2, "%s(), Chip found at 0x%03x\n", __func__, cfg_base); + pr_debug("%s(), Chip found at 0x%03x\n", + __func__, cfg_base); outb(0x1F, cfg_base); revision = inb(cfg_base+1); - IRDA_DEBUG(2, "%s(), Found %s chip, revision=%d\n", __func__, - chip->name, revision); + pr_debug("%s(), Found %s chip, revision=%d\n", + __func__, chip->name, revision); /* * If the user supplies the base address, then @@ -225,15 +224,14 @@ static int __init ali_ircc_init(void) } else { - IRDA_DEBUG(2, "%s(), No %s chip at 0x%03x\n", __func__, chip->name, cfg_base); + pr_debug("%s(), No %s chip at 0x%03x\n", + __func__, chip->name, cfg_base); } /* Exit configuration */ outb(0xbb, cfg_base); } } - IRDA_DEBUG(2, "%s(), ----------------- End -----------------\n", __func__); - if (ret) platform_driver_unregister(&ali_ircc_driver); @@ -250,8 +248,6 @@ static void __exit ali_ircc_cleanup(void) { int i; - IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __func__); - for (i=0; i < ARRAY_SIZE(dev_self); i++) { if (dev_self[i]) ali_ircc_close(dev_self[i]); @@ -259,7 +255,6 @@ static void __exit ali_ircc_cleanup(void) platform_driver_unregister(&ali_ircc_driver); - IRDA_DEBUG(2, "%s(), ----------------- End -----------------\n", __func__); } static const struct net_device_ops ali_ircc_sir_ops = { @@ -289,11 +284,9 @@ static int ali_ircc_open(int i, chipio_t *info) int dongle_id; int err; - IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __func__); - if (i >= ARRAY_SIZE(dev_self)) { - IRDA_ERROR("%s(), maximum number of supported chips reached!\n", - __func__); + net_err_ratelimited("%s(), maximum number of supported chips reached!\n", + __func__); return -ENOMEM; } @@ -303,8 +296,8 @@ static int ali_ircc_open(int i, chipio_t *info) dev = alloc_irdadev(sizeof(*self)); if (dev == NULL) { - IRDA_ERROR("%s(), can't allocate memory for control block!\n", - __func__); + net_err_ratelimited("%s(), can't allocate memory for control block!\n", + __func__); return -ENOMEM; } @@ -328,8 +321,8 @@ static int ali_ircc_open(int i, chipio_t *info) /* Reserve the ioports that we need */ if (!request_region(self->io.fir_base, self->io.fir_ext, ALI_IRCC_DRIVER_NAME)) { - IRDA_WARNING("%s(), can't get iobase of 0x%03x\n", __func__, - self->io.fir_base); + net_warn_ratelimited("%s(), can't get iobase of 0x%03x\n", + __func__, self->io.fir_base); err = -ENODEV; goto err_out1; } @@ -380,19 +373,20 @@ static int ali_ircc_open(int i, chipio_t *info) err = register_netdev(dev); if (err) { - IRDA_ERROR("%s(), register_netdev() failed!\n", __func__); + net_err_ratelimited("%s(), register_netdev() failed!\n", + __func__); goto err_out4; } - IRDA_MESSAGE("IrDA: Registered device %s\n", dev->name); + net_info_ratelimited("IrDA: Registered device %s\n", dev->name); /* Check dongle id */ dongle_id = ali_ircc_read_dongle_id(i, info); - IRDA_MESSAGE("%s(), %s, Found dongle: %s\n", __func__, - ALI_IRCC_DRIVER_NAME, dongle_types[dongle_id]); + net_info_ratelimited("%s(), %s, Found dongle: %s\n", + __func__, ALI_IRCC_DRIVER_NAME, + dongle_types[dongle_id]); self->io.dongle_id = dongle_id; - IRDA_DEBUG(2, "%s(), ----------------- End -----------------\n", __func__); return 0; @@ -421,8 +415,6 @@ static int __exit ali_ircc_close(struct ali_ircc_cb *self) { int iobase; - IRDA_DEBUG(4, "%s(), ---------------- Start ----------------\n", __func__); - IRDA_ASSERT(self != NULL, return -1;); iobase = self->io.fir_base; @@ -431,7 +423,7 @@ static int __exit ali_ircc_close(struct ali_ircc_cb *self) unregister_netdev(self->netdev); /* Release the PORT that this driver is using */ - IRDA_DEBUG(4, "%s(), Releasing Region %03x\n", __func__, self->io.fir_base); + pr_debug("%s(), Releasing Region %03x\n", __func__, self->io.fir_base); release_region(self->io.fir_base, self->io.fir_ext); if (self->tx_buff.head) @@ -445,7 +437,6 @@ static int __exit ali_ircc_close(struct ali_ircc_cb *self) dev_self[self->index] = NULL; free_netdev(self->netdev); - IRDA_DEBUG(2, "%s(), ----------------- End -----------------\n", __func__); return 0; } @@ -488,7 +479,6 @@ static int ali_ircc_probe_53(ali_chip_t *chip, chipio_t *info) int cfg_base = info->cfg_base; int hi, low, reg; - IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __func__); /* Enter Configuration */ outb(chip->entr1, cfg_base); @@ -507,13 +497,13 @@ static int ali_ircc_probe_53(ali_chip_t *chip, chipio_t *info) info->sir_base = info->fir_base; - IRDA_DEBUG(2, "%s(), probing fir_base=0x%03x\n", __func__, info->fir_base); + pr_debug("%s(), probing fir_base=0x%03x\n", __func__, info->fir_base); /* Read IRQ control register */ outb(0x70, cfg_base); reg = inb(cfg_base+1); info->irq = reg & 0x0f; - IRDA_DEBUG(2, "%s(), probing irq=%d\n", __func__, info->irq); + pr_debug("%s(), probing irq=%d\n", __func__, info->irq); /* Read DMA channel */ outb(0x74, cfg_base); @@ -521,26 +511,26 @@ static int ali_ircc_probe_53(ali_chip_t *chip, chipio_t *info) info->dma = reg & 0x07; if(info->dma == 0x04) - IRDA_WARNING("%s(), No DMA channel assigned !\n", __func__); + net_warn_ratelimited("%s(), No DMA channel assigned !\n", + __func__); else - IRDA_DEBUG(2, "%s(), probing dma=%d\n", __func__, info->dma); + pr_debug("%s(), probing dma=%d\n", __func__, info->dma); /* Read Enabled Status */ outb(0x30, cfg_base); reg = inb(cfg_base+1); info->enabled = (reg & 0x80) && (reg & 0x01); - IRDA_DEBUG(2, "%s(), probing enabled=%d\n", __func__, info->enabled); + pr_debug("%s(), probing enabled=%d\n", __func__, info->enabled); /* Read Power Status */ outb(0x22, cfg_base); reg = inb(cfg_base+1); info->suspended = (reg & 0x20); - IRDA_DEBUG(2, "%s(), probing suspended=%d\n", __func__, info->suspended); + pr_debug("%s(), probing suspended=%d\n", __func__, info->suspended); /* Exit configuration */ outb(0xbb, cfg_base); - IRDA_DEBUG(2, "%s(), ----------------- End -----------------\n", __func__); return 0; } @@ -558,7 +548,6 @@ static int ali_ircc_setup(chipio_t *info) int version; int iobase = info->fir_base; - IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __func__); /* Locking comments : * Most operations here need to be protected. We are called before @@ -578,8 +567,8 @@ static int ali_ircc_setup(chipio_t *info) /* Should be 0x00 in the M1535/M1535D */ if(version != 0x00) { - IRDA_ERROR("%s, Wrong chip version %02x\n", - ALI_IRCC_DRIVER_NAME, version); + net_err_ratelimited("%s, Wrong chip version %02x\n", + ALI_IRCC_DRIVER_NAME, version); return -1; } @@ -612,14 +601,13 @@ static int ali_ircc_setup(chipio_t *info) /* Switch to SIR space */ FIR2SIR(iobase); - IRDA_MESSAGE("%s, driver loaded (Benjamin Kong)\n", - ALI_IRCC_DRIVER_NAME); + net_info_ratelimited("%s, driver loaded (Benjamin Kong)\n", + ALI_IRCC_DRIVER_NAME); /* Enable receive interrupts */ // outb(UART_IER_RDI, iobase+UART_IER); //benjamin 2000/11/23 01:25PM // Turn on the interrupts in ali_ircc_net_open - IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __func__); return 0; } @@ -636,7 +624,6 @@ static int ali_ircc_read_dongle_id (int i, chipio_t *info) int dongle_id, reg; int cfg_base = info->cfg_base; - IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __func__); /* Enter Configuration */ outb(chips[i].entr1, cfg_base); @@ -650,13 +637,12 @@ static int ali_ircc_read_dongle_id (int i, chipio_t *info) outb(0xf0, cfg_base); reg = inb(cfg_base+1); dongle_id = ((reg>>6)&0x02) | ((reg>>5)&0x01); - IRDA_DEBUG(2, "%s(), probing dongle_id=%d, dongle_types=%s\n", __func__, - dongle_id, dongle_types[dongle_id]); + pr_debug("%s(), probing dongle_id=%d, dongle_types=%s\n", + __func__, dongle_id, dongle_types[dongle_id]); /* Exit configuration */ outb(0xbb, cfg_base); - IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __func__); return dongle_id; } @@ -673,7 +659,6 @@ static irqreturn_t ali_ircc_interrupt(int irq, void *dev_id) struct ali_ircc_cb *self; int ret; - IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __func__); self = netdev_priv(dev); @@ -687,7 +672,6 @@ static irqreturn_t ali_ircc_interrupt(int irq, void *dev_id) spin_unlock(&self->lock); - IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __func__); return ret; } /* @@ -701,7 +685,6 @@ static irqreturn_t ali_ircc_fir_interrupt(struct ali_ircc_cb *self) __u8 eir, OldMessageCount; int iobase, tmp; - IRDA_DEBUG(1, "%s(), ---------------- Start ----------------\n", __func__); iobase = self->io.fir_base; @@ -714,10 +697,10 @@ static irqreturn_t ali_ircc_fir_interrupt(struct ali_ircc_cb *self) //self->ier = inb(iobase+FIR_IER); 2000/12/1 04:32PM eir = self->InterruptID & self->ier; /* Mask out the interesting ones */ - IRDA_DEBUG(1, "%s(), self->InterruptID = %x\n", __func__,self->InterruptID); - IRDA_DEBUG(1, "%s(), self->LineStatus = %x\n", __func__,self->LineStatus); - IRDA_DEBUG(1, "%s(), self->ier = %x\n", __func__,self->ier); - IRDA_DEBUG(1, "%s(), eir = %x\n", __func__,eir); + pr_debug("%s(), self->InterruptID = %x\n", __func__, self->InterruptID); + pr_debug("%s(), self->LineStatus = %x\n", __func__, self->LineStatus); + pr_debug("%s(), self->ier = %x\n", __func__, self->ier); + pr_debug("%s(), eir = %x\n", __func__, eir); /* Disable interrupts */ SetCOMInterrupts(self, FALSE); @@ -728,7 +711,8 @@ static irqreturn_t ali_ircc_fir_interrupt(struct ali_ircc_cb *self) { if (self->io.direction == IO_XMIT) /* TX */ { - IRDA_DEBUG(1, "%s(), ******* IIR_EOM (Tx) *******\n", __func__); + pr_debug("%s(), ******* IIR_EOM (Tx) *******\n", + __func__); if(ali_ircc_dma_xmit_complete(self)) { @@ -747,23 +731,27 @@ static irqreturn_t ali_ircc_fir_interrupt(struct ali_ircc_cb *self) } else /* RX */ { - IRDA_DEBUG(1, "%s(), ******* IIR_EOM (Rx) *******\n", __func__); + pr_debug("%s(), ******* IIR_EOM (Rx) *******\n", + __func__); if(OldMessageCount > ((self->LineStatus+1) & 0x07)) { self->rcvFramesOverflow = TRUE; - IRDA_DEBUG(1, "%s(), ******* self->rcvFramesOverflow = TRUE ********\n", __func__); + pr_debug("%s(), ******* self->rcvFramesOverflow = TRUE ********\n", + __func__); } if (ali_ircc_dma_receive_complete(self)) { - IRDA_DEBUG(1, "%s(), ******* receive complete ********\n", __func__); + pr_debug("%s(), ******* receive complete ********\n", + __func__); self->ier = IER_EOM; } else { - IRDA_DEBUG(1, "%s(), ******* Not receive complete ********\n", __func__); + pr_debug("%s(), ******* Not receive complete ********\n", + __func__); self->ier = IER_EOM | IER_TIMER; } @@ -776,7 +764,8 @@ static irqreturn_t ali_ircc_fir_interrupt(struct ali_ircc_cb *self) if(OldMessageCount > ((self->LineStatus+1) & 0x07)) { self->rcvFramesOverflow = TRUE; - IRDA_DEBUG(1, "%s(), ******* self->rcvFramesOverflow = TRUE *******\n", __func__); + pr_debug("%s(), ******* self->rcvFramesOverflow = TRUE *******\n", + __func__); } /* Disable Timer */ switch_bank(iobase, BANK1); @@ -808,7 +797,6 @@ static irqreturn_t ali_ircc_fir_interrupt(struct ali_ircc_cb *self) /* Restore Interrupt */ SetCOMInterrupts(self, TRUE); - IRDA_DEBUG(1, "%s(), ----------------- End ---------------\n", __func__); return IRQ_RETVAL(eir); } @@ -823,7 +811,6 @@ static irqreturn_t ali_ircc_sir_interrupt(struct ali_ircc_cb *self) int iobase; int iir, lsr; - IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __func__); iobase = self->io.sir_base; @@ -832,13 +819,13 @@ static irqreturn_t ali_ircc_sir_interrupt(struct ali_ircc_cb *self) /* Clear interrupt */ lsr = inb(iobase+UART_LSR); - IRDA_DEBUG(4, "%s(), iir=%02x, lsr=%02x, iobase=%#x\n", __func__, - iir, lsr, iobase); + pr_debug("%s(), iir=%02x, lsr=%02x, iobase=%#x\n", + __func__, iir, lsr, iobase); switch (iir) { case UART_IIR_RLSI: - IRDA_DEBUG(2, "%s(), RLSI\n", __func__); + pr_debug("%s(), RLSI\n", __func__); break; case UART_IIR_RDI: /* Receive interrupt */ @@ -852,15 +839,14 @@ static irqreturn_t ali_ircc_sir_interrupt(struct ali_ircc_cb *self) } break; default: - IRDA_DEBUG(0, "%s(), unhandled IIR=%#x\n", __func__, iir); + pr_debug("%s(), unhandled IIR=%#x\n", + __func__, iir); break; } } - IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __func__); - return IRQ_RETVAL(iir); } @@ -876,7 +862,6 @@ static void ali_ircc_sir_receive(struct ali_ircc_cb *self) int boguscount = 0; int iobase; - IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __func__); IRDA_ASSERT(self != NULL, return;); iobase = self->io.sir_base; @@ -891,12 +876,11 @@ static void ali_ircc_sir_receive(struct ali_ircc_cb *self) /* Make sure we don't stay here too long */ if (boguscount++ > 32) { - IRDA_DEBUG(2,"%s(), breaking!\n", __func__); + pr_debug("%s(), breaking!\n", __func__); break; } } while (inb(iobase+UART_LSR) & UART_LSR_DR); - IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __func__ ); } /* @@ -913,7 +897,6 @@ static void ali_ircc_sir_write_wakeup(struct ali_ircc_cb *self) IRDA_ASSERT(self != NULL, return;); - IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __func__ ); iobase = self->io.sir_base; @@ -932,16 +915,18 @@ static void ali_ircc_sir_write_wakeup(struct ali_ircc_cb *self) { /* We must wait until all data are gone */ while(!(inb(iobase+UART_LSR) & UART_LSR_TEMT)) - IRDA_DEBUG(1, "%s(), UART_LSR_THRE\n", __func__ ); + pr_debug("%s(), UART_LSR_THRE\n", __func__); - IRDA_DEBUG(1, "%s(), Changing speed! self->new_speed = %d\n", __func__ , self->new_speed); + pr_debug("%s(), Changing speed! self->new_speed = %d\n", + __func__, self->new_speed); ali_ircc_change_speed(self, self->new_speed); self->new_speed = 0; // benjamin 2000/11/10 06:32PM if (self->io.speed > 115200) { - IRDA_DEBUG(2, "%s(), ali_ircc_change_speed from UART_LSR_TEMT\n", __func__ ); + pr_debug("%s(), ali_ircc_change_speed from UART_LSR_TEMT\n", + __func__); self->ier = IER_EOM; // SetCOMInterrupts(self, TRUE); @@ -959,7 +944,6 @@ static void ali_ircc_sir_write_wakeup(struct ali_ircc_cb *self) outb(UART_IER_RDI, iobase+UART_IER); } - IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __func__ ); } static void ali_ircc_change_speed(struct ali_ircc_cb *self, __u32 baud) @@ -967,9 +951,8 @@ static void ali_ircc_change_speed(struct ali_ircc_cb *self, __u32 baud) struct net_device *dev = self->netdev; int iobase; - IRDA_DEBUG(1, "%s(), ---------------- Start ----------------\n", __func__ ); - IRDA_DEBUG(2, "%s(), setting speed = %d\n", __func__ , baud); + pr_debug("%s(), setting speed = %d\n", __func__, baud); /* This function *must* be called with irq off and spin-lock. * - Jean II */ @@ -1008,7 +991,6 @@ static void ali_ircc_change_speed(struct ali_ircc_cb *self, __u32 baud) netif_wake_queue(self->netdev); - IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __func__ ); } static void ali_ircc_fir_change_speed(struct ali_ircc_cb *priv, __u32 baud) @@ -1018,14 +1000,14 @@ static void ali_ircc_fir_change_speed(struct ali_ircc_cb *priv, __u32 baud) struct ali_ircc_cb *self = priv; struct net_device *dev; - IRDA_DEBUG(1, "%s(), ---------------- Start ----------------\n", __func__ ); IRDA_ASSERT(self != NULL, return;); dev = self->netdev; iobase = self->io.fir_base; - IRDA_DEBUG(1, "%s(), self->io.speed = %d, change to speed = %d\n", __func__ ,self->io.speed,baud); + pr_debug("%s(), self->io.speed = %d, change to speed = %d\n", + __func__, self->io.speed, baud); /* Come from SIR speed */ if(self->io.speed <=115200) @@ -1039,7 +1021,6 @@ static void ali_ircc_fir_change_speed(struct ali_ircc_cb *priv, __u32 baud) // Set Dongle Speed mode ali_ircc_change_dongle_speed(self, baud); - IRDA_DEBUG(1, "%s(), ----------------- End ------------------\n", __func__ ); } /* @@ -1057,9 +1038,8 @@ static void ali_ircc_sir_change_speed(struct ali_ircc_cb *priv, __u32 speed) int lcr; /* Line control reg */ int divisor; - IRDA_DEBUG(1, "%s(), ---------------- Start ----------------\n", __func__ ); - IRDA_DEBUG(1, "%s(), Setting speed to: %d\n", __func__ , speed); + pr_debug("%s(), Setting speed to: %d\n", __func__, speed); IRDA_ASSERT(self != NULL, return;); @@ -1113,7 +1093,6 @@ static void ali_ircc_sir_change_speed(struct ali_ircc_cb *priv, __u32 speed) spin_unlock_irqrestore(&self->lock, flags); - IRDA_DEBUG(1, "%s(), ----------------- End ------------------\n", __func__ ); } static void ali_ircc_change_dongle_speed(struct ali_ircc_cb *priv, int speed) @@ -1123,14 +1102,14 @@ static void ali_ircc_change_dongle_speed(struct ali_ircc_cb *priv, int speed) int iobase,dongle_id; int tmp = 0; - IRDA_DEBUG(1, "%s(), ---------------- Start ----------------\n", __func__ ); iobase = self->io.fir_base; /* or iobase = self->io.sir_base; */ dongle_id = self->io.dongle_id; /* We are already locked, no need to do it again */ - IRDA_DEBUG(1, "%s(), Set Speed for %s , Speed = %d\n", __func__ , dongle_types[dongle_id], speed); + pr_debug("%s(), Set Speed for %s , Speed = %d\n", + __func__, dongle_types[dongle_id], speed); switch_bank(iobase, BANK2); tmp = inb(iobase+FIR_IRDA_CR); @@ -1294,7 +1273,6 @@ static void ali_ircc_change_dongle_speed(struct ali_ircc_cb *priv, int speed) switch_bank(iobase, BANK0); - IRDA_DEBUG(1, "%s(), ----------------- End ------------------\n", __func__ ); } /* @@ -1307,11 +1285,10 @@ static int ali_ircc_sir_write(int iobase, int fifo_size, __u8 *buf, int len) { int actual = 0; - IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __func__ ); /* Tx FIFO should be empty! */ if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) { - IRDA_DEBUG(0, "%s(), failed, fifo not empty!\n", __func__ ); + pr_debug("%s(), failed, fifo not empty!\n", __func__); return 0; } @@ -1323,7 +1300,6 @@ static int ali_ircc_sir_write(int iobase, int fifo_size, __u8 *buf, int len) actual++; } - IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __func__ ); return actual; } @@ -1339,7 +1315,6 @@ static int ali_ircc_net_open(struct net_device *dev) int iobase; char hwname[32]; - IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __func__ ); IRDA_ASSERT(dev != NULL, return -1;); @@ -1352,9 +1327,8 @@ static int ali_ircc_net_open(struct net_device *dev) /* Request IRQ and install Interrupt Handler */ if (request_irq(self->io.irq, ali_ircc_interrupt, 0, dev->name, dev)) { - IRDA_WARNING("%s, unable to allocate irq=%d\n", - ALI_IRCC_DRIVER_NAME, - self->io.irq); + net_warn_ratelimited("%s, unable to allocate irq=%d\n", + ALI_IRCC_DRIVER_NAME, self->io.irq); return -EAGAIN; } @@ -1363,9 +1337,8 @@ static int ali_ircc_net_open(struct net_device *dev) * failure. */ if (request_dma(self->io.dma, dev->name)) { - IRDA_WARNING("%s, unable to allocate dma=%d\n", - ALI_IRCC_DRIVER_NAME, - self->io.dma); + net_warn_ratelimited("%s, unable to allocate dma=%d\n", + ALI_IRCC_DRIVER_NAME, self->io.dma); free_irq(self->io.irq, dev); return -EAGAIN; } @@ -1385,7 +1358,6 @@ static int ali_ircc_net_open(struct net_device *dev) */ self->irlap = irlap_open(dev, &self->qos, hwname); - IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __func__ ); return 0; } @@ -1402,7 +1374,6 @@ static int ali_ircc_net_close(struct net_device *dev) struct ali_ircc_cb *self; //int iobase; - IRDA_DEBUG(4, "%s(), ---------------- Start ----------------\n", __func__ ); IRDA_ASSERT(dev != NULL, return -1;); @@ -1425,7 +1396,6 @@ static int ali_ircc_net_close(struct net_device *dev) free_irq(self->io.irq, dev); free_dma(self->io.dma); - IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __func__ ); return 0; } @@ -1445,7 +1415,6 @@ static netdev_tx_t ali_ircc_fir_hard_xmit(struct sk_buff *skb, __u32 speed; int mtt, diff; - IRDA_DEBUG(1, "%s(), ---------------- Start -----------------\n", __func__ ); self = netdev_priv(dev); iobase = self->io.fir_base; @@ -1499,7 +1468,8 @@ static netdev_tx_t ali_ircc_fir_hard_xmit(struct sk_buff *skb, diff = self->now.tv_usec - self->stamp.tv_usec; /* self->stamp is set from ali_ircc_dma_receive_complete() */ - IRDA_DEBUG(1, "%s(), ******* diff = %d *******\n", __func__ , diff); + pr_debug("%s(), ******* diff = %d *******\n", + __func__, diff); if (diff < 0) diff += 1000000; @@ -1521,7 +1491,8 @@ static netdev_tx_t ali_ircc_fir_hard_xmit(struct sk_buff *skb, /* Adjust for timer resolution */ mtt = (mtt+250) / 500; /* 4 discard, 5 get advanced, Let's round off */ - IRDA_DEBUG(1, "%s(), ************** mtt = %d ***********\n", __func__ , mtt); + pr_debug("%s(), ************** mtt = %d ***********\n", + __func__, mtt); /* Setup timer */ if (mtt == 1) /* 500 us */ @@ -1578,7 +1549,6 @@ static netdev_tx_t ali_ircc_fir_hard_xmit(struct sk_buff *skb, spin_unlock_irqrestore(&self->lock, flags); dev_kfree_skb(skb); - IRDA_DEBUG(1, "%s(), ----------------- End ------------------\n", __func__ ); return NETDEV_TX_OK; } @@ -1589,7 +1559,6 @@ static void ali_ircc_dma_xmit(struct ali_ircc_cb *self) unsigned char FIFO_OPTI, Hi, Lo; - IRDA_DEBUG(1, "%s(), ---------------- Start -----------------\n", __func__ ); iobase = self->io.fir_base; @@ -1640,7 +1609,8 @@ static void ali_ircc_dma_xmit(struct ali_ircc_cb *self) tmp = inb(iobase+FIR_LCR_B); tmp &= ~0x20; // Disable SIP outb(((unsigned char)(tmp & 0x3f) | LCR_B_TX_MODE) & ~LCR_B_BW, iobase+FIR_LCR_B); - IRDA_DEBUG(1, "%s(), *** Change to TX mode: FIR_LCR_B = 0x%x ***\n", __func__ , inb(iobase+FIR_LCR_B)); + pr_debug("%s(), *** Change to TX mode: FIR_LCR_B = 0x%x ***\n", + __func__, inb(iobase + FIR_LCR_B)); outb(0, iobase+FIR_LSR); @@ -1650,7 +1620,6 @@ static void ali_ircc_dma_xmit(struct ali_ircc_cb *self) switch_bank(iobase, BANK0); - IRDA_DEBUG(1, "%s(), ----------------- End ------------------\n", __func__ ); } static int ali_ircc_dma_xmit_complete(struct ali_ircc_cb *self) @@ -1658,7 +1627,6 @@ static int ali_ircc_dma_xmit_complete(struct ali_ircc_cb *self) int iobase; int ret = TRUE; - IRDA_DEBUG(1, "%s(), ---------------- Start -----------------\n", __func__ ); iobase = self->io.fir_base; @@ -1671,7 +1639,8 @@ static int ali_ircc_dma_xmit_complete(struct ali_ircc_cb *self) if((inb(iobase+FIR_LSR) & LSR_FRAME_ABORT) == LSR_FRAME_ABORT) { - IRDA_ERROR("%s(), ********* LSR_FRAME_ABORT *********\n", __func__); + net_err_ratelimited("%s(), ********* LSR_FRAME_ABORT *********\n", + __func__); self->netdev->stats.tx_errors++; self->netdev->stats.tx_fifo_errors++; } @@ -1714,7 +1683,6 @@ static int ali_ircc_dma_xmit_complete(struct ali_ircc_cb *self) switch_bank(iobase, BANK0); - IRDA_DEBUG(1, "%s(), ----------------- End ------------------\n", __func__ ); return ret; } @@ -1729,7 +1697,6 @@ static int ali_ircc_dma_receive(struct ali_ircc_cb *self) { int iobase, tmp; - IRDA_DEBUG(1, "%s(), ---------------- Start -----------------\n", __func__ ); iobase = self->io.fir_base; @@ -1767,7 +1734,8 @@ static int ali_ircc_dma_receive(struct ali_ircc_cb *self) //switch_bank(iobase, BANK0); tmp = inb(iobase+FIR_LCR_B); outb((unsigned char)(tmp &0x3f) | LCR_B_RX_MODE | LCR_B_BW , iobase + FIR_LCR_B); // 2000/12/1 05:16PM - IRDA_DEBUG(1, "%s(), *** Change To RX mode: FIR_LCR_B = 0x%x ***\n", __func__ , inb(iobase+FIR_LCR_B)); + pr_debug("%s(), *** Change To RX mode: FIR_LCR_B = 0x%x ***\n", + __func__, inb(iobase + FIR_LCR_B)); /* Set Rx Threshold */ switch_bank(iobase, BANK1); @@ -1779,7 +1747,6 @@ static int ali_ircc_dma_receive(struct ali_ircc_cb *self) outb(CR_DMA_EN | CR_DMA_BURST, iobase+FIR_CR); switch_bank(iobase, BANK0); - IRDA_DEBUG(1, "%s(), ----------------- End ------------------\n", __func__ ); return 0; } @@ -1790,8 +1757,6 @@ static int ali_ircc_dma_receive_complete(struct ali_ircc_cb *self) __u8 status, MessageCount; int len, i, iobase, val; - IRDA_DEBUG(1, "%s(), ---------------- Start -----------------\n", __func__ ); - st_fifo = &self->st_fifo; iobase = self->io.fir_base; @@ -1799,7 +1764,7 @@ static int ali_ircc_dma_receive_complete(struct ali_ircc_cb *self) MessageCount = inb(iobase+ FIR_LSR)&0x07; if (MessageCount > 0) - IRDA_DEBUG(0, "%s(), Message count = %d,\n", __func__ , MessageCount); + pr_debug("%s(), Message count = %d\n", __func__, MessageCount); for (i=0; i<=MessageCount; i++) { @@ -1812,11 +1777,11 @@ static int ali_ircc_dma_receive_complete(struct ali_ircc_cb *self) len = len << 8; len |= inb(iobase+FIR_RX_DSR_LO); - IRDA_DEBUG(1, "%s(), RX Length = 0x%.2x,\n", __func__ , len); - IRDA_DEBUG(1, "%s(), RX Status = 0x%.2x,\n", __func__ , status); + pr_debug("%s(), RX Length = 0x%.2x,\n", __func__ , len); + pr_debug("%s(), RX Status = 0x%.2x,\n", __func__ , status); if (st_fifo->tail >= MAX_RX_WINDOW) { - IRDA_DEBUG(0, "%s(), window is full!\n", __func__ ); + pr_debug("%s(), window is full!\n", __func__); continue; } @@ -1839,7 +1804,8 @@ static int ali_ircc_dma_receive_complete(struct ali_ircc_cb *self) /* Check for errors */ if ((status & 0xd8) || self->rcvFramesOverflow || (len==0)) { - IRDA_DEBUG(0,"%s(), ************* RX Errors ************\n", __func__ ); + pr_debug("%s(), ************* RX Errors ************\n", + __func__); /* Skip frame */ self->netdev->stats.rx_errors++; @@ -1849,29 +1815,34 @@ static int ali_ircc_dma_receive_complete(struct ali_ircc_cb *self) if (status & LSR_FIFO_UR) { self->netdev->stats.rx_frame_errors++; - IRDA_DEBUG(0,"%s(), ************* FIFO Errors ************\n", __func__ ); + pr_debug("%s(), ************* FIFO Errors ************\n", + __func__); } if (status & LSR_FRAME_ERROR) { self->netdev->stats.rx_frame_errors++; - IRDA_DEBUG(0,"%s(), ************* FRAME Errors ************\n", __func__ ); + pr_debug("%s(), ************* FRAME Errors ************\n", + __func__); } if (status & LSR_CRC_ERROR) { self->netdev->stats.rx_crc_errors++; - IRDA_DEBUG(0,"%s(), ************* CRC Errors ************\n", __func__ ); + pr_debug("%s(), ************* CRC Errors ************\n", + __func__); } if(self->rcvFramesOverflow) { self->netdev->stats.rx_frame_errors++; - IRDA_DEBUG(0,"%s(), ************* Overran DMA buffer ************\n", __func__ ); + pr_debug("%s(), ************* Overran DMA buffer ************\n", + __func__); } if(len == 0) { self->netdev->stats.rx_frame_errors++; - IRDA_DEBUG(0,"%s(), ********** Receive Frame Size = 0 *********\n", __func__ ); + pr_debug("%s(), ********** Receive Frame Size = 0 *********\n", + __func__); } } else @@ -1883,7 +1854,8 @@ static int ali_ircc_dma_receive_complete(struct ali_ircc_cb *self) val = inb(iobase+FIR_BSR); if ((val& BSR_FIFO_NOT_EMPTY)== 0x80) { - IRDA_DEBUG(0, "%s(), ************* BSR_FIFO_NOT_EMPTY ************\n", __func__ ); + pr_debug("%s(), ************* BSR_FIFO_NOT_EMPTY ************\n", + __func__); /* Put this entry back in fifo */ st_fifo->head--; @@ -1918,9 +1890,6 @@ static int ali_ircc_dma_receive_complete(struct ali_ircc_cb *self) skb = dev_alloc_skb(len+1); if (skb == NULL) { - IRDA_WARNING("%s(), memory squeeze, " - "dropping frame.\n", - __func__); self->netdev->stats.rx_dropped++; return FALSE; @@ -1947,7 +1916,6 @@ static int ali_ircc_dma_receive_complete(struct ali_ircc_cb *self) switch_bank(iobase, BANK0); - IRDA_DEBUG(1, "%s(), ----------------- End ------------------\n", __func__ ); return TRUE; } @@ -1967,7 +1935,6 @@ static netdev_tx_t ali_ircc_sir_hard_xmit(struct sk_buff *skb, int iobase; __u32 speed; - IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __func__ ); IRDA_ASSERT(dev != NULL, return NETDEV_TX_OK;); @@ -2016,7 +1983,6 @@ static netdev_tx_t ali_ircc_sir_hard_xmit(struct sk_buff *skb, dev_kfree_skb(skb); - IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __func__ ); return NETDEV_TX_OK; } @@ -2035,7 +2001,6 @@ static int ali_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) unsigned long flags; int ret = 0; - IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __func__ ); IRDA_ASSERT(dev != NULL, return -1;); @@ -2043,11 +2008,11 @@ static int ali_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) IRDA_ASSERT(self != NULL, return -1;); - IRDA_DEBUG(2, "%s(), %s, (cmd=0x%X)\n", __func__ , dev->name, cmd); + pr_debug("%s(), %s, (cmd=0x%X)\n", __func__ , dev->name, cmd); switch (cmd) { case SIOCSBANDWIDTH: /* Set bandwidth */ - IRDA_DEBUG(1, "%s(), SIOCSBANDWIDTH\n", __func__ ); + pr_debug("%s(), SIOCSBANDWIDTH\n", __func__); /* * This function will also be used by IrLAP to change the * speed, so we still must allow for speed change within @@ -2061,13 +2026,13 @@ static int ali_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) spin_unlock_irqrestore(&self->lock, flags); break; case SIOCSMEDIABUSY: /* Set media busy */ - IRDA_DEBUG(1, "%s(), SIOCSMEDIABUSY\n", __func__ ); + pr_debug("%s(), SIOCSMEDIABUSY\n", __func__); if (!capable(CAP_NET_ADMIN)) return -EPERM; irda_device_set_media_busy(self->netdev, TRUE); break; case SIOCGRECEIVING: /* Check if we are receiving right now */ - IRDA_DEBUG(2, "%s(), SIOCGRECEIVING\n", __func__ ); + pr_debug("%s(), SIOCGRECEIVING\n", __func__); /* This is protected */ irq->ifr_receiving = ali_ircc_is_receiving(self); break; @@ -2075,7 +2040,6 @@ static int ali_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ret = -EOPNOTSUPP; } - IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __func__ ); return ret; } @@ -2092,7 +2056,6 @@ static int ali_ircc_is_receiving(struct ali_ircc_cb *self) int status = FALSE; int iobase; - IRDA_DEBUG(2, "%s(), ---------------- Start -----------------\n", __func__ ); IRDA_ASSERT(self != NULL, return FALSE;); @@ -2106,7 +2069,8 @@ static int ali_ircc_is_receiving(struct ali_ircc_cb *self) if((inb(iobase+FIR_FIFO_FR) & 0x3f) != 0) { /* We are receiving something */ - IRDA_DEBUG(1, "%s(), We are receiving something\n", __func__ ); + pr_debug("%s(), We are receiving something\n", + __func__); status = TRUE; } switch_bank(iobase, BANK0); @@ -2118,7 +2082,6 @@ static int ali_ircc_is_receiving(struct ali_ircc_cb *self) spin_unlock_irqrestore(&self->lock, flags); - IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __func__ ); return status; } @@ -2127,7 +2090,7 @@ static int ali_ircc_suspend(struct platform_device *dev, pm_message_t state) { struct ali_ircc_cb *self = platform_get_drvdata(dev); - IRDA_MESSAGE("%s, Suspending\n", ALI_IRCC_DRIVER_NAME); + net_info_ratelimited("%s, Suspending\n", ALI_IRCC_DRIVER_NAME); if (self->io.suspended) return 0; @@ -2148,7 +2111,7 @@ static int ali_ircc_resume(struct platform_device *dev) ali_ircc_net_open(self->netdev); - IRDA_MESSAGE("%s, Waking up\n", ALI_IRCC_DRIVER_NAME); + net_info_ratelimited("%s, Waking up\n", ALI_IRCC_DRIVER_NAME); self->io.suspended = 0; @@ -2164,7 +2127,8 @@ static void SetCOMInterrupts(struct ali_ircc_cb *self , unsigned char enable) int iobase = self->io.fir_base; /* or sir_base */ - IRDA_DEBUG(2, "%s(), -------- Start -------- ( Enable = %d )\n", __func__ , enable); + pr_debug("%s(), -------- Start -------- ( Enable = %d )\n", + __func__, enable); /* Enable the interrupt which we wish to */ if (enable){ @@ -2205,14 +2169,12 @@ static void SetCOMInterrupts(struct ali_ircc_cb *self , unsigned char enable) else outb(newMask, iobase+UART_IER); - IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __func__ ); } static void SIR2FIR(int iobase) { //unsigned char tmp; - IRDA_DEBUG(1, "%s(), ---------------- Start ----------------\n", __func__ ); /* Already protected (change_speed() or setup()), no need to lock. * Jean II */ @@ -2228,14 +2190,12 @@ static void SIR2FIR(int iobase) //tmp |= 0x20; //outb(tmp, iobase+FIR_LCR_B); - IRDA_DEBUG(1, "%s(), ----------------- End ------------------\n", __func__ ); } static void FIR2SIR(int iobase) { unsigned char val; - IRDA_DEBUG(1, "%s(), ---------------- Start ----------------\n", __func__ ); /* Already protected (change_speed() or setup()), no need to lock. * Jean II */ @@ -2251,7 +2211,6 @@ static void FIR2SIR(int iobase) val = inb(iobase+UART_LSR); val = inb(iobase+UART_MSR); - IRDA_DEBUG(1, "%s(), ----------------- End ------------------\n", __func__ ); } MODULE_AUTHOR("Benjamin Kong <benjamin_kong@ali.com.tw>"); diff --git a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c index a87a82ca111f..b337e6d23a88 100644 --- a/drivers/net/irda/donauboe.c +++ b/drivers/net/irda/donauboe.c @@ -232,7 +232,7 @@ char head=tete; for (i=0;i<len;i+=16) { for (j=0;j<16 && i+j<len;j++) { sprintf(&dump[3*j],"%02x.",data[i+j]); } dump [3*j]=0; - IRDA_DEBUG (2, "%c%s\n",head , dump); + pr_debug("%c%s\n", head, dump); head='+'; } } @@ -245,8 +245,6 @@ toshoboe_dumpregs (struct toshoboe_cb *self) { __u32 ringbase; - IRDA_DEBUG (4, "%s()\n", __func__); - ringbase = INB (OBOE_RING_BASE0) << 10; ringbase |= INB (OBOE_RING_BASE1) << 18; ringbase |= INB (OBOE_RING_BASE2) << 26; @@ -293,8 +291,6 @@ static void toshoboe_disablebm (struct toshoboe_cb *self) { __u8 command; - IRDA_DEBUG (4, "%s()\n", __func__); - pci_read_config_byte (self->pdev, PCI_COMMAND, &command); command &= ~PCI_COMMAND_MASTER; pci_write_config_byte (self->pdev, PCI_COMMAND, command); @@ -305,8 +301,6 @@ toshoboe_disablebm (struct toshoboe_cb *self) static void toshoboe_stopchip (struct toshoboe_cb *self) { - IRDA_DEBUG (4, "%s()\n", __func__); - /*Disable interrupts */ OUTB (0x0, OBOE_IER); /*Disable DMA, Disable Rx, Disable Tx */ @@ -350,7 +344,7 @@ toshoboe_setbaud (struct toshoboe_cb *self) __u16 pconfig = 0; __u8 config0l = 0; - IRDA_DEBUG (2, "%s(%d/%d)\n", __func__, self->speed, self->io.speed); + pr_debug("%s(%d/%d)\n", __func__, self->speed, self->io.speed); switch (self->speed) { @@ -482,7 +476,6 @@ toshoboe_setbaud (struct toshoboe_cb *self) static void toshoboe_enablebm (struct toshoboe_cb *self) { - IRDA_DEBUG (4, "%s()\n", __func__); pci_set_master (self->pdev); } @@ -492,8 +485,6 @@ toshoboe_initring (struct toshoboe_cb *self) { int i; - IRDA_DEBUG (4, "%s()\n", __func__); - for (i = 0; i < TX_SLOTS; ++i) { self->ring->tx[i].len = 0; @@ -550,8 +541,6 @@ toshoboe_startchip (struct toshoboe_cb *self) { __u32 physaddr; - IRDA_DEBUG (4, "%s()\n", __func__); - toshoboe_initring (self); toshoboe_enablebm (self); OUTBP (OBOE_CONFIG1_RESET, OBOE_CONFIG1); @@ -636,9 +625,8 @@ toshoboe_makemttpacket (struct toshoboe_cb *self, void *buf, int mtt) xbofs=xbofs/80000; /*Eight bits per byte, and mtt is in us*/ xbofs++; - IRDA_DEBUG (2, DRIVER_NAME - ": generated mtt of %d bytes for %d us at %d baud\n" - , xbofs,mtt,self->speed); + pr_debug(DRIVER_NAME ": generated mtt of %d bytes for %d us at %d baud\n", + xbofs, mtt, self->speed); if (xbofs > TX_LEN) { @@ -824,8 +812,6 @@ toshoboe_probe (struct toshoboe_cb *self) #endif unsigned long flags; - IRDA_DEBUG (4, "%s()\n", __func__); - if (request_irq (self->io.irq, toshoboe_probeinterrupt, self->io.irqflags, "toshoboe", (void *) self)) { @@ -983,10 +969,10 @@ toshoboe_hard_xmit (struct sk_buff *skb, struct net_device *dev) IRDA_ASSERT (self != NULL, return NETDEV_TX_OK; ); - IRDA_DEBUG (1, "%s.tx:%x(%x)%x\n", __func__ - ,skb->len,self->txpending,INB (OBOE_ENABLEH)); + pr_debug("%s.tx:%x(%x)%x\n", + __func__, skb->len, self->txpending, INB(OBOE_ENABLEH)); if (!cb->magic) { - IRDA_DEBUG (2, "%s.Not IrLAP:%x\n", __func__, cb->magic); + pr_debug("%s.Not IrLAP:%x\n", __func__, cb->magic); #ifdef DUMP_PACKETS _dumpbufs(skb->data,skb->len,'>'); #endif @@ -1012,8 +998,8 @@ toshoboe_hard_xmit (struct sk_buff *skb, struct net_device *dev) if (self->txpending || skb->len) { self->new_speed = speed; - IRDA_DEBUG (1, "%s: Queued TxDone scheduled speed change %d\n" , - __func__, speed); + pr_debug("%s: Queued TxDone scheduled speed change %d\n" , + __func__, speed); /* if no data, that's all! */ if (!skb->len) { @@ -1055,8 +1041,7 @@ toshoboe_hard_xmit (struct sk_buff *skb, struct net_device *dev) /* which we will add a wrong checksum to */ mtt = toshoboe_makemttpacket (self, self->tx_bufs[self->txs], mtt); - IRDA_DEBUG (1, "%s.mtt:%x(%x)%d\n", __func__ - ,skb->len,mtt,self->txpending); + pr_debug("%s.mtt:%x(%x)%d\n", __func__, skb->len, mtt, self->txpending); if (mtt) { self->ring->tx[self->txs].len = mtt & 0xfff; @@ -1099,8 +1084,9 @@ dumpbufs(skb->data,skb->len,'>'); if (self->ring->tx[self->txs].control & OBOE_CTL_TX_HW_OWNS) { - IRDA_DEBUG (0, "%s.ful:%x(%x)%x\n", __func__ - ,skb->len, self->ring->tx[self->txs].control, self->txpending); + pr_debug("%s.ful:%x(%x)%x\n", + __func__, skb->len, self->ring->tx[self->txs].control, + self->txpending); toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX); spin_unlock_irqrestore(&self->spinlock, flags); return NETDEV_TX_BUSY; @@ -1177,8 +1163,7 @@ toshoboe_interrupt (int irq, void *dev_id) if (self->ring->tx[i].control & OBOE_CTL_TX_HW_OWNS) self->txpending++; } - IRDA_DEBUG (1, "%s.txd(%x)%x/%x\n", __func__ - ,irqstat,txp,self->txpending); + pr_debug("%s.txd(%x)%x/%x\n", __func__, irqstat, txp, self->txpending); txp = INB (OBOE_TXSLOT) & OBOE_SLOT_MASK; @@ -1206,8 +1191,8 @@ toshoboe_interrupt (int irq, void *dev_id) if ((!self->txpending) && (self->new_speed)) { self->speed = self->new_speed; - IRDA_DEBUG (1, "%s: Executed TxDone scheduled speed change %d\n", - __func__, self->speed); + pr_debug("%s: Executed TxDone scheduled speed change %d\n", + __func__, self->speed); toshoboe_setbaud (self); } @@ -1222,8 +1207,8 @@ toshoboe_interrupt (int irq, void *dev_id) { int len = self->ring->rx[self->rxs].len; skb = NULL; - IRDA_DEBUG (3, "%s.rcv:%x(%x)\n", __func__ - ,len,self->ring->rx[self->rxs].control); + pr_debug("%s.rcv:%x(%x)\n", __func__ + , len, self->ring->rx[self->rxs].control); #ifdef DUMP_PACKETS dumpbufs(self->rx_bufs[self->rxs],len,'<'); @@ -1244,7 +1229,7 @@ dumpbufs(self->rx_bufs[self->rxs],len,'<'); len -= 2; else len = 0; - IRDA_DEBUG (1, "%s.SIR:%x(%x)\n", __func__, len,enable); + pr_debug("%s.SIR:%x(%x)\n", __func__, len, enable); } #ifdef USE_MIR @@ -1254,7 +1239,7 @@ dumpbufs(self->rx_bufs[self->rxs],len,'<'); len -= 2; else len = 0; - IRDA_DEBUG (2, "%s.MIR:%x(%x)\n", __func__, len,enable); + pr_debug("%s.MIR:%x(%x)\n", __func__, len, enable); } #endif else if (enable & OBOE_ENABLEH_FIRON) @@ -1263,10 +1248,10 @@ dumpbufs(self->rx_bufs[self->rxs],len,'<'); len -= 4; /*FIXME: check this */ else len = 0; - IRDA_DEBUG (1, "%s.FIR:%x(%x)\n", __func__, len,enable); + pr_debug("%s.FIR:%x(%x)\n", __func__, len, enable); } else - IRDA_DEBUG (0, "%s.?IR:%x(%x)\n", __func__, len,enable); + pr_debug("%s.?IR:%x(%x)\n", __func__, len, enable); if (len) { @@ -1299,8 +1284,8 @@ dumpbufs(self->rx_bufs[self->rxs],len,'<'); /* (SIR) data is splitted in several slots. */ /* we have to join all the received buffers received */ /*in a large buffer before checking CRC. */ - IRDA_DEBUG (0, "%s.err:%x(%x)\n", __func__ - ,len,self->ring->rx[self->rxs].control); + pr_debug("%s.err:%x(%x)\n", __func__ + , len, self->ring->rx[self->rxs].control); } self->ring->rx[self->rxs].len = 0x0; @@ -1327,8 +1312,8 @@ dumpbufs(self->rx_bufs[self->rxs],len,'<'); if (irqstat & OBOE_INT_SIP) { self->int_sip++; - IRDA_DEBUG (1, "%s.sip:%x(%x)%x\n", __func__ - ,self->int_sip,irqstat,self->txpending); + pr_debug("%s.sip:%x(%x)%x\n", + __func__, self->int_sip, irqstat, self->txpending); } return IRQ_HANDLED; } @@ -1341,8 +1326,6 @@ toshoboe_net_open (struct net_device *dev) unsigned long flags; int rc; - IRDA_DEBUG (4, "%s()\n", __func__); - self = netdev_priv(dev); if (self->async) @@ -1379,8 +1362,6 @@ toshoboe_net_close (struct net_device *dev) { struct toshoboe_cb *self; - IRDA_DEBUG (4, "%s()\n", __func__); - IRDA_ASSERT (dev != NULL, return -1; ); self = netdev_priv(dev); @@ -1424,7 +1405,7 @@ toshoboe_net_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) IRDA_ASSERT (self != NULL, return -1; ); - IRDA_DEBUG (5, "%s(), %s, (cmd=0x%X)\n", __func__, dev->name, cmd); + pr_debug("%s(), %s, (cmd=0x%X)\n", __func__, dev->name, cmd); /* Disable interrupts & save flags */ spin_lock_irqsave(&self->spinlock, flags); @@ -1436,8 +1417,8 @@ toshoboe_net_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) * speed, so we still must allow for speed change within * interrupt context. */ - IRDA_DEBUG (1, "%s(BANDWIDTH), %s, (%X/%ld\n", __func__ - ,dev->name, INB (OBOE_STATUS), irq->ifr_baudrate ); + pr_debug("%s(BANDWIDTH), %s, (%X/%ld\n", + __func__, dev->name, INB(OBOE_STATUS), irq->ifr_baudrate); if (!in_interrupt () && !capable (CAP_NET_ADMIN)) { ret = -EPERM; goto out; @@ -1449,8 +1430,9 @@ toshoboe_net_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) self->new_speed = irq->ifr_baudrate; break; case SIOCSMEDIABUSY: /* Set media busy */ - IRDA_DEBUG (1, "%s(MEDIABUSY), %s, (%X/%x)\n", __func__ - ,dev->name, INB (OBOE_STATUS), capable (CAP_NET_ADMIN) ); + pr_debug("%s(MEDIABUSY), %s, (%X/%x)\n", + __func__, dev->name, + INB(OBOE_STATUS), capable(CAP_NET_ADMIN)); if (!capable (CAP_NET_ADMIN)) { ret = -EPERM; goto out; @@ -1459,11 +1441,11 @@ toshoboe_net_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) break; case SIOCGRECEIVING: /* Check if we are receiving right now */ irq->ifr_receiving = (INB (OBOE_STATUS) & OBOE_STATUS_RXBUSY) ? 1 : 0; - IRDA_DEBUG (3, "%s(RECEIVING), %s, (%X/%x)\n", __func__ - ,dev->name, INB (OBOE_STATUS), irq->ifr_receiving ); + pr_debug("%s(RECEIVING), %s, (%X/%x)\n", + __func__, dev->name, INB(OBOE_STATUS), irq->ifr_receiving); break; default: - IRDA_DEBUG (1, "%s(?), %s, (cmd=0x%X)\n", __func__, dev->name, cmd); + pr_debug("%s(?), %s, (cmd=0x%X)\n", __func__, dev->name, cmd); ret = -EOPNOTSUPP; } out: @@ -1490,8 +1472,6 @@ toshoboe_close (struct pci_dev *pci_dev) int i; struct toshoboe_cb *self = pci_get_drvdata(pci_dev); - IRDA_DEBUG (4, "%s()\n", __func__); - IRDA_ASSERT (self != NULL, return; ); if (!self->stopped) @@ -1538,8 +1518,6 @@ toshoboe_open (struct pci_dev *pci_dev, const struct pci_device_id *pdid) int ok = 0; int err; - IRDA_DEBUG (4, "%s()\n", __func__); - if ((err=pci_enable_device(pci_dev))) return err; @@ -1700,8 +1678,6 @@ toshoboe_gotosleep (struct pci_dev *pci_dev, pm_message_t crap) unsigned long flags; int i = 10; - IRDA_DEBUG (4, "%s()\n", __func__); - if (!self || self->stopped) return 0; @@ -1728,8 +1704,6 @@ toshoboe_wakeup (struct pci_dev *pci_dev) struct toshoboe_cb *self = pci_get_drvdata(pci_dev); unsigned long flags; - IRDA_DEBUG (4, "%s()\n", __func__); - if (!self || !self->stopped) return 0; diff --git a/drivers/net/irda/girbil-sir.c b/drivers/net/irda/girbil-sir.c index 96cdecff349d..7e0a5b8c6d53 100644 --- a/drivers/net/irda/girbil-sir.c +++ b/drivers/net/irda/girbil-sir.c @@ -86,8 +86,6 @@ static int girbil_open(struct sir_dev *dev) { struct qos_info *qos = &dev->qos; - IRDA_DEBUG(2, "%s()\n", __func__); - /* Power on dongle */ sirdev_set_dtr_rts(dev, TRUE, TRUE); @@ -102,8 +100,6 @@ static int girbil_open(struct sir_dev *dev) static int girbil_close(struct sir_dev *dev) { - IRDA_DEBUG(2, "%s()\n", __func__); - /* Power off dongle */ sirdev_set_dtr_rts(dev, FALSE, FALSE); @@ -126,8 +122,6 @@ static int girbil_change_speed(struct sir_dev *dev, unsigned speed) u8 control[2]; static int ret = 0; - IRDA_DEBUG(2, "%s()\n", __func__); - /* dongle alread reset - port and dongle at default speed */ switch(state) { @@ -179,7 +173,8 @@ static int girbil_change_speed(struct sir_dev *dev, unsigned speed) break; default: - IRDA_ERROR("%s - undefined state %d\n", __func__, state); + net_err_ratelimited("%s - undefined state %d\n", + __func__, state); ret = -EINVAL; break; } @@ -209,8 +204,6 @@ static int girbil_reset(struct sir_dev *dev) u8 control = GIRBIL_TXEN | GIRBIL_RXEN; int ret = 0; - IRDA_DEBUG(2, "%s()\n", __func__); - switch (state) { case SIRDEV_STATE_DONGLE_RESET: /* Reset dongle */ @@ -241,7 +234,8 @@ static int girbil_reset(struct sir_dev *dev) break; default: - IRDA_ERROR("%s(), undefined state %d\n", __func__, state); + net_err_ratelimited("%s(), undefined state %d\n", + __func__, state); ret = -1; break; } diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c index 925b78cc9797..48b2f9a321b7 100644 --- a/drivers/net/irda/irda-usb.c +++ b/drivers/net/irda/irda-usb.c @@ -176,12 +176,13 @@ static void irda_usb_build_header(struct irda_usb_cb *self, (!force) && (self->speed != -1)) { /* No speed and xbofs change here * (we'll do it later in the write callback) */ - IRDA_DEBUG(2, "%s(), not changing speed yet\n", __func__); + pr_debug("%s(), not changing speed yet\n", __func__); *header = 0; return; } - IRDA_DEBUG(2, "%s(), changing speed to %d\n", __func__, self->new_speed); + pr_debug("%s(), changing speed to %d\n", + __func__, self->new_speed); self->speed = self->new_speed; /* We will do ` self->new_speed = -1; ' in the completion * handler just in case the current URB fail - Jean II */ @@ -227,7 +228,8 @@ static void irda_usb_build_header(struct irda_usb_cb *self, /* Set the negotiated additional XBOFS */ if (self->new_xbofs != -1) { - IRDA_DEBUG(2, "%s(), changing xbofs to %d\n", __func__, self->new_xbofs); + pr_debug("%s(), changing xbofs to %d\n", + __func__, self->new_xbofs); self->xbofs = self->new_xbofs; /* We will do ` self->new_xbofs = -1; ' in the completion * handler just in case the current URB fail - Jean II */ @@ -301,13 +303,13 @@ static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self) struct urb *urb; int ret; - IRDA_DEBUG(2, "%s(), speed=%d, xbofs=%d\n", __func__, - self->new_speed, self->new_xbofs); + pr_debug("%s(), speed=%d, xbofs=%d\n", __func__, + self->new_speed, self->new_xbofs); /* Grab the speed URB */ urb = self->speed_urb; if (urb->status != 0) { - IRDA_WARNING("%s(), URB still in use!\n", __func__); + net_warn_ratelimited("%s(), URB still in use!\n", __func__); return; } @@ -333,7 +335,7 @@ static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self) /* Irq disabled -> GFP_ATOMIC */ if ((ret = usb_submit_urb(urb, GFP_ATOMIC))) { - IRDA_WARNING("%s(), failed Speed URB\n", __func__); + net_warn_ratelimited("%s(), failed Speed URB\n", __func__); } } @@ -346,8 +348,6 @@ static void speed_bulk_callback(struct urb *urb) { struct irda_usb_cb *self = urb->context; - IRDA_DEBUG(2, "%s()\n", __func__); - /* We should always have a context */ IRDA_ASSERT(self != NULL, return;); /* We should always be called for the speed URB */ @@ -356,7 +356,8 @@ static void speed_bulk_callback(struct urb *urb) /* Check for timeout and other USB nasties */ if (urb->status != 0) { /* I get a lot of -ECONNABORTED = -103 here - Jean II */ - IRDA_DEBUG(0, "%s(), URB complete status %d, transfer_flags 0x%04X\n", __func__, urb->status, urb->transfer_flags); + pr_debug("%s(), URB complete status %d, transfer_flags 0x%04X\n", + __func__, urb->status, urb->transfer_flags); /* Don't do anything here, that might confuse the USB layer. * Instead, we will wait for irda_usb_net_timeout(), the @@ -391,7 +392,7 @@ static netdev_tx_t irda_usb_hard_xmit(struct sk_buff *skb, s16 xbofs; int res, mtt; - IRDA_DEBUG(4, "%s() on %s\n", __func__, netdev->name); + pr_debug("%s() on %s\n", __func__, netdev->name); netif_stop_queue(netdev); @@ -402,7 +403,7 @@ static netdev_tx_t irda_usb_hard_xmit(struct sk_buff *skb, * We need to check self->present under the spinlock because * of irda_usb_disconnect() is synchronous - Jean II */ if (!self->present) { - IRDA_DEBUG(0, "%s(), Device is gone...\n", __func__); + pr_debug("%s(), Device is gone...\n", __func__); goto drop; } @@ -435,7 +436,7 @@ static netdev_tx_t irda_usb_hard_xmit(struct sk_buff *skb, } if (urb->status != 0) { - IRDA_WARNING("%s(), URB still in use!\n", __func__); + net_warn_ratelimited("%s(), URB still in use!\n", __func__); goto drop; } @@ -522,7 +523,7 @@ static netdev_tx_t irda_usb_hard_xmit(struct sk_buff *skb, /* Ask USB to send the packet - Irq disabled -> GFP_ATOMIC */ if ((res = usb_submit_urb(urb, GFP_ATOMIC))) { - IRDA_WARNING("%s(), failed Tx URB\n", __func__); + net_warn_ratelimited("%s(), failed Tx URB\n", __func__); netdev->stats.tx_errors++; /* Let USB recover : We will catch that in the watchdog */ /*netif_start_queue(netdev);*/ @@ -554,8 +555,6 @@ static void write_bulk_callback(struct urb *urb) struct sk_buff *skb = urb->context; struct irda_usb_cb *self = ((struct irda_skb_cb *) skb->cb)->context; - IRDA_DEBUG(2, "%s()\n", __func__); - /* We should always have a context */ IRDA_ASSERT(self != NULL, return;); /* We should always be called for the speed URB */ @@ -568,7 +567,8 @@ static void write_bulk_callback(struct urb *urb) /* Check for timeout and other USB nasties */ if (urb->status != 0) { /* I get a lot of -ECONNABORTED = -103 here - Jean II */ - IRDA_DEBUG(0, "%s(), URB complete status %d, transfer_flags 0x%04X\n", __func__, urb->status, urb->transfer_flags); + pr_debug("%s(), URB complete status %d, transfer_flags 0x%04X\n", + __func__, urb->status, urb->transfer_flags); /* Don't do anything here, that might confuse the USB layer, * and we could go in recursion and blow the kernel stack... @@ -587,7 +587,7 @@ static void write_bulk_callback(struct urb *urb) /* If the network is closed, stop everything */ if ((!self->netopen) || (!self->present)) { - IRDA_DEBUG(0, "%s(), Network is gone...\n", __func__); + pr_debug("%s(), Network is gone...\n", __func__); spin_unlock_irqrestore(&self->lock, flags); return; } @@ -598,7 +598,7 @@ static void write_bulk_callback(struct urb *urb) (self->new_xbofs != self->xbofs)) { /* We haven't changed speed yet (because of * IUC_SPEED_BUG), so do it now - Jean II */ - IRDA_DEBUG(1, "%s(), Changing speed now...\n", __func__); + pr_debug("%s(), Changing speed now...\n", __func__); irda_usb_change_speed_xbofs(self); } else { /* New speed and xbof is now committed in hardware */ @@ -630,7 +630,7 @@ static void irda_usb_net_timeout(struct net_device *netdev) struct urb *urb; int done = 0; /* If we have made any progress */ - IRDA_DEBUG(0, "%s(), Network layer thinks we timed out!\n", __func__); + pr_debug("%s(), Network layer thinks we timed out!\n", __func__); IRDA_ASSERT(self != NULL, return;); /* Protect us from USB callbacks, net Tx and else. */ @@ -638,7 +638,7 @@ static void irda_usb_net_timeout(struct net_device *netdev) /* self->present *MUST* be read under spinlock */ if (!self->present) { - IRDA_WARNING("%s(), device not present!\n", __func__); + net_warn_ratelimited("%s(), device not present!\n", __func__); netif_stop_queue(netdev); spin_unlock_irqrestore(&self->lock, flags); return; @@ -647,7 +647,8 @@ static void irda_usb_net_timeout(struct net_device *netdev) /* Check speed URB */ urb = self->speed_urb; if (urb->status != 0) { - IRDA_DEBUG(0, "%s: Speed change timed out, urb->status=%d, urb->transfer_flags=0x%04X\n", netdev->name, urb->status, urb->transfer_flags); + pr_debug("%s: Speed change timed out, urb->status=%d, urb->transfer_flags=0x%04X\n", + netdev->name, urb->status, urb->transfer_flags); switch (urb->status) { case -EINPROGRESS: @@ -672,7 +673,8 @@ static void irda_usb_net_timeout(struct net_device *netdev) if (urb->status != 0) { struct sk_buff *skb = urb->context; - IRDA_DEBUG(0, "%s: Tx timed out, urb->status=%d, urb->transfer_flags=0x%04X\n", netdev->name, urb->status, urb->transfer_flags); + pr_debug("%s: Tx timed out, urb->status=%d, urb->transfer_flags=0x%04X\n", + netdev->name, urb->status, urb->transfer_flags); /* Increase error count */ netdev->stats.tx_errors++; @@ -761,8 +763,6 @@ static void irda_usb_submit(struct irda_usb_cb *self, struct sk_buff *skb, struc struct irda_skb_cb *cb; int ret; - IRDA_DEBUG(2, "%s()\n", __func__); - /* This should never happen */ IRDA_ASSERT(skb != NULL, return;); IRDA_ASSERT(urb != NULL, return;); @@ -783,8 +783,8 @@ static void irda_usb_submit(struct irda_usb_cb *self, struct sk_buff *skb, struc if (ret) { /* If this ever happen, we are in deep s***. * Basically, the Rx path will stop... */ - IRDA_WARNING("%s(), Failed to submit Rx URB %d\n", - __func__, ret); + net_warn_ratelimited("%s(), Failed to submit Rx URB %d\n", + __func__, ret); } } @@ -805,7 +805,7 @@ static void irda_usb_receive(struct urb *urb) struct urb *next_urb; unsigned int len, docopy; - IRDA_DEBUG(2, "%s(), len=%d\n", __func__, urb->actual_length); + pr_debug("%s(), len=%d\n", __func__, urb->actual_length); /* Find ourselves */ cb = (struct irda_skb_cb *) skb->cb; @@ -815,7 +815,7 @@ static void irda_usb_receive(struct urb *urb) /* If the network is closed or the device gone, stop everything */ if ((!self->netopen) || (!self->present)) { - IRDA_DEBUG(0, "%s(), Network is gone!\n", __func__); + pr_debug("%s(), Network is gone!\n", __func__); /* Don't re-submit the URB : will stall the Rx path */ return; } @@ -838,7 +838,8 @@ static void irda_usb_receive(struct urb *urb) /* Usually precursor to a hot-unplug on OHCI. */ default: self->netdev->stats.rx_errors++; - IRDA_DEBUG(0, "%s(), RX status %d, transfer_flags 0x%04X\n", __func__, urb->status, urb->transfer_flags); + pr_debug("%s(), RX status %d, transfer_flags 0x%04X\n", + __func__, urb->status, urb->transfer_flags); break; } /* If we received an error, we don't want to resubmit the @@ -859,7 +860,7 @@ static void irda_usb_receive(struct urb *urb) /* Check for empty frames */ if (urb->actual_length <= self->header_length) { - IRDA_WARNING("%s(), empty frame!\n", __func__); + net_warn_ratelimited("%s(), empty frame!\n", __func__); goto done; } @@ -964,8 +965,6 @@ static void irda_usb_rx_defer_expired(unsigned long data) struct irda_skb_cb *cb; struct urb *next_urb; - IRDA_DEBUG(2, "%s()\n", __func__); - /* Find ourselves */ cb = (struct irda_skb_cb *) skb->cb; IRDA_ASSERT(cb != NULL, return;); @@ -1049,8 +1048,8 @@ static int stir421x_fw_upload(struct irda_usb_cb *self, self->bulk_out_ep), patch_block, block_size, &actual_len, msecs_to_jiffies(500)); - IRDA_DEBUG(3,"%s(): Bulk send %u bytes, ret=%d\n", - __func__, actual_len, ret); + pr_debug("%s(): Bulk send %u bytes, ret=%d\n", + __func__, actual_len, ret); if (ret < 0) break; @@ -1088,8 +1087,8 @@ static int stir421x_patch_device(struct irda_usb_cb *self) return ret; /* We get a patch from userspace */ - IRDA_MESSAGE("%s(): Received firmware %s (%zu bytes)\n", - __func__, stir421x_fw_name, fw->size); + net_info_ratelimited("%s(): Received firmware %s (%zu bytes)\n", + __func__, stir421x_fw_name, fw->size); ret = -EINVAL; @@ -1112,8 +1111,8 @@ static int stir421x_patch_device(struct irda_usb_cb *self) + ((build / 10) << 4) + (build % 10); - IRDA_DEBUG(3, "%s(): Firmware Product version %ld\n", - __func__, fw_version); + pr_debug("%s(): Firmware Product version %ld\n", + __func__, fw_version); } } @@ -1169,8 +1168,6 @@ static int irda_usb_net_open(struct net_device *netdev) char hwname[16]; int i; - IRDA_DEBUG(1, "%s()\n", __func__); - IRDA_ASSERT(netdev != NULL, return -1;); self = netdev_priv(netdev); IRDA_ASSERT(self != NULL, return -1;); @@ -1179,13 +1176,13 @@ static int irda_usb_net_open(struct net_device *netdev) /* Can only open the device if it's there */ if(!self->present) { spin_unlock_irqrestore(&self->lock, flags); - IRDA_WARNING("%s(), device not present!\n", __func__); + net_warn_ratelimited("%s(), device not present!\n", __func__); return -1; } if(self->needspatch) { spin_unlock_irqrestore(&self->lock, flags); - IRDA_WARNING("%s(), device needs patch\n", __func__) ; + net_warn_ratelimited("%s(), device needs patch\n", __func__); return -EIO ; } @@ -1227,8 +1224,6 @@ static int irda_usb_net_open(struct net_device *netdev) if (!skb) { /* If this ever happen, we are in deep s***. * Basically, we can't start the Rx path... */ - IRDA_WARNING("%s(), Failed to allocate Rx skb\n", - __func__); return -1; } //skb_reserve(newskb, USB_IRDA_HEADER - 1); @@ -1251,8 +1246,6 @@ static int irda_usb_net_close(struct net_device *netdev) struct irda_usb_cb *self; int i; - IRDA_DEBUG(1, "%s()\n", __func__); - IRDA_ASSERT(netdev != NULL, return -1;); self = netdev_priv(netdev); IRDA_ASSERT(self != NULL, return -1;); @@ -1306,7 +1299,7 @@ static int irda_usb_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) self = netdev_priv(dev); IRDA_ASSERT(self != NULL, return -1;); - IRDA_DEBUG(2, "%s(), %s, (cmd=0x%X)\n", __func__, dev->name, cmd); + pr_debug("%s(), %s, (cmd=0x%X)\n", __func__, dev->name, cmd); switch (cmd) { case SIOCSBANDWIDTH: /* Set bandwidth */ @@ -1356,7 +1349,6 @@ static inline void irda_usb_init_qos(struct irda_usb_cb *self) { struct irda_class_desc *desc; - IRDA_DEBUG(3, "%s()\n", __func__); desc = self->irda_desc; @@ -1372,8 +1364,10 @@ static inline void irda_usb_init_qos(struct irda_usb_cb *self) self->qos.window_size.bits = desc->bmWindowSize; self->qos.data_size.bits = desc->bmDataSize; - IRDA_DEBUG(0, "%s(), dongle says speed=0x%X, size=0x%X, window=0x%X, bofs=0x%X, turn=0x%X\n", - __func__, self->qos.baud_rate.bits, self->qos.data_size.bits, self->qos.window_size.bits, self->qos.additional_bofs.bits, self->qos.min_turn_time.bits); + pr_debug("%s(), dongle says speed=0x%X, size=0x%X, window=0x%X, bofs=0x%X, turn=0x%X\n", + __func__, self->qos.baud_rate.bits, self->qos.data_size.bits, + self->qos.window_size.bits, self->qos.additional_bofs.bits, + self->qos.min_turn_time.bits); /* Don't always trust what the dongle tell us */ if(self->capability & IUC_SIR_ONLY) @@ -1416,8 +1410,6 @@ static inline int irda_usb_open(struct irda_usb_cb *self) { struct net_device *netdev = self->netdev; - IRDA_DEBUG(1, "%s()\n", __func__); - netdev->netdev_ops = &irda_usb_netdev_ops; irda_usb_init_qos(self); @@ -1432,8 +1424,6 @@ static inline int irda_usb_open(struct irda_usb_cb *self) */ static inline void irda_usb_close(struct irda_usb_cb *self) { - IRDA_DEBUG(1, "%s()\n", __func__); - /* Remove netdevice */ unregister_netdev(self->netdev); @@ -1505,13 +1495,15 @@ static inline int irda_usb_parse_endpoints(struct irda_usb_cb *self, struct usb_ /* This is our interrupt endpoint */ self->bulk_int_ep = ep; } else { - IRDA_ERROR("%s(), Unrecognised endpoint %02X.\n", __func__, ep); + net_err_ratelimited("%s(), Unrecognised endpoint %02X\n", + __func__, ep); } } } - IRDA_DEBUG(0, "%s(), And our endpoints are : in=%02X, out=%02X (%d), int=%02X\n", - __func__, self->bulk_in_ep, self->bulk_out_ep, self->bulk_out_mtu, self->bulk_int_ep); + pr_debug("%s(), And our endpoints are : in=%02X, out=%02X (%d), int=%02X\n", + __func__, self->bulk_in_ep, self->bulk_out_ep, + self->bulk_out_mtu, self->bulk_int_ep); return (self->bulk_in_ep != 0) && (self->bulk_out_ep != 0); } @@ -1573,13 +1565,13 @@ static inline struct irda_class_desc *irda_usb_find_class_desc(struct usb_interf 0, intf->altsetting->desc.bInterfaceNumber, desc, sizeof(*desc), 500); - IRDA_DEBUG(1, "%s(), ret=%d\n", __func__, ret); + pr_debug("%s(), ret=%d\n", __func__, ret); if (ret < sizeof(*desc)) { - IRDA_WARNING("usb-irda: class_descriptor read %s (%d)\n", - (ret<0) ? "failed" : "too short", ret); + net_warn_ratelimited("usb-irda: class_descriptor read %s (%d)\n", + ret < 0 ? "failed" : "too short", ret); } else if (desc->bDescriptorType != USB_DT_IRDA) { - IRDA_WARNING("usb-irda: bad class_descriptor type\n"); + net_warn_ratelimited("usb-irda: bad class_descriptor type\n"); } else { #ifdef IU_DUMP_CLASS_DESC @@ -1622,9 +1614,9 @@ static int irda_usb_probe(struct usb_interface *intf, * don't need to check if the dongle is really ours. * Jean II */ - IRDA_MESSAGE("IRDA-USB found at address %d, Vendor: %x, Product: %x\n", - dev->devnum, le16_to_cpu(dev->descriptor.idVendor), - le16_to_cpu(dev->descriptor.idProduct)); + net_info_ratelimited("IRDA-USB found at address %d, Vendor: %x, Product: %x\n", + dev->devnum, le16_to_cpu(dev->descriptor.idVendor), + le16_to_cpu(dev->descriptor.idProduct)); net = alloc_irdadev(sizeof(*self)); if (!net) @@ -1680,7 +1672,8 @@ static int irda_usb_probe(struct usb_interface *intf, * specify an alternate, but very few driver do like this. * Jean II */ ret = usb_set_interface(dev, intf->altsetting->desc.bInterfaceNumber, 0); - IRDA_DEBUG(1, "usb-irda: set interface %d result %d\n", intf->altsetting->desc.bInterfaceNumber, ret); + pr_debug("usb-irda: set interface %d result %d\n", + intf->altsetting->desc.bInterfaceNumber, ret); switch (ret) { case 0: break; @@ -1688,10 +1681,11 @@ static int irda_usb_probe(struct usb_interface *intf, /* Martin Diehl says if we get a -EPIPE we should * be fine and we don't need to do a usb_clear_halt(). * - Jean II */ - IRDA_DEBUG(0, "%s(), Received -EPIPE, ignoring...\n", __func__); + pr_debug("%s(), Received -EPIPE, ignoring...\n", + __func__); break; default: - IRDA_DEBUG(0, "%s(), Unknown error %d\n", __func__, ret); + pr_debug("%s(), Unknown error %d\n", __func__, ret); ret = -EIO; goto err_out_3; } @@ -1700,7 +1694,7 @@ static int irda_usb_probe(struct usb_interface *intf, interface = intf->cur_altsetting; if(!irda_usb_parse_endpoints(self, interface->endpoint, interface->desc.bNumEndpoints)) { - IRDA_ERROR("%s(), Bogus endpoints...\n", __func__); + net_err_ratelimited("%s(), Bogus endpoints...\n", __func__); ret = -EIO; goto err_out_3; } @@ -1717,7 +1711,7 @@ static int irda_usb_probe(struct usb_interface *intf, ret = usb_control_msg (self->usbdev, usb_sndctrlpipe (self->usbdev, 0), 0x02, 0x40, 0, 0, NULL, 0, 500); if (ret < 0) { - IRDA_DEBUG (0, "usb_control_msg failed %d\n", ret); + pr_debug("usb_control_msg failed %d\n", ret); goto err_out_3; } else { mdelay(10); @@ -1746,7 +1740,7 @@ static int irda_usb_probe(struct usb_interface *intf, if (ret) goto err_out_5; - IRDA_MESSAGE("IrDA: Registered device %s\n", net->name); + net_info_ratelimited("IrDA: Registered device %s\n", net->name); usb_set_intfdata(intf, self); if (self->needspatch) { @@ -1754,7 +1748,7 @@ static int irda_usb_probe(struct usb_interface *intf, ret = stir421x_patch_device(self); self->needspatch = (ret < 0); if (self->needspatch) { - IRDA_ERROR("STIR421X: Couldn't upload patch\n"); + net_err_ratelimited("STIR421X: Couldn't upload patch\n"); goto err_out_6; } @@ -1809,8 +1803,6 @@ static void irda_usb_disconnect(struct usb_interface *intf) struct irda_usb_cb *self = usb_get_intfdata(intf); int i; - IRDA_DEBUG(1, "%s()\n", __func__); - usb_set_intfdata(intf, NULL); if (!self) return; @@ -1859,7 +1851,7 @@ static void irda_usb_disconnect(struct usb_interface *intf) /* Free self and network device */ free_netdev(self->netdev); - IRDA_DEBUG(0, "%s(), USB IrDA Disconnected\n", __func__); + pr_debug("%s(), USB IrDA Disconnected\n", __func__); } #ifdef CONFIG_PM diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c index 24b6dddd7f2f..696852eb23c3 100644 --- a/drivers/net/irda/irtty-sir.c +++ b/drivers/net/irda/irtty-sir.c @@ -231,7 +231,7 @@ static void irtty_receive_buf(struct tty_struct *tty, const unsigned char *cp, dev = priv->dev; if (!dev) { - IRDA_WARNING("%s(), not ready yet!\n", __func__); + net_warn_ratelimited("%s(), not ready yet!\n", __func__); return; } @@ -240,7 +240,7 @@ static void irtty_receive_buf(struct tty_struct *tty, const unsigned char *cp, * Characters received with a parity error, etc? */ if (fp && *fp++) { - IRDA_DEBUG(0, "Framing or parity error!\n"); + pr_debug("Framing or parity error!\n"); sirdev_receive(dev, NULL, 0); /* notify sir_dev (updating stats) */ return; } @@ -387,7 +387,7 @@ static int irtty_ioctl(struct tty_struct *tty, struct file *file, unsigned int c IRDA_ASSERT(priv != NULL, return -ENODEV;); IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return -EBADR;); - IRDA_DEBUG(3, "%s(cmd=0x%X)\n", __func__, cmd); + pr_debug("%s(cmd=0x%X)\n", __func__, cmd); dev = priv->dev; IRDA_ASSERT(dev != NULL, return -1;); @@ -477,7 +477,7 @@ static int irtty_open(struct tty_struct *tty) mutex_unlock(&irtty_mutex); - IRDA_DEBUG(0, "%s - %s: irda line discipline opened\n", __func__, tty->name); + pr_debug("%s - %s: irda line discipline opened\n", __func__, tty->name); return 0; @@ -528,7 +528,7 @@ static void irtty_close(struct tty_struct *tty) kfree(priv); - IRDA_DEBUG(0, "%s - %s: irda line discipline closed\n", __func__, tty->name); + pr_debug("%s - %s: irda line discipline closed\n", __func__, tty->name); } /* ------------------------------------------------------- */ @@ -555,8 +555,8 @@ static int __init irtty_sir_init(void) int err; if ((err = tty_register_ldisc(N_IRDA, &irda_ldisc)) != 0) - IRDA_ERROR("IrDA: can't register line discipline (err = %d)\n", - err); + net_err_ratelimited("IrDA: can't register line discipline (err = %d)\n", + err); return err; } @@ -565,8 +565,8 @@ static void __exit irtty_sir_cleanup(void) int err; if ((err = tty_unregister_ldisc(N_IRDA))) { - IRDA_ERROR("%s(), can't unregister line discipline (err = %d)\n", - __func__, err); + net_err_ratelimited("%s(), can't unregister line discipline (err = %d)\n", + __func__, err); } } diff --git a/drivers/net/irda/litelink-sir.c b/drivers/net/irda/litelink-sir.c index 6827777cbeea..8eefcb44bac3 100644 --- a/drivers/net/irda/litelink-sir.c +++ b/drivers/net/irda/litelink-sir.c @@ -76,8 +76,6 @@ static int litelink_open(struct sir_dev *dev) { struct qos_info *qos = &dev->qos; - IRDA_DEBUG(2, "%s()\n", __func__); - /* Power up dongle */ sirdev_set_dtr_rts(dev, TRUE, TRUE); @@ -93,8 +91,6 @@ static int litelink_open(struct sir_dev *dev) static int litelink_close(struct sir_dev *dev) { - IRDA_DEBUG(2, "%s()\n", __func__); - /* Power off dongle */ sirdev_set_dtr_rts(dev, FALSE, FALSE); @@ -111,8 +107,6 @@ static int litelink_change_speed(struct sir_dev *dev, unsigned speed) { int i; - IRDA_DEBUG(2, "%s()\n", __func__); - /* dongle already reset by irda-thread - current speed (dongle and * port) is the default speed (115200 for litelink!) */ @@ -154,8 +148,6 @@ static int litelink_change_speed(struct sir_dev *dev, unsigned speed) */ static int litelink_reset(struct sir_dev *dev) { - IRDA_DEBUG(2, "%s()\n", __func__); - /* probably the power-up can be dropped here, but with only * 15 usec delay it's not worth the risk unless somebody with * the hardware confirms it doesn't break anything... diff --git a/drivers/net/irda/ma600-sir.c b/drivers/net/irda/ma600-sir.c index a9a81358477b..a764817b47f1 100644 --- a/drivers/net/irda/ma600-sir.c +++ b/drivers/net/irda/ma600-sir.c @@ -65,13 +65,11 @@ static struct dongle_driver ma600 = { static int __init ma600_sir_init(void) { - IRDA_DEBUG(2, "%s()\n", __func__); return irda_register_dongle(&ma600); } static void __exit ma600_sir_cleanup(void) { - IRDA_DEBUG(2, "%s()\n", __func__); irda_unregister_dongle(&ma600); } @@ -86,8 +84,6 @@ static int ma600_open(struct sir_dev *dev) { struct qos_info *qos = &dev->qos; - IRDA_DEBUG(2, "%s()\n", __func__); - sirdev_set_dtr_rts(dev, TRUE, TRUE); /* Explicitly set the speeds we can accept */ @@ -104,8 +100,6 @@ static int ma600_open(struct sir_dev *dev) static int ma600_close(struct sir_dev *dev) { - IRDA_DEBUG(2, "%s()\n", __func__); - /* Power off dongle */ sirdev_set_dtr_rts(dev, FALSE, FALSE); @@ -174,8 +168,8 @@ static int ma600_change_speed(struct sir_dev *dev, unsigned speed) { u8 byte; - IRDA_DEBUG(2, "%s(), speed=%d (was %d)\n", __func__, - speed, dev->speed); + pr_debug("%s(), speed=%d (was %d)\n", __func__, + speed, dev->speed); /* dongle already reset, dongle and port at default speed (9600) */ @@ -198,13 +192,13 @@ static int ma600_change_speed(struct sir_dev *dev, unsigned speed) sirdev_raw_read(dev, &byte, sizeof(byte)); if (byte != get_control_byte(speed)) { - IRDA_WARNING("%s(): bad control byte read-back %02x != %02x\n", - __func__, (unsigned) byte, - (unsigned) get_control_byte(speed)); + net_warn_ratelimited("%s(): bad control byte read-back %02x != %02x\n", + __func__, (unsigned)byte, + (unsigned)get_control_byte(speed)); return -1; } else - IRDA_DEBUG(2, "%s() control byte write read OK\n", __func__); + pr_debug("%s() control byte write read OK\n", __func__); #endif /* Set DTR, Set RTS */ @@ -236,8 +230,6 @@ static int ma600_change_speed(struct sir_dev *dev, unsigned speed) static int ma600_reset(struct sir_dev *dev) { - IRDA_DEBUG(2, "%s()\n", __func__); - /* Reset the dongle : set DTR low for 10 ms */ sirdev_set_dtr_rts(dev, FALSE, TRUE); msleep(10); diff --git a/drivers/net/irda/mcp2120-sir.c b/drivers/net/irda/mcp2120-sir.c index 5e2f4859cee7..2e33f91bfe8f 100644 --- a/drivers/net/irda/mcp2120-sir.c +++ b/drivers/net/irda/mcp2120-sir.c @@ -63,8 +63,6 @@ static int mcp2120_open(struct sir_dev *dev) { struct qos_info *qos = &dev->qos; - IRDA_DEBUG(2, "%s()\n", __func__); - /* seems no explicit power-on required here and reset switching it on anyway */ qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200; @@ -76,8 +74,6 @@ static int mcp2120_open(struct sir_dev *dev) static int mcp2120_close(struct sir_dev *dev) { - IRDA_DEBUG(2, "%s()\n", __func__); - /* Power off dongle */ /* reset and inhibit mcp2120 */ sirdev_set_dtr_rts(dev, TRUE, TRUE); @@ -102,8 +98,6 @@ static int mcp2120_change_speed(struct sir_dev *dev, unsigned speed) u8 control[2]; static int ret = 0; - IRDA_DEBUG(2, "%s()\n", __func__); - switch (state) { case SIRDEV_STATE_DONGLE_SPEED: /* Set DTR to enter command mode */ @@ -155,7 +149,8 @@ static int mcp2120_change_speed(struct sir_dev *dev, unsigned speed) break; default: - IRDA_ERROR("%s(), undefine state %d\n", __func__, state); + net_err_ratelimited("%s(), undefine state %d\n", + __func__, state); ret = -EINVAL; break; } @@ -187,8 +182,6 @@ static int mcp2120_reset(struct sir_dev *dev) unsigned delay = 0; int ret = 0; - IRDA_DEBUG(2, "%s()\n", __func__); - switch (state) { case SIRDEV_STATE_DONGLE_RESET: //printk("mcp2120_reset: dongle_reset\n"); @@ -213,7 +206,8 @@ static int mcp2120_reset(struct sir_dev *dev) break; default: - IRDA_ERROR("%s(), undefined state %d\n", __func__, state); + net_err_ratelimited("%s(), undefined state %d\n", + __func__, state); ret = -EINVAL; break; } diff --git a/drivers/net/irda/mcs7780.c b/drivers/net/irda/mcs7780.c index 16f8ffb50e04..e4d678fbeb2f 100644 --- a/drivers/net/irda/mcs7780.c +++ b/drivers/net/irda/mcs7780.c @@ -197,14 +197,14 @@ error: /* Setup a communication between mcs7780 and agilent chip. */ static inline int mcs_setup_transceiver_agilent(struct mcs_cb *mcs) { - IRDA_WARNING("This transceiver type is not supported yet.\n"); + net_warn_ratelimited("This transceiver type is not supported yet\n"); return 1; } /* Setup a communication between mcs7780 and sharp chip. */ static inline int mcs_setup_transceiver_sharp(struct mcs_cb *mcs) { - IRDA_WARNING("This transceiver type is not supported yet.\n"); + net_warn_ratelimited("This transceiver type is not supported yet\n"); return 1; } @@ -213,9 +213,9 @@ static inline int mcs_setup_transceiver(struct mcs_cb *mcs) { int ret = 0; __u16 rval; - char *msg; + const char *msg; - msg = "Basic transceiver setup error."; + msg = "Basic transceiver setup error"; /* read value of MODE Register, set the DRIVER and RESET bits * and write value back out to MODE Register @@ -261,7 +261,7 @@ static inline int mcs_setup_transceiver(struct mcs_cb *mcs) if(unlikely(ret)) goto error; - msg = "transceiver model specific setup error."; + msg = "transceiver model specific setup error"; switch (mcs->transceiver_type) { case MCS_TSC_VISHAY: ret = mcs_setup_transceiver_vishay(mcs); @@ -276,8 +276,8 @@ static inline int mcs_setup_transceiver(struct mcs_cb *mcs) break; default: - IRDA_WARNING("Unknown transceiver type: %d\n", - mcs->transceiver_type); + net_warn_ratelimited("Unknown transceiver type: %d\n", + mcs->transceiver_type); ret = 1; } if (unlikely(ret)) @@ -300,7 +300,7 @@ static inline int mcs_setup_transceiver(struct mcs_cb *mcs) goto error; } - msg = "transceiver reset."; + msg = "transceiver reset"; ret = mcs_get_reg(mcs, MCS_MODE_REG, &rval); if (unlikely(ret != 2)) @@ -315,7 +315,7 @@ static inline int mcs_setup_transceiver(struct mcs_cb *mcs) return ret; error: - IRDA_ERROR("%s\n", msg); + net_err_ratelimited("%s\n", msg); return ret; } @@ -399,8 +399,8 @@ static void mcs_unwrap_mir(struct mcs_cb *mcs, __u8 *buf, int len) new_len = len - 2; if(unlikely(new_len <= 0)) { - IRDA_ERROR("%s short frame length %d\n", - mcs->netdev->name, new_len); + net_err_ratelimited("%s short frame length %d\n", + mcs->netdev->name, new_len); ++mcs->netdev->stats.rx_errors; ++mcs->netdev->stats.rx_length_errors; return; @@ -409,8 +409,8 @@ static void mcs_unwrap_mir(struct mcs_cb *mcs, __u8 *buf, int len) fcs = irda_calc_crc16(~fcs, buf, len); if(fcs != GOOD_FCS) { - IRDA_ERROR("crc error calc 0x%x len %d\n", - fcs, new_len); + net_err_ratelimited("crc error calc 0x%x len %d\n", + fcs, new_len); mcs->netdev->stats.rx_errors++; mcs->netdev->stats.rx_crc_errors++; return; @@ -452,8 +452,8 @@ static void mcs_unwrap_fir(struct mcs_cb *mcs, __u8 *buf, int len) new_len = len - 4; if(unlikely(new_len <= 0)) { - IRDA_ERROR("%s short frame length %d\n", - mcs->netdev->name, new_len); + net_err_ratelimited("%s short frame length %d\n", + mcs->netdev->name, new_len); ++mcs->netdev->stats.rx_errors; ++mcs->netdev->stats.rx_length_errors; return; @@ -461,7 +461,8 @@ static void mcs_unwrap_fir(struct mcs_cb *mcs, __u8 *buf, int len) fcs = ~(crc32_le(~0, buf, new_len)); if(fcs != get_unaligned_le32(buf + new_len)) { - IRDA_ERROR("crc error calc 0x%x len %d\n", fcs, new_len); + net_err_ratelimited("crc error calc 0x%x len %d\n", + fcs, new_len); mcs->netdev->stats.rx_errors++; mcs->netdev->stats.rx_crc_errors++; return; @@ -583,7 +584,7 @@ static int mcs_speed_change(struct mcs_cb *mcs) } while(cnt++ < 100 && (rval & MCS_IRINTX)); if (cnt > 100) { - IRDA_ERROR("unable to change speed\n"); + net_err_ratelimited("unable to change speed\n"); ret = -EIO; goto error; } @@ -634,8 +635,8 @@ static int mcs_speed_change(struct mcs_cb *mcs) default: ret = 1; - IRDA_WARNING("Unknown transceiver type: %d\n", - mcs->transceiver_type); + net_warn_ratelimited("Unknown transceiver type: %d\n", + mcs->transceiver_type); } if (unlikely(ret)) goto error; @@ -731,7 +732,7 @@ static int mcs_net_open(struct net_device *netdev) sprintf(hwname, "usb#%d", mcs->usbdev->devnum); mcs->irlap = irlap_open(netdev, &mcs->qos, hwname); if (!mcs->irlap) { - IRDA_ERROR("mcs7780: irlap_open failed\n"); + net_err_ratelimited("mcs7780: irlap_open failed\n"); goto error2; } @@ -851,7 +852,7 @@ static netdev_tx_t mcs_hard_xmit(struct sk_buff *skb, mcs->out_buf, wraplen, mcs_send_irq, mcs); if ((ret = usb_submit_urb(mcs->tx_urb, GFP_ATOMIC))) { - IRDA_ERROR("failed tx_urb: %d\n", ret); + net_err_ratelimited("failed tx_urb: %d\n", ret); switch (ret) { case -ENODEV: case -EPIPE: @@ -893,13 +894,13 @@ static int mcs_probe(struct usb_interface *intf, if (!ndev) goto error1; - IRDA_DEBUG(1, "MCS7780 USB-IrDA bridge found at %d.\n", udev->devnum); + pr_debug("MCS7780 USB-IrDA bridge found at %d.\n", udev->devnum); SET_NETDEV_DEV(ndev, &intf->dev); ret = usb_reset_configuration(udev); if (ret != 0) { - IRDA_ERROR("mcs7780: usb reset configuration failed\n"); + net_err_ratelimited("mcs7780: usb reset configuration failed\n"); goto error2; } @@ -941,8 +942,8 @@ static int mcs_probe(struct usb_interface *intf, if (ret != 0) goto error2; - IRDA_DEBUG(1, "IrDA: Registered MosChip MCS7780 device as %s\n", - ndev->name); + pr_debug("IrDA: Registered MosChip MCS7780 device as %s\n", + ndev->name); mcs->transceiver_type = transceiver_type; mcs->sir_tweak = sir_tweak; @@ -972,7 +973,7 @@ static void mcs_disconnect(struct usb_interface *intf) free_netdev(mcs->netdev); usb_set_intfdata(intf, NULL); - IRDA_DEBUG(0, "MCS7780 now disconnected.\n"); + pr_debug("MCS7780 now disconnected.\n"); } module_usb_driver(mcs_driver); diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c index 66bc03bdb138..e7317b104bfb 100644 --- a/drivers/net/irda/nsc-ircc.c +++ b/drivers/net/irda/nsc-ircc.c @@ -211,7 +211,8 @@ static int __init nsc_ircc_init(void) ret = platform_driver_register(&nsc_ircc_driver); if (ret) { - IRDA_ERROR("%s, Can't register driver!\n", driver_name); + net_err_ratelimited("%s, Can't register driver!\n", + driver_name); return ret; } @@ -225,8 +226,8 @@ static int __init nsc_ircc_init(void) /* Probe for all the NSC chipsets we know about */ for (chip = chips; chip->name ; chip++) { - IRDA_DEBUG(2, "%s(), Probing for %s ...\n", __func__, - chip->name); + pr_debug("%s(), Probing for %s ...\n", __func__, + chip->name); /* Try all config registers for this chip */ for (cfg = 0; cfg < ARRAY_SIZE(chip->cfg); cfg++) { @@ -237,7 +238,8 @@ static int __init nsc_ircc_init(void) /* Read index register */ reg = inb(cfg_base); if (reg == 0xff) { - IRDA_DEBUG(2, "%s() no chip at 0x%03x\n", __func__, cfg_base); + pr_debug("%s() no chip at 0x%03x\n", + __func__, cfg_base); continue; } @@ -245,8 +247,9 @@ static int __init nsc_ircc_init(void) outb(chip->cid_index, cfg_base); id = inb(cfg_base+1); if ((id & chip->cid_mask) == chip->cid_value) { - IRDA_DEBUG(2, "%s() Found %s chip, revision=%d\n", - __func__, chip->name, id & ~chip->cid_mask); + pr_debug("%s() Found %s chip, revision=%d\n", + __func__, chip->name, + id & ~chip->cid_mask); /* * If we found a correct PnP setting, @@ -260,7 +263,8 @@ static int __init nsc_ircc_init(void) info.irq = pnp_info.irq; if (info.fir_base < 0x2000) { - IRDA_MESSAGE("%s, chip->init\n", driver_name); + net_info_ratelimited("%s, chip->init\n", + driver_name); chip->init(chip, &info); } else chip->probe(chip, &info); @@ -275,7 +279,8 @@ static int __init nsc_ircc_init(void) * the chip. */ if (ret) { - IRDA_DEBUG(2, "%s, PnP init failed\n", driver_name); + pr_debug("%s, PnP init failed\n", + driver_name); memset(&info, 0, sizeof(chipio_t)); info.cfg_base = cfg_base; info.fir_base = io[i]; @@ -297,7 +302,8 @@ static int __init nsc_ircc_init(void) } i++; } else { - IRDA_DEBUG(2, "%s(), Wrong chip id=0x%02x\n", __func__, id); + pr_debug("%s(), Wrong chip id=0x%02x\n", + __func__, id); } } } @@ -361,31 +367,29 @@ static int __init nsc_ircc_open(chipio_t *info) void *ret; int err, chip_index; - IRDA_DEBUG(2, "%s()\n", __func__); - - for (chip_index = 0; chip_index < ARRAY_SIZE(dev_self); chip_index++) { if (!dev_self[chip_index]) break; } if (chip_index == ARRAY_SIZE(dev_self)) { - IRDA_ERROR("%s(), maximum number of supported chips reached!\n", __func__); + net_err_ratelimited("%s(), maximum number of supported chips reached!\n", + __func__); return -ENOMEM; } - IRDA_MESSAGE("%s, Found chip at base=0x%03x\n", driver_name, - info->cfg_base); + net_info_ratelimited("%s, Found chip at base=0x%03x\n", + driver_name, info->cfg_base); if ((nsc_ircc_setup(info)) == -1) return -1; - IRDA_MESSAGE("%s, driver loaded (Dag Brattli)\n", driver_name); + net_info_ratelimited("%s, driver loaded (Dag Brattli)\n", driver_name); dev = alloc_irdadev(sizeof(struct nsc_ircc_cb)); if (dev == NULL) { - IRDA_ERROR("%s(), can't allocate memory for " - "control block!\n", __func__); + net_err_ratelimited("%s(), can't allocate memory for control block!\n", + __func__); return -ENOMEM; } @@ -408,8 +412,8 @@ static int __init nsc_ircc_open(chipio_t *info) /* Reserve the ioports that we need */ ret = request_region(self->io.fir_base, self->io.fir_ext, driver_name); if (!ret) { - IRDA_WARNING("%s(), can't get iobase of 0x%03x\n", - __func__, self->io.fir_base); + net_warn_ratelimited("%s(), can't get iobase of 0x%03x\n", + __func__, self->io.fir_base); err = -ENODEV; goto out1; } @@ -460,21 +464,22 @@ static int __init nsc_ircc_open(chipio_t *info) err = register_netdev(dev); if (err) { - IRDA_ERROR("%s(), register_netdev() failed!\n", __func__); + net_err_ratelimited("%s(), register_netdev() failed!\n", + __func__); goto out4; } - IRDA_MESSAGE("IrDA: Registered device %s\n", dev->name); + net_info_ratelimited("IrDA: Registered device %s\n", dev->name); /* Check if user has supplied a valid dongle id or not */ if ((dongle_id <= 0) || (dongle_id >= ARRAY_SIZE(dongle_types))) { dongle_id = nsc_ircc_read_dongle_id(self->io.fir_base); - IRDA_MESSAGE("%s, Found dongle: %s\n", driver_name, - dongle_types[dongle_id]); + net_info_ratelimited("%s, Found dongle: %s\n", + driver_name, dongle_types[dongle_id]); } else { - IRDA_MESSAGE("%s, Using dongle: %s\n", driver_name, - dongle_types[dongle_id]); + net_info_ratelimited("%s, Using dongle: %s\n", + driver_name, dongle_types[dongle_id]); } self->io.dongle_id = dongle_id; @@ -516,8 +521,6 @@ static int __exit nsc_ircc_close(struct nsc_ircc_cb *self) { int iobase; - IRDA_DEBUG(4, "%s()\n", __func__); - IRDA_ASSERT(self != NULL, return -1;); iobase = self->io.fir_base; @@ -528,8 +531,8 @@ static int __exit nsc_ircc_close(struct nsc_ircc_cb *self) unregister_netdev(self->netdev); /* Release the PORT that this driver is using */ - IRDA_DEBUG(4, "%s(), Releasing Region %03x\n", - __func__, self->io.fir_base); + pr_debug("%s(), Releasing Region %03x\n", + __func__, self->io.fir_base); release_region(self->io.fir_base, self->io.fir_ext); if (self->tx_buff.head) @@ -567,7 +570,7 @@ static int nsc_ircc_init_108(nsc_chip_t *chip, chipio_t *info) case 0x2e8: outb(0x15, cfg_base+1); break; case 0x3f8: outb(0x16, cfg_base+1); break; case 0x2f8: outb(0x17, cfg_base+1); break; - default: IRDA_ERROR("%s(), invalid base_address", __func__); + default: net_err_ratelimited("%s(), invalid base_address\n", __func__); } /* Control Signal Routing Register (CSRT) */ @@ -579,7 +582,7 @@ static int nsc_ircc_init_108(nsc_chip_t *chip, chipio_t *info) case 9: temp = 0x05; break; case 11: temp = 0x06; break; case 15: temp = 0x07; break; - default: IRDA_ERROR("%s(), invalid irq", __func__); + default: net_err_ratelimited("%s(), invalid irq\n", __func__); } outb(CFG_108_CSRT, cfg_base); @@ -587,7 +590,7 @@ static int nsc_ircc_init_108(nsc_chip_t *chip, chipio_t *info) case 0: outb(0x08+temp, cfg_base+1); break; case 1: outb(0x10+temp, cfg_base+1); break; case 3: outb(0x18+temp, cfg_base+1); break; - default: IRDA_ERROR("%s(), invalid dma", __func__); + default: net_err_ratelimited("%s(), invalid dma\n", __func__); } outb(CFG_108_MCTL, cfg_base); /* Mode Control Register (MCTL) */ @@ -626,8 +629,8 @@ static int nsc_ircc_probe_108(nsc_chip_t *chip, chipio_t *info) break; } info->sir_base = info->fir_base; - IRDA_DEBUG(2, "%s(), probing fir_base=0x%03x\n", __func__, - info->fir_base); + pr_debug("%s(), probing fir_base=0x%03x\n", __func__, + info->fir_base); /* Read control signals routing register (CSRT) */ outb(CFG_108_CSRT, cfg_base); @@ -659,7 +662,7 @@ static int nsc_ircc_probe_108(nsc_chip_t *chip, chipio_t *info) info->irq = 15; break; } - IRDA_DEBUG(2, "%s(), probing irq=%d\n", __func__, info->irq); + pr_debug("%s(), probing irq=%d\n", __func__, info->irq); /* Currently we only read Rx DMA but it will also be used for Tx */ switch ((reg >> 3) & 0x03) { @@ -676,7 +679,7 @@ static int nsc_ircc_probe_108(nsc_chip_t *chip, chipio_t *info) info->dma = 3; break; } - IRDA_DEBUG(2, "%s(), probing dma=%d\n", __func__, info->dma); + pr_debug("%s(), probing dma=%d\n", __func__, info->dma); /* Read mode control register (MCTL) */ outb(CFG_108_MCTL, cfg_base); @@ -727,7 +730,7 @@ static int nsc_ircc_probe_338(nsc_chip_t *chip, chipio_t *info) pnp = (reg >> 3) & 0x01; if (pnp) { - IRDA_DEBUG(2, "(), Chip is in PnP mode\n"); + pr_debug("(), Chip is in PnP mode\n"); outb(0x46, cfg_base); reg = (inb(cfg_base+1) & 0xfe) << 2; @@ -831,9 +834,8 @@ static int nsc_ircc_init_39x(nsc_chip_t *chip, chipio_t *info) int enabled; /* User is sure about his config... accept it. */ - IRDA_DEBUG(2, "%s(): nsc_ircc_init_39x (user settings): " - "io=0x%04x, irq=%d, dma=%d\n", - __func__, info->fir_base, info->irq, info->dma); + pr_debug("%s(): nsc_ircc_init_39x (user settings): io=0x%04x, irq=%d, dma=%d\n", + __func__, info->fir_base, info->irq, info->dma); /* Access bank for SP2 */ outb(CFG_39X_LDN, cfg_base); @@ -873,8 +875,8 @@ static int nsc_ircc_probe_39x(nsc_chip_t *chip, chipio_t *info) int reg1, reg2, irq, irqt, dma1, dma2; int enabled, susp; - IRDA_DEBUG(2, "%s(), nsc_ircc_probe_39x, base=%d\n", - __func__, cfg_base); + pr_debug("%s(), nsc_ircc_probe_39x, base=%d\n", + __func__, cfg_base); /* This function should be executed with irq off to avoid * another driver messing with the Super I/O bank - Jean II */ @@ -908,7 +910,8 @@ static int nsc_ircc_probe_39x(nsc_chip_t *chip, chipio_t *info) outb(CFG_39X_SPC, cfg_base); susp = 1 - ((inb(cfg_base+1) & 0x02) >> 1); - IRDA_DEBUG(2, "%s(): io=0x%02x%02x, irq=%d (type %d), rxdma=%d, txdma=%d, enabled=%d (suspended=%d)\n", __func__, reg1,reg2,irq,irqt,dma1,dma2,enabled,susp); + pr_debug("%s(): io=0x%02x%02x, irq=%d (type %d), rxdma=%d, txdma=%d, enabled=%d (suspended=%d)\n", + __func__, reg1, reg2, irq, irqt, dma1, dma2, enabled, susp); /* Configure SP2 */ @@ -959,8 +962,8 @@ static int nsc_ircc_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *i !(pnp_dma_flags(dev, 0) & IORESOURCE_DISABLED)) pnp_info.dma = pnp_dma(dev, 0); - IRDA_DEBUG(0, "%s() : From PnP, found firbase 0x%03X ; irq %d ; dma %d.\n", - __func__, pnp_info.fir_base, pnp_info.irq, pnp_info.dma); + pr_debug("%s() : From PnP, found firbase 0x%03X ; irq %d ; dma %d.\n", + __func__, pnp_info.fir_base, pnp_info.irq, pnp_info.dma); if((pnp_info.fir_base == 0) || (pnp_info.irq == -1) || (pnp_info.dma == -1)) { @@ -988,13 +991,13 @@ static int nsc_ircc_setup(chipio_t *info) switch_bank(iobase, BANK3); version = inb(iobase+MID); - IRDA_DEBUG(2, "%s() Driver %s Found chip version %02x\n", - __func__, driver_name, version); + pr_debug("%s() Driver %s Found chip version %02x\n", + __func__, driver_name, version); /* Should be 0x2? */ if (0x20 != (version & 0xf0)) { - IRDA_ERROR("%s, Wrong chip version %02x\n", - driver_name, version); + net_err_ratelimited("%s, Wrong chip version %02x\n", + driver_name, version); return -1; } @@ -1092,39 +1095,39 @@ static void nsc_ircc_init_dongle_interface (int iobase, int dongle_id) switch (dongle_id) { case 0x00: /* same as */ case 0x01: /* Differential serial interface */ - IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n", - __func__, dongle_types[dongle_id]); + pr_debug("%s(), %s not defined by irda yet\n", + __func__, dongle_types[dongle_id]); break; case 0x02: /* same as */ case 0x03: /* Reserved */ - IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n", - __func__, dongle_types[dongle_id]); + pr_debug("%s(), %s not defined by irda yet\n", + __func__, dongle_types[dongle_id]); break; case 0x04: /* Sharp RY5HD01 */ break; case 0x05: /* Reserved, but this is what the Thinkpad reports */ - IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n", - __func__, dongle_types[dongle_id]); + pr_debug("%s(), %s not defined by irda yet\n", + __func__, dongle_types[dongle_id]); break; case 0x06: /* Single-ended serial interface */ - IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n", - __func__, dongle_types[dongle_id]); + pr_debug("%s(), %s not defined by irda yet\n", + __func__, dongle_types[dongle_id]); break; case 0x07: /* Consumer-IR only */ - IRDA_DEBUG(0, "%s(), %s is not for IrDA mode\n", - __func__, dongle_types[dongle_id]); + pr_debug("%s(), %s is not for IrDA mode\n", + __func__, dongle_types[dongle_id]); break; case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */ - IRDA_DEBUG(0, "%s(), %s\n", - __func__, dongle_types[dongle_id]); + pr_debug("%s(), %s\n", + __func__, dongle_types[dongle_id]); break; case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */ outb(0x28, iobase+7); /* Set irsl[0-2] as output */ break; case 0x0A: /* same as */ case 0x0B: /* Reserved */ - IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n", - __func__, dongle_types[dongle_id]); + pr_debug("%s(), %s not defined by irda yet\n", + __func__, dongle_types[dongle_id]); break; case 0x0C: /* same as */ case 0x0D: /* HP HSDL-1100/HSDL-2100 */ @@ -1138,15 +1141,15 @@ static void nsc_ircc_init_dongle_interface (int iobase, int dongle_id) outb(0x28, iobase+7); /* Set irsl[0-2] as output */ break; case 0x0F: /* No dongle connected */ - IRDA_DEBUG(0, "%s(), %s\n", - __func__, dongle_types[dongle_id]); + pr_debug("%s(), %s\n", + __func__, dongle_types[dongle_id]); switch_bank(iobase, BANK0); outb(0x62, iobase+MCR); break; default: - IRDA_DEBUG(0, "%s(), invalid dongle_id %#x", - __func__, dongle_id); + pr_debug("%s(), invalid dongle_id %#x", + __func__, dongle_id); } /* IRCFG1: IRSL1 and 2 are set to IrDA mode */ @@ -1177,31 +1180,31 @@ static void nsc_ircc_change_dongle_speed(int iobase, int speed, int dongle_id) switch (dongle_id) { case 0x00: /* same as */ case 0x01: /* Differential serial interface */ - IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n", - __func__, dongle_types[dongle_id]); + pr_debug("%s(), %s not defined by irda yet\n", + __func__, dongle_types[dongle_id]); break; case 0x02: /* same as */ case 0x03: /* Reserved */ - IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n", - __func__, dongle_types[dongle_id]); + pr_debug("%s(), %s not defined by irda yet\n", + __func__, dongle_types[dongle_id]); break; case 0x04: /* Sharp RY5HD01 */ break; case 0x05: /* Reserved */ - IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n", - __func__, dongle_types[dongle_id]); + pr_debug("%s(), %s not defined by irda yet\n", + __func__, dongle_types[dongle_id]); break; case 0x06: /* Single-ended serial interface */ - IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n", - __func__, dongle_types[dongle_id]); + pr_debug("%s(), %s not defined by irda yet\n", + __func__, dongle_types[dongle_id]); break; case 0x07: /* Consumer-IR only */ - IRDA_DEBUG(0, "%s(), %s is not for IrDA mode\n", - __func__, dongle_types[dongle_id]); + pr_debug("%s(), %s is not for IrDA mode\n", + __func__, dongle_types[dongle_id]); break; case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */ - IRDA_DEBUG(0, "%s(), %s\n", - __func__, dongle_types[dongle_id]); + pr_debug("%s(), %s\n", + __func__, dongle_types[dongle_id]); outb(0x00, iobase+4); if (speed > 115200) outb(0x01, iobase+4); @@ -1219,8 +1222,8 @@ static void nsc_ircc_change_dongle_speed(int iobase, int speed, int dongle_id) break; case 0x0A: /* same as */ case 0x0B: /* Reserved */ - IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n", - __func__, dongle_types[dongle_id]); + pr_debug("%s(), %s not defined by irda yet\n", + __func__, dongle_types[dongle_id]); break; case 0x0C: /* same as */ case 0x0D: /* HP HSDL-1100/HSDL-2100 */ @@ -1228,14 +1231,14 @@ static void nsc_ircc_change_dongle_speed(int iobase, int speed, int dongle_id) case 0x0E: /* Supports SIR Mode only */ break; case 0x0F: /* No dongle connected */ - IRDA_DEBUG(0, "%s(), %s is not for IrDA mode\n", - __func__, dongle_types[dongle_id]); + pr_debug("%s(), %s is not for IrDA mode\n", + __func__, dongle_types[dongle_id]); switch_bank(iobase, BANK0); outb(0x62, iobase+MCR); break; default: - IRDA_DEBUG(0, "%s(), invalid data_rate\n", __func__); + pr_debug("%s(), invalid data_rate\n", __func__); } /* Restore bank register */ outb(bank, iobase+BSR); @@ -1256,7 +1259,7 @@ static __u8 nsc_ircc_change_speed(struct nsc_ircc_cb *self, __u32 speed) __u8 bank; __u8 ier; /* Interrupt enable register */ - IRDA_DEBUG(2, "%s(), speed=%d\n", __func__, speed); + pr_debug("%s(), speed=%d\n", __func__, speed); IRDA_ASSERT(self != NULL, return 0;); @@ -1289,20 +1292,20 @@ static __u8 nsc_ircc_change_speed(struct nsc_ircc_cb *self, __u32 speed) outb(inb(iobase+4) | 0x04, iobase+4); mcr = MCR_MIR; - IRDA_DEBUG(0, "%s(), handling baud of 576000\n", __func__); + pr_debug("%s(), handling baud of 576000\n", __func__); break; case 1152000: mcr = MCR_MIR; - IRDA_DEBUG(0, "%s(), handling baud of 1152000\n", __func__); + pr_debug("%s(), handling baud of 1152000\n", __func__); break; case 4000000: mcr = MCR_FIR; - IRDA_DEBUG(0, "%s(), handling baud of 4000000\n", __func__); + pr_debug("%s(), handling baud of 4000000\n", __func__); break; default: mcr = MCR_FIR; - IRDA_DEBUG(0, "%s(), unknown baud rate of %d\n", - __func__, speed); + pr_debug("%s(), unknown baud rate of %d\n", + __func__, speed); break; } @@ -1609,15 +1612,13 @@ static int nsc_ircc_pio_write(int iobase, __u8 *buf, int len, int fifo_size) int actual = 0; __u8 bank; - IRDA_DEBUG(4, "%s()\n", __func__); - /* Save current bank */ bank = inb(iobase+BSR); switch_bank(iobase, BANK0); if (!(inb_p(iobase+LSR) & LSR_TXEMP)) { - IRDA_DEBUG(4, "%s(), warning, FIFO not empty yet!\n", - __func__); + pr_debug("%s(), warning, FIFO not empty yet!\n", + __func__); /* FIFO may still be filled to the Tx interrupt threshold */ fifo_size -= 17; @@ -1629,8 +1630,8 @@ static int nsc_ircc_pio_write(int iobase, __u8 *buf, int len, int fifo_size) outb(buf[actual++], iobase+TXD); } - IRDA_DEBUG(4, "%s(), fifo_size %d ; %d sent of %d\n", - __func__, fifo_size, actual, len); + pr_debug("%s(), fifo_size %d ; %d sent of %d\n", + __func__, fifo_size, actual, len); /* Restore bank */ outb(bank, iobase+BSR); @@ -1651,8 +1652,6 @@ static int nsc_ircc_dma_xmit_complete(struct nsc_ircc_cb *self) __u8 bank; int ret = TRUE; - IRDA_DEBUG(2, "%s()\n", __func__); - iobase = self->io.fir_base; /* Save current bank */ @@ -1782,7 +1781,7 @@ static int nsc_ircc_dma_receive_complete(struct nsc_ircc_cb *self, int iobase) len = inb(iobase+RFLFL) | ((inb(iobase+RFLFH) & 0x1f) << 8); if (st_fifo->tail >= MAX_RX_WINDOW) { - IRDA_DEBUG(0, "%s(), window is full!\n", __func__); + pr_debug("%s(), window is full!\n", __func__); continue; } @@ -1872,9 +1871,6 @@ static int nsc_ircc_dma_receive_complete(struct nsc_ircc_cb *self, int iobase) skb = dev_alloc_skb(len+1); if (skb == NULL) { - IRDA_WARNING("%s(), memory squeeze, " - "dropping frame.\n", - __func__); self->netdev->stats.rx_dropped++; /* Restore bank register */ @@ -1979,7 +1975,7 @@ static void nsc_ircc_sir_interrupt(struct nsc_ircc_cb *self, int eir) * Need to be after self->io.direction to avoid race with * nsc_ircc_hard_xmit_sir() - Jean II */ if (self->new_speed) { - IRDA_DEBUG(2, "%s(), Changing speed!\n", __func__); + pr_debug("%s(), Changing speed!\n", __func__); self->ier = nsc_ircc_change_speed(self, self->new_speed); self->new_speed = 0; @@ -2063,9 +2059,8 @@ static void nsc_ircc_fir_interrupt(struct nsc_ircc_cb *self, int iobase, nsc_ircc_dma_receive(self); self->ier = IER_SFIF_IE; } else - IRDA_WARNING("%s(), potential " - "Tx queue lockup !\n", - __func__); + net_warn_ratelimited("%s(), potential Tx queue lockup !\n", + __func__); } } else { /* Not finished yet, so interrupt on DMA again */ @@ -2174,7 +2169,6 @@ static int nsc_ircc_net_open(struct net_device *dev) char hwname[32]; __u8 bank; - IRDA_DEBUG(4, "%s()\n", __func__); IRDA_ASSERT(dev != NULL, return -1;); self = netdev_priv(dev); @@ -2184,8 +2178,8 @@ static int nsc_ircc_net_open(struct net_device *dev) iobase = self->io.fir_base; if (request_irq(self->io.irq, nsc_ircc_interrupt, 0, dev->name, dev)) { - IRDA_WARNING("%s, unable to allocate irq=%d\n", - driver_name, self->io.irq); + net_warn_ratelimited("%s, unable to allocate irq=%d\n", + driver_name, self->io.irq); return -EAGAIN; } /* @@ -2193,8 +2187,8 @@ static int nsc_ircc_net_open(struct net_device *dev) * failure. */ if (request_dma(self->io.dma, dev->name)) { - IRDA_WARNING("%s, unable to allocate dma=%d\n", - driver_name, self->io.dma); + net_warn_ratelimited("%s, unable to allocate dma=%d\n", + driver_name, self->io.dma); free_irq(self->io.irq, dev); return -EAGAIN; } @@ -2236,7 +2230,6 @@ static int nsc_ircc_net_close(struct net_device *dev) int iobase; __u8 bank; - IRDA_DEBUG(4, "%s()\n", __func__); IRDA_ASSERT(dev != NULL, return -1;); @@ -2290,7 +2283,7 @@ static int nsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) IRDA_ASSERT(self != NULL, return -1;); - IRDA_DEBUG(2, "%s(), %s, (cmd=0x%X)\n", __func__, dev->name, cmd); + pr_debug("%s(), %s, (cmd=0x%X)\n", __func__, dev->name, cmd); switch (cmd) { case SIOCSBANDWIDTH: /* Set bandwidth */ @@ -2329,7 +2322,7 @@ static int nsc_ircc_suspend(struct platform_device *dev, pm_message_t state) if (self->io.suspended) return 0; - IRDA_DEBUG(1, "%s, Suspending\n", driver_name); + pr_debug("%s, Suspending\n", driver_name); rtnl_lock(); if (netif_running(self->netdev)) { @@ -2363,7 +2356,7 @@ static int nsc_ircc_resume(struct platform_device *dev) if (!self->io.suspended) return 0; - IRDA_DEBUG(1, "%s, Waking up\n", driver_name); + pr_debug("%s, Waking up\n", driver_name); rtnl_lock(); nsc_ircc_setup(&self->io); @@ -2372,8 +2365,8 @@ static int nsc_ircc_resume(struct platform_device *dev) if (netif_running(self->netdev)) { if (request_irq(self->io.irq, nsc_ircc_interrupt, 0, self->netdev->name, self->netdev)) { - IRDA_WARNING("%s, unable to allocate irq=%d\n", - driver_name, self->io.irq); + net_warn_ratelimited("%s, unable to allocate irq=%d\n", + driver_name, self->io.irq); /* * Don't fail resume process, just kill this diff --git a/drivers/net/irda/old_belkin-sir.c b/drivers/net/irda/old_belkin-sir.c index f237136f3827..a7c2e990ae69 100644 --- a/drivers/net/irda/old_belkin-sir.c +++ b/drivers/net/irda/old_belkin-sir.c @@ -90,8 +90,6 @@ static int old_belkin_open(struct sir_dev *dev) { struct qos_info *qos = &dev->qos; - IRDA_DEBUG(2, "%s()\n", __func__); - /* Power on dongle */ sirdev_set_dtr_rts(dev, TRUE, TRUE); @@ -108,8 +106,6 @@ static int old_belkin_open(struct sir_dev *dev) static int old_belkin_close(struct sir_dev *dev) { - IRDA_DEBUG(2, "%s()\n", __func__); - /* Power off dongle */ sirdev_set_dtr_rts(dev, FALSE, FALSE); @@ -123,8 +119,6 @@ static int old_belkin_close(struct sir_dev *dev) */ static int old_belkin_change_speed(struct sir_dev *dev, unsigned speed) { - IRDA_DEBUG(2, "%s()\n", __func__); - dev->speed = 9600; return (speed==dev->speed) ? 0 : -EINVAL; } @@ -137,8 +131,6 @@ static int old_belkin_change_speed(struct sir_dev *dev, unsigned speed) */ static int old_belkin_reset(struct sir_dev *dev) { - IRDA_DEBUG(2, "%s()\n", __func__); - /* This dongles speed "defaults" to 9600 bps ;-) */ dev->speed = 9600; diff --git a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c index 43e9ab4f4d7e..6af26a7d787c 100644 --- a/drivers/net/irda/sir_dev.c +++ b/drivers/net/irda/sir_dev.c @@ -82,7 +82,7 @@ static int sirdev_tx_complete_fsm(struct sir_dev *dev) return 0; default: - IRDA_ERROR("%s - undefined state\n", __func__); + net_err_ratelimited("%s - undefined state\n", __func__); return -EINVAL; } fsm->substate = next_state; @@ -109,11 +109,11 @@ static void sirdev_config_fsm(struct work_struct *work) int ret = -1; unsigned delay; - IRDA_DEBUG(2, "%s(), <%ld>\n", __func__, jiffies); + pr_debug("%s(), <%ld>\n", __func__, jiffies); do { - IRDA_DEBUG(3, "%s - state=0x%04x / substate=0x%04x\n", - __func__, fsm->state, fsm->substate); + pr_debug("%s - state=0x%04x / substate=0x%04x\n", + __func__, fsm->state, fsm->substate); next_state = fsm->state; delay = 0; @@ -251,12 +251,13 @@ static void sirdev_config_fsm(struct work_struct *work) break; default: - IRDA_ERROR("%s - undefined state\n", __func__); + net_err_ratelimited("%s - undefined state\n", __func__); fsm->result = -EINVAL; /* fall thru */ case SIRDEV_STATE_ERROR: - IRDA_ERROR("%s - error: %d\n", __func__, fsm->result); + net_err_ratelimited("%s - error: %d\n", + __func__, fsm->result); #if 0 /* don't enable this before we have netdev->tx_timeout to recover */ netif_stop_queue(dev->netdev); @@ -286,12 +287,12 @@ int sirdev_schedule_request(struct sir_dev *dev, int initial_state, unsigned par { struct sir_fsm *fsm = &dev->fsm; - IRDA_DEBUG(2, "%s - state=0x%04x / param=%u\n", __func__, - initial_state, param); + pr_debug("%s - state=0x%04x / param=%u\n", __func__, + initial_state, param); if (down_trylock(&fsm->sem)) { if (in_interrupt() || in_atomic() || irqs_disabled()) { - IRDA_DEBUG(1, "%s(), state machine busy!\n", __func__); + pr_debug("%s(), state machine busy!\n", __func__); return -EWOULDBLOCK; } else down(&fsm->sem); @@ -299,7 +300,7 @@ int sirdev_schedule_request(struct sir_dev *dev, int initial_state, unsigned par if (fsm->state == SIRDEV_STATE_DEAD) { /* race with sirdev_close should never happen */ - IRDA_ERROR("%s(), instance staled!\n", __func__); + net_err_ratelimited("%s(), instance staled!\n", __func__); up(&fsm->sem); return -ESTALE; /* or better EPIPE? */ } @@ -344,7 +345,7 @@ int sirdev_set_dongle(struct sir_dev *dev, IRDA_DONGLE type) { int err; - IRDA_DEBUG(3, "%s : requesting dongle %d.\n", __func__, type); + pr_debug("%s : requesting dongle %d.\n", __func__, type); err = sirdev_schedule_dongle_open(dev, type); if (unlikely(err)) @@ -379,7 +380,7 @@ int sirdev_raw_write(struct sir_dev *dev, const char *buf, int len) ret = dev->drv->do_write(dev, dev->tx_buff.data, dev->tx_buff.len); if (ret > 0) { - IRDA_DEBUG(3, "%s(), raw-tx started\n", __func__); + pr_debug("%s(), raw-tx started\n", __func__); dev->tx_buff.data += ret; dev->tx_buff.len -= ret; @@ -439,8 +440,8 @@ void sirdev_write_complete(struct sir_dev *dev) spin_lock_irqsave(&dev->tx_lock, flags); - IRDA_DEBUG(3, "%s() - dev->tx_buff.len = %d\n", - __func__, dev->tx_buff.len); + pr_debug("%s() - dev->tx_buff.len = %d\n", + __func__, dev->tx_buff.len); if (likely(dev->tx_buff.len > 0)) { /* Write data left in transmit buffer */ @@ -452,8 +453,8 @@ void sirdev_write_complete(struct sir_dev *dev) } else if (unlikely(actual<0)) { /* could be dropped later when we have tx_timeout to recover */ - IRDA_ERROR("%s: drv->do_write failed (%d)\n", - __func__, actual); + net_err_ratelimited("%s: drv->do_write failed (%d)\n", + __func__, actual); if ((skb=dev->tx_skb) != NULL) { dev->tx_skb = NULL; dev_kfree_skb_any(skb); @@ -474,7 +475,7 @@ void sirdev_write_complete(struct sir_dev *dev) * restarted when the irda-thread has completed the request. */ - IRDA_DEBUG(3, "%s(), raw-tx done\n", __func__); + pr_debug("%s(), raw-tx done\n", __func__); dev->raw_tx = 0; goto done; /* no post-frame handling in raw mode */ } @@ -491,7 +492,7 @@ void sirdev_write_complete(struct sir_dev *dev) * re-activated. */ - IRDA_DEBUG(5, "%s(), finished with frame!\n", __func__); + pr_debug("%s(), finished with frame!\n", __func__); if ((skb=dev->tx_skb) != NULL) { dev->tx_skb = NULL; @@ -501,14 +502,14 @@ void sirdev_write_complete(struct sir_dev *dev) } if (unlikely(dev->new_speed > 0)) { - IRDA_DEBUG(5, "%s(), Changing speed!\n", __func__); + pr_debug("%s(), Changing speed!\n", __func__); err = sirdev_schedule_speed(dev, dev->new_speed); if (unlikely(err)) { /* should never happen * forget the speed change and hope the stack recovers */ - IRDA_ERROR("%s - schedule speed change failed: %d\n", - __func__, err); + net_err_ratelimited("%s - schedule speed change failed: %d\n", + __func__, err); netif_wake_queue(dev->netdev); } /* else: success @@ -535,13 +536,13 @@ EXPORT_SYMBOL(sirdev_write_complete); int sirdev_receive(struct sir_dev *dev, const unsigned char *cp, size_t count) { if (!dev || !dev->netdev) { - IRDA_WARNING("%s(), not ready yet!\n", __func__); + net_warn_ratelimited("%s(), not ready yet!\n", __func__); return -1; } if (!dev->irlap) { - IRDA_WARNING("%s - too early: %p / %zd!\n", - __func__, cp, count); + net_warn_ratelimited("%s - too early: %p / %zd!\n", + __func__, cp, count); return -1; } @@ -551,7 +552,7 @@ int sirdev_receive(struct sir_dev *dev, const unsigned char *cp, size_t count) */ irda_device_set_media_busy(dev->netdev, TRUE); dev->netdev->stats.rx_dropped++; - IRDA_DEBUG(0, "%s; rx-drop: %zd\n", __func__, count); + pr_debug("%s; rx-drop: %zd\n", __func__, count); return 0; } @@ -597,7 +598,7 @@ static netdev_tx_t sirdev_hard_xmit(struct sk_buff *skb, netif_stop_queue(ndev); - IRDA_DEBUG(3, "%s(), skb->len = %d\n", __func__, skb->len); + pr_debug("%s(), skb->len = %d\n", __func__, skb->len); speed = irda_get_next_speed(skb); if ((speed != dev->speed) && (speed != -1)) { @@ -634,7 +635,7 @@ static netdev_tx_t sirdev_hard_xmit(struct sk_buff *skb, /* Check problems */ if(spin_is_locked(&dev->tx_lock)) { - IRDA_DEBUG(3, "%s(), write not completed\n", __func__); + pr_debug("%s(), write not completed\n", __func__); } /* serialize with write completion */ @@ -661,8 +662,8 @@ static netdev_tx_t sirdev_hard_xmit(struct sk_buff *skb, } else if (unlikely(actual < 0)) { /* could be dropped later when we have tx_timeout to recover */ - IRDA_ERROR("%s: drv->do_write failed (%d)\n", - __func__, actual); + net_err_ratelimited("%s: drv->do_write failed (%d)\n", + __func__, actual); dev_kfree_skb_any(skb); dev->netdev->stats.tx_errors++; dev->netdev->stats.tx_dropped++; @@ -683,7 +684,7 @@ static int sirdev_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) IRDA_ASSERT(dev != NULL, return -1;); - IRDA_DEBUG(3, "%s(), %s, (cmd=0x%X)\n", __func__, ndev->name, cmd); + pr_debug("%s(), %s, (cmd=0x%X)\n", __func__, ndev->name, cmd); switch (cmd) { case SIOCSBANDWIDTH: /* Set bandwidth */ @@ -800,8 +801,6 @@ static int sirdev_open(struct net_device *ndev) if (!try_module_get(drv->owner)) return -ESTALE; - IRDA_DEBUG(2, "%s()\n", __func__); - if (sirdev_alloc_buffers(dev)) goto errout_dec; @@ -818,7 +817,7 @@ static int sirdev_open(struct net_device *ndev) netif_wake_queue(ndev); - IRDA_DEBUG(2, "%s - done, speed = %d\n", __func__, dev->speed); + pr_debug("%s - done, speed = %d\n", __func__, dev->speed); return 0; @@ -838,7 +837,7 @@ static int sirdev_close(struct net_device *ndev) struct sir_dev *dev = netdev_priv(ndev); const struct sir_driver *drv; -// IRDA_DEBUG(0, "%s\n", __func__); +/* pr_debug("%s\n", __func__); */ netif_stop_queue(ndev); @@ -880,7 +879,7 @@ struct sir_dev * sirdev_get_instance(const struct sir_driver *drv, const char *n struct net_device *ndev; struct sir_dev *dev; - IRDA_DEBUG(0, "%s - %s\n", __func__, name); + pr_debug("%s - %s\n", __func__, name); /* instead of adding tests to protect against drv->do_write==NULL * at several places we refuse to create a sir_dev instance for @@ -894,7 +893,8 @@ struct sir_dev * sirdev_get_instance(const struct sir_driver *drv, const char *n */ ndev = alloc_irdadev(sizeof(*dev)); if (ndev == NULL) { - IRDA_ERROR("%s - Can't allocate memory for IrDA control block!\n", __func__); + net_err_ratelimited("%s - Can't allocate memory for IrDA control block!\n", + __func__); goto out; } dev = netdev_priv(ndev); @@ -919,7 +919,8 @@ struct sir_dev * sirdev_get_instance(const struct sir_driver *drv, const char *n ndev->netdev_ops = &sirdev_ops; if (register_netdev(ndev)) { - IRDA_ERROR("%s(), register_netdev() failed!\n", __func__); + net_err_ratelimited("%s(), register_netdev() failed!\n", + __func__); goto out_freenetdev; } @@ -936,7 +937,7 @@ int sirdev_put_instance(struct sir_dev *dev) { int err = 0; - IRDA_DEBUG(0, "%s\n", __func__); + pr_debug("%s\n", __func__); atomic_set(&dev->enable_rx, 0); @@ -946,7 +947,7 @@ int sirdev_put_instance(struct sir_dev *dev) if (dev->dongle_drv) err = sirdev_schedule_dongle_close(dev); if (err) - IRDA_ERROR("%s - error %d\n", __func__, err); + net_err_ratelimited("%s - error %d\n", __func__, err); sirdev_close(dev->netdev); diff --git a/drivers/net/irda/sir_dongle.c b/drivers/net/irda/sir_dongle.c index cfbabb63f5cc..7436f73ff1bb 100644 --- a/drivers/net/irda/sir_dongle.c +++ b/drivers/net/irda/sir_dongle.c @@ -34,8 +34,8 @@ int irda_register_dongle(struct dongle_driver *new) struct list_head *entry; struct dongle_driver *drv; - IRDA_DEBUG(0, "%s : registering dongle \"%s\" (%d).\n", - __func__, new->driver_name, new->type); + pr_debug("%s : registering dongle \"%s\" (%d).\n", + __func__, new->driver_name, new->type); mutex_lock(&dongle_list_lock); list_for_each(entry, &dongle_list) { diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c index 282120430f12..b455ffe8850c 100644 --- a/drivers/net/irda/smsc-ircc2.c +++ b/drivers/net/irda/smsc-ircc2.c @@ -419,13 +419,16 @@ static int __init smsc_ircc_legacy_probe(void) #ifdef CONFIG_PCI if (smsc_ircc_preconfigure_subsystems(ircc_cfg, ircc_fir, ircc_sir, ircc_dma, ircc_irq) < 0) { /* Ignore errors from preconfiguration */ - IRDA_ERROR("%s, Preconfiguration failed !\n", driver_name); + net_err_ratelimited("%s, Preconfiguration failed !\n", + driver_name); } #endif if (ircc_fir > 0 && ircc_sir > 0) { - IRDA_MESSAGE(" Overriding FIR address 0x%04x\n", ircc_fir); - IRDA_MESSAGE(" Overriding SIR address 0x%04x\n", ircc_sir); + net_info_ratelimited(" Overriding FIR address 0x%04x\n", + ircc_fir); + net_info_ratelimited(" Overriding SIR address 0x%04x\n", + ircc_sir); if (smsc_ircc_open(ircc_fir, ircc_sir, ircc_dma, ircc_irq)) ret = -ENODEV; @@ -434,8 +437,8 @@ static int __init smsc_ircc_legacy_probe(void) /* try user provided configuration register base address */ if (ircc_cfg > 0) { - IRDA_MESSAGE(" Overriding configuration address " - "0x%04x\n", ircc_cfg); + net_info_ratelimited(" Overriding configuration address 0x%04x\n", + ircc_cfg); if (!smsc_superio_fdc(ircc_cfg)) ret = 0; if (!smsc_superio_lpc(ircc_cfg)) @@ -458,11 +461,12 @@ static int __init smsc_ircc_init(void) { int ret; - IRDA_DEBUG(1, "%s\n", __func__); + pr_debug("%s\n", __func__); ret = platform_driver_register(&smsc_ircc_driver); if (ret) { - IRDA_ERROR("%s, Can't register driver!\n", driver_name); + net_err_ratelimited("%s, Can't register driver!\n", + driver_name); return ret; } @@ -519,7 +523,7 @@ static int smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u8 dma, struct net_device *dev; int err; - IRDA_DEBUG(1, "%s\n", __func__); + pr_debug("%s\n", __func__); err = smsc_ircc_present(fir_base, sir_base); if (err) @@ -527,7 +531,7 @@ static int smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u8 dma, err = -ENOMEM; if (dev_count >= ARRAY_SIZE(dev_self)) { - IRDA_WARNING("%s(), too many devices!\n", __func__); + net_warn_ratelimited("%s(), too many devices!\n", __func__); goto err_out1; } @@ -536,7 +540,8 @@ static int smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u8 dma, */ dev = alloc_irdadev(sizeof(struct smsc_ircc_cb)); if (!dev) { - IRDA_WARNING("%s() can't allocate net device\n", __func__); + net_warn_ratelimited("%s() can't allocate net device\n", + __func__); goto err_out1; } @@ -588,8 +593,8 @@ static int smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u8 dma, err = register_netdev(self->netdev); if (err) { - IRDA_ERROR("%s, Network device registration failed!\n", - driver_name); + net_err_ratelimited("%s, Network device registration failed!\n", + driver_name); goto err_out4; } @@ -601,7 +606,7 @@ static int smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u8 dma, } platform_set_drvdata(self->pldev, self); - IRDA_MESSAGE("IrDA: Registered device %s\n", dev->name); + net_info_ratelimited("IrDA: Registered device %s\n", dev->name); dev_count++; return 0; @@ -637,15 +642,15 @@ static int smsc_ircc_present(unsigned int fir_base, unsigned int sir_base) if (!request_region(fir_base, SMSC_IRCC2_FIR_CHIP_IO_EXTENT, driver_name)) { - IRDA_WARNING("%s: can't get fir_base of 0x%03x\n", - __func__, fir_base); + net_warn_ratelimited("%s: can't get fir_base of 0x%03x\n", + __func__, fir_base); goto out1; } if (!request_region(sir_base, SMSC_IRCC2_SIR_CHIP_IO_EXTENT, driver_name)) { - IRDA_WARNING("%s: can't get sir_base of 0x%03x\n", - __func__, sir_base); + net_warn_ratelimited("%s: can't get sir_base of 0x%03x\n", + __func__, sir_base); goto out2; } @@ -660,13 +665,13 @@ static int smsc_ircc_present(unsigned int fir_base, unsigned int sir_base) irq = (config & IRCC_INTERFACE_IRQ_MASK) >> 4; if (high != 0x10 || low != 0xb8 || (chip != 0xf1 && chip != 0xf2)) { - IRDA_WARNING("%s(), addr 0x%04x - no device found!\n", - __func__, fir_base); + net_warn_ratelimited("%s(), addr 0x%04x - no device found!\n", + __func__, fir_base); goto out3; } - IRDA_MESSAGE("SMsC IrDA Controller found\n IrCC version %d.%d, " - "firport 0x%03x, sirport 0x%03x dma=%d, irq=%d\n", - chip & 0x0f, version, fir_base, sir_base, dma, irq); + net_info_ratelimited("SMsC IrDA Controller found\n IrCC version %d.%d, firport 0x%03x, sirport 0x%03x dma=%d, irq=%d\n", + chip & 0x0f, version, + fir_base, sir_base, dma, irq); return 0; @@ -704,16 +709,16 @@ static void smsc_ircc_setup_io(struct smsc_ircc_cb *self, if (irq != IRQ_INVAL) { if (irq != chip_irq) - IRDA_MESSAGE("%s, Overriding IRQ - chip says %d, using %d\n", - driver_name, chip_irq, irq); + net_info_ratelimited("%s, Overriding IRQ - chip says %d, using %d\n", + driver_name, chip_irq, irq); self->io.irq = irq; } else self->io.irq = chip_irq; if (dma != DMA_INVAL) { if (dma != chip_dma) - IRDA_MESSAGE("%s, Overriding DMA - chip says %d, using %d\n", - driver_name, chip_dma, dma); + net_info_ratelimited("%s, Overriding DMA - chip says %d, using %d\n", + driver_name, chip_dma, dma); self->io.dma = dma; } else self->io.dma = chip_dma; @@ -798,7 +803,7 @@ static int smsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd IRDA_ASSERT(self != NULL, return -1;); - IRDA_DEBUG(2, "%s(), %s, (cmd=0x%X)\n", __func__, dev->name, cmd); + pr_debug("%s(), %s, (cmd=0x%X)\n", __func__, dev->name, cmd); switch (cmd) { case SIOCSBANDWIDTH: /* Set bandwidth */ @@ -852,8 +857,8 @@ static void smsc_ircc_timeout(struct net_device *dev) struct smsc_ircc_cb *self = netdev_priv(dev); unsigned long flags; - IRDA_WARNING("%s: transmit timed out, changing speed to: %d\n", - dev->name, self->io.speed); + net_warn_ratelimited("%s: transmit timed out, changing speed to: %d\n", + dev->name, self->io.speed); spin_lock_irqsave(&self->lock, flags); smsc_ircc_sir_start(self); smsc_ircc_change_speed(self, self->io.speed); @@ -877,7 +882,7 @@ static netdev_tx_t smsc_ircc_hard_xmit_sir(struct sk_buff *skb, unsigned long flags; s32 speed; - IRDA_DEBUG(1, "%s\n", __func__); + pr_debug("%s\n", __func__); IRDA_ASSERT(dev != NULL, return NETDEV_TX_OK;); @@ -952,21 +957,21 @@ static void smsc_ircc_set_fir_speed(struct smsc_ircc_cb *self, u32 speed) ir_mode = IRCC_CFGA_IRDA_HDLC; ctrl = IRCC_CRC; fast = 0; - IRDA_DEBUG(0, "%s(), handling baud of 576000\n", __func__); + pr_debug("%s(), handling baud of 576000\n", __func__); break; case 1152000: ir_mode = IRCC_CFGA_IRDA_HDLC; ctrl = IRCC_1152 | IRCC_CRC; fast = IRCC_LCR_A_FAST | IRCC_LCR_A_GP_DATA; - IRDA_DEBUG(0, "%s(), handling baud of 1152000\n", - __func__); + pr_debug("%s(), handling baud of 1152000\n", + __func__); break; case 4000000: ir_mode = IRCC_CFGA_IRDA_4PPM; ctrl = IRCC_CRC; fast = IRCC_LCR_A_FAST; - IRDA_DEBUG(0, "%s(), handling baud of 4000000\n", - __func__); + pr_debug("%s(), handling baud of 4000000\n", + __func__); break; } #if 0 @@ -994,7 +999,7 @@ static void smsc_ircc_fir_start(struct smsc_ircc_cb *self) struct net_device *dev; int fir_base; - IRDA_DEBUG(1, "%s\n", __func__); + pr_debug("%s\n", __func__); IRDA_ASSERT(self != NULL, return;); dev = self->netdev; @@ -1039,7 +1044,7 @@ static void smsc_ircc_fir_stop(struct smsc_ircc_cb *self) { int fir_base; - IRDA_DEBUG(1, "%s\n", __func__); + pr_debug("%s\n", __func__); IRDA_ASSERT(self != NULL, return;); @@ -1063,7 +1068,7 @@ static void smsc_ircc_change_speed(struct smsc_ircc_cb *self, u32 speed) struct net_device *dev; int last_speed_was_sir; - IRDA_DEBUG(0, "%s() changing speed to: %d\n", __func__, speed); + pr_debug("%s() changing speed to: %d\n", __func__, speed); IRDA_ASSERT(self != NULL, return;); dev = self->netdev; @@ -1131,7 +1136,7 @@ static void smsc_ircc_set_sir_speed(struct smsc_ircc_cb *self, __u32 speed) int lcr; /* Line control reg */ int divisor; - IRDA_DEBUG(0, "%s(), Setting speed to: %d\n", __func__, speed); + pr_debug("%s(), Setting speed to: %d\n", __func__, speed); IRDA_ASSERT(self != NULL, return;); iobase = self->io.sir_base; @@ -1166,7 +1171,7 @@ static void smsc_ircc_set_sir_speed(struct smsc_ircc_cb *self, __u32 speed) /* Turn on interrups */ outb(UART_IER_RLSI | UART_IER_RDI | UART_IER_THRI, iobase + UART_IER); - IRDA_DEBUG(2, "%s() speed changed to: %d\n", __func__, speed); + pr_debug("%s() speed changed to: %d\n", __func__, speed); } @@ -1250,7 +1255,7 @@ static void smsc_ircc_dma_xmit(struct smsc_ircc_cb *self, int bofs) int iobase = self->io.fir_base; u8 ctrl; - IRDA_DEBUG(3, "%s\n", __func__); + pr_debug("%s\n", __func__); #if 1 /* Disable Rx */ register_bank(iobase, 0); @@ -1304,7 +1309,7 @@ static void smsc_ircc_dma_xmit_complete(struct smsc_ircc_cb *self) { int iobase = self->io.fir_base; - IRDA_DEBUG(3, "%s\n", __func__); + pr_debug("%s\n", __func__); #if 0 /* Disable Tx */ register_bank(iobase, 0); @@ -1408,7 +1413,7 @@ static void smsc_ircc_dma_receive_complete(struct smsc_ircc_cb *self) register_bank(iobase, 0); - IRDA_DEBUG(3, "%s\n", __func__); + pr_debug("%s\n", __func__); #if 0 /* Disable Rx */ register_bank(iobase, 0); @@ -1419,8 +1424,8 @@ static void smsc_ircc_dma_receive_complete(struct smsc_ircc_cb *self) lsr= inb(iobase + IRCC_LSR); msgcnt = inb(iobase + IRCC_LCR_B) & 0x08; - IRDA_DEBUG(2, "%s: dma count = %d\n", __func__, - get_dma_residue(self->io.dma)); + pr_debug("%s: dma count = %d\n", __func__, + get_dma_residue(self->io.dma)); len = self->rx_buff.truesize - get_dma_residue(self->io.dma); @@ -1442,17 +1447,15 @@ static void smsc_ircc_dma_receive_complete(struct smsc_ircc_cb *self) len -= self->io.speed < 4000000 ? 2 : 4; if (len < 2 || len > 2050) { - IRDA_WARNING("%s(), bogus len=%d\n", __func__, len); + net_warn_ratelimited("%s(), bogus len=%d\n", __func__, len); return; } - IRDA_DEBUG(2, "%s: msgcnt = %d, len=%d\n", __func__, msgcnt, len); + pr_debug("%s: msgcnt = %d, len=%d\n", __func__, msgcnt, len); skb = dev_alloc_skb(len + 1); - if (!skb) { - IRDA_WARNING("%s(), memory squeeze, dropping frame.\n", - __func__); + if (!skb) return; - } + /* Make sure IP header gets aligned */ skb_reserve(skb, 1); @@ -1491,7 +1494,7 @@ static void smsc_ircc_sir_receive(struct smsc_ircc_cb *self) /* Make sure we don't stay here to long */ if (boguscount++ > 32) { - IRDA_DEBUG(2, "%s(), breaking!\n", __func__); + pr_debug("%s(), breaking!\n", __func__); break; } } while (inb(iobase + UART_LSR) & UART_LSR_DR); @@ -1533,7 +1536,7 @@ static irqreturn_t smsc_ircc_interrupt(int dummy, void *dev_id) lcra = inb(iobase + IRCC_LCR_A); lsr = inb(iobase + IRCC_LSR); - IRDA_DEBUG(2, "%s(), iir = 0x%02x\n", __func__, iir); + pr_debug("%s(), iir = 0x%02x\n", __func__, iir); if (iir & IRCC_IIR_EOM) { if (self->io.direction == IO_RECV) @@ -1583,12 +1586,12 @@ static irqreturn_t smsc_ircc_interrupt_sir(struct net_device *dev) /* Clear interrupt */ lsr = inb(iobase + UART_LSR); - IRDA_DEBUG(4, "%s(), iir=%02x, lsr=%02x, iobase=%#x\n", - __func__, iir, lsr, iobase); + pr_debug("%s(), iir=%02x, lsr=%02x, iobase=%#x\n", + __func__, iir, lsr, iobase); switch (iir) { case UART_IIR_RLSI: - IRDA_DEBUG(2, "%s(), RLSI\n", __func__); + pr_debug("%s(), RLSI\n", __func__); break; case UART_IIR_RDI: /* Receive interrupt */ @@ -1600,8 +1603,8 @@ static irqreturn_t smsc_ircc_interrupt_sir(struct net_device *dev) smsc_ircc_sir_write_wakeup(self); break; default: - IRDA_DEBUG(0, "%s(), unhandled IIR=%#x\n", - __func__, iir); + pr_debug("%s(), unhandled IIR=%#x\n", + __func__, iir); break; } @@ -1628,12 +1631,12 @@ static int ircc_is_receiving(struct smsc_ircc_cb *self) int status = FALSE; /* int iobase; */ - IRDA_DEBUG(1, "%s\n", __func__); + pr_debug("%s\n", __func__); IRDA_ASSERT(self != NULL, return FALSE;); - IRDA_DEBUG(0, "%s: dma count = %d\n", __func__, - get_dma_residue(self->io.dma)); + pr_debug("%s: dma count = %d\n", __func__, + get_dma_residue(self->io.dma)); status = (self->rx_buff.state != OUTSIDE_FRAME); @@ -1648,8 +1651,8 @@ static int smsc_ircc_request_irq(struct smsc_ircc_cb *self) error = request_irq(self->io.irq, smsc_ircc_interrupt, 0, self->netdev->name, self->netdev); if (error) - IRDA_DEBUG(0, "%s(), unable to allocate irq=%d, err=%d\n", - __func__, self->io.irq, error); + pr_debug("%s(), unable to allocate irq=%d, err=%d\n", + __func__, self->io.irq, error); return error; } @@ -1693,21 +1696,21 @@ static int smsc_ircc_net_open(struct net_device *dev) struct smsc_ircc_cb *self; char hwname[16]; - IRDA_DEBUG(1, "%s\n", __func__); + pr_debug("%s\n", __func__); IRDA_ASSERT(dev != NULL, return -1;); self = netdev_priv(dev); IRDA_ASSERT(self != NULL, return 0;); if (self->io.suspended) { - IRDA_DEBUG(0, "%s(), device is suspended\n", __func__); + pr_debug("%s(), device is suspended\n", __func__); return -EAGAIN; } if (request_irq(self->io.irq, smsc_ircc_interrupt, 0, dev->name, (void *) dev)) { - IRDA_DEBUG(0, "%s(), unable to allocate irq=%d\n", - __func__, self->io.irq); + pr_debug("%s(), unable to allocate irq=%d\n", + __func__, self->io.irq); return -EAGAIN; } @@ -1730,8 +1733,8 @@ static int smsc_ircc_net_open(struct net_device *dev) if (request_dma(self->io.dma, dev->name)) { smsc_ircc_net_close(dev); - IRDA_WARNING("%s(), unable to allocate DMA=%d\n", - __func__, self->io.dma); + net_warn_ratelimited("%s(), unable to allocate DMA=%d\n", + __func__, self->io.dma); return -EAGAIN; } @@ -1750,7 +1753,7 @@ static int smsc_ircc_net_close(struct net_device *dev) { struct smsc_ircc_cb *self; - IRDA_DEBUG(1, "%s\n", __func__); + pr_debug("%s\n", __func__); IRDA_ASSERT(dev != NULL, return -1;); self = netdev_priv(dev); @@ -1781,7 +1784,7 @@ static int smsc_ircc_suspend(struct platform_device *dev, pm_message_t state) struct smsc_ircc_cb *self = platform_get_drvdata(dev); if (!self->io.suspended) { - IRDA_DEBUG(1, "%s, Suspending\n", driver_name); + pr_debug("%s, Suspending\n", driver_name); rtnl_lock(); if (netif_running(self->netdev)) { @@ -1802,7 +1805,7 @@ static int smsc_ircc_resume(struct platform_device *dev) struct smsc_ircc_cb *self = platform_get_drvdata(dev); if (self->io.suspended) { - IRDA_DEBUG(1, "%s, Waking up\n", driver_name); + pr_debug("%s, Waking up\n", driver_name); rtnl_lock(); smsc_ircc_init_chip(self); @@ -1833,7 +1836,7 @@ static int smsc_ircc_resume(struct platform_device *dev) */ static int __exit smsc_ircc_close(struct smsc_ircc_cb *self) { - IRDA_DEBUG(1, "%s\n", __func__); + pr_debug("%s\n", __func__); IRDA_ASSERT(self != NULL, return -1;); @@ -1845,13 +1848,13 @@ static int __exit smsc_ircc_close(struct smsc_ircc_cb *self) smsc_ircc_stop_interrupts(self); /* Release the PORTS that this driver is using */ - IRDA_DEBUG(0, "%s(), releasing 0x%03x\n", __func__, - self->io.fir_base); + pr_debug("%s(), releasing 0x%03x\n", __func__, + self->io.fir_base); release_region(self->io.fir_base, self->io.fir_ext); - IRDA_DEBUG(0, "%s(), releasing 0x%03x\n", __func__, - self->io.sir_base); + pr_debug("%s(), releasing 0x%03x\n", __func__, + self->io.sir_base); release_region(self->io.sir_base, self->io.sir_ext); @@ -1872,7 +1875,7 @@ static void __exit smsc_ircc_cleanup(void) { int i; - IRDA_DEBUG(1, "%s\n", __func__); + pr_debug("%s\n", __func__); for (i = 0; i < 2; i++) { if (dev_self[i]) @@ -1896,7 +1899,7 @@ static void smsc_ircc_sir_start(struct smsc_ircc_cb *self) struct net_device *dev; int fir_base, sir_base; - IRDA_DEBUG(3, "%s\n", __func__); + pr_debug("%s\n", __func__); IRDA_ASSERT(self != NULL, return;); dev = self->netdev; @@ -1922,7 +1925,7 @@ static void smsc_ircc_sir_start(struct smsc_ircc_cb *self) /* Turn on interrups */ outb(UART_IER_RLSI | UART_IER_RDI |UART_IER_THRI, sir_base + UART_IER); - IRDA_DEBUG(3, "%s() - exit\n", __func__); + pr_debug("%s() - exit\n", __func__); outb(0x00, fir_base + IRCC_MASTER); } @@ -1932,7 +1935,7 @@ void smsc_ircc_sir_stop(struct smsc_ircc_cb *self) { int iobase; - IRDA_DEBUG(3, "%s\n", __func__); + pr_debug("%s\n", __func__); iobase = self->io.sir_base; /* Reset UART */ @@ -1958,7 +1961,7 @@ static void smsc_ircc_sir_write_wakeup(struct smsc_ircc_cb *self) IRDA_ASSERT(self != NULL, return;); - IRDA_DEBUG(4, "%s\n", __func__); + pr_debug("%s\n", __func__); iobase = self->io.sir_base; @@ -1979,8 +1982,8 @@ static void smsc_ircc_sir_write_wakeup(struct smsc_ircc_cb *self) * if we need to change the speed of the hardware */ if (self->new_speed) { - IRDA_DEBUG(5, "%s(), Changing speed to %d.\n", - __func__, self->new_speed); + pr_debug("%s(), Changing speed to %d.\n", + __func__, self->new_speed); smsc_ircc_sir_wait_hw_transmitter_finish(self); smsc_ircc_change_speed(self, self->new_speed); self->new_speed = 0; @@ -2019,7 +2022,8 @@ static int smsc_ircc_sir_write(int iobase, int fifo_size, __u8 *buf, int len) /* Tx FIFO should be empty! */ if (!(inb(iobase + UART_LSR) & UART_LSR_THRE)) { - IRDA_WARNING("%s(), failed, fifo not empty!\n", __func__); + net_warn_ratelimited("%s(), failed, fifo not empty!\n", + __func__); return 0; } @@ -2058,14 +2062,14 @@ static void smsc_ircc_probe_transceiver(struct smsc_ircc_cb *self) for (i = 0; smsc_transceivers[i].name != NULL; i++) if (smsc_transceivers[i].probe(self->io.fir_base)) { - IRDA_MESSAGE(" %s transceiver found\n", - smsc_transceivers[i].name); + net_info_ratelimited(" %s transceiver found\n", + smsc_transceivers[i].name); self->transceiver= i + 1; return; } - IRDA_MESSAGE("No transceiver found. Defaulting to %s\n", - smsc_transceivers[SMSC_IRCC2_C_DEFAULT_TRANSCEIVER].name); + net_info_ratelimited("No transceiver found. Defaulting to %s\n", + smsc_transceivers[SMSC_IRCC2_C_DEFAULT_TRANSCEIVER].name); self->transceiver = SMSC_IRCC2_C_DEFAULT_TRANSCEIVER; } @@ -2119,7 +2123,7 @@ static void smsc_ircc_sir_wait_hw_transmitter_finish(struct smsc_ircc_cb *self) udelay(1); if (count < 0) - IRDA_DEBUG(0, "%s(): stuck transmitter\n", __func__); + pr_debug("%s(): stuck transmitter\n", __func__); } @@ -2180,7 +2184,7 @@ static int __init smsc_superio_flat(const struct smsc_chip *chips, unsigned shor u8 mode, dma, irq; int ret = -ENODEV; - IRDA_DEBUG(1, "%s\n", __func__); + pr_debug("%s\n", __func__); if (smsc_ircc_probe(cfgbase, SMSCSIOFLAT_DEVICEID_REG, chips, type) == NULL) return ret; @@ -2191,7 +2195,7 @@ static int __init smsc_superio_flat(const struct smsc_chip *chips, unsigned shor /*printk(KERN_WARNING "%s(): mode: 0x%02x\n", __func__, mode);*/ if (!(mode & SMSCSIOFLAT_UART2MODE_VAL_IRDA)) - IRDA_WARNING("%s(): IrDA not enabled\n", __func__); + net_warn_ratelimited("%s(): IrDA not enabled\n", __func__); outb(SMSCSIOFLAT_UART2BASEADDR_REG, cfgbase); sirbase = inb(cfgbase + 1) << 2; @@ -2208,7 +2212,8 @@ static int __init smsc_superio_flat(const struct smsc_chip *chips, unsigned shor outb(SMSCSIOFLAT_UARTIRQSELECT_REG, cfgbase); irq = inb(cfgbase + 1) & SMSCSIOFLAT_UART2IRQSELECT_MASK; - IRDA_MESSAGE("%s(): fir: 0x%02x, sir: 0x%02x, dma: %02d, irq: %d, mode: 0x%02x\n", __func__, firbase, sirbase, dma, irq, mode); + net_info_ratelimited("%s(): fir: 0x%02x, sir: 0x%02x, dma: %02d, irq: %d, mode: 0x%02x\n", + __func__, firbase, sirbase, dma, irq, mode); if (firbase && smsc_ircc_open(firbase, sirbase, dma, irq) == 0) ret = 0; @@ -2230,7 +2235,7 @@ static int __init smsc_superio_paged(const struct smsc_chip *chips, unsigned sho unsigned short fir_io, sir_io; int ret = -ENODEV; - IRDA_DEBUG(1, "%s\n", __func__); + pr_debug("%s\n", __func__); if (smsc_ircc_probe(cfg_base, 0x20, chips, type) == NULL) return ret; @@ -2264,7 +2269,7 @@ static int __init smsc_superio_paged(const struct smsc_chip *chips, unsigned sho static int __init smsc_access(unsigned short cfg_base, unsigned char reg) { - IRDA_DEBUG(1, "%s\n", __func__); + pr_debug("%s\n", __func__); outb(reg, cfg_base); return inb(cfg_base) != reg ? -1 : 0; @@ -2274,7 +2279,7 @@ static const struct smsc_chip * __init smsc_ircc_probe(unsigned short cfg_base, { u8 devid, xdevid, rev; - IRDA_DEBUG(1, "%s\n", __func__); + pr_debug("%s\n", __func__); /* Leave configuration */ @@ -2329,16 +2334,16 @@ static const struct smsc_chip * __init smsc_ircc_probe(unsigned short cfg_base, return NULL; } - IRDA_MESSAGE("found SMC SuperIO Chip (devid=0x%02x rev=%02X base=0x%04x): %s%s\n", - devid, rev, cfg_base, type, chip->name); + net_info_ratelimited("found SMC SuperIO Chip (devid=0x%02x rev=%02X base=0x%04x): %s%s\n", + devid, rev, cfg_base, type, chip->name); if (chip->rev > rev) { - IRDA_MESSAGE("Revision higher than expected\n"); + net_info_ratelimited("Revision higher than expected\n"); return NULL; } if (chip->flags & NoIRDA) - IRDA_MESSAGE("chipset does not support IRDA\n"); + net_info_ratelimited("chipset does not support IRDA\n"); return chip; } @@ -2348,8 +2353,8 @@ static int __init smsc_superio_fdc(unsigned short cfg_base) int ret = -1; if (!request_region(cfg_base, 2, driver_name)) { - IRDA_WARNING("%s: can't get cfg_base of 0x%03x\n", - __func__, cfg_base); + net_warn_ratelimited("%s: can't get cfg_base of 0x%03x\n", + __func__, cfg_base); } else { if (!smsc_superio_flat(fdc_chips_flat, cfg_base, "FDC") || !smsc_superio_paged(fdc_chips_paged, cfg_base, "FDC")) @@ -2366,8 +2371,8 @@ static int __init smsc_superio_lpc(unsigned short cfg_base) int ret = -1; if (!request_region(cfg_base, 2, driver_name)) { - IRDA_WARNING("%s: can't get cfg_base of 0x%03x\n", - __func__, cfg_base); + net_warn_ratelimited("%s: can't get cfg_base of 0x%03x\n", + __func__, cfg_base); } else { if (!smsc_superio_flat(lpc_chips_flat, cfg_base, "LPC") || !smsc_superio_paged(lpc_chips_paged, cfg_base, "LPC")) @@ -2529,9 +2534,8 @@ static int __init preconfigure_smsc_chip(struct outb(LPC47N227_CFGACCESSKEY, iobase); // enter configuration state outb(SMSCSIOFLAT_DEVICEID_REG, iobase); // set for device ID tmpbyte = inb(iobase +1); // Read device ID - IRDA_DEBUG(0, - "Detected Chip id: 0x%02x, setting up registers...\n", - tmpbyte); + pr_debug("Detected Chip id: 0x%02x, setting up registers...\n", + tmpbyte); /* Disable UART1 and set up SIR I/O port */ outb(0x24, iobase); // select CR24 - UART1 base addr @@ -2540,8 +2544,8 @@ static int __init preconfigure_smsc_chip(struct outb( (conf->sir_io >> 2), iobase + 1); // bits 2-9 of 0x3f8 tmpbyte = inb(iobase + 1); if (tmpbyte != (conf->sir_io >> 2) ) { - IRDA_WARNING("ERROR: could not configure SIR ioport.\n"); - IRDA_WARNING("Try to supply ircc_cfg argument.\n"); + net_warn_ratelimited("ERROR: could not configure SIR ioport\n"); + net_warn_ratelimited("Try to supply ircc_cfg argument\n"); return -ENXIO; } @@ -2553,7 +2557,7 @@ static int __init preconfigure_smsc_chip(struct outb(tmpbyte, iobase + 1); tmpbyte = inb(iobase + 1) & SMSCSIOFLAT_UART2IRQSELECT_MASK; if (tmpbyte != conf->fir_irq) { - IRDA_WARNING("ERROR: could not configure FIR IRQ channel.\n"); + net_warn_ratelimited("ERROR: could not configure FIR IRQ channel\n"); return -ENXIO; } @@ -2562,7 +2566,7 @@ static int __init preconfigure_smsc_chip(struct outb((conf->fir_io >> 3), iobase + 1); tmpbyte = inb(iobase + 1); if (tmpbyte != (conf->fir_io >> 3) ) { - IRDA_WARNING("ERROR: could not configure FIR I/O port.\n"); + net_warn_ratelimited("ERROR: could not configure FIR I/O port\n"); return -ENXIO; } @@ -2571,7 +2575,7 @@ static int __init preconfigure_smsc_chip(struct outb((conf->fir_dma & LPC47N227_FIRDMASELECT_MASK), iobase + 1); // DMA tmpbyte = inb(iobase + 1) & LPC47N227_FIRDMASELECT_MASK; if (tmpbyte != (conf->fir_dma & LPC47N227_FIRDMASELECT_MASK)) { - IRDA_WARNING("ERROR: could not configure FIR DMA channel.\n"); + net_warn_ratelimited("ERROR: could not configure FIR DMA channel\n"); return -ENXIO; } @@ -2628,7 +2632,7 @@ static int __init preconfigure_through_82801(struct pci_dev *dev, unsigned short tmpword; unsigned char tmpbyte; - IRDA_MESSAGE("Setting up Intel 82801 controller and SMSC device\n"); + net_info_ratelimited("Setting up Intel 82801 controller and SMSC device\n"); /* * Select the range for the COMA COM port (SIR) * Register COM_DEC: @@ -2677,7 +2681,7 @@ static int __init preconfigure_through_82801(struct pci_dev *dev, default: tmpbyte |= 0x01; /* COM2 default */ } - IRDA_DEBUG(1, "COM_DEC (write): 0x%02x\n", tmpbyte); + pr_debug("COM_DEC (write): 0x%02x\n", tmpbyte); pci_write_config_byte(dev, COM_DEC, tmpbyte); /* Enable Low Pin Count interface */ @@ -2699,13 +2703,13 @@ static int __init preconfigure_through_82801(struct pci_dev *dev, tmpword |= 0x0400; break; default: - IRDA_WARNING("Uncommon I/O base address: 0x%04x\n", - conf->cfg_base); + net_warn_ratelimited("Uncommon I/O base address: 0x%04x\n", + conf->cfg_base); break; } tmpword &= 0xfffd; /* disable LPC COMB */ tmpword |= 0x0001; /* set bit 0 : enable LPC COMA addr range (GEN2) */ - IRDA_DEBUG(1, "LPC_EN (write): 0x%04x\n", tmpword); + pr_debug("LPC_EN (write): 0x%04x\n", tmpword); pci_write_config_word(dev, LPC_EN, tmpword); /* @@ -2750,7 +2754,7 @@ static int __init preconfigure_through_82801(struct pci_dev *dev, default: break; /* do not change settings */ } - IRDA_DEBUG(1, "PCI_DMA_C (write): 0x%04x\n", tmpword); + pr_debug("PCI_DMA_C (write): 0x%04x\n", tmpword); pci_write_config_word(dev, PCI_DMA_C, tmpword); /* @@ -2761,7 +2765,7 @@ static int __init preconfigure_through_82801(struct pci_dev *dev, */ tmpword = conf->fir_io & 0xfff8; tmpword |= 0x0001; - IRDA_DEBUG(1, "GEN2_DEC (write): 0x%04x\n", tmpword); + pr_debug("GEN2_DEC (write): 0x%04x\n", tmpword); pci_write_config_word(dev, GEN2_DEC, tmpword); /* Pre-configure chip */ @@ -2800,7 +2804,8 @@ static void __init preconfigure_ali_port(struct pci_dev *dev, mask = 0x08; break; default: - IRDA_ERROR("Failed to configure unsupported port on ALi 1533 bridge: 0x%04x\n", port); + net_err_ratelimited("Failed to configure unsupported port on ALi 1533 bridge: 0x%04x\n", + port); return; } @@ -2808,7 +2813,8 @@ static void __init preconfigure_ali_port(struct pci_dev *dev, /* Turn on the right bits */ tmpbyte |= mask; pci_write_config_byte(dev, reg, tmpbyte); - IRDA_MESSAGE("Activated ALi 1533 ISA bridge port 0x%04x.\n", port); + net_info_ratelimited("Activated ALi 1533 ISA bridge port 0x%04x\n", + port); } static int __init preconfigure_through_ali(struct pci_dev *dev, @@ -2877,7 +2883,8 @@ static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg, if (ircc_irq != IRQ_INVAL) tmpconf.fir_irq = ircc_irq; - IRDA_MESSAGE("Detected unconfigured %s SMSC IrDA chip, pre-configuring device.\n", conf->name); + net_info_ratelimited("Detected unconfigured %s SMSC IrDA chip, pre-configuring device\n", + conf->name); if (conf->preconfigure) ret = conf->preconfigure(dev, &tmpconf); else @@ -2922,8 +2929,8 @@ static void smsc_ircc_set_transceiver_smsc_ircc_atc(int fir_base, u32 speed) /* empty */; if (val) - IRDA_WARNING("%s(): ATC: 0x%02x\n", __func__, - inb(fir_base + IRCC_ATC)); + net_warn_ratelimited("%s(): ATC: 0x%02x\n", + __func__, inb(fir_base + IRCC_ATC)); } /* diff --git a/drivers/net/irda/tekram-sir.c b/drivers/net/irda/tekram-sir.c index 048a15422844..9dcf0c103b9d 100644 --- a/drivers/net/irda/tekram-sir.c +++ b/drivers/net/irda/tekram-sir.c @@ -63,8 +63,8 @@ static int __init tekram_sir_init(void) { if (tekram_delay < 1 || tekram_delay > 500) tekram_delay = 200; - IRDA_DEBUG(1, "%s - using %d ms delay\n", - tekram.driver_name, tekram_delay); + pr_debug("%s - using %d ms delay\n", + tekram.driver_name, tekram_delay); return irda_register_dongle(&tekram); } @@ -77,8 +77,6 @@ static int tekram_open(struct sir_dev *dev) { struct qos_info *qos = &dev->qos; - IRDA_DEBUG(2, "%s()\n", __func__); - sirdev_set_dtr_rts(dev, TRUE, TRUE); qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200; @@ -92,8 +90,6 @@ static int tekram_open(struct sir_dev *dev) static int tekram_close(struct sir_dev *dev) { - IRDA_DEBUG(2, "%s()\n", __func__); - /* Power off dongle */ sirdev_set_dtr_rts(dev, FALSE, FALSE); @@ -130,8 +126,6 @@ static int tekram_change_speed(struct sir_dev *dev, unsigned speed) u8 byte; static int ret = 0; - IRDA_DEBUG(2, "%s()\n", __func__); - switch(state) { case SIRDEV_STATE_DONGLE_SPEED: @@ -179,7 +173,8 @@ static int tekram_change_speed(struct sir_dev *dev, unsigned speed) break; default: - IRDA_ERROR("%s - undefined state %d\n", __func__, state); + net_err_ratelimited("%s - undefined state %d\n", + __func__, state); ret = -EINVAL; break; } @@ -204,8 +199,6 @@ static int tekram_change_speed(struct sir_dev *dev, unsigned speed) static int tekram_reset(struct sir_dev *dev) { - IRDA_DEBUG(2, "%s()\n", __func__); - /* Clear DTR, Set RTS */ sirdev_set_dtr_rts(dev, FALSE, TRUE); diff --git a/drivers/net/irda/toim3232-sir.c b/drivers/net/irda/toim3232-sir.c index 19ad4606b799..6d2f55959c49 100644 --- a/drivers/net/irda/toim3232-sir.c +++ b/drivers/net/irda/toim3232-sir.c @@ -168,8 +168,8 @@ static int __init toim3232_sir_init(void) { if (toim3232delay < 1 || toim3232delay > 500) toim3232delay = 200; - IRDA_DEBUG(1, "%s - using %d ms delay\n", - toim3232.driver_name, toim3232delay); + pr_debug("%s - using %d ms delay\n", + toim3232.driver_name, toim3232delay); return irda_register_dongle(&toim3232); } @@ -182,8 +182,6 @@ static int toim3232_open(struct sir_dev *dev) { struct qos_info *qos = &dev->qos; - IRDA_DEBUG(2, "%s()\n", __func__); - /* Pull the lines high to start with. * * For the IR320ST-2, we need to charge the main supply capacitor to @@ -210,8 +208,6 @@ static int toim3232_open(struct sir_dev *dev) static int toim3232_close(struct sir_dev *dev) { - IRDA_DEBUG(2, "%s()\n", __func__); - /* Power off dongle */ sirdev_set_dtr_rts(dev, FALSE, FALSE); @@ -242,8 +238,6 @@ static int toim3232_change_speed(struct sir_dev *dev, unsigned speed) u8 byte; static int ret = 0; - IRDA_DEBUG(2, "%s()\n", __func__); - switch(state) { case SIRDEV_STATE_DONGLE_SPEED: @@ -345,8 +339,6 @@ static int toim3232_change_speed(struct sir_dev *dev, unsigned speed) static int toim3232_reset(struct sir_dev *dev) { - IRDA_DEBUG(2, "%s()\n", __func__); - /* Switch off both DTR and RTS to switch off dongle */ sirdev_set_dtr_rts(dev, FALSE, FALSE); diff --git a/drivers/net/irda/via-ircc.c b/drivers/net/irda/via-ircc.c index 36e004288ea7..6960d4cd3cae 100644 --- a/drivers/net/irda/via-ircc.c +++ b/drivers/net/irda/via-ircc.c @@ -144,12 +144,10 @@ static int __init via_ircc_init(void) { int rc; - IRDA_DEBUG(3, "%s()\n", __func__); - rc = pci_register_driver(&via_driver); if (rc < 0) { - IRDA_DEBUG(0, "%s(): error rc = %d, returning -ENODEV...\n", - __func__, rc); + pr_debug("%s(): error rc = %d, returning -ENODEV...\n", + __func__, rc); return -ENODEV; } return 0; @@ -162,11 +160,11 @@ static int via_init_one(struct pci_dev *pcidev, const struct pci_device_id *id) u16 Chipset,FirDRQ1,FirDRQ0,FirIRQ,FirIOBase; chipio_t info; - IRDA_DEBUG(2, "%s(): Device ID=(0X%X)\n", __func__, id->device); + pr_debug("%s(): Device ID=(0X%X)\n", __func__, id->device); rc = pci_enable_device (pcidev); if (rc) { - IRDA_DEBUG(0, "%s(): error rc = %d\n", __func__, rc); + pr_debug("%s(): error rc = %d\n", __func__, rc); return -ENODEV; } @@ -177,7 +175,7 @@ static int via_init_one(struct pci_dev *pcidev, const struct pci_device_id *id) Chipset=0x3076; if (Chipset==0x3076) { - IRDA_DEBUG(2, "%s(): Chipset = 3076\n", __func__); + pr_debug("%s(): Chipset = 3076\n", __func__); WriteLPCReg(7,0x0c ); temp=ReadLPCReg(0x30);//check if BIOS Enable Fir @@ -213,7 +211,7 @@ static int via_init_one(struct pci_dev *pcidev, const struct pci_device_id *id) } else rc = -ENODEV; //IR not turn on } else { //Not VT1211 - IRDA_DEBUG(2, "%s(): Chipset = 3096\n", __func__); + pr_debug("%s(): Chipset = 3096\n", __func__); pci_read_config_byte(pcidev,0x67,&bTmp);//check if BIOS Enable Fir if((bTmp&0x01)==1) { // BIOS enable FIR @@ -252,14 +250,12 @@ static int via_init_one(struct pci_dev *pcidev, const struct pci_device_id *id) rc = -ENODEV; //IR not turn on !!!!! }//Not VT1211 - IRDA_DEBUG(2, "%s(): End - rc = %d\n", __func__, rc); + pr_debug("%s(): End - rc = %d\n", __func__, rc); return rc; } static void __exit via_ircc_cleanup(void) { - IRDA_DEBUG(3, "%s()\n", __func__); - /* Cleanup all instances of the driver */ pci_unregister_driver (&via_driver); } @@ -289,8 +285,6 @@ static int via_ircc_open(struct pci_dev *pdev, chipio_t *info, unsigned int id) struct via_ircc_cb *self; int err; - IRDA_DEBUG(3, "%s()\n", __func__); - /* Allocate new instance of the driver */ dev = alloc_irdadev(sizeof(struct via_ircc_cb)); if (dev == NULL) @@ -316,8 +310,8 @@ static int via_ircc_open(struct pci_dev *pdev, chipio_t *info, unsigned int id) /* Reserve the ioports that we need */ if (!request_region(self->io.fir_base, self->io.fir_ext, driver_name)) { - IRDA_DEBUG(0, "%s(), can't get iobase of 0x%03x\n", - __func__, self->io.fir_base); + pr_debug("%s(), can't get iobase of 0x%03x\n", + __func__, self->io.fir_base); err = -ENODEV; goto err_out1; } @@ -391,7 +385,8 @@ static int via_ircc_open(struct pci_dev *pdev, chipio_t *info, unsigned int id) if (err) goto err_out4; - IRDA_MESSAGE("IrDA: Registered device %s (via-ircc)\n", dev->name); + net_info_ratelimited("IrDA: Registered device %s (via-ircc)\n", + dev->name); /* Initialise the hardware.. */ @@ -422,8 +417,6 @@ static void via_remove_one(struct pci_dev *pdev) struct via_ircc_cb *self = pci_get_drvdata(pdev); int iobase; - IRDA_DEBUG(3, "%s()\n", __func__); - iobase = self->io.fir_base; ResetChip(iobase, 5); //hardware reset. @@ -431,8 +424,8 @@ static void via_remove_one(struct pci_dev *pdev) unregister_netdev(self->netdev); /* Release the PORT that this driver is using */ - IRDA_DEBUG(2, "%s(), Releasing Region %03x\n", - __func__, self->io.fir_base); + pr_debug("%s(), Releasing Region %03x\n", + __func__, self->io.fir_base); release_region(self->io.fir_base, self->io.fir_ext); if (self->tx_buff.head) dma_free_coherent(&pdev->dev, self->tx_buff.truesize, @@ -457,8 +450,6 @@ static void via_hw_init(struct via_ircc_cb *self) { int iobase = self->io.fir_base; - IRDA_DEBUG(3, "%s()\n", __func__); - SetMaxRxPacketSize(iobase, 0x0fff); //set to max:4095 // FIFO Init EnRXFIFOReadyInt(iobase, OFF); @@ -510,7 +501,7 @@ static void via_hw_init(struct via_ircc_cb *self) */ static int via_ircc_read_dongle_id(int iobase) { - IRDA_ERROR("via-ircc: dongle probing not supported, please specify dongle_id module parameter.\n"); + net_err_ratelimited("via-ircc: dongle probing not supported, please specify dongle_id module parameter\n"); return 9; /* Default to IBM */ } @@ -527,8 +518,8 @@ static void via_ircc_change_dongle_speed(int iobase, int speed, /* speed is unused, as we use IsSIROn()/IsMIROn() */ speed = speed; - IRDA_DEBUG(1, "%s(): change_dongle_speed to %d for 0x%x, %d\n", - __func__, speed, iobase, dongle_id); + pr_debug("%s(): change_dongle_speed to %d for 0x%x, %d\n", + __func__, speed, iobase, dongle_id); switch (dongle_id) { @@ -617,7 +608,8 @@ static void via_ircc_change_dongle_speed(int iobase, int speed, case 0x11: /* Temic TFDS4500 */ - IRDA_DEBUG(2, "%s: Temic TFDS4500: One RX pin, TX normal, RX inverted.\n", __func__); + pr_debug("%s: Temic TFDS4500: One RX pin, TX normal, RX inverted\n", + __func__); UseOneRX(iobase, ON); //use ONE RX....RX1 InvertTX(iobase, OFF); @@ -635,7 +627,8 @@ static void via_ircc_change_dongle_speed(int iobase, int speed, SlowIRRXLowActive(iobase, OFF); } else{ - IRDA_DEBUG(0, "%s: Warning: TFDS4500 not running in SIR mode !\n", __func__); + pr_debug("%s: Warning: TFDS4500 not running in SIR mode !\n", + __func__); } break; @@ -652,8 +645,8 @@ static void via_ircc_change_dongle_speed(int iobase, int speed, break; default: - IRDA_ERROR("%s: Error: dongle_id %d unsupported !\n", - __func__, dongle_id); + net_err_ratelimited("%s: Error: dongle_id %d unsupported !\n", + __func__, dongle_id); } } @@ -672,7 +665,7 @@ static void via_ircc_change_speed(struct via_ircc_cb *self, __u32 speed) iobase = self->io.fir_base; /* Update accounting for new speed */ self->io.speed = speed; - IRDA_DEBUG(1, "%s: change_speed to %d bps.\n", __func__, speed); + pr_debug("%s: change_speed to %d bps.\n", __func__, speed); WriteReg(iobase, I_ST_CT_0, 0x0); @@ -902,10 +895,10 @@ static int via_ircc_dma_xmit(struct via_ircc_cb *self, u16 iobase) ((u8 *)self->tx_fifo.queue[self->tx_fifo.ptr].start - self->tx_buff.head) + self->tx_buff_dma, self->tx_fifo.queue[self->tx_fifo.ptr].len, DMA_TX_MODE); - IRDA_DEBUG(1, "%s: tx_fifo.ptr=%x,len=%x,tx_fifo.len=%x..\n", - __func__, self->tx_fifo.ptr, - self->tx_fifo.queue[self->tx_fifo.ptr].len, - self->tx_fifo.len); + pr_debug("%s: tx_fifo.ptr=%x,len=%x,tx_fifo.len=%x..\n", + __func__, self->tx_fifo.ptr, + self->tx_fifo.queue[self->tx_fifo.ptr].len, + self->tx_fifo.len); SetSendByte(iobase, self->tx_fifo.queue[self->tx_fifo.ptr].len); RXStart(iobase, OFF); @@ -926,8 +919,6 @@ static int via_ircc_dma_xmit_complete(struct via_ircc_cb *self) int iobase; u8 Tx_status; - IRDA_DEBUG(3, "%s()\n", __func__); - iobase = self->io.fir_base; /* Disable DMA */ // DisableDmaChannel(self->io.dma); @@ -957,10 +948,9 @@ static int via_ircc_dma_xmit_complete(struct via_ircc_cb *self) self->tx_fifo.ptr++; } } - IRDA_DEBUG(1, - "%s: tx_fifo.len=%x ,tx_fifo.ptr=%x,tx_fifo.free=%x...\n", - __func__, - self->tx_fifo.len, self->tx_fifo.ptr, self->tx_fifo.free); + pr_debug("%s: tx_fifo.len=%x ,tx_fifo.ptr=%x,tx_fifo.free=%x...\n", + __func__, + self->tx_fifo.len, self->tx_fifo.ptr, self->tx_fifo.free); /* F01_S // Any frames to be sent back-to-back? if (self->tx_fifo.len) { @@ -995,8 +985,6 @@ static int via_ircc_dma_receive(struct via_ircc_cb *self) iobase = self->io.fir_base; - IRDA_DEBUG(3, "%s()\n", __func__); - self->tx_fifo.len = self->tx_fifo.ptr = self->tx_fifo.free = 0; self->tx_fifo.tail = self->tx_buff.head; self->RxDataReady = 0; @@ -1078,15 +1066,15 @@ static int via_ircc_dma_receive_complete(struct via_ircc_cb *self, if (len == 0) return TRUE; //interrupt only, data maybe move by RxT if (((len - 4) < 2) || ((len - 4) > 2048)) { - IRDA_DEBUG(1, "%s(): Trouble:len=%x,CurCount=%x,LastCount=%x..\n", - __func__, len, RxCurCount(iobase, self), - self->RxLastCount); + pr_debug("%s(): Trouble:len=%x,CurCount=%x,LastCount=%x\n", + __func__, len, RxCurCount(iobase, self), + self->RxLastCount); hwreset(self); return FALSE; } - IRDA_DEBUG(2, "%s(): fifo.len=%x,len=%x,CurCount=%x..\n", - __func__, - st_fifo->len, len - 4, RxCurCount(iobase, self)); + pr_debug("%s(): fifo.len=%x,len=%x,CurCount=%x..\n", + __func__, + st_fifo->len, len - 4, RxCurCount(iobase, self)); st_fifo->entries[st_fifo->tail].status = status; st_fifo->entries[st_fifo->tail].len = len; @@ -1133,8 +1121,8 @@ F01_E */ skb_put(skb, len - 4); skb_copy_to_linear_data(skb, self->rx_buff.data, len - 4); - IRDA_DEBUG(2, "%s(): len=%x.rx_buff=%p\n", __func__, - len - 4, self->rx_buff.data); + pr_debug("%s(): len=%x.rx_buff=%p\n", __func__, + len - 4, self->rx_buff.data); // Move to next frame self->rx_buff.data += len; @@ -1163,7 +1151,7 @@ static int upload_rxdata(struct via_ircc_cb *self, int iobase) len = GetRecvByte(iobase, self); - IRDA_DEBUG(2, "%s(): len=%x\n", __func__, len); + pr_debug("%s(): len=%x\n", __func__, len); if ((len - 4) < 2) { self->netdev->stats.rx_dropped++; @@ -1248,8 +1236,8 @@ static int RxTimerHandler(struct via_ircc_cb *self, int iobase) skb_put(skb, len - 4); skb_copy_to_linear_data(skb, self->rx_buff.data, len - 4); - IRDA_DEBUG(2, "%s(): len=%x.head=%x\n", __func__, - len - 4, st_fifo->head); + pr_debug("%s(): len=%x.head=%x\n", __func__, + len - 4, st_fifo->head); // Move to next frame self->rx_buff.data += len; @@ -1262,10 +1250,8 @@ static int RxTimerHandler(struct via_ircc_cb *self, int iobase) } //while self->RetryCount = 0; - IRDA_DEBUG(2, - "%s(): End of upload HostStatus=%x,RxStatus=%x\n", - __func__, - GetHostStatus(iobase), GetRXStatus(iobase)); + pr_debug("%s(): End of upload HostStatus=%x,RxStatus=%x\n", + __func__, GetHostStatus(iobase), GetRXStatus(iobase)); /* * if frame is receive complete at this routine ,then upload @@ -1303,12 +1289,12 @@ static irqreturn_t via_ircc_interrupt(int dummy, void *dev_id) spin_lock(&self->lock); iHostIntType = GetHostStatus(iobase); - IRDA_DEBUG(4, "%s(): iHostIntType %02x: %s %s %s %02x\n", - __func__, iHostIntType, - (iHostIntType & 0x40) ? "Timer" : "", - (iHostIntType & 0x20) ? "Tx" : "", - (iHostIntType & 0x10) ? "Rx" : "", - (iHostIntType & 0x0e) >> 1); + pr_debug("%s(): iHostIntType %02x: %s %s %s %02x\n", + __func__, iHostIntType, + (iHostIntType & 0x40) ? "Timer" : "", + (iHostIntType & 0x20) ? "Tx" : "", + (iHostIntType & 0x10) ? "Rx" : "", + (iHostIntType & 0x0e) >> 1); if ((iHostIntType & 0x40) != 0) { //Timer Event self->EventFlag.TimeOut++; @@ -1333,12 +1319,12 @@ static irqreturn_t via_ircc_interrupt(int dummy, void *dev_id) if ((iHostIntType & 0x20) != 0) { //Tx Event iTxIntType = GetTXStatus(iobase); - IRDA_DEBUG(4, "%s(): iTxIntType %02x: %s %s %s %s\n", - __func__, iTxIntType, - (iTxIntType & 0x08) ? "FIFO underr." : "", - (iTxIntType & 0x04) ? "EOM" : "", - (iTxIntType & 0x02) ? "FIFO ready" : "", - (iTxIntType & 0x01) ? "Early EOM" : ""); + pr_debug("%s(): iTxIntType %02x: %s %s %s %s\n", + __func__, iTxIntType, + (iTxIntType & 0x08) ? "FIFO underr." : "", + (iTxIntType & 0x04) ? "EOM" : "", + (iTxIntType & 0x02) ? "FIFO ready" : "", + (iTxIntType & 0x01) ? "Early EOM" : ""); if (iTxIntType & 0x4) { self->EventFlag.EOMessage++; // read and will auto clean @@ -1357,17 +1343,17 @@ static irqreturn_t via_ircc_interrupt(int dummy, void *dev_id) /* Check if DMA has finished */ iRxIntType = GetRXStatus(iobase); - IRDA_DEBUG(4, "%s(): iRxIntType %02x: %s %s %s %s %s %s %s\n", - __func__, iRxIntType, - (iRxIntType & 0x80) ? "PHY err." : "", - (iRxIntType & 0x40) ? "CRC err" : "", - (iRxIntType & 0x20) ? "FIFO overr." : "", - (iRxIntType & 0x10) ? "EOF" : "", - (iRxIntType & 0x08) ? "RxData" : "", - (iRxIntType & 0x02) ? "RxMaxLen" : "", - (iRxIntType & 0x01) ? "SIR bad" : ""); + pr_debug("%s(): iRxIntType %02x: %s %s %s %s %s %s %s\n", + __func__, iRxIntType, + (iRxIntType & 0x80) ? "PHY err." : "", + (iRxIntType & 0x40) ? "CRC err" : "", + (iRxIntType & 0x20) ? "FIFO overr." : "", + (iRxIntType & 0x10) ? "EOF" : "", + (iRxIntType & 0x08) ? "RxData" : "", + (iRxIntType & 0x02) ? "RxMaxLen" : "", + (iRxIntType & 0x01) ? "SIR bad" : ""); if (!iRxIntType) - IRDA_DEBUG(3, "%s(): RxIRQ =0\n", __func__); + pr_debug("%s(): RxIRQ =0\n", __func__); if (iRxIntType & 0x10) { if (via_ircc_dma_receive_complete(self, iobase)) { @@ -1376,10 +1362,9 @@ static irqreturn_t via_ircc_interrupt(int dummy, void *dev_id) } } // No ERR else { //ERR - IRDA_DEBUG(4, "%s(): RxIRQ ERR:iRxIntType=%x,HostIntType=%x,CurCount=%x,RxLastCount=%x_____\n", - __func__, iRxIntType, iHostIntType, - RxCurCount(iobase, self), - self->RxLastCount); + pr_debug("%s(): RxIRQ ERR:iRxIntType=%x,HostIntType=%x,CurCount=%x,RxLastCount=%x_____\n", + __func__, iRxIntType, iHostIntType, + RxCurCount(iobase, self), self->RxLastCount); if (iRxIntType & 0x20) { //FIFO OverRun ERR ResetChip(iobase, 0); @@ -1402,8 +1387,6 @@ static void hwreset(struct via_ircc_cb *self) int iobase; iobase = self->io.fir_base; - IRDA_DEBUG(3, "%s()\n", __func__); - ResetChip(iobase, 5); EnableDMA(iobase, OFF); EnableTX(iobase, OFF); @@ -1447,7 +1430,7 @@ static int via_ircc_is_receiving(struct via_ircc_cb *self) if (CkRxRecv(iobase, self)) status = TRUE; - IRDA_DEBUG(2, "%s(): status=%x....\n", __func__, status); + pr_debug("%s(): status=%x....\n", __func__, status); return status; } @@ -1465,16 +1448,14 @@ static int via_ircc_net_open(struct net_device *dev) int iobase; char hwname[32]; - IRDA_DEBUG(3, "%s()\n", __func__); - IRDA_ASSERT(dev != NULL, return -1;); self = netdev_priv(dev); dev->stats.rx_packets = 0; IRDA_ASSERT(self != NULL, return 0;); iobase = self->io.fir_base; if (request_irq(self->io.irq, via_ircc_interrupt, 0, dev->name, dev)) { - IRDA_WARNING("%s, unable to allocate irq=%d\n", driver_name, - self->io.irq); + net_warn_ratelimited("%s, unable to allocate irq=%d\n", + driver_name, self->io.irq); return -EAGAIN; } /* @@ -1482,15 +1463,15 @@ static int via_ircc_net_open(struct net_device *dev) * failure. */ if (request_dma(self->io.dma, dev->name)) { - IRDA_WARNING("%s, unable to allocate dma=%d\n", driver_name, - self->io.dma); + net_warn_ratelimited("%s, unable to allocate dma=%d\n", + driver_name, self->io.dma); free_irq(self->io.irq, dev); return -EAGAIN; } if (self->io.dma2 != self->io.dma) { if (request_dma(self->io.dma2, dev->name)) { - IRDA_WARNING("%s, unable to allocate dma2=%d\n", - driver_name, self->io.dma2); + net_warn_ratelimited("%s, unable to allocate dma2=%d\n", + driver_name, self->io.dma2); free_irq(self->io.irq, dev); free_dma(self->io.dma); return -EAGAIN; @@ -1532,8 +1513,6 @@ static int via_ircc_net_close(struct net_device *dev) struct via_ircc_cb *self; int iobase; - IRDA_DEBUG(3, "%s()\n", __func__); - IRDA_ASSERT(dev != NULL, return -1;); self = netdev_priv(dev); IRDA_ASSERT(self != NULL, return 0;); @@ -1576,8 +1555,8 @@ static int via_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, IRDA_ASSERT(dev != NULL, return -1;); self = netdev_priv(dev); IRDA_ASSERT(self != NULL, return -1;); - IRDA_DEBUG(1, "%s(), %s, (cmd=0x%X)\n", __func__, dev->name, - cmd); + pr_debug("%s(), %s, (cmd=0x%X)\n", __func__, dev->name, + cmd); /* Disable interrupts & save flags */ spin_lock_irqsave(&self->lock, flags); switch (cmd) { diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c index a2e556168286..ac39d9f33d5f 100644 --- a/drivers/net/irda/vlsi_ir.c +++ b/drivers/net/irda/vlsi_ir.c @@ -429,8 +429,8 @@ static struct vlsi_ring *vlsi_alloc_ring(struct pci_dev *pdev, struct ring_descr if (rd->buf == NULL || !(busaddr = pci_map_single(pdev, rd->buf, len, dir))) { if (rd->buf) { - IRDA_ERROR("%s: failed to create PCI-MAP for %p", - __func__, rd->buf); + net_err_ratelimited("%s: failed to create PCI-MAP for %p\n", + __func__, rd->buf); kfree(rd->buf); rd->buf = NULL; } @@ -483,11 +483,8 @@ static int vlsi_create_hwif(vlsi_irda_dev_t *idev) ringarea = pci_zalloc_consistent(idev->pdev, HW_RING_AREA_SIZE, &idev->busaddr); - if (!ringarea) { - IRDA_ERROR("%s: insufficient memory for descriptor rings\n", - __func__); + if (!ringarea) goto out; - } hwmap = (struct ring_descr_hw *)ringarea; idev->rx_ring = vlsi_alloc_ring(idev->pdev, hwmap, ringsize[1], @@ -559,7 +556,7 @@ static int vlsi_process_rx(struct vlsi_ring *r, struct ring_descr *rd) crclen = (idev->mode==IFF_FIR) ? sizeof(u32) : sizeof(u16); len -= crclen; /* remove trailing CRC */ if (len <= 0) { - IRDA_DEBUG(0, "%s: strange frame (len=%d)\n", __func__, len); + pr_debug("%s: strange frame (len=%d)\n", __func__, len); ret |= VLSI_RX_DROP; goto done; } @@ -574,14 +571,14 @@ static int vlsi_process_rx(struct vlsi_ring *r, struct ring_descr *rd) */ le16_to_cpus(rd->buf+len); if (irda_calc_crc16(INIT_FCS,rd->buf,len+crclen) != GOOD_FCS) { - IRDA_DEBUG(0, "%s: crc error\n", __func__); + pr_debug("%s: crc error\n", __func__); ret |= VLSI_RX_CRC; goto done; } } if (!rd->skb) { - IRDA_WARNING("%s: rx packet lost\n", __func__); + net_warn_ratelimited("%s: rx packet lost\n", __func__); ret |= VLSI_RX_DROP; goto done; } @@ -610,8 +607,8 @@ static void vlsi_fill_rx(struct vlsi_ring *r) for (rd = ring_last(r); rd != NULL; rd = ring_put(r)) { if (rd_is_active(rd)) { - IRDA_WARNING("%s: driver bug: rx descr race with hw\n", - __func__); + net_warn_ratelimited("%s: driver bug: rx descr race with hw\n", + __func__); vlsi_ring_debug(r); break; } @@ -670,7 +667,7 @@ static void vlsi_rx_interrupt(struct net_device *ndev) if (ring_first(r) == NULL) { /* we are in big trouble, if this should ever happen */ - IRDA_ERROR("%s: rx ring exhausted!\n", __func__); + net_err_ratelimited("%s: rx ring exhausted!\n", __func__); vlsi_ring_debug(r); } else @@ -692,7 +689,7 @@ static void vlsi_unarm_rx(vlsi_irda_dev_t *idev) if (rd_is_active(rd)) { rd_set_status(rd, 0); if (rd_get_count(rd)) { - IRDA_DEBUG(0, "%s - dropping rx packet\n", __func__); + pr_debug("%s - dropping rx packet\n", __func__); ret = -VLSI_RX_DROP; } rd_set_count(rd, 0); @@ -767,7 +764,7 @@ static int vlsi_set_baud(vlsi_irda_dev_t *idev, unsigned iobase) int fifocnt; baudrate = idev->new_baud; - IRDA_DEBUG(2, "%s: %d -> %d\n", __func__, idev->baud, idev->new_baud); + pr_debug("%s: %d -> %d\n", __func__, idev->baud, idev->new_baud); if (baudrate == 4000000) { mode = IFF_FIR; config = IRCFG_FIR; @@ -783,8 +780,8 @@ static int vlsi_set_baud(vlsi_irda_dev_t *idev, unsigned iobase) config = IRCFG_SIR | IRCFG_SIRFILT | IRCFG_RXANY; switch(baudrate) { default: - IRDA_WARNING("%s: undefined baudrate %d - fallback to 9600!\n", - __func__, baudrate); + net_warn_ratelimited("%s: undefined baudrate %d - fallback to 9600!\n", + __func__, baudrate); baudrate = 9600; /* fallthru */ case 2400: @@ -801,7 +798,7 @@ static int vlsi_set_baud(vlsi_irda_dev_t *idev, unsigned iobase) fifocnt = inw(iobase+VLSI_PIO_RCVBCNT) & RCVBCNT_MASK; if (fifocnt != 0) { - IRDA_DEBUG(0, "%s: rx fifo not empty(%d)\n", __func__, fifocnt); + pr_debug("%s: rx fifo not empty(%d)\n", __func__, fifocnt); } outw(0, iobase+VLSI_PIO_IRENABLE); @@ -825,14 +822,16 @@ static int vlsi_set_baud(vlsi_irda_dev_t *idev, unsigned iobase) config ^= IRENABLE_SIR_ON; if (config != (IRENABLE_PHYANDCLOCK|IRENABLE_ENRXST)) { - IRDA_WARNING("%s: failed to set %s mode!\n", __func__, - (mode==IFF_SIR)?"SIR":((mode==IFF_MIR)?"MIR":"FIR")); + net_warn_ratelimited("%s: failed to set %s mode!\n", + __func__, + mode == IFF_SIR ? "SIR" : + mode == IFF_MIR ? "MIR" : "FIR"); ret = -1; } else { if (inw(iobase+VLSI_PIO_PHYCTL) != nphyctl) { - IRDA_WARNING("%s: failed to apply baudrate %d\n", - __func__, baudrate); + net_warn_ratelimited("%s: failed to apply baudrate %d\n", + __func__, baudrate); ret = -1; } else { @@ -977,8 +976,8 @@ static netdev_tx_t vlsi_hard_start_xmit(struct sk_buff *skb, */ if (len >= r->len-5) - IRDA_WARNING("%s: possible buffer overflow with SIR wrapping!\n", - __func__); + net_warn_ratelimited("%s: possible buffer overflow with SIR wrapping!\n", + __func__); } else { /* hw deals with MIR/FIR mode wrapping */ @@ -1023,7 +1022,8 @@ static netdev_tx_t vlsi_hard_start_xmit(struct sk_buff *skb, fifocnt = inw(ndev->base_addr+VLSI_PIO_RCVBCNT) & RCVBCNT_MASK; if (fifocnt != 0) { - IRDA_DEBUG(0, "%s: rx fifo not empty(%d)\n", __func__, fifocnt); + pr_debug("%s: rx fifo not empty(%d)\n", + __func__, fifocnt); } config = inw(iobase+VLSI_PIO_IRCFG); @@ -1035,7 +1035,7 @@ static netdev_tx_t vlsi_hard_start_xmit(struct sk_buff *skb, if (ring_put(r) == NULL) { netif_stop_queue(ndev); - IRDA_DEBUG(3, "%s: tx ring full - queue stopped\n", __func__); + pr_debug("%s: tx ring full - queue stopped\n", __func__); } spin_unlock_irqrestore(&idev->lock, flags); @@ -1044,7 +1044,7 @@ static netdev_tx_t vlsi_hard_start_xmit(struct sk_buff *skb, drop_unlock: spin_unlock_irqrestore(&idev->lock, flags); drop: - IRDA_WARNING("%s: dropping packet - %s\n", __func__, msg); + net_warn_ratelimited("%s: dropping packet - %s\n", __func__, msg); dev_kfree_skb_any(skb); ndev->stats.tx_errors++; ndev->stats.tx_dropped++; @@ -1100,8 +1100,8 @@ static void vlsi_tx_interrupt(struct net_device *ndev) fifocnt = inw(iobase+VLSI_PIO_RCVBCNT) & RCVBCNT_MASK; if (fifocnt != 0) { - IRDA_DEBUG(0, "%s: rx fifo not empty(%d)\n", - __func__, fifocnt); + pr_debug("%s: rx fifo not empty(%d)\n", + __func__, fifocnt); } outw(config | IRCFG_ENTX, iobase+VLSI_PIO_IRCFG); } @@ -1110,7 +1110,7 @@ static void vlsi_tx_interrupt(struct net_device *ndev) if (netif_queue_stopped(ndev) && !idev->new_baud) { netif_wake_queue(ndev); - IRDA_DEBUG(3, "%s: queue awoken\n", __func__); + pr_debug("%s: queue awoken\n", __func__); } } @@ -1134,7 +1134,7 @@ static void vlsi_unarm_tx(vlsi_irda_dev_t *idev) dev_kfree_skb_any(rd->skb); rd->skb = NULL; } - IRDA_DEBUG(0, "%s - dropping tx packet\n", __func__); + pr_debug("%s - dropping tx packet\n", __func__); ret = -VLSI_TX_DROP; } else @@ -1183,8 +1183,8 @@ static int vlsi_start_clock(struct pci_dev *pdev) } if (count < 3) { if (clksrc == 1) { /* explicitly asked for PLL hence bail out */ - IRDA_ERROR("%s: no PLL or failed to lock!\n", - __func__); + net_err_ratelimited("%s: no PLL or failed to lock!\n", + __func__); clkctl = CLKCTL_CLKSTP; pci_write_config_byte(pdev, VLSI_PCI_CLKCTL, clkctl); return -1; @@ -1192,8 +1192,8 @@ static int vlsi_start_clock(struct pci_dev *pdev) else /* was: clksrc=0(auto) */ clksrc = 3; /* fallback to 40MHz XCLK (OB800) */ - IRDA_DEBUG(0, "%s: PLL not locked, fallback to clksrc=%d\n", - __func__, clksrc); + pr_debug("%s: PLL not locked, fallback to clksrc=%d\n", + __func__, clksrc); } else clksrc = 1; /* got successful PLL lock */ @@ -1265,7 +1265,7 @@ static int vlsi_init_chip(struct pci_dev *pdev) /* start the clock and clean the registers */ if (vlsi_start_clock(pdev)) { - IRDA_ERROR("%s: no valid clock source\n", __func__); + net_err_ratelimited("%s: no valid clock source\n", __func__); return -1; } iobase = ndev->base_addr; @@ -1389,8 +1389,8 @@ static void vlsi_tx_timeout(struct net_device *ndev) idev->new_baud = idev->baud; /* keep current baudrate */ if (vlsi_start_hw(idev)) - IRDA_ERROR("%s: failed to restart hw - %s(%s) unusable!\n", - __func__, pci_name(idev->pdev), ndev->name); + net_err_ratelimited("%s: failed to restart hw - %s(%s) unusable!\n", + __func__, pci_name(idev->pdev), ndev->name); else netif_start_queue(ndev); } @@ -1434,8 +1434,8 @@ static int vlsi_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) irq->ifr_receiving = (fifocnt!=0) ? 1 : 0; break; default: - IRDA_WARNING("%s: notsupp - cmd=%04x\n", - __func__, cmd); + net_warn_ratelimited("%s: notsupp - cmd=%04x\n", + __func__, cmd); ret = -EOPNOTSUPP; } @@ -1479,8 +1479,8 @@ static irqreturn_t vlsi_interrupt(int irq, void *dev_instance) spin_unlock_irqrestore(&idev->lock,flags); if (boguscount <= 0) - IRDA_MESSAGE("%s: too much work in interrupt!\n", - __func__); + net_info_ratelimited("%s: too much work in interrupt!\n", + __func__); return IRQ_RETVAL(handled); } @@ -1493,7 +1493,7 @@ static int vlsi_open(struct net_device *ndev) char hwname[32]; if (pci_request_regions(idev->pdev, drivername)) { - IRDA_WARNING("%s: io resource busy\n", __func__); + net_warn_ratelimited("%s: io resource busy\n", __func__); goto errout; } ndev->base_addr = pci_resource_start(idev->pdev,0); @@ -1507,8 +1507,8 @@ static int vlsi_open(struct net_device *ndev) if (request_irq(ndev->irq, vlsi_interrupt, IRQF_SHARED, drivername, ndev)) { - IRDA_WARNING("%s: couldn't get IRQ: %d\n", - __func__, ndev->irq); + net_warn_ratelimited("%s: couldn't get IRQ: %d\n", + __func__, ndev->irq); goto errout_io; } @@ -1529,7 +1529,8 @@ static int vlsi_open(struct net_device *ndev) netif_start_queue(ndev); - IRDA_MESSAGE("%s: device %s operational\n", __func__, ndev->name); + net_info_ratelimited("%s: device %s operational\n", + __func__, ndev->name); return 0; @@ -1563,7 +1564,7 @@ static int vlsi_close(struct net_device *ndev) pci_release_regions(idev->pdev); - IRDA_MESSAGE("%s: device %s stopped\n", __func__, ndev->name); + net_info_ratelimited("%s: device %s stopped\n", __func__, ndev->name); return 0; } @@ -1590,7 +1591,8 @@ static int vlsi_irda_init(struct net_device *ndev) if (pci_set_dma_mask(pdev,DMA_MASK_USED_BY_HW) || pci_set_dma_mask(pdev,DMA_MASK_MSTRPAGE)) { - IRDA_ERROR("%s: aborting due to PCI BM-DMA address limitations\n", __func__); + net_err_ratelimited("%s: aborting due to PCI BM-DMA address limitations\n", + __func__); return -1; } @@ -1632,19 +1634,19 @@ vlsi_irda_probe(struct pci_dev *pdev, const struct pci_device_id *id) else pdev->current_state = 0; /* hw must be running now */ - IRDA_MESSAGE("%s: IrDA PCI controller %s detected\n", - drivername, pci_name(pdev)); + net_info_ratelimited("%s: IrDA PCI controller %s detected\n", + drivername, pci_name(pdev)); if ( !pci_resource_start(pdev,0) || !(pci_resource_flags(pdev,0) & IORESOURCE_IO) ) { - IRDA_ERROR("%s: bar 0 invalid", __func__); + net_err_ratelimited("%s: bar 0 invalid", __func__); goto out_disable; } ndev = alloc_irdadev(sizeof(*idev)); if (ndev==NULL) { - IRDA_ERROR("%s: Unable to allocate device memory.\n", - __func__); + net_err_ratelimited("%s: Unable to allocate device memory.\n", + __func__); goto out_disable; } @@ -1659,7 +1661,7 @@ vlsi_irda_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto out_freedev; if (register_netdev(ndev) < 0) { - IRDA_ERROR("%s: register_netdev failed\n", __func__); + net_err_ratelimited("%s: register_netdev failed\n", __func__); goto out_freedev; } @@ -1669,14 +1671,15 @@ vlsi_irda_probe(struct pci_dev *pdev, const struct pci_device_id *id) ent = proc_create_data(ndev->name, S_IFREG|S_IRUGO, vlsi_proc_root, VLSI_PROC_FOPS, ndev); if (!ent) { - IRDA_WARNING("%s: failed to create proc entry\n", - __func__); + net_warn_ratelimited("%s: failed to create proc entry\n", + __func__); } else { proc_set_size(ent, 0); } idev->proc_entry = ent; } - IRDA_MESSAGE("%s: registered device %s\n", drivername, ndev->name); + net_info_ratelimited("%s: registered device %s\n", + drivername, ndev->name); pci_set_drvdata(pdev, ndev); mutex_unlock(&idev->mtx); @@ -1698,7 +1701,7 @@ static void vlsi_irda_remove(struct pci_dev *pdev) vlsi_irda_dev_t *idev; if (!ndev) { - IRDA_ERROR("%s: lost netdevice?\n", drivername); + net_err_ratelimited("%s: lost netdevice?\n", drivername); return; } @@ -1714,7 +1717,7 @@ static void vlsi_irda_remove(struct pci_dev *pdev) free_netdev(ndev); - IRDA_MESSAGE("%s: %s removed\n", drivername, pci_name(pdev)); + net_info_ratelimited("%s: %s removed\n", drivername, pci_name(pdev)); } #ifdef CONFIG_PM @@ -1733,8 +1736,8 @@ static int vlsi_irda_suspend(struct pci_dev *pdev, pm_message_t state) vlsi_irda_dev_t *idev; if (!ndev) { - IRDA_ERROR("%s - %s: no netdevice\n", - __func__, pci_name(pdev)); + net_err_ratelimited("%s - %s: no netdevice\n", + __func__, pci_name(pdev)); return 0; } idev = netdev_priv(ndev); @@ -1745,7 +1748,9 @@ static int vlsi_irda_suspend(struct pci_dev *pdev, pm_message_t state) pdev->current_state = state.event; } else - IRDA_ERROR("%s - %s: invalid suspend request %u -> %u\n", __func__, pci_name(pdev), pdev->current_state, state.event); + net_err_ratelimited("%s - %s: invalid suspend request %u -> %u\n", + __func__, pci_name(pdev), + pdev->current_state, state.event); mutex_unlock(&idev->mtx); return 0; } @@ -1772,16 +1777,16 @@ static int vlsi_irda_resume(struct pci_dev *pdev) vlsi_irda_dev_t *idev; if (!ndev) { - IRDA_ERROR("%s - %s: no netdevice\n", - __func__, pci_name(pdev)); + net_err_ratelimited("%s - %s: no netdevice\n", + __func__, pci_name(pdev)); return 0; } idev = netdev_priv(ndev); mutex_lock(&idev->mtx); if (pdev->current_state == 0) { mutex_unlock(&idev->mtx); - IRDA_WARNING("%s - %s: already resumed\n", - __func__, pci_name(pdev)); + net_warn_ratelimited("%s - %s: already resumed\n", + __func__, pci_name(pdev)); return 0; } @@ -1800,7 +1805,7 @@ static int vlsi_irda_resume(struct pci_dev *pdev) * now we explicitly set pdev->current_state = 0 after enabling the * device and independently resume_ok should catch any garbage config. */ - IRDA_WARNING("%s - hm, nothing to resume?\n", __func__); + net_warn_ratelimited("%s - hm, nothing to resume?\n", __func__); mutex_unlock(&idev->mtx); return 0; } @@ -1837,7 +1842,8 @@ static int __init vlsi_mod_init(void) int i, ret; if (clksrc < 0 || clksrc > 3) { - IRDA_ERROR("%s: invalid clksrc=%d\n", drivername, clksrc); + net_err_ratelimited("%s: invalid clksrc=%d\n", + drivername, clksrc); return -1; } @@ -1850,7 +1856,10 @@ static int __init vlsi_mod_init(void) case 64: break; default: - IRDA_WARNING("%s: invalid %s ringsize %d, using default=8", drivername, (i)?"rx":"tx", ringsize[i]); + net_warn_ratelimited("%s: invalid %s ringsize %d, using default=8\n", + drivername, + i ? "rx" : "tx", + ringsize[i]); ringsize[i] = 8; break; } diff --git a/drivers/net/irda/vlsi_ir.h b/drivers/net/irda/vlsi_ir.h index 56399204e68c..f9119c6d2a09 100644 --- a/drivers/net/irda/vlsi_ir.h +++ b/drivers/net/irda/vlsi_ir.h @@ -615,7 +615,8 @@ static inline void rd_set_addr_status(struct ring_descr *rd, dma_addr_t a, u8 s) */ if ((a & ~DMA_MASK_MSTRPAGE)>>24 != MSTRPAGE_VALUE) { - IRDA_ERROR("%s: pci busaddr inconsistency!\n", __func__); + net_err_ratelimited("%s: pci busaddr inconsistency!\n", + __func__); dump_stack(); return; } diff --git a/drivers/net/irda/w83977af_ir.c b/drivers/net/irda/w83977af_ir.c index 11dbdf36d9c1..4e3d2e7c697c 100644 --- a/drivers/net/irda/w83977af_ir.c +++ b/drivers/net/irda/w83977af_ir.c @@ -110,8 +110,6 @@ static int __init w83977af_init(void) { int i; - IRDA_DEBUG(0, "%s()\n", __func__ ); - for (i=0; i < ARRAY_SIZE(dev_self) && io[i] < 2000; i++) { if (w83977af_open(i, io[i], irq[i], dma[i]) == 0) return 0; @@ -129,8 +127,6 @@ static void __exit w83977af_cleanup(void) { int i; - IRDA_DEBUG(4, "%s()\n", __func__ ); - for (i=0; i < ARRAY_SIZE(dev_self); i++) { if (dev_self[i]) w83977af_close(dev_self[i]); @@ -157,12 +153,10 @@ static int w83977af_open(int i, unsigned int iobase, unsigned int irq, struct w83977af_ir *self; int err; - IRDA_DEBUG(0, "%s()\n", __func__ ); - /* Lock the port that we need */ if (!request_region(iobase, CHIP_IO_EXTENT, driver_name)) { - IRDA_DEBUG(0, "%s(), can't get iobase of 0x%03x\n", - __func__ , iobase); + pr_debug("%s(), can't get iobase of 0x%03x\n", + __func__ , iobase); return -ENODEV; } @@ -236,10 +230,11 @@ static int w83977af_open(int i, unsigned int iobase, unsigned int irq, err = register_netdev(dev); if (err) { - IRDA_ERROR("%s(), register_netdevice() failed!\n", __func__); + net_err_ratelimited("%s(), register_netdevice() failed!\n", + __func__); goto err_out3; } - IRDA_MESSAGE("IrDA: Registered device %s\n", dev->name); + net_info_ratelimited("IrDA: Registered device %s\n", dev->name); /* Need to store self somewhere */ dev_self[i] = self; @@ -268,8 +263,6 @@ static int w83977af_close(struct w83977af_ir *self) { int iobase; - IRDA_DEBUG(0, "%s()\n", __func__ ); - iobase = self->io.fir_base; #ifdef CONFIG_USE_W977_PNP @@ -288,8 +281,8 @@ static int w83977af_close(struct w83977af_ir *self) unregister_netdev(self->netdev); /* Release the PORT that this driver is using */ - IRDA_DEBUG(0 , "%s(), Releasing Region %03x\n", - __func__ , self->io.fir_base); + pr_debug("%s(), Releasing Region %03x\n", + __func__ , self->io.fir_base); release_region(self->io.fir_base, self->io.fir_ext); if (self->tx_buff.head) @@ -311,7 +304,6 @@ static int w83977af_probe(int iobase, int irq, int dma) int i; for (i=0; i < 2; i++) { - IRDA_DEBUG( 0, "%s()\n", __func__ ); #ifdef CONFIG_USE_W977_PNP /* Enter PnP configuration mode */ w977_efm_enter(efbase[i]); @@ -392,13 +384,13 @@ static int w83977af_probe(int iobase, int irq, int dma) switch_bank(iobase, SET7); outb(0x40, iobase+7); - IRDA_MESSAGE("W83977AF (IR) driver loaded. " - "Version: 0x%02x\n", version); + net_info_ratelimited("W83977AF (IR) driver loaded. Version: 0x%02x\n", + version); return 0; } else { /* Try next extented function register address */ - IRDA_DEBUG( 0, "%s(), Wrong chip version", __func__ ); + pr_debug("%s(), Wrong chip version", __func__); } } return -1; @@ -434,19 +426,19 @@ static void w83977af_change_speed(struct w83977af_ir *self, __u32 speed) case 115200: outb(0x01, iobase+ABLL); break; case 576000: ir_mode = HCR_MIR_576; - IRDA_DEBUG(0, "%s(), handling baud of 576000\n", __func__ ); + pr_debug("%s(), handling baud of 576000\n", __func__); break; case 1152000: ir_mode = HCR_MIR_1152; - IRDA_DEBUG(0, "%s(), handling baud of 1152000\n", __func__ ); + pr_debug("%s(), handling baud of 1152000\n", __func__); break; case 4000000: ir_mode = HCR_FIR; - IRDA_DEBUG(0, "%s(), handling baud of 4000000\n", __func__ ); + pr_debug("%s(), handling baud of 4000000\n", __func__); break; default: ir_mode = HCR_FIR; - IRDA_DEBUG(0, "%s(), unknown baud rate of %d\n", __func__ , speed); + pr_debug("%s(), unknown baud rate of %d\n", __func__ , speed); break; } @@ -497,8 +489,8 @@ static netdev_tx_t w83977af_hard_xmit(struct sk_buff *skb, iobase = self->io.fir_base; - IRDA_DEBUG(4, "%s(%ld), skb->len=%d\n", __func__ , jiffies, - (int) skb->len); + pr_debug("%s(%ld), skb->len=%d\n", __func__ , jiffies, + (int)skb->len); /* Lock transmit buffer */ netif_stop_queue(dev); @@ -525,7 +517,7 @@ static netdev_tx_t w83977af_hard_xmit(struct sk_buff *skb, self->tx_buff.len = skb->len; mtt = irda_get_mtt(skb); - IRDA_DEBUG(4, "%s(%ld), mtt=%d\n", __func__ , jiffies, mtt); + pr_debug("%s(%ld), mtt=%d\n", __func__ , jiffies, mtt); if (mtt) udelay(mtt); @@ -559,7 +551,7 @@ static netdev_tx_t w83977af_hard_xmit(struct sk_buff *skb, static void w83977af_dma_write(struct w83977af_ir *self, int iobase) { __u8 set; - IRDA_DEBUG(4, "%s(), len=%d\n", __func__ , self->tx_buff.len); + pr_debug("%s(), len=%d\n", __func__ , self->tx_buff.len); /* Save current set */ set = inb(iobase+SSR); @@ -594,19 +586,16 @@ static int w83977af_pio_write(int iobase, __u8 *buf, int len, int fifo_size) int actual = 0; __u8 set; - IRDA_DEBUG(4, "%s()\n", __func__ ); - /* Save current bank */ set = inb(iobase+SSR); switch_bank(iobase, SET0); if (!(inb_p(iobase+USR) & USR_TSRE)) { - IRDA_DEBUG(4, - "%s(), warning, FIFO not empty yet!\n", __func__ ); + pr_debug("%s(), warning, FIFO not empty yet!\n", __func__); fifo_size -= 17; - IRDA_DEBUG(4, "%s(), %d bytes left in tx fifo\n", - __func__ , fifo_size); + pr_debug("%s(), %d bytes left in tx fifo\n", + __func__ , fifo_size); } /* Fill FIFO with current frame */ @@ -615,8 +604,8 @@ static int w83977af_pio_write(int iobase, __u8 *buf, int len, int fifo_size) outb(buf[actual++], iobase+TBR); } - IRDA_DEBUG(4, "%s(), fifo_size %d ; %d sent of %d\n", - __func__ , fifo_size, actual, len); + pr_debug("%s(), fifo_size %d ; %d sent of %d\n", + __func__ , fifo_size, actual, len); /* Restore bank */ outb(set, iobase+SSR); @@ -636,7 +625,7 @@ static void w83977af_dma_xmit_complete(struct w83977af_ir *self) int iobase; __u8 set; - IRDA_DEBUG(4, "%s(%ld)\n", __func__ , jiffies); + pr_debug("%s(%ld)\n", __func__ , jiffies); IRDA_ASSERT(self != NULL, return;); @@ -651,7 +640,7 @@ static void w83977af_dma_xmit_complete(struct w83977af_ir *self) /* Check for underrun! */ if (inb(iobase+AUDR) & AUDR_UNDR) { - IRDA_DEBUG(0, "%s(), Transmit underrun!\n", __func__ ); + pr_debug("%s(), Transmit underrun!\n", __func__); self->netdev->stats.tx_errors++; self->netdev->stats.tx_fifo_errors++; @@ -692,7 +681,7 @@ static int w83977af_dma_receive(struct w83977af_ir *self) #endif IRDA_ASSERT(self != NULL, return -1;); - IRDA_DEBUG(4, "%s\n", __func__ ); + pr_debug("%s\n", __func__); iobase= self->io.fir_base; @@ -763,7 +752,7 @@ static int w83977af_dma_receive_complete(struct w83977af_ir *self) __u8 set; __u8 status; - IRDA_DEBUG(4, "%s\n", __func__ ); + pr_debug("%s\n", __func__); st_fifo = &self->st_fifo; @@ -880,8 +869,6 @@ static void w83977af_pio_receive(struct w83977af_ir *self) __u8 byte = 0x00; int iobase; - IRDA_DEBUG(4, "%s()\n", __func__ ); - IRDA_ASSERT(self != NULL, return;); iobase = self->io.fir_base; @@ -907,7 +894,7 @@ static __u8 w83977af_sir_interrupt(struct w83977af_ir *self, int isr) __u8 set; int iobase; - IRDA_DEBUG(4, "%s(), isr=%#x\n", __func__ , isr); + pr_debug("%s(), isr=%#x\n", __func__ , isr); iobase = self->io.fir_base; /* Transmit FIFO low on data */ @@ -943,8 +930,7 @@ static __u8 w83977af_sir_interrupt(struct w83977af_ir *self, int isr) if (isr & ISR_TXEMP_I) { /* Check if we need to change the speed? */ if (self->new_speed) { - IRDA_DEBUG(2, - "%s(), Changing speed!\n", __func__ ); + pr_debug("%s(), Changing speed!\n", __func__); w83977af_change_speed(self, self->new_speed); self->new_speed = 0; } @@ -1126,7 +1112,6 @@ static int w83977af_net_open(struct net_device *dev) char hwname[32]; __u8 set; - IRDA_DEBUG(0, "%s()\n", __func__ ); IRDA_ASSERT(dev != NULL, return -1;); self = netdev_priv(dev); @@ -1189,8 +1174,6 @@ static int w83977af_net_close(struct net_device *dev) int iobase; __u8 set; - IRDA_DEBUG(0, "%s()\n", __func__ ); - IRDA_ASSERT(dev != NULL, return -1;); self = netdev_priv(dev); @@ -1244,7 +1227,7 @@ static int w83977af_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) IRDA_ASSERT(self != NULL, return -1;); - IRDA_DEBUG(2, "%s(), %s, (cmd=0x%X)\n", __func__ , dev->name, cmd); + pr_debug("%s(), %s, (cmd=0x%X)\n", __func__ , dev->name, cmd); spin_lock_irqsave(&self->lock, flags); diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index bfb0b6ec8c56..11d4b3506d6e 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -742,11 +742,12 @@ static struct lock_class_key macvlan_netdev_xmit_lock_key; static struct lock_class_key macvlan_netdev_addr_lock_key; #define ALWAYS_ON_FEATURES \ - (NETIF_F_SG | NETIF_F_GEN_CSUM | NETIF_F_GSO_SOFTWARE | NETIF_F_LLTX) + (NETIF_F_SG | NETIF_F_GEN_CSUM | NETIF_F_GSO_SOFTWARE | NETIF_F_LLTX | \ + NETIF_F_GSO_ROBUST) #define MACVLAN_FEATURES \ (NETIF_F_SG | NETIF_F_ALL_CSUM | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \ - NETIF_F_GSO | NETIF_F_TSO | NETIF_F_UFO | NETIF_F_GSO_ROBUST | \ + NETIF_F_GSO | NETIF_F_TSO | NETIF_F_UFO | \ NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_GRO | NETIF_F_RXCSUM | \ NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_STAG_FILTER) diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 880cc090dc44..22b4cf2fa108 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -15,6 +15,7 @@ #include <linux/cdev.h> #include <linux/idr.h> #include <linux/fs.h> +#include <linux/uio.h> #include <net/ipv6.h> #include <net/net_namespace.h> @@ -639,12 +640,12 @@ static void macvtap_skb_to_vnet_hdr(const struct sk_buff *skb, /* Get packet from user space buffer */ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, - const struct iovec *iv, unsigned long total_len, - size_t count, int noblock) + struct iov_iter *from, int noblock) { int good_linear = SKB_MAX_HEAD(NET_IP_ALIGN); struct sk_buff *skb; struct macvlan_dev *vlan; + unsigned long total_len = iov_iter_count(from); unsigned long len = total_len; int err; struct virtio_net_hdr vnet_hdr = { 0 }; @@ -652,6 +653,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, int copylen = 0; bool zerocopy = false; size_t linear; + ssize_t n; if (q->flags & IFF_VNET_HDR) { vnet_hdr_len = q->vnet_hdr_sz; @@ -661,10 +663,11 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, goto err; len -= vnet_hdr_len; - err = memcpy_fromiovecend((void *)&vnet_hdr, iv, 0, - sizeof(vnet_hdr)); - if (err < 0) + err = -EFAULT; + n = copy_from_iter(&vnet_hdr, sizeof(vnet_hdr), from); + if (n != sizeof(vnet_hdr)) goto err; + iov_iter_advance(from, vnet_hdr_len - sizeof(vnet_hdr)); if ((vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && vnet_hdr.csum_start + vnet_hdr.csum_offset + 2 > vnet_hdr.hdr_len) @@ -679,17 +682,16 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, if (unlikely(len < ETH_HLEN)) goto err; - err = -EMSGSIZE; - if (unlikely(count > UIO_MAXIOV)) - goto err; - if (m && m->msg_control && sock_flag(&q->sk, SOCK_ZEROCOPY)) { + struct iov_iter i; + copylen = vnet_hdr.hdr_len ? vnet_hdr.hdr_len : GOODCOPY_LEN; if (copylen > good_linear) copylen = good_linear; linear = copylen; - if (iov_pages(iv, vnet_hdr_len + copylen, count) - <= MAX_SKB_FRAGS) + i = *from; + iov_iter_advance(&i, copylen); + if (iov_iter_npages(&i, INT_MAX) <= MAX_SKB_FRAGS) zerocopy = true; } @@ -707,10 +709,9 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, goto err; if (zerocopy) - err = zerocopy_sg_from_iovec(skb, iv, vnet_hdr_len, count); + err = zerocopy_sg_from_iter(skb, from); else { - err = skb_copy_datagram_from_iovec(skb, 0, iv, vnet_hdr_len, - len); + err = skb_copy_datagram_from_iter(skb, 0, from, len); if (!err && m && m->msg_control) { struct ubuf_info *uarg = m->msg_control; uarg->callback(uarg, false); @@ -763,46 +764,42 @@ err: return err; } -static ssize_t macvtap_aio_write(struct kiocb *iocb, const struct iovec *iv, - unsigned long count, loff_t pos) +static ssize_t macvtap_write_iter(struct kiocb *iocb, struct iov_iter *from) { struct file *file = iocb->ki_filp; - ssize_t result = -ENOLINK; struct macvtap_queue *q = file->private_data; - result = macvtap_get_user(q, NULL, iv, iov_length(iv, count), count, - file->f_flags & O_NONBLOCK); - return result; + return macvtap_get_user(q, NULL, from, file->f_flags & O_NONBLOCK); } /* Put packet to the user space buffer */ static ssize_t macvtap_put_user(struct macvtap_queue *q, const struct sk_buff *skb, - const struct iovec *iv, int len) + struct iov_iter *iter) { int ret; int vnet_hdr_len = 0; int vlan_offset = 0; - int copied, total; + int total; if (q->flags & IFF_VNET_HDR) { struct virtio_net_hdr vnet_hdr; vnet_hdr_len = q->vnet_hdr_sz; - if ((len -= vnet_hdr_len) < 0) + if (iov_iter_count(iter) < vnet_hdr_len) return -EINVAL; macvtap_skb_to_vnet_hdr(skb, &vnet_hdr); - if (memcpy_toiovecend(iv, (void *)&vnet_hdr, 0, sizeof(vnet_hdr))) + if (copy_to_iter(&vnet_hdr, sizeof(vnet_hdr), iter) != + sizeof(vnet_hdr)) return -EFAULT; + + iov_iter_advance(iter, vnet_hdr_len - sizeof(vnet_hdr)); } - total = copied = vnet_hdr_len; + total = vnet_hdr_len; total += skb->len; - if (!vlan_tx_tag_present(skb)) - len = min_t(int, skb->len, len); - else { - int copy; + if (vlan_tx_tag_present(skb)) { struct { __be16 h_vlan_proto; __be16 h_vlan_TCI; @@ -811,86 +808,74 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q, veth.h_vlan_TCI = htons(vlan_tx_tag_get(skb)); vlan_offset = offsetof(struct vlan_ethhdr, h_vlan_proto); - len = min_t(int, skb->len + VLAN_HLEN, len); total += VLAN_HLEN; - copy = min_t(int, vlan_offset, len); - ret = skb_copy_datagram_const_iovec(skb, 0, iv, copied, copy); - len -= copy; - copied += copy; - if (ret || !len) + ret = skb_copy_datagram_iter(skb, 0, iter, vlan_offset); + if (ret || !iov_iter_count(iter)) goto done; - copy = min_t(int, sizeof(veth), len); - ret = memcpy_toiovecend(iv, (void *)&veth, copied, copy); - len -= copy; - copied += copy; - if (ret || !len) + ret = copy_to_iter(&veth, sizeof(veth), iter); + if (ret != sizeof(veth) || !iov_iter_count(iter)) goto done; } - ret = skb_copy_datagram_const_iovec(skb, vlan_offset, iv, copied, len); + ret = skb_copy_datagram_iter(skb, vlan_offset, iter, + skb->len - vlan_offset); done: return ret ? ret : total; } static ssize_t macvtap_do_read(struct macvtap_queue *q, - const struct iovec *iv, unsigned long len, + struct iov_iter *to, int noblock) { DEFINE_WAIT(wait); struct sk_buff *skb; ssize_t ret = 0; - while (len) { + if (!iov_iter_count(to)) + return 0; + + while (1) { if (!noblock) prepare_to_wait(sk_sleep(&q->sk), &wait, TASK_INTERRUPTIBLE); /* Read frames from the queue */ skb = skb_dequeue(&q->sk.sk_receive_queue); - if (!skb) { - if (noblock) { - ret = -EAGAIN; - break; - } - if (signal_pending(current)) { - ret = -ERESTARTSYS; - break; - } - /* Nothing to read, let's sleep */ - schedule(); - continue; + if (skb) + break; + if (noblock) { + ret = -EAGAIN; + break; } - ret = macvtap_put_user(q, skb, iv, len); + if (signal_pending(current)) { + ret = -ERESTARTSYS; + break; + } + /* Nothing to read, let's sleep */ + schedule(); + } + if (skb) { + ret = macvtap_put_user(q, skb, to); kfree_skb(skb); - break; } - if (!noblock) finish_wait(sk_sleep(&q->sk), &wait); return ret; } -static ssize_t macvtap_aio_read(struct kiocb *iocb, const struct iovec *iv, - unsigned long count, loff_t pos) +static ssize_t macvtap_read_iter(struct kiocb *iocb, struct iov_iter *to) { struct file *file = iocb->ki_filp; struct macvtap_queue *q = file->private_data; - ssize_t len, ret = 0; + ssize_t len = iov_iter_count(to), ret; - len = iov_length(iv, count); - if (len < 0) { - ret = -EINVAL; - goto out; - } - - ret = macvtap_do_read(q, iv, len, file->f_flags & O_NONBLOCK); + ret = macvtap_do_read(q, to, file->f_flags & O_NONBLOCK); ret = min_t(ssize_t, ret, len); if (ret > 0) iocb->ki_pos = ret; -out: return ret; } @@ -1091,8 +1076,10 @@ static const struct file_operations macvtap_fops = { .owner = THIS_MODULE, .open = macvtap_open, .release = macvtap_release, - .aio_read = macvtap_aio_read, - .aio_write = macvtap_aio_write, + .read = new_sync_read, + .write = new_sync_write, + .read_iter = macvtap_read_iter, + .write_iter = macvtap_write_iter, .poll = macvtap_poll, .llseek = no_llseek, .unlocked_ioctl = macvtap_ioctl, @@ -1105,8 +1092,9 @@ static int macvtap_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t total_len) { struct macvtap_queue *q = container_of(sock, struct macvtap_queue, sock); - return macvtap_get_user(q, m, m->msg_iov, total_len, m->msg_iovlen, - m->msg_flags & MSG_DONTWAIT); + struct iov_iter from; + iov_iter_init(&from, WRITE, m->msg_iov, m->msg_iovlen, total_len); + return macvtap_get_user(q, m, &from, m->msg_flags & MSG_DONTWAIT); } static int macvtap_recvmsg(struct kiocb *iocb, struct socket *sock, @@ -1114,11 +1102,12 @@ static int macvtap_recvmsg(struct kiocb *iocb, struct socket *sock, int flags) { struct macvtap_queue *q = container_of(sock, struct macvtap_queue, sock); + struct iov_iter to; int ret; if (flags & ~(MSG_DONTWAIT|MSG_TRUNC)) return -EINVAL; - ret = macvtap_do_read(q, m->msg_iov, total_len, - flags & MSG_DONTWAIT); + iov_iter_init(&to, READ, m->msg_iov, m->msg_iovlen, total_len); + ret = macvtap_do_read(q, &to, flags & MSG_DONTWAIT); if (ret > total_len) { m->msg_flags |= MSG_TRUNC; ret = flags & MSG_TRUNC ? ret : total_len; diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 75472cf734de..b4b0f804e84c 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -26,7 +26,7 @@ config AMD_PHY config AMD_XGBE_PHY tristate "Driver for the AMD 10GbE (amd-xgbe) PHYs" - depends on OF + depends on OF && HAS_IOMEM ---help--- Currently supports the AMD 10GbE PHY diff --git a/drivers/net/phy/amd-xgbe-phy.c b/drivers/net/phy/amd-xgbe-phy.c index c456559f6e7f..903dc3dc9ea7 100644 --- a/drivers/net/phy/amd-xgbe-phy.c +++ b/drivers/net/phy/amd-xgbe-phy.c @@ -992,7 +992,8 @@ static int amd_xgbe_phy_soft_reset(struct phy_device *phydev) if (ret & MDIO_CTRL1_RESET) return -ETIMEDOUT; - return 0; + /* Make sure the XPCS and SerDes are in compatible states */ + return amd_xgbe_phy_xgmii_mode(phydev); } static int amd_xgbe_phy_config_init(struct phy_device *phydev) @@ -1467,20 +1468,7 @@ static struct phy_driver amd_xgbe_phy_driver[] = { }, }; -static int __init amd_xgbe_phy_init(void) -{ - return phy_drivers_register(amd_xgbe_phy_driver, - ARRAY_SIZE(amd_xgbe_phy_driver)); -} - -static void __exit amd_xgbe_phy_exit(void) -{ - phy_drivers_unregister(amd_xgbe_phy_driver, - ARRAY_SIZE(amd_xgbe_phy_driver)); -} - -module_init(amd_xgbe_phy_init); -module_exit(amd_xgbe_phy_exit); +module_phy_driver(amd_xgbe_phy_driver); static struct mdio_device_id __maybe_unused amd_xgbe_phy_ids[] = { { XGBE_PHY_ID, XGBE_PHY_MASK }, diff --git a/drivers/net/phy/amd.c b/drivers/net/phy/amd.c index a3fb5ceb6487..65a488f82eb8 100644 --- a/drivers/net/phy/amd.c +++ b/drivers/net/phy/amd.c @@ -61,7 +61,7 @@ static int am79c_config_intr(struct phy_device *phydev) return err; } -static struct phy_driver am79c_driver = { +static struct phy_driver am79c_driver[] = { { .phy_id = PHY_ID_AM79C874, .name = "AM79C874", .phy_id_mask = 0xfffffff0, @@ -73,20 +73,9 @@ static struct phy_driver am79c_driver = { .ack_interrupt = am79c_ack_interrupt, .config_intr = am79c_config_intr, .driver = { .owner = THIS_MODULE,}, -}; - -static int __init am79c_init(void) -{ - return phy_driver_register(&am79c_driver); -} - -static void __exit am79c_exit(void) -{ - phy_driver_unregister(&am79c_driver); -} +} }; -module_init(am79c_init); -module_exit(am79c_exit); +module_phy_driver(am79c_driver); static struct mdio_device_id __maybe_unused amd_tbl[] = { { PHY_ID_AM79C874, 0xfffffff0 }, diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c index fdc1b418fa6a..f80e19ac6704 100644 --- a/drivers/net/phy/at803x.c +++ b/drivers/net/phy/at803x.c @@ -352,19 +352,7 @@ static struct phy_driver at803x_driver[] = { }, } }; -static int __init atheros_init(void) -{ - return phy_drivers_register(at803x_driver, - ARRAY_SIZE(at803x_driver)); -} - -static void __exit atheros_exit(void) -{ - phy_drivers_unregister(at803x_driver, ARRAY_SIZE(at803x_driver)); -} - -module_init(atheros_init); -module_exit(atheros_exit); +module_phy_driver(at803x_driver); static struct mdio_device_id __maybe_unused atheros_tbl[] = { { ATH8030_PHY_ID, 0xffffffef }, diff --git a/drivers/net/phy/bcm63xx.c b/drivers/net/phy/bcm63xx.c index ac55b0807853..830ec31f952f 100644 --- a/drivers/net/phy/bcm63xx.c +++ b/drivers/net/phy/bcm63xx.c @@ -100,20 +100,7 @@ static struct phy_driver bcm63xx_driver[] = { .driver = { .owner = THIS_MODULE }, } }; -static int __init bcm63xx_phy_init(void) -{ - return phy_drivers_register(bcm63xx_driver, - ARRAY_SIZE(bcm63xx_driver)); -} - -static void __exit bcm63xx_phy_exit(void) -{ - phy_drivers_unregister(bcm63xx_driver, - ARRAY_SIZE(bcm63xx_driver)); -} - -module_init(bcm63xx_phy_init); -module_exit(bcm63xx_phy_exit); +module_phy_driver(bcm63xx_driver); static struct mdio_device_id __maybe_unused bcm63xx_tbl[] = { { 0x00406000, 0xfffffc00 }, diff --git a/drivers/net/phy/bcm7xxx.c b/drivers/net/phy/bcm7xxx.c index 1d211d369039..7a53af4346e4 100644 --- a/drivers/net/phy/bcm7xxx.c +++ b/drivers/net/phy/bcm7xxx.c @@ -39,45 +39,15 @@ #define AFE_RXCONFIG_0 MISC_ADDR(0x38, 0) #define AFE_RXCONFIG_1 MISC_ADDR(0x38, 1) +#define AFE_RXCONFIG_2 MISC_ADDR(0x38, 2) #define AFE_RX_LP_COUNTER MISC_ADDR(0x38, 3) #define AFE_TX_CONFIG MISC_ADDR(0x39, 0) +#define AFE_VDCA_ICTRL_0 MISC_ADDR(0x39, 1) +#define AFE_VDAC_OTHERS_0 MISC_ADDR(0x39, 3) #define AFE_HPF_TRIM_OTHERS MISC_ADDR(0x3a, 0) #define CORE_EXPB0 0xb0 -static int bcm7445_config_init(struct phy_device *phydev) -{ - int ret; - const struct bcm7445_regs { - int reg; - u16 value; - } bcm7445_regs_cfg[] = { - /* increases ADC latency by 24ns */ - { MII_BCM54XX_EXP_SEL, 0x0038 }, - { MII_BCM54XX_EXP_DATA, 0xAB95 }, - /* increases internal 1V LDO voltage by 5% */ - { MII_BCM54XX_EXP_SEL, 0x2038 }, - { MII_BCM54XX_EXP_DATA, 0xBB22 }, - /* reduce RX low pass filter corner frequency */ - { MII_BCM54XX_EXP_SEL, 0x6038 }, - { MII_BCM54XX_EXP_DATA, 0xFFC5 }, - /* reduce RX high pass filter corner frequency */ - { MII_BCM54XX_EXP_SEL, 0x003a }, - { MII_BCM54XX_EXP_DATA, 0x2002 }, - }; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(bcm7445_regs_cfg); i++) { - ret = phy_write(phydev, - bcm7445_regs_cfg[i].reg, - bcm7445_regs_cfg[i].value); - if (ret) - return ret; - } - - return 0; -} - static void phy_write_exp(struct phy_device *phydev, u16 reg, u16 value) { @@ -102,7 +72,16 @@ static void phy_write_misc(struct phy_device *phydev, phy_write(phydev, MII_BCM54XX_EXP_DATA, value); } -static int bcm7xxx_28nm_afe_config_init(struct phy_device *phydev) +static void r_rc_cal_reset(struct phy_device *phydev) +{ + /* Reset R_CAL/RC_CAL Engine */ + phy_write_exp(phydev, 0x00b0, 0x0010); + + /* Disable Reset R_AL/RC_CAL Engine */ + phy_write_exp(phydev, 0x00b0, 0x0000); +} + +static int bcm7xxx_28nm_b0_afe_config_init(struct phy_device *phydev) { /* Increase VCO range to prevent unlocking problem of PLL at low * temp @@ -123,11 +102,7 @@ static int bcm7xxx_28nm_afe_config_init(struct phy_device *phydev) /* Switch to CORE_BASE1E */ phy_write(phydev, MII_BCM7XXX_CORE_BASE1E, 0xd); - /* Reset R_CAL/RC_CAL Engine */ - phy_write_exp(phydev, CORE_EXPB0, 0x0010); - - /* Disable Reset R_CAL/RC_CAL Engine */ - phy_write_exp(phydev, CORE_EXPB0, 0x0000); + r_rc_cal_reset(phydev); /* write AFE_RXCONFIG_0 */ phy_write_misc(phydev, AFE_RXCONFIG_0, 0xeb19); @@ -147,6 +122,71 @@ static int bcm7xxx_28nm_afe_config_init(struct phy_device *phydev) return 0; } +static int bcm7xxx_28nm_d0_afe_config_init(struct phy_device *phydev) +{ + /* AFE_RXCONFIG_0 */ + phy_write_misc(phydev, AFE_RXCONFIG_0, 0xeb15); + + /* AFE_RXCONFIG_1 */ + phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9b2f); + + /* AFE_RXCONFIG_2, set rCal offset for HT=0 code and LT=-2 code */ + phy_write_misc(phydev, AFE_RXCONFIG_2, 0x2003); + + /* AFE_RX_LP_COUNTER, set RX bandwidth to maximum */ + phy_write_misc(phydev, AFE_RX_LP_COUNTER, 0x7fc0); + + /* AFE_TX_CONFIG, set 1000BT Cfeed=110 for all ports */ + phy_write_misc(phydev, AFE_TX_CONFIG, 0x0061); + + /* AFE_VDCA_ICTRL_0, set Iq=1101 instead of 0111 for AB symmetry */ + phy_write_misc(phydev, AFE_VDCA_ICTRL_0, 0xa7da); + + /* AFE_VDAC_OTHERS_0, set 1000BT Cidac=010 for all ports */ + phy_write_misc(phydev, AFE_VDAC_OTHERS_0, 0xa020); + + /* AFE_HPF_TRIM_OTHERS, set 100Tx/10BT to -4.5% swing and set rCal + * offset for HT=0 code + */ + phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x00e3); + + /* CORE_BASE1E, force trim to overwrite and set I_ext trim to 0000 */ + phy_write(phydev, MII_BCM7XXX_CORE_BASE1E, 0x0010); + + /* DSP_TAP10, adjust bias current trim (+0% swing, +0 tick) */ + phy_write_misc(phydev, DSP_TAP10, 0x011b); + + /* Reset R_CAL/RC_CAL engine */ + r_rc_cal_reset(phydev); + + return 0; +} + +static int bcm7xxx_28nm_e0_plus_afe_config_init(struct phy_device *phydev) +{ + /* AFE_RXCONFIG_1, provide more margin for INL/DNL measurement */ + phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9b2f); + + /* AFE_VDCA_ICTRL_0, set Iq=1101 instead of 0111 for AB symmetry */ + phy_write_misc(phydev, AFE_VDCA_ICTRL_0, 0xa7da); + + /* AFE_HPF_TRIM_OTHERS, set 100Tx/10BT to -4.5% swing and set rCal + * offset for HT=0 code + */ + phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x00e3); + + /* CORE_BASE1E, force trim to overwrite and set I_ext trim to 0000 */ + phy_write(phydev, MII_BCM7XXX_CORE_BASE1E, 0x0010); + + /* DSP_TAP10, adjust bias current trim (+0% swing, +0 tick) */ + phy_write_misc(phydev, DSP_TAP10, 0x011b); + + /* Reset R_CAL/RC_CAL engine */ + r_rc_cal_reset(phydev); + + return 0; +} + static int bcm7xxx_apd_enable(struct phy_device *phydev) { int val; @@ -200,15 +240,21 @@ static int bcm7xxx_28nm_config_init(struct phy_device *phydev) u8 patch = PHY_BRCM_7XXX_PATCH(phydev->dev_flags); int ret = 0; - dev_info(&phydev->dev, "PHY revision: 0x%02x, patch: %d\n", rev, patch); + pr_info_once("%s: %s PHY revision: 0x%02x, patch: %d\n", + dev_name(&phydev->dev), phydev->drv->name, rev, patch); switch (rev) { - case 0xa0: case 0xb0: - ret = bcm7445_config_init(phydev); + ret = bcm7xxx_28nm_b0_afe_config_init(phydev); + break; + case 0xd0: + ret = bcm7xxx_28nm_d0_afe_config_init(phydev); + break; + case 0xe0: + case 0xf0: + ret = bcm7xxx_28nm_e0_plus_afe_config_init(phydev); break; default: - ret = bcm7xxx_28nm_afe_config_init(phydev); break; } @@ -336,7 +382,7 @@ static int bcm7xxx_dummy_config_init(struct phy_device *phydev) .features = PHY_GBIT_FEATURES | \ SUPPORTED_Pause | SUPPORTED_Asym_Pause, \ .flags = PHY_IS_INTERNAL, \ - .config_init = bcm7xxx_28nm_afe_config_init, \ + .config_init = bcm7xxx_28nm_config_init, \ .config_aneg = genphy_config_aneg, \ .read_status = genphy_read_status, \ .resume = bcm7xxx_28nm_resume, \ @@ -416,20 +462,7 @@ static struct mdio_device_id __maybe_unused bcm7xxx_tbl[] = { { } }; -static int __init bcm7xxx_phy_init(void) -{ - return phy_drivers_register(bcm7xxx_driver, - ARRAY_SIZE(bcm7xxx_driver)); -} - -static void __exit bcm7xxx_phy_exit(void) -{ - phy_drivers_unregister(bcm7xxx_driver, - ARRAY_SIZE(bcm7xxx_driver)); -} - -module_init(bcm7xxx_phy_init); -module_exit(bcm7xxx_phy_exit); +module_phy_driver(bcm7xxx_driver); MODULE_DEVICE_TABLE(mdio, bcm7xxx_tbl); diff --git a/drivers/net/phy/bcm87xx.c b/drivers/net/phy/bcm87xx.c index 799789518e87..1eca20452f03 100644 --- a/drivers/net/phy/bcm87xx.c +++ b/drivers/net/phy/bcm87xx.c @@ -216,18 +216,6 @@ static struct phy_driver bcm87xx_driver[] = { .driver = { .owner = THIS_MODULE }, } }; -static int __init bcm87xx_init(void) -{ - return phy_drivers_register(bcm87xx_driver, - ARRAY_SIZE(bcm87xx_driver)); -} -module_init(bcm87xx_init); - -static void __exit bcm87xx_exit(void) -{ - phy_drivers_unregister(bcm87xx_driver, - ARRAY_SIZE(bcm87xx_driver)); -} -module_exit(bcm87xx_exit); +module_phy_driver(bcm87xx_driver); MODULE_LICENSE("GPL"); diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c index 854f2c9a7b2b..a52afb26421b 100644 --- a/drivers/net/phy/broadcom.c +++ b/drivers/net/phy/broadcom.c @@ -654,20 +654,7 @@ static struct phy_driver broadcom_drivers[] = { .driver = { .owner = THIS_MODULE }, } }; -static int __init broadcom_init(void) -{ - return phy_drivers_register(broadcom_drivers, - ARRAY_SIZE(broadcom_drivers)); -} - -static void __exit broadcom_exit(void) -{ - phy_drivers_unregister(broadcom_drivers, - ARRAY_SIZE(broadcom_drivers)); -} - -module_init(broadcom_init); -module_exit(broadcom_exit); +module_phy_driver(broadcom_drivers); static struct mdio_device_id __maybe_unused broadcom_tbl[] = { { PHY_ID_BCM5411, 0xfffffff0 }, diff --git a/drivers/net/phy/cicada.c b/drivers/net/phy/cicada.c index b57ce0cc9657..27f5464899d4 100644 --- a/drivers/net/phy/cicada.c +++ b/drivers/net/phy/cicada.c @@ -129,20 +129,7 @@ static struct phy_driver cis820x_driver[] = { .driver = { .owner = THIS_MODULE,}, } }; -static int __init cicada_init(void) -{ - return phy_drivers_register(cis820x_driver, - ARRAY_SIZE(cis820x_driver)); -} - -static void __exit cicada_exit(void) -{ - phy_drivers_unregister(cis820x_driver, - ARRAY_SIZE(cis820x_driver)); -} - -module_init(cicada_init); -module_exit(cicada_exit); +module_phy_driver(cis820x_driver); static struct mdio_device_id __maybe_unused cicada_tbl[] = { { 0x000fc410, 0x000ffff0 }, diff --git a/drivers/net/phy/davicom.c b/drivers/net/phy/davicom.c index d2c08f625a41..0d16c7d9e1bf 100644 --- a/drivers/net/phy/davicom.c +++ b/drivers/net/phy/davicom.c @@ -182,20 +182,7 @@ static struct phy_driver dm91xx_driver[] = { .driver = { .owner = THIS_MODULE,}, } }; -static int __init davicom_init(void) -{ - return phy_drivers_register(dm91xx_driver, - ARRAY_SIZE(dm91xx_driver)); -} - -static void __exit davicom_exit(void) -{ - phy_drivers_unregister(dm91xx_driver, - ARRAY_SIZE(dm91xx_driver)); -} - -module_init(davicom_init); -module_exit(davicom_exit); +module_phy_driver(dm91xx_driver); static struct mdio_device_id __maybe_unused davicom_tbl[] = { { 0x0181b880, 0x0ffffff0 }, diff --git a/drivers/net/phy/et1011c.c b/drivers/net/phy/et1011c.c index a8eb19ec3183..a907743816a8 100644 --- a/drivers/net/phy/et1011c.c +++ b/drivers/net/phy/et1011c.c @@ -87,7 +87,7 @@ static int et1011c_read_status(struct phy_device *phydev) return ret; } -static struct phy_driver et1011c_driver = { +static struct phy_driver et1011c_driver[] = { { .phy_id = 0x0282f014, .name = "ET1011C", .phy_id_mask = 0xfffffff0, @@ -96,20 +96,9 @@ static struct phy_driver et1011c_driver = { .config_aneg = et1011c_config_aneg, .read_status = et1011c_read_status, .driver = { .owner = THIS_MODULE,}, -}; - -static int __init et1011c_init(void) -{ - return phy_driver_register(&et1011c_driver); -} - -static void __exit et1011c_exit(void) -{ - phy_driver_unregister(&et1011c_driver); -} +} }; -module_init(et1011c_init); -module_exit(et1011c_exit); +module_phy_driver(et1011c_driver); static struct mdio_device_id __maybe_unused et1011c_tbl[] = { { 0x0282f014, 0xfffffff0 }, diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c index 97bf58bf4939..8644f039d922 100644 --- a/drivers/net/phy/icplus.c +++ b/drivers/net/phy/icplus.c @@ -253,20 +253,7 @@ static struct phy_driver icplus_driver[] = { .driver = { .owner = THIS_MODULE,}, } }; -static int __init icplus_init(void) -{ - return phy_drivers_register(icplus_driver, - ARRAY_SIZE(icplus_driver)); -} - -static void __exit icplus_exit(void) -{ - phy_drivers_unregister(icplus_driver, - ARRAY_SIZE(icplus_driver)); -} - -module_init(icplus_init); -module_exit(icplus_exit); +module_phy_driver(icplus_driver); static struct mdio_device_id __maybe_unused icplus_tbl[] = { { 0x02430d80, 0x0ffffff0 }, diff --git a/drivers/net/phy/lxt.c b/drivers/net/phy/lxt.c index 9108f3191701..a3a5a703635b 100644 --- a/drivers/net/phy/lxt.c +++ b/drivers/net/phy/lxt.c @@ -312,20 +312,7 @@ static struct phy_driver lxt97x_driver[] = { .driver = { .owner = THIS_MODULE,}, } }; -static int __init lxt_init(void) -{ - return phy_drivers_register(lxt97x_driver, - ARRAY_SIZE(lxt97x_driver)); -} - -static void __exit lxt_exit(void) -{ - phy_drivers_unregister(lxt97x_driver, - ARRAY_SIZE(lxt97x_driver)); -} - -module_init(lxt_init); -module_exit(lxt_exit); +module_phy_driver(lxt97x_driver); static struct mdio_device_id __maybe_unused lxt_tbl[] = { { 0x78100000, 0xfffffff0 }, diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 225c033b08f3..1b1698f98818 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -54,6 +54,9 @@ #define MII_M1145_PHY_EXT_CR 0x14 #define MII_M1145_RGMII_RX_DELAY 0x0080 #define MII_M1145_RGMII_TX_DELAY 0x0002 +#define MII_M1145_HWCFG_MODE_SGMII_NO_CLK 0x4 +#define MII_M1145_HWCFG_MODE_MASK 0xf +#define MII_M1145_HWCFG_FIBER_COPPER_AUTO 0x8000 #define MII_M1145_HWCFG_MODE_SGMII_NO_CLK 0x4 #define MII_M1145_HWCFG_MODE_MASK 0xf @@ -123,6 +126,9 @@ #define MII_M1116R_CONTROL_REG_MAC 21 +#define MII_88E3016_PHY_SPEC_CTRL 0x10 +#define MII_88E3016_DISABLE_SCRAMBLER 0x0200 +#define MII_88E3016_AUTO_MDIX_CROSSOVER 0x0030 MODULE_DESCRIPTION("Marvell PHY driver"); MODULE_AUTHOR("Andy Fleming"); @@ -439,6 +445,25 @@ static int m88e1116r_config_init(struct phy_device *phydev) return 0; } +static int m88e3016_config_init(struct phy_device *phydev) +{ + int reg; + + /* Enable Scrambler and Auto-Crossover */ + reg = phy_read(phydev, MII_88E3016_PHY_SPEC_CTRL); + if (reg < 0) + return reg; + + reg &= ~MII_88E3016_DISABLE_SCRAMBLER; + reg |= MII_88E3016_AUTO_MDIX_CROSSOVER; + + reg = phy_write(phydev, MII_88E3016_PHY_SPEC_CTRL, reg); + if (reg < 0) + return reg; + + return 0; +} + static int m88e1111_config_init(struct phy_device *phydev) { int err; @@ -625,6 +650,7 @@ static int m88e1149_config_init(struct phy_device *phydev) static int m88e1145_config_init(struct phy_device *phydev) { int err; + int temp; /* Take care of errata E0 & E1 */ err = phy_write(phydev, 0x1d, 0x001b); @@ -682,7 +708,7 @@ static int m88e1145_config_init(struct phy_device *phydev) } if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { - int temp = phy_read(phydev, MII_M1145_PHY_EXT_SR); + temp = phy_read(phydev, MII_M1145_PHY_EXT_SR); if (temp < 0) return temp; @@ -789,6 +815,12 @@ static int marvell_read_status(struct phy_device *phydev) return 0; } +static int marvell_aneg_done(struct phy_device *phydev) +{ + int retval = phy_read(phydev, MII_M1011_PHY_STATUS); + return (retval < 0) ? retval : (retval & MII_M1011_PHY_STATUS_RESOLVED); +} + static int m88e1121_did_interrupt(struct phy_device *phydev) { int imask; @@ -1069,22 +1101,26 @@ static struct phy_driver marvell_drivers[] = { .suspend = &genphy_suspend, .driver = { .owner = THIS_MODULE }, }, + { + .phy_id = MARVELL_PHY_ID_88E3016, + .phy_id_mask = MARVELL_PHY_ID_MASK, + .name = "Marvell 88E3016", + .features = PHY_BASIC_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_aneg = &genphy_config_aneg, + .config_init = &m88e3016_config_init, + .aneg_done = &marvell_aneg_done, + .read_status = &marvell_read_status, + .ack_interrupt = &marvell_ack_interrupt, + .config_intr = &marvell_config_intr, + .did_interrupt = &m88e1121_did_interrupt, + .resume = &genphy_resume, + .suspend = &genphy_suspend, + .driver = { .owner = THIS_MODULE }, + }, }; -static int __init marvell_init(void) -{ - return phy_drivers_register(marvell_drivers, - ARRAY_SIZE(marvell_drivers)); -} - -static void __exit marvell_exit(void) -{ - phy_drivers_unregister(marvell_drivers, - ARRAY_SIZE(marvell_drivers)); -} - -module_init(marvell_init); -module_exit(marvell_exit); +module_phy_driver(marvell_drivers); static struct mdio_device_id __maybe_unused marvell_tbl[] = { { MARVELL_PHY_ID_88E1101, MARVELL_PHY_ID_MASK }, @@ -1098,6 +1134,7 @@ static struct mdio_device_id __maybe_unused marvell_tbl[] = { { MARVELL_PHY_ID_88E1318S, MARVELL_PHY_ID_MASK }, { MARVELL_PHY_ID_88E1116R, MARVELL_PHY_ID_MASK }, { MARVELL_PHY_ID_88E1510, MARVELL_PHY_ID_MASK }, + { MARVELL_PHY_ID_88E3016, MARVELL_PHY_ID_MASK }, { } }; diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index 8c2a29a9bd7f..c530de1e63f5 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c @@ -6,6 +6,7 @@ * Author: David J. Choi * * Copyright (c) 2010-2013 Micrel, Inc. + * Copyright (c) 2014 Johan Hovold <johan@kernel.org> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -30,30 +31,32 @@ /* Operation Mode Strap Override */ #define MII_KSZPHY_OMSO 0x16 -#define KSZPHY_OMSO_B_CAST_OFF (1 << 9) -#define KSZPHY_OMSO_RMII_OVERRIDE (1 << 1) -#define KSZPHY_OMSO_MII_OVERRIDE (1 << 0) +#define KSZPHY_OMSO_B_CAST_OFF BIT(9) +#define KSZPHY_OMSO_RMII_OVERRIDE BIT(1) +#define KSZPHY_OMSO_MII_OVERRIDE BIT(0) /* general Interrupt control/status reg in vendor specific block. */ #define MII_KSZPHY_INTCS 0x1B -#define KSZPHY_INTCS_JABBER (1 << 15) -#define KSZPHY_INTCS_RECEIVE_ERR (1 << 14) -#define KSZPHY_INTCS_PAGE_RECEIVE (1 << 13) -#define KSZPHY_INTCS_PARELLEL (1 << 12) -#define KSZPHY_INTCS_LINK_PARTNER_ACK (1 << 11) -#define KSZPHY_INTCS_LINK_DOWN (1 << 10) -#define KSZPHY_INTCS_REMOTE_FAULT (1 << 9) -#define KSZPHY_INTCS_LINK_UP (1 << 8) +#define KSZPHY_INTCS_JABBER BIT(15) +#define KSZPHY_INTCS_RECEIVE_ERR BIT(14) +#define KSZPHY_INTCS_PAGE_RECEIVE BIT(13) +#define KSZPHY_INTCS_PARELLEL BIT(12) +#define KSZPHY_INTCS_LINK_PARTNER_ACK BIT(11) +#define KSZPHY_INTCS_LINK_DOWN BIT(10) +#define KSZPHY_INTCS_REMOTE_FAULT BIT(9) +#define KSZPHY_INTCS_LINK_UP BIT(8) #define KSZPHY_INTCS_ALL (KSZPHY_INTCS_LINK_UP |\ KSZPHY_INTCS_LINK_DOWN) -/* general PHY control reg in vendor specific block. */ -#define MII_KSZPHY_CTRL 0x1F +/* PHY Control 1 */ +#define MII_KSZPHY_CTRL_1 0x1e + +/* PHY Control 2 / PHY Control (if no PHY Control 1) */ +#define MII_KSZPHY_CTRL_2 0x1f +#define MII_KSZPHY_CTRL MII_KSZPHY_CTRL_2 /* bitmap of PHY register to set interrupt mode */ -#define KSZPHY_CTRL_INT_ACTIVE_HIGH (1 << 9) -#define KSZ9021_CTRL_INT_ACTIVE_HIGH (1 << 14) -#define KS8737_CTRL_INT_ACTIVE_HIGH (1 << 14) -#define KSZ8051_RMII_50MHZ_CLK (1 << 7) +#define KSZPHY_CTRL_INT_ACTIVE_HIGH BIT(9) +#define KSZPHY_RMII_REF_CLK_SEL BIT(7) /* Write/read to/from extended registers */ #define MII_KSZPHY_EXTREG 0x0b @@ -69,20 +72,46 @@ #define PS_TO_REG 200 -static int ksz_config_flags(struct phy_device *phydev) -{ - int regval; +struct kszphy_type { + u32 led_mode_reg; + u16 interrupt_level_mask; + bool has_broadcast_disable; + bool has_rmii_ref_clk_sel; +}; - if (phydev->dev_flags & (MICREL_PHY_50MHZ_CLK | MICREL_PHY_25MHZ_CLK)) { - regval = phy_read(phydev, MII_KSZPHY_CTRL); - if (phydev->dev_flags & MICREL_PHY_50MHZ_CLK) - regval |= KSZ8051_RMII_50MHZ_CLK; - else - regval &= ~KSZ8051_RMII_50MHZ_CLK; - return phy_write(phydev, MII_KSZPHY_CTRL, regval); - } - return 0; -} +struct kszphy_priv { + const struct kszphy_type *type; + int led_mode; + bool rmii_ref_clk_sel; + bool rmii_ref_clk_sel_val; +}; + +static const struct kszphy_type ksz8021_type = { + .led_mode_reg = MII_KSZPHY_CTRL_2, + .has_rmii_ref_clk_sel = true, +}; + +static const struct kszphy_type ksz8041_type = { + .led_mode_reg = MII_KSZPHY_CTRL_1, +}; + +static const struct kszphy_type ksz8051_type = { + .led_mode_reg = MII_KSZPHY_CTRL_2, +}; + +static const struct kszphy_type ksz8081_type = { + .led_mode_reg = MII_KSZPHY_CTRL_2, + .has_broadcast_disable = true, + .has_rmii_ref_clk_sel = true, +}; + +static const struct kszphy_type ks8737_type = { + .interrupt_level_mask = BIT(14), +}; + +static const struct kszphy_type ksz9021_type = { + .interrupt_level_mask = BIT(14), +}; static int kszphy_extended_write(struct phy_device *phydev, u32 regnum, u16 val) @@ -108,112 +137,137 @@ static int kszphy_ack_interrupt(struct phy_device *phydev) return (rc < 0) ? rc : 0; } -static int kszphy_set_interrupt(struct phy_device *phydev) +static int kszphy_config_intr(struct phy_device *phydev) { + const struct kszphy_type *type = phydev->drv->driver_data; int temp; - temp = (PHY_INTERRUPT_ENABLED == phydev->interrupts) ? - KSZPHY_INTCS_ALL : 0; - return phy_write(phydev, MII_KSZPHY_INTCS, temp); -} + u16 mask; -static int kszphy_config_intr(struct phy_device *phydev) -{ - int temp, rc; + if (type && type->interrupt_level_mask) + mask = type->interrupt_level_mask; + else + mask = KSZPHY_CTRL_INT_ACTIVE_HIGH; /* set the interrupt pin active low */ temp = phy_read(phydev, MII_KSZPHY_CTRL); - temp &= ~KSZPHY_CTRL_INT_ACTIVE_HIGH; + if (temp < 0) + return temp; + temp &= ~mask; phy_write(phydev, MII_KSZPHY_CTRL, temp); - rc = kszphy_set_interrupt(phydev); - return rc < 0 ? rc : 0; -} -static int ksz9021_config_intr(struct phy_device *phydev) -{ - int temp, rc; + /* enable / disable interrupts */ + if (phydev->interrupts == PHY_INTERRUPT_ENABLED) + temp = KSZPHY_INTCS_ALL; + else + temp = 0; - /* set the interrupt pin active low */ - temp = phy_read(phydev, MII_KSZPHY_CTRL); - temp &= ~KSZ9021_CTRL_INT_ACTIVE_HIGH; - phy_write(phydev, MII_KSZPHY_CTRL, temp); - rc = kszphy_set_interrupt(phydev); - return rc < 0 ? rc : 0; + return phy_write(phydev, MII_KSZPHY_INTCS, temp); } -static int ks8737_config_intr(struct phy_device *phydev) +static int kszphy_rmii_clk_sel(struct phy_device *phydev, bool val) { - int temp, rc; + int ctrl; - /* set the interrupt pin active low */ - temp = phy_read(phydev, MII_KSZPHY_CTRL); - temp &= ~KS8737_CTRL_INT_ACTIVE_HIGH; - phy_write(phydev, MII_KSZPHY_CTRL, temp); - rc = kszphy_set_interrupt(phydev); - return rc < 0 ? rc : 0; -} - -static int kszphy_setup_led(struct phy_device *phydev, - unsigned int reg, unsigned int shift) -{ + ctrl = phy_read(phydev, MII_KSZPHY_CTRL); + if (ctrl < 0) + return ctrl; - struct device *dev = &phydev->dev; - struct device_node *of_node = dev->of_node; - int rc, temp; - u32 val; + if (val) + ctrl |= KSZPHY_RMII_REF_CLK_SEL; + else + ctrl &= ~KSZPHY_RMII_REF_CLK_SEL; - if (!of_node && dev->parent->of_node) - of_node = dev->parent->of_node; + return phy_write(phydev, MII_KSZPHY_CTRL, ctrl); +} - if (of_property_read_u32(of_node, "micrel,led-mode", &val)) - return 0; +static int kszphy_setup_led(struct phy_device *phydev, u32 reg, int val) +{ + int rc, temp, shift; + + switch (reg) { + case MII_KSZPHY_CTRL_1: + shift = 14; + break; + case MII_KSZPHY_CTRL_2: + shift = 4; + break; + default: + return -EINVAL; + } temp = phy_read(phydev, reg); - if (temp < 0) - return temp; + if (temp < 0) { + rc = temp; + goto out; + } temp &= ~(3 << shift); temp |= val << shift; rc = phy_write(phydev, reg, temp); +out: + if (rc < 0) + dev_err(&phydev->dev, "failed to set led mode\n"); - return rc < 0 ? rc : 0; + return rc; } -static int kszphy_config_init(struct phy_device *phydev) +/* Disable PHY address 0 as the broadcast address, so that it can be used as a + * unique (non-broadcast) address on a shared bus. + */ +static int kszphy_broadcast_disable(struct phy_device *phydev) { - return 0; -} + int ret; -static int kszphy_config_init_led8041(struct phy_device *phydev) -{ - /* single led control, register 0x1e bits 15..14 */ - return kszphy_setup_led(phydev, 0x1e, 14); + ret = phy_read(phydev, MII_KSZPHY_OMSO); + if (ret < 0) + goto out; + + ret = phy_write(phydev, MII_KSZPHY_OMSO, ret | KSZPHY_OMSO_B_CAST_OFF); +out: + if (ret) + dev_err(&phydev->dev, "failed to disable broadcast address\n"); + + return ret; } -static int ksz8021_config_init(struct phy_device *phydev) +static int kszphy_config_init(struct phy_device *phydev) { - const u16 val = KSZPHY_OMSO_B_CAST_OFF | KSZPHY_OMSO_RMII_OVERRIDE; - int rc; + struct kszphy_priv *priv = phydev->priv; + const struct kszphy_type *type; + int ret; - rc = kszphy_setup_led(phydev, 0x1f, 4); - if (rc) - dev_err(&phydev->dev, "failed to set led mode\n"); + if (!priv) + return 0; - rc = ksz_config_flags(phydev); - if (rc < 0) - return rc; - rc = phy_write(phydev, MII_KSZPHY_OMSO, val); - return rc < 0 ? rc : 0; + type = priv->type; + + if (type->has_broadcast_disable) + kszphy_broadcast_disable(phydev); + + if (priv->rmii_ref_clk_sel) { + ret = kszphy_rmii_clk_sel(phydev, priv->rmii_ref_clk_sel_val); + if (ret) { + dev_err(&phydev->dev, "failed to set rmii reference clock\n"); + return ret; + } + } + + if (priv->led_mode >= 0) + kszphy_setup_led(phydev, type->led_mode_reg, priv->led_mode); + + return 0; } -static int ks8051_config_init(struct phy_device *phydev) +static int ksz8021_config_init(struct phy_device *phydev) { int rc; - rc = kszphy_setup_led(phydev, 0x1f, 4); + rc = kszphy_config_init(phydev); if (rc) - dev_err(&phydev->dev, "failed to set led mode\n"); + return rc; + + rc = kszphy_broadcast_disable(phydev); - rc = ksz_config_flags(phydev); return rc < 0 ? rc : 0; } @@ -394,8 +448,8 @@ static int ksz9031_config_init(struct phy_device *phydev) } #define KSZ8873MLL_GLOBAL_CONTROL_4 0x06 -#define KSZ8873MLL_GLOBAL_CONTROL_4_DUPLEX (1 << 6) -#define KSZ8873MLL_GLOBAL_CONTROL_4_SPEED (1 << 4) +#define KSZ8873MLL_GLOBAL_CONTROL_4_DUPLEX BIT(6) +#define KSZ8873MLL_GLOBAL_CONTROL_4_SPEED BIT(4) static int ksz8873mll_read_status(struct phy_device *phydev) { int regval; @@ -446,24 +500,62 @@ ksz9021_wr_mmd_phyreg(struct phy_device *phydev, int ptrad, int devnum, { } -static int ksz8021_probe(struct phy_device *phydev) +static int kszphy_probe(struct phy_device *phydev) { + const struct kszphy_type *type = phydev->drv->driver_data; + struct device_node *np = phydev->dev.of_node; + struct kszphy_priv *priv; struct clk *clk; + int ret; + + priv = devm_kzalloc(&phydev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + phydev->priv = priv; + + priv->type = type; + + if (type->led_mode_reg) { + ret = of_property_read_u32(np, "micrel,led-mode", + &priv->led_mode); + if (ret) + priv->led_mode = -1; + + if (priv->led_mode > 3) { + dev_err(&phydev->dev, "invalid led mode: 0x%02x\n", + priv->led_mode); + priv->led_mode = -1; + } + } else { + priv->led_mode = -1; + } clk = devm_clk_get(&phydev->dev, "rmii-ref"); if (!IS_ERR(clk)) { unsigned long rate = clk_get_rate(clk); + bool rmii_ref_clk_sel_25_mhz; + + priv->rmii_ref_clk_sel = type->has_rmii_ref_clk_sel; + rmii_ref_clk_sel_25_mhz = of_property_read_bool(np, + "micrel,rmii-reference-clock-select-25-mhz"); if (rate > 24500000 && rate < 25500000) { - phydev->dev_flags |= MICREL_PHY_25MHZ_CLK; + priv->rmii_ref_clk_sel_val = rmii_ref_clk_sel_25_mhz; } else if (rate > 49500000 && rate < 50500000) { - phydev->dev_flags |= MICREL_PHY_50MHZ_CLK; + priv->rmii_ref_clk_sel_val = !rmii_ref_clk_sel_25_mhz; } else { dev_err(&phydev->dev, "Clock rate out of range: %ld\n", rate); return -EINVAL; } } + /* Support legacy board-file configuration */ + if (phydev->dev_flags & MICREL_PHY_50MHZ_CLK) { + priv->rmii_ref_clk_sel = true; + priv->rmii_ref_clk_sel_val = true; + } + return 0; } @@ -474,11 +566,12 @@ static struct phy_driver ksphy_driver[] = { .name = "Micrel KS8737", .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause), .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, + .driver_data = &ks8737_type, .config_init = kszphy_config_init, .config_aneg = genphy_config_aneg, .read_status = genphy_read_status, .ack_interrupt = kszphy_ack_interrupt, - .config_intr = ks8737_config_intr, + .config_intr = kszphy_config_intr, .suspend = genphy_suspend, .resume = genphy_resume, .driver = { .owner = THIS_MODULE,}, @@ -489,7 +582,8 @@ static struct phy_driver ksphy_driver[] = { .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause | SUPPORTED_Asym_Pause), .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, - .probe = ksz8021_probe, + .driver_data = &ksz8021_type, + .probe = kszphy_probe, .config_init = ksz8021_config_init, .config_aneg = genphy_config_aneg, .read_status = genphy_read_status, @@ -505,7 +599,8 @@ static struct phy_driver ksphy_driver[] = { .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause | SUPPORTED_Asym_Pause), .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, - .probe = ksz8021_probe, + .driver_data = &ksz8021_type, + .probe = kszphy_probe, .config_init = ksz8021_config_init, .config_aneg = genphy_config_aneg, .read_status = genphy_read_status, @@ -521,7 +616,9 @@ static struct phy_driver ksphy_driver[] = { .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause | SUPPORTED_Asym_Pause), .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, - .config_init = kszphy_config_init_led8041, + .driver_data = &ksz8041_type, + .probe = kszphy_probe, + .config_init = kszphy_config_init, .config_aneg = genphy_config_aneg, .read_status = genphy_read_status, .ack_interrupt = kszphy_ack_interrupt, @@ -536,7 +633,9 @@ static struct phy_driver ksphy_driver[] = { .features = PHY_BASIC_FEATURES | SUPPORTED_Pause | SUPPORTED_Asym_Pause, .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, - .config_init = kszphy_config_init_led8041, + .driver_data = &ksz8041_type, + .probe = kszphy_probe, + .config_init = kszphy_config_init, .config_aneg = genphy_config_aneg, .read_status = genphy_read_status, .ack_interrupt = kszphy_ack_interrupt, @@ -551,7 +650,9 @@ static struct phy_driver ksphy_driver[] = { .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause | SUPPORTED_Asym_Pause), .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, - .config_init = ks8051_config_init, + .driver_data = &ksz8051_type, + .probe = kszphy_probe, + .config_init = kszphy_config_init, .config_aneg = genphy_config_aneg, .read_status = genphy_read_status, .ack_interrupt = kszphy_ack_interrupt, @@ -565,7 +666,9 @@ static struct phy_driver ksphy_driver[] = { .phy_id_mask = 0x00ffffff, .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause), .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, - .config_init = kszphy_config_init_led8041, + .driver_data = &ksz8041_type, + .probe = kszphy_probe, + .config_init = kszphy_config_init, .config_aneg = genphy_config_aneg, .read_status = genphy_read_status, .ack_interrupt = kszphy_ack_interrupt, @@ -579,6 +682,8 @@ static struct phy_driver ksphy_driver[] = { .phy_id_mask = 0x00fffff0, .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause), .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, + .driver_data = &ksz8081_type, + .probe = kszphy_probe, .config_init = kszphy_config_init, .config_aneg = genphy_config_aneg, .read_status = genphy_read_status, @@ -607,11 +712,12 @@ static struct phy_driver ksphy_driver[] = { .name = "Micrel KSZ9021 Gigabit PHY", .features = (PHY_GBIT_FEATURES | SUPPORTED_Pause), .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, + .driver_data = &ksz9021_type, .config_init = ksz9021_config_init, .config_aneg = genphy_config_aneg, .read_status = genphy_read_status, .ack_interrupt = kszphy_ack_interrupt, - .config_intr = ksz9021_config_intr, + .config_intr = kszphy_config_intr, .suspend = genphy_suspend, .resume = genphy_resume, .read_mmd_indirect = ksz9021_rd_mmd_phyreg, @@ -623,11 +729,12 @@ static struct phy_driver ksphy_driver[] = { .name = "Micrel KSZ9031 Gigabit PHY", .features = (PHY_GBIT_FEATURES | SUPPORTED_Pause), .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, + .driver_data = &ksz9021_type, .config_init = ksz9031_config_init, .config_aneg = genphy_config_aneg, .read_status = genphy_read_status, .ack_interrupt = kszphy_ack_interrupt, - .config_intr = ksz9021_config_intr, + .config_intr = kszphy_config_intr, .suspend = genphy_suspend, .resume = genphy_resume, .driver = { .owner = THIS_MODULE, }, @@ -657,20 +764,7 @@ static struct phy_driver ksphy_driver[] = { .driver = { .owner = THIS_MODULE, }, } }; -static int __init ksphy_init(void) -{ - return phy_drivers_register(ksphy_driver, - ARRAY_SIZE(ksphy_driver)); -} - -static void __exit ksphy_exit(void) -{ - phy_drivers_unregister(ksphy_driver, - ARRAY_SIZE(ksphy_driver)); -} - -module_init(ksphy_init); -module_exit(ksphy_exit); +module_phy_driver(ksphy_driver); MODULE_DESCRIPTION("Micrel PHY driver"); MODULE_AUTHOR("David J. Choi"); diff --git a/drivers/net/phy/national.c b/drivers/net/phy/national.c index 9a5f234d95b0..0a7b9c7f09a2 100644 --- a/drivers/net/phy/national.c +++ b/drivers/net/phy/national.c @@ -129,7 +129,7 @@ static int ns_config_init(struct phy_device *phydev) return ns_ack_interrupt(phydev); } -static struct phy_driver dp83865_driver = { +static struct phy_driver dp83865_driver[] = { { .phy_id = DP83865_PHY_ID, .phy_id_mask = 0xfffffff0, .name = "NatSemi DP83865", @@ -141,25 +141,14 @@ static struct phy_driver dp83865_driver = { .ack_interrupt = ns_ack_interrupt, .config_intr = ns_config_intr, .driver = {.owner = THIS_MODULE,} -}; +} }; -static int __init ns_init(void) -{ - return phy_driver_register(&dp83865_driver); -} - -static void __exit ns_exit(void) -{ - phy_driver_unregister(&dp83865_driver); -} +module_phy_driver(dp83865_driver); MODULE_DESCRIPTION("NatSemi PHY driver"); MODULE_AUTHOR("Stuart Menefy"); MODULE_LICENSE("GPL"); -module_init(ns_init); -module_exit(ns_exit); - static struct mdio_device_id __maybe_unused ns_tbl[] = { { DP83865_PHY_ID, 0xfffffff0 }, { } diff --git a/drivers/net/phy/qsemi.c b/drivers/net/phy/qsemi.c index fe0d0a15d5e1..be4c6f7c3645 100644 --- a/drivers/net/phy/qsemi.c +++ b/drivers/net/phy/qsemi.c @@ -111,7 +111,7 @@ static int qs6612_config_intr(struct phy_device *phydev) } -static struct phy_driver qs6612_driver = { +static struct phy_driver qs6612_driver[] = { { .phy_id = 0x00181440, .name = "QS6612", .phy_id_mask = 0xfffffff0, @@ -123,20 +123,9 @@ static struct phy_driver qs6612_driver = { .ack_interrupt = qs6612_ack_interrupt, .config_intr = qs6612_config_intr, .driver = { .owner = THIS_MODULE,}, -}; - -static int __init qs6612_init(void) -{ - return phy_driver_register(&qs6612_driver); -} - -static void __exit qs6612_exit(void) -{ - phy_driver_unregister(&qs6612_driver); -} +} }; -module_init(qs6612_init); -module_exit(qs6612_exit); +module_phy_driver(qs6612_driver); static struct mdio_device_id __maybe_unused qs6612_tbl[] = { { 0x00181440, 0xfffffff0 }, diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c index 45483fdfbe06..96a0f0fab3ca 100644 --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c @@ -101,18 +101,7 @@ static struct phy_driver realtek_drvs[] = { }, }; -static int __init realtek_init(void) -{ - return phy_drivers_register(realtek_drvs, ARRAY_SIZE(realtek_drvs)); -} - -static void __exit realtek_exit(void) -{ - phy_drivers_unregister(realtek_drvs, ARRAY_SIZE(realtek_drvs)); -} - -module_init(realtek_init); -module_exit(realtek_exit); +module_phy_driver(realtek_drvs); static struct mdio_device_id __maybe_unused realtek_tbl[] = { { 0x001cc912, 0x001fffff }, diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c index a4b08198fb9f..c0f6479e19d4 100644 --- a/drivers/net/phy/smsc.c +++ b/drivers/net/phy/smsc.c @@ -250,24 +250,12 @@ static struct phy_driver smsc_phy_driver[] = { .driver = { .owner = THIS_MODULE, } } }; -static int __init smsc_init(void) -{ - return phy_drivers_register(smsc_phy_driver, - ARRAY_SIZE(smsc_phy_driver)); -} - -static void __exit smsc_exit(void) -{ - phy_drivers_unregister(smsc_phy_driver, ARRAY_SIZE(smsc_phy_driver)); -} +module_phy_driver(smsc_phy_driver); MODULE_DESCRIPTION("SMSC PHY driver"); MODULE_AUTHOR("Herbert Valerio Riedel"); MODULE_LICENSE("GPL"); -module_init(smsc_init); -module_exit(smsc_exit); - static struct mdio_device_id __maybe_unused smsc_tbl[] = { { 0x0007c0a0, 0xfffffff0 }, { 0x0007c0b0, 0xfffffff0 }, diff --git a/drivers/net/phy/spi_ks8995.c b/drivers/net/phy/spi_ks8995.c index eab57fc5b967..46530159256b 100644 --- a/drivers/net/phy/spi_ks8995.c +++ b/drivers/net/phy/spi_ks8995.c @@ -353,7 +353,9 @@ static int ks8995_probe(struct spi_device *spi) static int ks8995_remove(struct spi_device *spi) { - sysfs_remove_bin_file(&spi->dev.kobj, &ks8995_registers_attr); + struct ks8995_switch *ks = spi_get_drvdata(spi); + + sysfs_remove_bin_file(&spi->dev.kobj, &ks->regs_attr); return 0; } diff --git a/drivers/net/phy/ste10Xp.c b/drivers/net/phy/ste10Xp.c index 5e1eb138916f..3fc199b773e6 100644 --- a/drivers/net/phy/ste10Xp.c +++ b/drivers/net/phy/ste10Xp.c @@ -112,20 +112,7 @@ static struct phy_driver ste10xp_pdriver[] = { .driver = {.owner = THIS_MODULE,} } }; -static int __init ste10Xp_init(void) -{ - return phy_drivers_register(ste10xp_pdriver, - ARRAY_SIZE(ste10xp_pdriver)); -} - -static void __exit ste10Xp_exit(void) -{ - phy_drivers_unregister(ste10xp_pdriver, - ARRAY_SIZE(ste10xp_pdriver)); -} - -module_init(ste10Xp_init); -module_exit(ste10Xp_exit); +module_phy_driver(ste10xp_pdriver); static struct mdio_device_id __maybe_unused ste10Xp_tbl[] = { { STE101P_PHY_ID, 0xfffffff0 }, diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c index 5dc0935da99c..76cad712ddb2 100644 --- a/drivers/net/phy/vitesse.c +++ b/drivers/net/phy/vitesse.c @@ -311,19 +311,7 @@ static struct phy_driver vsc82xx_driver[] = { .driver = { .owner = THIS_MODULE,}, } }; -static int __init vsc82xx_init(void) -{ - return phy_drivers_register(vsc82xx_driver, - ARRAY_SIZE(vsc82xx_driver)); -} - -static void __exit vsc82xx_exit(void) -{ - phy_drivers_unregister(vsc82xx_driver, ARRAY_SIZE(vsc82xx_driver)); -} - -module_init(vsc82xx_init); -module_exit(vsc82xx_exit); +module_phy_driver(vsc82xx_driver); static struct mdio_device_id __maybe_unused vitesse_tbl[] = { { PHY_ID_VSC8234, 0x000ffff0 }, diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c index 6c9c16d76935..d2408a5e43a6 100644 --- a/drivers/net/ppp/pppoe.c +++ b/drivers/net/ppp/pppoe.c @@ -869,7 +869,7 @@ static int pppoe_sendmsg(struct kiocb *iocb, struct socket *sock, ph = (struct pppoe_hdr *)skb_put(skb, total_len + sizeof(struct pppoe_hdr)); start = (char *)&ph->tag[0]; - error = memcpy_fromiovec(start, m->msg_iov, total_len); + error = memcpy_from_msg(start, m, total_len); if (error < 0) { kfree_skb(skb); goto end; @@ -981,7 +981,7 @@ static int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock, if (skb) { total_len = min_t(size_t, total_len, skb->len); - error = skb_copy_datagram_iovec(skb, 0, m->msg_iov, total_len); + error = skb_copy_datagram_msg(skb, 0, m, total_len); if (error == 0) { consume_skb(skb); return total_len; diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 2368395d8ae5..93e224217e24 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -1179,6 +1179,9 @@ static int team_port_add(struct team *team, struct net_device *port_dev) goto err_enable_netpoll; } + if (!(dev->features & NETIF_F_LRO)) + dev_disable_lro(port_dev); + err = netdev_rx_handler_register(port_dev, team_handle_frame, port); if (err) { diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 9dd3746994a4..4b743c612624 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -71,6 +71,7 @@ #include <net/rtnetlink.h> #include <net/sock.h> #include <linux/seq_file.h> +#include <linux/uio.h> #include <asm/uaccess.h> @@ -818,7 +819,7 @@ drop: skb_tx_error(skb); kfree_skb(skb); rcu_read_unlock(); - return NETDEV_TX_OK; + return NET_XMIT_DROP; } static void tun_net_mclist(struct net_device *dev) @@ -1011,28 +1012,29 @@ static struct sk_buff *tun_alloc_skb(struct tun_file *tfile, /* Get packet from user space buffer */ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, - void *msg_control, const struct iovec *iv, - size_t total_len, size_t count, int noblock) + void *msg_control, struct iov_iter *from, + int noblock) { struct tun_pi pi = { 0, cpu_to_be16(ETH_P_IP) }; struct sk_buff *skb; + size_t total_len = iov_iter_count(from); size_t len = total_len, align = NET_SKB_PAD, linear; struct virtio_net_hdr gso = { 0 }; int good_linear; - int offset = 0; int copylen; bool zerocopy = false; int err; u32 rxhash; + ssize_t n; if (!(tun->flags & TUN_NO_PI)) { if (len < sizeof(pi)) return -EINVAL; len -= sizeof(pi); - if (memcpy_fromiovecend((void *)&pi, iv, 0, sizeof(pi))) + n = copy_from_iter(&pi, sizeof(pi), from); + if (n != sizeof(pi)) return -EFAULT; - offset += sizeof(pi); } if (tun->flags & TUN_VNET_HDR) { @@ -1040,7 +1042,8 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, return -EINVAL; len -= tun->vnet_hdr_sz; - if (memcpy_fromiovecend((void *)&gso, iv, offset, sizeof(gso))) + n = copy_from_iter(&gso, sizeof(gso), from); + if (n != sizeof(gso)) return -EFAULT; if ((gso.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && @@ -1049,7 +1052,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, if (gso.hdr_len > len) return -EINVAL; - offset += tun->vnet_hdr_sz; + iov_iter_advance(from, tun->vnet_hdr_sz); } if ((tun->flags & TUN_TYPE_MASK) == TUN_TAP_DEV) { @@ -1062,6 +1065,8 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, good_linear = SKB_MAX_HEAD(align); if (msg_control) { + struct iov_iter i = *from; + /* There are 256 bytes to be copied in skb, so there is * enough room for skb expand head in case it is used. * The rest of the buffer is mapped from userspace. @@ -1070,7 +1075,8 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, if (copylen > good_linear) copylen = good_linear; linear = copylen; - if (iov_pages(iv, offset + copylen, count) <= MAX_SKB_FRAGS) + iov_iter_advance(&i, copylen); + if (iov_iter_npages(&i, INT_MAX) <= MAX_SKB_FRAGS) zerocopy = true; } @@ -1090,9 +1096,9 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, } if (zerocopy) - err = zerocopy_sg_from_iovec(skb, iv, offset, count); + err = zerocopy_sg_from_iter(skb, from); else { - err = skb_copy_datagram_from_iovec(skb, 0, iv, offset, len); + err = skb_copy_datagram_from_iter(skb, 0, from, len); if (!err && msg_control) { struct ubuf_info *uarg = msg_control; uarg->callback(uarg, false); @@ -1206,8 +1212,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, return total_len; } -static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv, - unsigned long count, loff_t pos) +static ssize_t tun_chr_write_iter(struct kiocb *iocb, struct iov_iter *from) { struct file *file = iocb->ki_filp; struct tun_struct *tun = tun_get(file); @@ -1217,10 +1222,7 @@ static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv, if (!tun) return -EBADFD; - tun_debug(KERN_INFO, tun, "tun_chr_write %ld\n", count); - - result = tun_get_user(tun, tfile, NULL, iv, iov_length(iv, count), - count, file->f_flags & O_NONBLOCK); + result = tun_get_user(tun, tfile, NULL, from, file->f_flags & O_NONBLOCK); tun_put(tun); return result; @@ -1230,11 +1232,11 @@ static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv, static ssize_t tun_put_user(struct tun_struct *tun, struct tun_file *tfile, struct sk_buff *skb, - const struct iovec *iv, int len) + struct iov_iter *iter) { struct tun_pi pi = { 0, skb->protocol }; - ssize_t total = 0; - int vlan_offset = 0, copied; + ssize_t total; + int vlan_offset = 0; int vlan_hlen = 0; int vnet_hdr_sz = 0; @@ -1244,23 +1246,25 @@ static ssize_t tun_put_user(struct tun_struct *tun, if (tun->flags & TUN_VNET_HDR) vnet_hdr_sz = tun->vnet_hdr_sz; + total = skb->len + vlan_hlen + vnet_hdr_sz; + if (!(tun->flags & TUN_NO_PI)) { - if ((len -= sizeof(pi)) < 0) + if (iov_iter_count(iter) < sizeof(pi)) return -EINVAL; - if (len < skb->len + vlan_hlen + vnet_hdr_sz) { + total += sizeof(pi); + if (iov_iter_count(iter) < total) { /* Packet will be striped */ pi.flags |= TUN_PKT_STRIP; } - if (memcpy_toiovecend(iv, (void *) &pi, 0, sizeof(pi))) + if (copy_to_iter(&pi, sizeof(pi), iter) != sizeof(pi)) return -EFAULT; - total += sizeof(pi); } if (vnet_hdr_sz) { struct virtio_net_hdr gso = { 0 }; /* no info leak */ - if ((len -= vnet_hdr_sz) < 0) + if (iov_iter_count(iter) < vnet_hdr_sz) return -EINVAL; if (skb_is_gso(skb)) { @@ -1299,17 +1303,14 @@ static ssize_t tun_put_user(struct tun_struct *tun, gso.flags = VIRTIO_NET_HDR_F_DATA_VALID; } /* else everything is zero */ - if (unlikely(memcpy_toiovecend(iv, (void *)&gso, total, - sizeof(gso)))) + if (copy_to_iter(&gso, sizeof(gso), iter) != sizeof(gso)) return -EFAULT; - total += vnet_hdr_sz; + + iov_iter_advance(iter, vnet_hdr_sz - sizeof(gso)); } - copied = total; - len = min_t(int, skb->len + vlan_hlen, len); - total += skb->len + vlan_hlen; if (vlan_hlen) { - int copy, ret; + int ret; struct { __be16 h_vlan_proto; __be16 h_vlan_TCI; @@ -1320,41 +1321,36 @@ static ssize_t tun_put_user(struct tun_struct *tun, vlan_offset = offsetof(struct vlan_ethhdr, h_vlan_proto); - copy = min_t(int, vlan_offset, len); - ret = skb_copy_datagram_const_iovec(skb, 0, iv, copied, copy); - len -= copy; - copied += copy; - if (ret || !len) + ret = skb_copy_datagram_iter(skb, 0, iter, vlan_offset); + if (ret || !iov_iter_count(iter)) goto done; - copy = min_t(int, sizeof(veth), len); - ret = memcpy_toiovecend(iv, (void *)&veth, copied, copy); - len -= copy; - copied += copy; - if (ret || !len) + ret = copy_to_iter(&veth, sizeof(veth), iter); + if (ret != sizeof(veth) || !iov_iter_count(iter)) goto done; } - skb_copy_datagram_const_iovec(skb, vlan_offset, iv, copied, len); + skb_copy_datagram_iter(skb, vlan_offset, iter, skb->len - vlan_offset); done: tun->dev->stats.tx_packets++; - tun->dev->stats.tx_bytes += len; + tun->dev->stats.tx_bytes += skb->len + vlan_hlen; return total; } static ssize_t tun_do_read(struct tun_struct *tun, struct tun_file *tfile, - const struct iovec *iv, ssize_t len, int noblock) + struct iov_iter *to, + int noblock) { struct sk_buff *skb; - ssize_t ret = 0; + ssize_t ret; int peeked, err, off = 0; tun_debug(KERN_INFO, tun, "tun_do_read\n"); - if (!len) - return ret; + if (!iov_iter_count(to)) + return 0; if (tun->dev->reg_state != NETREG_REGISTERED) return -EIO; @@ -1362,37 +1358,28 @@ static ssize_t tun_do_read(struct tun_struct *tun, struct tun_file *tfile, /* Read frames from queue */ skb = __skb_recv_datagram(tfile->socket.sk, noblock ? MSG_DONTWAIT : 0, &peeked, &off, &err); - if (skb) { - ret = tun_put_user(tun, tfile, skb, iv, len); - kfree_skb(skb); - } else - ret = err; + if (!skb) + return 0; + + ret = tun_put_user(tun, tfile, skb, to); + kfree_skb(skb); return ret; } -static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv, - unsigned long count, loff_t pos) +static ssize_t tun_chr_read_iter(struct kiocb *iocb, struct iov_iter *to) { struct file *file = iocb->ki_filp; struct tun_file *tfile = file->private_data; struct tun_struct *tun = __tun_get(tfile); - ssize_t len, ret; + ssize_t len = iov_iter_count(to), ret; if (!tun) return -EBADFD; - len = iov_length(iv, count); - if (len < 0) { - ret = -EINVAL; - goto out; - } - - ret = tun_do_read(tun, tfile, iv, len, - file->f_flags & O_NONBLOCK); + ret = tun_do_read(tun, tfile, to, file->f_flags & O_NONBLOCK); ret = min_t(ssize_t, ret, len); if (ret > 0) iocb->ki_pos = ret; -out: tun_put(tun); return ret; } @@ -1459,11 +1446,14 @@ static int tun_sendmsg(struct kiocb *iocb, struct socket *sock, int ret; struct tun_file *tfile = container_of(sock, struct tun_file, socket); struct tun_struct *tun = __tun_get(tfile); + struct iov_iter from; if (!tun) return -EBADFD; - ret = tun_get_user(tun, tfile, m->msg_control, m->msg_iov, total_len, - m->msg_iovlen, m->msg_flags & MSG_DONTWAIT); + + iov_iter_init(&from, WRITE, m->msg_iov, m->msg_iovlen, total_len); + ret = tun_get_user(tun, tfile, m->msg_control, &from, + m->msg_flags & MSG_DONTWAIT); tun_put(tun); return ret; } @@ -1474,6 +1464,7 @@ static int tun_recvmsg(struct kiocb *iocb, struct socket *sock, { struct tun_file *tfile = container_of(sock, struct tun_file, socket); struct tun_struct *tun = __tun_get(tfile); + struct iov_iter to; int ret; if (!tun) @@ -1488,8 +1479,8 @@ static int tun_recvmsg(struct kiocb *iocb, struct socket *sock, SOL_PACKET, TUN_TX_TIMESTAMP); goto out; } - ret = tun_do_read(tun, tfile, m->msg_iov, total_len, - flags & MSG_DONTWAIT); + iov_iter_init(&to, READ, m->msg_iov, m->msg_iovlen, total_len); + ret = tun_do_read(tun, tfile, &to, flags & MSG_DONTWAIT); if (ret > total_len) { m->msg_flags |= MSG_TRUNC; ret = flags & MSG_TRUNC ? ret : total_len; @@ -2245,10 +2236,10 @@ static int tun_chr_show_fdinfo(struct seq_file *m, struct file *f) static const struct file_operations tun_fops = { .owner = THIS_MODULE, .llseek = no_llseek, - .read = do_sync_read, - .aio_read = tun_chr_aio_read, - .write = do_sync_write, - .aio_write = tun_chr_aio_write, + .read = new_sync_read, + .write = new_sync_write, + .read_iter = tun_chr_read_iter, + .write_iter = tun_chr_write_iter, .poll = tun_chr_poll, .unlocked_ioctl = tun_chr_ioctl, #ifdef CONFIG_COMPAT diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c index 816d511e34d3..bf49792062a2 100644 --- a/drivers/net/usb/asix_devices.c +++ b/drivers/net/usb/asix_devices.c @@ -487,8 +487,7 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) static void ax88772_unbind(struct usbnet *dev, struct usb_interface *intf) { - if (dev->driver_priv) - kfree(dev->driver_priv); + kfree(dev->driver_priv); } static const struct ethtool_ops ax88178_ethtool_ops = { diff --git a/drivers/net/usb/cdc-phonet.c b/drivers/net/usb/cdc-phonet.c index 2ec1500d0077..415ce8b882c6 100644 --- a/drivers/net/usb/cdc-phonet.c +++ b/drivers/net/usb/cdc-phonet.c @@ -130,7 +130,7 @@ static int rx_submit(struct usbpn_dev *pnd, struct urb *req, gfp_t gfp_flags) struct page *page; int err; - page = __skb_alloc_page(gfp_flags | __GFP_NOMEMALLOC, NULL); + page = __dev_alloc_page(gfp_flags | __GFP_NOMEMALLOC); if (!page) return -ENOMEM; @@ -212,7 +212,7 @@ resubmit: if (page) put_page(page); if (req) - rx_submit(pnd, req, GFP_ATOMIC | __GFP_COLD); + rx_submit(pnd, req, GFP_ATOMIC); } static int usbpn_close(struct net_device *dev); @@ -231,7 +231,7 @@ static int usbpn_open(struct net_device *dev) for (i = 0; i < rxq_size; i++) { struct urb *req = usb_alloc_urb(0, GFP_KERNEL); - if (!req || rx_submit(pnd, req, GFP_KERNEL | __GFP_COLD)) { + if (!req || rx_submit(pnd, req, GFP_KERNEL)) { usb_free_urb(req); usbpn_close(dev); return -ENOMEM; diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index d3920b54a92c..9311a08565be 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -71,18 +71,19 @@ static void usbnet_cdc_update_filter(struct usbnet *dev) { struct cdc_state *info = (void *) &dev->data; struct usb_interface *intf = info->control; + struct net_device *net = dev->net; - u16 cdc_filter = - USB_CDC_PACKET_TYPE_ALL_MULTICAST | USB_CDC_PACKET_TYPE_DIRECTED | - USB_CDC_PACKET_TYPE_BROADCAST; + u16 cdc_filter = USB_CDC_PACKET_TYPE_DIRECTED + | USB_CDC_PACKET_TYPE_BROADCAST; - if (dev->net->flags & IFF_PROMISC) - cdc_filter |= USB_CDC_PACKET_TYPE_PROMISCUOUS; - - /* FIXME cdc-ether has some multicast code too, though it complains - * in routine cases. info->ether describes the multicast support. - * Implement that here, manipulating the cdc filter as needed. + /* filtering on the device is an optional feature and not worth + * the hassle so we just roughly care about snooping and if any + * multicast is requested, we take every multicast */ + if (net->flags & IFF_PROMISC) + cdc_filter |= USB_CDC_PACKET_TYPE_PROMISCUOUS; + if (!netdev_mc_empty(net) || (net->flags & IFF_ALLMULTI)) + cdc_filter |= USB_CDC_PACKET_TYPE_ALL_MULTICAST; usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c index 5ee7a1dbc023..96fc8a5bde84 100644 --- a/drivers/net/usb/cdc_mbim.c +++ b/drivers/net/usb/cdc_mbim.c @@ -402,7 +402,7 @@ static struct sk_buff *cdc_mbim_process_dgram(struct usbnet *dev, u8 *buf, size_ /* map MBIM session to VLAN */ if (tci) - vlan_put_tag(skb, htons(ETH_P_8021Q), tci); + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), tci); err: return skb; } diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index babda7d8693e..9c5aa922a9f4 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -2746,8 +2746,7 @@ exit: tty_unregister_device(tty_drv, serial->minor); kfree(serial); } - if (hso_dev) - kfree(hso_dev); + kfree(hso_dev); return NULL; } diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index c6554c7a8147..4a9ece01def6 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -461,11 +461,7 @@ enum rtl8152_flags { /* Define these values to match your device */ #define VENDOR_ID_REALTEK 0x0bda -#define PRODUCT_ID_RTL8152 0x8152 -#define PRODUCT_ID_RTL8153 0x8153 - #define VENDOR_ID_SAMSUNG 0x04e8 -#define PRODUCT_ID_SAMSUNG 0xa101 #define MCU_TYPE_PLA 0x0100 #define MCU_TYPE_USB 0x0000 @@ -486,7 +482,7 @@ struct tally_counter { __le64 rx_broadcast; __le32 rx_multicast; __le16 tx_aborted; - __le16 tx_underun; + __le16 tx_underrun; }; struct rx_desc { @@ -690,6 +686,9 @@ static int generic_ocp_read(struct r8152 *tp, u16 index, u16 size, } } + if (ret == -ENODEV) + set_bit(RTL8152_UNPLUG, &tp->flags); + return ret; } @@ -757,6 +756,9 @@ static int generic_ocp_write(struct r8152 *tp, u16 index, u16 byteen, } error1: + if (ret == -ENODEV) + set_bit(RTL8152_UNPLUG, &tp->flags); + return ret; } @@ -1030,7 +1032,6 @@ static void read_bulk_callback(struct urb *urb) int status = urb->status; struct rx_agg *agg; struct r8152 *tp; - int result; agg = urb->context; if (!agg) @@ -1081,15 +1082,7 @@ static void read_bulk_callback(struct urb *urb) break; } - result = r8152_submit_rx(tp, agg, GFP_ATOMIC); - if (result == -ENODEV) { - netif_device_detach(tp->netdev); - } else if (result) { - spin_lock(&tp->rx_lock); - list_add_tail(&agg->list, &tp->rx_done); - spin_unlock(&tp->rx_lock); - tasklet_schedule(&tp->tl); - } + r8152_submit_rx(tp, agg, GFP_ATOMIC); } static void write_bulk_callback(struct urb *urb) @@ -1190,11 +1183,13 @@ static void intr_callback(struct urb *urb) resubmit: res = usb_submit_urb(urb, GFP_ATOMIC); - if (res == -ENODEV) + if (res == -ENODEV) { + set_bit(RTL8152_UNPLUG, &tp->flags); netif_device_detach(tp->netdev); - else if (res) + } else if (res) { netif_err(tp, intr, tp->netdev, "can't resubmit intr, status %d\n", res); + } } static inline void *rx_agg_align(void *data) @@ -1250,7 +1245,6 @@ static int alloc_all_mem(struct r8152 *tp) spin_lock_init(&tp->rx_lock); spin_lock_init(&tp->tx_lock); - INIT_LIST_HEAD(&tp->rx_done); INIT_LIST_HEAD(&tp->tx_free); skb_queue_head_init(&tp->tx_queue); @@ -1676,7 +1670,6 @@ static void rx_bottom(struct r8152 *tp) int len_used = 0; struct urb *urb; u8 *rx_data; - int ret; list_del_init(cursor); @@ -1729,13 +1722,7 @@ find_next_rx: } submit: - ret = r8152_submit_rx(tp, agg, GFP_ATOMIC); - if (ret && ret != -ENODEV) { - spin_lock_irqsave(&tp->rx_lock, flags); - list_add_tail(&agg->list, &tp->rx_done); - spin_unlock_irqrestore(&tp->rx_lock, flags); - tasklet_schedule(&tp->tl); - } + r8152_submit_rx(tp, agg, GFP_ATOMIC); } } @@ -1758,6 +1745,7 @@ static void tx_bottom(struct r8152 *tp) struct net_device *netdev = tp->netdev; if (res == -ENODEV) { + set_bit(RTL8152_UNPLUG, &tp->flags); netif_device_detach(netdev); } else { struct net_device_stats *stats = &netdev->stats; @@ -1792,6 +1780,8 @@ static void bottom_half(unsigned long data) if (!netif_carrier_ok(tp->netdev)) return; + clear_bit(SCHEDULE_TASKLET, &tp->flags); + rx_bottom(tp); tx_bottom(tp); } @@ -1799,11 +1789,28 @@ static void bottom_half(unsigned long data) static int r8152_submit_rx(struct r8152 *tp, struct rx_agg *agg, gfp_t mem_flags) { + int ret; + usb_fill_bulk_urb(agg->urb, tp->udev, usb_rcvbulkpipe(tp->udev, 1), agg->head, agg_buf_sz, (usb_complete_t)read_bulk_callback, agg); - return usb_submit_urb(agg->urb, mem_flags); + ret = usb_submit_urb(agg->urb, mem_flags); + if (ret == -ENODEV) { + set_bit(RTL8152_UNPLUG, &tp->flags); + netif_device_detach(tp->netdev); + } else if (ret) { + struct urb *urb = agg->urb; + unsigned long flags; + + urb->actual_length = 0; + spin_lock_irqsave(&tp->rx_lock, flags); + list_add_tail(&agg->list, &tp->rx_done); + spin_unlock_irqrestore(&tp->rx_lock, flags); + tasklet_schedule(&tp->tl); + } + + return ret; } static void rtl_drop_queued_tx(struct r8152 *tp) @@ -1994,6 +2001,25 @@ static int rtl_start_rx(struct r8152 *tp) break; } + if (ret && ++i < RTL8152_MAX_RX) { + struct list_head rx_queue; + unsigned long flags; + + INIT_LIST_HEAD(&rx_queue); + + do { + struct rx_agg *agg = &tp->rx_info[i++]; + struct urb *urb = agg->urb; + + urb->actual_length = 0; + list_add_tail(&agg->list, &rx_queue); + } while (i < RTL8152_MAX_RX); + + spin_lock_irqsave(&tp->rx_lock, flags); + list_splice_tail(&rx_queue, &tp->rx_done); + spin_unlock_irqrestore(&tp->rx_lock, flags); + } + return ret; } @@ -2850,15 +2876,18 @@ static void rtl_work_func_t(struct work_struct *work) { struct r8152 *tp = container_of(work, struct r8152, schedule.work); + /* If the device is unplugged or !netif_running(), the workqueue + * doesn't need to wake the device, and could return directly. + */ + if (test_bit(RTL8152_UNPLUG, &tp->flags) || !netif_running(tp->netdev)) + return; + if (usb_autopm_get_interface(tp->intf) < 0) return; if (!test_bit(WORK_ENABLE, &tp->flags)) goto out1; - if (test_bit(RTL8152_UNPLUG, &tp->flags)) - goto out1; - if (!mutex_trylock(&tp->control)) { schedule_delayed_work(&tp->schedule, 0); goto out1; @@ -2933,6 +2962,8 @@ static int rtl8152_open(struct net_device *netdev) netif_warn(tp, ifup, netdev, "intr_urb submit failed: %d\n", res); free_all_mem(tp); + } else { + tasklet_enable(&tp->tl); } mutex_unlock(&tp->control); @@ -2948,6 +2979,7 @@ static int rtl8152_close(struct net_device *netdev) struct r8152 *tp = netdev_priv(netdev); int res = 0; + tasklet_disable(&tp->tl); clear_bit(WORK_ENABLE, &tp->flags); usb_kill_urb(tp->intr_urb); cancel_delayed_work_sync(&tp->schedule); @@ -2965,9 +2997,7 @@ static int rtl8152_close(struct net_device *netdev) */ rtl_runtime_suspend_enable(tp, false); - tasklet_disable(&tp->tl); tp->rtl_ops.down(tp); - tasklet_enable(&tp->tl); mutex_unlock(&tp->control); @@ -3427,7 +3457,7 @@ static void rtl8152_get_ethtool_stats(struct net_device *dev, data[9] = le64_to_cpu(tally.rx_broadcast); data[10] = le32_to_cpu(tally.rx_multicast); data[11] = le16_to_cpu(tally.tx_aborted); - data[12] = le16_to_cpu(tally.tx_underun); + data[12] = le16_to_cpu(tally.tx_underrun); } static void rtl8152_get_strings(struct net_device *dev, u32 stringset, u8 *data) @@ -3565,11 +3595,33 @@ out: return ret; } +static int rtl8152_nway_reset(struct net_device *dev) +{ + struct r8152 *tp = netdev_priv(dev); + int ret; + + ret = usb_autopm_get_interface(tp->intf); + if (ret < 0) + goto out; + + mutex_lock(&tp->control); + + ret = mii_nway_restart(&tp->mii); + + mutex_unlock(&tp->control); + + usb_autopm_put_interface(tp->intf); + +out: + return ret; +} + static struct ethtool_ops ops = { .get_drvinfo = rtl8152_get_drvinfo, .get_settings = rtl8152_get_settings, .set_settings = rtl8152_set_settings, .get_link = ethtool_op_get_link, + .nway_reset = rtl8152_nway_reset, .get_msglevel = rtl8152_get_msglevel, .set_msglevel = rtl8152_set_msglevel, .get_wol = rtl8152_get_wol, @@ -3709,66 +3761,43 @@ static void rtl8153_unload(struct r8152 *tp) r8153_power_cut_en(tp, false); } -static int rtl_ops_init(struct r8152 *tp, const struct usb_device_id *id) +static int rtl_ops_init(struct r8152 *tp) { struct rtl_ops *ops = &tp->rtl_ops; - int ret = -ENODEV; - - switch (id->idVendor) { - case VENDOR_ID_REALTEK: - switch (id->idProduct) { - case PRODUCT_ID_RTL8152: - ops->init = r8152b_init; - ops->enable = rtl8152_enable; - ops->disable = rtl8152_disable; - ops->up = rtl8152_up; - ops->down = rtl8152_down; - ops->unload = rtl8152_unload; - ops->eee_get = r8152_get_eee; - ops->eee_set = r8152_set_eee; - ret = 0; - break; - case PRODUCT_ID_RTL8153: - ops->init = r8153_init; - ops->enable = rtl8153_enable; - ops->disable = rtl8153_disable; - ops->up = rtl8153_up; - ops->down = rtl8153_down; - ops->unload = rtl8153_unload; - ops->eee_get = r8153_get_eee; - ops->eee_set = r8153_set_eee; - ret = 0; - break; - default: - break; - } + int ret = 0; + + switch (tp->version) { + case RTL_VER_01: + case RTL_VER_02: + ops->init = r8152b_init; + ops->enable = rtl8152_enable; + ops->disable = rtl8152_disable; + ops->up = rtl8152_up; + ops->down = rtl8152_down; + ops->unload = rtl8152_unload; + ops->eee_get = r8152_get_eee; + ops->eee_set = r8152_set_eee; break; - case VENDOR_ID_SAMSUNG: - switch (id->idProduct) { - case PRODUCT_ID_SAMSUNG: - ops->init = r8153_init; - ops->enable = rtl8153_enable; - ops->disable = rtl8153_disable; - ops->up = rtl8153_up; - ops->down = rtl8153_down; - ops->unload = rtl8153_unload; - ops->eee_get = r8153_get_eee; - ops->eee_set = r8153_set_eee; - ret = 0; - break; - default: - break; - } + case RTL_VER_03: + case RTL_VER_04: + case RTL_VER_05: + ops->init = r8153_init; + ops->enable = rtl8153_enable; + ops->disable = rtl8153_disable; + ops->up = rtl8153_up; + ops->down = rtl8153_down; + ops->unload = rtl8153_unload; + ops->eee_get = r8153_get_eee; + ops->eee_set = r8153_set_eee; break; default: + ret = -ENODEV; + netif_err(tp, probe, tp->netdev, "Unknown Device\n"); break; } - if (ret) - netif_err(tp, probe, tp->netdev, "Unknown Device\n"); - return ret; } @@ -3800,7 +3829,8 @@ static int rtl8152_probe(struct usb_interface *intf, tp->netdev = netdev; tp->intf = intf; - ret = rtl_ops_init(tp, id); + r8152b_get_version(tp); + ret = rtl_ops_init(tp); if (ret) goto out; @@ -3833,11 +3863,9 @@ static int rtl8152_probe(struct usb_interface *intf, tp->mii.phy_id_mask = 0x3f; tp->mii.reg_num_mask = 0x1f; tp->mii.phy_id = R8152_PHY_ID; - tp->mii.supports_gmii = 0; intf->needs_remote_wakeup = 1; - r8152b_get_version(tp); tp->rtl_ops.init(tp); set_ethernet_addr(tp); @@ -3855,12 +3883,15 @@ static int rtl8152_probe(struct usb_interface *intf, else device_set_wakeup_enable(&udev->dev, false); + tasklet_disable(&tp->tl); + netif_info(tp, probe, netdev, "%s\n", DRIVER_VERSION); return 0; out1: usb_set_intfdata(intf, NULL); + tasklet_kill(&tp->tl); out: free_netdev(netdev); return ret; @@ -3886,9 +3917,9 @@ static void rtl8152_disconnect(struct usb_interface *intf) /* table of devices that work with this driver */ static struct usb_device_id rtl8152_table[] = { - {USB_DEVICE(VENDOR_ID_REALTEK, PRODUCT_ID_RTL8152)}, - {USB_DEVICE(VENDOR_ID_REALTEK, PRODUCT_ID_RTL8153)}, - {USB_DEVICE(VENDOR_ID_SAMSUNG, PRODUCT_ID_SAMSUNG)}, + {USB_DEVICE(VENDOR_ID_REALTEK, 0x8152)}, + {USB_DEVICE(VENDOR_ID_REALTEK, 0x8153)}, + {USB_DEVICE(VENDOR_ID_SAMSUNG, 0xa101)}, {} }; diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c index 6e87e5710048..d37b7dce2d40 100644 --- a/drivers/net/usb/rtl8150.c +++ b/drivers/net/usb/rtl8150.c @@ -753,14 +753,13 @@ static int rtl8150_open(struct net_device *netdev) static int rtl8150_close(struct net_device *netdev) { rtl8150_t *dev = netdev_priv(netdev); - int res = 0; netif_stop_queue(netdev); if (!test_bit(RTL8150_UNPLUG, &dev->flags)) disable_net_traffic(dev); unlink_all_urbs(dev); - return res; + return 0; } static void rtl8150_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *info) diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index d07bf4cb893f..26423adc35ee 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -1670,12 +1670,14 @@ done: static int smsc95xx_resume(struct usb_interface *intf) { struct usbnet *dev = usb_get_intfdata(intf); - struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); - u8 suspend_flags = pdata->suspend_flags; + struct smsc95xx_priv *pdata; + u8 suspend_flags; int ret; u32 val; BUG_ON(!dev); + pdata = (struct smsc95xx_priv *)(dev->data[0]); + suspend_flags = pdata->suspend_flags; netdev_dbg(dev->net, "resume suspend_flags=0x%02x\n", suspend_flags); diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index 6dfcbf523936..afd295348ddb 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -2199,13 +2199,6 @@ vmxnet3_setup_driver_shared(struct vmxnet3_adapter *adapter) if (adapter->rss) { struct UPT1_RSSConf *rssConf = adapter->rss_conf; - static const uint8_t rss_key[UPT1_RSS_MAX_KEY_SIZE] = { - 0x3b, 0x56, 0xd1, 0x56, 0x13, 0x4a, 0xe7, 0xac, - 0xe8, 0x79, 0x09, 0x75, 0xe8, 0x65, 0x79, 0x28, - 0x35, 0x12, 0xb9, 0x56, 0x7c, 0x76, 0x4b, 0x70, - 0xd8, 0x56, 0xa3, 0x18, 0x9b, 0x0a, 0xee, 0xf3, - 0x96, 0xa6, 0x9f, 0x8f, 0x9e, 0x8c, 0x90, 0xc9, - }; devRead->misc.uptFeatures |= UPT1_F_RSS; devRead->misc.numRxQueues = adapter->num_rx_queues; @@ -2216,7 +2209,7 @@ vmxnet3_setup_driver_shared(struct vmxnet3_adapter *adapter) rssConf->hashFunc = UPT1_RSS_HASH_FUNC_TOEPLITZ; rssConf->hashKeySize = UPT1_RSS_MAX_KEY_SIZE; rssConf->indTableSize = VMXNET3_RSS_IND_TABLE_SIZE; - memcpy(rssConf->hashKey, rss_key, sizeof(rss_key)); + netdev_rss_key_fill(rssConf->hashKey, sizeof(rssConf->hashKey)); for (i = 0; i < rssConf->indTableSize; i++) rssConf->indTable[i] = ethtool_rxfh_indir_default( diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index be4649a49c5e..d802a1ae4560 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -1593,14 +1593,9 @@ static int vxlan6_xmit_skb(struct vxlan_sock *vs, if (unlikely(err)) return err; - if (vlan_tx_tag_present(skb)) { - if (WARN_ON(!__vlan_put_tag(skb, - skb->vlan_proto, - vlan_tx_tag_get(skb)))) - return -ENOMEM; - - skb->vlan_tci = 0; - } + skb = vlan_hwaccel_push_inside(skb); + if (WARN_ON(!skb)) + return -ENOMEM; vxh = (struct vxlanhdr *) __skb_push(skb, sizeof(*vxh)); vxh->vx_flags = htonl(VXLAN_FLAGS); @@ -1637,14 +1632,9 @@ int vxlan_xmit_skb(struct vxlan_sock *vs, if (unlikely(err)) return err; - if (vlan_tx_tag_present(skb)) { - if (WARN_ON(!__vlan_put_tag(skb, - skb->vlan_proto, - vlan_tx_tag_get(skb)))) - return -ENOMEM; - - skb->vlan_tci = 0; - } + skb = vlan_hwaccel_push_inside(skb); + if (WARN_ON(!skb)) + return -ENOMEM; vxh = (struct vxlanhdr *) __skb_push(skb, sizeof(*vxh)); vxh->vx_flags = htonl(VXLAN_FLAGS); @@ -2236,6 +2226,9 @@ static const struct nla_policy vxlan_policy[IFLA_VXLAN_MAX + 1] = { [IFLA_VXLAN_L2MISS] = { .type = NLA_U8 }, [IFLA_VXLAN_L3MISS] = { .type = NLA_U8 }, [IFLA_VXLAN_PORT] = { .type = NLA_U16 }, + [IFLA_VXLAN_UDP_CSUM] = { .type = NLA_U8 }, + [IFLA_VXLAN_UDP_ZERO_CSUM6_TX] = { .type = NLA_U8 }, + [IFLA_VXLAN_UDP_ZERO_CSUM6_RX] = { .type = NLA_U8 }, }; static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[]) diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index 86907e5ba6ca..ccba4fea7269 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h @@ -135,6 +135,11 @@ struct ath_ops { struct ath_common; struct ath_bus_ops; +struct ath_ps_ops { + void (*wakeup)(struct ath_common *common); + void (*restore)(struct ath_common *common); +}; + struct ath_common { void *ah; void *priv; @@ -148,7 +153,7 @@ struct ath_common { u16 cachelsz; u16 curaid; u8 macaddr[ETH_ALEN]; - u8 curbssid[ETH_ALEN]; + u8 curbssid[ETH_ALEN] __aligned(2); u8 bssidmask[ETH_ALEN]; u32 rx_bufsize; @@ -169,6 +174,7 @@ struct ath_common { struct ath_regulatory reg_world_copy; const struct ath_ops *ops; const struct ath_bus_ops *bus_ops; + const struct ath_ps_ops *ps_ops; bool btcoex_enabled; bool disable_ani; @@ -178,6 +184,11 @@ struct ath_common { struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; }; +static inline const struct ath_ps_ops *ath_ps_ops(struct ath_common *common) +{ + return common->ps_ops; +} + struct sk_buff *ath_rxbuf_alloc(struct ath_common *common, u32 len, gfp_t gfp_mask); diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index 101cadb6e4ba..a156e6e48708 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -443,12 +443,12 @@ int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr) * Guts of ath10k_ce_completed_recv_next. * The caller takes responsibility for any necessary locking. */ -static int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state, - void **per_transfer_contextp, - u32 *bufferp, - unsigned int *nbytesp, - unsigned int *transfer_idp, - unsigned int *flagsp) +int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state, + void **per_transfer_contextp, + u32 *bufferp, + unsigned int *nbytesp, + unsigned int *transfer_idp, + unsigned int *flagsp) { struct ath10k_ce_ring *dest_ring = ce_state->dest_ring; unsigned int nentries_mask = dest_ring->nentries_mask; @@ -558,6 +558,7 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state, /* sanity */ dest_ring->per_transfer_context[sw_index] = NULL; + desc->nbytes = 0; /* Update sw_index */ sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index); @@ -576,11 +577,11 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state, * Guts of ath10k_ce_completed_send_next. * The caller takes responsibility for any necessary locking. */ -static int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, - void **per_transfer_contextp, - u32 *bufferp, - unsigned int *nbytesp, - unsigned int *transfer_idp) +int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, + void **per_transfer_contextp, + u32 *bufferp, + unsigned int *nbytesp, + unsigned int *transfer_idp) { struct ath10k_ce_ring *src_ring = ce_state->src_ring; u32 ctrl_addr = ce_state->ctrl_addr; @@ -817,7 +818,10 @@ void ath10k_ce_enable_interrupts(struct ath10k *ar) struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); int ce_id; - for (ce_id = 0; ce_id < CE_COUNT; ce_id++) + /* Skip the last copy engine, CE7 the diagnostic window, as that + * uses polling and isn't initialized for interrupts. + */ + for (ce_id = 0; ce_id < CE_COUNT - 1; ce_id++) ath10k_ce_per_engine_handler_adjust(&ar_pci->ce_states[ce_id]); } @@ -832,8 +836,8 @@ static int ath10k_ce_init_src_ring(struct ath10k *ar, nentries = roundup_pow_of_two(attr->src_nentries); - memset(src_ring->per_transfer_context, 0, - nentries * sizeof(*src_ring->per_transfer_context)); + memset(src_ring->base_addr_owner_space, 0, + nentries * sizeof(struct ce_desc)); src_ring->sw_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr); src_ring->sw_index &= src_ring->nentries_mask; @@ -869,8 +873,8 @@ static int ath10k_ce_init_dest_ring(struct ath10k *ar, nentries = roundup_pow_of_two(attr->dest_nentries); - memset(dest_ring->per_transfer_context, 0, - nentries * sizeof(*dest_ring->per_transfer_context)); + memset(dest_ring->base_addr_owner_space, 0, + nentries * sizeof(struct ce_desc)); dest_ring->sw_index = ath10k_ce_dest_ring_read_index_get(ar, ctrl_addr); dest_ring->sw_index &= dest_ring->nentries_mask; @@ -1020,37 +1024,10 @@ ath10k_ce_alloc_dest_ring(struct ath10k *ar, unsigned int ce_id, * initialized by software/firmware. */ int ath10k_ce_init_pipe(struct ath10k *ar, unsigned int ce_id, - const struct ce_attr *attr, - void (*send_cb)(struct ath10k_ce_pipe *), - void (*recv_cb)(struct ath10k_ce_pipe *)) + const struct ce_attr *attr) { - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id]; int ret; - /* - * Make sure there's enough CE ringbuffer entries for HTT TX to avoid - * additional TX locking checks. - * - * For the lack of a better place do the check here. - */ - BUILD_BUG_ON(2*TARGET_NUM_MSDU_DESC > - (CE_HTT_H2T_MSG_SRC_NENTRIES - 1)); - BUILD_BUG_ON(2*TARGET_10X_NUM_MSDU_DESC > - (CE_HTT_H2T_MSG_SRC_NENTRIES - 1)); - - spin_lock_bh(&ar_pci->ce_lock); - ce_state->ar = ar; - ce_state->id = ce_id; - ce_state->ctrl_addr = ath10k_ce_base_address(ce_id); - ce_state->attr_flags = attr->flags; - ce_state->src_sz_max = attr->src_sz_max; - if (attr->src_nentries) - ce_state->send_cb = send_cb; - if (attr->dest_nentries) - ce_state->recv_cb = recv_cb; - spin_unlock_bh(&ar_pci->ce_lock); - if (attr->src_nentries) { ret = ath10k_ce_init_src_ring(ar, ce_id, attr); if (ret) { @@ -1098,12 +1075,37 @@ void ath10k_ce_deinit_pipe(struct ath10k *ar, unsigned int ce_id) } int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id, - const struct ce_attr *attr) + const struct ce_attr *attr, + void (*send_cb)(struct ath10k_ce_pipe *), + void (*recv_cb)(struct ath10k_ce_pipe *)) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id]; int ret; + /* + * Make sure there's enough CE ringbuffer entries for HTT TX to avoid + * additional TX locking checks. + * + * For the lack of a better place do the check here. + */ + BUILD_BUG_ON(2*TARGET_NUM_MSDU_DESC > + (CE_HTT_H2T_MSG_SRC_NENTRIES - 1)); + BUILD_BUG_ON(2*TARGET_10X_NUM_MSDU_DESC > + (CE_HTT_H2T_MSG_SRC_NENTRIES - 1)); + + ce_state->ar = ar; + ce_state->id = ce_id; + ce_state->ctrl_addr = ath10k_ce_base_address(ce_id); + ce_state->attr_flags = attr->flags; + ce_state->src_sz_max = attr->src_sz_max; + + if (attr->src_nentries) + ce_state->send_cb = send_cb; + + if (attr->dest_nentries) + ce_state->recv_cb = recv_cb; + if (attr->src_nentries) { ce_state->src_ring = ath10k_ce_alloc_src_ring(ar, ce_id, attr); if (IS_ERR(ce_state->src_ring)) { diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index 329b7340fa72..617a151e8ce4 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h @@ -192,15 +192,21 @@ int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state, unsigned int *nbytesp, unsigned int *transfer_idp); +int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, + void **per_transfer_contextp, + u32 *bufferp, + unsigned int *nbytesp, + unsigned int *transfer_idp); + /*==================CE Engine Initialization=======================*/ int ath10k_ce_init_pipe(struct ath10k *ar, unsigned int ce_id, - const struct ce_attr *attr, - void (*send_cb)(struct ath10k_ce_pipe *), - void (*recv_cb)(struct ath10k_ce_pipe *)); + const struct ce_attr *attr); void ath10k_ce_deinit_pipe(struct ath10k *ar, unsigned int ce_id); int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id, - const struct ce_attr *attr); + const struct ce_attr *attr, + void (*send_cb)(struct ath10k_ce_pipe *), + void (*recv_cb)(struct ath10k_ce_pipe *)); void ath10k_ce_free_pipe(struct ath10k *ar, int ce_id); /*==================CE Engine Shutdown=======================*/ @@ -213,6 +219,13 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state, void **per_transfer_contextp, u32 *bufferp); +int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state, + void **per_transfer_contextp, + u32 *bufferp, + unsigned int *nbytesp, + unsigned int *transfer_idp, + unsigned int *flagsp); + /* * Support clean shutdown by allowing the caller to cancel * pending sends. Target DMA must be stopped before using diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index cee18c89d7f2..f660553c6c48 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -31,12 +31,17 @@ unsigned int ath10k_debug_mask; static bool uart_print; static unsigned int ath10k_p2p; +static bool skip_otp; + module_param_named(debug_mask, ath10k_debug_mask, uint, 0644); module_param(uart_print, bool, 0644); module_param_named(p2p, ath10k_p2p, uint, 0644); +module_param(skip_otp, bool, 0644); + MODULE_PARM_DESC(debug_mask, "Debugging mask"); MODULE_PARM_DESC(uart_print, "Uart target debugging"); MODULE_PARM_DESC(p2p, "Enable ath10k P2P support"); +MODULE_PARM_DESC(skip_otp, "Skip otp failure for calibration in testmode"); static const struct ath10k_hw_params ath10k_hw_params_list[] = { { @@ -138,7 +143,8 @@ static const struct firmware *ath10k_fetch_fw_file(struct ath10k *ar, return fw; } -static int ath10k_push_board_ext_data(struct ath10k *ar) +static int ath10k_push_board_ext_data(struct ath10k *ar, const void *data, + size_t data_len) { u32 board_data_size = QCA988X_BOARD_DATA_SZ; u32 board_ext_data_size = QCA988X_BOARD_EXT_DATA_SZ; @@ -159,14 +165,14 @@ static int ath10k_push_board_ext_data(struct ath10k *ar) if (board_ext_data_addr == 0) return 0; - if (ar->board_len != (board_data_size + board_ext_data_size)) { + if (data_len != (board_data_size + board_ext_data_size)) { ath10k_err(ar, "invalid board (ext) data sizes %zu != %d+%d\n", - ar->board_len, board_data_size, board_ext_data_size); + data_len, board_data_size, board_ext_data_size); return -EINVAL; } ret = ath10k_bmi_write_memory(ar, board_ext_data_addr, - ar->board_data + board_data_size, + data + board_data_size, board_ext_data_size); if (ret) { ath10k_err(ar, "could not write board ext data (%d)\n", ret); @@ -184,13 +190,14 @@ static int ath10k_push_board_ext_data(struct ath10k *ar) return 0; } -static int ath10k_download_board_data(struct ath10k *ar) +static int ath10k_download_board_data(struct ath10k *ar, const void *data, + size_t data_len) { u32 board_data_size = QCA988X_BOARD_DATA_SZ; u32 address; int ret; - ret = ath10k_push_board_ext_data(ar); + ret = ath10k_push_board_ext_data(ar, data, data_len); if (ret) { ath10k_err(ar, "could not push board ext data (%d)\n", ret); goto exit; @@ -202,9 +209,9 @@ static int ath10k_download_board_data(struct ath10k *ar) goto exit; } - ret = ath10k_bmi_write_memory(ar, address, ar->board_data, + ret = ath10k_bmi_write_memory(ar, address, data, min_t(u32, board_data_size, - ar->board_len)); + data_len)); if (ret) { ath10k_err(ar, "could not write board data (%d)\n", ret); goto exit; @@ -220,11 +227,39 @@ exit: return ret; } +static int ath10k_download_cal_file(struct ath10k *ar) +{ + int ret; + + if (!ar->cal_file) + return -ENOENT; + + if (IS_ERR(ar->cal_file)) + return PTR_ERR(ar->cal_file); + + ret = ath10k_download_board_data(ar, ar->cal_file->data, + ar->cal_file->size); + if (ret) { + ath10k_err(ar, "failed to download cal_file data: %d\n", ret); + return ret; + } + + ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cal file downloaded\n"); + + return 0; +} + static int ath10k_download_and_run_otp(struct ath10k *ar) { u32 result, address = ar->hw_params.patch_load_addr; int ret; + ret = ath10k_download_board_data(ar, ar->board_data, ar->board_len); + if (ret) { + ath10k_err(ar, "failed to download board data: %d\n", ret); + return ret; + } + /* OTP is optional */ if (!ar->otp_data || !ar->otp_len) { @@ -250,7 +285,7 @@ static int ath10k_download_and_run_otp(struct ath10k *ar) ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot otp execute result %d\n", result); - if (result != 0) { + if (!skip_otp && result != 0) { ath10k_err(ar, "otp calibration failed: %d", result); return -EINVAL; } @@ -308,6 +343,9 @@ static void ath10k_core_free_firmware_files(struct ath10k *ar) if (ar->firmware && !IS_ERR(ar->firmware)) release_firmware(ar->firmware); + if (ar->cal_file && !IS_ERR(ar->cal_file)) + release_firmware(ar->cal_file); + ar->board = NULL; ar->board_data = NULL; ar->board_len = 0; @@ -319,6 +357,27 @@ static void ath10k_core_free_firmware_files(struct ath10k *ar) ar->firmware = NULL; ar->firmware_data = NULL; ar->firmware_len = 0; + + ar->cal_file = NULL; +} + +static int ath10k_fetch_cal_file(struct ath10k *ar) +{ + char filename[100]; + + /* cal-<bus>-<id>.bin */ + scnprintf(filename, sizeof(filename), "cal-%s-%s.bin", + ath10k_bus_str(ar->hif.bus), dev_name(ar->dev)); + + ar->cal_file = ath10k_fetch_fw_file(ar, ATH10K_FW_DIR, filename); + if (IS_ERR(ar->cal_file)) + /* calibration file is optional, don't print any warnings */ + return PTR_ERR(ar->cal_file); + + ath10k_dbg(ar, ATH10K_DBG_BOOT, "found calibration file %s/%s\n", + ATH10K_FW_DIR, filename); + + return 0; } static int ath10k_core_fetch_firmware_api_1(struct ath10k *ar) @@ -562,6 +621,9 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar) { int ret; + /* calibration file is optional, don't check for any errors */ + ath10k_fetch_cal_file(ar); + ar->fw_api = 3; ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api); @@ -589,30 +651,32 @@ success: return 0; } -static int ath10k_init_download_firmware(struct ath10k *ar, - enum ath10k_firmware_mode mode) +static int ath10k_download_cal_data(struct ath10k *ar) { int ret; - ret = ath10k_download_board_data(ar); - if (ret) { - ath10k_err(ar, "failed to download board data: %d\n", ret); - return ret; + ret = ath10k_download_cal_file(ar); + if (ret == 0) { + ar->cal_mode = ATH10K_CAL_MODE_FILE; + goto done; } + ath10k_dbg(ar, ATH10K_DBG_BOOT, + "boot did not find a calibration file, try OTP next: %d\n", + ret); + ret = ath10k_download_and_run_otp(ar); if (ret) { ath10k_err(ar, "failed to run otp: %d\n", ret); return ret; } - ret = ath10k_download_fw(ar, mode); - if (ret) { - ath10k_err(ar, "failed to download firmware: %d\n", ret); - return ret; - } + ar->cal_mode = ATH10K_CAL_MODE_OTP; - return ret; +done: + ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot using calibration mode %s\n", + ath10k_cal_mode_str(ar->cal_mode)); + return 0; } static int ath10k_init_uart(struct ath10k *ar) @@ -685,6 +749,25 @@ static void ath10k_core_restart(struct work_struct *work) { struct ath10k *ar = container_of(work, struct ath10k, restart_work); + set_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags); + + /* Place a barrier to make sure the compiler doesn't reorder + * CRASH_FLUSH and calling other functions. + */ + barrier(); + + ieee80211_stop_queues(ar->hw); + ath10k_drain_tx(ar); + complete_all(&ar->scan.started); + complete_all(&ar->scan.completed); + complete_all(&ar->scan.on_channel); + complete_all(&ar->offchan_tx_completed); + complete_all(&ar->install_key_done); + complete_all(&ar->vdev_setup_done); + wake_up(&ar->htt.empty_tx_wq); + wake_up(&ar->wmi.tx_credits_wq); + wake_up(&ar->peer_mapping_wq); + mutex_lock(&ar->conf_mutex); switch (ar->state) { @@ -722,6 +805,8 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode) lockdep_assert_held(&ar->conf_mutex); + clear_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags); + ath10k_bmi_start(ar); if (ath10k_init_configure_target(ar)) { @@ -729,7 +814,11 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode) goto err; } - status = ath10k_init_download_firmware(ar, mode); + status = ath10k_download_cal_data(ar); + if (status) + goto err; + + status = ath10k_download_fw(ar, mode); if (status) goto err; @@ -846,9 +935,9 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode) goto err_hif_stop; if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) - ar->free_vdev_map = (1 << TARGET_10X_NUM_VDEVS) - 1; + ar->free_vdev_map = (1LL << TARGET_10X_NUM_VDEVS) - 1; else - ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1; + ar->free_vdev_map = (1LL << TARGET_NUM_VDEVS) - 1; INIT_LIST_HEAD(&ar->arvifs); @@ -1084,6 +1173,7 @@ void ath10k_core_unregister(struct ath10k *ar) EXPORT_SYMBOL(ath10k_core_unregister); struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, + enum ath10k_bus bus, const struct ath10k_hif_ops *hif_ops) { struct ath10k *ar; @@ -1100,6 +1190,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, ar->dev = dev; ar->hif.ops = hif_ops; + ar->hif.bus = bus; init_completion(&ar->scan.started); init_completion(&ar->scan.completed); @@ -1120,6 +1211,8 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, INIT_LIST_HEAD(&ar->peers); init_waitqueue_head(&ar->peer_mapping_wq); + init_waitqueue_head(&ar->htt.empty_tx_wq); + init_waitqueue_head(&ar->wmi.tx_credits_wq); init_completion(&ar->offchan_tx_completed); INIT_WORK(&ar->offchan_tx_work, ath10k_offchan_tx_work); diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index fe531ea6926c..8f86bd34e823 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -63,6 +63,20 @@ struct ath10k; +enum ath10k_bus { + ATH10K_BUS_PCI, +}; + +static inline const char *ath10k_bus_str(enum ath10k_bus bus) +{ + switch (bus) { + case ATH10K_BUS_PCI: + return "pci"; + } + + return "unknown"; +} + struct ath10k_skb_cb { dma_addr_t paddr; u8 vdev_id; @@ -96,8 +110,6 @@ struct ath10k_bmi { bool done_sent; }; -#define ATH10K_MAX_MEM_REQS 16 - struct ath10k_mem_chunk { void *vaddr; dma_addr_t paddr; @@ -115,17 +127,21 @@ struct ath10k_wmi { struct wmi_pdev_param_map *pdev_param; u32 num_mem_chunks; - struct ath10k_mem_chunk mem_chunks[ATH10K_MAX_MEM_REQS]; + struct ath10k_mem_chunk mem_chunks[WMI_MAX_MEM_REQS]; }; -struct ath10k_peer_stat { +struct ath10k_fw_stats_peer { + struct list_head list; + u8 peer_macaddr[ETH_ALEN]; u32 peer_rssi; u32 peer_tx_rate; u32 peer_rx_rate; /* 10x only */ }; -struct ath10k_target_stats { +struct ath10k_fw_stats_pdev { + struct list_head list; + /* PDEV stats */ s32 ch_noise_floor; u32 tx_frame_count; @@ -180,15 +196,11 @@ struct ath10k_target_stats { s32 phy_errs; s32 phy_err_drop; s32 mpdu_errs; +}; - /* VDEV STATS */ - - /* PEER STATS */ - u8 peers; - struct ath10k_peer_stat peer_stat[TARGET_NUM_PEERS]; - - /* TODO: Beacon filter stats */ - +struct ath10k_fw_stats { + struct list_head pdevs; + struct list_head peers; }; struct ath10k_dfs_stats { @@ -234,6 +246,8 @@ struct ath10k_vif { struct sk_buff *beacon; /* protected by data_lock */ bool beacon_sent; + void *beacon_buf; + dma_addr_t beacon_paddr; struct ath10k *ar; struct ieee80211_vif *vif; @@ -273,6 +287,7 @@ struct ath10k_vif { u8 force_sgi; bool use_cts_prot; int num_legacy_stations; + int txpower; }; struct ath10k_vif_iter { @@ -292,17 +307,19 @@ struct ath10k_fw_crash_data { struct ath10k_debug { struct dentry *debugfs_phy; - struct ath10k_target_stats target_stats; + struct ath10k_fw_stats fw_stats; + struct completion fw_stats_complete; + bool fw_stats_done; DECLARE_BITMAP(wmi_service_bitmap, WMI_SERVICE_MAX); - struct completion event_stats_compl; - unsigned long htt_stats_mask; struct delayed_work htt_stats_dwork; struct ath10k_dfs_stats dfs_stats; struct ath_dfs_pool_stats dfs_pool_stats; + /* protected by conf_mutex */ u32 fw_dbglog_mask; + u32 pktlog_filter; u8 htt_max_amsdu; u8 htt_max_ampdu; @@ -321,7 +338,7 @@ enum ath10k_state { * stopped in ath10k_core_restart() work holding conf_mutex. The state * RESTARTED means that the device is up and mac80211 has started hw * reconfiguration. Once mac80211 is done with the reconfiguration we - * set the state to STATE_ON in restart_complete(). */ + * set the state to STATE_ON in reconfig_complete(). */ ATH10K_STATE_RESTARTING, ATH10K_STATE_RESTARTED, @@ -369,8 +386,30 @@ enum ath10k_dev_flags { /* Indicates that ath10k device is during CAC phase of DFS */ ATH10K_CAC_RUNNING, ATH10K_FLAG_CORE_REGISTERED, + + /* Device has crashed and needs to restart. This indicates any pending + * waiters should immediately cancel instead of waiting for a time out. + */ + ATH10K_FLAG_CRASH_FLUSH, }; +enum ath10k_cal_mode { + ATH10K_CAL_MODE_FILE, + ATH10K_CAL_MODE_OTP, +}; + +static inline const char *ath10k_cal_mode_str(enum ath10k_cal_mode mode) +{ + switch (mode) { + case ATH10K_CAL_MODE_FILE: + return "file"; + case ATH10K_CAL_MODE_OTP: + return "otp"; + } + + return "unknown"; +} + enum ath10k_scan_state { ATH10K_SCAN_IDLE, ATH10K_SCAN_STARTING, @@ -421,6 +460,7 @@ struct ath10k { bool p2p; struct { + enum ath10k_bus bus; const struct ath10k_hif_ops *ops; } hif; @@ -456,7 +496,10 @@ struct ath10k { const void *firmware_data; size_t firmware_len; + const struct firmware *cal_file; + int fw_api; + enum ath10k_cal_mode cal_mode; struct { struct completion started; @@ -482,7 +525,7 @@ struct ath10k { /* current operating channel definition */ struct cfg80211_chan_def chandef; - int free_vdev_map; + unsigned long long free_vdev_map; bool monitor; int monitor_vdev_id; bool monitor_started; @@ -563,11 +606,19 @@ struct ath10k { bool utf_monitor; } testmode; + struct { + /* protected by data_lock */ + u32 fw_crash_counter; + u32 fw_warm_reset_counter; + u32 fw_cold_reset_counter; + } stats; + /* must be last */ u8 drv_priv[0] __aligned(sizeof(void *)); }; struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, + enum ath10k_bus bus, const struct ath10k_hif_ops *hif_ops); void ath10k_core_destroy(struct ath10k *ar); diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 3756feba3223..a8f5a72ba259 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -23,6 +23,7 @@ #include "core.h" #include "debug.h" +#include "hif.h" /* ms */ #define ATH10K_DEBUG_HTT_STATS_INTERVAL 1000 @@ -106,34 +107,36 @@ struct ath10k_dump_file_data { u8 data[0]; } __packed; -int ath10k_info(struct ath10k *ar, const char *fmt, ...) +void ath10k_info(struct ath10k *ar, const char *fmt, ...) { struct va_format vaf = { .fmt = fmt, }; va_list args; - int ret; va_start(args, fmt); vaf.va = &args; - ret = dev_info(ar->dev, "%pV", &vaf); + dev_info(ar->dev, "%pV", &vaf); trace_ath10k_log_info(ar, &vaf); va_end(args); - - return ret; } EXPORT_SYMBOL(ath10k_info); void ath10k_print_driver_info(struct ath10k *ar) { - ath10k_info(ar, "%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d\n", + ath10k_info(ar, "%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d wmi %d.%d.%d.%d cal %s\n", ar->hw_params.name, ar->target_version, ar->chip_id, ar->hw->wiphy->fw_version, ar->fw_api, ar->htt.target_version_major, - ar->htt.target_version_minor); + ar->htt.target_version_minor, + ar->fw_version_major, + ar->fw_version_minor, + ar->fw_version_release, + ar->fw_version_build, + ath10k_cal_mode_str(ar->cal_mode)); ath10k_info(ar, "debug %d debugfs %d tracing %d dfs %d testmode %d\n", config_enabled(CONFIG_ATH10K_DEBUG), config_enabled(CONFIG_ATH10K_DEBUGFS), @@ -143,25 +146,22 @@ void ath10k_print_driver_info(struct ath10k *ar) } EXPORT_SYMBOL(ath10k_print_driver_info); -int ath10k_err(struct ath10k *ar, const char *fmt, ...) +void ath10k_err(struct ath10k *ar, const char *fmt, ...) { struct va_format vaf = { .fmt = fmt, }; va_list args; - int ret; va_start(args, fmt); vaf.va = &args; - ret = dev_err(ar->dev, "%pV", &vaf); + dev_err(ar->dev, "%pV", &vaf); trace_ath10k_log_err(ar, &vaf); va_end(args); - - return ret; } EXPORT_SYMBOL(ath10k_err); -int ath10k_warn(struct ath10k *ar, const char *fmt, ...) +void ath10k_warn(struct ath10k *ar, const char *fmt, ...) { struct va_format vaf = { .fmt = fmt, @@ -174,15 +174,13 @@ int ath10k_warn(struct ath10k *ar, const char *fmt, ...) trace_ath10k_log_warn(ar, &vaf); va_end(args); - - return 0; } EXPORT_SYMBOL(ath10k_warn); #ifdef CONFIG_ATH10K_DEBUGFS void ath10k_debug_read_service_map(struct ath10k *ar, - void *service_map, + const void *service_map, size_t map_size) { memcpy(ar->debug.wmi_service_bitmap, service_map, map_size); @@ -242,169 +240,182 @@ static const struct file_operations fops_wmi_services = { .llseek = default_llseek, }; -void ath10k_debug_read_target_stats(struct ath10k *ar, - struct wmi_stats_event *ev) +static void ath10k_debug_fw_stats_pdevs_free(struct list_head *head) { - u8 *tmp = ev->data; - struct ath10k_target_stats *stats; - int num_pdev_stats, num_vdev_stats, num_peer_stats; - struct wmi_pdev_stats_10x *ps; - int i; + struct ath10k_fw_stats_pdev *i, *tmp; + + list_for_each_entry_safe(i, tmp, head, list) { + list_del(&i->list); + kfree(i); + } +} + +static void ath10k_debug_fw_stats_peers_free(struct list_head *head) +{ + struct ath10k_fw_stats_peer *i, *tmp; + + list_for_each_entry_safe(i, tmp, head, list) { + list_del(&i->list); + kfree(i); + } +} +static void ath10k_debug_fw_stats_reset(struct ath10k *ar) +{ spin_lock_bh(&ar->data_lock); + ar->debug.fw_stats_done = false; + ath10k_debug_fw_stats_pdevs_free(&ar->debug.fw_stats.pdevs); + ath10k_debug_fw_stats_peers_free(&ar->debug.fw_stats.peers); + spin_unlock_bh(&ar->data_lock); +} - stats = &ar->debug.target_stats; - - num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats); /* 0 or 1 */ - num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats); /* 0 or max vdevs */ - num_peer_stats = __le32_to_cpu(ev->num_peer_stats); /* 0 or max peers */ - - if (num_pdev_stats) { - ps = (struct wmi_pdev_stats_10x *)tmp; - - stats->ch_noise_floor = __le32_to_cpu(ps->chan_nf); - stats->tx_frame_count = __le32_to_cpu(ps->tx_frame_count); - stats->rx_frame_count = __le32_to_cpu(ps->rx_frame_count); - stats->rx_clear_count = __le32_to_cpu(ps->rx_clear_count); - stats->cycle_count = __le32_to_cpu(ps->cycle_count); - stats->phy_err_count = __le32_to_cpu(ps->phy_err_count); - stats->chan_tx_power = __le32_to_cpu(ps->chan_tx_pwr); - - stats->comp_queued = __le32_to_cpu(ps->wal.tx.comp_queued); - stats->comp_delivered = - __le32_to_cpu(ps->wal.tx.comp_delivered); - stats->msdu_enqued = __le32_to_cpu(ps->wal.tx.msdu_enqued); - stats->mpdu_enqued = __le32_to_cpu(ps->wal.tx.mpdu_enqued); - stats->wmm_drop = __le32_to_cpu(ps->wal.tx.wmm_drop); - stats->local_enqued = __le32_to_cpu(ps->wal.tx.local_enqued); - stats->local_freed = __le32_to_cpu(ps->wal.tx.local_freed); - stats->hw_queued = __le32_to_cpu(ps->wal.tx.hw_queued); - stats->hw_reaped = __le32_to_cpu(ps->wal.tx.hw_reaped); - stats->underrun = __le32_to_cpu(ps->wal.tx.underrun); - stats->tx_abort = __le32_to_cpu(ps->wal.tx.tx_abort); - stats->mpdus_requed = __le32_to_cpu(ps->wal.tx.mpdus_requed); - stats->tx_ko = __le32_to_cpu(ps->wal.tx.tx_ko); - stats->data_rc = __le32_to_cpu(ps->wal.tx.data_rc); - stats->self_triggers = __le32_to_cpu(ps->wal.tx.self_triggers); - stats->sw_retry_failure = - __le32_to_cpu(ps->wal.tx.sw_retry_failure); - stats->illgl_rate_phy_err = - __le32_to_cpu(ps->wal.tx.illgl_rate_phy_err); - stats->pdev_cont_xretry = - __le32_to_cpu(ps->wal.tx.pdev_cont_xretry); - stats->pdev_tx_timeout = - __le32_to_cpu(ps->wal.tx.pdev_tx_timeout); - stats->pdev_resets = __le32_to_cpu(ps->wal.tx.pdev_resets); - stats->phy_underrun = __le32_to_cpu(ps->wal.tx.phy_underrun); - stats->txop_ovf = __le32_to_cpu(ps->wal.tx.txop_ovf); - - stats->mid_ppdu_route_change = - __le32_to_cpu(ps->wal.rx.mid_ppdu_route_change); - stats->status_rcvd = __le32_to_cpu(ps->wal.rx.status_rcvd); - stats->r0_frags = __le32_to_cpu(ps->wal.rx.r0_frags); - stats->r1_frags = __le32_to_cpu(ps->wal.rx.r1_frags); - stats->r2_frags = __le32_to_cpu(ps->wal.rx.r2_frags); - stats->r3_frags = __le32_to_cpu(ps->wal.rx.r3_frags); - stats->htt_msdus = __le32_to_cpu(ps->wal.rx.htt_msdus); - stats->htt_mpdus = __le32_to_cpu(ps->wal.rx.htt_mpdus); - stats->loc_msdus = __le32_to_cpu(ps->wal.rx.loc_msdus); - stats->loc_mpdus = __le32_to_cpu(ps->wal.rx.loc_mpdus); - stats->oversize_amsdu = - __le32_to_cpu(ps->wal.rx.oversize_amsdu); - stats->phy_errs = __le32_to_cpu(ps->wal.rx.phy_errs); - stats->phy_err_drop = __le32_to_cpu(ps->wal.rx.phy_err_drop); - stats->mpdu_errs = __le32_to_cpu(ps->wal.rx.mpdu_errs); - - if (test_bit(ATH10K_FW_FEATURE_WMI_10X, - ar->fw_features)) { - stats->ack_rx_bad = __le32_to_cpu(ps->ack_rx_bad); - stats->rts_bad = __le32_to_cpu(ps->rts_bad); - stats->rts_good = __le32_to_cpu(ps->rts_good); - stats->fcs_bad = __le32_to_cpu(ps->fcs_bad); - stats->no_beacons = __le32_to_cpu(ps->no_beacons); - stats->mib_int_count = __le32_to_cpu(ps->mib_int_count); - tmp += sizeof(struct wmi_pdev_stats_10x); - } else { - tmp += sizeof(struct wmi_pdev_stats_old); - } +static size_t ath10k_debug_fw_stats_num_peers(struct list_head *head) +{ + struct ath10k_fw_stats_peer *i; + size_t num = 0; + + list_for_each_entry(i, head, list) + ++num; + + return num; +} + +void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb) +{ + struct ath10k_fw_stats stats = {}; + bool is_start, is_started, is_end; + size_t num_peers; + int ret; + + INIT_LIST_HEAD(&stats.pdevs); + INIT_LIST_HEAD(&stats.peers); + + spin_lock_bh(&ar->data_lock); + ret = ath10k_wmi_pull_fw_stats(ar, skb, &stats); + if (ret) { + ath10k_warn(ar, "failed to pull fw stats: %d\n", ret); + goto unlock; } - /* 0 or max vdevs */ - /* Currently firmware does not support VDEV stats */ - if (num_vdev_stats) { - struct wmi_vdev_stats *vdev_stats; + /* Stat data may exceed htc-wmi buffer limit. In such case firmware + * splits the stats data and delivers it in a ping-pong fashion of + * request cmd-update event. + * + * However there is no explicit end-of-data. Instead start-of-data is + * used as an implicit one. This works as follows: + * a) discard stat update events until one with pdev stats is + * delivered - this skips session started at end of (b) + * b) consume stat update events until another one with pdev stats is + * delivered which is treated as end-of-data and is itself discarded + */ - for (i = 0; i < num_vdev_stats; i++) { - vdev_stats = (struct wmi_vdev_stats *)tmp; - tmp += sizeof(struct wmi_vdev_stats); - } + if (ar->debug.fw_stats_done) { + ath10k_warn(ar, "received unsolicited stats update event\n"); + goto free; } - if (num_peer_stats) { - struct wmi_peer_stats_10x *peer_stats; - struct ath10k_peer_stat *s; - - stats->peers = num_peer_stats; - - for (i = 0; i < num_peer_stats; i++) { - peer_stats = (struct wmi_peer_stats_10x *)tmp; - s = &stats->peer_stat[i]; - - memcpy(s->peer_macaddr, &peer_stats->peer_macaddr.addr, - ETH_ALEN); - s->peer_rssi = __le32_to_cpu(peer_stats->peer_rssi); - s->peer_tx_rate = - __le32_to_cpu(peer_stats->peer_tx_rate); - if (test_bit(ATH10K_FW_FEATURE_WMI_10X, - ar->fw_features)) { - s->peer_rx_rate = - __le32_to_cpu(peer_stats->peer_rx_rate); - tmp += sizeof(struct wmi_peer_stats_10x); - - } else { - tmp += sizeof(struct wmi_peer_stats_old); - } + num_peers = ath10k_debug_fw_stats_num_peers(&ar->debug.fw_stats.peers); + is_start = (list_empty(&ar->debug.fw_stats.pdevs) && + !list_empty(&stats.pdevs)); + is_end = (!list_empty(&ar->debug.fw_stats.pdevs) && + !list_empty(&stats.pdevs)); + + if (is_start) + list_splice_tail_init(&stats.pdevs, &ar->debug.fw_stats.pdevs); + + if (is_end) + ar->debug.fw_stats_done = true; + + is_started = !list_empty(&ar->debug.fw_stats.pdevs); + + if (is_started && !is_end) { + if (num_peers >= ATH10K_MAX_NUM_PEER_IDS) { + /* Although this is unlikely impose a sane limit to + * prevent firmware from DoS-ing the host. + */ + ath10k_warn(ar, "dropping fw peer stats\n"); + goto free; } + + list_splice_tail_init(&stats.peers, &ar->debug.fw_stats.peers); } + complete(&ar->debug.fw_stats_complete); + +free: + /* In some cases lists have been spliced and cleared. Free up + * resources if that is not the case. + */ + ath10k_debug_fw_stats_pdevs_free(&stats.pdevs); + ath10k_debug_fw_stats_peers_free(&stats.peers); + +unlock: spin_unlock_bh(&ar->data_lock); - complete(&ar->debug.event_stats_compl); } -static ssize_t ath10k_read_fw_stats(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) +static int ath10k_debug_fw_stats_request(struct ath10k *ar) { - struct ath10k *ar = file->private_data; - struct ath10k_target_stats *fw_stats; - char *buf = NULL; - unsigned int len = 0, buf_len = 8000; - ssize_t ret_cnt = 0; - long left; - int i; + unsigned long timeout; int ret; - fw_stats = &ar->debug.target_stats; + lockdep_assert_held(&ar->conf_mutex); - mutex_lock(&ar->conf_mutex); + timeout = jiffies + msecs_to_jiffies(1*HZ); - if (ar->state != ATH10K_STATE_ON) - goto exit; + ath10k_debug_fw_stats_reset(ar); - buf = kzalloc(buf_len, GFP_KERNEL); - if (!buf) - goto exit; + for (;;) { + if (time_after(jiffies, timeout)) + return -ETIMEDOUT; - ret = ath10k_wmi_request_stats(ar, WMI_REQUEST_PEER_STAT); - if (ret) { - ath10k_warn(ar, "could not request stats (%d)\n", ret); - goto exit; + reinit_completion(&ar->debug.fw_stats_complete); + + ret = ath10k_wmi_request_stats(ar, WMI_REQUEST_PEER_STAT); + if (ret) { + ath10k_warn(ar, "could not request stats (%d)\n", ret); + return ret; + } + + ret = wait_for_completion_timeout(&ar->debug.fw_stats_complete, + 1*HZ); + if (ret <= 0) + return -ETIMEDOUT; + + spin_lock_bh(&ar->data_lock); + if (ar->debug.fw_stats_done) { + spin_unlock_bh(&ar->data_lock); + break; + } + spin_unlock_bh(&ar->data_lock); } - left = wait_for_completion_timeout(&ar->debug.event_stats_compl, 1*HZ); - if (left <= 0) - goto exit; + return 0; +} + +/* FIXME: How to calculate the buffer size sanely? */ +#define ATH10K_FW_STATS_BUF_SIZE (1024*1024) + +static void ath10k_fw_stats_fill(struct ath10k *ar, + struct ath10k_fw_stats *fw_stats, + char *buf) +{ + unsigned int len = 0; + unsigned int buf_len = ATH10K_FW_STATS_BUF_SIZE; + const struct ath10k_fw_stats_pdev *pdev; + const struct ath10k_fw_stats_peer *peer; + size_t num_peers; spin_lock_bh(&ar->data_lock); + + pdev = list_first_entry_or_null(&fw_stats->pdevs, + struct ath10k_fw_stats_pdev, list); + if (!pdev) { + ath10k_warn(ar, "failed to get pdev stats\n"); + goto unlock; + } + + num_peers = ath10k_debug_fw_stats_num_peers(&fw_stats->peers); + len += scnprintf(buf + len, buf_len - len, "\n"); len += scnprintf(buf + len, buf_len - len, "%30s\n", "ath10k PDEV stats"); @@ -412,29 +423,29 @@ static ssize_t ath10k_read_fw_stats(struct file *file, char __user *user_buf, "================="); len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Channel noise floor", fw_stats->ch_noise_floor); + "Channel noise floor", pdev->ch_noise_floor); len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", - "Channel TX power", fw_stats->chan_tx_power); + "Channel TX power", pdev->chan_tx_power); len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", - "TX frame count", fw_stats->tx_frame_count); + "TX frame count", pdev->tx_frame_count); len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", - "RX frame count", fw_stats->rx_frame_count); + "RX frame count", pdev->rx_frame_count); len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", - "RX clear count", fw_stats->rx_clear_count); + "RX clear count", pdev->rx_clear_count); len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", - "Cycle count", fw_stats->cycle_count); + "Cycle count", pdev->cycle_count); len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", - "PHY error count", fw_stats->phy_err_count); + "PHY error count", pdev->phy_err_count); len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", - "RTS bad count", fw_stats->rts_bad); + "RTS bad count", pdev->rts_bad); len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", - "RTS good count", fw_stats->rts_good); + "RTS good count", pdev->rts_good); len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", - "FCS bad count", fw_stats->fcs_bad); + "FCS bad count", pdev->fcs_bad); len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", - "No beacon count", fw_stats->no_beacons); + "No beacon count", pdev->no_beacons); len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", - "MIB int count", fw_stats->mib_int_count); + "MIB int count", pdev->mib_int_count); len += scnprintf(buf + len, buf_len - len, "\n"); len += scnprintf(buf + len, buf_len - len, "%30s\n", @@ -443,51 +454,51 @@ static ssize_t ath10k_read_fw_stats(struct file *file, char __user *user_buf, "================="); len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "HTT cookies queued", fw_stats->comp_queued); + "HTT cookies queued", pdev->comp_queued); len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "HTT cookies disp.", fw_stats->comp_delivered); + "HTT cookies disp.", pdev->comp_delivered); len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "MSDU queued", fw_stats->msdu_enqued); + "MSDU queued", pdev->msdu_enqued); len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "MPDU queued", fw_stats->mpdu_enqued); + "MPDU queued", pdev->mpdu_enqued); len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "MSDUs dropped", fw_stats->wmm_drop); + "MSDUs dropped", pdev->wmm_drop); len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Local enqued", fw_stats->local_enqued); + "Local enqued", pdev->local_enqued); len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Local freed", fw_stats->local_freed); + "Local freed", pdev->local_freed); len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "HW queued", fw_stats->hw_queued); + "HW queued", pdev->hw_queued); len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "PPDUs reaped", fw_stats->hw_reaped); + "PPDUs reaped", pdev->hw_reaped); len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Num underruns", fw_stats->underrun); + "Num underruns", pdev->underrun); len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "PPDUs cleaned", fw_stats->tx_abort); + "PPDUs cleaned", pdev->tx_abort); len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "MPDUs requed", fw_stats->mpdus_requed); + "MPDUs requed", pdev->mpdus_requed); len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Excessive retries", fw_stats->tx_ko); + "Excessive retries", pdev->tx_ko); len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "HW rate", fw_stats->data_rc); + "HW rate", pdev->data_rc); len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Sched self tiggers", fw_stats->self_triggers); + "Sched self tiggers", pdev->self_triggers); len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", "Dropped due to SW retries", - fw_stats->sw_retry_failure); + pdev->sw_retry_failure); len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", "Illegal rate phy errors", - fw_stats->illgl_rate_phy_err); + pdev->illgl_rate_phy_err); len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Pdev continous xretry", fw_stats->pdev_cont_xretry); + "Pdev continous xretry", pdev->pdev_cont_xretry); len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "TX timeout", fw_stats->pdev_tx_timeout); + "TX timeout", pdev->pdev_tx_timeout); len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "PDEV resets", fw_stats->pdev_resets); + "PDEV resets", pdev->pdev_resets); len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "PHY underrun", fw_stats->phy_underrun); + "PHY underrun", pdev->phy_underrun); len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "MPDU is more than txop limit", fw_stats->txop_ovf); + "MPDU is more than txop limit", pdev->txop_ovf); len += scnprintf(buf + len, buf_len - len, "\n"); len += scnprintf(buf + len, buf_len - len, "%30s\n", @@ -497,70 +508,161 @@ static ssize_t ath10k_read_fw_stats(struct file *file, char __user *user_buf, len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", "Mid PPDU route change", - fw_stats->mid_ppdu_route_change); + pdev->mid_ppdu_route_change); len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Tot. number of statuses", fw_stats->status_rcvd); + "Tot. number of statuses", pdev->status_rcvd); len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Extra frags on rings 0", fw_stats->r0_frags); + "Extra frags on rings 0", pdev->r0_frags); len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Extra frags on rings 1", fw_stats->r1_frags); + "Extra frags on rings 1", pdev->r1_frags); len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Extra frags on rings 2", fw_stats->r2_frags); + "Extra frags on rings 2", pdev->r2_frags); len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Extra frags on rings 3", fw_stats->r3_frags); + "Extra frags on rings 3", pdev->r3_frags); len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "MSDUs delivered to HTT", fw_stats->htt_msdus); + "MSDUs delivered to HTT", pdev->htt_msdus); len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "MPDUs delivered to HTT", fw_stats->htt_mpdus); + "MPDUs delivered to HTT", pdev->htt_mpdus); len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "MSDUs delivered to stack", fw_stats->loc_msdus); + "MSDUs delivered to stack", pdev->loc_msdus); len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "MPDUs delivered to stack", fw_stats->loc_mpdus); + "MPDUs delivered to stack", pdev->loc_mpdus); len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Oversized AMSUs", fw_stats->oversize_amsdu); + "Oversized AMSUs", pdev->oversize_amsdu); len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "PHY errors", fw_stats->phy_errs); + "PHY errors", pdev->phy_errs); len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "PHY errors drops", fw_stats->phy_err_drop); + "PHY errors drops", pdev->phy_err_drop); len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "MPDU errors (FCS, MIC, ENC)", fw_stats->mpdu_errs); + "MPDU errors (FCS, MIC, ENC)", pdev->mpdu_errs); len += scnprintf(buf + len, buf_len - len, "\n"); - len += scnprintf(buf + len, buf_len - len, "%30s (%d)\n", - "ath10k PEER stats", fw_stats->peers); + len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n", + "ath10k PEER stats", num_peers); len += scnprintf(buf + len, buf_len - len, "%30s\n\n", "================="); - for (i = 0; i < fw_stats->peers; i++) { + list_for_each_entry(peer, &fw_stats->peers, list) { len += scnprintf(buf + len, buf_len - len, "%30s %pM\n", - "Peer MAC address", - fw_stats->peer_stat[i].peer_macaddr); + "Peer MAC address", peer->peer_macaddr); len += scnprintf(buf + len, buf_len - len, "%30s %u\n", - "Peer RSSI", fw_stats->peer_stat[i].peer_rssi); + "Peer RSSI", peer->peer_rssi); len += scnprintf(buf + len, buf_len - len, "%30s %u\n", - "Peer TX rate", - fw_stats->peer_stat[i].peer_tx_rate); + "Peer TX rate", peer->peer_tx_rate); len += scnprintf(buf + len, buf_len - len, "%30s %u\n", - "Peer RX rate", - fw_stats->peer_stat[i].peer_rx_rate); + "Peer RX rate", peer->peer_rx_rate); len += scnprintf(buf + len, buf_len - len, "\n"); } + +unlock: spin_unlock_bh(&ar->data_lock); - if (len > buf_len) - len = buf_len; + if (len >= buf_len) + buf[len - 1] = 0; + else + buf[len] = 0; +} - ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); +static int ath10k_fw_stats_open(struct inode *inode, struct file *file) +{ + struct ath10k *ar = inode->i_private; + void *buf = NULL; + int ret; + + mutex_lock(&ar->conf_mutex); + + if (ar->state != ATH10K_STATE_ON) { + ret = -ENETDOWN; + goto err_unlock; + } + + buf = vmalloc(ATH10K_FW_STATS_BUF_SIZE); + if (!buf) { + ret = -ENOMEM; + goto err_unlock; + } + + ret = ath10k_debug_fw_stats_request(ar); + if (ret) { + ath10k_warn(ar, "failed to request fw stats: %d\n", ret); + goto err_free; + } + + ath10k_fw_stats_fill(ar, &ar->debug.fw_stats, buf); + file->private_data = buf; -exit: mutex_unlock(&ar->conf_mutex); - kfree(buf); - return ret_cnt; + return 0; + +err_free: + vfree(buf); + +err_unlock: + mutex_unlock(&ar->conf_mutex); + return ret; +} + +static int ath10k_fw_stats_release(struct inode *inode, struct file *file) +{ + vfree(file->private_data); + + return 0; +} + +static ssize_t ath10k_fw_stats_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + const char *buf = file->private_data; + unsigned int len = strlen(buf); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); } static const struct file_operations fops_fw_stats = { - .read = ath10k_read_fw_stats, + .open = ath10k_fw_stats_open, + .release = ath10k_fw_stats_release, + .read = ath10k_fw_stats_read, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + +static ssize_t ath10k_debug_fw_reset_stats_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath10k *ar = file->private_data; + int ret, len, buf_len; + char *buf; + + buf_len = 500; + buf = kmalloc(buf_len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + spin_lock_bh(&ar->data_lock); + + len = 0; + len += scnprintf(buf + len, buf_len - len, + "fw_crash_counter\t\t%d\n", ar->stats.fw_crash_counter); + len += scnprintf(buf + len, buf_len - len, + "fw_warm_reset_counter\t\t%d\n", + ar->stats.fw_warm_reset_counter); + len += scnprintf(buf + len, buf_len - len, + "fw_cold_reset_counter\t\t%d\n", + ar->stats.fw_cold_reset_counter); + + spin_unlock_bh(&ar->data_lock); + + ret = simple_read_from_buffer(user_buf, count, ppos, buf, len); + + kfree(buf); + + return ret; +} + +static const struct file_operations fops_fw_reset_stats = { .open = simple_open, + .read = ath10k_debug_fw_reset_stats_read, .owner = THIS_MODULE, .llseek = default_llseek, }; @@ -593,7 +695,8 @@ static ssize_t ath10k_read_simulate_fw_crash(struct file *file, "To simulate firmware crash write one of the keywords to this file:\n" "`soft` - this will send WMI_FORCE_FW_HANG_ASSERT to firmware if FW supports that command.\n" "`hard` - this will send to firmware command with illegal parameters causing firmware crash.\n" - "`assert` - this will send special illegal parameter to firmware to cause assert failure and crash.\n"; + "`assert` - this will send special illegal parameter to firmware to cause assert failure and crash.\n" + "`hw-restart` - this will simply queue hw restart without fw/hw actually crashing.\n"; return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); } @@ -646,6 +749,10 @@ static ssize_t ath10k_write_simulate_fw_crash(struct file *file, } else if (!strcmp(buf, "assert")) { ath10k_info(ar, "simulating firmware assert crash\n"); ret = ath10k_debug_fw_assert(ar); + } else if (!strcmp(buf, "hw-restart")) { + ath10k_info(ar, "user requested hw restart\n"); + queue_work(ar->workqueue, &ar->restart_work); + ret = 0; } else { ret = -EINVAL; goto exit; @@ -1029,6 +1136,166 @@ exit: return ret; } +/* TODO: Would be nice to always support ethtool stats, would need to + * move the stats storage out of ath10k_debug, or always have ath10k_debug + * struct available.. + */ + +/* This generally cooresponds to the debugfs fw_stats file */ +static const char ath10k_gstrings_stats[][ETH_GSTRING_LEN] = { + "tx_pkts_nic", + "tx_bytes_nic", + "rx_pkts_nic", + "rx_bytes_nic", + "d_noise_floor", + "d_cycle_count", + "d_phy_error", + "d_rts_bad", + "d_rts_good", + "d_tx_power", /* in .5 dbM I think */ + "d_rx_crc_err", /* fcs_bad */ + "d_no_beacon", + "d_tx_mpdus_queued", + "d_tx_msdu_queued", + "d_tx_msdu_dropped", + "d_local_enqued", + "d_local_freed", + "d_tx_ppdu_hw_queued", + "d_tx_ppdu_reaped", + "d_tx_fifo_underrun", + "d_tx_ppdu_abort", + "d_tx_mpdu_requed", + "d_tx_excessive_retries", + "d_tx_hw_rate", + "d_tx_dropped_sw_retries", + "d_tx_illegal_rate", + "d_tx_continuous_xretries", + "d_tx_timeout", + "d_tx_mpdu_txop_limit", + "d_pdev_resets", + "d_rx_mid_ppdu_route_change", + "d_rx_status", + "d_rx_extra_frags_ring0", + "d_rx_extra_frags_ring1", + "d_rx_extra_frags_ring2", + "d_rx_extra_frags_ring3", + "d_rx_msdu_htt", + "d_rx_mpdu_htt", + "d_rx_msdu_stack", + "d_rx_mpdu_stack", + "d_rx_phy_err", + "d_rx_phy_err_drops", + "d_rx_mpdu_errors", /* FCS, MIC, ENC */ + "d_fw_crash_count", + "d_fw_warm_reset_count", + "d_fw_cold_reset_count", +}; + +#define ATH10K_SSTATS_LEN ARRAY_SIZE(ath10k_gstrings_stats) + +void ath10k_debug_get_et_strings(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + u32 sset, u8 *data) +{ + if (sset == ETH_SS_STATS) + memcpy(data, *ath10k_gstrings_stats, + sizeof(ath10k_gstrings_stats)); +} + +int ath10k_debug_get_et_sset_count(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, int sset) +{ + if (sset == ETH_SS_STATS) + return ATH10K_SSTATS_LEN; + + return 0; +} + +void ath10k_debug_get_et_stats(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ethtool_stats *stats, u64 *data) +{ + struct ath10k *ar = hw->priv; + static const struct ath10k_fw_stats_pdev zero_stats = {}; + const struct ath10k_fw_stats_pdev *pdev_stats; + int i = 0, ret; + + mutex_lock(&ar->conf_mutex); + + if (ar->state == ATH10K_STATE_ON) { + ret = ath10k_debug_fw_stats_request(ar); + if (ret) { + /* just print a warning and try to use older results */ + ath10k_warn(ar, + "failed to get fw stats for ethtool: %d\n", + ret); + } + } + + pdev_stats = list_first_entry_or_null(&ar->debug.fw_stats.pdevs, + struct ath10k_fw_stats_pdev, + list); + if (!pdev_stats) { + /* no results available so just return zeroes */ + pdev_stats = &zero_stats; + } + + spin_lock_bh(&ar->data_lock); + + data[i++] = pdev_stats->hw_reaped; /* ppdu reaped */ + data[i++] = 0; /* tx bytes */ + data[i++] = pdev_stats->htt_mpdus; + data[i++] = 0; /* rx bytes */ + data[i++] = pdev_stats->ch_noise_floor; + data[i++] = pdev_stats->cycle_count; + data[i++] = pdev_stats->phy_err_count; + data[i++] = pdev_stats->rts_bad; + data[i++] = pdev_stats->rts_good; + data[i++] = pdev_stats->chan_tx_power; + data[i++] = pdev_stats->fcs_bad; + data[i++] = pdev_stats->no_beacons; + data[i++] = pdev_stats->mpdu_enqued; + data[i++] = pdev_stats->msdu_enqued; + data[i++] = pdev_stats->wmm_drop; + data[i++] = pdev_stats->local_enqued; + data[i++] = pdev_stats->local_freed; + data[i++] = pdev_stats->hw_queued; + data[i++] = pdev_stats->hw_reaped; + data[i++] = pdev_stats->underrun; + data[i++] = pdev_stats->tx_abort; + data[i++] = pdev_stats->mpdus_requed; + data[i++] = pdev_stats->tx_ko; + data[i++] = pdev_stats->data_rc; + data[i++] = pdev_stats->sw_retry_failure; + data[i++] = pdev_stats->illgl_rate_phy_err; + data[i++] = pdev_stats->pdev_cont_xretry; + data[i++] = pdev_stats->pdev_tx_timeout; + data[i++] = pdev_stats->txop_ovf; + data[i++] = pdev_stats->pdev_resets; + data[i++] = pdev_stats->mid_ppdu_route_change; + data[i++] = pdev_stats->status_rcvd; + data[i++] = pdev_stats->r0_frags; + data[i++] = pdev_stats->r1_frags; + data[i++] = pdev_stats->r2_frags; + data[i++] = pdev_stats->r3_frags; + data[i++] = pdev_stats->htt_msdus; + data[i++] = pdev_stats->htt_mpdus; + data[i++] = pdev_stats->loc_msdus; + data[i++] = pdev_stats->loc_mpdus; + data[i++] = pdev_stats->phy_errs; + data[i++] = pdev_stats->phy_err_drop; + data[i++] = pdev_stats->mpdu_errs; + data[i++] = ar->stats.fw_crash_counter; + data[i++] = ar->stats.fw_warm_reset_counter; + data[i++] = ar->stats.fw_cold_reset_counter; + + spin_unlock_bh(&ar->data_lock); + + mutex_unlock(&ar->conf_mutex); + + WARN_ON(i != ATH10K_SSTATS_LEN); +} + static const struct file_operations fops_fw_dbglog = { .read = ath10k_read_fw_dbglog, .write = ath10k_write_fw_dbglog, @@ -1037,6 +1304,84 @@ static const struct file_operations fops_fw_dbglog = { .llseek = default_llseek, }; +static int ath10k_debug_cal_data_open(struct inode *inode, struct file *file) +{ + struct ath10k *ar = inode->i_private; + void *buf; + u32 hi_addr; + __le32 addr; + int ret; + + mutex_lock(&ar->conf_mutex); + + if (ar->state != ATH10K_STATE_ON && + ar->state != ATH10K_STATE_UTF) { + ret = -ENETDOWN; + goto err; + } + + buf = vmalloc(QCA988X_CAL_DATA_LEN); + if (!buf) { + ret = -ENOMEM; + goto err; + } + + hi_addr = host_interest_item_address(HI_ITEM(hi_board_data)); + + ret = ath10k_hif_diag_read(ar, hi_addr, &addr, sizeof(addr)); + if (ret) { + ath10k_warn(ar, "failed to read hi_board_data address: %d\n", ret); + goto err_vfree; + } + + ret = ath10k_hif_diag_read(ar, le32_to_cpu(addr), buf, + QCA988X_CAL_DATA_LEN); + if (ret) { + ath10k_warn(ar, "failed to read calibration data: %d\n", ret); + goto err_vfree; + } + + file->private_data = buf; + + mutex_unlock(&ar->conf_mutex); + + return 0; + +err_vfree: + vfree(buf); + +err: + mutex_unlock(&ar->conf_mutex); + + return ret; +} + +static ssize_t ath10k_debug_cal_data_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + void *buf = file->private_data; + + return simple_read_from_buffer(user_buf, count, ppos, + buf, QCA988X_CAL_DATA_LEN); +} + +static int ath10k_debug_cal_data_release(struct inode *inode, + struct file *file) +{ + vfree(file->private_data); + + return 0; +} + +static const struct file_operations fops_cal_data = { + .open = ath10k_debug_cal_data_open, + .read = ath10k_debug_cal_data_read, + .release = ath10k_debug_cal_data_release, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + int ath10k_debug_start(struct ath10k *ar) { int ret; @@ -1057,7 +1402,22 @@ int ath10k_debug_start(struct ath10k *ar) ret); } - return 0; + if (ar->debug.pktlog_filter) { + ret = ath10k_wmi_pdev_pktlog_enable(ar, + ar->debug.pktlog_filter); + if (ret) + /* not serious */ + ath10k_warn(ar, + "failed to enable pktlog filter %x: %d\n", + ar->debug.pktlog_filter, ret); + } else { + ret = ath10k_wmi_pdev_pktlog_disable(ar); + if (ret) + /* not serious */ + ath10k_warn(ar, "failed to disable pktlog: %d\n", ret); + } + + return ret; } void ath10k_debug_stop(struct ath10k *ar) @@ -1072,6 +1432,8 @@ void ath10k_debug_stop(struct ath10k *ar) ar->debug.htt_max_amsdu = 0; ar->debug.htt_max_ampdu = 0; + + ath10k_wmi_pdev_pktlog_disable(ar); } static ssize_t ath10k_write_simulate_radar(struct file *file, @@ -1154,12 +1516,78 @@ static const struct file_operations fops_dfs_stats = { .llseek = default_llseek, }; +static ssize_t ath10k_write_pktlog_filter(struct file *file, + const char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct ath10k *ar = file->private_data; + u32 filter; + int ret; + + if (kstrtouint_from_user(ubuf, count, 0, &filter)) + return -EINVAL; + + mutex_lock(&ar->conf_mutex); + + if (ar->state != ATH10K_STATE_ON) { + ar->debug.pktlog_filter = filter; + ret = count; + goto out; + } + + if (filter && (filter != ar->debug.pktlog_filter)) { + ret = ath10k_wmi_pdev_pktlog_enable(ar, filter); + if (ret) { + ath10k_warn(ar, "failed to enable pktlog filter %x: %d\n", + ar->debug.pktlog_filter, ret); + goto out; + } + } else { + ret = ath10k_wmi_pdev_pktlog_disable(ar); + if (ret) { + ath10k_warn(ar, "failed to disable pktlog: %d\n", ret); + goto out; + } + } + + ar->debug.pktlog_filter = filter; + ret = count; + +out: + mutex_unlock(&ar->conf_mutex); + return ret; +} + +static ssize_t ath10k_read_pktlog_filter(struct file *file, char __user *ubuf, + size_t count, loff_t *ppos) +{ + char buf[32]; + struct ath10k *ar = file->private_data; + int len = 0; + + mutex_lock(&ar->conf_mutex); + len = scnprintf(buf, sizeof(buf) - len, "%08x\n", + ar->debug.pktlog_filter); + mutex_unlock(&ar->conf_mutex); + + return simple_read_from_buffer(ubuf, count, ppos, buf, len); +} + +static const struct file_operations fops_pktlog_filter = { + .read = ath10k_read_pktlog_filter, + .write = ath10k_write_pktlog_filter, + .open = simple_open +}; + int ath10k_debug_create(struct ath10k *ar) { ar->debug.fw_crash_data = vzalloc(sizeof(*ar->debug.fw_crash_data)); if (!ar->debug.fw_crash_data) return -ENOMEM; + INIT_LIST_HEAD(&ar->debug.fw_stats.pdevs); + INIT_LIST_HEAD(&ar->debug.fw_stats.peers); + return 0; } @@ -1167,6 +1595,8 @@ void ath10k_debug_destroy(struct ath10k *ar) { vfree(ar->debug.fw_crash_data); ar->debug.fw_crash_data = NULL; + + ath10k_debug_fw_stats_reset(ar); } int ath10k_debug_register(struct ath10k *ar) @@ -1183,11 +1613,14 @@ int ath10k_debug_register(struct ath10k *ar) INIT_DELAYED_WORK(&ar->debug.htt_stats_dwork, ath10k_debug_htt_stats_dwork); - init_completion(&ar->debug.event_stats_compl); + init_completion(&ar->debug.fw_stats_complete); debugfs_create_file("fw_stats", S_IRUSR, ar->debug.debugfs_phy, ar, &fops_fw_stats); + debugfs_create_file("fw_reset_stats", S_IRUSR, ar->debug.debugfs_phy, + ar, &fops_fw_reset_stats); + debugfs_create_file("wmi_services", S_IRUSR, ar->debug.debugfs_phy, ar, &fops_wmi_services); @@ -1210,6 +1643,9 @@ int ath10k_debug_register(struct ath10k *ar) debugfs_create_file("fw_dbglog", S_IRUSR, ar->debug.debugfs_phy, ar, &fops_fw_dbglog); + debugfs_create_file("cal_data", S_IRUSR, ar->debug.debugfs_phy, + ar, &fops_cal_data); + if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)) { debugfs_create_file("dfs_simulate_radar", S_IWUSR, ar->debug.debugfs_phy, ar, @@ -1224,6 +1660,9 @@ int ath10k_debug_register(struct ath10k *ar) &fops_dfs_stats); } + debugfs_create_file("pktlog_filter", S_IRUGO | S_IWUSR, + ar->debug.debugfs_phy, ar, &fops_pktlog_filter); + return 0; } @@ -1260,11 +1699,26 @@ void ath10k_dbg_dump(struct ath10k *ar, const char *msg, const char *prefix, const void *buf, size_t len) { + char linebuf[256]; + unsigned int linebuflen; + const void *ptr; + if (ath10k_debug_mask & mask) { if (msg) ath10k_dbg(ar, mask, "%s\n", msg); - print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len); + for (ptr = buf; (ptr - buf) < len; ptr += 16) { + linebuflen = 0; + linebuflen += scnprintf(linebuf + linebuflen, + sizeof(linebuf) - linebuflen, + "%s%08x: ", + (prefix ? prefix : ""), + (unsigned int)(ptr - buf)); + hex_dump_to_buffer(ptr, len - (ptr - buf), 16, 1, + linebuf + linebuflen, + sizeof(linebuf) - linebuflen, true); + dev_printk(KERN_DEBUG, ar->dev, "%s\n", linebuf); + } } /* tracing code doesn't like null strings :/ */ diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h index b3774f7f492c..0c934a8378db 100644 --- a/drivers/net/wireless/ath/ath10k/debug.h +++ b/drivers/net/wireless/ath/ath10k/debug.h @@ -38,11 +38,20 @@ enum ath10k_debug_mask { ATH10K_DBG_ANY = 0xffffffff, }; +enum ath10k_pktlog_filter { + ATH10K_PKTLOG_RX = 0x000000001, + ATH10K_PKTLOG_TX = 0x000000002, + ATH10K_PKTLOG_RCFIND = 0x000000004, + ATH10K_PKTLOG_RCUPDATE = 0x000000008, + ATH10K_PKTLOG_DBG_PRINT = 0x000000010, + ATH10K_PKTLOG_ANY = 0x00000001f, +}; + extern unsigned int ath10k_debug_mask; -__printf(2, 3) int ath10k_info(struct ath10k *ar, const char *fmt, ...); -__printf(2, 3) int ath10k_err(struct ath10k *ar, const char *fmt, ...); -__printf(2, 3) int ath10k_warn(struct ath10k *ar, const char *fmt, ...); +__printf(2, 3) void ath10k_info(struct ath10k *ar, const char *fmt, ...); +__printf(2, 3) void ath10k_err(struct ath10k *ar, const char *fmt, ...); +__printf(2, 3) void ath10k_warn(struct ath10k *ar, const char *fmt, ...); void ath10k_print_driver_info(struct ath10k *ar); #ifdef CONFIG_ATH10K_DEBUGFS @@ -53,17 +62,24 @@ void ath10k_debug_destroy(struct ath10k *ar); int ath10k_debug_register(struct ath10k *ar); void ath10k_debug_unregister(struct ath10k *ar); void ath10k_debug_read_service_map(struct ath10k *ar, - void *service_map, + const void *service_map, size_t map_size); -void ath10k_debug_read_target_stats(struct ath10k *ar, - struct wmi_stats_event *ev); +void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb); struct ath10k_fw_crash_data * ath10k_debug_get_new_fw_crash_data(struct ath10k *ar); void ath10k_debug_dbglog_add(struct ath10k *ar, u8 *buffer, int len); - #define ATH10K_DFS_STAT_INC(ar, c) (ar->debug.dfs_stats.c++) +void ath10k_debug_get_et_strings(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + u32 sset, u8 *data); +int ath10k_debug_get_et_sset_count(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, int sset); +void ath10k_debug_get_et_stats(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ethtool_stats *stats, u64 *data); + #else static inline int ath10k_debug_start(struct ath10k *ar) { @@ -93,13 +109,13 @@ static inline void ath10k_debug_unregister(struct ath10k *ar) } static inline void ath10k_debug_read_service_map(struct ath10k *ar, - void *service_map, + const void *service_map, size_t map_size) { } -static inline void ath10k_debug_read_target_stats(struct ath10k *ar, - struct wmi_stats_event *ev) +static inline void ath10k_debug_fw_stats_process(struct ath10k *ar, + struct sk_buff *skb) { } @@ -116,6 +132,10 @@ ath10k_debug_get_new_fw_crash_data(struct ath10k *ar) #define ATH10K_DFS_STAT_INC(ar, c) do { } while (0) +#define ath10k_debug_get_et_strings NULL +#define ath10k_debug_get_et_sset_count NULL +#define ath10k_debug_get_et_stats NULL + #endif /* CONFIG_ATH10K_DEBUGFS */ #ifdef CONFIG_ATH10K_DEBUG diff --git a/drivers/net/wireless/ath/ath10k/hif.h b/drivers/net/wireless/ath/ath10k/hif.h index 62323fea27e1..30301f5b6051 100644 --- a/drivers/net/wireless/ath/ath10k/hif.h +++ b/drivers/net/wireless/ath/ath10k/hif.h @@ -43,6 +43,10 @@ struct ath10k_hif_ops { int (*tx_sg)(struct ath10k *ar, u8 pipe_id, struct ath10k_hif_sg_item *items, int n_items); + /* read firmware memory through the diagnose interface */ + int (*diag_read)(struct ath10k *ar, u32 address, void *buf, + size_t buf_len); + /* * API to handle HIF-specific BMI message exchanges, this API is * synchronous and only allowed to be called from a context that @@ -98,6 +102,12 @@ static inline int ath10k_hif_tx_sg(struct ath10k *ar, u8 pipe_id, return ar->hif.ops->tx_sg(ar, pipe_id, items, n_items); } +static inline int ath10k_hif_diag_read(struct ath10k *ar, u32 address, void *buf, + size_t buf_len) +{ + return ar->hif.ops->diag_read(ar, address, buf, buf_len); +} + static inline int ath10k_hif_exchange_bmi_msg(struct ath10k *ar, void *request, u32 request_len, void *response, u32 *response_len) diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 3b44217a6c19..15c58e884b6a 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -725,7 +725,7 @@ static inline u8 *htt_rx_test_get_chars(struct htt_rx_test *rx_test) */ struct htt_pktlog_msg { u8 pad[3]; - __le32 payload[1 /* or more */]; + u8 payload[0]; } __packed; struct htt_dbg_stats_rx_reorder_stats { diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 60d40a04508b..52c630672718 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -291,6 +291,13 @@ static inline struct sk_buff *ath10k_htt_rx_netbuf_pop(struct ath10k_htt *htt) htt->rx_ring.sw_rd_idx.msdu_payld = idx; htt->rx_ring.fill_cnt--; + dma_unmap_single(htt->ar->dev, + ATH10K_SKB_CB(msdu)->paddr, + msdu->len + skb_tailroom(msdu), + DMA_FROM_DEVICE); + ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt rx netbuf pop: ", + msdu->data, msdu->len + skb_tailroom(msdu)); + return msdu; } @@ -328,14 +335,6 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, while (msdu) { int last_msdu, msdu_len_invalid, msdu_chained; - dma_unmap_single(htt->ar->dev, - ATH10K_SKB_CB(msdu)->paddr, - msdu->len + skb_tailroom(msdu), - DMA_FROM_DEVICE); - - ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt rx pop: ", - msdu->data, msdu->len + skb_tailroom(msdu)); - rx_desc = (struct htt_rx_desc *)msdu->data; /* FIXME: we must report msdu payload since this is what caller @@ -426,14 +425,14 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, while (msdu_chained--) { struct sk_buff *next = ath10k_htt_rx_netbuf_pop(htt); - dma_unmap_single(htt->ar->dev, - ATH10K_SKB_CB(next)->paddr, - next->len + skb_tailroom(next), - DMA_FROM_DEVICE); - - ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, - "htt rx chained: ", next->data, - next->len + skb_tailroom(next)); + if (!next) { + ath10k_warn(ar, "failed to pop chained msdu\n"); + ath10k_htt_rx_free_msdu_chain(*head_msdu); + *head_msdu = NULL; + msdu = NULL; + htt->rx_confused = true; + break; + } skb_trim(next, 0); skb_put(next, min(msdu_len, HTT_RX_BUF_SIZE)); @@ -447,6 +446,8 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, last_msdu = __le32_to_cpu(rx_desc->msdu_end.info0) & RX_MSDU_END_INFO0_LAST_MSDU; + trace_ath10k_htt_rx_desc(ar, &rx_desc->attention, + sizeof(*rx_desc) - sizeof(u32)); if (last_msdu) { msdu->next = NULL; break; @@ -492,6 +493,8 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt) size_t size; struct timer_list *timer = &htt->rx_ring.refill_retry_timer; + htt->rx_confused = false; + htt->rx_ring.size = ath10k_htt_rx_ring_size(htt); if (!is_power_of_2(htt->rx_ring.size)) { ath10k_warn(ar, "htt rx ring size is not power of 2\n"); @@ -581,41 +584,47 @@ static int ath10k_htt_rx_crypto_param_len(struct ath10k *ar, enum htt_rx_mpdu_encrypt_type type) { switch (type) { + case HTT_RX_MPDU_ENCRYPT_NONE: + return 0; case HTT_RX_MPDU_ENCRYPT_WEP40: case HTT_RX_MPDU_ENCRYPT_WEP104: - return 4; + return IEEE80211_WEP_IV_LEN; case HTT_RX_MPDU_ENCRYPT_TKIP_WITHOUT_MIC: - case HTT_RX_MPDU_ENCRYPT_WEP128: /* not tested */ case HTT_RX_MPDU_ENCRYPT_TKIP_WPA: - case HTT_RX_MPDU_ENCRYPT_WAPI: /* not tested */ + return IEEE80211_TKIP_IV_LEN; case HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2: - return 8; - case HTT_RX_MPDU_ENCRYPT_NONE: - return 0; + return IEEE80211_CCMP_HDR_LEN; + case HTT_RX_MPDU_ENCRYPT_WEP128: + case HTT_RX_MPDU_ENCRYPT_WAPI: + break; } - ath10k_warn(ar, "unknown encryption type %d\n", type); + ath10k_warn(ar, "unsupported encryption type %d\n", type); return 0; } +#define MICHAEL_MIC_LEN 8 + static int ath10k_htt_rx_crypto_tail_len(struct ath10k *ar, enum htt_rx_mpdu_encrypt_type type) { switch (type) { case HTT_RX_MPDU_ENCRYPT_NONE: + return 0; case HTT_RX_MPDU_ENCRYPT_WEP40: case HTT_RX_MPDU_ENCRYPT_WEP104: - case HTT_RX_MPDU_ENCRYPT_WEP128: - case HTT_RX_MPDU_ENCRYPT_WAPI: - return 0; + return IEEE80211_WEP_ICV_LEN; case HTT_RX_MPDU_ENCRYPT_TKIP_WITHOUT_MIC: case HTT_RX_MPDU_ENCRYPT_TKIP_WPA: - return 4; + return IEEE80211_TKIP_ICV_LEN; case HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2: - return 8; + return IEEE80211_CCMP_MIC_LEN; + case HTT_RX_MPDU_ENCRYPT_WEP128: + case HTT_RX_MPDU_ENCRYPT_WAPI: + break; } - ath10k_warn(ar, "unknown encryption type %d\n", type); + ath10k_warn(ar, "unsupported encryption type %d\n", type); return 0; } @@ -892,6 +901,8 @@ static void ath10k_process_rx(struct ath10k *ar, !!(status->flag & RX_FLAG_AMSDU_MORE)); ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "rx skb: ", skb->data, skb->len); + trace_ath10k_rx_hdr(ar, skb->data, skb->len); + trace_ath10k_rx_payload(ar, skb->data, skb->len); ieee80211_rx(ar->hw, skb); } @@ -1169,7 +1180,6 @@ static int ath10k_unchain_msdu(struct sk_buff *msdu_head) static bool ath10k_htt_rx_amsdu_allowed(struct ath10k_htt *htt, struct sk_buff *head, - enum htt_rx_mpdu_status status, bool channel_set, u32 attention) { @@ -1193,22 +1203,11 @@ static bool ath10k_htt_rx_amsdu_allowed(struct ath10k_htt *htt, } /* Skip mgmt frames while we handle this in WMI */ - if (status == HTT_RX_IND_MPDU_STATUS_MGMT_CTRL || - attention & RX_ATTENTION_FLAGS_MGMT_TYPE) { + if (attention & RX_ATTENTION_FLAGS_MGMT_TYPE) { ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx mgmt ctrl\n"); return false; } - if (status != HTT_RX_IND_MPDU_STATUS_OK && - status != HTT_RX_IND_MPDU_STATUS_TKIP_MIC_ERR && - status != HTT_RX_IND_MPDU_STATUS_ERR_INV_PEER && - !htt->ar->monitor_started) { - ath10k_dbg(ar, ATH10K_DBG_HTT, - "htt rx ignoring frame w/ status %d\n", - status); - return false; - } - if (test_bit(ATH10K_CAC_RUNNING, &htt->ar->dev_flags)) { ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx CAC running\n"); @@ -1224,8 +1223,6 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, struct ath10k *ar = htt->ar; struct ieee80211_rx_status *rx_status = &htt->rx_status; struct htt_rx_indication_mpdu_range *mpdu_ranges; - struct htt_rx_desc *rxd; - enum htt_rx_mpdu_status status; struct ieee80211_hdr *hdr; int num_mpdu_ranges; u32 attention; @@ -1273,8 +1270,6 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, num_mpdu_ranges)); for (i = 0; i < num_mpdu_ranges; i++) { - status = mpdu_ranges[i].mpdu_range_status; - for (j = 0; j < mpdu_ranges[i].mpdu_count; j++) { struct sk_buff *msdu_head, *msdu_tail; @@ -1295,12 +1290,7 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, continue; } - rxd = container_of((void *)msdu_head->data, - struct htt_rx_desc, - msdu_payload); - if (!ath10k_htt_rx_amsdu_allowed(htt, msdu_head, - status, channel_set, attention)) { ath10k_htt_rx_free_msdu_chain(msdu_head); @@ -1365,6 +1355,8 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt, &attention); spin_unlock_bh(&htt->rx_ring.lock); + tasklet_schedule(&htt->rx_replenish_task); + ath10k_dbg(ar, ATH10K_DBG_HTT_DUMP, "htt rx frag ahead\n"); if (ret) { @@ -1426,7 +1418,7 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt, /* last fragment of TKIP frags has MIC */ if (!ieee80211_has_morefrags(hdr->frame_control) && enctype == HTT_RX_MPDU_ENCRYPT_TKIP_WPA) - trim += 8; + trim += MICHAEL_MIC_LEN; if (trim > msdu_head->len) { ath10k_warn(ar, "htt rx fragment: trailer longer than the frame itself? drop\n"); @@ -1674,6 +1666,15 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) case HTT_T2H_MSG_TYPE_RX_DELBA: ath10k_htt_rx_delba(ar, resp); break; + case HTT_T2H_MSG_TYPE_PKTLOG: { + struct ath10k_pktlog_hdr *hdr = + (struct ath10k_pktlog_hdr *)resp->pktlog_msg.payload; + + trace_ath10k_htt_pktlog(ar, resp->pktlog_msg.payload, + sizeof(*hdr) + + __le16_to_cpu(hdr->size)); + break; + } case HTT_T2H_MSG_TYPE_RX_FLUSH: { /* Ignore this event because mac80211 takes care of Rx * aggregation reordering. @@ -1681,8 +1682,8 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) break; } default: - ath10k_dbg(ar, ATH10K_DBG_HTT, "htt event (%d) not handled\n", - resp->hdr.msg_type); + ath10k_warn(ar, "htt event (%d) not handled\n", + resp->hdr.msg_type); ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt event: ", skb->data, skb->len); break; diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index bd87a35201d8..5b7e42f7377c 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -92,7 +92,6 @@ int ath10k_htt_tx_alloc(struct ath10k_htt *htt) struct ath10k *ar = htt->ar; spin_lock_init(&htt->tx_lock); - init_waitqueue_head(&htt->empty_tx_wq); if (test_bit(ATH10K_FW_FEATURE_WMI_10X, htt->ar->fw_features)) htt->max_num_pending_tx = TARGET_10X_NUM_MSDU_DESC; @@ -557,12 +556,15 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) skb_cb->htt.txbuf->cmd_tx.frags_paddr = __cpu_to_le32(frags_paddr); skb_cb->htt.txbuf->cmd_tx.peerid = __cpu_to_le32(HTT_INVALID_PEERID); + trace_ath10k_htt_tx(ar, msdu_id, msdu->len, vdev_id, tid); ath10k_dbg(ar, ATH10K_DBG_HTT, "htt tx flags0 %hhu flags1 %hu len %d id %hu frags_paddr %08x, msdu_paddr %08x vdev %hhu tid %hhu\n", flags0, flags1, msdu->len, msdu_id, frags_paddr, (u32)skb_cb->paddr, vdev_id, tid); ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt tx msdu: ", msdu->data, msdu->len); + trace_ath10k_tx_hdr(ar, msdu->data, msdu->len); + trace_ath10k_tx_payload(ar, msdu->data, msdu->len); sg_items[0].transfer_id = 0; sg_items[0].transfer_context = NULL; diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 3cf5702c1e7e..392c2501d0a1 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -20,15 +20,16 @@ #include "targaddrs.h" +#define ATH10K_FW_DIR "ath10k" + /* QCA988X 1.0 definitions (unsupported) */ #define QCA988X_HW_1_0_CHIP_ID_REV 0x0 /* QCA988X 2.0 definitions */ #define QCA988X_HW_2_0_VERSION 0x4100016c #define QCA988X_HW_2_0_CHIP_ID_REV 0x2 -#define QCA988X_HW_2_0_FW_DIR "ath10k/QCA988X/hw2.0" +#define QCA988X_HW_2_0_FW_DIR ATH10K_FW_DIR "/QCA988X/hw2.0" #define QCA988X_HW_2_0_FW_FILE "firmware.bin" -#define QCA988X_HW_2_0_FW_3_FILE "firmware-3.bin" #define QCA988X_HW_2_0_OTP_FILE "otp.bin" #define QCA988X_HW_2_0_BOARD_DATA_FILE "board.bin" #define QCA988X_HW_2_0_PATCH_LOAD_ADDR 0x1234 @@ -43,6 +44,8 @@ #define REG_DUMP_COUNT_QCA988X 60 +#define QCA988X_CAL_DATA_LEN 2116 + struct ath10k_fw_ie { __le32 id; __le32 len; @@ -78,6 +81,15 @@ enum ath10k_mcast2ucast_mode { ATH10K_MCAST2UCAST_ENABLED = 1, }; +struct ath10k_pktlog_hdr { + __le16 flags; + __le16 missed_cnt; + __le16 log_type; + __le16 size; + __le32 timestamp; + u8 payload[0]; +} __packed; + /* Target specific defines for MAIN firmware */ #define TARGET_NUM_VDEVS 8 #define TARGET_NUM_PEER_AST 2 @@ -279,6 +291,7 @@ enum ath10k_mcast2ucast_mode { #define SI_RX_DATA1_OFFSET 0x00000014 #define CORE_CTRL_CPU_INTR_MASK 0x00002000 +#define CORE_CTRL_PCIE_REG_31_MASK 0x00000800 #define CORE_CTRL_ADDRESS 0x0000 #define PCIE_INTR_ENABLE_ADDRESS 0x0008 #define PCIE_INTR_CAUSE_ADDRESS 0x000c diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 46709301a51e..1245ac8c5c6f 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -479,12 +479,49 @@ static void ath10k_peer_cleanup_all(struct ath10k *ar) /* Interface management */ /************************/ +void ath10k_mac_vif_beacon_free(struct ath10k_vif *arvif) +{ + struct ath10k *ar = arvif->ar; + + lockdep_assert_held(&ar->data_lock); + + if (!arvif->beacon) + return; + + if (!arvif->beacon_buf) + dma_unmap_single(ar->dev, ATH10K_SKB_CB(arvif->beacon)->paddr, + arvif->beacon->len, DMA_TO_DEVICE); + + dev_kfree_skb_any(arvif->beacon); + + arvif->beacon = NULL; + arvif->beacon_sent = false; +} + +static void ath10k_mac_vif_beacon_cleanup(struct ath10k_vif *arvif) +{ + struct ath10k *ar = arvif->ar; + + lockdep_assert_held(&ar->data_lock); + + ath10k_mac_vif_beacon_free(arvif); + + if (arvif->beacon_buf) { + dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN, + arvif->beacon_buf, arvif->beacon_paddr); + arvif->beacon_buf = NULL; + } +} + static inline int ath10k_vdev_setup_sync(struct ath10k *ar) { int ret; lockdep_assert_held(&ar->conf_mutex); + if (test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags)) + return -ESHUTDOWN; + ret = wait_for_completion_timeout(&ar->vdev_setup_done, ATH10K_VDEV_SETUP_TIMEOUT_HZ); if (ret == 0) @@ -517,6 +554,8 @@ static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id) arg.channel.max_reg_power = channel->max_reg_power * 2; arg.channel.max_antenna_gain = channel->max_antenna_gain * 2; + reinit_completion(&ar->vdev_setup_done); + ret = ath10k_wmi_vdev_start(ar, &arg); if (ret) { ath10k_warn(ar, "failed to request monitor vdev %i start: %d\n", @@ -564,6 +603,8 @@ static int ath10k_monitor_vdev_stop(struct ath10k *ar) ath10k_warn(ar, "failed to put down monitor vdev %i: %d\n", ar->monitor_vdev_id, ret); + reinit_completion(&ar->vdev_setup_done); + ret = ath10k_wmi_vdev_stop(ar, ar->monitor_vdev_id); if (ret) ath10k_warn(ar, "failed to to request monitor vdev %i stop: %d\n", @@ -590,9 +631,9 @@ static int ath10k_monitor_vdev_create(struct ath10k *ar) return -ENOMEM; } - bit = ffs(ar->free_vdev_map); + bit = __ffs64(ar->free_vdev_map); - ar->monitor_vdev_id = bit - 1; + ar->monitor_vdev_id = bit; ret = ath10k_wmi_vdev_create(ar, ar->monitor_vdev_id, WMI_VDEV_TYPE_MONITOR, @@ -603,7 +644,7 @@ static int ath10k_monitor_vdev_create(struct ath10k *ar) return ret; } - ar->free_vdev_map &= ~(1 << ar->monitor_vdev_id); + ar->free_vdev_map &= ~(1LL << ar->monitor_vdev_id); ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor vdev %d created\n", ar->monitor_vdev_id); @@ -623,7 +664,7 @@ static int ath10k_monitor_vdev_delete(struct ath10k *ar) return ret; } - ar->free_vdev_map |= 1 << ar->monitor_vdev_id; + ar->free_vdev_map |= 1LL << ar->monitor_vdev_id; ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor vdev %d deleted\n", ar->monitor_vdev_id); @@ -909,15 +950,7 @@ static void ath10k_control_beaconing(struct ath10k_vif *arvif, arvif->is_up = false; spin_lock_bh(&arvif->ar->data_lock); - if (arvif->beacon) { - dma_unmap_single(arvif->ar->dev, - ATH10K_SKB_CB(arvif->beacon)->paddr, - arvif->beacon->len, DMA_TO_DEVICE); - dev_kfree_skb_any(arvif->beacon); - - arvif->beacon = NULL; - arvif->beacon_sent = false; - } + ath10k_mac_vif_beacon_free(arvif); spin_unlock_bh(&arvif->ar->data_lock); return; @@ -966,14 +999,6 @@ static void ath10k_control_ibss(struct ath10k_vif *arvif, if (is_zero_ether_addr(arvif->bssid)) return; - ret = ath10k_peer_delete(arvif->ar, arvif->vdev_id, - arvif->bssid); - if (ret) { - ath10k_warn(ar, "failed to delete IBSS BSSID peer %pM for vdev %d: %d\n", - arvif->bssid, arvif->vdev_id, ret); - return; - } - memset(arvif->bssid, 0, ETH_ALEN); return; @@ -1042,51 +1067,45 @@ static int ath10k_mac_vif_setup_ps(struct ath10k_vif *arvif) /* Station management */ /**********************/ +static u32 ath10k_peer_assoc_h_listen_intval(struct ath10k *ar, + struct ieee80211_vif *vif) +{ + /* Some firmware revisions have unstable STA powersave when listen + * interval is set too high (e.g. 5). The symptoms are firmware doesn't + * generate NullFunc frames properly even if buffered frames have been + * indicated in Beacon TIM. Firmware would seldom wake up to pull + * buffered frames. Often pinging the device from AP would simply fail. + * + * As a workaround set it to 1. + */ + if (vif->type == NL80211_IFTYPE_STATION) + return 1; + + return ar->hw->conf.listen_interval; +} + static void ath10k_peer_assoc_h_basic(struct ath10k *ar, - struct ath10k_vif *arvif, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct ieee80211_bss_conf *bss_conf, struct wmi_peer_assoc_complete_arg *arg) { + struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + lockdep_assert_held(&ar->conf_mutex); ether_addr_copy(arg->addr, sta->addr); arg->vdev_id = arvif->vdev_id; arg->peer_aid = sta->aid; arg->peer_flags |= WMI_PEER_AUTH; - - if (arvif->vdev_type == WMI_VDEV_TYPE_STA) - /* - * Seems FW have problems with Power Save in STA - * mode when we setup this parameter to high (eg. 5). - * Often we see that FW don't send NULL (with clean P flags) - * frame even there is info about buffered frames in beacons. - * Sometimes we have to wait more than 10 seconds before FW - * will wakeup. Often sending one ping from AP to our device - * just fail (more than 50%). - * - * Seems setting this FW parameter to 1 couse FW - * will check every beacon and will wakup immediately - * after detection buffered data. - */ - arg->peer_listen_intval = 1; - else - arg->peer_listen_intval = ar->hw->conf.listen_interval; - + arg->peer_listen_intval = ath10k_peer_assoc_h_listen_intval(ar, vif); arg->peer_num_spatial_streams = 1; - - /* - * The assoc capabilities are available only in managed mode. - */ - if (arvif->vdev_type == WMI_VDEV_TYPE_STA && bss_conf) - arg->peer_caps = bss_conf->assoc_capability; + arg->peer_caps = vif->bss_conf.assoc_capability; } static void ath10k_peer_assoc_h_crypto(struct ath10k *ar, - struct ath10k_vif *arvif, + struct ieee80211_vif *vif, struct wmi_peer_assoc_complete_arg *arg) { - struct ieee80211_vif *vif = arvif->vif; struct ieee80211_bss_conf *info = &vif->bss_conf; struct cfg80211_bss *bss; const u8 *rsnie = NULL; @@ -1343,11 +1362,12 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar, } static void ath10k_peer_assoc_h_qos(struct ath10k *ar, - struct ath10k_vif *arvif, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct ieee80211_bss_conf *bss_conf, struct wmi_peer_assoc_complete_arg *arg) { + struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + switch (arvif->vdev_type) { case WMI_VDEV_TYPE_AP: if (sta->wme) @@ -1359,7 +1379,7 @@ static void ath10k_peer_assoc_h_qos(struct ath10k *ar, } break; case WMI_VDEV_TYPE_STA: - if (bss_conf->qos) + if (vif->bss_conf.qos) arg->peer_flags |= WMI_PEER_QOS; break; default: @@ -1368,7 +1388,7 @@ static void ath10k_peer_assoc_h_qos(struct ath10k *ar, } static void ath10k_peer_assoc_h_phymode(struct ath10k *ar, - struct ath10k_vif *arvif, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct wmi_peer_assoc_complete_arg *arg) { @@ -1419,22 +1439,21 @@ static void ath10k_peer_assoc_h_phymode(struct ath10k *ar, } static int ath10k_peer_assoc_prepare(struct ath10k *ar, - struct ath10k_vif *arvif, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct ieee80211_bss_conf *bss_conf, struct wmi_peer_assoc_complete_arg *arg) { lockdep_assert_held(&ar->conf_mutex); memset(arg, 0, sizeof(*arg)); - ath10k_peer_assoc_h_basic(ar, arvif, sta, bss_conf, arg); - ath10k_peer_assoc_h_crypto(ar, arvif, arg); + ath10k_peer_assoc_h_basic(ar, vif, sta, arg); + ath10k_peer_assoc_h_crypto(ar, vif, arg); ath10k_peer_assoc_h_rates(ar, sta, arg); ath10k_peer_assoc_h_ht(ar, sta, arg); ath10k_peer_assoc_h_vht(ar, sta, arg); - ath10k_peer_assoc_h_qos(ar, arvif, sta, bss_conf, arg); - ath10k_peer_assoc_h_phymode(ar, arvif, sta, arg); + ath10k_peer_assoc_h_qos(ar, vif, sta, arg); + ath10k_peer_assoc_h_phymode(ar, vif, sta, arg); return 0; } @@ -1480,6 +1499,9 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw, lockdep_assert_held(&ar->conf_mutex); + ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %i assoc bssid %pM aid %d\n", + arvif->vdev_id, arvif->bssid, arvif->aid); + rcu_read_lock(); ap_sta = ieee80211_find_sta(vif, bss_conf->bssid); @@ -1494,8 +1516,7 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw, * before calling ath10k_setup_peer_smps() which might sleep. */ ht_cap = ap_sta->ht_cap; - ret = ath10k_peer_assoc_prepare(ar, arvif, ap_sta, - bss_conf, &peer_arg); + ret = ath10k_peer_assoc_prepare(ar, vif, ap_sta, &peer_arg); if (ret) { ath10k_warn(ar, "failed to prepare peer assoc for %pM vdev %i: %d\n", bss_conf->bssid, arvif->vdev_id, ret); @@ -1523,6 +1544,8 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw, "mac vdev %d up (associated) bssid %pM aid %d\n", arvif->vdev_id, bss_conf->bssid, bss_conf->aid); + WARN_ON(arvif->is_up); + arvif->aid = bss_conf->aid; ether_addr_copy(arvif->bssid, bss_conf->bssid); @@ -1536,9 +1559,6 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw, arvif->is_up = true; } -/* - * FIXME: flush TIDs - */ static void ath10k_bss_disassoc(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { @@ -1548,45 +1568,30 @@ static void ath10k_bss_disassoc(struct ieee80211_hw *hw, lockdep_assert_held(&ar->conf_mutex); - /* - * For some reason, calling VDEV-DOWN before VDEV-STOP - * makes the FW to send frames via HTT after disassociation. - * No idea why this happens, even though VDEV-DOWN is supposed - * to be analogous to link down, so just stop the VDEV. - */ - ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d stop (disassociated\n", - arvif->vdev_id); - - /* FIXME: check return value */ - ret = ath10k_vdev_stop(arvif); + ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %i disassoc bssid %pM\n", + arvif->vdev_id, arvif->bssid); - /* - * If we don't call VDEV-DOWN after VDEV-STOP FW will remain active and - * report beacons from previously associated network through HTT. - * This in turn would spam mac80211 WARN_ON if we bring down all - * interfaces as it expects there is no rx when no interface is - * running. - */ - ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d down\n", arvif->vdev_id); - - /* FIXME: why don't we print error if wmi call fails? */ ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id); + if (ret) + ath10k_warn(ar, "faield to down vdev %i: %d\n", + arvif->vdev_id, ret); arvif->def_wep_key_idx = 0; - - arvif->is_started = false; arvif->is_up = false; } -static int ath10k_station_assoc(struct ath10k *ar, struct ath10k_vif *arvif, - struct ieee80211_sta *sta, bool reassoc) +static int ath10k_station_assoc(struct ath10k *ar, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + bool reassoc) { + struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); struct wmi_peer_assoc_complete_arg peer_arg; int ret = 0; lockdep_assert_held(&ar->conf_mutex); - ret = ath10k_peer_assoc_prepare(ar, arvif, sta, NULL, &peer_arg); + ret = ath10k_peer_assoc_prepare(ar, vif, sta, &peer_arg); if (ret) { ath10k_warn(ar, "failed to prepare WMI peer assoc for %pM vdev %i: %i\n", sta->addr, arvif->vdev_id, ret); @@ -1601,43 +1606,51 @@ static int ath10k_station_assoc(struct ath10k *ar, struct ath10k_vif *arvif, return ret; } - ret = ath10k_setup_peer_smps(ar, arvif, sta->addr, &sta->ht_cap); - if (ret) { - ath10k_warn(ar, "failed to setup peer SMPS for vdev %d: %d\n", - arvif->vdev_id, ret); - return ret; - } - - if (!sta->wme && !reassoc) { - arvif->num_legacy_stations++; - ret = ath10k_recalc_rtscts_prot(arvif); + /* Re-assoc is run only to update supported rates for given station. It + * doesn't make much sense to reconfigure the peer completely. + */ + if (!reassoc) { + ret = ath10k_setup_peer_smps(ar, arvif, sta->addr, + &sta->ht_cap); if (ret) { - ath10k_warn(ar, "failed to recalculate rts/cts prot for vdev %d: %d\n", + ath10k_warn(ar, "failed to setup peer SMPS for vdev %d: %d\n", arvif->vdev_id, ret); return ret; } - } - ret = ath10k_install_peer_wep_keys(arvif, sta->addr); - if (ret) { - ath10k_warn(ar, "failed to install peer wep keys for vdev %i: %d\n", - arvif->vdev_id, ret); - return ret; - } + ret = ath10k_peer_assoc_qos_ap(ar, arvif, sta); + if (ret) { + ath10k_warn(ar, "failed to set qos params for STA %pM for vdev %i: %d\n", + sta->addr, arvif->vdev_id, ret); + return ret; + } - ret = ath10k_peer_assoc_qos_ap(ar, arvif, sta); - if (ret) { - ath10k_warn(ar, "failed to set qos params for STA %pM for vdev %i: %d\n", - sta->addr, arvif->vdev_id, ret); - return ret; + if (!sta->wme) { + arvif->num_legacy_stations++; + ret = ath10k_recalc_rtscts_prot(arvif); + if (ret) { + ath10k_warn(ar, "failed to recalculate rts/cts prot for vdev %d: %d\n", + arvif->vdev_id, ret); + return ret; + } + } + + ret = ath10k_install_peer_wep_keys(arvif, sta->addr); + if (ret) { + ath10k_warn(ar, "failed to install peer wep keys for vdev %i: %d\n", + arvif->vdev_id, ret); + return ret; + } } return ret; } -static int ath10k_station_disassoc(struct ath10k *ar, struct ath10k_vif *arvif, +static int ath10k_station_disassoc(struct ath10k *ar, + struct ieee80211_vif *vif, struct ieee80211_sta *sta) { + struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); int ret = 0; lockdep_assert_held(&ar->conf_mutex); @@ -1729,6 +1742,7 @@ static int ath10k_update_channel_list(struct ath10k *ar) ch->passive = passive; ch->freq = channel->center_freq; + ch->band_center_freq1 = channel->center_freq; ch->min_power = 0; ch->max_power = channel->max_power * 2; ch->max_reg_power = channel->max_reg_power * 2; @@ -2343,7 +2357,7 @@ static void ath10k_tx(struct ieee80211_hw *hw, } /* Must not be called with conf_mutex held as workers can use that also. */ -static void ath10k_drain_tx(struct ath10k *ar) +void ath10k_drain_tx(struct ath10k *ar) { /* make sure rcu-protected mac80211 tx path itself is drained */ synchronize_net(); @@ -2376,16 +2390,8 @@ void ath10k_halt(struct ath10k *ar) ath10k_hif_power_down(ar); spin_lock_bh(&ar->data_lock); - list_for_each_entry(arvif, &ar->arvifs, list) { - if (!arvif->beacon) - continue; - - dma_unmap_single(arvif->ar->dev, - ATH10K_SKB_CB(arvif->beacon)->paddr, - arvif->beacon->len, DMA_TO_DEVICE); - dev_kfree_skb_any(arvif->beacon); - arvif->beacon = NULL; - } + list_for_each_entry(arvif, &ar->arvifs, list) + ath10k_mac_vif_beacon_cleanup(arvif); spin_unlock_bh(&ar->data_lock); } @@ -2677,12 +2683,68 @@ static void ath10k_config_chan(struct ath10k *ar) ath10k_monitor_recalc(ar); } +static int ath10k_mac_txpower_setup(struct ath10k *ar, int txpower) +{ + int ret; + u32 param; + + lockdep_assert_held(&ar->conf_mutex); + + ath10k_dbg(ar, ATH10K_DBG_MAC, "mac txpower %d\n", txpower); + + param = ar->wmi.pdev_param->txpower_limit2g; + ret = ath10k_wmi_pdev_set_param(ar, param, txpower * 2); + if (ret) { + ath10k_warn(ar, "failed to set 2g txpower %d: %d\n", + txpower, ret); + return ret; + } + + param = ar->wmi.pdev_param->txpower_limit5g; + ret = ath10k_wmi_pdev_set_param(ar, param, txpower * 2); + if (ret) { + ath10k_warn(ar, "failed to set 5g txpower %d: %d\n", + txpower, ret); + return ret; + } + + return 0; +} + +static int ath10k_mac_txpower_recalc(struct ath10k *ar) +{ + struct ath10k_vif *arvif; + int ret, txpower = -1; + + lockdep_assert_held(&ar->conf_mutex); + + list_for_each_entry(arvif, &ar->arvifs, list) { + WARN_ON(arvif->txpower < 0); + + if (txpower == -1) + txpower = arvif->txpower; + else + txpower = min(txpower, arvif->txpower); + } + + if (WARN_ON(txpower == -1)) + return -EINVAL; + + ret = ath10k_mac_txpower_setup(ar, txpower); + if (ret) { + ath10k_warn(ar, "failed to setup tx power %d: %d\n", + txpower, ret); + return ret; + } + + return 0; +} + static int ath10k_config(struct ieee80211_hw *hw, u32 changed) { struct ath10k *ar = hw->priv; struct ieee80211_conf *conf = &hw->conf; int ret = 0; - u32 param; mutex_lock(&ar->conf_mutex); @@ -2706,25 +2768,6 @@ static int ath10k_config(struct ieee80211_hw *hw, u32 changed) } } - if (changed & IEEE80211_CONF_CHANGE_POWER) { - ath10k_dbg(ar, ATH10K_DBG_MAC, "mac config power %d\n", - hw->conf.power_level); - - param = ar->wmi.pdev_param->txpower_limit2g; - ret = ath10k_wmi_pdev_set_param(ar, param, - hw->conf.power_level * 2); - if (ret) - ath10k_warn(ar, "failed to set 2g txpower %d: %d\n", - hw->conf.power_level, ret); - - param = ar->wmi.pdev_param->txpower_limit5g; - ret = ath10k_wmi_pdev_set_param(ar, param, - hw->conf.power_level * 2); - if (ret) - ath10k_warn(ar, "failed to set 5g txpower %d: %d\n", - hw->conf.power_level, ret); - } - if (changed & IEEE80211_CONF_CHANGE_PS) ath10k_config_ps(ar); @@ -2772,9 +2815,12 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, ret = -EBUSY; goto err; } - bit = ffs(ar->free_vdev_map); + bit = __ffs64(ar->free_vdev_map); + + ath10k_dbg(ar, ATH10K_DBG_MAC, "mac create vdev %i map %llx\n", + bit, ar->free_vdev_map); - arvif->vdev_id = bit - 1; + arvif->vdev_id = bit; arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE; if (ar->p2p) @@ -2804,8 +2850,39 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, break; } - ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev create %d (add interface) type %d subtype %d\n", - arvif->vdev_id, arvif->vdev_type, arvif->vdev_subtype); + /* Some firmware revisions don't wait for beacon tx completion before + * sending another SWBA event. This could lead to hardware using old + * (freed) beacon data in some cases, e.g. tx credit starvation + * combined with missed TBTT. This is very very rare. + * + * On non-IOMMU-enabled hosts this could be a possible security issue + * because hw could beacon some random data on the air. On + * IOMMU-enabled hosts DMAR faults would occur in most cases and target + * device would crash. + * + * Since there are no beacon tx completions (implicit nor explicit) + * propagated to host the only workaround for this is to allocate a + * DMA-coherent buffer for a lifetime of a vif and use it for all + * beacon tx commands. Worst case for this approach is some beacons may + * become corrupted, e.g. have garbled IEs or out-of-date TIM bitmap. + */ + if (vif->type == NL80211_IFTYPE_ADHOC || + vif->type == NL80211_IFTYPE_AP) { + arvif->beacon_buf = dma_zalloc_coherent(ar->dev, + IEEE80211_MAX_FRAME_LEN, + &arvif->beacon_paddr, + GFP_ATOMIC); + if (!arvif->beacon_buf) { + ret = -ENOMEM; + ath10k_warn(ar, "failed to allocate beacon buffer: %d\n", + ret); + goto err; + } + } + + ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev create %d (add interface) type %d subtype %d bcnmode %s\n", + arvif->vdev_id, arvif->vdev_type, arvif->vdev_subtype, + arvif->beacon_buf ? "single-buf" : "per-skb"); ret = ath10k_wmi_vdev_create(ar, arvif->vdev_id, arvif->vdev_type, arvif->vdev_subtype, vif->addr); @@ -2815,7 +2892,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, goto err; } - ar->free_vdev_map &= ~(1 << arvif->vdev_id); + ar->free_vdev_map &= ~(1LL << arvif->vdev_id); list_add(&arvif->list, &ar->arvifs); vdev_param = ar->wmi.vdev_param->def_keyid; @@ -2899,6 +2976,13 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, goto err_peer_delete; } + arvif->txpower = vif->bss_conf.txpower; + ret = ath10k_mac_txpower_recalc(ar); + if (ret) { + ath10k_warn(ar, "failed to recalc tx power: %d\n", ret); + goto err_peer_delete; + } + mutex_unlock(&ar->conf_mutex); return 0; @@ -2908,10 +2992,16 @@ err_peer_delete: err_vdev_delete: ath10k_wmi_vdev_delete(ar, arvif->vdev_id); - ar->free_vdev_map |= 1 << arvif->vdev_id; + ar->free_vdev_map |= 1LL << arvif->vdev_id; list_del(&arvif->list); err: + if (arvif->beacon_buf) { + dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN, + arvif->beacon_buf, arvif->beacon_paddr); + arvif->beacon_buf = NULL; + } + mutex_unlock(&ar->conf_mutex); return ret; @@ -2929,14 +3019,7 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw, cancel_work_sync(&arvif->wep_key_work); spin_lock_bh(&ar->data_lock); - if (arvif->beacon) { - dma_unmap_single(arvif->ar->dev, - ATH10K_SKB_CB(arvif->beacon)->paddr, - arvif->beacon->len, DMA_TO_DEVICE); - dev_kfree_skb_any(arvif->beacon); - arvif->beacon = NULL; - } - + ath10k_mac_vif_beacon_cleanup(arvif); spin_unlock_bh(&ar->data_lock); ret = ath10k_spectral_vif_stop(arvif); @@ -2944,7 +3027,7 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw, ath10k_warn(ar, "failed to stop spectral for vdev %i: %d\n", arvif->vdev_id, ret); - ar->free_vdev_map |= 1 << arvif->vdev_id; + ar->free_vdev_map |= 1LL << arvif->vdev_id; list_del(&arvif->list); if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { @@ -3068,54 +3151,8 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, arvif->u.ap.hidden_ssid = info->hidden_ssid; } - /* - * Firmware manages AP self-peer internally so make sure to not create - * it in driver. Otherwise AP self-peer deletion may timeout later. - */ - if (changed & BSS_CHANGED_BSSID && - vif->type != NL80211_IFTYPE_AP) { - if (!is_zero_ether_addr(info->bssid)) { - ath10k_dbg(ar, ATH10K_DBG_MAC, - "mac vdev %d create peer %pM\n", - arvif->vdev_id, info->bssid); - - ret = ath10k_peer_create(ar, arvif->vdev_id, - info->bssid); - if (ret) - ath10k_warn(ar, "failed to add peer %pM for vdev %d when changing bssid: %i\n", - info->bssid, arvif->vdev_id, ret); - - if (vif->type == NL80211_IFTYPE_STATION) { - /* - * this is never erased as we it for crypto key - * clearing; this is FW requirement - */ - ether_addr_copy(arvif->bssid, info->bssid); - - ath10k_dbg(ar, ATH10K_DBG_MAC, - "mac vdev %d start %pM\n", - arvif->vdev_id, info->bssid); - - ret = ath10k_vdev_start(arvif); - if (ret) { - ath10k_warn(ar, "failed to start vdev %i: %d\n", - arvif->vdev_id, ret); - goto exit; - } - - arvif->is_started = true; - } - - /* - * Mac80211 does not keep IBSS bssid when leaving IBSS, - * so driver need to store it. It is needed when leaving - * IBSS in order to remove BSSID peer. - */ - if (vif->type == NL80211_IFTYPE_ADHOC) - memcpy(arvif->bssid, info->bssid, - ETH_ALEN); - } - } + if (changed & BSS_CHANGED_BSSID && !is_zero_ether_addr(info->bssid)) + ether_addr_copy(arvif->bssid, info->bssid); if (changed & BSS_CHANGED_BEACON_ENABLED) ath10k_control_beaconing(arvif, info); @@ -3177,10 +3214,21 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, ath10k_monitor_stop(ar); ath10k_bss_assoc(hw, vif, info); ath10k_monitor_recalc(ar); + } else { + ath10k_bss_disassoc(hw, vif); } } -exit: + if (changed & BSS_CHANGED_TXPOWER) { + ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev_id %i txpower %d\n", + arvif->vdev_id, info->txpower); + + arvif->txpower = info->txpower; + ret = ath10k_mac_txpower_recalc(ar); + if (ret) + ath10k_warn(ar, "failed to recalc tx power: %d\n", ret); + } + mutex_unlock(&ar->conf_mutex); } @@ -3266,9 +3314,10 @@ static void ath10k_cancel_hw_scan(struct ieee80211_hw *hw, struct ath10k *ar = hw->priv; mutex_lock(&ar->conf_mutex); - cancel_delayed_work_sync(&ar->scan.timeout); ath10k_scan_abort(ar); mutex_unlock(&ar->conf_mutex); + + cancel_delayed_work_sync(&ar->scan.timeout); } static void ath10k_set_key_h_def_keyidx(struct ath10k *ar, @@ -3453,7 +3502,7 @@ static void ath10k_sta_rc_update_wk(struct work_struct *wk) ath10k_dbg(ar, ATH10K_DBG_MAC, "mac update sta %pM supp rates\n", sta->addr); - err = ath10k_station_assoc(ar, arvif, sta, true); + err = ath10k_station_assoc(ar, arvif->vif, sta, true); if (err) ath10k_warn(ar, "failed to reassociate station: %pM\n", sta->addr); @@ -3489,8 +3538,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, mutex_lock(&ar->conf_mutex); if (old_state == IEEE80211_STA_NOTEXIST && - new_state == IEEE80211_STA_NONE && - vif->type != NL80211_IFTYPE_STATION) { + new_state == IEEE80211_STA_NONE) { /* * New station addition. */ @@ -3514,6 +3562,21 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, if (ret) ath10k_warn(ar, "failed to add peer %pM for vdev %d when adding a new sta: %i\n", sta->addr, arvif->vdev_id, ret); + + if (vif->type == NL80211_IFTYPE_STATION) { + WARN_ON(arvif->is_started); + + ret = ath10k_vdev_start(arvif); + if (ret) { + ath10k_warn(ar, "failed to start vdev %i: %d\n", + arvif->vdev_id, ret); + WARN_ON(ath10k_peer_delete(ar, arvif->vdev_id, + sta->addr)); + goto exit; + } + + arvif->is_started = true; + } } else if ((old_state == IEEE80211_STA_NONE && new_state == IEEE80211_STA_NOTEXIST)) { /* @@ -3522,13 +3585,23 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d peer delete %pM (sta gone)\n", arvif->vdev_id, sta->addr); + + if (vif->type == NL80211_IFTYPE_STATION) { + WARN_ON(!arvif->is_started); + + ret = ath10k_vdev_stop(arvif); + if (ret) + ath10k_warn(ar, "failed to stop vdev %i: %d\n", + arvif->vdev_id, ret); + + arvif->is_started = false; + } + ret = ath10k_peer_delete(ar, arvif->vdev_id, sta->addr); if (ret) ath10k_warn(ar, "failed to delete peer %pM for vdev %d: %i\n", sta->addr, arvif->vdev_id, ret); - if (vif->type == NL80211_IFTYPE_STATION) - ath10k_bss_disassoc(hw, vif); } else if (old_state == IEEE80211_STA_AUTH && new_state == IEEE80211_STA_ASSOC && (vif->type == NL80211_IFTYPE_AP || @@ -3539,7 +3612,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, ath10k_dbg(ar, ATH10K_DBG_MAC, "mac sta %pM associated\n", sta->addr); - ret = ath10k_station_assoc(ar, arvif, sta, false); + ret = ath10k_station_assoc(ar, vif, sta, false); if (ret) ath10k_warn(ar, "failed to associate station %pM for vdev %i: %i\n", sta->addr, arvif->vdev_id, ret); @@ -3553,7 +3626,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, ath10k_dbg(ar, ATH10K_DBG_MAC, "mac sta %pM disassociated\n", sta->addr); - ret = ath10k_station_disassoc(ar, arvif, sta); + ret = ath10k_station_disassoc(ar, vif, sta); if (ret) ath10k_warn(ar, "failed to disassociate station: %pM vdev %i: %i\n", sta->addr, arvif->vdev_id, ret); @@ -3761,10 +3834,11 @@ static int ath10k_cancel_remain_on_channel(struct ieee80211_hw *hw) struct ath10k *ar = hw->priv; mutex_lock(&ar->conf_mutex); - cancel_delayed_work_sync(&ar->scan.timeout); ath10k_scan_abort(ar); mutex_unlock(&ar->conf_mutex); + cancel_delayed_work_sync(&ar->scan.timeout); + return 0; } @@ -3807,7 +3881,7 @@ static int ath10k_set_frag_threshold(struct ieee80211_hw *hw, u32 value) ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d fragmentation threshold %d\n", arvif->vdev_id, value); - ret = ath10k_mac_set_rts(arvif, value); + ret = ath10k_mac_set_frag(arvif, value); if (ret) { ath10k_warn(ar, "failed to set fragmentation threshold for vdev %d: %d\n", arvif->vdev_id, ret); @@ -3843,7 +3917,9 @@ static void ath10k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, empty = (ar->htt.num_pending_tx == 0); spin_unlock_bh(&ar->htt.tx_lock); - skip = (ar->state == ATH10K_STATE_WEDGED); + skip = (ar->state == ATH10K_STATE_WEDGED) || + test_bit(ATH10K_FLAG_CRASH_FLUSH, + &ar->dev_flags); (empty || skip); }), ATH10K_FLUSH_TIMEOUT_HZ); @@ -3929,10 +4005,14 @@ exit: } #endif -static void ath10k_restart_complete(struct ieee80211_hw *hw) +static void ath10k_reconfig_complete(struct ieee80211_hw *hw, + enum ieee80211_reconfig_type reconfig_type) { struct ath10k *ar = hw->priv; + if (reconfig_type != IEEE80211_RECONFIG_TYPE_RESTART) + return; + mutex_lock(&ar->conf_mutex); /* If device failed to restart it will be in a different state, e.g. @@ -3940,6 +4020,7 @@ static void ath10k_restart_complete(struct ieee80211_hw *hw) if (ar->state == ATH10K_STATE_RESTARTED) { ath10k_info(ar, "device successfully recovered\n"); ar->state = ATH10K_STATE_ON; + ieee80211_wake_queues(ar->hw); } mutex_unlock(&ar->conf_mutex); @@ -3975,6 +4056,9 @@ static int ath10k_get_survey(struct ieee80211_hw *hw, int idx, survey->channel = &sband->channels[idx]; + if (ar->rx_channel == survey->channel) + survey->filled |= SURVEY_INFO_IN_USE; + exit: mutex_unlock(&ar->conf_mutex); return ret; @@ -4450,12 +4534,15 @@ static const struct ieee80211_ops ath10k_ops = { .tx_last_beacon = ath10k_tx_last_beacon, .set_antenna = ath10k_set_antenna, .get_antenna = ath10k_get_antenna, - .restart_complete = ath10k_restart_complete, + .reconfig_complete = ath10k_reconfig_complete, .get_survey = ath10k_get_survey, .set_bitrate_mask = ath10k_set_bitrate_mask, .sta_rc_update = ath10k_sta_rc_update, .get_tsf = ath10k_get_tsf, .ampdu_action = ath10k_ampdu_action, + .get_et_sset_count = ath10k_debug_get_et_sset_count, + .get_et_stats = ath10k_debug_get_et_stats, + .get_et_strings = ath10k_debug_get_et_strings, CFG80211_TESTMODE_CMD(ath10k_tm_cmd) @@ -4800,15 +4887,6 @@ int ath10k_mac_register(struct ath10k *ar) BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP); - if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) { - /* TODO: Have to deal with 2x2 chips if/when the come out. */ - ar->supp_tx_chainmask = TARGET_10X_TX_CHAIN_MASK; - ar->supp_rx_chainmask = TARGET_10X_RX_CHAIN_MASK; - } else { - ar->supp_tx_chainmask = TARGET_TX_CHAIN_MASK; - ar->supp_rx_chainmask = TARGET_RX_CHAIN_MASK; - } - ar->hw->wiphy->available_antennas_rx = ar->supp_rx_chainmask; ar->hw->wiphy->available_antennas_tx = ar->supp_tx_chainmask; @@ -4854,6 +4932,8 @@ int ath10k_mac_register(struct ath10k *ar) ar->hw->wiphy->max_remain_on_channel_duration = 5000; ar->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; + ar->hw->wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE; + /* * on LL hardware queues are managed entirely by the FW * so we only advertise to mac we can do the queues thing diff --git a/drivers/net/wireless/ath/ath10k/mac.h b/drivers/net/wireless/ath/ath10k/mac.h index 6c80eeada3e2..4e3c989aa841 100644 --- a/drivers/net/wireless/ath/ath10k/mac.h +++ b/drivers/net/wireless/ath/ath10k/mac.h @@ -39,6 +39,8 @@ void ath10k_offchan_tx_work(struct work_struct *work); void ath10k_mgmt_over_wmi_tx_purge(struct ath10k *ar); void ath10k_mgmt_over_wmi_tx_work(struct work_struct *work); void ath10k_halt(struct ath10k *ar); +void ath10k_mac_vif_beacon_free(struct ath10k_vif *arvif); +void ath10k_drain_tx(struct ath10k *ar); static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif) { diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 59e0ea83be50..3a6b8a5ca96c 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -485,6 +485,8 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, void *data_buf = NULL; int i; + spin_lock_bh(&ar_pci->ce_lock); + ce_diag = ar_pci->ce_diag; /* @@ -511,7 +513,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, nbytes = min_t(unsigned int, remaining_bytes, DIAG_TRANSFER_LIMIT); - ret = ath10k_ce_rx_post_buf(ce_diag, NULL, ce_data); + ret = __ath10k_ce_rx_post_buf(ce_diag, NULL, ce_data); if (ret != 0) goto done; @@ -527,15 +529,15 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, address = TARG_CPU_SPACE_TO_CE_SPACE(ar, ar_pci->mem, address); - ret = ath10k_ce_send(ce_diag, NULL, (u32)address, nbytes, 0, - 0); + ret = ath10k_ce_send_nolock(ce_diag, NULL, (u32)address, nbytes, 0, + 0); if (ret) goto done; i = 0; - while (ath10k_ce_completed_send_next(ce_diag, NULL, &buf, - &completed_nbytes, - &id) != 0) { + while (ath10k_ce_completed_send_next_nolock(ce_diag, NULL, &buf, + &completed_nbytes, + &id) != 0) { mdelay(1); if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { ret = -EBUSY; @@ -554,9 +556,9 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, } i = 0; - while (ath10k_ce_completed_recv_next(ce_diag, NULL, &buf, - &completed_nbytes, - &id, &flags) != 0) { + while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf, + &completed_nbytes, + &id, &flags) != 0) { mdelay(1); if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { @@ -591,6 +593,8 @@ done: dma_free_coherent(ar->dev, orig_nbytes, data_buf, ce_data_base); + spin_unlock_bh(&ar_pci->ce_lock); + return ret; } @@ -648,6 +652,8 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, dma_addr_t ce_data_base = 0; int i; + spin_lock_bh(&ar_pci->ce_lock); + ce_diag = ar_pci->ce_diag; /* @@ -688,7 +694,7 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, nbytes = min_t(int, remaining_bytes, DIAG_TRANSFER_LIMIT); /* Set up to receive directly into Target(!) address */ - ret = ath10k_ce_rx_post_buf(ce_diag, NULL, address); + ret = __ath10k_ce_rx_post_buf(ce_diag, NULL, address); if (ret != 0) goto done; @@ -696,15 +702,15 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, * Request CE to send caller-supplied data that * was copied to bounce buffer to Target(!) address. */ - ret = ath10k_ce_send(ce_diag, NULL, (u32)ce_data, - nbytes, 0, 0); + ret = ath10k_ce_send_nolock(ce_diag, NULL, (u32)ce_data, + nbytes, 0, 0); if (ret != 0) goto done; i = 0; - while (ath10k_ce_completed_send_next(ce_diag, NULL, &buf, - &completed_nbytes, - &id) != 0) { + while (ath10k_ce_completed_send_next_nolock(ce_diag, NULL, &buf, + &completed_nbytes, + &id) != 0) { mdelay(1); if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { @@ -724,9 +730,9 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, } i = 0; - while (ath10k_ce_completed_recv_next(ce_diag, NULL, &buf, - &completed_nbytes, - &id, &flags) != 0) { + while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf, + &completed_nbytes, + &id, &flags) != 0) { mdelay(1); if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { @@ -760,6 +766,8 @@ done: ath10k_warn(ar, "failed to write diag value at 0x%x: %d\n", address, ret); + spin_unlock_bh(&ar_pci->ce_lock); + return ret; } @@ -861,6 +869,12 @@ static void ath10k_pci_ce_recv_data(struct ath10k_ce_pipe *ce_state) } skb_put(skb, nbytes); + + ath10k_dbg(ar, ATH10K_DBG_PCI, "pci rx ce pipe %d len %d\n", + ce_state->id, skb->len); + ath10k_dbg_dump(ar, ATH10K_DBG_PCI_DUMP, NULL, "pci rx: ", + skb->data, skb->len); + cb->rx_completion(ar, skb, pipe_info->pipe_num); } @@ -936,6 +950,12 @@ err: return err; } +static int ath10k_pci_hif_diag_read(struct ath10k *ar, u32 address, void *buf, + size_t buf_len) +{ + return ath10k_pci_diag_read_mem(ar, address, buf, buf_len); +} + static u16 ath10k_pci_hif_get_free_queue_number(struct ath10k *ar, u8 pipe) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); @@ -986,6 +1006,8 @@ static void ath10k_pci_fw_crashed_dump(struct ath10k *ar) spin_lock_bh(&ar->data_lock); + ar->stats.fw_crash_counter++; + crash_data = ath10k_debug_get_new_fw_crash_data(ar); if (crash_data) @@ -1121,14 +1143,37 @@ static void ath10k_pci_hif_get_default_pipe(struct ath10k *ar, &dl_is_polled); } -static void ath10k_pci_irq_disable(struct ath10k *ar) +static void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar) { - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - int i; + u32 val; + + val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS); + val &= ~CORE_CTRL_PCIE_REG_31_MASK; + + ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS, val); +} + +static void ath10k_pci_irq_msi_fw_unmask(struct ath10k *ar) +{ + u32 val; + val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS); + val |= CORE_CTRL_PCIE_REG_31_MASK; + + ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS, val); +} + +static void ath10k_pci_irq_disable(struct ath10k *ar) +{ ath10k_ce_disable_interrupts(ar); ath10k_pci_disable_and_clear_legacy_irq(ar); - /* FIXME: How to mask all MSI interrupts? */ + ath10k_pci_irq_msi_fw_mask(ar); +} + +static void ath10k_pci_irq_sync(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + int i; for (i = 0; i < max(1, ar_pci->num_msi_intrs); i++) synchronize_irq(ar_pci->pdev->irq + i); @@ -1138,7 +1183,7 @@ static void ath10k_pci_irq_enable(struct ath10k *ar) { ath10k_ce_enable_interrupts(ar); ath10k_pci_enable_legacy_irq(ar); - /* FIXME: How to unmask all MSI interrupts? */ + ath10k_pci_irq_msi_fw_unmask(ar); } static int ath10k_pci_hif_start(struct ath10k *ar) @@ -1151,64 +1196,74 @@ static int ath10k_pci_hif_start(struct ath10k *ar) return 0; } -static void ath10k_pci_rx_pipe_cleanup(struct ath10k_pci_pipe *pipe_info) +static void ath10k_pci_rx_pipe_cleanup(struct ath10k_pci_pipe *pci_pipe) { struct ath10k *ar; - struct ath10k_pci *ar_pci; - struct ath10k_ce_pipe *ce_hdl; - u32 buf_sz; - struct sk_buff *netbuf; - u32 ce_data; + struct ath10k_ce_pipe *ce_pipe; + struct ath10k_ce_ring *ce_ring; + struct sk_buff *skb; + int i; - buf_sz = pipe_info->buf_sz; + ar = pci_pipe->hif_ce_state; + ce_pipe = pci_pipe->ce_hdl; + ce_ring = ce_pipe->dest_ring; - /* Unused Copy Engine */ - if (buf_sz == 0) + if (!ce_ring) return; - ar = pipe_info->hif_ce_state; - ar_pci = ath10k_pci_priv(ar); - ce_hdl = pipe_info->ce_hdl; + if (!pci_pipe->buf_sz) + return; - while (ath10k_ce_revoke_recv_next(ce_hdl, (void **)&netbuf, - &ce_data) == 0) { - dma_unmap_single(ar->dev, ATH10K_SKB_CB(netbuf)->paddr, - netbuf->len + skb_tailroom(netbuf), + for (i = 0; i < ce_ring->nentries; i++) { + skb = ce_ring->per_transfer_context[i]; + if (!skb) + continue; + + ce_ring->per_transfer_context[i] = NULL; + + dma_unmap_single(ar->dev, ATH10K_SKB_CB(skb)->paddr, + skb->len + skb_tailroom(skb), DMA_FROM_DEVICE); - dev_kfree_skb_any(netbuf); + dev_kfree_skb_any(skb); } } -static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pipe_info) +static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pci_pipe) { struct ath10k *ar; struct ath10k_pci *ar_pci; - struct ath10k_ce_pipe *ce_hdl; - struct sk_buff *netbuf; - u32 ce_data; - unsigned int nbytes; + struct ath10k_ce_pipe *ce_pipe; + struct ath10k_ce_ring *ce_ring; + struct ce_desc *ce_desc; + struct sk_buff *skb; unsigned int id; - u32 buf_sz; + int i; - buf_sz = pipe_info->buf_sz; + ar = pci_pipe->hif_ce_state; + ar_pci = ath10k_pci_priv(ar); + ce_pipe = pci_pipe->ce_hdl; + ce_ring = ce_pipe->src_ring; - /* Unused Copy Engine */ - if (buf_sz == 0) + if (!ce_ring) return; - ar = pipe_info->hif_ce_state; - ar_pci = ath10k_pci_priv(ar); - ce_hdl = pipe_info->ce_hdl; + if (!pci_pipe->buf_sz) + return; - while (ath10k_ce_cancel_send_next(ce_hdl, (void **)&netbuf, - &ce_data, &nbytes, &id) == 0) { - /* no need to call tx completion for NULL pointers */ - if (!netbuf) + ce_desc = ce_ring->shadow_base; + if (WARN_ON(!ce_desc)) + return; + + for (i = 0; i < ce_ring->nentries; i++) { + skb = ce_ring->per_transfer_context[i]; + if (!skb) continue; - ar_pci->msg_callbacks_current.tx_completion(ar, - netbuf, - id); + ce_ring->per_transfer_context[i] = NULL; + id = MS(__le16_to_cpu(ce_desc[i].flags), + CE_DESC_FLAGS_META_DATA); + + ar_pci->msg_callbacks_current.tx_completion(ar, skb, id); } } @@ -1266,6 +1321,7 @@ static void ath10k_pci_hif_stop(struct ath10k *ar) ath10k_pci_warm_reset(ar); ath10k_pci_irq_disable(ar); + ath10k_pci_irq_sync(ar); ath10k_pci_flush(ar); } @@ -1386,6 +1442,9 @@ static void ath10k_pci_bmi_recv_data(struct ath10k_ce_pipe *ce_state) &nbytes, &transfer_id, &flags)) return; + if (WARN_ON_ONCE(!xfer)) + return; + if (!xfer->wait_for_resp) { ath10k_warn(ar, "unexpected: BMI data received; ignoring\n"); return; @@ -1569,23 +1628,40 @@ static int ath10k_pci_init_config(struct ath10k *ar) return 0; } -static int ath10k_pci_alloc_ce(struct ath10k *ar) +static int ath10k_pci_alloc_pipes(struct ath10k *ar) { + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct ath10k_pci_pipe *pipe; int i, ret; for (i = 0; i < CE_COUNT; i++) { - ret = ath10k_ce_alloc_pipe(ar, i, &host_ce_config_wlan[i]); + pipe = &ar_pci->pipe_info[i]; + pipe->ce_hdl = &ar_pci->ce_states[i]; + pipe->pipe_num = i; + pipe->hif_ce_state = ar; + + ret = ath10k_ce_alloc_pipe(ar, i, &host_ce_config_wlan[i], + ath10k_pci_ce_send_done, + ath10k_pci_ce_recv_data); if (ret) { ath10k_err(ar, "failed to allocate copy engine pipe %d: %d\n", i, ret); return ret; } + + /* Last CE is Diagnostic Window */ + if (i == CE_COUNT - 1) { + ar_pci->ce_diag = pipe->ce_hdl; + continue; + } + + pipe->buf_sz = (size_t)(host_ce_config_wlan[i].src_sz_max); } return 0; } -static void ath10k_pci_free_ce(struct ath10k *ar) +static void ath10k_pci_free_pipes(struct ath10k *ar) { int i; @@ -1593,39 +1669,17 @@ static void ath10k_pci_free_ce(struct ath10k *ar) ath10k_ce_free_pipe(ar, i); } -static int ath10k_pci_ce_init(struct ath10k *ar) +static int ath10k_pci_init_pipes(struct ath10k *ar) { - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - struct ath10k_pci_pipe *pipe_info; - const struct ce_attr *attr; - int pipe_num, ret; + int i, ret; - for (pipe_num = 0; pipe_num < CE_COUNT; pipe_num++) { - pipe_info = &ar_pci->pipe_info[pipe_num]; - pipe_info->ce_hdl = &ar_pci->ce_states[pipe_num]; - pipe_info->pipe_num = pipe_num; - pipe_info->hif_ce_state = ar; - attr = &host_ce_config_wlan[pipe_num]; - - ret = ath10k_ce_init_pipe(ar, pipe_num, attr, - ath10k_pci_ce_send_done, - ath10k_pci_ce_recv_data); + for (i = 0; i < CE_COUNT; i++) { + ret = ath10k_ce_init_pipe(ar, i, &host_ce_config_wlan[i]); if (ret) { ath10k_err(ar, "failed to initialize copy engine pipe %d: %d\n", - pipe_num, ret); + i, ret); return ret; } - - if (pipe_num == CE_COUNT - 1) { - /* - * Reserve the ultimate CE for - * diagnostic Window support - */ - ar_pci->ce_diag = pipe_info->ce_hdl; - continue; - } - - pipe_info->buf_sz = (size_t)(attr->src_sz_max); } return 0; @@ -1666,93 +1720,167 @@ static void ath10k_pci_warm_reset_si0(struct ath10k *ar) msleep(10); } -static int ath10k_pci_warm_reset(struct ath10k *ar) +static void ath10k_pci_warm_reset_cpu(struct ath10k *ar) { u32 val; - ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot warm reset\n"); - - /* debug */ - val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + - PCIE_INTR_CAUSE_ADDRESS); - ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot host cpu intr cause: 0x%08x\n", - val); + ath10k_pci_write32(ar, FW_INDICATOR_ADDRESS, 0); - val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + - CPU_INTR_ADDRESS); - ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot target cpu intr cause: 0x%08x\n", - val); + val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS + + SOC_RESET_CONTROL_ADDRESS); + ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS, + val | SOC_RESET_CONTROL_CPU_WARM_RST_MASK); +} - /* disable pending irqs */ - ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + - PCIE_INTR_ENABLE_ADDRESS, 0); +static void ath10k_pci_warm_reset_ce(struct ath10k *ar) +{ + u32 val; - ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + - PCIE_INTR_CLR_ADDRESS, ~0); + val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS + + SOC_RESET_CONTROL_ADDRESS); - msleep(100); + ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS, + val | SOC_RESET_CONTROL_CE_RST_MASK); + msleep(10); + ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS, + val & ~SOC_RESET_CONTROL_CE_RST_MASK); +} - /* clear fw indicator */ - ath10k_pci_write32(ar, FW_INDICATOR_ADDRESS, 0); +static void ath10k_pci_warm_reset_clear_lf(struct ath10k *ar) +{ + u32 val; - /* clear target LF timer interrupts */ val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS + SOC_LF_TIMER_CONTROL0_ADDRESS); ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_LF_TIMER_CONTROL0_ADDRESS, val & ~SOC_LF_TIMER_CONTROL0_ENABLE_MASK); +} - /* reset CE */ - val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS + - SOC_RESET_CONTROL_ADDRESS); - ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS, - val | SOC_RESET_CONTROL_CE_RST_MASK); - val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS + - SOC_RESET_CONTROL_ADDRESS); - msleep(10); +static int ath10k_pci_warm_reset(struct ath10k *ar) +{ + int ret; - /* unreset CE */ - ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS, - val & ~SOC_RESET_CONTROL_CE_RST_MASK); - val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS + - SOC_RESET_CONTROL_ADDRESS); - msleep(10); + ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot warm reset\n"); + + spin_lock_bh(&ar->data_lock); + ar->stats.fw_warm_reset_counter++; + spin_unlock_bh(&ar->data_lock); + + ath10k_pci_irq_disable(ar); + /* Make sure the target CPU is not doing anything dangerous, e.g. if it + * were to access copy engine while host performs copy engine reset + * then it is possible for the device to confuse pci-e controller to + * the point of bringing host system to a complete stop (i.e. hang). + */ ath10k_pci_warm_reset_si0(ar); + ath10k_pci_warm_reset_cpu(ar); + ath10k_pci_init_pipes(ar); + ath10k_pci_wait_for_target_init(ar); - /* debug */ - val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + - PCIE_INTR_CAUSE_ADDRESS); - ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot host cpu intr cause: 0x%08x\n", - val); + ath10k_pci_warm_reset_clear_lf(ar); + ath10k_pci_warm_reset_ce(ar); + ath10k_pci_warm_reset_cpu(ar); + ath10k_pci_init_pipes(ar); - val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + - CPU_INTR_ADDRESS); - ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot target cpu intr cause: 0x%08x\n", - val); + ret = ath10k_pci_wait_for_target_init(ar); + if (ret) { + ath10k_warn(ar, "failed to wait for target init: %d\n", ret); + return ret; + } - /* CPU warm reset */ - val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS + - SOC_RESET_CONTROL_ADDRESS); - ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS, - val | SOC_RESET_CONTROL_CPU_WARM_RST_MASK); + ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot warm reset complete\n"); - val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS + - SOC_RESET_CONTROL_ADDRESS); - ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot target reset state: 0x%08x\n", - val); + return 0; +} + +static int ath10k_pci_chip_reset(struct ath10k *ar) +{ + int i, ret; + u32 val; - msleep(100); + ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot chip reset\n"); - ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot warm reset complete\n"); + /* Some hardware revisions (e.g. CUS223v2) has issues with cold reset. + * It is thus preferred to use warm reset which is safer but may not be + * able to recover the device from all possible fail scenarios. + * + * Warm reset doesn't always work on first try so attempt it a few + * times before giving up. + */ + for (i = 0; i < ATH10K_PCI_NUM_WARM_RESET_ATTEMPTS; i++) { + ret = ath10k_pci_warm_reset(ar); + if (ret) { + ath10k_warn(ar, "failed to warm reset attempt %d of %d: %d\n", + i + 1, ATH10K_PCI_NUM_WARM_RESET_ATTEMPTS, + ret); + continue; + } + + /* FIXME: Sometimes copy engine doesn't recover after warm + * reset. In most cases this needs cold reset. In some of these + * cases the device is in such a state that a cold reset may + * lock up the host. + * + * Reading any host interest register via copy engine is + * sufficient to verify if device is capable of booting + * firmware blob. + */ + ret = ath10k_pci_init_pipes(ar); + if (ret) { + ath10k_warn(ar, "failed to init copy engine: %d\n", + ret); + continue; + } + + ret = ath10k_pci_diag_read32(ar, QCA988X_HOST_INTEREST_ADDRESS, + &val); + if (ret) { + ath10k_warn(ar, "failed to poke copy engine: %d\n", + ret); + continue; + } + + ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot chip reset complete (warm)\n"); + return 0; + } + + if (ath10k_pci_reset_mode == ATH10K_PCI_RESET_WARM_ONLY) { + ath10k_warn(ar, "refusing cold reset as requested\n"); + return -EPERM; + } + + ret = ath10k_pci_cold_reset(ar); + if (ret) { + ath10k_warn(ar, "failed to cold reset: %d\n", ret); + return ret; + } + + ret = ath10k_pci_wait_for_target_init(ar); + if (ret) { + ath10k_warn(ar, "failed to wait for target after cold reset: %d\n", + ret); + return ret; + } + + ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot chip reset complete (cold)\n"); return 0; } -static int __ath10k_pci_hif_power_up(struct ath10k *ar, bool cold_reset) +static int ath10k_pci_hif_power_up(struct ath10k *ar) { int ret; + ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif power up\n"); + + ret = ath10k_pci_wake(ar); + if (ret) { + ath10k_err(ar, "failed to wake up target: %d\n", ret); + return ret; + } + /* * Bring the target up cleanly. * @@ -1763,26 +1891,16 @@ static int __ath10k_pci_hif_power_up(struct ath10k *ar, bool cold_reset) * is in an unexpected state. We try to catch that here in order to * reset the Target and retry the probe. */ - if (cold_reset) - ret = ath10k_pci_cold_reset(ar); - else - ret = ath10k_pci_warm_reset(ar); - + ret = ath10k_pci_chip_reset(ar); if (ret) { - ath10k_err(ar, "failed to reset target: %d\n", ret); - goto err; + ath10k_err(ar, "failed to reset chip: %d\n", ret); + goto err_sleep; } - ret = ath10k_pci_ce_init(ar); + ret = ath10k_pci_init_pipes(ar); if (ret) { ath10k_err(ar, "failed to initialize CE: %d\n", ret); - goto err; - } - - ret = ath10k_pci_wait_for_target_init(ar); - if (ret) { - ath10k_err(ar, "failed to wait for target to init: %d\n", ret); - goto err_ce; + goto err_sleep; } ret = ath10k_pci_init_config(ar); @@ -1801,73 +1919,21 @@ static int __ath10k_pci_hif_power_up(struct ath10k *ar, bool cold_reset) err_ce: ath10k_pci_ce_deinit(ar); - ath10k_pci_warm_reset(ar); -err: - return ret; -} - -static int ath10k_pci_hif_power_up_warm(struct ath10k *ar) -{ - int i, ret; - - /* - * Sometime warm reset succeeds after retries. - * - * FIXME: It might be possible to tune ath10k_pci_warm_reset() to work - * at first try. - */ - for (i = 0; i < ATH10K_PCI_NUM_WARM_RESET_ATTEMPTS; i++) { - ret = __ath10k_pci_hif_power_up(ar, false); - if (ret == 0) - break; - - ath10k_warn(ar, "failed to warm reset (attempt %d out of %d): %d\n", - i + 1, ATH10K_PCI_NUM_WARM_RESET_ATTEMPTS, ret); - } +err_sleep: + ath10k_pci_sleep(ar); return ret; } -static int ath10k_pci_hif_power_up(struct ath10k *ar) -{ - int ret; - - ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif power up\n"); - - /* - * Hardware CUS232 version 2 has some issues with cold reset and the - * preferred (and safer) way to perform a device reset is through a - * warm reset. - * - * Warm reset doesn't always work though so fall back to cold reset may - * be necessary. - */ - ret = ath10k_pci_hif_power_up_warm(ar); - if (ret) { - ath10k_warn(ar, "failed to power up target using warm reset: %d\n", - ret); - - if (ath10k_pci_reset_mode == ATH10K_PCI_RESET_WARM_ONLY) - return ret; - - ath10k_warn(ar, "trying cold reset\n"); - - ret = __ath10k_pci_hif_power_up(ar, true); - if (ret) { - ath10k_err(ar, "failed to power up target using cold reset too (%d)\n", - ret); - return ret; - } - } - - return 0; -} - static void ath10k_pci_hif_power_down(struct ath10k *ar) { ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif power down\n"); - ath10k_pci_warm_reset(ar); + /* Currently hif_power_up performs effectively a reset and hif_stop + * resets the chip as well so there's no point in resetting here. + */ + + ath10k_pci_sleep(ar); } #ifdef CONFIG_PM @@ -1921,6 +1987,7 @@ static int ath10k_pci_hif_resume(struct ath10k *ar) static const struct ath10k_hif_ops ath10k_pci_hif_ops = { .tx_sg = ath10k_pci_hif_tx_sg, + .diag_read = ath10k_pci_hif_diag_read, .exchange_bmi_msg = ath10k_pci_hif_exchange_bmi_msg, .start = ath10k_pci_hif_start, .stop = ath10k_pci_hif_stop, @@ -2250,14 +2317,14 @@ static int ath10k_pci_wait_for_target_init(struct ath10k *ar) if (ar_pci->num_msi_intrs == 0) /* Fix potential race by repeating CORE_BASE writes */ - ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + - PCIE_INTR_ENABLE_ADDRESS, - PCIE_INTR_FIRMWARE_MASK | - PCIE_INTR_CE_MASK_ALL); + ath10k_pci_enable_legacy_irq(ar); mdelay(10); } while (time_before(jiffies, timeout)); + ath10k_pci_disable_and_clear_legacy_irq(ar); + ath10k_pci_irq_msi_fw_mask(ar); + if (val == 0xffffffff) { ath10k_err(ar, "failed to read device register, device is gone\n"); return -EIO; @@ -2287,6 +2354,12 @@ static int ath10k_pci_cold_reset(struct ath10k *ar) ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cold reset\n"); + spin_lock_bh(&ar->data_lock); + + ar->stats.fw_cold_reset_counter++; + + spin_unlock_bh(&ar->data_lock); + /* Put Target, including PCIe, into RESET. */ val = ath10k_pci_reg_read32(ar, SOC_GLOBAL_RESET_ADDRESS); val |= 1; @@ -2400,6 +2473,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev, u32 chip_id; ar = ath10k_core_create(sizeof(*ar_pci), &pdev->dev, + ATH10K_BUS_PCI, &ath10k_pci_hif_ops); if (!ar) { dev_err(&pdev->dev, "failed to allocate core\n"); @@ -2435,7 +2509,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev, goto err_sleep; } - ret = ath10k_pci_alloc_ce(ar); + ret = ath10k_pci_alloc_pipes(ar); if (ret) { ath10k_err(ar, "failed to allocate copy engine pipes: %d\n", ret); @@ -2443,25 +2517,12 @@ static int ath10k_pci_probe(struct pci_dev *pdev, } ath10k_pci_ce_deinit(ar); - - ret = ath10k_ce_disable_interrupts(ar); - if (ret) { - ath10k_err(ar, "failed to disable copy engine interrupts: %d\n", - ret); - goto err_free_ce; - } - - /* Workaround: There's no known way to mask all possible interrupts via - * device CSR. The only way to make sure device doesn't assert - * interrupts is to reset it. Interrupts are then disabled on host - * after handlers are registered. - */ - ath10k_pci_warm_reset(ar); + ath10k_pci_irq_disable(ar); ret = ath10k_pci_init_irq(ar); if (ret) { ath10k_err(ar, "failed to init irqs: %d\n", ret); - goto err_free_ce; + goto err_free_pipes; } ath10k_info(ar, "pci irq %s interrupts %d irq_mode %d reset_mode %d\n", @@ -2474,8 +2535,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev, goto err_deinit_irq; } - /* This shouldn't race as the device has been reset above. */ - ath10k_pci_irq_disable(ar); + ath10k_pci_sleep(ar); ret = ath10k_core_register(ar, chip_id); if (ret) { @@ -2492,8 +2552,8 @@ err_free_irq: err_deinit_irq: ath10k_pci_deinit_irq(ar); -err_free_ce: - ath10k_pci_free_ce(ar); +err_free_pipes: + ath10k_pci_free_pipes(ar); err_sleep: ath10k_pci_sleep(ar); @@ -2527,8 +2587,7 @@ static void ath10k_pci_remove(struct pci_dev *pdev) ath10k_pci_kill_tasklet(ar); ath10k_pci_deinit_irq(ar); ath10k_pci_ce_deinit(ar); - ath10k_pci_free_ce(ar); - ath10k_pci_sleep(ar); + ath10k_pci_free_pipes(ar); ath10k_pci_release(ar); ath10k_core_destroy(ar); } @@ -2565,5 +2624,7 @@ module_exit(ath10k_pci_exit); MODULE_AUTHOR("Qualcomm Atheros"); MODULE_DESCRIPTION("Driver support for Atheros QCA988X PCIe devices"); MODULE_LICENSE("Dual BSD/GPL"); -MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_FW_3_FILE); +MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_FW_FILE); +MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API2_FILE); +MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API3_FILE); MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_BOARD_DATA_FILE); diff --git a/drivers/net/wireless/ath/ath10k/spectral.c b/drivers/net/wireless/ath/ath10k/spectral.c index 3e1454b74e00..63ce61fcdac8 100644 --- a/drivers/net/wireless/ath/ath10k/spectral.c +++ b/drivers/net/wireless/ath/ath10k/spectral.c @@ -56,14 +56,14 @@ static uint8_t get_max_exp(s8 max_index, u16 max_magnitude, size_t bin_len, } int ath10k_spectral_process_fft(struct ath10k *ar, - struct wmi_single_phyerr_rx_event *event, - struct phyerr_fft_report *fftr, + const struct wmi_phyerr *phyerr, + const struct phyerr_fft_report *fftr, size_t bin_len, u64 tsf) { struct fft_sample_ath10k *fft_sample; u8 buf[sizeof(*fft_sample) + SPECTRAL_ATH10K_MAX_NUM_BINS]; u16 freq1, freq2, total_gain_db, base_pwr_db, length, peak_mag; - u32 reg0, reg1, nf_list1, nf_list2; + u32 reg0, reg1; u8 chain_idx, *bins; int dc_pos; @@ -82,7 +82,7 @@ int ath10k_spectral_process_fft(struct ath10k *ar, /* TODO: there might be a reason why the hardware reports 20/40/80 MHz, * but the results/plots suggest that its actually 22/44/88 MHz. */ - switch (event->hdr.chan_width_mhz) { + switch (phyerr->chan_width_mhz) { case 20: fft_sample->chan_width_mhz = 22; break; @@ -101,7 +101,7 @@ int ath10k_spectral_process_fft(struct ath10k *ar, fft_sample->chan_width_mhz = 88; break; default: - fft_sample->chan_width_mhz = event->hdr.chan_width_mhz; + fft_sample->chan_width_mhz = phyerr->chan_width_mhz; } fft_sample->relpwr_db = MS(reg1, SEARCH_FFT_REPORT_REG1_RELPWR_DB); @@ -110,36 +110,22 @@ int ath10k_spectral_process_fft(struct ath10k *ar, peak_mag = MS(reg1, SEARCH_FFT_REPORT_REG1_PEAK_MAG); fft_sample->max_magnitude = __cpu_to_be16(peak_mag); fft_sample->max_index = MS(reg0, SEARCH_FFT_REPORT_REG0_PEAK_SIDX); - fft_sample->rssi = event->hdr.rssi_combined; + fft_sample->rssi = phyerr->rssi_combined; total_gain_db = MS(reg0, SEARCH_FFT_REPORT_REG0_TOTAL_GAIN_DB); base_pwr_db = MS(reg0, SEARCH_FFT_REPORT_REG0_BASE_PWR_DB); fft_sample->total_gain_db = __cpu_to_be16(total_gain_db); fft_sample->base_pwr_db = __cpu_to_be16(base_pwr_db); - freq1 = __le16_to_cpu(event->hdr.freq1); - freq2 = __le16_to_cpu(event->hdr.freq2); + freq1 = __le16_to_cpu(phyerr->freq1); + freq2 = __le16_to_cpu(phyerr->freq2); fft_sample->freq1 = __cpu_to_be16(freq1); fft_sample->freq2 = __cpu_to_be16(freq2); - nf_list1 = __le32_to_cpu(event->hdr.nf_list_1); - nf_list2 = __le32_to_cpu(event->hdr.nf_list_2); chain_idx = MS(reg0, SEARCH_FFT_REPORT_REG0_FFT_CHN_IDX); - switch (chain_idx) { - case 0: - fft_sample->noise = __cpu_to_be16(nf_list1 & 0xffffu); - break; - case 1: - fft_sample->noise = __cpu_to_be16((nf_list1 >> 16) & 0xffffu); - break; - case 2: - fft_sample->noise = __cpu_to_be16(nf_list2 & 0xffffu); - break; - case 3: - fft_sample->noise = __cpu_to_be16((nf_list2 >> 16) & 0xffffu); - break; - } + fft_sample->noise = __cpu_to_be16( + __le16_to_cpu(phyerr->nf_chains[chain_idx])); bins = (u8 *)fftr; bins += sizeof(*fftr); diff --git a/drivers/net/wireless/ath/ath10k/spectral.h b/drivers/net/wireless/ath/ath10k/spectral.h index ddc57c557272..042f5b302c75 100644 --- a/drivers/net/wireless/ath/ath10k/spectral.h +++ b/drivers/net/wireless/ath/ath10k/spectral.h @@ -47,8 +47,8 @@ enum ath10k_spectral_mode { #ifdef CONFIG_ATH10K_DEBUGFS int ath10k_spectral_process_fft(struct ath10k *ar, - struct wmi_single_phyerr_rx_event *event, - struct phyerr_fft_report *fftr, + const struct wmi_phyerr *phyerr, + const struct phyerr_fft_report *fftr, size_t bin_len, u64 tsf); int ath10k_spectral_start(struct ath10k *ar); int ath10k_spectral_vif_stop(struct ath10k_vif *arvif); @@ -59,8 +59,8 @@ void ath10k_spectral_destroy(struct ath10k *ar); static inline int ath10k_spectral_process_fft(struct ath10k *ar, - struct wmi_single_phyerr_rx_event *event, - struct phyerr_fft_report *fftr, + const struct wmi_phyerr *phyerr, + const struct phyerr_fft_report *fftr, size_t bin_len, u64 tsf) { return 0; diff --git a/drivers/net/wireless/ath/ath10k/trace.h b/drivers/net/wireless/ath/ath10k/trace.h index 574b75ab2609..ceea5668f3f6 100644 --- a/drivers/net/wireless/ath/ath10k/trace.h +++ b/drivers/net/wireless/ath/ath10k/trace.h @@ -20,6 +20,13 @@ #include <linux/tracepoint.h> #include "core.h" +#if !defined(_TRACE_H_) +static inline u32 ath10k_frm_hdr_len(void *buf) +{ + return ieee80211_hdrlen(((struct ieee80211_hdr *)buf)->frame_control); +} +#endif + #define _TRACE_H_ /* create empty functions when tracing is disabled */ @@ -254,6 +261,195 @@ TRACE_EVENT(ath10k_wmi_dbglog, ) ); +TRACE_EVENT(ath10k_htt_pktlog, + TP_PROTO(struct ath10k *ar, void *buf, u16 buf_len), + + TP_ARGS(ar, buf, buf_len), + + TP_STRUCT__entry( + __string(device, dev_name(ar->dev)) + __string(driver, dev_driver_string(ar->dev)) + __field(u16, buf_len) + __dynamic_array(u8, pktlog, buf_len) + ), + + TP_fast_assign( + __assign_str(device, dev_name(ar->dev)); + __assign_str(driver, dev_driver_string(ar->dev)); + __entry->buf_len = buf_len; + memcpy(__get_dynamic_array(pktlog), buf, buf_len); + ), + + TP_printk( + "%s %s size %hu", + __get_str(driver), + __get_str(device), + __entry->buf_len + ) +); + +TRACE_EVENT(ath10k_htt_tx, + TP_PROTO(struct ath10k *ar, u16 msdu_id, u16 msdu_len, + u8 vdev_id, u8 tid), + + TP_ARGS(ar, msdu_id, msdu_len, vdev_id, tid), + + TP_STRUCT__entry( + __string(device, dev_name(ar->dev)) + __string(driver, dev_driver_string(ar->dev)) + __field(u16, msdu_id) + __field(u16, msdu_len) + __field(u8, vdev_id) + __field(u8, tid) + ), + + TP_fast_assign( + __assign_str(device, dev_name(ar->dev)); + __assign_str(driver, dev_driver_string(ar->dev)); + __entry->msdu_id = msdu_id; + __entry->msdu_len = msdu_len; + __entry->vdev_id = vdev_id; + __entry->tid = tid; + ), + + TP_printk( + "%s %s msdu_id %d msdu_len %d vdev_id %d tid %d", + __get_str(driver), + __get_str(device), + __entry->msdu_id, + __entry->msdu_len, + __entry->vdev_id, + __entry->tid + ) +); + +TRACE_EVENT(ath10k_txrx_tx_unref, + TP_PROTO(struct ath10k *ar, u16 msdu_id), + + TP_ARGS(ar, msdu_id), + + TP_STRUCT__entry( + __string(device, dev_name(ar->dev)) + __string(driver, dev_driver_string(ar->dev)) + __field(u16, msdu_id) + ), + + TP_fast_assign( + __assign_str(device, dev_name(ar->dev)); + __assign_str(driver, dev_driver_string(ar->dev)); + __entry->msdu_id = msdu_id; + ), + + TP_printk( + "%s %s msdu_id %d", + __get_str(driver), + __get_str(device), + __entry->msdu_id + ) +); + +DECLARE_EVENT_CLASS(ath10k_hdr_event, + TP_PROTO(struct ath10k *ar, void *data, size_t len), + + TP_ARGS(ar, data, len), + + TP_STRUCT__entry( + __string(device, dev_name(ar->dev)) + __string(driver, dev_driver_string(ar->dev)) + __field(size_t, len) + __dynamic_array(u8, data, ath10k_frm_hdr_len(data)) + ), + + TP_fast_assign( + __assign_str(device, dev_name(ar->dev)); + __assign_str(driver, dev_driver_string(ar->dev)); + __entry->len = ath10k_frm_hdr_len(data); + memcpy(__get_dynamic_array(data), data, __entry->len); + ), + + TP_printk( + "%s %s len %zu\n", + __get_str(driver), + __get_str(device), + __entry->len + ) +); + +DECLARE_EVENT_CLASS(ath10k_payload_event, + TP_PROTO(struct ath10k *ar, void *data, size_t len), + + TP_ARGS(ar, data, len), + + TP_STRUCT__entry( + __string(device, dev_name(ar->dev)) + __string(driver, dev_driver_string(ar->dev)) + __field(size_t, len) + __dynamic_array(u8, payload, (len - ath10k_frm_hdr_len(data))) + ), + + TP_fast_assign( + __assign_str(device, dev_name(ar->dev)); + __assign_str(driver, dev_driver_string(ar->dev)); + __entry->len = len - ath10k_frm_hdr_len(data); + memcpy(__get_dynamic_array(payload), + data + ath10k_frm_hdr_len(data), __entry->len); + ), + + TP_printk( + "%s %s len %zu\n", + __get_str(driver), + __get_str(device), + __entry->len + ) +); + +DEFINE_EVENT(ath10k_hdr_event, ath10k_tx_hdr, + TP_PROTO(struct ath10k *ar, void *data, size_t len), + TP_ARGS(ar, data, len) +); + +DEFINE_EVENT(ath10k_payload_event, ath10k_tx_payload, + TP_PROTO(struct ath10k *ar, void *data, size_t len), + TP_ARGS(ar, data, len) +); + +DEFINE_EVENT(ath10k_hdr_event, ath10k_rx_hdr, + TP_PROTO(struct ath10k *ar, void *data, size_t len), + TP_ARGS(ar, data, len) +); + +DEFINE_EVENT(ath10k_payload_event, ath10k_rx_payload, + TP_PROTO(struct ath10k *ar, void *data, size_t len), + TP_ARGS(ar, data, len) +); + +TRACE_EVENT(ath10k_htt_rx_desc, + TP_PROTO(struct ath10k *ar, void *data, size_t len), + + TP_ARGS(ar, data, len), + + TP_STRUCT__entry( + __string(device, dev_name(ar->dev)) + __string(driver, dev_driver_string(ar->dev)) + __field(u16, len) + __dynamic_array(u8, rxdesc, len) + ), + + TP_fast_assign( + __assign_str(device, dev_name(ar->dev)); + __assign_str(driver, dev_driver_string(ar->dev)); + __entry->len = len; + memcpy(__get_dynamic_array(rxdesc), data, len); + ), + + TP_printk( + "%s %s rxdesc len %d", + __get_str(driver), + __get_str(device), + __entry->len + ) +); + #endif /* _TRACE_H_ || TRACE_HEADER_MULTI_READ*/ /* we don't want to use include/trace/events */ diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index a0cbc21d0d4b..7579de8e7a8c 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c @@ -78,6 +78,7 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt, info = IEEE80211_SKB_CB(msdu); memset(&info->status, 0, sizeof(info->status)); + trace_ath10k_txrx_tx_unref(ar, tx_done->msdu_id); if (tx_done->discard) { ieee80211_free_txskb(htt->ar->hw, msdu); @@ -145,7 +146,8 @@ static int ath10k_wait_for_peer_common(struct ath10k *ar, int vdev_id, mapped = !!ath10k_peer_find(ar, vdev_id, addr); spin_unlock_bh(&ar->data_lock); - mapped == expect_mapped; + (mapped == expect_mapped || + test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags)); }), 3*HZ); if (ret <= 0) diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 2c42bd504b79..c2bc8282f6cb 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -609,6 +609,40 @@ static struct wmi_cmd_map wmi_10_2_cmd_map = { .gpio_output_cmdid = WMI_10_2_GPIO_OUTPUT_CMDID, }; +static void +ath10k_wmi_put_wmi_channel(struct wmi_channel *ch, + const struct wmi_channel_arg *arg) +{ + u32 flags = 0; + + memset(ch, 0, sizeof(*ch)); + + if (arg->passive) + flags |= WMI_CHAN_FLAG_PASSIVE; + if (arg->allow_ibss) + flags |= WMI_CHAN_FLAG_ADHOC_ALLOWED; + if (arg->allow_ht) + flags |= WMI_CHAN_FLAG_ALLOW_HT; + if (arg->allow_vht) + flags |= WMI_CHAN_FLAG_ALLOW_VHT; + if (arg->ht40plus) + flags |= WMI_CHAN_FLAG_HT40_PLUS; + if (arg->chan_radar) + flags |= WMI_CHAN_FLAG_DFS; + + ch->mhz = __cpu_to_le32(arg->freq); + ch->band_center_freq1 = __cpu_to_le32(arg->band_center_freq1); + ch->band_center_freq2 = 0; + ch->min_power = arg->min_power; + ch->max_power = arg->max_power; + ch->reg_power = arg->max_reg_power; + ch->antenna_max = arg->max_antenna_gain; + + /* mode & flags share storage */ + ch->mode = arg->mode; + ch->flags |= __cpu_to_le32(flags); +} + int ath10k_wmi_wait_for_service_ready(struct ath10k *ar) { int ret; @@ -745,6 +779,10 @@ int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id) ath10k_wmi_tx_beacons_nowait(ar); ret = ath10k_wmi_cmd_send_nowait(ar, skb, cmd_id); + + if (ret && test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags)) + ret = -ESHUTDOWN; + (ret != -EAGAIN); }), 3*HZ); @@ -800,6 +838,8 @@ int ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *skb) ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi mgmt tx skb %p len %d ftype %02x stype %02x\n", wmi_skb, wmi_skb->len, fc & IEEE80211_FCTL_FTYPE, fc & IEEE80211_FCTL_STYPE); + trace_ath10k_tx_hdr(ar, skb->data, skb->len); + trace_ath10k_tx_payload(ar, skb->data, skb->len); /* Send the management frame buffer to the target */ ret = ath10k_wmi_cmd_send(ar, wmi_skb, ar->wmi.cmd->mgmt_tx_cmdid); @@ -1079,7 +1119,6 @@ static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) struct wmi_mgmt_rx_event_v2 *ev_v2; struct wmi_mgmt_rx_hdr_v1 *ev_hdr; struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); - struct ieee80211_channel *ch; struct ieee80211_hdr *hdr; u32 rx_status; u32 channel; @@ -1132,25 +1171,26 @@ static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) if (rx_status & WMI_RX_STATUS_ERR_MIC) status->flag |= RX_FLAG_MMIC_ERROR; - /* HW can Rx CCK rates on 5GHz. In that case phy_mode is set to + /* Hardware can Rx CCK rates on 5GHz. In that case phy_mode is set to * MODE_11B. This means phy_mode is not a reliable source for the band - * of mgmt rx. */ - - ch = ar->scan_channel; - if (!ch) - ch = ar->rx_channel; - - if (ch) { - status->band = ch->band; - - if (phy_mode == MODE_11B && - status->band == IEEE80211_BAND_5GHZ) - ath10k_dbg(ar, ATH10K_DBG_MGMT, "wmi mgmt rx 11b (CCK) on 5GHz\n"); + * of mgmt rx. + */ + if (channel >= 1 && channel <= 14) { + status->band = IEEE80211_BAND_2GHZ; + } else if (channel >= 36 && channel <= 165) { + status->band = IEEE80211_BAND_5GHZ; } else { - ath10k_warn(ar, "using (unreliable) phy_mode to extract band for mgmt rx\n"); - status->band = phy_mode_to_band(phy_mode); + /* Shouldn't happen unless list of advertised channels to + * mac80211 has been changed. + */ + WARN_ON_ONCE(1); + dev_kfree_skb(skb); + return 0; } + if (phy_mode == MODE_11B && status->band == IEEE80211_BAND_5GHZ) + ath10k_dbg(ar, ATH10K_DBG_MGMT, "wmi mgmt rx 11b (CCK) on 5GHz\n"); + status->freq = ieee80211_channel_to_frequency(channel, status->band); status->signal = snr + ATH10K_DEFAULT_NOISE_FLOOR; status->rate_idx = get_rate_idx(rate, status->band); @@ -1295,14 +1335,196 @@ static int ath10k_wmi_event_debug_mesg(struct ath10k *ar, struct sk_buff *skb) return 0; } +static void ath10k_wmi_pull_pdev_stats(const struct wmi_pdev_stats *src, + struct ath10k_fw_stats_pdev *dst) +{ + const struct wal_dbg_tx_stats *tx = &src->wal.tx; + const struct wal_dbg_rx_stats *rx = &src->wal.rx; + + dst->ch_noise_floor = __le32_to_cpu(src->chan_nf); + dst->tx_frame_count = __le32_to_cpu(src->tx_frame_count); + dst->rx_frame_count = __le32_to_cpu(src->rx_frame_count); + dst->rx_clear_count = __le32_to_cpu(src->rx_clear_count); + dst->cycle_count = __le32_to_cpu(src->cycle_count); + dst->phy_err_count = __le32_to_cpu(src->phy_err_count); + dst->chan_tx_power = __le32_to_cpu(src->chan_tx_pwr); + + dst->comp_queued = __le32_to_cpu(tx->comp_queued); + dst->comp_delivered = __le32_to_cpu(tx->comp_delivered); + dst->msdu_enqued = __le32_to_cpu(tx->msdu_enqued); + dst->mpdu_enqued = __le32_to_cpu(tx->mpdu_enqued); + dst->wmm_drop = __le32_to_cpu(tx->wmm_drop); + dst->local_enqued = __le32_to_cpu(tx->local_enqued); + dst->local_freed = __le32_to_cpu(tx->local_freed); + dst->hw_queued = __le32_to_cpu(tx->hw_queued); + dst->hw_reaped = __le32_to_cpu(tx->hw_reaped); + dst->underrun = __le32_to_cpu(tx->underrun); + dst->tx_abort = __le32_to_cpu(tx->tx_abort); + dst->mpdus_requed = __le32_to_cpu(tx->mpdus_requed); + dst->tx_ko = __le32_to_cpu(tx->tx_ko); + dst->data_rc = __le32_to_cpu(tx->data_rc); + dst->self_triggers = __le32_to_cpu(tx->self_triggers); + dst->sw_retry_failure = __le32_to_cpu(tx->sw_retry_failure); + dst->illgl_rate_phy_err = __le32_to_cpu(tx->illgl_rate_phy_err); + dst->pdev_cont_xretry = __le32_to_cpu(tx->pdev_cont_xretry); + dst->pdev_tx_timeout = __le32_to_cpu(tx->pdev_tx_timeout); + dst->pdev_resets = __le32_to_cpu(tx->pdev_resets); + dst->phy_underrun = __le32_to_cpu(tx->phy_underrun); + dst->txop_ovf = __le32_to_cpu(tx->txop_ovf); + + dst->mid_ppdu_route_change = __le32_to_cpu(rx->mid_ppdu_route_change); + dst->status_rcvd = __le32_to_cpu(rx->status_rcvd); + dst->r0_frags = __le32_to_cpu(rx->r0_frags); + dst->r1_frags = __le32_to_cpu(rx->r1_frags); + dst->r2_frags = __le32_to_cpu(rx->r2_frags); + dst->r3_frags = __le32_to_cpu(rx->r3_frags); + dst->htt_msdus = __le32_to_cpu(rx->htt_msdus); + dst->htt_mpdus = __le32_to_cpu(rx->htt_mpdus); + dst->loc_msdus = __le32_to_cpu(rx->loc_msdus); + dst->loc_mpdus = __le32_to_cpu(rx->loc_mpdus); + dst->oversize_amsdu = __le32_to_cpu(rx->oversize_amsdu); + dst->phy_errs = __le32_to_cpu(rx->phy_errs); + dst->phy_err_drop = __le32_to_cpu(rx->phy_err_drop); + dst->mpdu_errs = __le32_to_cpu(rx->mpdu_errs); +} + +static void ath10k_wmi_pull_peer_stats(const struct wmi_peer_stats *src, + struct ath10k_fw_stats_peer *dst) +{ + ether_addr_copy(dst->peer_macaddr, src->peer_macaddr.addr); + dst->peer_rssi = __le32_to_cpu(src->peer_rssi); + dst->peer_tx_rate = __le32_to_cpu(src->peer_tx_rate); +} + +static int ath10k_wmi_main_pull_fw_stats(struct ath10k *ar, + struct sk_buff *skb, + struct ath10k_fw_stats *stats) +{ + const struct wmi_stats_event *ev = (void *)skb->data; + u32 num_pdev_stats, num_vdev_stats, num_peer_stats; + int i; + + if (!skb_pull(skb, sizeof(*ev))) + return -EPROTO; + + num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats); + num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats); + num_peer_stats = __le32_to_cpu(ev->num_peer_stats); + + for (i = 0; i < num_pdev_stats; i++) { + const struct wmi_pdev_stats *src; + struct ath10k_fw_stats_pdev *dst; + + src = (void *)skb->data; + if (!skb_pull(skb, sizeof(*src))) + return -EPROTO; + + dst = kzalloc(sizeof(*dst), GFP_ATOMIC); + if (!dst) + continue; + + ath10k_wmi_pull_pdev_stats(src, dst); + list_add_tail(&dst->list, &stats->pdevs); + } + + /* fw doesn't implement vdev stats */ + + for (i = 0; i < num_peer_stats; i++) { + const struct wmi_peer_stats *src; + struct ath10k_fw_stats_peer *dst; + + src = (void *)skb->data; + if (!skb_pull(skb, sizeof(*src))) + return -EPROTO; + + dst = kzalloc(sizeof(*dst), GFP_ATOMIC); + if (!dst) + continue; + + ath10k_wmi_pull_peer_stats(src, dst); + list_add_tail(&dst->list, &stats->peers); + } + + return 0; +} + +static int ath10k_wmi_10x_pull_fw_stats(struct ath10k *ar, + struct sk_buff *skb, + struct ath10k_fw_stats *stats) +{ + const struct wmi_stats_event *ev = (void *)skb->data; + u32 num_pdev_stats, num_vdev_stats, num_peer_stats; + int i; + + if (!skb_pull(skb, sizeof(*ev))) + return -EPROTO; + + num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats); + num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats); + num_peer_stats = __le32_to_cpu(ev->num_peer_stats); + + for (i = 0; i < num_pdev_stats; i++) { + const struct wmi_10x_pdev_stats *src; + struct ath10k_fw_stats_pdev *dst; + + src = (void *)skb->data; + if (!skb_pull(skb, sizeof(*src))) + return -EPROTO; + + dst = kzalloc(sizeof(*dst), GFP_ATOMIC); + if (!dst) + continue; + + ath10k_wmi_pull_pdev_stats(&src->old, dst); + + dst->ack_rx_bad = __le32_to_cpu(src->ack_rx_bad); + dst->rts_bad = __le32_to_cpu(src->rts_bad); + dst->rts_good = __le32_to_cpu(src->rts_good); + dst->fcs_bad = __le32_to_cpu(src->fcs_bad); + dst->no_beacons = __le32_to_cpu(src->no_beacons); + dst->mib_int_count = __le32_to_cpu(src->mib_int_count); + + list_add_tail(&dst->list, &stats->pdevs); + } + + /* fw doesn't implement vdev stats */ + + for (i = 0; i < num_peer_stats; i++) { + const struct wmi_10x_peer_stats *src; + struct ath10k_fw_stats_peer *dst; + + src = (void *)skb->data; + if (!skb_pull(skb, sizeof(*src))) + return -EPROTO; + + dst = kzalloc(sizeof(*dst), GFP_ATOMIC); + if (!dst) + continue; + + ath10k_wmi_pull_peer_stats(&src->old, dst); + + dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate); + + list_add_tail(&dst->list, &stats->peers); + } + + return 0; +} + +int ath10k_wmi_pull_fw_stats(struct ath10k *ar, struct sk_buff *skb, + struct ath10k_fw_stats *stats) +{ + if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) + return ath10k_wmi_10x_pull_fw_stats(ar, skb, stats); + else + return ath10k_wmi_main_pull_fw_stats(ar, skb, stats); +} + static void ath10k_wmi_event_update_stats(struct ath10k *ar, struct sk_buff *skb) { - struct wmi_stats_event *ev = (struct wmi_stats_event *)skb->data; - ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_UPDATE_STATS_EVENTID\n"); - - ath10k_debug_read_target_stats(ar, ev); + ath10k_debug_fw_stats_process(ar, skb); } static void ath10k_wmi_event_vdev_start_resp(struct ath10k *ar, @@ -1579,6 +1801,7 @@ static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb) struct wmi_bcn_info *bcn_info; struct ath10k_vif *arvif; struct sk_buff *bcn; + dma_addr_t paddr; int ret, vdev_id = 0; ev = (struct wmi_host_swba_event *)skb->data; @@ -1647,27 +1870,37 @@ static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb) ath10k_warn(ar, "SWBA overrun on vdev %d\n", arvif->vdev_id); - dma_unmap_single(arvif->ar->dev, - ATH10K_SKB_CB(arvif->beacon)->paddr, - arvif->beacon->len, DMA_TO_DEVICE); - dev_kfree_skb_any(arvif->beacon); - arvif->beacon = NULL; + ath10k_mac_vif_beacon_free(arvif); } - ATH10K_SKB_CB(bcn)->paddr = dma_map_single(arvif->ar->dev, - bcn->data, bcn->len, - DMA_TO_DEVICE); - ret = dma_mapping_error(arvif->ar->dev, - ATH10K_SKB_CB(bcn)->paddr); - if (ret) { - ath10k_warn(ar, "failed to map beacon: %d\n", ret); - dev_kfree_skb_any(bcn); - goto skip; + if (!arvif->beacon_buf) { + paddr = dma_map_single(arvif->ar->dev, bcn->data, + bcn->len, DMA_TO_DEVICE); + ret = dma_mapping_error(arvif->ar->dev, paddr); + if (ret) { + ath10k_warn(ar, "failed to map beacon: %d\n", + ret); + dev_kfree_skb_any(bcn); + goto skip; + } + + ATH10K_SKB_CB(bcn)->paddr = paddr; + } else { + if (bcn->len > IEEE80211_MAX_FRAME_LEN) { + ath10k_warn(ar, "trimming beacon %d -> %d bytes!\n", + bcn->len, IEEE80211_MAX_FRAME_LEN); + skb_trim(bcn, IEEE80211_MAX_FRAME_LEN); + } + memcpy(arvif->beacon_buf, bcn->data, bcn->len); + ATH10K_SKB_CB(bcn)->paddr = arvif->beacon_paddr; } arvif->beacon = bcn; arvif->beacon_sent = false; + trace_ath10k_tx_hdr(ar, bcn->data, bcn->len); + trace_ath10k_tx_payload(ar, bcn->data, bcn->len); + ath10k_wmi_tx_beacon_nowait(arvif); skip: spin_unlock_bh(&ar->data_lock); @@ -1681,8 +1914,8 @@ static void ath10k_wmi_event_tbttoffset_update(struct ath10k *ar, } static void ath10k_dfs_radar_report(struct ath10k *ar, - struct wmi_single_phyerr_rx_event *event, - struct phyerr_radar_report *rr, + const struct wmi_phyerr *phyerr, + const struct phyerr_radar_report *rr, u64 tsf) { u32 reg0, reg1, tsf32l; @@ -1715,12 +1948,12 @@ static void ath10k_dfs_radar_report(struct ath10k *ar, return; /* report event to DFS pattern detector */ - tsf32l = __le32_to_cpu(event->hdr.tsf_timestamp); + tsf32l = __le32_to_cpu(phyerr->tsf_timestamp); tsf64 = tsf & (~0xFFFFFFFFULL); tsf64 |= tsf32l; width = MS(reg1, RADAR_REPORT_REG1_PULSE_DUR); - rssi = event->hdr.rssi_combined; + rssi = phyerr->rssi_combined; /* hardware store this as 8 bit signed value, * set to zero if negative number @@ -1759,8 +1992,8 @@ static void ath10k_dfs_radar_report(struct ath10k *ar, } static int ath10k_dfs_fft_report(struct ath10k *ar, - struct wmi_single_phyerr_rx_event *event, - struct phyerr_fft_report *fftr, + const struct wmi_phyerr *phyerr, + const struct phyerr_fft_report *fftr, u64 tsf) { u32 reg0, reg1; @@ -1768,7 +2001,7 @@ static int ath10k_dfs_fft_report(struct ath10k *ar, reg0 = __le32_to_cpu(fftr->reg0); reg1 = __le32_to_cpu(fftr->reg1); - rssi = event->hdr.rssi_combined; + rssi = phyerr->rssi_combined; ath10k_dbg(ar, ATH10K_DBG_REGULATORY, "wmi phyerr fft report total_gain_db %d base_pwr_db %d fft_chn_idx %d peak_sidx %d\n", @@ -1797,20 +2030,20 @@ static int ath10k_dfs_fft_report(struct ath10k *ar, } static void ath10k_wmi_event_dfs(struct ath10k *ar, - struct wmi_single_phyerr_rx_event *event, + const struct wmi_phyerr *phyerr, u64 tsf) { int buf_len, tlv_len, res, i = 0; - struct phyerr_tlv *tlv; - struct phyerr_radar_report *rr; - struct phyerr_fft_report *fftr; - u8 *tlv_buf; + const struct phyerr_tlv *tlv; + const struct phyerr_radar_report *rr; + const struct phyerr_fft_report *fftr; + const u8 *tlv_buf; - buf_len = __le32_to_cpu(event->hdr.buf_len); + buf_len = __le32_to_cpu(phyerr->buf_len); ath10k_dbg(ar, ATH10K_DBG_REGULATORY, "wmi event dfs err_code %d rssi %d tsfl 0x%X tsf64 0x%llX len %d\n", - event->hdr.phy_err_code, event->hdr.rssi_combined, - __le32_to_cpu(event->hdr.tsf_timestamp), tsf, buf_len); + phyerr->phy_err_code, phyerr->rssi_combined, + __le32_to_cpu(phyerr->tsf_timestamp), tsf, buf_len); /* Skip event if DFS disabled */ if (!config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)) @@ -1825,9 +2058,9 @@ static void ath10k_wmi_event_dfs(struct ath10k *ar, return; } - tlv = (struct phyerr_tlv *)&event->bufp[i]; + tlv = (struct phyerr_tlv *)&phyerr->buf[i]; tlv_len = __le16_to_cpu(tlv->len); - tlv_buf = &event->bufp[i + sizeof(*tlv)]; + tlv_buf = &phyerr->buf[i + sizeof(*tlv)]; ath10k_dbg(ar, ATH10K_DBG_REGULATORY, "wmi event dfs tlv_len %d tlv_tag 0x%02X tlv_sig 0x%02X\n", tlv_len, tlv->tag, tlv->sig); @@ -1841,7 +2074,7 @@ static void ath10k_wmi_event_dfs(struct ath10k *ar, } rr = (struct phyerr_radar_report *)tlv_buf; - ath10k_dfs_radar_report(ar, event, rr, tsf); + ath10k_dfs_radar_report(ar, phyerr, rr, tsf); break; case PHYERR_TLV_TAG_SEARCH_FFT_REPORT: if (i + sizeof(*tlv) + sizeof(*fftr) > buf_len) { @@ -1851,7 +2084,7 @@ static void ath10k_wmi_event_dfs(struct ath10k *ar, } fftr = (struct phyerr_fft_report *)tlv_buf; - res = ath10k_dfs_fft_report(ar, event, fftr, tsf); + res = ath10k_dfs_fft_report(ar, phyerr, fftr, tsf); if (res) return; break; @@ -1863,16 +2096,16 @@ static void ath10k_wmi_event_dfs(struct ath10k *ar, static void ath10k_wmi_event_spectral_scan(struct ath10k *ar, - struct wmi_single_phyerr_rx_event *event, + const struct wmi_phyerr *phyerr, u64 tsf) { int buf_len, tlv_len, res, i = 0; struct phyerr_tlv *tlv; - u8 *tlv_buf; - struct phyerr_fft_report *fftr; + const void *tlv_buf; + const struct phyerr_fft_report *fftr; size_t fftr_len; - buf_len = __le32_to_cpu(event->hdr.buf_len); + buf_len = __le32_to_cpu(phyerr->buf_len); while (i < buf_len) { if (i + sizeof(*tlv) > buf_len) { @@ -1881,9 +2114,9 @@ ath10k_wmi_event_spectral_scan(struct ath10k *ar, return; } - tlv = (struct phyerr_tlv *)&event->bufp[i]; + tlv = (struct phyerr_tlv *)&phyerr->buf[i]; tlv_len = __le16_to_cpu(tlv->len); - tlv_buf = &event->bufp[i + sizeof(*tlv)]; + tlv_buf = &phyerr->buf[i + sizeof(*tlv)]; if (i + sizeof(*tlv) + tlv_len > buf_len) { ath10k_warn(ar, "failed to parse phyerr tlv payload at byte %d\n", @@ -1900,8 +2133,8 @@ ath10k_wmi_event_spectral_scan(struct ath10k *ar, } fftr_len = tlv_len - sizeof(*fftr); - fftr = (struct phyerr_fft_report *)tlv_buf; - res = ath10k_spectral_process_fft(ar, event, + fftr = tlv_buf; + res = ath10k_spectral_process_fft(ar, phyerr, fftr, fftr_len, tsf); if (res < 0) { @@ -1918,8 +2151,8 @@ ath10k_wmi_event_spectral_scan(struct ath10k *ar, static void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb) { - struct wmi_comb_phyerr_rx_event *comb_event; - struct wmi_single_phyerr_rx_event *event; + const struct wmi_phyerr_event *ev; + const struct wmi_phyerr *phyerr; u32 count, i, buf_len, phy_err_code; u64 tsf; int left_len = skb->len; @@ -1927,38 +2160,38 @@ static void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb) ATH10K_DFS_STAT_INC(ar, phy_errors); /* Check if combined event available */ - if (left_len < sizeof(*comb_event)) { + if (left_len < sizeof(*ev)) { ath10k_warn(ar, "wmi phyerr combined event wrong len\n"); return; } - left_len -= sizeof(*comb_event); + left_len -= sizeof(*ev); /* Check number of included events */ - comb_event = (struct wmi_comb_phyerr_rx_event *)skb->data; - count = __le32_to_cpu(comb_event->hdr.num_phyerr_events); + ev = (const struct wmi_phyerr_event *)skb->data; + count = __le32_to_cpu(ev->num_phyerrs); - tsf = __le32_to_cpu(comb_event->hdr.tsf_u32); + tsf = __le32_to_cpu(ev->tsf_u32); tsf <<= 32; - tsf |= __le32_to_cpu(comb_event->hdr.tsf_l32); + tsf |= __le32_to_cpu(ev->tsf_l32); ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi event phyerr count %d tsf64 0x%llX\n", count, tsf); - event = (struct wmi_single_phyerr_rx_event *)comb_event->bufp; + phyerr = ev->phyerrs; for (i = 0; i < count; i++) { /* Check if we can read event header */ - if (left_len < sizeof(*event)) { + if (left_len < sizeof(*phyerr)) { ath10k_warn(ar, "single event (%d) wrong head len\n", i); return; } - left_len -= sizeof(*event); + left_len -= sizeof(*phyerr); - buf_len = __le32_to_cpu(event->hdr.buf_len); - phy_err_code = event->hdr.phy_err_code; + buf_len = __le32_to_cpu(phyerr->buf_len); + phy_err_code = phyerr->phy_err_code; if (left_len < buf_len) { ath10k_warn(ar, "single event (%d) wrong buf len\n", i); @@ -1969,20 +2202,20 @@ static void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb) switch (phy_err_code) { case PHY_ERROR_RADAR: - ath10k_wmi_event_dfs(ar, event, tsf); + ath10k_wmi_event_dfs(ar, phyerr, tsf); break; case PHY_ERROR_SPECTRAL_SCAN: - ath10k_wmi_event_spectral_scan(ar, event, tsf); + ath10k_wmi_event_spectral_scan(ar, phyerr, tsf); break; case PHY_ERROR_FALSE_RADAR_EXT: - ath10k_wmi_event_dfs(ar, event, tsf); - ath10k_wmi_event_spectral_scan(ar, event, tsf); + ath10k_wmi_event_dfs(ar, phyerr, tsf); + ath10k_wmi_event_spectral_scan(ar, phyerr, tsf); break; default: break; } - event += sizeof(*event) + buf_len; + phyerr = (void *)phyerr + sizeof(*phyerr) + buf_len; } } @@ -2163,30 +2396,113 @@ static int ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id, return 0; } -static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar, - struct sk_buff *skb) +static int ath10k_wmi_main_pull_svc_rdy_ev(struct sk_buff *skb, + struct wmi_svc_rdy_ev_arg *arg) { - struct wmi_service_ready_event *ev = (void *)skb->data; + struct wmi_service_ready_event *ev; + size_t i, n; + + if (skb->len < sizeof(*ev)) + return -EPROTO; + + ev = (void *)skb->data; + skb_pull(skb, sizeof(*ev)); + arg->min_tx_power = ev->hw_min_tx_power; + arg->max_tx_power = ev->hw_max_tx_power; + arg->ht_cap = ev->ht_cap_info; + arg->vht_cap = ev->vht_cap_info; + arg->sw_ver0 = ev->sw_version; + arg->sw_ver1 = ev->sw_version_1; + arg->phy_capab = ev->phy_capability; + arg->num_rf_chains = ev->num_rf_chains; + arg->eeprom_rd = ev->hal_reg_capabilities.eeprom_rd; + arg->num_mem_reqs = ev->num_mem_reqs; + arg->service_map = ev->wmi_service_bitmap; + + n = min_t(size_t, __le32_to_cpu(arg->num_mem_reqs), + ARRAY_SIZE(arg->mem_reqs)); + for (i = 0; i < n; i++) + arg->mem_reqs[i] = &ev->mem_reqs[i]; + + if (skb->len < + __le32_to_cpu(arg->num_mem_reqs) * sizeof(arg->mem_reqs[0])) + return -EPROTO; + + return 0; +} + +static int ath10k_wmi_10x_pull_svc_rdy_ev(struct sk_buff *skb, + struct wmi_svc_rdy_ev_arg *arg) +{ + struct wmi_10x_service_ready_event *ev; + int i, n; + + if (skb->len < sizeof(*ev)) + return -EPROTO; + + ev = (void *)skb->data; + skb_pull(skb, sizeof(*ev)); + arg->min_tx_power = ev->hw_min_tx_power; + arg->max_tx_power = ev->hw_max_tx_power; + arg->ht_cap = ev->ht_cap_info; + arg->vht_cap = ev->vht_cap_info; + arg->sw_ver0 = ev->sw_version; + arg->phy_capab = ev->phy_capability; + arg->num_rf_chains = ev->num_rf_chains; + arg->eeprom_rd = ev->hal_reg_capabilities.eeprom_rd; + arg->num_mem_reqs = ev->num_mem_reqs; + arg->service_map = ev->wmi_service_bitmap; + + n = min_t(size_t, __le32_to_cpu(arg->num_mem_reqs), + ARRAY_SIZE(arg->mem_reqs)); + for (i = 0; i < n; i++) + arg->mem_reqs[i] = &ev->mem_reqs[i]; + + if (skb->len < + __le32_to_cpu(arg->num_mem_reqs) * sizeof(arg->mem_reqs[0])) + return -EPROTO; + + return 0; +} + +static void ath10k_wmi_event_service_ready(struct ath10k *ar, + struct sk_buff *skb) +{ + struct wmi_svc_rdy_ev_arg arg = {}; + u32 num_units, req_id, unit_size, num_mem_reqs, num_unit_info, i; DECLARE_BITMAP(svc_bmap, WMI_SERVICE_MAX) = {}; + int ret; + + if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) { + ret = ath10k_wmi_10x_pull_svc_rdy_ev(skb, &arg); + wmi_10x_svc_map(arg.service_map, svc_bmap); + } else { + ret = ath10k_wmi_main_pull_svc_rdy_ev(skb, &arg); + wmi_main_svc_map(arg.service_map, svc_bmap); + } - if (skb->len < sizeof(*ev)) { - ath10k_warn(ar, "Service ready event was %d B but expected %zu B. Wrong firmware version?\n", - skb->len, sizeof(*ev)); + if (ret) { + ath10k_warn(ar, "failed to parse service ready: %d\n", ret); return; } - ar->hw_min_tx_power = __le32_to_cpu(ev->hw_min_tx_power); - ar->hw_max_tx_power = __le32_to_cpu(ev->hw_max_tx_power); - ar->ht_cap_info = __le32_to_cpu(ev->ht_cap_info); - ar->vht_cap_info = __le32_to_cpu(ev->vht_cap_info); + ar->hw_min_tx_power = __le32_to_cpu(arg.min_tx_power); + ar->hw_max_tx_power = __le32_to_cpu(arg.max_tx_power); + ar->ht_cap_info = __le32_to_cpu(arg.ht_cap); + ar->vht_cap_info = __le32_to_cpu(arg.vht_cap); ar->fw_version_major = - (__le32_to_cpu(ev->sw_version) & 0xff000000) >> 24; - ar->fw_version_minor = (__le32_to_cpu(ev->sw_version) & 0x00ffffff); + (__le32_to_cpu(arg.sw_ver0) & 0xff000000) >> 24; + ar->fw_version_minor = (__le32_to_cpu(arg.sw_ver0) & 0x00ffffff); ar->fw_version_release = - (__le32_to_cpu(ev->sw_version_1) & 0xffff0000) >> 16; - ar->fw_version_build = (__le32_to_cpu(ev->sw_version_1) & 0x0000ffff); - ar->phy_capability = __le32_to_cpu(ev->phy_capability); - ar->num_rf_chains = __le32_to_cpu(ev->num_rf_chains); + (__le32_to_cpu(arg.sw_ver1) & 0xffff0000) >> 16; + ar->fw_version_build = (__le32_to_cpu(arg.sw_ver1) & 0x0000ffff); + ar->phy_capability = __le32_to_cpu(arg.phy_capab); + ar->num_rf_chains = __le32_to_cpu(arg.num_rf_chains); + ar->ath_common.regulatory.current_rd = __le32_to_cpu(arg.eeprom_rd); + + ath10k_debug_read_service_map(ar, svc_bmap, sizeof(svc_bmap)); + ath10k_dbg_dump(ar, ATH10K_DBG_WMI, NULL, "wmi svc: ", + arg.service_map, sizeof(arg.service_map)); /* only manually set fw features when not using FW IE format */ if (ar->fw_api == 1 && ar->fw_version_build > 636) @@ -2198,13 +2514,8 @@ static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar, ar->num_rf_chains = WMI_MAX_SPATIAL_STREAM; } - ar->ath_common.regulatory.current_rd = - __le32_to_cpu(ev->hal_reg_capabilities.eeprom_rd); - - wmi_main_svc_map(ev->wmi_service_bitmap, svc_bmap); - ath10k_debug_read_service_map(ar, svc_bmap, sizeof(svc_bmap)); - ath10k_dbg_dump(ar, ATH10K_DBG_WMI, NULL, "wmi svc: ", - ev->wmi_service_bitmap, sizeof(ev->wmi_service_bitmap)); + ar->supp_tx_chainmask = (1 << ar->num_rf_chains) - 1; + ar->supp_rx_chainmask = (1 << ar->num_rf_chains) - 1; if (strlen(ar->hw->wiphy->fw_version) == 0) { snprintf(ar->hw->wiphy->fw_version, @@ -2216,93 +2527,18 @@ static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar, ar->fw_version_build); } - /* FIXME: it probably should be better to support this */ - if (__le32_to_cpu(ev->num_mem_reqs) > 0) { - ath10k_warn(ar, "target requested %d memory chunks; ignoring\n", - __le32_to_cpu(ev->num_mem_reqs)); - } - - ath10k_dbg(ar, ATH10K_DBG_WMI, - "wmi event service ready sw_ver 0x%08x sw_ver1 0x%08x abi_ver %u phy_cap 0x%08x ht_cap 0x%08x vht_cap 0x%08x vht_supp_msc 0x%08x sys_cap_info 0x%08x mem_reqs %u num_rf_chains %u\n", - __le32_to_cpu(ev->sw_version), - __le32_to_cpu(ev->sw_version_1), - __le32_to_cpu(ev->abi_version), - __le32_to_cpu(ev->phy_capability), - __le32_to_cpu(ev->ht_cap_info), - __le32_to_cpu(ev->vht_cap_info), - __le32_to_cpu(ev->vht_supp_mcs), - __le32_to_cpu(ev->sys_cap_info), - __le32_to_cpu(ev->num_mem_reqs), - __le32_to_cpu(ev->num_rf_chains)); - - complete(&ar->wmi.service_ready); -} - -static void ath10k_wmi_10x_service_ready_event_rx(struct ath10k *ar, - struct sk_buff *skb) -{ - u32 num_units, req_id, unit_size, num_mem_reqs, num_unit_info, i; - int ret; - struct wmi_service_ready_event_10x *ev = (void *)skb->data; - DECLARE_BITMAP(svc_bmap, WMI_SERVICE_MAX) = {}; - - if (skb->len < sizeof(*ev)) { - ath10k_warn(ar, "Service ready event was %d B but expected %zu B. Wrong firmware version?\n", - skb->len, sizeof(*ev)); - return; - } - - ar->hw_min_tx_power = __le32_to_cpu(ev->hw_min_tx_power); - ar->hw_max_tx_power = __le32_to_cpu(ev->hw_max_tx_power); - ar->ht_cap_info = __le32_to_cpu(ev->ht_cap_info); - ar->vht_cap_info = __le32_to_cpu(ev->vht_cap_info); - ar->fw_version_major = - (__le32_to_cpu(ev->sw_version) & 0xff000000) >> 24; - ar->fw_version_minor = (__le32_to_cpu(ev->sw_version) & 0x00ffffff); - ar->phy_capability = __le32_to_cpu(ev->phy_capability); - ar->num_rf_chains = __le32_to_cpu(ev->num_rf_chains); - - if (ar->num_rf_chains > WMI_MAX_SPATIAL_STREAM) { - ath10k_warn(ar, "hardware advertises support for more spatial streams than it should (%d > %d)\n", - ar->num_rf_chains, WMI_MAX_SPATIAL_STREAM); - ar->num_rf_chains = WMI_MAX_SPATIAL_STREAM; - } - - ar->ath_common.regulatory.current_rd = - __le32_to_cpu(ev->hal_reg_capabilities.eeprom_rd); - - wmi_10x_svc_map(ev->wmi_service_bitmap, svc_bmap); - ath10k_debug_read_service_map(ar, svc_bmap, sizeof(svc_bmap)); - ath10k_dbg_dump(ar, ATH10K_DBG_WMI, NULL, "wmi svc: ", - ev->wmi_service_bitmap, sizeof(ev->wmi_service_bitmap)); - - if (strlen(ar->hw->wiphy->fw_version) == 0) { - snprintf(ar->hw->wiphy->fw_version, - sizeof(ar->hw->wiphy->fw_version), - "%u.%u", - ar->fw_version_major, - ar->fw_version_minor); - } - - num_mem_reqs = __le32_to_cpu(ev->num_mem_reqs); - - if (num_mem_reqs > ATH10K_MAX_MEM_REQS) { + num_mem_reqs = __le32_to_cpu(arg.num_mem_reqs); + if (num_mem_reqs > WMI_MAX_MEM_REQS) { ath10k_warn(ar, "requested memory chunks number (%d) exceeds the limit\n", num_mem_reqs); return; } - if (!num_mem_reqs) - goto exit; - - ath10k_dbg(ar, ATH10K_DBG_WMI, "firmware has requested %d memory chunks\n", - num_mem_reqs); - for (i = 0; i < num_mem_reqs; ++i) { - req_id = __le32_to_cpu(ev->mem_reqs[i].req_id); - num_units = __le32_to_cpu(ev->mem_reqs[i].num_units); - unit_size = __le32_to_cpu(ev->mem_reqs[i].unit_size); - num_unit_info = __le32_to_cpu(ev->mem_reqs[i].num_unit_info); + req_id = __le32_to_cpu(arg.mem_reqs[i]->req_id); + num_units = __le32_to_cpu(arg.mem_reqs[i]->num_units); + unit_size = __le32_to_cpu(arg.mem_reqs[i]->unit_size); + num_unit_info = __le32_to_cpu(arg.mem_reqs[i]->num_unit_info); if (num_unit_info & NUM_UNITS_IS_NUM_PEERS) /* number of units to allocate is number of @@ -2316,7 +2552,7 @@ static void ath10k_wmi_10x_service_ready_event_rx(struct ath10k *ar, ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi mem_req_id %d num_units %d num_unit_info %d unit size %d actual units %d\n", req_id, - __le32_to_cpu(ev->mem_reqs[i].num_units), + __le32_to_cpu(arg.mem_reqs[i]->num_units), num_unit_info, unit_size, num_units); @@ -2327,23 +2563,23 @@ static void ath10k_wmi_10x_service_ready_event_rx(struct ath10k *ar, return; } -exit: ath10k_dbg(ar, ATH10K_DBG_WMI, - "wmi event service ready sw_ver 0x%08x abi_ver %u phy_cap 0x%08x ht_cap 0x%08x vht_cap 0x%08x vht_supp_msc 0x%08x sys_cap_info 0x%08x mem_reqs %u num_rf_chains %u\n", - __le32_to_cpu(ev->sw_version), - __le32_to_cpu(ev->abi_version), - __le32_to_cpu(ev->phy_capability), - __le32_to_cpu(ev->ht_cap_info), - __le32_to_cpu(ev->vht_cap_info), - __le32_to_cpu(ev->vht_supp_mcs), - __le32_to_cpu(ev->sys_cap_info), - __le32_to_cpu(ev->num_mem_reqs), - __le32_to_cpu(ev->num_rf_chains)); + "wmi event service ready min_tx_power 0x%08x max_tx_power 0x%08x ht_cap 0x%08x vht_cap 0x%08x sw_ver0 0x%08x sw_ver1 0x%08x phy_capab 0x%08x num_rf_chains 0x%08x eeprom_rd 0x%08x num_mem_reqs 0x%08x\n", + __le32_to_cpu(arg.min_tx_power), + __le32_to_cpu(arg.max_tx_power), + __le32_to_cpu(arg.ht_cap), + __le32_to_cpu(arg.vht_cap), + __le32_to_cpu(arg.sw_ver0), + __le32_to_cpu(arg.sw_ver1), + __le32_to_cpu(arg.phy_capab), + __le32_to_cpu(arg.num_rf_chains), + __le32_to_cpu(arg.eeprom_rd), + __le32_to_cpu(arg.num_mem_reqs)); complete(&ar->wmi.service_ready); } -static int ath10k_wmi_ready_event_rx(struct ath10k *ar, struct sk_buff *skb) +static int ath10k_wmi_event_ready(struct ath10k *ar, struct sk_buff *skb) { struct wmi_ready_event *ev = (struct wmi_ready_event *)skb->data; @@ -2466,10 +2702,10 @@ static void ath10k_wmi_main_process_rx(struct ath10k *ar, struct sk_buff *skb) ath10k_wmi_event_vdev_install_key_complete(ar, skb); break; case WMI_SERVICE_READY_EVENTID: - ath10k_wmi_service_ready_event_rx(ar, skb); + ath10k_wmi_event_service_ready(ar, skb); break; case WMI_READY_EVENTID: - ath10k_wmi_ready_event_rx(ar, skb); + ath10k_wmi_event_ready(ar, skb); break; default: ath10k_warn(ar, "Unknown eventid: %d\n", id); @@ -2586,10 +2822,10 @@ static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb) ath10k_wmi_event_vdev_resume_req(ar, skb); break; case WMI_10X_SERVICE_READY_EVENTID: - ath10k_wmi_10x_service_ready_event_rx(ar, skb); + ath10k_wmi_event_service_ready(ar, skb); break; case WMI_10X_READY_EVENTID: - ath10k_wmi_ready_event_rx(ar, skb); + ath10k_wmi_event_ready(ar, skb); break; case WMI_10X_PDEV_UTF_EVENTID: /* ignore utf events */ @@ -2697,10 +2933,10 @@ static void ath10k_wmi_10_2_process_rx(struct ath10k *ar, struct sk_buff *skb) ath10k_wmi_event_vdev_resume_req(ar, skb); break; case WMI_10_2_SERVICE_READY_EVENTID: - ath10k_wmi_10x_service_ready_event_rx(ar, skb); + ath10k_wmi_event_service_ready(ar, skb); break; case WMI_10_2_READY_EVENTID: - ath10k_wmi_ready_event_rx(ar, skb); + ath10k_wmi_event_ready(ar, skb); break; case WMI_10_2_RTT_KEEPALIVE_EVENTID: case WMI_10_2_GPIO_INPUT_EVENTID: @@ -2732,45 +2968,6 @@ static void ath10k_wmi_process_rx(struct ath10k *ar, struct sk_buff *skb) } } -/* WMI Initialization functions */ -int ath10k_wmi_attach(struct ath10k *ar) -{ - if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) { - if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, ar->fw_features)) - ar->wmi.cmd = &wmi_10_2_cmd_map; - else - ar->wmi.cmd = &wmi_10x_cmd_map; - - ar->wmi.vdev_param = &wmi_10x_vdev_param_map; - ar->wmi.pdev_param = &wmi_10x_pdev_param_map; - } else { - ar->wmi.cmd = &wmi_cmd_map; - ar->wmi.vdev_param = &wmi_vdev_param_map; - ar->wmi.pdev_param = &wmi_pdev_param_map; - } - - init_completion(&ar->wmi.service_ready); - init_completion(&ar->wmi.unified_ready); - init_waitqueue_head(&ar->wmi.tx_credits_wq); - - return 0; -} - -void ath10k_wmi_detach(struct ath10k *ar) -{ - int i; - - /* free the host memory chunks requested by firmware */ - for (i = 0; i < ar->wmi.num_mem_chunks; i++) { - dma_free_coherent(ar->dev, - ar->wmi.mem_chunks[i].len, - ar->wmi.mem_chunks[i].vaddr, - ar->wmi.mem_chunks[i].paddr); - } - - ar->wmi.num_mem_chunks = 0; -} - int ath10k_wmi_connect(struct ath10k *ar) { int status; @@ -2865,42 +3062,6 @@ int ath10k_wmi_pdev_set_regdomain(struct ath10k *ar, u16 rd, u16 rd2g, ctl2g, ctl5g); } -int ath10k_wmi_pdev_set_channel(struct ath10k *ar, - const struct wmi_channel_arg *arg) -{ - struct wmi_set_channel_cmd *cmd; - struct sk_buff *skb; - u32 ch_flags = 0; - - if (arg->passive) - return -EINVAL; - - skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd)); - if (!skb) - return -ENOMEM; - - if (arg->chan_radar) - ch_flags |= WMI_CHAN_FLAG_DFS; - - cmd = (struct wmi_set_channel_cmd *)skb->data; - cmd->chan.mhz = __cpu_to_le32(arg->freq); - cmd->chan.band_center_freq1 = __cpu_to_le32(arg->freq); - cmd->chan.mode = arg->mode; - cmd->chan.flags |= __cpu_to_le32(ch_flags); - cmd->chan.min_power = arg->min_power; - cmd->chan.max_power = arg->max_power; - cmd->chan.reg_power = arg->max_reg_power; - cmd->chan.reg_classid = arg->reg_class_id; - cmd->chan.antenna_max = arg->max_antenna_gain; - - ath10k_dbg(ar, ATH10K_DBG_WMI, - "wmi set channel mode %d freq %d\n", - arg->mode, arg->freq); - - return ath10k_wmi_cmd_send(ar, skb, - ar->wmi.cmd->pdev_set_channel_cmdid); -} - int ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt) { struct wmi_pdev_suspend_cmd *cmd; @@ -2951,13 +3112,34 @@ int ath10k_wmi_pdev_set_param(struct ath10k *ar, u32 id, u32 value) return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_set_param_cmdid); } +static void ath10k_wmi_put_host_mem_chunks(struct ath10k *ar, + struct wmi_host_mem_chunks *chunks) +{ + struct host_memory_chunk *chunk; + int i; + + chunks->count = __cpu_to_le32(ar->wmi.num_mem_chunks); + + for (i = 0; i < ar->wmi.num_mem_chunks; i++) { + chunk = &chunks->items[i]; + chunk->ptr = __cpu_to_le32(ar->wmi.mem_chunks[i].paddr); + chunk->size = __cpu_to_le32(ar->wmi.mem_chunks[i].len); + chunk->req_id = __cpu_to_le32(ar->wmi.mem_chunks[i].req_id); + + ath10k_dbg(ar, ATH10K_DBG_WMI, + "wmi chunk %d len %d requested, addr 0x%llx\n", + i, + ar->wmi.mem_chunks[i].len, + (unsigned long long)ar->wmi.mem_chunks[i].paddr); + } +} + static int ath10k_wmi_main_cmd_init(struct ath10k *ar) { struct wmi_init_cmd *cmd; struct sk_buff *buf; struct wmi_resource_config config = {}; u32 len, val; - int i; config.num_vdevs = __cpu_to_le32(TARGET_NUM_VDEVS); config.num_peers = __cpu_to_le32(TARGET_NUM_PEERS + TARGET_NUM_VDEVS); @@ -3019,32 +3201,8 @@ static int ath10k_wmi_main_cmd_init(struct ath10k *ar) cmd = (struct wmi_init_cmd *)buf->data; - if (ar->wmi.num_mem_chunks == 0) { - cmd->num_host_mem_chunks = 0; - goto out; - } - - ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi sending %d memory chunks info.\n", - ar->wmi.num_mem_chunks); - - cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks); - - for (i = 0; i < ar->wmi.num_mem_chunks; i++) { - cmd->host_mem_chunks[i].ptr = - __cpu_to_le32(ar->wmi.mem_chunks[i].paddr); - cmd->host_mem_chunks[i].size = - __cpu_to_le32(ar->wmi.mem_chunks[i].len); - cmd->host_mem_chunks[i].req_id = - __cpu_to_le32(ar->wmi.mem_chunks[i].req_id); - - ath10k_dbg(ar, ATH10K_DBG_WMI, - "wmi chunk %d len %d requested, addr 0x%llx\n", - i, - ar->wmi.mem_chunks[i].len, - (unsigned long long)ar->wmi.mem_chunks[i].paddr); - } -out: memcpy(&cmd->resource_config, &config, sizeof(config)); + ath10k_wmi_put_host_mem_chunks(ar, &cmd->mem_chunks); ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi init\n"); return ath10k_wmi_cmd_send(ar, buf, ar->wmi.cmd->init_cmdid); @@ -3056,7 +3214,6 @@ static int ath10k_wmi_10x_cmd_init(struct ath10k *ar) struct sk_buff *buf; struct wmi_resource_config_10x config = {}; u32 len, val; - int i; config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS); config.num_peers = __cpu_to_le32(TARGET_10X_NUM_PEERS); @@ -3110,32 +3267,8 @@ static int ath10k_wmi_10x_cmd_init(struct ath10k *ar) cmd = (struct wmi_init_cmd_10x *)buf->data; - if (ar->wmi.num_mem_chunks == 0) { - cmd->num_host_mem_chunks = 0; - goto out; - } - - ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi sending %d memory chunks info.\n", - ar->wmi.num_mem_chunks); - - cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks); - - for (i = 0; i < ar->wmi.num_mem_chunks; i++) { - cmd->host_mem_chunks[i].ptr = - __cpu_to_le32(ar->wmi.mem_chunks[i].paddr); - cmd->host_mem_chunks[i].size = - __cpu_to_le32(ar->wmi.mem_chunks[i].len); - cmd->host_mem_chunks[i].req_id = - __cpu_to_le32(ar->wmi.mem_chunks[i].req_id); - - ath10k_dbg(ar, ATH10K_DBG_WMI, - "wmi chunk %d len %d requested, addr 0x%llx\n", - i, - ar->wmi.mem_chunks[i].len, - (unsigned long long)ar->wmi.mem_chunks[i].paddr); - } -out: memcpy(&cmd->resource_config, &config, sizeof(config)); + ath10k_wmi_put_host_mem_chunks(ar, &cmd->mem_chunks); ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi init 10x\n"); return ath10k_wmi_cmd_send(ar, buf, ar->wmi.cmd->init_cmdid); @@ -3147,7 +3280,6 @@ static int ath10k_wmi_10_2_cmd_init(struct ath10k *ar) struct sk_buff *buf; struct wmi_resource_config_10x config = {}; u32 len, val; - int i; config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS); config.num_peers = __cpu_to_le32(TARGET_10X_NUM_PEERS); @@ -3201,32 +3333,8 @@ static int ath10k_wmi_10_2_cmd_init(struct ath10k *ar) cmd = (struct wmi_init_cmd_10_2 *)buf->data; - if (ar->wmi.num_mem_chunks == 0) { - cmd->num_host_mem_chunks = 0; - goto out; - } - - ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi sending %d memory chunks info.\n", - ar->wmi.num_mem_chunks); - - cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks); - - for (i = 0; i < ar->wmi.num_mem_chunks; i++) { - cmd->host_mem_chunks[i].ptr = - __cpu_to_le32(ar->wmi.mem_chunks[i].paddr); - cmd->host_mem_chunks[i].size = - __cpu_to_le32(ar->wmi.mem_chunks[i].len); - cmd->host_mem_chunks[i].req_id = - __cpu_to_le32(ar->wmi.mem_chunks[i].req_id); - - ath10k_dbg(ar, ATH10K_DBG_WMI, - "wmi chunk %d len %d requested, addr 0x%llx\n", - i, - ar->wmi.mem_chunks[i].len, - (unsigned long long)ar->wmi.mem_chunks[i].paddr); - } -out: memcpy(&cmd->resource_config.common, &config, sizeof(config)); + ath10k_wmi_put_host_mem_chunks(ar, &cmd->mem_chunks); ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi init 10.2\n"); return ath10k_wmi_cmd_send(ar, buf, ar->wmi.cmd->init_cmdid); @@ -3248,52 +3356,50 @@ int ath10k_wmi_cmd_init(struct ath10k *ar) return ret; } -static int ath10k_wmi_start_scan_calc_len(struct ath10k *ar, - const struct wmi_start_scan_arg *arg) +static int ath10k_wmi_start_scan_verify(const struct wmi_start_scan_arg *arg) { - int len; + if (arg->ie_len && !arg->ie) + return -EINVAL; + if (arg->n_channels && !arg->channels) + return -EINVAL; + if (arg->n_ssids && !arg->ssids) + return -EINVAL; + if (arg->n_bssids && !arg->bssids) + return -EINVAL; - if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) - len = sizeof(struct wmi_start_scan_cmd_10x); - else - len = sizeof(struct wmi_start_scan_cmd); + if (arg->ie_len > WLAN_SCAN_PARAMS_MAX_IE_LEN) + return -EINVAL; + if (arg->n_channels > ARRAY_SIZE(arg->channels)) + return -EINVAL; + if (arg->n_ssids > WLAN_SCAN_PARAMS_MAX_SSID) + return -EINVAL; + if (arg->n_bssids > WLAN_SCAN_PARAMS_MAX_BSSID) + return -EINVAL; - if (arg->ie_len) { - if (!arg->ie) - return -EINVAL; - if (arg->ie_len > WLAN_SCAN_PARAMS_MAX_IE_LEN) - return -EINVAL; + return 0; +} + +static size_t +ath10k_wmi_start_scan_tlvs_len(const struct wmi_start_scan_arg *arg) +{ + int len = 0; + if (arg->ie_len) { len += sizeof(struct wmi_ie_data); len += roundup(arg->ie_len, 4); } if (arg->n_channels) { - if (!arg->channels) - return -EINVAL; - if (arg->n_channels > ARRAY_SIZE(arg->channels)) - return -EINVAL; - len += sizeof(struct wmi_chan_list); len += sizeof(__le32) * arg->n_channels; } if (arg->n_ssids) { - if (!arg->ssids) - return -EINVAL; - if (arg->n_ssids > WLAN_SCAN_PARAMS_MAX_SSID) - return -EINVAL; - len += sizeof(struct wmi_ssid_list); len += sizeof(struct wmi_ssid) * arg->n_ssids; } if (arg->n_bssids) { - if (!arg->bssids) - return -EINVAL; - if (arg->n_bssids > WLAN_SCAN_PARAMS_MAX_BSSID) - return -EINVAL; - len += sizeof(struct wmi_bssid_list); len += sizeof(struct wmi_mac_addr) * arg->n_bssids; } @@ -3301,28 +3407,12 @@ static int ath10k_wmi_start_scan_calc_len(struct ath10k *ar, return len; } -int ath10k_wmi_start_scan(struct ath10k *ar, - const struct wmi_start_scan_arg *arg) +static void +ath10k_wmi_put_start_scan_common(struct wmi_start_scan_common *cmn, + const struct wmi_start_scan_arg *arg) { - struct wmi_start_scan_cmd *cmd; - struct sk_buff *skb; - struct wmi_ie_data *ie; - struct wmi_chan_list *channels; - struct wmi_ssid_list *ssids; - struct wmi_bssid_list *bssids; u32 scan_id; u32 scan_req_id; - int off; - int len = 0; - int i; - - len = ath10k_wmi_start_scan_calc_len(ar, arg); - if (len < 0) - return len; /* len contains error code here */ - - skb = ath10k_wmi_alloc_skb(ar, len); - if (!skb) - return -ENOMEM; scan_id = WMI_HOST_SCAN_REQ_ID_PREFIX; scan_id |= arg->scan_id; @@ -3330,35 +3420,36 @@ int ath10k_wmi_start_scan(struct ath10k *ar, scan_req_id = WMI_HOST_SCAN_REQUESTOR_ID_PREFIX; scan_req_id |= arg->scan_req_id; - cmd = (struct wmi_start_scan_cmd *)skb->data; - cmd->scan_id = __cpu_to_le32(scan_id); - cmd->scan_req_id = __cpu_to_le32(scan_req_id); - cmd->vdev_id = __cpu_to_le32(arg->vdev_id); - cmd->scan_priority = __cpu_to_le32(arg->scan_priority); - cmd->notify_scan_events = __cpu_to_le32(arg->notify_scan_events); - cmd->dwell_time_active = __cpu_to_le32(arg->dwell_time_active); - cmd->dwell_time_passive = __cpu_to_le32(arg->dwell_time_passive); - cmd->min_rest_time = __cpu_to_le32(arg->min_rest_time); - cmd->max_rest_time = __cpu_to_le32(arg->max_rest_time); - cmd->repeat_probe_time = __cpu_to_le32(arg->repeat_probe_time); - cmd->probe_spacing_time = __cpu_to_le32(arg->probe_spacing_time); - cmd->idle_time = __cpu_to_le32(arg->idle_time); - cmd->max_scan_time = __cpu_to_le32(arg->max_scan_time); - cmd->probe_delay = __cpu_to_le32(arg->probe_delay); - cmd->scan_ctrl_flags = __cpu_to_le32(arg->scan_ctrl_flags); - - /* TLV list starts after fields included in the struct */ - /* There's just one filed that differes the two start_scan - * structures - burst_duration, which we are not using btw, - no point to make the split here, just shift the buffer to fit with - given FW */ - if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) - off = sizeof(struct wmi_start_scan_cmd_10x); - else - off = sizeof(struct wmi_start_scan_cmd); + cmn->scan_id = __cpu_to_le32(scan_id); + cmn->scan_req_id = __cpu_to_le32(scan_req_id); + cmn->vdev_id = __cpu_to_le32(arg->vdev_id); + cmn->scan_priority = __cpu_to_le32(arg->scan_priority); + cmn->notify_scan_events = __cpu_to_le32(arg->notify_scan_events); + cmn->dwell_time_active = __cpu_to_le32(arg->dwell_time_active); + cmn->dwell_time_passive = __cpu_to_le32(arg->dwell_time_passive); + cmn->min_rest_time = __cpu_to_le32(arg->min_rest_time); + cmn->max_rest_time = __cpu_to_le32(arg->max_rest_time); + cmn->repeat_probe_time = __cpu_to_le32(arg->repeat_probe_time); + cmn->probe_spacing_time = __cpu_to_le32(arg->probe_spacing_time); + cmn->idle_time = __cpu_to_le32(arg->idle_time); + cmn->max_scan_time = __cpu_to_le32(arg->max_scan_time); + cmn->probe_delay = __cpu_to_le32(arg->probe_delay); + cmn->scan_ctrl_flags = __cpu_to_le32(arg->scan_ctrl_flags); +} + +static void +ath10k_wmi_put_start_scan_tlvs(struct wmi_start_scan_tlvs *tlvs, + const struct wmi_start_scan_arg *arg) +{ + struct wmi_ie_data *ie; + struct wmi_chan_list *channels; + struct wmi_ssid_list *ssids; + struct wmi_bssid_list *bssids; + void *ptr = tlvs->tlvs; + int i; if (arg->n_channels) { - channels = (void *)skb->data + off; + channels = ptr; channels->tag = __cpu_to_le32(WMI_CHAN_LIST_TAG); channels->num_chan = __cpu_to_le32(arg->n_channels); @@ -3366,12 +3457,12 @@ int ath10k_wmi_start_scan(struct ath10k *ar, channels->channel_list[i].freq = __cpu_to_le16(arg->channels[i]); - off += sizeof(*channels); - off += sizeof(__le32) * arg->n_channels; + ptr += sizeof(*channels); + ptr += sizeof(__le32) * arg->n_channels; } if (arg->n_ssids) { - ssids = (void *)skb->data + off; + ssids = ptr; ssids->tag = __cpu_to_le32(WMI_SSID_LIST_TAG); ssids->num_ssids = __cpu_to_le32(arg->n_ssids); @@ -3383,12 +3474,12 @@ int ath10k_wmi_start_scan(struct ath10k *ar, arg->ssids[i].len); } - off += sizeof(*ssids); - off += sizeof(struct wmi_ssid) * arg->n_ssids; + ptr += sizeof(*ssids); + ptr += sizeof(struct wmi_ssid) * arg->n_ssids; } if (arg->n_bssids) { - bssids = (void *)skb->data + off; + bssids = ptr; bssids->tag = __cpu_to_le32(WMI_BSSID_LIST_TAG); bssids->num_bssid = __cpu_to_le32(arg->n_bssids); @@ -3397,23 +3488,57 @@ int ath10k_wmi_start_scan(struct ath10k *ar, arg->bssids[i].bssid, ETH_ALEN); - off += sizeof(*bssids); - off += sizeof(struct wmi_mac_addr) * arg->n_bssids; + ptr += sizeof(*bssids); + ptr += sizeof(struct wmi_mac_addr) * arg->n_bssids; } if (arg->ie_len) { - ie = (void *)skb->data + off; + ie = ptr; ie->tag = __cpu_to_le32(WMI_IE_TAG); ie->ie_len = __cpu_to_le32(arg->ie_len); memcpy(ie->ie_data, arg->ie, arg->ie_len); - off += sizeof(*ie); - off += roundup(arg->ie_len, 4); + ptr += sizeof(*ie); + ptr += roundup(arg->ie_len, 4); } +} - if (off != skb->len) { - dev_kfree_skb(skb); - return -EINVAL; +int ath10k_wmi_start_scan(struct ath10k *ar, + const struct wmi_start_scan_arg *arg) +{ + struct sk_buff *skb; + size_t len; + int ret; + + ret = ath10k_wmi_start_scan_verify(arg); + if (ret) + return ret; + + if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) + len = sizeof(struct wmi_10x_start_scan_cmd) + + ath10k_wmi_start_scan_tlvs_len(arg); + else + len = sizeof(struct wmi_start_scan_cmd) + + ath10k_wmi_start_scan_tlvs_len(arg); + + skb = ath10k_wmi_alloc_skb(ar, len); + if (!skb) + return -ENOMEM; + + if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) { + struct wmi_10x_start_scan_cmd *cmd; + + cmd = (struct wmi_10x_start_scan_cmd *)skb->data; + ath10k_wmi_put_start_scan_common(&cmd->common, arg); + ath10k_wmi_put_start_scan_tlvs(&cmd->tlvs, arg); + } else { + struct wmi_start_scan_cmd *cmd; + + cmd = (struct wmi_start_scan_cmd *)skb->data; + cmd->burst_duration_ms = __cpu_to_le32(0); + + ath10k_wmi_put_start_scan_common(&cmd->common, arg); + ath10k_wmi_put_start_scan_tlvs(&cmd->tlvs, arg); } ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi start scan\n"); @@ -3532,7 +3657,6 @@ ath10k_wmi_vdev_start_restart(struct ath10k *ar, struct sk_buff *skb; const char *cmdname; u32 flags = 0; - u32 ch_flags = 0; if (cmd_id != ar->wmi.cmd->vdev_start_request_cmdid && cmd_id != ar->wmi.cmd->vdev_restart_request_cmdid) @@ -3559,8 +3683,6 @@ ath10k_wmi_vdev_start_restart(struct ath10k *ar, flags |= WMI_VDEV_START_HIDDEN_SSID; if (arg->pmf_enabled) flags |= WMI_VDEV_START_PMF_ENABLED; - if (arg->channel.chan_radar) - ch_flags |= WMI_CHAN_FLAG_DFS; cmd = (struct wmi_vdev_start_request_cmd *)skb->data; cmd->vdev_id = __cpu_to_le32(arg->vdev_id); @@ -3576,18 +3698,7 @@ ath10k_wmi_vdev_start_restart(struct ath10k *ar, memcpy(cmd->ssid.ssid, arg->ssid, arg->ssid_len); } - cmd->chan.mhz = __cpu_to_le32(arg->channel.freq); - - cmd->chan.band_center_freq1 = - __cpu_to_le32(arg->channel.band_center_freq1); - - cmd->chan.mode = arg->channel.mode; - cmd->chan.flags |= __cpu_to_le32(ch_flags); - cmd->chan.min_power = arg->channel.min_power; - cmd->chan.max_power = arg->channel.max_power; - cmd->chan.reg_power = arg->channel.max_reg_power; - cmd->chan.reg_classid = arg->channel.reg_class_id; - cmd->chan.antenna_max = arg->channel.max_antenna_gain; + ath10k_wmi_put_wmi_channel(&cmd->chan, &arg->channel); ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi vdev %s id 0x%x flags: 0x%0X, freq %d, mode %d, ch_flags: 0x%0X, max_power: %d\n", @@ -3968,35 +4079,10 @@ int ath10k_wmi_scan_chan_list(struct ath10k *ar, cmd->num_scan_chans = __cpu_to_le32(arg->n_channels); for (i = 0; i < arg->n_channels; i++) { - u32 flags = 0; - ch = &arg->channels[i]; ci = &cmd->chan_info[i]; - if (ch->passive) - flags |= WMI_CHAN_FLAG_PASSIVE; - if (ch->allow_ibss) - flags |= WMI_CHAN_FLAG_ADHOC_ALLOWED; - if (ch->allow_ht) - flags |= WMI_CHAN_FLAG_ALLOW_HT; - if (ch->allow_vht) - flags |= WMI_CHAN_FLAG_ALLOW_VHT; - if (ch->ht40plus) - flags |= WMI_CHAN_FLAG_HT40_PLUS; - if (ch->chan_radar) - flags |= WMI_CHAN_FLAG_DFS; - - ci->mhz = __cpu_to_le32(ch->freq); - ci->band_center_freq1 = __cpu_to_le32(ch->freq); - ci->band_center_freq2 = 0; - ci->min_power = ch->min_power; - ci->max_power = ch->max_power; - ci->reg_power = ch->max_reg_power; - ci->antenna_max = ch->max_antenna_gain; - - /* mode & flags share storage */ - ci->mode = ch->mode; - ci->flags |= __cpu_to_le32(flags); + ath10k_wmi_put_wmi_channel(ci, ch); } return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->scan_chan_list_cmdid); @@ -4108,9 +4194,9 @@ int ath10k_wmi_peer_assoc(struct ath10k *ar, if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) { if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, ar->fw_features)) - ath10k_wmi_peer_assoc_fill_10_1(ar, skb->data, arg); - else ath10k_wmi_peer_assoc_fill_10_2(ar, skb->data, arg); + else + ath10k_wmi_peer_assoc_fill_10_1(ar, skb->data, arg); } else { ath10k_wmi_peer_assoc_fill_main(ar, skb->data, arg); } @@ -4267,3 +4353,73 @@ int ath10k_wmi_dbglog_cfg(struct ath10k *ar, u32 module_enable) return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->dbglog_cfg_cmdid); } + +int ath10k_wmi_pdev_pktlog_enable(struct ath10k *ar, u32 ev_bitmap) +{ + struct wmi_pdev_pktlog_enable_cmd *cmd; + struct sk_buff *skb; + + skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + ev_bitmap &= ATH10K_PKTLOG_ANY; + ath10k_dbg(ar, ATH10K_DBG_WMI, + "wmi enable pktlog filter:%x\n", ev_bitmap); + + cmd = (struct wmi_pdev_pktlog_enable_cmd *)skb->data; + cmd->ev_bitmap = __cpu_to_le32(ev_bitmap); + return ath10k_wmi_cmd_send(ar, skb, + ar->wmi.cmd->pdev_pktlog_enable_cmdid); +} + +int ath10k_wmi_pdev_pktlog_disable(struct ath10k *ar) +{ + struct sk_buff *skb; + + skb = ath10k_wmi_alloc_skb(ar, 0); + if (!skb) + return -ENOMEM; + + ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi disable pktlog\n"); + + return ath10k_wmi_cmd_send(ar, skb, + ar->wmi.cmd->pdev_pktlog_disable_cmdid); +} + +int ath10k_wmi_attach(struct ath10k *ar) +{ + if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) { + if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, ar->fw_features)) + ar->wmi.cmd = &wmi_10_2_cmd_map; + else + ar->wmi.cmd = &wmi_10x_cmd_map; + + ar->wmi.vdev_param = &wmi_10x_vdev_param_map; + ar->wmi.pdev_param = &wmi_10x_pdev_param_map; + } else { + ar->wmi.cmd = &wmi_cmd_map; + ar->wmi.vdev_param = &wmi_vdev_param_map; + ar->wmi.pdev_param = &wmi_pdev_param_map; + } + + init_completion(&ar->wmi.service_ready); + init_completion(&ar->wmi.unified_ready); + + return 0; +} + +void ath10k_wmi_detach(struct ath10k *ar) +{ + int i; + + /* free the host memory chunks requested by firmware */ + for (i = 0; i < ar->wmi.num_mem_chunks; i++) { + dma_free_coherent(ar->dev, + ar->wmi.mem_chunks[i].len, + ar->wmi.mem_chunks[i].vaddr, + ar->wmi.mem_chunks[i].paddr); + } + + ar->wmi.num_mem_chunks = 0; +} diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 86f5ebccfe79..a38d788a6101 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -1428,11 +1428,11 @@ struct wmi_service_ready_event { * where FW can access this memory directly (or) by DMA. */ __le32 num_mem_reqs; - struct wlan_host_mem_req mem_reqs[1]; + struct wlan_host_mem_req mem_reqs[0]; } __packed; /* This is the definition from 10.X firmware branch */ -struct wmi_service_ready_event_10x { +struct wmi_10x_service_ready_event { __le32 sw_version; __le32 abi_version; @@ -1467,7 +1467,7 @@ struct wmi_service_ready_event_10x { */ __le32 num_mem_reqs; - struct wlan_host_mem_req mem_reqs[1]; + struct wlan_host_mem_req mem_reqs[0]; } __packed; #define WMI_SERVICE_READY_TIMEOUT_HZ (5*HZ) @@ -1883,38 +1883,26 @@ struct host_memory_chunk { __le32 size; } __packed; +struct wmi_host_mem_chunks { + __le32 count; + /* some fw revisions require at least 1 chunk regardless of count */ + struct host_memory_chunk items[1]; +} __packed; + struct wmi_init_cmd { struct wmi_resource_config resource_config; - __le32 num_host_mem_chunks; - - /* - * variable number of host memory chunks. - * This should be the last element in the structure - */ - struct host_memory_chunk host_mem_chunks[1]; + struct wmi_host_mem_chunks mem_chunks; } __packed; /* _10x stucture is from 10.X FW API */ struct wmi_init_cmd_10x { struct wmi_resource_config_10x resource_config; - __le32 num_host_mem_chunks; - - /* - * variable number of host memory chunks. - * This should be the last element in the structure - */ - struct host_memory_chunk host_mem_chunks[1]; + struct wmi_host_mem_chunks mem_chunks; } __packed; struct wmi_init_cmd_10_2 { struct wmi_resource_config_10_2 resource_config; - __le32 num_host_mem_chunks; - - /* - * variable number of host memory chunks. - * This should be the last element in the structure - */ - struct host_memory_chunk host_mem_chunks[1]; + struct wmi_host_mem_chunks mem_chunks; } __packed; struct wmi_chan_list_entry { @@ -1974,7 +1962,7 @@ enum wmi_scan_priority { WMI_SCAN_PRIORITY_COUNT /* number of priorities supported */ }; -struct wmi_start_scan_cmd { +struct wmi_start_scan_common { /* Scan ID */ __le32 scan_id; /* Scan requestor ID */ @@ -2032,95 +2020,25 @@ struct wmi_start_scan_cmd { __le32 probe_delay; /* Scan control flags */ __le32 scan_ctrl_flags; - - /* Burst duration time in msecs */ - __le32 burst_duration; - /* - * TLV (tag length value ) paramerters follow the scan_cmd structure. - * TLV can contain channel list, bssid list, ssid list and - * ie. the TLV tags are defined above; - */ } __packed; -/* This is the definition from 10.X firmware branch */ -struct wmi_start_scan_cmd_10x { - /* Scan ID */ - __le32 scan_id; - - /* Scan requestor ID */ - __le32 scan_req_id; - - /* VDEV id(interface) that is requesting scan */ - __le32 vdev_id; - - /* Scan Priority, input to scan scheduler */ - __le32 scan_priority; - - /* Scan events subscription */ - __le32 notify_scan_events; - - /* dwell time in msec on active channels */ - __le32 dwell_time_active; - - /* dwell time in msec on passive channels */ - __le32 dwell_time_passive; - - /* - * min time in msec on the BSS channel,only valid if atleast one - * VDEV is active - */ - __le32 min_rest_time; - - /* - * max rest time in msec on the BSS channel,only valid if at least - * one VDEV is active - */ - /* - * the scanner will rest on the bss channel at least min_rest_time - * after min_rest_time the scanner will start checking for tx/rx - * activity on all VDEVs. if there is no activity the scanner will - * switch to off channel. if there is activity the scanner will let - * the radio on the bss channel until max_rest_time expires.at - * max_rest_time scanner will switch to off channel irrespective of - * activity. activity is determined by the idle_time parameter. - */ - __le32 max_rest_time; - - /* - * time before sending next set of probe requests. - * The scanner keeps repeating probe requests transmission with - * period specified by repeat_probe_time. - * The number of probe requests specified depends on the ssid_list - * and bssid_list - */ - __le32 repeat_probe_time; - - /* time in msec between 2 consequetive probe requests with in a set. */ - __le32 probe_spacing_time; - - /* - * data inactivity time in msec on bss channel that will be used by - * scanner for measuring the inactivity. - */ - __le32 idle_time; - - /* maximum time in msec allowed for scan */ - __le32 max_scan_time; - - /* - * delay in msec before sending first probe request after switching - * to a channel +struct wmi_start_scan_tlvs { + /* TLV parameters. These includes channel list, ssid list, bssid list, + * extra ies. */ - __le32 probe_delay; + u8 tlvs[0]; +} __packed; - /* Scan control flags */ - __le32 scan_ctrl_flags; +struct wmi_start_scan_cmd { + struct wmi_start_scan_common common; + __le32 burst_duration_ms; + struct wmi_start_scan_tlvs tlvs; +} __packed; - /* - * TLV (tag length value ) paramerters follow the scan_cmd structure. - * TLV can contain channel list, bssid list, ssid list and - * ie. the TLV tags are defined above; - */ +/* This is the definition from 10.X firmware branch */ +struct wmi_10x_start_scan_cmd { + struct wmi_start_scan_common common; + struct wmi_start_scan_tlvs tlvs; } __packed; struct wmi_ssid_arg { @@ -2306,94 +2224,25 @@ struct wmi_mgmt_rx_event_v2 { #define PHY_ERROR_FALSE_RADAR_EXT 0x24 #define PHY_ERROR_RADAR 0x05 -struct wmi_single_phyerr_rx_hdr { - /* TSF timestamp */ +struct wmi_phyerr { __le32 tsf_timestamp; - - /* - * Current freq1, freq2 - * - * [7:0]: freq1[lo] - * [15:8] : freq1[hi] - * [23:16]: freq2[lo] - * [31:24]: freq2[hi] - */ __le16 freq1; __le16 freq2; - - /* - * Combined RSSI over all chains and channel width for this PHY error - * - * [7:0]: RSSI combined - * [15:8]: Channel width (MHz) - * [23:16]: PHY error code - * [24:16]: reserved (future use) - */ u8 rssi_combined; u8 chan_width_mhz; u8 phy_err_code; u8 rsvd0; - - /* - * RSSI on chain 0 through 3 - * - * This is formatted the same as the PPDU_START RX descriptor - * field: - * - * [7:0]: pri20 - * [15:8]: sec20 - * [23:16]: sec40 - * [31:24]: sec80 - */ - - __le32 rssi_chain0; - __le32 rssi_chain1; - __le32 rssi_chain2; - __le32 rssi_chain3; - - /* - * Last calibrated NF value for chain 0 through 3 - * - * nf_list_1: - * - * + [15:0] - chain 0 - * + [31:16] - chain 1 - * - * nf_list_2: - * - * + [15:0] - chain 2 - * + [31:16] - chain 3 - */ - __le32 nf_list_1; - __le32 nf_list_2; - - /* Length of the frame */ + __le32 rssi_chains[4]; + __le16 nf_chains[4]; __le32 buf_len; + u8 buf[0]; } __packed; -struct wmi_single_phyerr_rx_event { - /* Phy error event header */ - struct wmi_single_phyerr_rx_hdr hdr; - /* frame buffer */ - u8 bufp[0]; -} __packed; - -struct wmi_comb_phyerr_rx_hdr { - /* Phy error phy error count */ - __le32 num_phyerr_events; +struct wmi_phyerr_event { + __le32 num_phyerrs; __le32 tsf_l32; __le32 tsf_u32; -} __packed; - -struct wmi_comb_phyerr_rx_event { - /* Phy error phy error count */ - struct wmi_comb_phyerr_rx_hdr hdr; - /* - * frame buffer - contains multiple payloads in the order: - * header - payload, header - payload... - * (The header is of type: wmi_single_phyerr_rx_hdr) - */ - u8 bufp[0]; + struct wmi_phyerr phyerrs[0]; } __packed; #define PHYERR_TLV_SIG 0xBB @@ -2908,11 +2757,6 @@ enum wmi_tp_scale { WMI_TP_SCALE_SIZE = 5, /* max num of enum */ }; -struct wmi_set_channel_cmd { - /* channel (only frequency and mode info are used) */ - struct wmi_channel chan; -} __packed; - struct wmi_pdev_chanlist_update_event { /* number of channels */ __le32 num_chan; @@ -2943,6 +2787,10 @@ struct wmi_pdev_set_channel_cmd { struct wmi_channel chan; } __packed; +struct wmi_pdev_pktlog_enable_cmd { + __le32 ev_bitmap; +} __packed; + /* Customize the DSCP (bit) to TID (0-7) mapping for QOS */ #define WMI_DSCP_MAP_MAX (64) struct wmi_pdev_set_dscp_tid_map_cmd { @@ -3177,7 +3025,7 @@ struct wmi_stats_event { * PDEV statistics * TODO: add all PDEV stats here */ -struct wmi_pdev_stats_old { +struct wmi_pdev_stats { __le32 chan_nf; /* Channel noise floor */ __le32 tx_frame_count; /* TX frame count */ __le32 rx_frame_count; /* RX frame count */ @@ -3188,15 +3036,8 @@ struct wmi_pdev_stats_old { struct wal_dbg_stats wal; /* WAL dbg stats */ } __packed; -struct wmi_pdev_stats_10x { - __le32 chan_nf; /* Channel noise floor */ - __le32 tx_frame_count; /* TX frame count */ - __le32 rx_frame_count; /* RX frame count */ - __le32 rx_clear_count; /* rx clear count */ - __le32 cycle_count; /* cycle count */ - __le32 phy_err_count; /* Phy error count */ - __le32 chan_tx_pwr; /* channel tx power */ - struct wal_dbg_stats wal; /* WAL dbg stats */ +struct wmi_10x_pdev_stats { + struct wmi_pdev_stats old; __le32 ack_rx_bad; __le32 rts_bad; __le32 rts_good; @@ -3217,16 +3058,14 @@ struct wmi_vdev_stats { * peer statistics. * TODO: add more stats */ -struct wmi_peer_stats_old { +struct wmi_peer_stats { struct wmi_mac_addr peer_macaddr; __le32 peer_rssi; __le32 peer_tx_rate; } __packed; -struct wmi_peer_stats_10x { - struct wmi_mac_addr peer_macaddr; - __le32 peer_rssi; - __le32 peer_tx_rate; +struct wmi_10x_peer_stats { + struct wmi_peer_stats old; __le32 peer_rx_rate; } __packed; @@ -4719,8 +4558,26 @@ struct wmi_dbglog_cfg_cmd { /* By default disable power save for IBSS */ #define ATH10K_DEFAULT_ATIM 0 +#define WMI_MAX_MEM_REQS 16 + +struct wmi_svc_rdy_ev_arg { + __le32 min_tx_power; + __le32 max_tx_power; + __le32 ht_cap; + __le32 vht_cap; + __le32 sw_ver0; + __le32 sw_ver1; + __le32 phy_capab; + __le32 num_rf_chains; + __le32 eeprom_rd; + __le32 num_mem_reqs; + const __le32 *service_map; + const struct wlan_host_mem_req *mem_reqs[WMI_MAX_MEM_REQS]; +}; + struct ath10k; struct ath10k_vif; +struct ath10k_fw_stats; int ath10k_wmi_attach(struct ath10k *ar); void ath10k_wmi_detach(struct ath10k *ar); @@ -4732,8 +4589,6 @@ int ath10k_wmi_connect(struct ath10k *ar); struct sk_buff *ath10k_wmi_alloc_skb(struct ath10k *ar, u32 len); int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id); -int ath10k_wmi_pdev_set_channel(struct ath10k *ar, - const struct wmi_channel_arg *); int ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt); int ath10k_wmi_pdev_resume_target(struct ath10k *ar); int ath10k_wmi_pdev_set_regdomain(struct ath10k *ar, u16 rd, u16 rd2g, @@ -4794,5 +4649,9 @@ int ath10k_wmi_force_fw_hang(struct ath10k *ar, enum wmi_force_fw_hang_type type, u32 delay_ms); int ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *skb); int ath10k_wmi_dbglog_cfg(struct ath10k *ar, u32 module_enable); +int ath10k_wmi_pull_fw_stats(struct ath10k *ar, struct sk_buff *skb, + struct ath10k_fw_stats *stats); +int ath10k_wmi_pdev_pktlog_enable(struct ath10k *ar, u32 ev_list); +int ath10k_wmi_pdev_pktlog_disable(struct ath10k *ar); #endif /* _WMI_H_ */ diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c index ab2709a43768..19eab2a69ad5 100644 --- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c +++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c @@ -547,7 +547,9 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, static void -ath5k_sw_scan_start(struct ieee80211_hw *hw) +ath5k_sw_scan_start(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + const u8 *mac_addr) { struct ath5k_hw *ah = hw->priv; if (!ah->assoc) @@ -556,7 +558,7 @@ ath5k_sw_scan_start(struct ieee80211_hw *hw) static void -ath5k_sw_scan_complete(struct ieee80211_hw *hw) +ath5k_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct ath5k_hw *ah = hw->priv; ath5k_hw_set_ledstate(ah, ah->assoc ? diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index ba60e37213eb..7a5337877a0c 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -2976,11 +2976,11 @@ static int ath6kl_stop_ap(struct wiphy *wiphy, struct net_device *dev) static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; static int ath6kl_del_station(struct wiphy *wiphy, struct net_device *dev, - const u8 *mac) + struct station_del_parameters *params) { struct ath6kl *ar = ath6kl_priv(dev); struct ath6kl_vif *vif = netdev_priv(dev); - const u8 *addr = mac ? mac : bcast_addr; + const u8 *addr = params->mac ? params->mac : bcast_addr; return ath6kl_wmi_ap_set_mlme(ar->wmi, vif->fw_vif_idx, WMI_AP_DEAUTH, addr, WLAN_REASON_PREV_AUTH_NOT_VALID); diff --git a/drivers/net/wireless/ath/ath6kl/common.h b/drivers/net/wireless/ath/ath6kl/common.h index 05debf700a84..4f82e8632d37 100644 --- a/drivers/net/wireless/ath/ath6kl/common.h +++ b/drivers/net/wireless/ath/ath6kl/common.h @@ -22,7 +22,7 @@ #define ATH6KL_MAX_IE 256 -__printf(2, 3) int ath6kl_printk(const char *level, const char *fmt, ...); +__printf(2, 3) void ath6kl_printk(const char *level, const char *fmt, ...); /* * Reflects the version of binary interface exposed by ATH6KL target diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c index 55c4064dd506..81ba48d2938b 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.c +++ b/drivers/net/wireless/ath/ath6kl/debug.c @@ -37,76 +37,64 @@ struct ath6kl_fwlog_slot { #define ATH6KL_FWLOG_VALID_MASK 0x1ffff -int ath6kl_printk(const char *level, const char *fmt, ...) +void ath6kl_printk(const char *level, const char *fmt, ...) { struct va_format vaf; va_list args; - int rtn; va_start(args, fmt); vaf.fmt = fmt; vaf.va = &args; - rtn = printk("%sath6kl: %pV", level, &vaf); + printk("%sath6kl: %pV", level, &vaf); va_end(args); - - return rtn; } EXPORT_SYMBOL(ath6kl_printk); -int ath6kl_info(const char *fmt, ...) +void ath6kl_info(const char *fmt, ...) { struct va_format vaf = { .fmt = fmt, }; va_list args; - int ret; va_start(args, fmt); vaf.va = &args; - ret = ath6kl_printk(KERN_INFO, "%pV", &vaf); + ath6kl_printk(KERN_INFO, "%pV", &vaf); trace_ath6kl_log_info(&vaf); va_end(args); - - return ret; } EXPORT_SYMBOL(ath6kl_info); -int ath6kl_err(const char *fmt, ...) +void ath6kl_err(const char *fmt, ...) { struct va_format vaf = { .fmt = fmt, }; va_list args; - int ret; va_start(args, fmt); vaf.va = &args; - ret = ath6kl_printk(KERN_ERR, "%pV", &vaf); + ath6kl_printk(KERN_ERR, "%pV", &vaf); trace_ath6kl_log_err(&vaf); va_end(args); - - return ret; } EXPORT_SYMBOL(ath6kl_err); -int ath6kl_warn(const char *fmt, ...) +void ath6kl_warn(const char *fmt, ...) { struct va_format vaf = { .fmt = fmt, }; va_list args; - int ret; va_start(args, fmt); vaf.va = &args; - ret = ath6kl_printk(KERN_WARNING, "%pV", &vaf); + ath6kl_printk(KERN_WARNING, "%pV", &vaf); trace_ath6kl_log_warn(&vaf); va_end(args); - - return ret; } EXPORT_SYMBOL(ath6kl_warn); diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h index e194c10d9f00..19106ed28961 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.h +++ b/drivers/net/wireless/ath/ath6kl/debug.h @@ -50,10 +50,10 @@ enum ATH6K_DEBUG_MASK { }; extern unsigned int debug_mask; -__printf(2, 3) int ath6kl_printk(const char *level, const char *fmt, ...); -__printf(1, 2) int ath6kl_info(const char *fmt, ...); -__printf(1, 2) int ath6kl_err(const char *fmt, ...); -__printf(1, 2) int ath6kl_warn(const char *fmt, ...); +__printf(2, 3) void ath6kl_printk(const char *level, const char *fmt, ...); +__printf(1, 2) void ath6kl_info(const char *fmt, ...); +__printf(1, 2) void ath6kl_err(const char *fmt, ...); +__printf(1, 2) void ath6kl_warn(const char *fmt, ...); enum ath6kl_war { ATH6KL_WAR_INVALID_RATE, @@ -81,10 +81,9 @@ int ath6kl_debug_init_fs(struct ath6kl *ar); void ath6kl_debug_cleanup(struct ath6kl *ar); #else -static inline int ath6kl_dbg(enum ATH6K_DEBUG_MASK dbg_mask, - const char *fmt, ...) +static inline void ath6kl_dbg(enum ATH6K_DEBUG_MASK dbg_mask, + const char *fmt, ...) { - return 0; } static inline void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask, diff --git a/drivers/net/wireless/ath/ath6kl/usb.c b/drivers/net/wireless/ath/ath6kl/usb.c index a6a5e40b3e98..9da3594fd010 100644 --- a/drivers/net/wireless/ath/ath6kl/usb.c +++ b/drivers/net/wireless/ath/ath6kl/usb.c @@ -1193,18 +1193,10 @@ static int ath6kl_usb_pm_resume(struct usb_interface *interface) return 0; } -static int ath6kl_usb_pm_reset_resume(struct usb_interface *intf) -{ - if (usb_get_intfdata(intf)) - ath6kl_usb_remove(intf); - return 0; -} - #else #define ath6kl_usb_pm_suspend NULL #define ath6kl_usb_pm_resume NULL -#define ath6kl_usb_pm_reset_resume NULL #endif @@ -1222,7 +1214,6 @@ static struct usb_driver ath6kl_usb_driver = { .probe = ath6kl_usb_probe, .suspend = ath6kl_usb_pm_suspend, .resume = ath6kl_usb_pm_resume, - .reset_resume = ath6kl_usb_pm_reset_resume, .disconnect = ath6kl_usb_remove, .id_table = ath6kl_usb_ids, .supports_autosuspend = true, diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index 896e63281b3b..fee0cadb0f5e 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig @@ -3,6 +3,8 @@ config ATH9K_HW config ATH9K_COMMON tristate select ATH_COMMON + select DEBUG_FS + select RELAY config ATH9K_DFS_DEBUGFS def_bool y depends on ATH9K_DEBUGFS && ATH9K_DFS_CERTIFIED @@ -148,6 +150,11 @@ config ATH9K_CHANNEL_CONTEXT for multi-channel concurrency. Enable this if P2P PowerSave support is required. +config ATH9K_PCOEM + bool "Atheros ath9k support for PC OEM cards" if EXPERT + depends on ATH9K + default y + config ATH9K_HTC tristate "Atheros HTC based wireless cards support" depends on USB && MAC80211 diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 73704c1be736..473972288a84 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile @@ -16,8 +16,7 @@ ath9k-$(CONFIG_ATH9K_DFS_CERTIFIED) += dfs.o ath9k-$(CONFIG_ATH9K_TX99) += tx99.o ath9k-$(CONFIG_ATH9K_WOW) += wow.o -ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o \ - spectral.o +ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o ath9k-$(CONFIG_ATH9K_STATION_STATISTICS) += debug_sta.o @@ -32,7 +31,6 @@ ath9k_hw-y:= \ ar5008_phy.o \ ar9002_calib.o \ ar9003_calib.o \ - ar9003_rtt.o \ calib.o \ eeprom.o \ eeprom_def.o \ @@ -50,6 +48,8 @@ ath9k_hw-$(CONFIG_ATH9K_WOW) += ar9003_wow.o ath9k_hw-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += btcoex.o \ ar9003_mci.o +ath9k_hw-$(CONFIG_ATH9K_PCOEM) += ar9003_rtt.o + ath9k_hw-$(CONFIG_ATH9K_DYNACK) += dynack.o obj-$(CONFIG_ATH9K_HW) += ath9k_hw.o @@ -58,7 +58,8 @@ obj-$(CONFIG_ATH9K_COMMON) += ath9k_common.o ath9k_common-y:= common.o \ common-init.o \ common-beacon.o \ - common-debug.o + common-debug.o \ + common-spectral.o ath9k_htc-y += htc_hst.o \ hif_usb.o \ diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index b72d0be716db..5829074208fa 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c @@ -1190,7 +1190,7 @@ static void ar5008_hw_set_nf_limits(struct ath_hw *ah) static void ar5008_hw_set_radar_params(struct ath_hw *ah, struct ath_hw_radar_conf *conf) { - u32 radar_0 = 0, radar_1 = 0; + u32 radar_0 = 0, radar_1; if (!conf) { REG_CLR_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA); @@ -1204,6 +1204,9 @@ static void ar5008_hw_set_radar_params(struct ath_hw *ah, radar_0 |= SM(conf->pulse_rssi, AR_PHY_RADAR_0_PRSSI); radar_0 |= SM(conf->pulse_inband, AR_PHY_RADAR_0_INBAND); + radar_1 = REG_READ(ah, AR_PHY_RADAR_1); + radar_1 &= ~(AR_PHY_RADAR_1_MAXLEN | AR_PHY_RADAR_1_RELSTEP_THRESH | + AR_PHY_RADAR_1_RELPWR_THRESH); radar_1 |= AR_PHY_RADAR_1_MAX_RRSSI; radar_1 |= AR_PHY_RADAR_1_BLOCK_CHECK; radar_1 |= SM(conf->pulse_maxlen, AR_PHY_RADAR_1_MAXLEN); @@ -1225,7 +1228,7 @@ static void ar5008_hw_set_radar_conf(struct ath_hw *ah) conf->fir_power = -33; conf->radar_rssi = 20; conf->pulse_height = 10; - conf->pulse_rssi = 24; + conf->pulse_rssi = 15; conf->pulse_inband = 15; conf->pulse_maxlen = 255; conf->pulse_inband_step = 12; diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c index cdc74005650c..42190b67c671 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c @@ -657,31 +657,29 @@ static void ar9002_hw_olc_temp_compensation(struct ath_hw *ah) ar9280_hw_olc_temp_compensation(ah); } -static bool ar9002_hw_calibrate(struct ath_hw *ah, - struct ath9k_channel *chan, - u8 rxchainmask, - bool longcal) +static int ar9002_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, + u8 rxchainmask, bool longcal) { - bool iscaldone = true; struct ath9k_cal_list *currCal = ah->cal_list_curr; - bool nfcal, nfcal_pending = false; + bool nfcal, nfcal_pending = false, percal_pending; + int ret; nfcal = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF); if (ah->caldata) nfcal_pending = test_bit(NFCAL_PENDING, &ah->caldata->cal_flags); - if (currCal && !nfcal && - (currCal->calState == CAL_RUNNING || - currCal->calState == CAL_WAITING)) { - iscaldone = ar9002_hw_per_calibration(ah, chan, - rxchainmask, currCal); - if (iscaldone) { - ah->cal_list_curr = currCal = currCal->calNext; - - if (currCal->calState == CAL_WAITING) { - iscaldone = false; - ath9k_hw_reset_calibration(ah, currCal); - } + percal_pending = (currCal && + (currCal->calState == CAL_RUNNING || + currCal->calState == CAL_WAITING)); + + if (percal_pending && !nfcal) { + if (!ar9002_hw_per_calibration(ah, chan, rxchainmask, currCal)) + return 0; + + ah->cal_list_curr = currCal = currCal->calNext; + if (currCal->calState == CAL_WAITING) { + ath9k_hw_reset_calibration(ah, currCal); + return 0; } } @@ -698,7 +696,9 @@ static bool ar9002_hw_calibrate(struct ath_hw *ah, * NF is slow time-variant, so it is OK to use a * historical value. */ - ath9k_hw_loadnf(ah, ah->curchan); + ret = ath9k_hw_loadnf(ah, ah->curchan); + if (ret < 0) + return ret; } if (longcal) { @@ -709,7 +709,7 @@ static bool ar9002_hw_calibrate(struct ath_hw *ah, } } - return iscaldone; + return !percal_pending; } /* Carrier leakage Calibration fix */ @@ -856,6 +856,8 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) /* Do PA Calibration */ ar9002_hw_pa_cal(ah, true); + ath9k_hw_loadnf(ah, chan); + ath9k_hw_start_nfcal(ah, true); if (ah->caldata) set_bit(NFCAL_PENDING, &ah->caldata->cal_flags); diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c index 9a2afa2c690b..fc08162b5820 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c @@ -643,9 +643,12 @@ static void ar9002_hw_spectral_scan_config(struct ath_hw *ah, * and fix otherwise. */ count = param->count; - if (param->endless) - count = 0x80; - else if (count & 0x80) + if (param->endless) { + if (AR_SREV_9271(ah)) + count = 0; + else + count = 0x80; + } else if (count & 0x80) count = 0x7f; REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN, diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index ac8301ef5242..06ab71db6e80 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -121,13 +121,12 @@ static bool ar9003_hw_per_calibration(struct ath_hw *ah, return iscaldone; } -static bool ar9003_hw_calibrate(struct ath_hw *ah, - struct ath9k_channel *chan, - u8 rxchainmask, - bool longcal) +static int ar9003_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, + u8 rxchainmask, bool longcal) { bool iscaldone = true; struct ath9k_cal_list *currCal = ah->cal_list_curr; + int ret; /* * For given calibration: @@ -163,7 +162,9 @@ static bool ar9003_hw_calibrate(struct ath_hw *ah, * NF is slow time-variant, so it is OK to use a historical * value. */ - ath9k_hw_loadnf(ah, ah->curchan); + ret = ath9k_hw_loadnf(ah, ah->curchan); + if (ret < 0) + return ret; /* start NF calibration, without updating BB NF register */ ath9k_hw_start_nfcal(ah, false); diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 80c6eacbda53..e726e405152c 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -4079,27 +4079,28 @@ static int ar9003_hw_get_thermometer(struct ath_hw *ah) static void ar9003_hw_thermometer_apply(struct ath_hw *ah) { + struct ath9k_hw_capabilities *pCap = &ah->caps; int thermometer = ar9003_hw_get_thermometer(ah); u8 therm_on = (thermometer < 0) ? 0 : 1; REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, therm_on); - if (ah->caps.tx_chainmask & BIT(1)) + if (pCap->chip_chainmask & BIT(1)) REG_RMW_FIELD(ah, AR_PHY_65NM_CH1_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, therm_on); - if (ah->caps.tx_chainmask & BIT(2)) + if (pCap->chip_chainmask & BIT(2)) REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, therm_on); therm_on = (thermometer < 0) ? 0 : (thermometer == 0); REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON, therm_on); - if (ah->caps.tx_chainmask & BIT(1)) { + if (pCap->chip_chainmask & BIT(1)) { therm_on = (thermometer < 0) ? 0 : (thermometer == 1); REG_RMW_FIELD(ah, AR_PHY_65NM_CH1_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON, therm_on); } - if (ah->caps.tx_chainmask & BIT(2)) { + if (pCap->chip_chainmask & BIT(2)) { therm_on = (thermometer < 0) ? 0 : (thermometer == 2); REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON, therm_on); diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index ddef9eedbac6..06ad2172030e 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -333,12 +333,29 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) qca953x_1p0_soc_preamble); INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], qca953x_1p0_soc_postamble); - INIT_INI_ARRAY(&ah->iniModesRxGain, - qca953x_1p0_common_wo_xlna_rx_gain_table); - INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, - qca953x_1p0_common_wo_xlna_rx_gain_bounds); - INIT_INI_ARRAY(&ah->iniModesTxGain, - qca953x_1p0_modes_no_xpa_tx_gain_table); + + if (AR_SREV_9531_20(ah)) { + INIT_INI_ARRAY(&ah->iniModesRxGain, + qca953x_2p0_common_wo_xlna_rx_gain_table); + INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, + qca953x_2p0_common_wo_xlna_rx_gain_bounds); + } else { + INIT_INI_ARRAY(&ah->iniModesRxGain, + qca953x_1p0_common_wo_xlna_rx_gain_table); + INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, + qca953x_1p0_common_wo_xlna_rx_gain_bounds); + } + + if (AR_SREV_9531_20(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + qca953x_2p0_modes_no_xpa_tx_gain_table); + else if (AR_SREV_9531_11(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + qca953x_1p1_modes_no_xpa_tx_gain_table); + else + INIT_INI_ARRAY(&ah->iniModesTxGain, + qca953x_1p0_modes_no_xpa_tx_gain_table); + INIT_INI_ARRAY(&ah->iniModesFastClock, qca953x_1p0_modes_fast_clock); } else if (AR_SREV_9580(ah)) { @@ -518,9 +535,15 @@ static void ar9003_tx_gain_table_mode0(struct ath_hw *ah) else if (AR_SREV_9550(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, ar955x_1p0_modes_xpa_tx_gain_table); - else if (AR_SREV_9531(ah)) + else if (AR_SREV_9531_10(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + qca953x_1p0_modes_xpa_tx_gain_table); + else if (AR_SREV_9531_11(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + qca953x_1p1_modes_xpa_tx_gain_table); + else if (AR_SREV_9531_20(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, - qca953x_1p0_modes_xpa_tx_gain_table); + qca953x_2p0_modes_xpa_tx_gain_table); else if (AR_SREV_9580(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, ar9580_1p0_lowest_ob_db_tx_gain_table); @@ -562,7 +585,10 @@ static void ar9003_tx_gain_table_mode1(struct ath_hw *ah) INIT_INI_ARRAY(&ah->iniModesTxGain, ar955x_1p0_modes_no_xpa_tx_gain_table); else if (AR_SREV_9531(ah)) { - if (AR_SREV_9531_11(ah)) + if (AR_SREV_9531_20(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + qca953x_2p0_modes_no_xpa_tx_gain_table); + else if (AR_SREV_9531_11(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, qca953x_1p1_modes_no_xpa_tx_gain_table); else @@ -670,9 +696,6 @@ static void ar9003_tx_gain_table_mode5(struct ath_hw *ah) if (AR_SREV_9485_11_OR_LATER(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, ar9485Modes_green_ob_db_tx_gain_1_1); - else if (AR_SREV_9340(ah)) - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9340Modes_ub124_tx_gain_table_1p0); else if (AR_SREV_9580(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, ar9580_1p0_type5_tx_gain_table); @@ -792,11 +815,16 @@ static void ar9003_rx_gain_table_mode1(struct ath_hw *ah) ar955x_1p0_common_wo_xlna_rx_gain_table); INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, ar955x_1p0_common_wo_xlna_rx_gain_bounds); - } else if (AR_SREV_9531(ah)) { + } else if (AR_SREV_9531_10(ah) || AR_SREV_9531_11(ah)) { INIT_INI_ARRAY(&ah->iniModesRxGain, qca953x_1p0_common_wo_xlna_rx_gain_table); INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, qca953x_1p0_common_wo_xlna_rx_gain_bounds); + } else if (AR_SREV_9531_20(ah)) { + INIT_INI_ARRAY(&ah->iniModesRxGain, + qca953x_2p0_common_wo_xlna_rx_gain_table); + INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, + qca953x_2p0_common_wo_xlna_rx_gain_bounds); } else if (AR_SREV_9580(ah)) INIT_INI_ARRAY(&ah->iniModesRxGain, ar9580_1p0_wo_xlna_rx_gain_table); diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 1e8ea5e4d4ca..2df6d2ee70c2 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -1361,7 +1361,7 @@ static void ar9003_hw_set_radar_params(struct ath_hw *ah, struct ath_hw_radar_conf *conf) { unsigned int regWrites = 0; - u32 radar_0 = 0, radar_1 = 0; + u32 radar_0 = 0, radar_1; if (!conf) { REG_CLR_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA); @@ -1375,6 +1375,9 @@ static void ar9003_hw_set_radar_params(struct ath_hw *ah, radar_0 |= SM(conf->pulse_rssi, AR_PHY_RADAR_0_PRSSI); radar_0 |= SM(conf->pulse_inband, AR_PHY_RADAR_0_INBAND); + radar_1 = REG_READ(ah, AR_PHY_RADAR_1); + radar_1 &= ~(AR_PHY_RADAR_1_MAXLEN | AR_PHY_RADAR_1_RELSTEP_THRESH | + AR_PHY_RADAR_1_RELPWR_THRESH); radar_1 |= AR_PHY_RADAR_1_MAX_RRSSI; radar_1 |= AR_PHY_RADAR_1_BLOCK_CHECK; radar_1 |= SM(conf->pulse_maxlen, AR_PHY_RADAR_1_MAXLEN); @@ -1401,7 +1404,7 @@ static void ar9003_hw_set_radar_conf(struct ath_hw *ah) conf->fir_power = -28; conf->radar_rssi = 0; conf->pulse_height = 10; - conf->pulse_rssi = 24; + conf->pulse_rssi = 15; conf->pulse_inband = 8; conf->pulse_maxlen = 255; conf->pulse_inband_step = 12; diff --git a/drivers/net/wireless/ath/ath9k/ar9003_rtt.h b/drivers/net/wireless/ath/ath9k/ar9003_rtt.h index a43b30d723a4..6290467a75a0 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_rtt.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_rtt.h @@ -17,6 +17,7 @@ #ifndef AR9003_RTT_H #define AR9003_RTT_H +#ifdef CONFIG_ATH9K_PCOEM void ar9003_hw_rtt_enable(struct ath_hw *ah); void ar9003_hw_rtt_disable(struct ath_hw *ah); void ar9003_hw_rtt_set_mask(struct ath_hw *ah, u32 rtt_mask); @@ -25,5 +26,40 @@ void ar9003_hw_rtt_load_hist(struct ath_hw *ah); void ar9003_hw_rtt_fill_hist(struct ath_hw *ah); void ar9003_hw_rtt_clear_hist(struct ath_hw *ah); bool ar9003_hw_rtt_restore(struct ath_hw *ah, struct ath9k_channel *chan); +#else +static inline void ar9003_hw_rtt_enable(struct ath_hw *ah) +{ +} + +static inline void ar9003_hw_rtt_disable(struct ath_hw *ah) +{ +} + +static inline void ar9003_hw_rtt_set_mask(struct ath_hw *ah, u32 rtt_mask) +{ +} + +static inline bool ar9003_hw_rtt_force_restore(struct ath_hw *ah) +{ + return false; +} + +static inline void ar9003_hw_rtt_load_hist(struct ath_hw *ah) +{ +} + +static inline void ar9003_hw_rtt_fill_hist(struct ath_hw *ah) +{ +} + +static inline void ar9003_hw_rtt_clear_hist(struct ath_hw *ah) +{ +} + +static inline bool ar9003_hw_rtt_restore(struct ath_hw *ah, struct ath9k_channel *chan) +{ + return false; +} +#endif #endif diff --git a/drivers/net/wireless/ath/ath9k/ar953x_initvals.h b/drivers/net/wireless/ath/ath9k/ar953x_initvals.h index 812a9d787bf3..159cc6fd2362 100644 --- a/drivers/net/wireless/ath/ath9k/ar953x_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar953x_initvals.h @@ -20,6 +20,8 @@ #define qca953x_1p0_mac_postamble ar9300_2p2_mac_postamble +#define qca953x_1p0_soc_preamble ar955x_1p0_soc_preamble + #define qca953x_1p0_soc_postamble ar9300_2p2_soc_postamble #define qca953x_1p0_common_rx_gain_table ar9300Common_rx_gain_table_2p2 @@ -28,6 +30,10 @@ #define qca953x_1p0_modes_fast_clock ar9300Modes_fast_clock_2p2 +#define qca953x_1p0_common_wo_xlna_rx_gain_bounds ar955x_1p0_common_wo_xlna_rx_gain_bounds + +#define qca953x_1p0_common_rx_gain_bounds ar955x_1p0_common_rx_gain_bounds + static const u32 qca953x_1p0_mac_core[][2] = { /* Addr allmodes */ {0x00000008, 0x00000000}, @@ -490,35 +496,6 @@ static const u32 qca953x_1p0_radio_postamble[][5] = { {0x00016540, 0x10804008, 0x10804008, 0x50804000, 0x50804000}, }; -static const u32 qca953x_1p0_soc_preamble[][2] = { - /* Addr allmodes */ - {0x00007000, 0x00000000}, - {0x00007004, 0x00000000}, - {0x00007008, 0x00000000}, - {0x0000700c, 0x00000000}, - {0x0000701c, 0x00000000}, - {0x00007020, 0x00000000}, - {0x00007024, 0x00000000}, - {0x00007028, 0x00000000}, - {0x0000702c, 0x00000000}, - {0x00007030, 0x00000000}, - {0x00007034, 0x00000002}, - {0x00007038, 0x000004c2}, - {0x00007048, 0x00000000}, -}; - -static const u32 qca953x_1p0_common_rx_gain_bounds[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, - {0x00009e48, 0x5030201a, 0x5030201a, 0x50302018, 0x50302018}, -}; - -static const u32 qca953x_1p0_common_wo_xlna_rx_gain_bounds[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, - {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, -}; - static const u32 qca953x_1p0_modes_xpa_tx_gain_table[][2] = { /* Addr allmodes */ {0x0000a2dc, 0xfffd5aaa}, @@ -715,8 +692,73 @@ static const u32 qca953x_1p1_modes_no_xpa_tx_gain_table[][2] = { {0x00016448, 0x6c927a70}, }; +static const u32 qca953x_1p1_modes_xpa_tx_gain_table[][2] = { + /* Addr allmodes */ + {0x0000a2dc, 0xfffb52aa}, + {0x0000a2e0, 0xfffd64cc}, + {0x0000a2e4, 0xfffe80f0}, + {0x0000a2e8, 0xffffff00}, + {0x0000a410, 0x000050d5}, + {0x0000a500, 0x00000000}, + {0x0000a504, 0x04000002}, + {0x0000a508, 0x08000004}, + {0x0000a50c, 0x0c000006}, + {0x0000a510, 0x1000000a}, + {0x0000a514, 0x1400000c}, + {0x0000a518, 0x1800000e}, + {0x0000a51c, 0x1c000048}, + {0x0000a520, 0x2000004a}, + {0x0000a524, 0x2400004c}, + {0x0000a528, 0x2800004e}, + {0x0000a52c, 0x2b00024a}, + {0x0000a530, 0x2f00024c}, + {0x0000a534, 0x3300024e}, + {0x0000a538, 0x36000668}, + {0x0000a53c, 0x38000669}, + {0x0000a540, 0x3a000868}, + {0x0000a544, 0x3d00086a}, + {0x0000a548, 0x4000086c}, + {0x0000a54c, 0x4200086e}, + {0x0000a550, 0x43000a6e}, + {0x0000a554, 0x43000a6e}, + {0x0000a558, 0x43000a6e}, + {0x0000a55c, 0x43000a6e}, + {0x0000a560, 0x43000a6e}, + {0x0000a564, 0x43000a6e}, + {0x0000a568, 0x43000a6e}, + {0x0000a56c, 0x43000a6e}, + {0x0000a570, 0x43000a6e}, + {0x0000a574, 0x43000a6e}, + {0x0000a578, 0x43000a6e}, + {0x0000a57c, 0x43000a6e}, + {0x0000a600, 0x00000000}, + {0x0000a604, 0x00000000}, + {0x0000a608, 0x00000000}, + {0x0000a60c, 0x03804000}, + {0x0000a610, 0x03804e01}, + {0x0000a614, 0x03804e01}, + {0x0000a618, 0x03804e01}, + {0x0000a61c, 0x04009002}, + {0x0000a620, 0x04009002}, + {0x0000a624, 0x04009002}, + {0x0000a628, 0x04009002}, + {0x0000a62c, 0x04009002}, + {0x0000a630, 0x04009002}, + {0x0000a634, 0x04009002}, + {0x0000a638, 0x04009002}, + {0x0000a63c, 0x04009002}, + {0x0000b2dc, 0xfffb52aa}, + {0x0000b2e0, 0xfffd64cc}, + {0x0000b2e4, 0xfffe80f0}, + {0x0000b2e8, 0xffffff00}, + {0x00016044, 0x024922db}, + {0x00016048, 0x6c927a70}, + {0x00016444, 0x024922db}, + {0x00016448, 0x6c927a70}, +}; + static const u32 qca953x_2p0_baseband_core[][2] = { - /* Addr allmodes */ + /* Addr allmodes */ {0x00009800, 0xafe68e30}, {0x00009804, 0xfd14e000}, {0x00009808, 0x9c0a9f6b}, @@ -914,4 +956,400 @@ static const u32 qca953x_2p0_baseband_postamble[][5] = { {0x0000b284, 0x00000000, 0x00000000, 0x00000010, 0x00000010}, }; +static const u32 qca953x_2p0_common_wo_xlna_rx_gain_table[][2] = { + /* Addr allmodes */ + {0x0000a000, 0x00010000}, + {0x0000a004, 0x00030002}, + {0x0000a008, 0x00050004}, + {0x0000a00c, 0x00810080}, + {0x0000a010, 0x00830082}, + {0x0000a014, 0x01810180}, + {0x0000a018, 0x01830182}, + {0x0000a01c, 0x01850184}, + {0x0000a020, 0x01890188}, + {0x0000a024, 0x018b018a}, + {0x0000a028, 0x018d018c}, + {0x0000a02c, 0x03820190}, + {0x0000a030, 0x03840383}, + {0x0000a034, 0x03880385}, + {0x0000a038, 0x038a0389}, + {0x0000a03c, 0x038c038b}, + {0x0000a040, 0x0390038d}, + {0x0000a044, 0x03920391}, + {0x0000a048, 0x03940393}, + {0x0000a04c, 0x03960395}, + {0x0000a050, 0x00000000}, + {0x0000a054, 0x00000000}, + {0x0000a058, 0x00000000}, + {0x0000a05c, 0x00000000}, + {0x0000a060, 0x00000000}, + {0x0000a064, 0x00000000}, + {0x0000a068, 0x00000000}, + {0x0000a06c, 0x00000000}, + {0x0000a070, 0x00000000}, + {0x0000a074, 0x00000000}, + {0x0000a078, 0x00000000}, + {0x0000a07c, 0x00000000}, + {0x0000a080, 0x29292929}, + {0x0000a084, 0x29292929}, + {0x0000a088, 0x29292929}, + {0x0000a08c, 0x29292929}, + {0x0000a090, 0x22292929}, + {0x0000a094, 0x1d1d2222}, + {0x0000a098, 0x0c111117}, + {0x0000a09c, 0x00030303}, + {0x0000a0a0, 0x00000000}, + {0x0000a0a4, 0x00000000}, + {0x0000a0a8, 0x00000000}, + {0x0000a0ac, 0x00000000}, + {0x0000a0b0, 0x00000000}, + {0x0000a0b4, 0x00000000}, + {0x0000a0b8, 0x00000000}, + {0x0000a0bc, 0x00000000}, + {0x0000a0c0, 0x001f0000}, + {0x0000a0c4, 0x01000101}, + {0x0000a0c8, 0x011e011f}, + {0x0000a0cc, 0x011c011d}, + {0x0000a0d0, 0x02030204}, + {0x0000a0d4, 0x02010202}, + {0x0000a0d8, 0x021f0200}, + {0x0000a0dc, 0x0302021e}, + {0x0000a0e0, 0x03000301}, + {0x0000a0e4, 0x031e031f}, + {0x0000a0e8, 0x0402031d}, + {0x0000a0ec, 0x04000401}, + {0x0000a0f0, 0x041e041f}, + {0x0000a0f4, 0x0502041d}, + {0x0000a0f8, 0x05000501}, + {0x0000a0fc, 0x051e051f}, + {0x0000a100, 0x06010602}, + {0x0000a104, 0x061f0600}, + {0x0000a108, 0x061d061e}, + {0x0000a10c, 0x07020703}, + {0x0000a110, 0x07000701}, + {0x0000a114, 0x00000000}, + {0x0000a118, 0x00000000}, + {0x0000a11c, 0x00000000}, + {0x0000a120, 0x00000000}, + {0x0000a124, 0x00000000}, + {0x0000a128, 0x00000000}, + {0x0000a12c, 0x00000000}, + {0x0000a130, 0x00000000}, + {0x0000a134, 0x00000000}, + {0x0000a138, 0x00000000}, + {0x0000a13c, 0x00000000}, + {0x0000a140, 0x001f0000}, + {0x0000a144, 0x01000101}, + {0x0000a148, 0x011e011f}, + {0x0000a14c, 0x011c011d}, + {0x0000a150, 0x02030204}, + {0x0000a154, 0x02010202}, + {0x0000a158, 0x021f0200}, + {0x0000a15c, 0x0302021e}, + {0x0000a160, 0x03000301}, + {0x0000a164, 0x031e031f}, + {0x0000a168, 0x0402031d}, + {0x0000a16c, 0x04000401}, + {0x0000a170, 0x041e041f}, + {0x0000a174, 0x0502041d}, + {0x0000a178, 0x05000501}, + {0x0000a17c, 0x051e051f}, + {0x0000a180, 0x06010602}, + {0x0000a184, 0x061f0600}, + {0x0000a188, 0x061d061e}, + {0x0000a18c, 0x07020703}, + {0x0000a190, 0x07000701}, + {0x0000a194, 0x00000000}, + {0x0000a198, 0x00000000}, + {0x0000a19c, 0x00000000}, + {0x0000a1a0, 0x00000000}, + {0x0000a1a4, 0x00000000}, + {0x0000a1a8, 0x00000000}, + {0x0000a1ac, 0x00000000}, + {0x0000a1b0, 0x00000000}, + {0x0000a1b4, 0x00000000}, + {0x0000a1b8, 0x00000000}, + {0x0000a1bc, 0x00000000}, + {0x0000a1c0, 0x00000000}, + {0x0000a1c4, 0x00000000}, + {0x0000a1c8, 0x00000000}, + {0x0000a1cc, 0x00000000}, + {0x0000a1d0, 0x00000000}, + {0x0000a1d4, 0x00000000}, + {0x0000a1d8, 0x00000000}, + {0x0000a1dc, 0x00000000}, + {0x0000a1e0, 0x00000000}, + {0x0000a1e4, 0x00000000}, + {0x0000a1e8, 0x00000000}, + {0x0000a1ec, 0x00000000}, + {0x0000a1f0, 0x00000396}, + {0x0000a1f4, 0x00000396}, + {0x0000a1f8, 0x00000396}, + {0x0000a1fc, 0x00000196}, + {0x0000b000, 0x00010000}, + {0x0000b004, 0x00030002}, + {0x0000b008, 0x00050004}, + {0x0000b00c, 0x00810080}, + {0x0000b010, 0x00830082}, + {0x0000b014, 0x01810180}, + {0x0000b018, 0x01830182}, + {0x0000b01c, 0x01850184}, + {0x0000b020, 0x02810280}, + {0x0000b024, 0x02830282}, + {0x0000b028, 0x02850284}, + {0x0000b02c, 0x02890288}, + {0x0000b030, 0x028b028a}, + {0x0000b034, 0x0388028c}, + {0x0000b038, 0x038a0389}, + {0x0000b03c, 0x038c038b}, + {0x0000b040, 0x0390038d}, + {0x0000b044, 0x03920391}, + {0x0000b048, 0x03940393}, + {0x0000b04c, 0x03960395}, + {0x0000b050, 0x00000000}, + {0x0000b054, 0x00000000}, + {0x0000b058, 0x00000000}, + {0x0000b05c, 0x00000000}, + {0x0000b060, 0x00000000}, + {0x0000b064, 0x00000000}, + {0x0000b068, 0x00000000}, + {0x0000b06c, 0x00000000}, + {0x0000b070, 0x00000000}, + {0x0000b074, 0x00000000}, + {0x0000b078, 0x00000000}, + {0x0000b07c, 0x00000000}, + {0x0000b080, 0x32323232}, + {0x0000b084, 0x2f2f3232}, + {0x0000b088, 0x23282a2d}, + {0x0000b08c, 0x1c1e2123}, + {0x0000b090, 0x14171919}, + {0x0000b094, 0x0e0e1214}, + {0x0000b098, 0x03050707}, + {0x0000b09c, 0x00030303}, + {0x0000b0a0, 0x00000000}, + {0x0000b0a4, 0x00000000}, + {0x0000b0a8, 0x00000000}, + {0x0000b0ac, 0x00000000}, + {0x0000b0b0, 0x00000000}, + {0x0000b0b4, 0x00000000}, + {0x0000b0b8, 0x00000000}, + {0x0000b0bc, 0x00000000}, + {0x0000b0c0, 0x003f0020}, + {0x0000b0c4, 0x00400041}, + {0x0000b0c8, 0x0140005f}, + {0x0000b0cc, 0x0160015f}, + {0x0000b0d0, 0x017e017f}, + {0x0000b0d4, 0x02410242}, + {0x0000b0d8, 0x025f0240}, + {0x0000b0dc, 0x027f0260}, + {0x0000b0e0, 0x0341027e}, + {0x0000b0e4, 0x035f0340}, + {0x0000b0e8, 0x037f0360}, + {0x0000b0ec, 0x04400441}, + {0x0000b0f0, 0x0460045f}, + {0x0000b0f4, 0x0541047f}, + {0x0000b0f8, 0x055f0540}, + {0x0000b0fc, 0x057f0560}, + {0x0000b100, 0x06400641}, + {0x0000b104, 0x0660065f}, + {0x0000b108, 0x067e067f}, + {0x0000b10c, 0x07410742}, + {0x0000b110, 0x075f0740}, + {0x0000b114, 0x077f0760}, + {0x0000b118, 0x07800781}, + {0x0000b11c, 0x07a0079f}, + {0x0000b120, 0x07c107bf}, + {0x0000b124, 0x000007c0}, + {0x0000b128, 0x00000000}, + {0x0000b12c, 0x00000000}, + {0x0000b130, 0x00000000}, + {0x0000b134, 0x00000000}, + {0x0000b138, 0x00000000}, + {0x0000b13c, 0x00000000}, + {0x0000b140, 0x003f0020}, + {0x0000b144, 0x00400041}, + {0x0000b148, 0x0140005f}, + {0x0000b14c, 0x0160015f}, + {0x0000b150, 0x017e017f}, + {0x0000b154, 0x02410242}, + {0x0000b158, 0x025f0240}, + {0x0000b15c, 0x027f0260}, + {0x0000b160, 0x0341027e}, + {0x0000b164, 0x035f0340}, + {0x0000b168, 0x037f0360}, + {0x0000b16c, 0x04400441}, + {0x0000b170, 0x0460045f}, + {0x0000b174, 0x0541047f}, + {0x0000b178, 0x055f0540}, + {0x0000b17c, 0x057f0560}, + {0x0000b180, 0x06400641}, + {0x0000b184, 0x0660065f}, + {0x0000b188, 0x067e067f}, + {0x0000b18c, 0x07410742}, + {0x0000b190, 0x075f0740}, + {0x0000b194, 0x077f0760}, + {0x0000b198, 0x07800781}, + {0x0000b19c, 0x07a0079f}, + {0x0000b1a0, 0x07c107bf}, + {0x0000b1a4, 0x000007c0}, + {0x0000b1a8, 0x00000000}, + {0x0000b1ac, 0x00000000}, + {0x0000b1b0, 0x00000000}, + {0x0000b1b4, 0x00000000}, + {0x0000b1b8, 0x00000000}, + {0x0000b1bc, 0x00000000}, + {0x0000b1c0, 0x00000000}, + {0x0000b1c4, 0x00000000}, + {0x0000b1c8, 0x00000000}, + {0x0000b1cc, 0x00000000}, + {0x0000b1d0, 0x00000000}, + {0x0000b1d4, 0x00000000}, + {0x0000b1d8, 0x00000000}, + {0x0000b1dc, 0x00000000}, + {0x0000b1e0, 0x00000000}, + {0x0000b1e4, 0x00000000}, + {0x0000b1e8, 0x00000000}, + {0x0000b1ec, 0x00000000}, + {0x0000b1f0, 0x00000396}, + {0x0000b1f4, 0x00000396}, + {0x0000b1f8, 0x00000396}, + {0x0000b1fc, 0x00000196}, +}; + +static const u32 qca953x_2p0_common_wo_xlna_rx_gain_bounds[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, + {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, +}; + +static const u32 qca953x_2p0_modes_xpa_tx_gain_table[][2] = { + /* Addr allmodes */ + {0x0000a2dc, 0xfffb52aa}, + {0x0000a2e0, 0xfffd64cc}, + {0x0000a2e4, 0xfffe80f0}, + {0x0000a2e8, 0xffffff00}, + {0x0000a410, 0x000050d5}, + {0x0000a500, 0x00000000}, + {0x0000a504, 0x04000002}, + {0x0000a508, 0x08000004}, + {0x0000a50c, 0x0c000006}, + {0x0000a510, 0x1000000a}, + {0x0000a514, 0x1400000c}, + {0x0000a518, 0x1800000e}, + {0x0000a51c, 0x1c000048}, + {0x0000a520, 0x2000004a}, + {0x0000a524, 0x2400004c}, + {0x0000a528, 0x2800004e}, + {0x0000a52c, 0x2b00024a}, + {0x0000a530, 0x2f00024c}, + {0x0000a534, 0x3300024e}, + {0x0000a538, 0x36000668}, + {0x0000a53c, 0x38000669}, + {0x0000a540, 0x3a000868}, + {0x0000a544, 0x3d00086a}, + {0x0000a548, 0x4000086c}, + {0x0000a54c, 0x4200086e}, + {0x0000a550, 0x43000a6e}, + {0x0000a554, 0x43000a6e}, + {0x0000a558, 0x43000a6e}, + {0x0000a55c, 0x43000a6e}, + {0x0000a560, 0x43000a6e}, + {0x0000a564, 0x43000a6e}, + {0x0000a568, 0x43000a6e}, + {0x0000a56c, 0x43000a6e}, + {0x0000a570, 0x43000a6e}, + {0x0000a574, 0x43000a6e}, + {0x0000a578, 0x43000a6e}, + {0x0000a57c, 0x43000a6e}, + {0x0000a600, 0x00000000}, + {0x0000a604, 0x00000000}, + {0x0000a608, 0x00000000}, + {0x0000a60c, 0x03804000}, + {0x0000a610, 0x03804e01}, + {0x0000a614, 0x03804e01}, + {0x0000a618, 0x03804e01}, + {0x0000a61c, 0x04009002}, + {0x0000a620, 0x04009002}, + {0x0000a624, 0x04009002}, + {0x0000a628, 0x04009002}, + {0x0000a62c, 0x04009002}, + {0x0000a630, 0x04009002}, + {0x0000a634, 0x04009002}, + {0x0000a638, 0x04009002}, + {0x0000a63c, 0x04009002}, + {0x0000b2dc, 0xfffb52aa}, + {0x0000b2e0, 0xfffd64cc}, + {0x0000b2e4, 0xfffe80f0}, + {0x0000b2e8, 0xffffff00}, + {0x00016044, 0x024922db}, + {0x00016048, 0x6c927a70}, + {0x00016444, 0x024922db}, + {0x00016448, 0x6c927a70}, +}; + +static const u32 qca953x_2p0_modes_no_xpa_tx_gain_table[][2] = { + /* Addr allmodes */ + {0x0000a2dc, 0xffd5f552}, + {0x0000a2e0, 0xffe60664}, + {0x0000a2e4, 0xfff80780}, + {0x0000a2e8, 0xfffff800}, + {0x0000a410, 0x000050de}, + {0x0000a500, 0x00000061}, + {0x0000a504, 0x04000063}, + {0x0000a508, 0x08000065}, + {0x0000a50c, 0x0c000261}, + {0x0000a510, 0x10000263}, + {0x0000a514, 0x14000265}, + {0x0000a518, 0x18000482}, + {0x0000a51c, 0x1b000484}, + {0x0000a520, 0x1f000486}, + {0x0000a524, 0x240008c2}, + {0x0000a528, 0x28000cc1}, + {0x0000a52c, 0x2d000ce3}, + {0x0000a530, 0x31000ce5}, + {0x0000a534, 0x350010e5}, + {0x0000a538, 0x360012e5}, + {0x0000a53c, 0x380014e5}, + {0x0000a540, 0x3b0018e5}, + {0x0000a544, 0x3d001d04}, + {0x0000a548, 0x3e001d05}, + {0x0000a54c, 0x40001d07}, + {0x0000a550, 0x42001f27}, + {0x0000a554, 0x43001f67}, + {0x0000a558, 0x46001fe7}, + {0x0000a55c, 0x47001f2b}, + {0x0000a560, 0x49001f0d}, + {0x0000a564, 0x4b001ed2}, + {0x0000a568, 0x4c001ed4}, + {0x0000a56c, 0x4e001f15}, + {0x0000a570, 0x4f001ff6}, + {0x0000a574, 0x4f001ff6}, + {0x0000a578, 0x4f001ff6}, + {0x0000a57c, 0x4f001ff6}, + {0x0000a600, 0x00000000}, + {0x0000a604, 0x00000000}, + {0x0000a608, 0x00000000}, + {0x0000a60c, 0x00804201}, + {0x0000a610, 0x01008201}, + {0x0000a614, 0x0180c402}, + {0x0000a618, 0x0180c603}, + {0x0000a61c, 0x0180c603}, + {0x0000a620, 0x01c10603}, + {0x0000a624, 0x01c10704}, + {0x0000a628, 0x02c18b05}, + {0x0000a62c, 0x02c14c07}, + {0x0000a630, 0x01008704}, + {0x0000a634, 0x01c10402}, + {0x0000a638, 0x0301cc07}, + {0x0000a63c, 0x0301cc07}, + {0x0000b2dc, 0xffd5f552}, + {0x0000b2e0, 0xffe60664}, + {0x0000b2e4, 0xfff80780}, + {0x0000b2e8, 0xfffff800}, + {0x00016044, 0x049242db}, + {0x00016048, 0x6c927a70}, + {0x00016444, 0x049242db}, + {0x00016448, 0x6c927a70}, +}; + #endif /* INITVALS_953X_H */ diff --git a/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h index 74d8bc05b317..fd6a84ccd49e 100644 --- a/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h @@ -507,7 +507,7 @@ static const u32 ar955x_1p0_baseband_core[][2] = { {0x00009d04, 0x40206c10}, {0x00009d08, 0x009c4060}, {0x00009d0c, 0x9883800a}, - {0x00009d10, 0x01834061}, + {0x00009d10, 0x01884061}, {0x00009d14, 0x00c0040b}, {0x00009d18, 0x00000000}, {0x00009e08, 0x0038230c}, @@ -545,9 +545,9 @@ static const u32 ar955x_1p0_baseband_core[][2] = { {0x0000a370, 0x00000000}, {0x0000a390, 0x00000001}, {0x0000a394, 0x00000444}, - {0x0000a398, 0x1f020503}, - {0x0000a39c, 0x29180c03}, - {0x0000a3a0, 0x9a8b6844}, + {0x0000a398, 0x001f0e0f}, + {0x0000a39c, 0x0075393f}, + {0x0000a3a0, 0xb79f6427}, {0x0000a3a4, 0x00000000}, {0x0000a3a8, 0xaaaaaaaa}, {0x0000a3ac, 0x3c466478}, diff --git a/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h index a5ca65240af3..5d4629f96c15 100644 --- a/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h @@ -24,7 +24,149 @@ #define ar9580_1p0_soc_postamble ar9300_2p2_soc_postamble -#define ar9580_1p0_radio_core ar9300_2p2_radio_core +static const u32 ar9580_1p0_radio_core[][2] = { + /* Addr allmodes */ + {0x00016000, 0x36db2db6}, + {0x00016004, 0x6db6db40}, + {0x00016008, 0x73f00000}, + {0x0001600c, 0x00000000}, + {0x00016040, 0x7f80fff8}, + {0x0001604c, 0x76d005b5}, + {0x00016050, 0x556cf031}, + {0x00016054, 0x13449440}, + {0x00016058, 0x0c51c92c}, + {0x0001605c, 0x3db7fffc}, + {0x00016060, 0xfffffffc}, + {0x00016064, 0x000f0278}, + {0x0001606c, 0x6db60000}, + {0x00016080, 0x00000000}, + {0x00016084, 0x0e48048c}, + {0x00016088, 0x54214514}, + {0x0001608c, 0x119f481e}, + {0x00016090, 0x24926490}, + {0x00016098, 0xd2888888}, + {0x000160a0, 0x0a108ffe}, + {0x000160a4, 0x812fc370}, + {0x000160a8, 0x423c8000}, + {0x000160b4, 0x92480080}, + {0x000160c0, 0x00adb6d0}, + {0x000160c4, 0x6db6db60}, + {0x000160c8, 0x6db6db6c}, + {0x000160cc, 0x01e6c000}, + {0x00016100, 0x3fffbe01}, + {0x00016104, 0xfff80000}, + {0x00016108, 0x00080010}, + {0x00016144, 0x02084080}, + {0x00016148, 0x00000000}, + {0x00016280, 0x058a0001}, + {0x00016284, 0x3d840208}, + {0x00016288, 0x05a20408}, + {0x0001628c, 0x00038c07}, + {0x00016290, 0x00000004}, + {0x00016294, 0x458a214f}, + {0x00016380, 0x00000000}, + {0x00016384, 0x00000000}, + {0x00016388, 0x00800700}, + {0x0001638c, 0x00800700}, + {0x00016390, 0x00800700}, + {0x00016394, 0x00000000}, + {0x00016398, 0x00000000}, + {0x0001639c, 0x00000000}, + {0x000163a0, 0x00000001}, + {0x000163a4, 0x00000001}, + {0x000163a8, 0x00000000}, + {0x000163ac, 0x00000000}, + {0x000163b0, 0x00000000}, + {0x000163b4, 0x00000000}, + {0x000163b8, 0x00000000}, + {0x000163bc, 0x00000000}, + {0x000163c0, 0x000000a0}, + {0x000163c4, 0x000c0000}, + {0x000163c8, 0x14021402}, + {0x000163cc, 0x00001402}, + {0x000163d0, 0x00000000}, + {0x000163d4, 0x00000000}, + {0x00016400, 0x36db2db6}, + {0x00016404, 0x6db6db40}, + {0x00016408, 0x73f00000}, + {0x0001640c, 0x00000000}, + {0x00016440, 0x7f80fff8}, + {0x0001644c, 0x76d005b5}, + {0x00016450, 0x556cf031}, + {0x00016454, 0x13449440}, + {0x00016458, 0x0c51c92c}, + {0x0001645c, 0x3db7fffc}, + {0x00016460, 0xfffffffc}, + {0x00016464, 0x000f0278}, + {0x0001646c, 0x6db60000}, + {0x00016500, 0x3fffbe01}, + {0x00016504, 0xfff80000}, + {0x00016508, 0x00080010}, + {0x00016544, 0x02084080}, + {0x00016548, 0x00000000}, + {0x00016780, 0x00000000}, + {0x00016784, 0x00000000}, + {0x00016788, 0x00800700}, + {0x0001678c, 0x00800700}, + {0x00016790, 0x00800700}, + {0x00016794, 0x00000000}, + {0x00016798, 0x00000000}, + {0x0001679c, 0x00000000}, + {0x000167a0, 0x00000001}, + {0x000167a4, 0x00000001}, + {0x000167a8, 0x00000000}, + {0x000167ac, 0x00000000}, + {0x000167b0, 0x00000000}, + {0x000167b4, 0x00000000}, + {0x000167b8, 0x00000000}, + {0x000167bc, 0x00000000}, + {0x000167c0, 0x000000a0}, + {0x000167c4, 0x000c0000}, + {0x000167c8, 0x14021402}, + {0x000167cc, 0x00001402}, + {0x000167d0, 0x00000000}, + {0x000167d4, 0x00000000}, + {0x00016800, 0x36db2db6}, + {0x00016804, 0x6db6db40}, + {0x00016808, 0x73f00000}, + {0x0001680c, 0x00000000}, + {0x00016840, 0x7f80fff8}, + {0x0001684c, 0x76d005b5}, + {0x00016850, 0x556cf031}, + {0x00016854, 0x13449440}, + {0x00016858, 0x0c51c92c}, + {0x0001685c, 0x3db7fffc}, + {0x00016860, 0xfffffffc}, + {0x00016864, 0x000f0278}, + {0x0001686c, 0x6db60000}, + {0x00016900, 0x3fffbe01}, + {0x00016904, 0xfff80000}, + {0x00016908, 0x00080010}, + {0x00016944, 0x02084080}, + {0x00016948, 0x00000000}, + {0x00016b80, 0x00000000}, + {0x00016b84, 0x00000000}, + {0x00016b88, 0x00800700}, + {0x00016b8c, 0x00800700}, + {0x00016b90, 0x00800700}, + {0x00016b94, 0x00000000}, + {0x00016b98, 0x00000000}, + {0x00016b9c, 0x00000000}, + {0x00016ba0, 0x00000001}, + {0x00016ba4, 0x00000001}, + {0x00016ba8, 0x00000000}, + {0x00016bac, 0x00000000}, + {0x00016bb0, 0x00000000}, + {0x00016bb4, 0x00000000}, + {0x00016bb8, 0x00000000}, + {0x00016bbc, 0x00000000}, + {0x00016bc0, 0x000000a0}, + {0x00016bc4, 0x000c0000}, + {0x00016bc8, 0x14021402}, + {0x00016bcc, 0x00001402}, + {0x00016bd0, 0x00000000}, + {0x00016bd4, 0x00000000}, +}; #define ar9580_1p0_mac_postamble ar9300_2p2_mac_postamble diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 01a7db061c6a..abe8bd6b972d 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -28,7 +28,6 @@ #include "debug.h" #include "mci.h" #include "dfs.h" -#include "spectral.h" struct ath_node; struct ath_vif; @@ -345,7 +344,9 @@ struct ath_chanctx { u64 tsf_val; u32 last_beacon; + int flush_timeout; u16 txpower; + u16 cur_txpower; bool offchannel; bool stopped; bool active; @@ -362,7 +363,7 @@ enum ath_chanctx_event { ATH_CHANCTX_EVENT_BEACON_SENT, ATH_CHANCTX_EVENT_TSF_TIMER, ATH_CHANCTX_EVENT_BEACON_RECEIVED, - ATH_CHANCTX_EVENT_ASSOC, + ATH_CHANCTX_EVENT_AUTHORIZED, ATH_CHANCTX_EVENT_SWITCH, ATH_CHANCTX_EVENT_ASSIGN, ATH_CHANCTX_EVENT_UNASSIGN, @@ -380,10 +381,12 @@ enum ath_chanctx_state { struct ath_chanctx_sched { bool beacon_pending; + bool beacon_adjust; bool offchannel_pending; bool wait_switch; bool force_noa_update; bool extend_absence; + bool mgd_prepare_tx; enum ath_chanctx_state state; u8 beacon_miss; @@ -468,6 +471,7 @@ void ath_chanctx_set_next(struct ath_softc *sc, bool force); void ath_offchannel_next(struct ath_softc *sc); void ath_scan_complete(struct ath_softc *sc, bool abort); void ath_roc_complete(struct ath_softc *sc, bool abort); +struct ath_chanctx* ath_is_go_chanctx_present(struct ath_softc *sc); #else @@ -540,7 +544,6 @@ static inline void ath_chanctx_check_active(struct ath_softc *sc, #endif /* CONFIG_ATH9K_CHANNEL_CONTEXT */ -int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan); void ath_startrecv(struct ath_softc *sc); bool ath_stoprecv(struct ath_softc *sc); u32 ath_calcrxfilter(struct ath_softc *sc); @@ -595,7 +598,7 @@ struct ath_vif { u16 seq_no; /* BSS info */ - u8 bssid[ETH_ALEN]; + u8 bssid[ETH_ALEN] __aligned(2); u16 aid; bool assoc; @@ -618,6 +621,7 @@ struct ath_vif { u32 noa_start; u32 noa_duration; bool periodic_noa; + bool oneshot_noa; }; struct ath9k_vif_iter_data { @@ -715,7 +719,8 @@ int ath_update_survey_stats(struct ath_softc *sc); void ath_update_survey_nf(struct ath_softc *sc, int channel); void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type); void ath_ps_full_sleep(unsigned long data); -void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop); +void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop, + bool sw_pending, bool timeout_override); /**********/ /* BTCOEX */ @@ -927,6 +932,7 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs); #define ATH9K_PCI_AR9565_2ANT 0x0100 #define ATH9K_PCI_NO_PLL_PWRSAVE 0x0200 #define ATH9K_PCI_KILLER 0x0400 +#define ATH9K_PCI_LED_ACT_HI 0x0800 /* * Default cache line size, in bytes. @@ -975,6 +981,7 @@ struct ath_softc { struct ath_chanctx_sched sched; struct ath_offchannel offchannel; struct ath_chanctx *next_chan; + struct completion go_beacon; #endif unsigned long driver_data; @@ -982,7 +989,6 @@ struct ath_softc { u8 gtt_cnt; u32 intrstatus; u16 ps_flags; /* PS_* */ - u16 curtxpow; bool ps_enabled; bool ps_idle; short nbcnvifs; @@ -1023,10 +1029,8 @@ struct ath_softc { struct dfs_pattern_detector *dfs_detector; u64 dfs_prev_pulse_ts; u32 wow_enabled; - /* relay(fs) channel for spectral scan */ - struct rchan *rfs_chan_spec_scan; - enum spectral_mode spectral_mode; - struct ath_spec_scan spec_config; + + struct ath_spec_scan_priv spec_priv; struct ieee80211_vif *tx99_vif; struct sk_buff *tx99_skb; @@ -1069,7 +1073,7 @@ void ath9k_tasklet(unsigned long data); int ath_cabq_update(struct ath_softc *); u8 ath9k_parse_mpdudensity(u8 mpdudensity); irqreturn_t ath_isr(int irq, void *dev); -int ath_reset(struct ath_softc *sc); +int ath_reset(struct ath_softc *sc, struct ath9k_channel *hchan); void ath_cancel_work(struct ath_softc *sc); void ath_restart_work(struct ath_softc *sc); int ath9k_init_device(u16 devid, struct ath_softc *sc, diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 278365b8a895..e200a6e3aca5 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -234,7 +234,7 @@ void ath9k_hw_start_nfcal(struct ath_hw *ah, bool update) REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); } -void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) +int ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) { struct ath9k_nfcal_hist *h = NULL; unsigned i, j; @@ -301,7 +301,7 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) ath_dbg(common, ANY, "Timeout while waiting for nf to load: AR_PHY_AGC_CONTROL=0x%x\n", REG_READ(ah, AR_PHY_AGC_CONTROL)); - return; + return -ETIMEDOUT; } /* @@ -322,6 +322,8 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) } } REGWRITE_BUFFER_FLUSH(ah); + + return 0; } diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h index b8ed95e9a335..87badf4bb8a4 100644 --- a/drivers/net/wireless/ath/ath9k/calib.h +++ b/drivers/net/wireless/ath/ath9k/calib.h @@ -109,7 +109,7 @@ struct ath9k_pacal_info{ bool ath9k_hw_reset_calvalid(struct ath_hw *ah); void ath9k_hw_start_nfcal(struct ath_hw *ah, bool update); -void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan); +int ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan); bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan); void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, struct ath9k_channel *chan); diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c index 945c89826b14..206665059d66 100644 --- a/drivers/net/wireless/ath/ath9k/channel.c +++ b/drivers/net/wireless/ath/ath9k/channel.c @@ -66,7 +66,7 @@ static int ath_set_channel(struct ath_softc *sc) } hchan = &sc->sc_ah->channels[pos]; - r = ath_reset_internal(sc, hchan); + r = ath_reset(sc, hchan); if (r) return r; @@ -92,8 +92,8 @@ static int ath_set_channel(struct ath_softc *sc) } else { /* perform spectral scan if requested. */ if (test_bit(ATH_OP_SCANNING, &common->op_flags) && - sc->spectral_mode == SPECTRAL_CHANSCAN) - ath9k_spectral_scan_trigger(hw); + sc->spec_priv.spectral_mode == SPECTRAL_CHANSCAN) + ath9k_cmn_spectral_scan_trigger(common, &sc->spec_priv); } return 0; @@ -117,6 +117,7 @@ void ath_chanctx_init(struct ath_softc *sc) cfg80211_chandef_create(&ctx->chandef, chan, NL80211_CHAN_HT20); INIT_LIST_HEAD(&ctx->vifs); ctx->txpower = ATH_TXPOWER_MAX; + ctx->flush_timeout = HZ / 5; /* 200ms */ for (j = 0; j < ARRAY_SIZE(ctx->acq); j++) INIT_LIST_HEAD(&ctx->acq[j]); } @@ -145,6 +146,36 @@ void ath_chanctx_set_channel(struct ath_softc *sc, struct ath_chanctx *ctx, #ifdef CONFIG_ATH9K_CHANNEL_CONTEXT +/*************/ +/* Utilities */ +/*************/ + +struct ath_chanctx* ath_is_go_chanctx_present(struct ath_softc *sc) +{ + struct ath_chanctx *ctx; + struct ath_vif *avp; + struct ieee80211_vif *vif; + + spin_lock_bh(&sc->chan_lock); + + ath_for_each_chanctx(sc, ctx) { + if (!ctx->active) + continue; + + list_for_each_entry(avp, &ctx->vifs, list) { + vif = avp->vif; + + if (ieee80211_vif_type_p2p(vif) == NL80211_IFTYPE_P2P_GO) { + spin_unlock_bh(&sc->chan_lock); + return ctx; + } + } + } + + spin_unlock_bh(&sc->chan_lock); + return NULL; +} + /**********************************************************/ /* Functions to handle the channel context state machine. */ /**********************************************************/ @@ -171,7 +202,7 @@ static const char *chanctx_event_string(enum ath_chanctx_event ev) case_rtn_string(ATH_CHANCTX_EVENT_BEACON_SENT); case_rtn_string(ATH_CHANCTX_EVENT_TSF_TIMER); case_rtn_string(ATH_CHANCTX_EVENT_BEACON_RECEIVED); - case_rtn_string(ATH_CHANCTX_EVENT_ASSOC); + case_rtn_string(ATH_CHANCTX_EVENT_AUTHORIZED); case_rtn_string(ATH_CHANCTX_EVENT_SWITCH); case_rtn_string(ATH_CHANCTX_EVENT_ASSIGN); case_rtn_string(ATH_CHANCTX_EVENT_UNASSIGN); @@ -198,6 +229,7 @@ static const char *chanctx_state_string(enum ath_chanctx_state state) void ath_chanctx_check_active(struct ath_softc *sc, struct ath_chanctx *ctx) { struct ath_common *common = ath9k_hw_common(sc->sc_ah); + struct ath_chanctx *ictx; struct ath_vif *avp; bool active = false; u8 n_active = 0; @@ -205,6 +237,28 @@ void ath_chanctx_check_active(struct ath_softc *sc, struct ath_chanctx *ctx) if (!ctx) return; + if (ctx == &sc->offchannel.chan) { + spin_lock_bh(&sc->chan_lock); + + if (likely(sc->sched.channel_switch_time)) + ctx->flush_timeout = + usecs_to_jiffies(sc->sched.channel_switch_time); + else + ctx->flush_timeout = + msecs_to_jiffies(10); + + spin_unlock_bh(&sc->chan_lock); + + /* + * There is no need to iterate over the + * active/assigned channel contexts if + * the current context is offchannel. + */ + return; + } + + ictx = ctx; + list_for_each_entry(avp, &ctx->vifs, list) { struct ieee80211_vif *vif = avp->vif; @@ -227,12 +281,23 @@ void ath_chanctx_check_active(struct ath_softc *sc, struct ath_chanctx *ctx) n_active++; } + spin_lock_bh(&sc->chan_lock); + if (n_active <= 1) { + ictx->flush_timeout = HZ / 5; clear_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags); + spin_unlock_bh(&sc->chan_lock); return; } - if (test_and_set_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags)) + + ictx->flush_timeout = usecs_to_jiffies(sc->sched.channel_switch_time); + + if (test_and_set_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags)) { + spin_unlock_bh(&sc->chan_lock); return; + } + + spin_unlock_bh(&sc->chan_lock); if (ath9k_is_chanctx_enabled()) { ath_chanctx_event(sc, NULL, @@ -301,6 +366,111 @@ static void ath_chanctx_setup_timer(struct ath_softc *sc, u32 tsf_time) "Setup chanctx timer with timeout: %d ms\n", jiffies_to_msecs(tsf_time)); } +static void ath_chanctx_handle_bmiss(struct ath_softc *sc, + struct ath_chanctx *ctx, + struct ath_vif *avp) +{ + /* + * Clear the extend_absence flag if it had been + * set during the previous beacon transmission, + * since we need to revert to the normal NoA + * schedule. + */ + if (ctx->active && sc->sched.extend_absence) { + avp->noa_duration = 0; + sc->sched.extend_absence = false; + } + + /* If at least two consecutive beacons were missed on the STA + * chanctx, stay on the STA channel for one extra beacon period, + * to resync the timer properly. + */ + if (ctx->active && sc->sched.beacon_miss >= 2) { + avp->noa_duration = 0; + sc->sched.extend_absence = true; + } +} + +static void ath_chanctx_offchannel_noa(struct ath_softc *sc, + struct ath_chanctx *ctx, + struct ath_vif *avp, + u32 tsf_time) +{ + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + + avp->noa_index++; + avp->offchannel_start = tsf_time; + avp->offchannel_duration = sc->sched.offchannel_duration; + + ath_dbg(common, CHAN_CTX, + "offchannel noa_duration: %d, noa_start: %d, noa_index: %d\n", + avp->offchannel_duration, + avp->offchannel_start, + avp->noa_index); + + /* + * When multiple contexts are active, the NoA + * has to be recalculated and advertised after + * an offchannel operation. + */ + if (ctx->active && avp->noa_duration) + avp->noa_duration = 0; +} + +static void ath_chanctx_set_periodic_noa(struct ath_softc *sc, + struct ath_vif *avp, + struct ath_beacon_config *cur_conf, + u32 tsf_time, + u32 beacon_int) +{ + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + + avp->noa_index++; + avp->noa_start = tsf_time; + + if (sc->sched.extend_absence) + avp->noa_duration = (3 * beacon_int / 2) + + sc->sched.channel_switch_time; + else + avp->noa_duration = + TU_TO_USEC(cur_conf->beacon_interval) / 2 + + sc->sched.channel_switch_time; + + if (test_bit(ATH_OP_SCANNING, &common->op_flags) || + sc->sched.extend_absence) + avp->periodic_noa = false; + else + avp->periodic_noa = true; + + ath_dbg(common, CHAN_CTX, + "noa_duration: %d, noa_start: %d, noa_index: %d, periodic: %d\n", + avp->noa_duration, + avp->noa_start, + avp->noa_index, + avp->periodic_noa); +} + +static void ath_chanctx_set_oneshot_noa(struct ath_softc *sc, + struct ath_vif *avp, + u32 tsf_time, + u32 duration) +{ + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + + avp->noa_index++; + avp->noa_start = tsf_time; + avp->periodic_noa = false; + avp->oneshot_noa = true; + avp->noa_duration = duration + sc->sched.channel_switch_time; + + ath_dbg(common, CHAN_CTX, + "oneshot noa_duration: %d, noa_start: %d, noa_index: %d, periodic: %d\n", + avp->noa_duration, + avp->noa_start, + avp->noa_index, + avp->periodic_noa); +} + void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif, enum ath_chanctx_event ev) { @@ -327,6 +497,14 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif, if (avp->offchannel_duration) avp->offchannel_duration = 0; + if (avp->oneshot_noa) { + avp->noa_duration = 0; + avp->oneshot_noa = false; + + ath_dbg(common, CHAN_CTX, + "Clearing oneshot NoA\n"); + } + if (avp->chanctx != sc->cur_chan) { ath_dbg(common, CHAN_CTX, "Contexts differ, not preparing beacon\n"); @@ -356,6 +534,24 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif, "Move chanctx state from WAIT_FOR_TIMER to WAIT_FOR_BEACON\n"); } + if (sc->sched.mgd_prepare_tx) + sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_BEACON; + + /* + * When a context becomes inactive, for example, + * disassociation of a station context, the NoA + * attribute needs to be removed from subsequent + * beacons. + */ + if (!ctx->active && avp->noa_duration && + sc->sched.state != ATH_CHANCTX_STATE_WAIT_FOR_BEACON) { + avp->noa_duration = 0; + avp->periodic_noa = false; + + ath_dbg(common, CHAN_CTX, + "Clearing NoA schedule\n"); + } + if (sc->sched.state != ATH_CHANCTX_STATE_WAIT_FOR_BEACON) break; @@ -378,45 +574,22 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif, * values and increment the index. */ if (sc->next_chan == &sc->offchannel.chan) { - avp->noa_index++; - avp->offchannel_start = tsf_time; - avp->offchannel_duration = sc->sched.offchannel_duration; - - ath_dbg(common, CHAN_CTX, - "offchannel noa_duration: %d, noa_start: %d, noa_index: %d\n", - avp->offchannel_duration, - avp->offchannel_start, - avp->noa_index); - - /* - * When multiple contexts are active, the NoA - * has to be recalculated and advertised after - * an offchannel operation. - */ - if (ctx->active && avp->noa_duration) - avp->noa_duration = 0; - + ath_chanctx_offchannel_noa(sc, ctx, avp, tsf_time); break; } - /* - * Clear the extend_absence flag if it had been - * set during the previous beacon transmission, - * since we need to revert to the normal NoA - * schedule. - */ - if (ctx->active && sc->sched.extend_absence) { - avp->noa_duration = 0; - sc->sched.extend_absence = false; - } + ath_chanctx_handle_bmiss(sc, ctx, avp); - /* If at least two consecutive beacons were missed on the STA - * chanctx, stay on the STA channel for one extra beacon period, - * to resync the timer properly. + /* + * If a mgd_prepare_tx() has been called by mac80211, + * a one-shot NoA needs to be sent. This can happen + * with one or more active channel contexts - in both + * cases, a new NoA schedule has to be advertised. */ - if (ctx->active && sc->sched.beacon_miss >= 2) { - avp->noa_duration = 0; - sc->sched.extend_absence = true; + if (sc->sched.mgd_prepare_tx) { + ath_chanctx_set_oneshot_noa(sc, avp, tsf_time, + jiffies_to_usecs(HZ / 5)); + break; } /* Prevent wrap-around issues */ @@ -429,31 +602,9 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif, * announcement. */ if (ctx->active && - (!avp->noa_duration || sc->sched.force_noa_update)) { - avp->noa_index++; - avp->noa_start = tsf_time; - - if (sc->sched.extend_absence) - avp->noa_duration = (3 * beacon_int / 2) + - sc->sched.channel_switch_time; - else - avp->noa_duration = - TU_TO_USEC(cur_conf->beacon_interval) / 2 + - sc->sched.channel_switch_time; - - if (test_bit(ATH_OP_SCANNING, &common->op_flags) || - sc->sched.extend_absence) - avp->periodic_noa = false; - else - avp->periodic_noa = true; - - ath_dbg(common, CHAN_CTX, - "noa_duration: %d, noa_start: %d, noa_index: %d, periodic: %d\n", - avp->noa_duration, - avp->noa_start, - avp->noa_index, - avp->periodic_noa); - } + (!avp->noa_duration || sc->sched.force_noa_update)) + ath_chanctx_set_periodic_noa(sc, avp, cur_conf, + tsf_time, beacon_int); if (ctx->active && sc->sched.force_noa_update) sc->sched.force_noa_update = false; @@ -467,6 +618,15 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif, } sc->sched.beacon_pending = false; + + if (sc->sched.mgd_prepare_tx) { + sc->sched.mgd_prepare_tx = false; + complete(&sc->go_beacon); + ath_dbg(common, CHAN_CTX, + "Beacon sent, complete go_beacon\n"); + break; + } + if (sc->sched.state != ATH_CHANCTX_STATE_WAIT_FOR_BEACON) break; @@ -495,10 +655,16 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif, sc->cur_chan == &sc->offchannel.chan) break; - ath_chanctx_adjust_tbtt_delta(sc); sc->sched.beacon_pending = false; sc->sched.beacon_miss = 0; + if (sc->sched.state == ATH_CHANCTX_STATE_FORCE_ACTIVE || + !sc->sched.beacon_adjust || + !sc->cur_chan->tsf_val) + break; + + ath_chanctx_adjust_tbtt_delta(sc); + /* TSF time might have been updated by the incoming beacon, * need update the channel switch timer to reflect the change. */ @@ -507,10 +673,10 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif, ath9k_hw_get_tsf_offset(&sc->cur_chan->tsf_ts, NULL); tsf_time += ath9k_hw_gettsf32(ah); - + sc->sched.beacon_adjust = false; ath_chanctx_setup_timer(sc, tsf_time); break; - case ATH_CHANCTX_EVENT_ASSOC: + case ATH_CHANCTX_EVENT_AUTHORIZED: if (sc->sched.state != ATH_CHANCTX_STATE_FORCE_ACTIVE || avp->chanctx != sc->cur_chan) break; @@ -552,6 +718,7 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif, ath_chanctx_setup_timer(sc, tsf_time); sc->sched.beacon_pending = true; + sc->sched.beacon_adjust = true; break; case ATH_CHANCTX_EVENT_ENABLE_MULTICHANNEL: if (sc->cur_chan == &sc->offchannel.chan || @@ -578,22 +745,6 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif, ieee80211_queue_work(sc->hw, &sc->chanctx_work); break; case ATH_CHANCTX_EVENT_ASSIGN: - /* - * When adding a new channel context, check if a scan - * is in progress and abort it since the addition of - * a new channel context is usually followed by VIF - * assignment, in which case we have to start multi-channel - * operation. - */ - if (test_bit(ATH_OP_SCANNING, &common->op_flags)) { - ath_dbg(common, CHAN_CTX, - "Aborting HW scan to add new context\n"); - - spin_unlock_bh(&sc->chan_lock); - del_timer_sync(&sc->offchannel.timer); - ath_scan_complete(sc, true); - spin_lock_bh(&sc->chan_lock); - } break; case ATH_CHANCTX_EVENT_CHANGE: break; @@ -751,6 +902,11 @@ void ath_offchannel_next(struct ath_softc *sc) sc->offchannel.state = ATH_OFFCHANNEL_ROC_START; ath_chanctx_offchan_switch(sc, sc->offchannel.roc_chan); } else { + spin_lock_bh(&sc->chan_lock); + sc->sched.offchannel_pending = false; + sc->sched.wait_switch = false; + spin_unlock_bh(&sc->chan_lock); + ath_chanctx_switch(sc, ath_chanctx_get_oper_chan(sc, false), NULL); sc->offchannel.state = ATH_OFFCHANNEL_IDLE; @@ -770,8 +926,7 @@ void ath_roc_complete(struct ath_softc *sc, bool abort) sc->offchannel.roc_vif = NULL; sc->offchannel.roc_chan = NULL; - if (!abort) - ieee80211_remain_on_channel_expired(sc->hw); + ieee80211_remain_on_channel_expired(sc->hw); ath_offchannel_next(sc); ath9k_ps_restore(sc); } @@ -808,7 +963,7 @@ static void ath_scan_send_probe(struct ath_softc *sc, struct ieee80211_tx_info *info; int band = sc->offchannel.chan.chandef.chan->band; - skb = ieee80211_probereq_get(sc->hw, vif, + skb = ieee80211_probereq_get(sc->hw, vif->addr, ssid->ssid, ssid->ssid_len, req->ie_len); if (!skb) return; @@ -902,9 +1057,8 @@ static void ath_offchannel_timer(unsigned long data) break; case ATH_OFFCHANNEL_ROC_START: case ATH_OFFCHANNEL_ROC_WAIT: - ctx = ath_chanctx_get_oper_chan(sc, false); sc->offchannel.state = ATH_OFFCHANNEL_ROC_DONE; - ath_chanctx_switch(sc, ctx, NULL); + ath_roc_complete(sc, false); break; default: break; @@ -1034,7 +1188,6 @@ static void ath_offchannel_channel_change(struct ath_softc *sc) ieee80211_ready_on_channel(sc->hw); break; case ATH_OFFCHANNEL_ROC_DONE: - ath_roc_complete(sc, false); break; default: break; @@ -1082,10 +1235,11 @@ void ath_chanctx_set_next(struct ath_softc *sc, bool force) ath9k_chanctx_stop_queues(sc, sc->cur_chan); queues_stopped = true; - __ath9k_flush(sc->hw, ~0, true); + __ath9k_flush(sc->hw, ~0, true, false, false); if (ath_chanctx_send_ps_frame(sc, true)) - __ath9k_flush(sc->hw, BIT(IEEE80211_AC_VO), false); + __ath9k_flush(sc->hw, BIT(IEEE80211_AC_VO), + false, false, false); send_ps = true; spin_lock_bh(&sc->chan_lock); @@ -1177,6 +1331,8 @@ void ath9k_init_channel_context(struct ath_softc *sc) (unsigned long)sc); setup_timer(&sc->sched.timer, ath_chanctx_timer, (unsigned long)sc); + + init_completion(&sc->go_beacon); } void ath9k_deinit_channel_context(struct ath_softc *sc) diff --git a/drivers/net/wireless/ath/ath9k/spectral.c b/drivers/net/wireless/ath/ath9k/common-spectral.c index 8f68426ca653..ec93ddf0863a 100644 --- a/drivers/net/wireless/ath/ath9k/spectral.c +++ b/drivers/net/wireless/ath/ath9k/common-spectral.c @@ -24,23 +24,24 @@ static s8 fix_rssi_inv_only(u8 rssi_val) return (s8) rssi_val; } -static void ath_debug_send_fft_sample(struct ath_softc *sc, +static void ath_debug_send_fft_sample(struct ath_spec_scan_priv *spec_priv, struct fft_sample_tlv *fft_sample_tlv) { int length; - if (!sc->rfs_chan_spec_scan) + if (!spec_priv->rfs_chan_spec_scan) return; length = __be16_to_cpu(fft_sample_tlv->length) + sizeof(*fft_sample_tlv); - relay_write(sc->rfs_chan_spec_scan, fft_sample_tlv, length); + relay_write(spec_priv->rfs_chan_spec_scan, fft_sample_tlv, length); } /* returns 1 if this was a spectral frame, even if not handled. */ -int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr, +int ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, struct ieee80211_hdr *hdr, struct ath_rx_status *rs, u64 tsf) { - struct ath_hw *ah = sc->sc_ah; + struct ath_hw *ah = spec_priv->ah; + struct ath_common *common = ath9k_hw_common(spec_priv->ah); u8 num_bins, *bins, *vdata = (u8 *)hdr; struct fft_sample_ht20 fft_sample_20; struct fft_sample_ht20_40 fft_sample_40; @@ -67,7 +68,7 @@ int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr, if (!(radar_info->pulse_bw_info & SPECTRAL_SCAN_BITMASK)) return 0; - chan_type = cfg80211_get_chandef_type(&sc->hw->conf.chandef); + chan_type = cfg80211_get_chandef_type(&common->hw->conf.chandef); if ((chan_type == NL80211_CHAN_HT40MINUS) || (chan_type == NL80211_CHAN_HT40PLUS)) { fft_len = SPECTRAL_HT20_40_TOTAL_DATA_LEN; @@ -199,10 +200,11 @@ int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr, tlv = (struct fft_sample_tlv *)&fft_sample_20; } - ath_debug_send_fft_sample(sc, tlv); + ath_debug_send_fft_sample(spec_priv, tlv); return 1; } +EXPORT_SYMBOL(ath_cmn_process_fft); /*********************/ /* spectral_scan_ctl */ @@ -211,11 +213,11 @@ int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr, static ssize_t read_file_spec_scan_ctl(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct ath_softc *sc = file->private_data; + struct ath_spec_scan_priv *spec_priv = file->private_data; char *mode = ""; unsigned int len; - switch (sc->spectral_mode) { + switch (spec_priv->spectral_mode) { case SPECTRAL_DISABLED: mode = "disable"; break; @@ -233,12 +235,84 @@ static ssize_t read_file_spec_scan_ctl(struct file *file, char __user *user_buf, return simple_read_from_buffer(user_buf, count, ppos, mode, len); } +void ath9k_cmn_spectral_scan_trigger(struct ath_common *common, + struct ath_spec_scan_priv *spec_priv) +{ + struct ath_hw *ah = spec_priv->ah; + u32 rxfilter; + + if (config_enabled(CONFIG_ATH9K_TX99)) + return; + + if (!ath9k_hw_ops(ah)->spectral_scan_trigger) { + ath_err(common, "spectrum analyzer not implemented on this hardware\n"); + return; + } + + ath_ps_ops(common)->wakeup(common); + rxfilter = ath9k_hw_getrxfilter(ah); + ath9k_hw_setrxfilter(ah, rxfilter | + ATH9K_RX_FILTER_PHYRADAR | + ATH9K_RX_FILTER_PHYERR); + + /* TODO: usually this should not be neccesary, but for some reason + * (or in some mode?) the trigger must be called after the + * configuration, otherwise the register will have its values reset + * (on my ar9220 to value 0x01002310) + */ + ath9k_cmn_spectral_scan_config(common, spec_priv, spec_priv->spectral_mode); + ath9k_hw_ops(ah)->spectral_scan_trigger(ah); + ath_ps_ops(common)->restore(common); +} +EXPORT_SYMBOL(ath9k_cmn_spectral_scan_trigger); + +int ath9k_cmn_spectral_scan_config(struct ath_common *common, + struct ath_spec_scan_priv *spec_priv, + enum spectral_mode spectral_mode) +{ + struct ath_hw *ah = spec_priv->ah; + + if (!ath9k_hw_ops(ah)->spectral_scan_trigger) { + ath_err(common, "spectrum analyzer not implemented on this hardware\n"); + return -1; + } + + switch (spectral_mode) { + case SPECTRAL_DISABLED: + spec_priv->spec_config.enabled = 0; + break; + case SPECTRAL_BACKGROUND: + /* send endless samples. + * TODO: is this really useful for "background"? + */ + spec_priv->spec_config.endless = 1; + spec_priv->spec_config.enabled = 1; + break; + case SPECTRAL_CHANSCAN: + case SPECTRAL_MANUAL: + spec_priv->spec_config.endless = 0; + spec_priv->spec_config.enabled = 1; + break; + default: + return -1; + } + + ath_ps_ops(common)->wakeup(common); + ath9k_hw_ops(ah)->spectral_scan_config(ah, &spec_priv->spec_config); + ath_ps_ops(common)->restore(common); + + spec_priv->spectral_mode = spectral_mode; + + return 0; +} +EXPORT_SYMBOL(ath9k_cmn_spectral_scan_config); + static ssize_t write_file_spec_scan_ctl(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { - struct ath_softc *sc = file->private_data; - struct ath_common *common = ath9k_hw_common(sc->sc_ah); + struct ath_spec_scan_priv *spec_priv = file->private_data; + struct ath_common *common = ath9k_hw_common(spec_priv->ah); char buf[32]; ssize_t len; @@ -252,18 +326,18 @@ static ssize_t write_file_spec_scan_ctl(struct file *file, buf[len] = '\0'; if (strncmp("trigger", buf, 7) == 0) { - ath9k_spectral_scan_trigger(sc->hw); + ath9k_cmn_spectral_scan_trigger(common, spec_priv); } else if (strncmp("background", buf, 10) == 0) { - ath9k_spectral_scan_config(sc->hw, SPECTRAL_BACKGROUND); + ath9k_cmn_spectral_scan_config(common, spec_priv, SPECTRAL_BACKGROUND); ath_dbg(common, CONFIG, "spectral scan: background mode enabled\n"); } else if (strncmp("chanscan", buf, 8) == 0) { - ath9k_spectral_scan_config(sc->hw, SPECTRAL_CHANSCAN); + ath9k_cmn_spectral_scan_config(common, spec_priv, SPECTRAL_CHANSCAN); ath_dbg(common, CONFIG, "spectral scan: channel scan mode enabled\n"); } else if (strncmp("manual", buf, 6) == 0) { - ath9k_spectral_scan_config(sc->hw, SPECTRAL_MANUAL); + ath9k_cmn_spectral_scan_config(common, spec_priv, SPECTRAL_MANUAL); ath_dbg(common, CONFIG, "spectral scan: manual mode enabled\n"); } else if (strncmp("disable", buf, 7) == 0) { - ath9k_spectral_scan_config(sc->hw, SPECTRAL_DISABLED); + ath9k_cmn_spectral_scan_config(common, spec_priv, SPECTRAL_DISABLED); ath_dbg(common, CONFIG, "spectral scan: disabled\n"); } else { return -EINVAL; @@ -288,11 +362,11 @@ static ssize_t read_file_spectral_short_repeat(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct ath_softc *sc = file->private_data; + struct ath_spec_scan_priv *spec_priv = file->private_data; char buf[32]; unsigned int len; - len = sprintf(buf, "%d\n", sc->spec_config.short_repeat); + len = sprintf(buf, "%d\n", spec_priv->spec_config.short_repeat); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -300,7 +374,7 @@ static ssize_t write_file_spectral_short_repeat(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { - struct ath_softc *sc = file->private_data; + struct ath_spec_scan_priv *spec_priv = file->private_data; unsigned long val; char buf[32]; ssize_t len; @@ -316,7 +390,7 @@ static ssize_t write_file_spectral_short_repeat(struct file *file, if (val > 1) return -EINVAL; - sc->spec_config.short_repeat = val; + spec_priv->spec_config.short_repeat = val; return count; } @@ -336,11 +410,11 @@ static ssize_t read_file_spectral_count(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct ath_softc *sc = file->private_data; + struct ath_spec_scan_priv *spec_priv = file->private_data; char buf[32]; unsigned int len; - len = sprintf(buf, "%d\n", sc->spec_config.count); + len = sprintf(buf, "%d\n", spec_priv->spec_config.count); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -348,7 +422,7 @@ static ssize_t write_file_spectral_count(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { - struct ath_softc *sc = file->private_data; + struct ath_spec_scan_priv *spec_priv = file->private_data; unsigned long val; char buf[32]; ssize_t len; @@ -364,7 +438,7 @@ static ssize_t write_file_spectral_count(struct file *file, if (val > 255) return -EINVAL; - sc->spec_config.count = val; + spec_priv->spec_config.count = val; return count; } @@ -384,11 +458,11 @@ static ssize_t read_file_spectral_period(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct ath_softc *sc = file->private_data; + struct ath_spec_scan_priv *spec_priv = file->private_data; char buf[32]; unsigned int len; - len = sprintf(buf, "%d\n", sc->spec_config.period); + len = sprintf(buf, "%d\n", spec_priv->spec_config.period); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -396,7 +470,7 @@ static ssize_t write_file_spectral_period(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { - struct ath_softc *sc = file->private_data; + struct ath_spec_scan_priv *spec_priv = file->private_data; unsigned long val; char buf[32]; ssize_t len; @@ -412,7 +486,7 @@ static ssize_t write_file_spectral_period(struct file *file, if (val > 255) return -EINVAL; - sc->spec_config.period = val; + spec_priv->spec_config.period = val; return count; } @@ -432,11 +506,11 @@ static ssize_t read_file_spectral_fft_period(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct ath_softc *sc = file->private_data; + struct ath_spec_scan_priv *spec_priv = file->private_data; char buf[32]; unsigned int len; - len = sprintf(buf, "%d\n", sc->spec_config.fft_period); + len = sprintf(buf, "%d\n", spec_priv->spec_config.fft_period); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -444,7 +518,7 @@ static ssize_t write_file_spectral_fft_period(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { - struct ath_softc *sc = file->private_data; + struct ath_spec_scan_priv *spec_priv = file->private_data; unsigned long val; char buf[32]; ssize_t len; @@ -460,7 +534,7 @@ static ssize_t write_file_spectral_fft_period(struct file *file, if (val > 15) return -EINVAL; - sc->spec_config.fft_period = val; + spec_priv->spec_config.fft_period = val; return count; } @@ -506,38 +580,41 @@ static struct rchan_callbacks rfs_spec_scan_cb = { /* Debug Init/Deinit */ /*********************/ -void ath9k_spectral_deinit_debug(struct ath_softc *sc) +void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv) { - if (config_enabled(CONFIG_ATH9K_DEBUGFS) && sc->rfs_chan_spec_scan) { - relay_close(sc->rfs_chan_spec_scan); - sc->rfs_chan_spec_scan = NULL; + if (config_enabled(CONFIG_ATH9K_DEBUGFS) && spec_priv->rfs_chan_spec_scan) { + relay_close(spec_priv->rfs_chan_spec_scan); + spec_priv->rfs_chan_spec_scan = NULL; } } +EXPORT_SYMBOL(ath9k_cmn_spectral_deinit_debug); -void ath9k_spectral_init_debug(struct ath_softc *sc) +void ath9k_cmn_spectral_init_debug(struct ath_spec_scan_priv *spec_priv, + struct dentry *debugfs_phy) { - sc->rfs_chan_spec_scan = relay_open("spectral_scan", - sc->debug.debugfs_phy, + spec_priv->rfs_chan_spec_scan = relay_open("spectral_scan", + debugfs_phy, 1024, 256, &rfs_spec_scan_cb, NULL); debugfs_create_file("spectral_scan_ctl", S_IRUSR | S_IWUSR, - sc->debug.debugfs_phy, sc, + debugfs_phy, spec_priv, &fops_spec_scan_ctl); debugfs_create_file("spectral_short_repeat", S_IRUSR | S_IWUSR, - sc->debug.debugfs_phy, sc, + debugfs_phy, spec_priv, &fops_spectral_short_repeat); debugfs_create_file("spectral_count", S_IRUSR | S_IWUSR, - sc->debug.debugfs_phy, sc, + debugfs_phy, spec_priv, &fops_spectral_count); debugfs_create_file("spectral_period", S_IRUSR | S_IWUSR, - sc->debug.debugfs_phy, sc, + debugfs_phy, spec_priv, &fops_spectral_period); debugfs_create_file("spectral_fft_period", S_IRUSR | S_IWUSR, - sc->debug.debugfs_phy, sc, + debugfs_phy, spec_priv, &fops_spectral_fft_period); } +EXPORT_SYMBOL(ath9k_cmn_spectral_init_debug); diff --git a/drivers/net/wireless/ath/ath9k/spectral.h b/drivers/net/wireless/ath/ath9k/common-spectral.h index 7b410c6858b0..82d9dd29652c 100644 --- a/drivers/net/wireless/ath/ath9k/spectral.h +++ b/drivers/net/wireless/ath/ath9k/common-spectral.h @@ -92,6 +92,13 @@ struct ath_ht20_40_fft_packet { struct ath_radar_info radar_info; } __packed; +struct ath_spec_scan_priv { + struct ath_hw *ah; + /* relay(fs) channel for spectral scan */ + struct rchan *rfs_chan_spec_scan; + enum spectral_mode spectral_mode; + struct ath_spec_scan spec_config; +}; #define SPECTRAL_HT20_40_TOTAL_DATA_LEN (sizeof(struct ath_ht20_40_fft_packet)) @@ -123,23 +130,15 @@ static inline u8 spectral_bitmap_weight(u8 *bins) return bins[0] & 0x3f; } -void ath9k_spectral_init_debug(struct ath_softc *sc); -void ath9k_spectral_deinit_debug(struct ath_softc *sc); +void ath9k_cmn_spectral_init_debug(struct ath_spec_scan_priv *spec_priv, struct dentry *debugfs_phy); +void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv); -void ath9k_spectral_scan_trigger(struct ieee80211_hw *hw); -int ath9k_spectral_scan_config(struct ieee80211_hw *hw, +void ath9k_cmn_spectral_scan_trigger(struct ath_common *common, + struct ath_spec_scan_priv *spec_priv); +int ath9k_cmn_spectral_scan_config(struct ath_common *common, + struct ath_spec_scan_priv *spec_priv, enum spectral_mode spectral_mode); - -#ifdef CONFIG_ATH9K_DEBUGFS -int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr, +int ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, struct ieee80211_hdr *hdr, struct ath_rx_status *rs, u64 tsf); -#else -static inline int ath_process_fft(struct ath_softc *sc, - struct ieee80211_hdr *hdr, - struct ath_rx_status *rs, u64 tsf) -{ - return 0; -} -#endif /* CONFIG_ATH9K_DEBUGFS */ #endif /* SPECTRAL_H */ diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index 33b0c7aef2ea..e8c699446470 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c @@ -159,7 +159,7 @@ void ath9k_cmn_rx_skb_postprocess(struct ath_common *common, if (test_bit(keyix, common->keymap)) rxs->flag |= RX_FLAG_DECRYPTED; } - if (ah->sw_mgmt_crypto && + if (ah->sw_mgmt_crypto_rx && (rxs->flag & RX_FLAG_DECRYPTED) && ieee80211_is_mgmt(fc)) /* Use software decrypt for management frames. */ diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index ffc454b18637..2b79a568e803 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h @@ -24,6 +24,7 @@ #include "common-init.h" #include "common-beacon.h" #include "common-debug.h" +#include "common-spectral.h" /* Common header for Atheros 802.11n base driver cores */ diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 5c45e787814e..696e3d5309c6 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -828,13 +828,14 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf, i = 0; ath_for_each_chanctx(sc, ctx) { - if (!ctx->assigned || list_empty(&ctx->vifs)) + if (list_empty(&ctx->vifs)) continue; ath9k_calculate_iter_data(sc, ctx, &iter_data); len += scnprintf(buf + len, sizeof(buf) - len, - "VIF-COUNTS: CTX %i AP: %i STA: %i MESH: %i WDS: %i", - i++, iter_data.naps, iter_data.nstations, + "VIFS: CTX %i(%i) AP: %i STA: %i MESH: %i WDS: %i", + i++, (int)(ctx->assigned), iter_data.naps, + iter_data.nstations, iter_data.nmeshes, iter_data.nwds); len += scnprintf(buf + len, sizeof(buf) - len, " ADHOC: %i TOTAL: %hi BEACON-VIF: %hi\n", @@ -852,36 +853,31 @@ static ssize_t read_file_reset(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct ath_softc *sc = file->private_data; + static const char * const reset_cause[__RESET_TYPE_MAX] = { + [RESET_TYPE_BB_HANG] = "Baseband Hang", + [RESET_TYPE_BB_WATCHDOG] = "Baseband Watchdog", + [RESET_TYPE_FATAL_INT] = "Fatal HW Error", + [RESET_TYPE_TX_ERROR] = "TX HW error", + [RESET_TYPE_TX_GTT] = "Transmit timeout", + [RESET_TYPE_TX_HANG] = "TX Path Hang", + [RESET_TYPE_PLL_HANG] = "PLL RX Hang", + [RESET_TYPE_MAC_HANG] = "MAC Hang", + [RESET_TYPE_BEACON_STUCK] = "Stuck Beacon", + [RESET_TYPE_MCI] = "MCI Reset", + [RESET_TYPE_CALIBRATION] = "Calibration error", + }; char buf[512]; unsigned int len = 0; + int i; - len += scnprintf(buf + len, sizeof(buf) - len, - "%17s: %2d\n", "Baseband Hang", - sc->debug.stats.reset[RESET_TYPE_BB_HANG]); - len += scnprintf(buf + len, sizeof(buf) - len, - "%17s: %2d\n", "Baseband Watchdog", - sc->debug.stats.reset[RESET_TYPE_BB_WATCHDOG]); - len += scnprintf(buf + len, sizeof(buf) - len, - "%17s: %2d\n", "Fatal HW Error", - sc->debug.stats.reset[RESET_TYPE_FATAL_INT]); - len += scnprintf(buf + len, sizeof(buf) - len, - "%17s: %2d\n", "TX HW error", - sc->debug.stats.reset[RESET_TYPE_TX_ERROR]); - len += scnprintf(buf + len, sizeof(buf) - len, - "%17s: %2d\n", "TX Path Hang", - sc->debug.stats.reset[RESET_TYPE_TX_HANG]); - len += scnprintf(buf + len, sizeof(buf) - len, - "%17s: %2d\n", "PLL RX Hang", - sc->debug.stats.reset[RESET_TYPE_PLL_HANG]); - len += scnprintf(buf + len, sizeof(buf) - len, - "%17s: %2d\n", "MAC Hang", - sc->debug.stats.reset[RESET_TYPE_MAC_HANG]); - len += scnprintf(buf + len, sizeof(buf) - len, - "%17s: %2d\n", "Stuck Beacon", - sc->debug.stats.reset[RESET_TYPE_BEACON_STUCK]); - len += scnprintf(buf + len, sizeof(buf) - len, - "%17s: %2d\n", "MCI Reset", - sc->debug.stats.reset[RESET_TYPE_MCI]); + for (i = 0; i < ARRAY_SIZE(reset_cause); i++) { + if (!reset_cause[i]) + continue; + + len += scnprintf(buf + len, sizeof(buf) - len, + "%17s: %2d\n", reset_cause[i], + sc->debug.stats.reset[i]); + } if (len > sizeof(buf)) len = sizeof(buf); @@ -1315,7 +1311,7 @@ void ath9k_get_et_stats(struct ieee80211_hw *hw, void ath9k_deinit_debug(struct ath_softc *sc) { - ath9k_spectral_deinit_debug(sc); + ath9k_cmn_spectral_deinit_debug(&sc->spec_priv); } int ath9k_init_debug(struct ath_hw *ah) @@ -1335,7 +1331,7 @@ int ath9k_init_debug(struct ath_hw *ah) ath9k_dfs_init_debug(sc); ath9k_tx99_init_debug(sc); - ath9k_spectral_init_debug(sc); + ath9k_cmn_spectral_init_debug(&sc->spec_priv, sc->debug.debugfs_phy); debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, sc, &fops_dma); diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 53ae15bd0c9d..bd75b1f716db 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h @@ -49,6 +49,7 @@ enum ath_reset_type { RESET_TYPE_MAC_HANG, RESET_TYPE_BEACON_STUCK, RESET_TYPE_MCI, + RESET_TYPE_CALIBRATION, __RESET_TYPE_MAX }; diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index 3218ca994746..122b846b8ec0 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c @@ -262,7 +262,7 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) { struct ar5416_eeprom_def *eep = &ah->eeprom.def; struct ath_common *common = ath9k_hw_common(ah); - u16 *eepdata, temp, magic, magic2; + u16 *eepdata, temp, magic; u32 sum = 0, el; bool need_swap = false; int i, addr, size; @@ -272,27 +272,16 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) return false; } - if (!ath9k_hw_use_flash(ah)) { - ath_dbg(common, EEPROM, "Read Magic = 0x%04X\n", magic); - - if (magic != AR5416_EEPROM_MAGIC) { - magic2 = swab16(magic); - - if (magic2 == AR5416_EEPROM_MAGIC) { - size = sizeof(struct ar5416_eeprom_def); - need_swap = true; - eepdata = (u16 *) (&ah->eeprom); + if (swab16(magic) == AR5416_EEPROM_MAGIC && + !(ah->ah_flags & AH_NO_EEP_SWAP)) { + size = sizeof(struct ar5416_eeprom_def); + need_swap = true; + eepdata = (u16 *) (&ah->eeprom); - for (addr = 0; addr < size / sizeof(u16); addr++) { - temp = swab16(*eepdata); - *eepdata = temp; - eepdata++; - } - } else { - ath_err(common, - "Invalid EEPROM Magic. Endianness mismatch.\n"); - return -EINVAL; - } + for (addr = 0; addr < size / sizeof(u16); addr++) { + temp = swab16(*eepdata); + *eepdata = temp; + eepdata++; } } diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index b1956bf6e01e..2fef7a480fec 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c @@ -25,7 +25,12 @@ static void ath_led_brightness(struct led_classdev *led_cdev, enum led_brightness brightness) { struct ath_softc *sc = container_of(led_cdev, struct ath_softc, led_cdev); - ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, (brightness == LED_OFF)); + u32 val = (brightness == LED_OFF); + + if (sc->sc_ah->config.led_active_high) + val = !val; + + ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, val); } void ath_deinit_leds(struct ath_softc *sc) @@ -82,7 +87,7 @@ void ath_fill_led_pin(struct ath_softc *sc) ath9k_hw_cfg_output(ah, ah->led_pin, AR_GPIO_OUTPUT_MUX_AS_OUTPUT); /* LED off, active low */ - ath9k_hw_set_gpio(ah, ah->led_pin, 1); + ath9k_hw_set_gpio(ah, ah->led_pin, (ah->config.led_active_high) ? 0 : 1); } #endif diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 09a5d72f3ff5..9dde265d3f84 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -481,6 +481,7 @@ struct ath9k_htc_priv { unsigned long op_flags; struct ath9k_hw_cal_data caldata; + struct ath_spec_scan_priv spec_priv; spinlock_t beacon_lock; struct ath_beacon_config cur_beacon_conf; @@ -625,8 +626,12 @@ int ath9k_htc_resume(struct htc_target *htc_handle); #endif #ifdef CONFIG_ATH9K_HTC_DEBUGFS int ath9k_htc_init_debug(struct ath_hw *ah); +void ath9k_htc_deinit_debug(struct ath9k_htc_priv *priv); #else static inline int ath9k_htc_init_debug(struct ath_hw *ah) { return 0; }; +static inline void ath9k_htc_deinit_debug(struct ath9k_htc_priv *priv) +{ +} #endif /* CONFIG_ATH9K_HTC_DEBUGFS */ #endif /* HTC_H */ diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c index 8b529e4b8ac4..8cef1edcc621 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c @@ -490,6 +490,10 @@ void ath9k_htc_get_et_stats(struct ieee80211_hw *hw, WARN_ON(i != ATH9K_HTC_SSTATS_LEN); } +void ath9k_htc_deinit_debug(struct ath9k_htc_priv *priv) +{ + ath9k_cmn_spectral_deinit_debug(&priv->spec_priv); +} int ath9k_htc_init_debug(struct ath_hw *ah) { @@ -501,6 +505,8 @@ int ath9k_htc_init_debug(struct ath_hw *ah) if (!priv->debug.debugfs_phy) return -ENOMEM; + ath9k_cmn_spectral_init_debug(&priv->spec_priv, priv->debug.debugfs_phy); + debugfs_create_file("tgt_int_stats", S_IRUSR, priv->debug.debugfs_phy, priv, &fops_tgt_int_stats); debugfs_create_file("tgt_tx_stats", S_IRUSR, priv->debug.debugfs_phy, diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 4014c4be6e79..e8fa9448da24 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -53,6 +53,21 @@ static const struct ieee80211_tpt_blink ath9k_htc_tpt_blink[] = { }; #endif +static void ath9k_htc_op_ps_wakeup(struct ath_common *common) +{ + ath9k_htc_ps_wakeup((struct ath9k_htc_priv *) common->priv); +} + +static void ath9k_htc_op_ps_restore(struct ath_common *common) +{ + ath9k_htc_ps_restore((struct ath9k_htc_priv *) common->priv); +} + +static struct ath_ps_ops ath9k_htc_ps_ops = { + .wakeup = ath9k_htc_op_ps_wakeup, + .restore = ath9k_htc_op_ps_restore, +}; + static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv) { int time_left; @@ -87,6 +102,7 @@ static void ath9k_deinit_device(struct ath9k_htc_priv *priv) wiphy_rfkill_stop_polling(hw->wiphy); ath9k_deinit_leds(priv); + ath9k_htc_deinit_debug(priv); ieee80211_unregister_hw(hw); ath9k_rx_cleanup(priv); ath9k_tx_cleanup(priv); @@ -449,6 +465,14 @@ static void ath9k_init_misc(struct ath9k_htc_priv *priv) common->last_rssi = ATH_RSSI_DUMMY_MARKER; priv->ah->opmode = NL80211_IFTYPE_STATION; + + priv->spec_priv.ah = priv->ah; + priv->spec_priv.spec_config.enabled = 0; + priv->spec_priv.spec_config.short_repeat = false; + priv->spec_priv.spec_config.count = 8; + priv->spec_priv.spec_config.endless = false; + priv->spec_priv.spec_config.period = 0x12; + priv->spec_priv.spec_config.fft_period = 0x02; } static int ath9k_init_priv(struct ath9k_htc_priv *priv, @@ -478,6 +502,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, common = ath9k_hw_common(ah); common->ops = &ah->reg_ops; + common->ps_ops = &ath9k_htc_ps_ops; common->bus_ops = &ath9k_usb_bus_ops; common->ah = ah; common->hw = priv->hw; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 994fff1ff519..92d5a6c5a225 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -314,6 +314,10 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, mod_timer(&priv->tx.cleanup_timer, jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL)); + /* perform spectral scan if requested. */ + if (test_bit(ATH_OP_SCANNING, &common->op_flags) && + priv->spec_priv.spectral_mode == SPECTRAL_CHANSCAN) + ath9k_cmn_spectral_scan_trigger(common, &priv->spec_priv); err: ath9k_htc_ps_restore(priv); return ret; @@ -1443,7 +1447,7 @@ static int ath9k_htc_set_key(struct ieee80211_hw *hw, key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; if (key->cipher == WLAN_CIPHER_SUITE_TKIP) key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; - if (priv->ah->sw_mgmt_crypto && + if (priv->ah->sw_mgmt_crypto_tx && key->cipher == WLAN_CIPHER_SUITE_CCMP) key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; ret = 0; @@ -1687,7 +1691,9 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, return ret; } -static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw) +static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + const u8 *mac_addr) { struct ath9k_htc_priv *priv = hw->priv; struct ath_common *common = ath9k_hw_common(priv->ah); @@ -1701,7 +1707,8 @@ static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw) mutex_unlock(&priv->mutex); } -static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw) +static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) { struct ath9k_htc_priv *priv = hw->priv; struct ath_common *common = ath9k_hw_common(priv->ah); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index f0484b1b617e..a0f58e2aa553 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -946,7 +946,7 @@ static inline void convert_htc_flag(struct ath_rx_status *rx_stats, static void rx_status_htc_to_ath(struct ath_rx_status *rx_stats, struct ath_htc_rx_status *rxstatus) { - rx_stats->rs_datalen = rxstatus->rs_datalen; + rx_stats->rs_datalen = be16_to_cpu(rxstatus->rs_datalen); rx_stats->rs_status = rxstatus->rs_status; rx_stats->rs_phyerr = rxstatus->rs_phyerr; rx_stats->rs_rssi = rxstatus->rs_rssi; @@ -1012,6 +1012,20 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, * separately to avoid doing two lookups for a rate for each frame. */ hdr = (struct ieee80211_hdr *)skb->data; + + /* + * Process PHY errors and return so that the packet + * can be dropped. + */ + if (rx_stats.rs_status & ATH9K_RXERR_PHY) { + /* TODO: Not using DFS processing now. */ + if (ath_cmn_process_fft(&priv->spec_priv, hdr, + &rx_stats, rx_status->mactime)) { + /* TODO: Code to collect spectral scan statistics */ + } + goto rx_next; + } + if (!ath9k_cmn_rx_accept(common, hdr, rx_status, &rx_stats, &decrypt_error, priv->rxfilter)) goto rx_next; diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index 8e85efeaeffc..88769b64b20b 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h @@ -41,10 +41,9 @@ static inline void ath9k_hw_set_desc_link(struct ath_hw *ah, void *ds, ath9k_hw_ops(ah)->set_desc_link(ds, link); } -static inline bool ath9k_hw_calibrate(struct ath_hw *ah, - struct ath9k_channel *chan, - u8 rxchainmask, - bool longcal) +static inline int ath9k_hw_calibrate(struct ath_hw *ah, + struct ath9k_channel *chan, + u8 rxchainmask, bool longcal) { return ath9k_hw_ops(ah)->calibrate(ah, chan, rxchainmask, longcal); } diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 2ad605760e21..6d4b273469b1 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -19,6 +19,7 @@ #include <linux/module.h> #include <linux/time.h> #include <linux/bitops.h> +#include <linux/etherdevice.h> #include <asm/unaligned.h> #include "hw.h" @@ -446,8 +447,16 @@ static int ath9k_hw_init_macaddr(struct ath_hw *ah) common->macaddr[2 * i] = eeval >> 8; common->macaddr[2 * i + 1] = eeval & 0xff; } - if (sum == 0 || sum == 0xffff * 3) - return -EADDRNOTAVAIL; + if (!is_valid_ether_addr(common->macaddr)) { + ath_err(common, + "eeprom contains invalid mac address: %pM\n", + common->macaddr); + + random_ether_addr(common->macaddr); + ath_err(common, + "random mac address will be used: %pM\n", + common->macaddr); + } return 0; } @@ -1576,16 +1585,22 @@ static void ath9k_hw_init_mfp(struct ath_hw *ah) * frames when constructing CCMP AAD. */ REG_RMW_FIELD(ah, AR_AES_MUTE_MASK1, AR_AES_MUTE_MASK1_FC_MGMT, 0xc7ff); - ah->sw_mgmt_crypto = false; + if (AR_SREV_9271(ah) || AR_DEVID_7010(ah)) + ah->sw_mgmt_crypto_tx = true; + else + ah->sw_mgmt_crypto_tx = false; + ah->sw_mgmt_crypto_rx = false; } else if (AR_SREV_9160_10_OR_LATER(ah)) { /* Disable hardware crypto for management frames */ REG_CLR_BIT(ah, AR_PCU_MISC_MODE2, AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE); REG_SET_BIT(ah, AR_PCU_MISC_MODE2, AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT); - ah->sw_mgmt_crypto = true; + ah->sw_mgmt_crypto_tx = true; + ah->sw_mgmt_crypto_rx = true; } else { - ah->sw_mgmt_crypto = true; + ah->sw_mgmt_crypto_tx = true; + ah->sw_mgmt_crypto_rx = true; } } @@ -1932,6 +1947,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, REGWRITE_BUFFER_FLUSH(ah); + ath9k_hw_gen_timer_start_tsf2(ah); + ath9k_hw_init_desc(ah); if (ath9k_hw_btcoex_is_enabled(ah)) @@ -1940,8 +1957,10 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, if (ath9k_hw_mci_is_enabled(ah)) ar9003_mci_check_bt(ah); - ath9k_hw_loadnf(ah, chan); - ath9k_hw_start_nfcal(ah, true); + if (AR_SREV_9300_20_OR_LATER(ah)) { + ath9k_hw_loadnf(ah, chan); + ath9k_hw_start_nfcal(ah, true); + } if (AR_SREV_9300_20_OR_LATER(ah)) ar9003_hw_bb_watchdog_config(ah); @@ -2309,7 +2328,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) struct ath9k_hw_capabilities *pCap = &ah->caps; struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); struct ath_common *common = ath9k_hw_common(ah); - unsigned int chip_chainmask; u16 eeval; u8 ant_div_ctl1, tx_chainmask, rx_chainmask; @@ -2329,31 +2347,40 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) } eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE); - if ((eeval & (AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A)) == 0) { - ath_err(common, - "no band has been marked as supported in EEPROM\n"); - return -EINVAL; + + if (eeval & AR5416_OPFLAGS_11A) { + if (ah->disable_5ghz) + ath_warn(common, "disabling 5GHz band\n"); + else + pCap->hw_caps |= ATH9K_HW_CAP_5GHZ; } - if (eeval & AR5416_OPFLAGS_11A) - pCap->hw_caps |= ATH9K_HW_CAP_5GHZ; + if (eeval & AR5416_OPFLAGS_11G) { + if (ah->disable_2ghz) + ath_warn(common, "disabling 2GHz band\n"); + else + pCap->hw_caps |= ATH9K_HW_CAP_2GHZ; + } - if (eeval & AR5416_OPFLAGS_11G) - pCap->hw_caps |= ATH9K_HW_CAP_2GHZ; + if ((pCap->hw_caps & (ATH9K_HW_CAP_2GHZ | ATH9K_HW_CAP_5GHZ)) == 0) { + ath_err(common, "both bands are disabled\n"); + return -EINVAL; + } if (AR_SREV_9485(ah) || AR_SREV_9285(ah) || AR_SREV_9330(ah) || AR_SREV_9565(ah)) - chip_chainmask = 1; - else if (AR_SREV_9462(ah)) - chip_chainmask = 3; + pCap->chip_chainmask = 1; else if (!AR_SREV_9280_20_OR_LATER(ah)) - chip_chainmask = 7; - else if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9340(ah)) - chip_chainmask = 3; + pCap->chip_chainmask = 7; + else if (!AR_SREV_9300_20_OR_LATER(ah) || + AR_SREV_9340(ah) || + AR_SREV_9462(ah) || + AR_SREV_9531(ah)) + pCap->chip_chainmask = 3; else - chip_chainmask = 7; + pCap->chip_chainmask = 7; pCap->tx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_TX_MASK); /* @@ -2371,8 +2398,8 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) /* Use rx_chainmask from EEPROM. */ pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK); - pCap->tx_chainmask = fixup_chainmask(chip_chainmask, pCap->tx_chainmask); - pCap->rx_chainmask = fixup_chainmask(chip_chainmask, pCap->rx_chainmask); + pCap->tx_chainmask = fixup_chainmask(pCap->chip_chainmask, pCap->tx_chainmask); + pCap->rx_chainmask = fixup_chainmask(pCap->chip_chainmask, pCap->rx_chainmask); ah->txchainmask = pCap->tx_chainmask; ah->rxchainmask = pCap->rx_chainmask; @@ -2886,6 +2913,16 @@ u32 ath9k_hw_gettsf32(struct ath_hw *ah) } EXPORT_SYMBOL(ath9k_hw_gettsf32); +void ath9k_hw_gen_timer_start_tsf2(struct ath_hw *ah) +{ + struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; + + if (timer_table->tsf2_enabled) { + REG_SET_BIT(ah, AR_DIRECT_CONNECT, AR_DC_AP_STA_EN); + REG_SET_BIT(ah, AR_RESET_TSF, AR_RESET_TSF2_ONCE); + } +} + struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, void (*trigger)(void *), void (*overflow)(void *), @@ -2896,7 +2933,11 @@ struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, struct ath_gen_timer *timer; if ((timer_index < AR_FIRST_NDP_TIMER) || - (timer_index >= ATH_MAX_GEN_TIMER)) + (timer_index >= ATH_MAX_GEN_TIMER)) + return NULL; + + if ((timer_index > AR_FIRST_NDP_TIMER) && + !AR_SREV_9300_20_OR_LATER(ah)) return NULL; timer = kzalloc(sizeof(struct ath_gen_timer), GFP_KERNEL); @@ -2910,6 +2951,11 @@ struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, timer->overflow = overflow; timer->arg = arg; + if ((timer_index > AR_FIRST_NDP_TIMER) && !timer_table->tsf2_enabled) { + timer_table->tsf2_enabled = true; + ath9k_hw_gen_timer_start_tsf2(ah); + } + return timer; } EXPORT_SYMBOL(ath_gen_timer_alloc); diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 975074fc11bc..4cf9e0ac0743 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -244,13 +244,20 @@ enum ath9k_hw_caps { ATH9K_HW_CAP_2GHZ = BIT(11), ATH9K_HW_CAP_5GHZ = BIT(12), ATH9K_HW_CAP_APM = BIT(13), +#ifdef CONFIG_ATH9K_PCOEM ATH9K_HW_CAP_RTT = BIT(14), ATH9K_HW_CAP_MCI = BIT(15), - ATH9K_HW_CAP_DFS = BIT(16), - ATH9K_HW_WOW_DEVICE_CAPABLE = BIT(17), - ATH9K_HW_CAP_PAPRD = BIT(18), - ATH9K_HW_CAP_FCC_BAND_SWITCH = BIT(19), - ATH9K_HW_CAP_BT_ANT_DIV = BIT(20), + ATH9K_HW_WOW_DEVICE_CAPABLE = BIT(16), + ATH9K_HW_CAP_BT_ANT_DIV = BIT(17), +#else + ATH9K_HW_CAP_RTT = 0, + ATH9K_HW_CAP_MCI = 0, + ATH9K_HW_WOW_DEVICE_CAPABLE = 0, + ATH9K_HW_CAP_BT_ANT_DIV = 0, +#endif + ATH9K_HW_CAP_DFS = BIT(18), + ATH9K_HW_CAP_PAPRD = BIT(19), + ATH9K_HW_CAP_FCC_BAND_SWITCH = BIT(20), }; /* @@ -269,6 +276,7 @@ struct ath9k_hw_capabilities { u16 rts_aggr_limit; u8 tx_chainmask; u8 rx_chainmask; + u8 chip_chainmask; u8 max_txchains; u8 max_rxchains; u8 num_gpio_pins; @@ -322,6 +330,7 @@ struct ath9k_ops_config { bool alt_mingainidx; bool no_pll_pwrsave; bool tx_gain_buffalo; + bool led_active_high; }; enum ath9k_int { @@ -517,6 +526,7 @@ struct ath_gen_timer { struct ath_gen_timer_table { struct ath_gen_timer *timers[ATH_MAX_GEN_TIMER]; u16 timer_mask; + bool tsf2_enabled; }; struct ath_hw_antcomb_conf { @@ -681,10 +691,8 @@ struct ath_hw_ops { bool power_off); void (*rx_enable)(struct ath_hw *ah); void (*set_desc_link)(void *ds, u32 link); - bool (*calibrate)(struct ath_hw *ah, - struct ath9k_channel *chan, - u8 rxchainmask, - bool longcal); + int (*calibrate)(struct ath_hw *ah, struct ath9k_channel *chan, + u8 rxchainmask, bool longcal); bool (*get_isr)(struct ath_hw *ah, enum ath9k_int *masked, u32 *sync_cause_p); void (*set_txdesc)(struct ath_hw *ah, void *ds, @@ -726,6 +734,7 @@ enum ath_cal_list { #define AH_USE_EEPROM 0x1 #define AH_UNPLUGGED 0x2 /* The card has been physically removed. */ #define AH_FASTCC 0x4 +#define AH_NO_EEP_SWAP 0x8 /* Do not swap EEPROM data */ struct ath_hw { struct ath_ops reg_ops; @@ -747,7 +756,8 @@ struct ath_hw { } eeprom; const struct eeprom_ops *eep_ops; - bool sw_mgmt_crypto; + bool sw_mgmt_crypto_tx; + bool sw_mgmt_crypto_rx; bool is_pciexpress; bool aspm_enabled; bool is_monitoring; @@ -924,6 +934,8 @@ struct ath_hw { bool is_clk_25mhz; int (*get_mac_revision)(void); int (*external_reset)(void); + bool disable_2ghz; + bool disable_5ghz; const struct firmware *eeprom_blob; @@ -1027,6 +1039,7 @@ void ath9k_hw_gen_timer_start(struct ath_hw *ah, struct ath_gen_timer *timer, u32 timer_next, u32 timer_period); +void ath9k_hw_gen_timer_start_tsf2(struct ath_hw *ah); void ath9k_hw_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer); void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer); diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 3bd030494986..59d679cebc89 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -88,6 +88,21 @@ static const struct ieee80211_tpt_blink ath9k_tpt_blink[] = { static void ath9k_deinit_softc(struct ath_softc *sc); +static void ath9k_op_ps_wakeup(struct ath_common *common) +{ + ath9k_ps_wakeup((struct ath_softc *) common->priv); +} + +static void ath9k_op_ps_restore(struct ath_common *common) +{ + ath9k_ps_restore((struct ath_softc *) common->priv); +} + +static struct ath_ps_ops ath9k_ps_ops = { + .wakeup = ath9k_op_ps_wakeup, + .restore = ath9k_op_ps_restore, +}; + /* * Read and write, they both share the same lock. We do this to serialize * reads and writes on Atheros 802.11n PCI devices only. This is required @@ -172,17 +187,20 @@ static void ath9k_reg_notifier(struct wiphy *wiphy, ath_reg_notifier_apply(wiphy, request, reg); /* Set tx power */ - if (ah->curchan) { - sc->cur_chan->txpower = 2 * ah->curchan->chan->max_power; - ath9k_ps_wakeup(sc); - ath9k_hw_set_txpowerlimit(ah, sc->cur_chan->txpower, false); - sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit; - /* synchronize DFS detector if regulatory domain changed */ - if (sc->dfs_detector != NULL) - sc->dfs_detector->set_dfs_domain(sc->dfs_detector, - request->dfs_region); - ath9k_ps_restore(sc); - } + if (!ah->curchan) + return; + + sc->cur_chan->txpower = 2 * ah->curchan->chan->max_power; + ath9k_ps_wakeup(sc); + ath9k_hw_set_txpowerlimit(ah, sc->cur_chan->txpower, false); + ath9k_cmn_update_txpow(ah, sc->cur_chan->cur_txpower, + sc->cur_chan->txpower, + &sc->cur_chan->cur_txpower); + /* synchronize DFS detector if regulatory domain changed */ + if (sc->dfs_detector != NULL) + sc->dfs_detector->set_dfs_domain(sc->dfs_detector, + request->dfs_region); + ath9k_ps_restore(sc); } /* @@ -348,12 +366,13 @@ static void ath9k_init_misc(struct ath_softc *sc) if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) sc->ant_comb.count = ATH_ANT_DIV_COMB_INIT_COUNT; - sc->spec_config.enabled = 0; - sc->spec_config.short_repeat = true; - sc->spec_config.count = 8; - sc->spec_config.endless = false; - sc->spec_config.period = 0xFF; - sc->spec_config.fft_period = 0xF; + sc->spec_priv.ah = sc->sc_ah; + sc->spec_priv.spec_config.enabled = 0; + sc->spec_priv.spec_config.short_repeat = true; + sc->spec_priv.spec_config.count = 8; + sc->spec_priv.spec_config.endless = false; + sc->spec_priv.spec_config.period = 0xFF; + sc->spec_priv.spec_config.fft_period = 0xF; } static void ath9k_init_pcoem_platform(struct ath_softc *sc) @@ -362,6 +381,9 @@ static void ath9k_init_pcoem_platform(struct ath_softc *sc) struct ath9k_hw_capabilities *pCap = &ah->caps; struct ath_common *common = ath9k_hw_common(ah); + if (!IS_ENABLED(CONFIG_ATH9K_PCOEM)) + return; + if (common->bus_ops->ath_bus_type != ATH_PCI) return; @@ -419,6 +441,9 @@ static void ath9k_init_pcoem_platform(struct ath_softc *sc) ah->config.no_pll_pwrsave = true; ath_info(common, "Disable PLL PowerSave\n"); } + + if (sc->driver_data & ATH9K_PCI_LED_ACT_HI) + ah->config.led_active_high = true; } static void ath9k_eeprom_request_cb(const struct firmware *eeprom_blob, @@ -528,10 +553,15 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, ah->is_clk_25mhz = pdata->is_clk_25mhz; ah->get_mac_revision = pdata->get_mac_revision; ah->external_reset = pdata->external_reset; + ah->disable_2ghz = pdata->disable_2ghz; + ah->disable_5ghz = pdata->disable_5ghz; + if (!pdata->endian_check) + ah->ah_flags |= AH_NO_EEP_SWAP; } common->ops = &ah->reg_ops; common->bus_ops = bus_ops; + common->ps_ops = &ath9k_ps_ops; common->ah = ah; common->hw = sc->hw; common->priv = sc; diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c index 2343f56e6498..b829263e3d0a 100644 --- a/drivers/net/wireless/ath/ath9k/link.c +++ b/drivers/net/wireless/ath/ath9k/link.c @@ -371,9 +371,15 @@ void ath_ani_calibrate(unsigned long data) /* Perform calibration if necessary */ if (longcal || shortcal) { - common->ani.caldone = - ath9k_hw_calibrate(ah, ah->curchan, - ah->rxchainmask, longcal); + int ret = ath9k_hw_calibrate(ah, ah->curchan, ah->rxchainmask, + longcal); + if (ret < 0) { + common->ani.caldone = 0; + ath9k_queue_reset(sc, RESET_TYPE_CALIBRATION); + return; + } + + common->ani.caldone = ret; } ath_dbg(common, ANI, diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 4f18a6be0c7d..ebbbfc7a193b 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -54,7 +54,8 @@ u8 ath9k_parse_mpdudensity(u8 mpdudensity) } } -static bool ath9k_has_pending_frames(struct ath_softc *sc, struct ath_txq *txq) +static bool ath9k_has_pending_frames(struct ath_softc *sc, struct ath_txq *txq, + bool sw_pending) { bool pending = false; @@ -65,6 +66,9 @@ static bool ath9k_has_pending_frames(struct ath_softc *sc, struct ath_txq *txq) goto out; } + if (!sw_pending) + goto out; + if (txq->mac80211_qnum >= 0) { struct list_head *list; @@ -229,8 +233,9 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start) ath9k_calculate_summary_state(sc, sc->cur_chan); ath_startrecv(sc); - ath9k_cmn_update_txpow(ah, sc->curtxpow, - sc->cur_chan->txpower, &sc->curtxpow); + ath9k_cmn_update_txpow(ah, sc->cur_chan->cur_txpower, + sc->cur_chan->txpower, + &sc->cur_chan->cur_txpower); clear_bit(ATH_OP_HW_RESET, &common->op_flags); if (!sc->cur_chan->offchannel && start) { @@ -270,7 +275,7 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start) return true; } -int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan) +static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan) { struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); @@ -281,6 +286,7 @@ int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan) __ath_cancel_work(sc); tasklet_disable(&sc->intr_tq); + tasklet_disable(&sc->bcon_tasklet); spin_lock_bh(&sc->sc_pcu_lock); if (!sc->cur_chan->offchannel) { @@ -326,6 +332,7 @@ int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan) out: spin_unlock_bh(&sc->sc_pcu_lock); + tasklet_enable(&sc->bcon_tasklet); tasklet_enable(&sc->intr_tq); return r; @@ -539,11 +546,10 @@ irqreturn_t ath_isr(int irq, void *dev) sched = true; /* - * If a FATAL or RXORN interrupt is received, we have to reset the - * chip immediately. + * If a FATAL interrupt is received, we have to reset the chip + * immediately. */ - if ((status & ATH9K_INT_FATAL) || ((status & ATH9K_INT_RXORN) && - !(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA))) + if (status & ATH9K_INT_FATAL) goto chip_reset; if ((ah->config.hw_hang_checks & HW_BB_WATCHDOG) && @@ -598,17 +604,29 @@ chip_reset: #undef SCHED_INTR } -int ath_reset(struct ath_softc *sc) +/* + * This function is called when a HW reset cannot be deferred + * and has to be immediate. + */ +int ath_reset(struct ath_softc *sc, struct ath9k_channel *hchan) { + struct ath_common *common = ath9k_hw_common(sc->sc_ah); int r; + set_bit(ATH_OP_HW_RESET, &common->op_flags); + ath9k_ps_wakeup(sc); - r = ath_reset_internal(sc, NULL); + r = ath_reset_internal(sc, hchan); ath9k_ps_restore(sc); return r; } +/* + * When a HW reset can be deferred, it is added to the + * hw_reset_work workqueue, but we set ATH_OP_HW_RESET before + * queueing. + */ void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type) { struct ath_common *common = ath9k_hw_common(sc->sc_ah); @@ -623,7 +641,9 @@ void ath_reset_work(struct work_struct *work) { struct ath_softc *sc = container_of(work, struct ath_softc, hw_reset_work); - ath_reset(sc); + ath9k_ps_wakeup(sc); + ath_reset_internal(sc, NULL); + ath9k_ps_restore(sc); } /**********************/ @@ -707,7 +727,8 @@ static int ath9k_start(struct ieee80211_hw *hw) if (ah->led_pin >= 0) { ath9k_hw_cfg_output(ah, ah->led_pin, AR_GPIO_OUTPUT_MUX_AS_OUTPUT); - ath9k_hw_set_gpio(ah, ah->led_pin, 0); + ath9k_hw_set_gpio(ah, ah->led_pin, + (ah->config.led_active_high) ? 1 : 0); } /* @@ -849,7 +870,8 @@ static void ath9k_stop(struct ieee80211_hw *hw) spin_lock_bh(&sc->sc_pcu_lock); if (ah->led_pin >= 0) { - ath9k_hw_set_gpio(ah, ah->led_pin, 1); + ath9k_hw_set_gpio(ah, ah->led_pin, + (ah->config.led_active_high) ? 0 : 1); ath9k_hw_cfg_gpio_input(ah, ah->led_pin); } @@ -1036,7 +1058,7 @@ static void ath9k_set_offchannel_state(struct ath_softc *sc) eth_zero_addr(common->curbssid); eth_broadcast_addr(common->bssidmask); - ether_addr_copy(common->macaddr, vif->addr); + memcpy(common->macaddr, vif->addr, ETH_ALEN); common->curaid = 0; ah->opmode = vif->type; ah->imask &= ~ATH9K_INT_SWBA; @@ -1077,7 +1099,7 @@ void ath9k_calculate_summary_state(struct ath_softc *sc, ath9k_calculate_iter_data(sc, ctx, &iter_data); if (iter_data.has_hw_macaddr) - ether_addr_copy(common->macaddr, iter_data.hw_macaddr); + memcpy(common->macaddr, iter_data.hw_macaddr, ETH_ALEN); memcpy(common->bssidmask, iter_data.mask, ETH_ALEN); ath_hw_setbssidmask(common); @@ -1167,7 +1189,8 @@ static void ath9k_assign_hw_queues(struct ieee80211_hw *hw, for (i = 0; i < IEEE80211_NUM_ACS; i++) vif->hw_queue[i] = i; - if (vif->type == NL80211_IFTYPE_AP) + if (vif->type == NL80211_IFTYPE_AP || + vif->type == NL80211_IFTYPE_MESH_POINT) vif->cab_queue = hw->queues - 2; else vif->cab_queue = IEEE80211_INVAL_HW_QUEUE; @@ -1323,78 +1346,6 @@ static void ath9k_disable_ps(struct ath_softc *sc) ath_dbg(common, PS, "PowerSave disabled\n"); } -void ath9k_spectral_scan_trigger(struct ieee80211_hw *hw) -{ - struct ath_softc *sc = hw->priv; - struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); - u32 rxfilter; - - if (config_enabled(CONFIG_ATH9K_TX99)) - return; - - if (!ath9k_hw_ops(ah)->spectral_scan_trigger) { - ath_err(common, "spectrum analyzer not implemented on this hardware\n"); - return; - } - - ath9k_ps_wakeup(sc); - rxfilter = ath9k_hw_getrxfilter(ah); - ath9k_hw_setrxfilter(ah, rxfilter | - ATH9K_RX_FILTER_PHYRADAR | - ATH9K_RX_FILTER_PHYERR); - - /* TODO: usually this should not be neccesary, but for some reason - * (or in some mode?) the trigger must be called after the - * configuration, otherwise the register will have its values reset - * (on my ar9220 to value 0x01002310) - */ - ath9k_spectral_scan_config(hw, sc->spectral_mode); - ath9k_hw_ops(ah)->spectral_scan_trigger(ah); - ath9k_ps_restore(sc); -} - -int ath9k_spectral_scan_config(struct ieee80211_hw *hw, - enum spectral_mode spectral_mode) -{ - struct ath_softc *sc = hw->priv; - struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); - - if (!ath9k_hw_ops(ah)->spectral_scan_trigger) { - ath_err(common, "spectrum analyzer not implemented on this hardware\n"); - return -1; - } - - switch (spectral_mode) { - case SPECTRAL_DISABLED: - sc->spec_config.enabled = 0; - break; - case SPECTRAL_BACKGROUND: - /* send endless samples. - * TODO: is this really useful for "background"? - */ - sc->spec_config.endless = 1; - sc->spec_config.enabled = 1; - break; - case SPECTRAL_CHANSCAN: - case SPECTRAL_MANUAL: - sc->spec_config.endless = 0; - sc->spec_config.enabled = 1; - break; - default: - return -1; - } - - ath9k_ps_wakeup(sc); - ath9k_hw_ops(ah)->spectral_scan_config(ah, &sc->spec_config); - ath9k_ps_restore(sc); - - sc->spectral_mode = spectral_mode; - - return 0; -} - static int ath9k_config(struct ieee80211_hw *hw, u32 changed) { struct ath_softc *sc = hw->priv; @@ -1455,8 +1406,9 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) if (changed & IEEE80211_CONF_CHANGE_POWER) { ath_dbg(common, CONFIG, "Set power: %d\n", conf->power_level); sc->cur_chan->txpower = 2 * conf->power_level; - ath9k_cmn_update_txpow(ah, sc->curtxpow, - sc->cur_chan->txpower, &sc->curtxpow); + ath9k_cmn_update_txpow(ah, sc->cur_chan->cur_txpower, + sc->cur_chan->txpower, + &sc->cur_chan->cur_txpower); } mutex_unlock(&sc->mutex); @@ -1553,6 +1505,40 @@ static int ath9k_sta_remove(struct ieee80211_hw *hw, return 0; } +static int ath9k_sta_state(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + enum ieee80211_sta_state old_state, + enum ieee80211_sta_state new_state) +{ + struct ath_softc *sc = hw->priv; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + int ret = 0; + + if (old_state == IEEE80211_STA_AUTH && + new_state == IEEE80211_STA_ASSOC) { + ret = ath9k_sta_add(hw, vif, sta); + ath_dbg(common, CONFIG, + "Add station: %pM\n", sta->addr); + } else if (old_state == IEEE80211_STA_ASSOC && + new_state == IEEE80211_STA_AUTH) { + ret = ath9k_sta_remove(hw, vif, sta); + ath_dbg(common, CONFIG, + "Remove station: %pM\n", sta->addr); + } + + if (ath9k_is_chanctx_enabled()) { + if (vif->type == NL80211_IFTYPE_STATION) { + if (old_state == IEEE80211_STA_ASSOC && + new_state == IEEE80211_STA_AUTHORIZED) + ath_chanctx_event(sc, vif, + ATH_CHANCTX_EVENT_AUTHORIZED); + } + } + + return ret; +} + static void ath9k_sta_set_tx_filter(struct ath_hw *ah, struct ath_node *an, bool set) @@ -1677,7 +1663,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw, key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; if (key->cipher == WLAN_CIPHER_SUITE_TKIP) key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; - if (sc->sc_ah->sw_mgmt_crypto && + if (sc->sc_ah->sw_mgmt_crypto_tx && key->cipher == WLAN_CIPHER_SUITE_CCMP) key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; ret = 0; @@ -1737,17 +1723,11 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, ath_dbg(common, CONFIG, "BSSID %pM Changed ASSOC %d\n", bss_conf->bssid, bss_conf->assoc); - ether_addr_copy(avp->bssid, bss_conf->bssid); + memcpy(avp->bssid, bss_conf->bssid, ETH_ALEN); avp->aid = bss_conf->aid; avp->assoc = bss_conf->assoc; ath9k_calculate_summary_state(sc, avp->chanctx); - - if (ath9k_is_chanctx_enabled()) { - if (bss_conf->assoc) - ath_chanctx_event(sc, vif, - ATH_CHANCTX_EVENT_ASSOC); - } } if (changed & BSS_CHANGED_IBSS) { @@ -1843,6 +1823,7 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, u16 tid, u16 *ssn, u8 buf_size) { struct ath_softc *sc = hw->priv; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); bool flush = false; int ret = 0; @@ -1854,6 +1835,12 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, case IEEE80211_AMPDU_RX_STOP: break; case IEEE80211_AMPDU_TX_START: + if (ath9k_is_chanctx_enabled()) { + if (test_bit(ATH_OP_SCANNING, &common->op_flags)) { + ret = -EBUSY; + break; + } + } ath9k_ps_wakeup(sc); ret = ath_tx_aggr_start(sc, sta, tid, ssn); if (!ret) @@ -1967,7 +1954,8 @@ static void ath9k_set_coverage_class(struct ieee80211_hw *hw, mutex_unlock(&sc->mutex); } -static bool ath9k_has_tx_pending(struct ath_softc *sc) +static bool ath9k_has_tx_pending(struct ath_softc *sc, + bool sw_pending) { int i, npend = 0; @@ -1975,7 +1963,8 @@ static bool ath9k_has_tx_pending(struct ath_softc *sc) if (!ATH_TXQ_SETUP(sc, i)) continue; - npend = ath9k_has_pending_frames(sc, &sc->tx.txq[i]); + npend = ath9k_has_pending_frames(sc, &sc->tx.txq[i], + sw_pending); if (npend) break; } @@ -1987,18 +1976,38 @@ static void ath9k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u32 queues, bool drop) { struct ath_softc *sc = hw->priv; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + + if (ath9k_is_chanctx_enabled()) { + if (!test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags)) + goto flush; + /* + * If MCC is active, extend the flush timeout + * and wait for the HW/SW queues to become + * empty. This needs to be done outside the + * sc->mutex lock to allow the channel scheduler + * to switch channel contexts. + * + * The vif queues have been stopped in mac80211, + * so there won't be any incoming frames. + */ + __ath9k_flush(hw, queues, drop, true, true); + return; + } +flush: mutex_lock(&sc->mutex); - __ath9k_flush(hw, queues, drop); + __ath9k_flush(hw, queues, drop, true, false); mutex_unlock(&sc->mutex); } -void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop) +void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop, + bool sw_pending, bool timeout_override) { struct ath_softc *sc = hw->priv; struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); - int timeout = HZ / 5; /* 200 ms */ + int timeout; bool drain_txq; cancel_delayed_work_sync(&sc->tx_complete_work); @@ -2013,7 +2022,17 @@ void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop) return; } - if (wait_event_timeout(sc->tx_wait, !ath9k_has_tx_pending(sc), + spin_lock_bh(&sc->chan_lock); + if (timeout_override) + timeout = HZ / 5; + else + timeout = sc->cur_chan->flush_timeout; + spin_unlock_bh(&sc->chan_lock); + + ath_dbg(common, CHAN_CTX, + "Flush timeout: %d\n", jiffies_to_msecs(timeout)); + + if (wait_event_timeout(sc->tx_wait, !ath9k_has_tx_pending(sc, sw_pending), timeout) > 0) drop = false; @@ -2024,7 +2043,7 @@ void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop) spin_unlock_bh(&sc->sc_pcu_lock); if (!drain_txq) - ath_reset(sc); + ath_reset(sc, NULL); ath9k_ps_restore(sc); } @@ -2036,7 +2055,7 @@ static bool ath9k_tx_frames_pending(struct ieee80211_hw *hw) { struct ath_softc *sc = hw->priv; - return ath9k_has_tx_pending(sc); + return ath9k_has_tx_pending(sc, true); } static int ath9k_tx_last_beacon(struct ieee80211_hw *hw) @@ -2167,14 +2186,17 @@ static int ath9k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) return 0; } -static void ath9k_sw_scan_start(struct ieee80211_hw *hw) +static void ath9k_sw_scan_start(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + const u8 *mac_addr) { struct ath_softc *sc = hw->priv; struct ath_common *common = ath9k_hw_common(sc->sc_ah); set_bit(ATH_OP_SCANNING, &common->op_flags); } -static void ath9k_sw_scan_complete(struct ieee80211_hw *hw) +static void ath9k_sw_scan_complete(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) { struct ath_softc *sc = hw->priv; struct ath_common *common = ath9k_hw_common(sc->sc_ah); @@ -2183,6 +2205,28 @@ static void ath9k_sw_scan_complete(struct ieee80211_hw *hw) #ifdef CONFIG_ATH9K_CHANNEL_CONTEXT +static void ath9k_cancel_pending_offchannel(struct ath_softc *sc) +{ + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + + if (sc->offchannel.roc_vif) { + ath_dbg(common, CHAN_CTX, + "%s: Aborting RoC\n", __func__); + + del_timer_sync(&sc->offchannel.timer); + if (sc->offchannel.state >= ATH_OFFCHANNEL_ROC_START) + ath_roc_complete(sc, true); + } + + if (test_bit(ATH_OP_SCANNING, &common->op_flags)) { + ath_dbg(common, CHAN_CTX, + "%s: Aborting HW scan\n", __func__); + + del_timer_sync(&sc->offchannel.timer); + ath_scan_complete(sc, true); + } +} + static int ath9k_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_scan_request *hw_req) { @@ -2313,7 +2357,6 @@ static int ath9k_add_chanctx(struct ieee80211_hw *hw, conf->def.chan->center_freq); ath_chanctx_set_channel(sc, ctx, &conf->def); - ath_chanctx_event(sc, NULL, ATH_CHANCTX_EVENT_ASSIGN); mutex_unlock(&sc->mutex); return 0; @@ -2370,6 +2413,8 @@ static int ath9k_assign_vif_chanctx(struct ieee80211_hw *hw, struct ath_chanctx *ctx = ath_chanctx_get(conf); int i; + ath9k_cancel_pending_offchannel(sc); + mutex_lock(&sc->mutex); ath_dbg(common, CHAN_CTX, @@ -2399,6 +2444,8 @@ static void ath9k_unassign_vif_chanctx(struct ieee80211_hw *hw, struct ath_chanctx *ctx = ath_chanctx_get(conf); int ac; + ath9k_cancel_pending_offchannel(sc); + mutex_lock(&sc->mutex); ath_dbg(common, CHAN_CTX, @@ -2422,7 +2469,11 @@ static void ath9k_mgd_prepare_tx(struct ieee80211_hw *hw, struct ath_softc *sc = hw->priv; struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_vif *avp = (struct ath_vif *) vif->drv_priv; + struct ath_beacon_config *cur_conf; + struct ath_chanctx *go_ctx; + unsigned long timeout; bool changed = false; + u32 beacon_int; if (!test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags)) return; @@ -2433,19 +2484,57 @@ static void ath9k_mgd_prepare_tx(struct ieee80211_hw *hw, mutex_lock(&sc->mutex); spin_lock_bh(&sc->chan_lock); - if (sc->next_chan || (sc->cur_chan != avp->chanctx)) { - sc->next_chan = avp->chanctx; + if (sc->next_chan || (sc->cur_chan != avp->chanctx)) changed = true; + spin_unlock_bh(&sc->chan_lock); + + if (!changed) + goto out; + + ath9k_cancel_pending_offchannel(sc); + + go_ctx = ath_is_go_chanctx_present(sc); + + if (go_ctx) { + /* + * Wait till the GO interface gets a chance + * to send out an NoA. + */ + spin_lock_bh(&sc->chan_lock); + sc->sched.mgd_prepare_tx = true; + cur_conf = &go_ctx->beacon; + beacon_int = TU_TO_USEC(cur_conf->beacon_interval); + spin_unlock_bh(&sc->chan_lock); + + timeout = usecs_to_jiffies(beacon_int * 2); + init_completion(&sc->go_beacon); + + mutex_unlock(&sc->mutex); + + if (wait_for_completion_timeout(&sc->go_beacon, + timeout) == 0) { + ath_dbg(common, CHAN_CTX, + "Failed to send new NoA\n"); + + spin_lock_bh(&sc->chan_lock); + sc->sched.mgd_prepare_tx = false; + spin_unlock_bh(&sc->chan_lock); + } + + mutex_lock(&sc->mutex); } + ath_dbg(common, CHAN_CTX, - "%s: Set chanctx state to FORCE_ACTIVE, changed: %d\n", - __func__, changed); + "%s: Set chanctx state to FORCE_ACTIVE for vif: %pM\n", + __func__, vif->addr); + + spin_lock_bh(&sc->chan_lock); + sc->next_chan = avp->chanctx; sc->sched.state = ATH_CHANCTX_STATE_FORCE_ACTIVE; spin_unlock_bh(&sc->chan_lock); - if (changed) - ath_chanctx_set_next(sc, true); - + ath_chanctx_set_next(sc, true); +out: mutex_unlock(&sc->mutex); } @@ -2468,6 +2557,24 @@ void ath9k_fill_chanctx_ops(void) #endif +static int ath9k_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + int *dbm) +{ + struct ath_softc *sc = hw->priv; + struct ath_vif *avp = (void *)vif->drv_priv; + + mutex_lock(&sc->mutex); + if (avp->chanctx) + *dbm = avp->chanctx->cur_txpower; + else + *dbm = sc->cur_chan->cur_txpower; + mutex_unlock(&sc->mutex); + + *dbm /= 2; + + return 0; +} + struct ieee80211_ops ath9k_ops = { .tx = ath9k_tx, .start = ath9k_start, @@ -2477,8 +2584,7 @@ struct ieee80211_ops ath9k_ops = { .remove_interface = ath9k_remove_interface, .config = ath9k_config, .configure_filter = ath9k_configure_filter, - .sta_add = ath9k_sta_add, - .sta_remove = ath9k_sta_remove, + .sta_state = ath9k_sta_state, .sta_notify = ath9k_sta_notify, .conf_tx = ath9k_conf_tx, .bss_info_changed = ath9k_bss_info_changed, @@ -2515,4 +2621,5 @@ struct ieee80211_ops ath9k_ops = { #endif .sw_scan_start = ath9k_sw_scan_start, .sw_scan_complete = ath9k_sw_scan_complete, + .get_txpower = ath9k_get_txpower, }; diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index c018dea0b2e8..f009b5b57e5e 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -30,6 +30,7 @@ static const struct pci_device_id ath_pci_id_table[] = { { PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */ { PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */ +#ifdef CONFIG_ATH9K_PCOEM { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, 0x002A, PCI_VENDOR_ID_AZWAVE, @@ -82,6 +83,7 @@ static const struct pci_device_id ath_pci_id_table[] = { PCI_VENDOR_ID_AZWAVE, 0x2C37), .driver_data = ATH9K_PCI_BT_ANT_DIV }, +#endif { PCI_VDEVICE(ATHEROS, 0x002B) }, /* PCI-E */ { PCI_VDEVICE(ATHEROS, 0x002C) }, /* PCI-E 802.11n bonded out */ @@ -102,6 +104,7 @@ static const struct pci_device_id ath_pci_id_table[] = { { PCI_VDEVICE(ATHEROS, 0x0030) }, /* PCI-E AR9300 */ +#ifdef CONFIG_ATH9K_PCOEM /* PCI-E CUS198 */ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, 0x0032, @@ -294,10 +297,12 @@ static const struct pci_device_id ath_pci_id_table[] = { PCI_VENDOR_ID_ASUSTEK, 0x850D), .driver_data = ATH9K_PCI_NO_PLL_PWRSAVE }, +#endif { PCI_VDEVICE(ATHEROS, 0x0032) }, /* PCI-E AR9485 */ { PCI_VDEVICE(ATHEROS, 0x0033) }, /* PCI-E AR9580 */ +#ifdef CONFIG_ATH9K_PCOEM /* PCI-E CUS217 */ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, 0x0034, @@ -652,11 +657,14 @@ static const struct pci_device_id ath_pci_id_table[] = { 0x0036, PCI_VENDOR_ID_DELL, 0x020E), - .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, + .driver_data = ATH9K_PCI_AR9565_2ANT | + ATH9K_PCI_BT_ANT_DIV | + ATH9K_PCI_LED_ACT_HI}, /* PCI-E AR9565 (WB335) */ { PCI_VDEVICE(ATHEROS, 0x0036), .driver_data = ATH9K_PCI_BT_ANT_DIV }, +#endif { 0 } }; diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 6914e21816e4..7395afbc5124 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -870,7 +870,7 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc, */ if (rx_stats->rs_status & ATH9K_RXERR_PHY) { ath9k_dfs_process_phyerr(sc, hdr, rx_stats, rx_status->mactime); - if (ath_process_fft(sc, hdr, rx_stats, rx_status->mactime)) + if (ath_cmn_process_fft(&sc->spec_priv, hdr, rx_stats, rx_status->mactime)) RX_STAT_INC(rx_spectral); return -EINVAL; diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 2a938f4feac5..ced36b475acc 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -892,10 +892,21 @@ (AR_SREV_9330((_ah)) && \ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9330_12)) +#ifdef CONFIG_ATH9K_PCOEM +#define AR_SREV_9462(_ah) \ + (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462)) #define AR_SREV_9485(_ah) \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485)) +#define AR_SREV_9565(_ah) \ + (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565)) +#else +#define AR_SREV_9462(_ah) 0 +#define AR_SREV_9485(_ah) 0 +#define AR_SREV_9565(_ah) 0 +#endif + #define AR_SREV_9485_11_OR_LATER(_ah) \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485) && \ + (AR_SREV_9485(_ah) && \ ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9485_11)) #define AR_SREV_9485_OR_LATER(_ah) \ (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9485)) @@ -915,34 +926,30 @@ (AR_SREV_9285_12_OR_LATER(_ah) && \ ((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1)) -#define AR_SREV_9462(_ah) \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462)) #define AR_SREV_9462_20(_ah) \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \ + (AR_SREV_9462(_ah) && \ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9462_20)) #define AR_SREV_9462_21(_ah) \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \ + (AR_SREV_9462(_ah) && \ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9462_21)) #define AR_SREV_9462_20_OR_LATER(_ah) \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \ + (AR_SREV_9462(_ah) && \ ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9462_20)) #define AR_SREV_9462_21_OR_LATER(_ah) \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \ + (AR_SREV_9462(_ah) && \ ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9462_21)) -#define AR_SREV_9565(_ah) \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565)) #define AR_SREV_9565_10(_ah) \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565) && \ + (AR_SREV_9565(_ah) && \ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9565_10)) #define AR_SREV_9565_101(_ah) \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565) && \ + (AR_SREV_9565(_ah) && \ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9565_101)) #define AR_SREV_9565_11(_ah) \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565) && \ + (AR_SREV_9565(_ah) && \ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9565_11)) #define AR_SREV_9565_11_OR_LATER(_ah) \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565) && \ + (AR_SREV_9565(_ah) && \ ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9565_11)) #define AR_SREV_9550(_ah) \ @@ -1598,6 +1605,7 @@ enum { #define AR_RESET_TSF 0x8020 #define AR_RESET_TSF_ONCE 0x01000000 +#define AR_RESET_TSF2_ONCE 0x02000000 #define AR_MAX_CFP_DUR 0x8038 #define AR_CFP_VAL 0x0000FFFF @@ -1959,6 +1967,8 @@ enum { #define AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET 0x80000000 #define AR_MAC_PCU_GEN_TIMER_TSF_SEL 0x83d8 +#define AR_DIRECT_CONNECT 0x83a0 +#define AR_DC_AP_STA_EN 0x00000001 #define AR_AES_MUTE_MASK0 0x805c #define AR_AES_MUTE_MASK0_FC 0x0000FFFF diff --git a/drivers/net/wireless/ath/ath9k/tx99.c b/drivers/net/wireless/ath/ath9k/tx99.c index 40ab65e6882f..ac4781f37e78 100644 --- a/drivers/net/wireless/ath/ath9k/tx99.c +++ b/drivers/net/wireless/ath/ath9k/tx99.c @@ -99,7 +99,7 @@ static struct sk_buff *ath9k_build_tx99_skb(struct ath_softc *sc) static void ath9k_tx99_deinit(struct ath_softc *sc) { - ath_reset(sc); + ath_reset(sc, NULL); ath9k_ps_wakeup(sc); ath9k_tx99_stop(sc); @@ -127,7 +127,7 @@ static int ath9k_tx99_init(struct ath_softc *sc) memset(&txctl, 0, sizeof(txctl)); txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO]; - ath_reset(sc); + ath_reset(sc, NULL); ath9k_ps_wakeup(sc); diff --git a/drivers/net/wireless/ath/carl9170/phy.c b/drivers/net/wireless/ath/carl9170/phy.c index b80b2138ce3c..dca6df13fd5b 100644 --- a/drivers/net/wireless/ath/carl9170/phy.c +++ b/drivers/net/wireless/ath/carl9170/phy.c @@ -994,7 +994,7 @@ static int carl9170_init_rf_bank4_pwr(struct ar9170 *ar, bool band5ghz, refsel0 = 0; refsel1 = 1; } - chansel = byte_rev_table[chansel]; + chansel = bitrev8(chansel); } else { if (freq == 2484) { chansel = 10 + (freq - 2274) / 5; @@ -1002,7 +1002,7 @@ static int carl9170_init_rf_bank4_pwr(struct ar9170 *ar, bool band5ghz, } else chansel = 16 + (freq - 2272) / 5; chansel *= 4; - chansel = byte_rev_table[chansel]; + chansel = bitrev8(chansel); } d1 = chansel; diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index b71d2b33532d..267c35d1f699 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -494,7 +494,9 @@ out: return ret; } -static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw) +static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + const u8 *mac_addr) { struct wcn36xx *wcn = hw->priv; @@ -502,7 +504,8 @@ static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw) wcn36xx_smd_start_scan(wcn); } -static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw) +static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) { struct wcn36xx *wcn = hw->priv; diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index d9f4b30dd343..0fc0b9f8e605 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -792,12 +792,13 @@ static int wil_cfg80211_stop_ap(struct wiphy *wiphy, } static int wil_cfg80211_del_station(struct wiphy *wiphy, - struct net_device *dev, const u8 *mac) + struct net_device *dev, + struct station_del_parameters *params) { struct wil6210_priv *wil = wiphy_to_wil(wiphy); mutex_lock(&wil->mutex); - wil6210_disconnect(wil, mac); + wil6210_disconnect(wil, params->mac, false); mutex_unlock(&wil->mutex); return 0; diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 6500caf8d609..6212983fede2 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -38,6 +38,35 @@ static unsigned int itr_trsh = WIL6210_ITR_TRSH_DEFAULT; module_param(itr_trsh, uint, S_IRUGO); MODULE_PARM_DESC(itr_trsh, " Interrupt moderation threshold, usecs."); +/* We allow allocation of more than 1 page buffers to support large packets. + * It is suboptimal behavior performance wise in case MTU above page size. + */ +unsigned int mtu_max = TXRX_BUF_LEN_DEFAULT - ETH_HLEN; +static int mtu_max_set(const char *val, const struct kernel_param *kp) +{ + int ret; + + /* sets mtu_max directly. no need to restore it in case of + * illegal value since we assume this will fail insmod + */ + ret = param_set_uint(val, kp); + if (ret) + return ret; + + if (mtu_max < 68 || mtu_max > IEEE80211_MAX_DATA_LEN_DMG) + ret = -EINVAL; + + return ret; +} + +static struct kernel_param_ops mtu_max_ops = { + .set = mtu_max_set, + .get = param_get_uint, +}; + +module_param_cb(mtu_max, &mtu_max_ops, &mtu_max, S_IRUGO); +MODULE_PARM_DESC(mtu_max, " Max MTU value."); + #define RST_DELAY (20) /* msec, for loop in @wil_target_reset */ #define RST_COUNT (1 + 1000/RST_DELAY) /* round up to be above 1 sec total */ @@ -74,7 +103,8 @@ void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src, __raw_writel(*s++, d++); } -static void wil_disconnect_cid(struct wil6210_priv *wil, int cid) +static void wil_disconnect_cid(struct wil6210_priv *wil, int cid, + bool from_event) { uint i; struct net_device *ndev = wil_to_ndev(wil); @@ -86,7 +116,10 @@ static void wil_disconnect_cid(struct wil6210_priv *wil, int cid) sta->data_port_open = false; if (sta->status != wil_sta_unused) { - wmi_disconnect_sta(wil, sta->addr, WLAN_REASON_DEAUTH_LEAVING); + if (!from_event) + wmi_disconnect_sta(wil, sta->addr, + WLAN_REASON_DEAUTH_LEAVING); + switch (wdev->iftype) { case NL80211_IFTYPE_AP: case NL80211_IFTYPE_P2P_GO: @@ -118,7 +151,8 @@ static void wil_disconnect_cid(struct wil6210_priv *wil, int cid) memset(&sta->stats, 0, sizeof(sta->stats)); } -static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid) +static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, + bool from_event) { int cid = -ENOENT; struct net_device *ndev = wil_to_ndev(wil); @@ -133,10 +167,10 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid) } if (cid >= 0) /* disconnect 1 peer */ - wil_disconnect_cid(wil, cid); + wil_disconnect_cid(wil, cid, from_event); else /* disconnect all */ for (cid = 0; cid < WIL6210_MAX_CID; cid++) - wil_disconnect_cid(wil, cid); + wil_disconnect_cid(wil, cid, from_event); /* link state */ switch (wdev->iftype) { @@ -166,7 +200,7 @@ static void wil_disconnect_worker(struct work_struct *work) struct wil6210_priv, disconnect_worker); mutex_lock(&wil->mutex); - _wil6210_disconnect(wil, NULL); + _wil6210_disconnect(wil, NULL, false); mutex_unlock(&wil->mutex); } @@ -223,6 +257,11 @@ static void wil_fw_error_worker(struct work_struct *work) wil_dbg_misc(wil, "fw error worker\n"); + if (!netif_running(wil_to_ndev(wil))) { + wil_info(wil, "No recovery - interface is down\n"); + return; + } + /* increment @recovery_count if less then WIL6210_FW_RECOVERY_TO * passed since last recovery attempt */ @@ -257,9 +296,12 @@ static void wil_fw_error_worker(struct work_struct *work) break; case NL80211_IFTYPE_AP: case NL80211_IFTYPE_P2P_GO: + wil_info(wil, "No recovery for AP-like interface\n"); /* recovery in these modes is done by upper layers */ break; default: + wil_err(wil, "No recovery - unknown interface type %d\n", + wdev->iftype); break; } mutex_unlock(&wil->mutex); @@ -346,12 +388,22 @@ int wil_priv_init(struct wil6210_priv *wil) return 0; } -void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid) +/** + * wil6210_disconnect - disconnect one connection + * @wil: driver context + * @bssid: peer to disconnect, NULL to disconnect all + * @from_event: whether is invoked from FW event handler + * + * Disconnect and release associated resources. If invoked not from the + * FW event handler, issue WMI command(s) to trigger MAC disconnect. + */ +void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, + bool from_event) { wil_dbg_misc(wil, "%s()\n", __func__); del_timer_sync(&wil->connect_timer); - _wil6210_disconnect(wil, bssid); + _wil6210_disconnect(wil, bssid, from_event); } void wil_priv_deinit(struct wil6210_priv *wil) @@ -363,7 +415,7 @@ void wil_priv_deinit(struct wil6210_priv *wil) cancel_work_sync(&wil->disconnect_worker); cancel_work_sync(&wil->fw_error_worker); mutex_lock(&wil->mutex); - wil6210_disconnect(wil, NULL); + wil6210_disconnect(wil, NULL, false); mutex_unlock(&wil->mutex); wmi_event_flush(wil); destroy_workqueue(wil->wmi_wq_conn); @@ -395,7 +447,7 @@ static inline void wil_release_cpu(struct wil6210_priv *wil) static int wil_target_reset(struct wil6210_priv *wil) { int delay = 0; - u32 hw_state; + u32 x; u32 rev_id; bool is_sparrow = (wil->board->board == WIL_BOARD_SPARROW); @@ -410,9 +462,22 @@ static int wil_target_reset(struct wil6210_priv *wil) S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT_CAR_PERST_RST); wil_halt_cpu(wil); - C(RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_CAR_AHB_SW_SEL); /* 40 MHz */ if (is_sparrow) { + S(RGF_CAF_OSC_CONTROL, BIT_CAF_OSC_XTAL_EN); + /* XTAL stabilization should take about 3ms */ + usleep_range(5000, 7000); + x = R(RGF_CAF_PLL_LOCK_STATUS); + if (!(x & BIT_CAF_OSC_DIG_XTAL_STABLE)) { + wil_err(wil, "Xtal stabilization timeout\n" + "RGF_CAF_PLL_LOCK_STATUS = 0x%08x\n", x); + return -ETIME; + } + /* switch 10k to XTAL*/ + C(RGF_USER_SPARROW_M_4, BIT_SPARROW_M_4_SEL_SLEEP_OR_REF); + /* 40 MHz */ + C(RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_CAR_AHB_SW_SEL); + W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0, 0x3ff81f); W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_1, 0xf); } @@ -453,13 +518,13 @@ static int wil_target_reset(struct wil6210_priv *wil) /* wait until device ready. typical time is 200..250 msec */ do { msleep(RST_DELAY); - hw_state = R(RGF_USER_HW_MACHINE_STATE); + x = R(RGF_USER_HW_MACHINE_STATE); if (delay++ > RST_COUNT) { wil_err(wil, "Reset not completed, hw_state 0x%08x\n", - hw_state); + x); return -ETIME; } - } while (hw_state != HW_MACHINE_BOOT_DONE); + } while (x != HW_MACHINE_BOOT_DONE); /* TODO: Erez check rev_id != 1 */ if (!is_sparrow && (rev_id != 1)) @@ -535,7 +600,7 @@ int wil_reset(struct wil6210_priv *wil) WARN_ON(test_bit(wil_status_napi_en, &wil->status)); cancel_work_sync(&wil->disconnect_worker); - wil6210_disconnect(wil, NULL); + wil6210_disconnect(wil, NULL, false); wil->status = 0; /* prevent NAPI from being scheduled */ diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c index 239965106c05..e81703ca7701 100644 --- a/drivers/net/wireless/ath/wil6210/netdev.c +++ b/drivers/net/wireless/ath/wil6210/netdev.c @@ -41,7 +41,7 @@ static int wil_change_mtu(struct net_device *ndev, int new_mtu) { struct wil6210_priv *wil = ndev_to_wil(ndev); - if (new_mtu < 68 || new_mtu > (TX_BUF_LEN - ETH_HLEN)) { + if (new_mtu < 68 || new_mtu > mtu_max) { wil_err(wil, "invalid MTU %d\n", new_mtu); return -EINVAL; } diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 2936ef0c18cb..c680906bc0dc 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -206,7 +206,7 @@ static int wil_vring_alloc_skb(struct wil6210_priv *wil, struct vring *vring, u32 i, int headroom) { struct device *dev = wil_to_dev(wil); - unsigned int sz = RX_BUF_LEN; + unsigned int sz = mtu_max + ETH_HLEN; struct vring_rx_desc dd, *d = ⅆ volatile struct vring_rx_desc *_d = &vring->va[i].rx; dma_addr_t pa; @@ -385,7 +385,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, struct vring_rx_desc *d; struct sk_buff *skb; dma_addr_t pa; - unsigned int sz = RX_BUF_LEN; + unsigned int sz = mtu_max + ETH_HLEN; u16 dmalen; u8 ftype; u8 ds_bits; @@ -646,7 +646,8 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, .action = cpu_to_le32(WMI_VRING_CMD_ADD), .vring_cfg = { .tx_sw_ring = { - .max_mpdu_size = cpu_to_le16(TX_BUF_LEN), + .max_mpdu_size = + cpu_to_le16(mtu_max + ETH_HLEN), .ring_size = cpu_to_le16(size), }, .ringid = id, diff --git a/drivers/net/wireless/ath/wil6210/txrx.h b/drivers/net/wireless/ath/wil6210/txrx.h index de046716d2b7..630aeb5fa7f4 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.h +++ b/drivers/net/wireless/ath/wil6210/txrx.h @@ -21,8 +21,8 @@ #define BUF_HW_OWNED (0) /* size of max. Tx/Rx buffers, as supported by FW */ -#define RX_BUF_LEN (2242) -#define TX_BUF_LEN (2242) +#define TXRX_BUF_LEN_DEFAULT (2242) + /* how many bytes to reserve for rtap header? */ #define WIL6210_RTAP_SIZE (128) diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index ce6488e42091..95d3a062d35c 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -24,6 +24,7 @@ #include "wil_platform.h" extern bool no_fw_recovery; +extern unsigned int mtu_max; #define WIL_NAME "wil6210" #define WIL_FW_NAME "wil6210.fw" @@ -117,6 +118,8 @@ struct RGF_ICR { #define BIT_USER_USER_ICR_SW_INT_2 BIT(18) #define RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0 (0x880c18) #define RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_1 (0x880c2c) +#define RGF_USER_SPARROW_M_4 (0x880c50) /* Sparrow */ + #define BIT_SPARROW_M_4_SEL_SLEEP_OR_REF BIT(2) #define RGF_DMA_EP_TX_ICR (0x881bb4) /* struct RGF_ICR */ #define BIT_DMA_EP_TX_ICR_TX_DONE BIT(0) @@ -152,6 +155,10 @@ struct RGF_ICR { #define RGF_MAC_MTRL_COUNTER_0 (0x886aa8) #define RGF_CAF_ICR (0x88946c) /* struct RGF_ICR */ +#define RGF_CAF_OSC_CONTROL (0x88afa4) + #define BIT_CAF_OSC_XTAL_EN BIT(0) +#define RGF_CAF_PLL_LOCK_STATUS (0x88afec) + #define BIT_CAF_OSC_DIG_XTAL_STABLE BIT(0) /* popular locations */ #define HOST_MBOX HOSTADDR(RGF_USER_USER_SCRATCH_PAD) @@ -463,8 +470,11 @@ struct wil6210_priv { #define ndev_to_wil(n) (wdev_to_wil(n->ieee80211_ptr)) #define wil_to_pcie_dev(i) (&i->pdev->dev) +__printf(2, 3) void wil_dbg_trace(struct wil6210_priv *wil, const char *fmt, ...); +__printf(2, 3) void wil_err(struct wil6210_priv *wil, const char *fmt, ...); +__printf(2, 3) void wil_info(struct wil6210_priv *wil, const char *fmt, ...); #define wil_dbg(wil, fmt, arg...) do { \ netdev_dbg(wil_to_ndev(wil), fmt, ##arg); \ @@ -575,7 +585,8 @@ void wil_wdev_free(struct wil6210_priv *wil); int wmi_set_mac_address(struct wil6210_priv *wil, void *addr); int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan); int wmi_pcp_stop(struct wil6210_priv *wil); -void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid); +void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, + bool from_event); int wil_rx_init(struct wil6210_priv *wil); void wil_rx_fini(struct wil6210_priv *wil); diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 4311df982c60..bb1e066f756a 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -486,7 +486,7 @@ static void wmi_evt_disconnect(struct wil6210_priv *wil, int id, wil->sinfo_gen++; mutex_lock(&wil->mutex); - wil6210_disconnect(wil, evt->bssid); + wil6210_disconnect(wil, evt->bssid, true); mutex_unlock(&wil->mutex); } @@ -1025,7 +1025,7 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring) struct wmi_cfg_rx_chain_cmd cmd = { .action = WMI_RX_CHAIN_ADD, .rx_sw_ring = { - .max_mpdu_size = cpu_to_le16(RX_BUF_LEN), + .max_mpdu_size = cpu_to_le16(mtu_max + ETH_HLEN), .ring_mem_base = cpu_to_le64(vring->pa), .ring_size = cpu_to_le16(vring->size), }, diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 5d4173ee55bc..47731cb0d815 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -5110,7 +5110,9 @@ static void b43_op_sta_notify(struct ieee80211_hw *hw, B43_WARN_ON(!vif || wl->vif != vif); } -static void b43_op_sw_scan_start_notifier(struct ieee80211_hw *hw) +static void b43_op_sw_scan_start_notifier(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + const u8 *mac_addr) { struct b43_wl *wl = hw_to_b43_wl(hw); struct b43_wldev *dev; @@ -5124,7 +5126,8 @@ static void b43_op_sw_scan_start_notifier(struct ieee80211_hw *hw) mutex_unlock(&wl->mutex); } -static void b43_op_sw_scan_complete_notifier(struct ieee80211_hw *hw) +static void b43_op_sw_scan_complete_notifier(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) { struct b43_wl *wl = hw_to_b43_wl(hw); struct b43_wldev *dev; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/brcm80211/brcmfmac/Makefile index 90a977fe9a64..dc4c75083085 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/Makefile +++ b/drivers/net/wireless/brcm80211/brcmfmac/Makefile @@ -23,15 +23,15 @@ ccflags-y += -D__CHECK_ENDIAN__ obj-$(CONFIG_BRCMFMAC) += brcmfmac.o brcmfmac-objs += \ - wl_cfg80211.o \ + cfg80211.o \ chip.o \ fwil.o \ fweh.o \ fwsignal.o \ p2p.o \ proto.o \ - dhd_common.o \ - dhd_linux.o \ + common.o \ + core.o \ firmware.o \ feature.o \ btcoex.o \ @@ -43,14 +43,14 @@ brcmfmac-$(CONFIG_BRCMFMAC_PROTO_MSGBUF) += \ flowring.o \ msgbuf.o brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \ - dhd_sdio.o \ + sdio.o \ bcmsdh.o brcmfmac-$(CONFIG_BRCMFMAC_USB) += \ usb.o brcmfmac-$(CONFIG_BRCMFMAC_PCIE) += \ pcie.o brcmfmac-$(CONFIG_BRCMDBG) += \ - dhd_dbg.o + debug.o brcmfmac-$(CONFIG_BRCM_TRACING) += \ tracepoint.o brcmfmac-$(CONFIG_OF) += \ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c index a159ff3427de..8e0e91c4a0b1 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c @@ -25,10 +25,10 @@ #include <brcmu_utils.h> #include <brcmu_wifi.h> -#include "dhd.h" -#include "dhd_bus.h" +#include "core.h" +#include "bus.h" #include "fwsignal.h" -#include "dhd_dbg.h" +#include "debug.h" #include "tracepoint.h" #include "proto.h" #include "bcdc.h" diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index 8dbd5dbb78fd..f754ffcd0308 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c @@ -41,9 +41,9 @@ #include <chipcommon.h> #include <soc.h> #include "chip.h" -#include "dhd_bus.h" -#include "dhd_dbg.h" -#include "sdio_host.h" +#include "bus.h" +#include "debug.h" +#include "sdio.h" #include "of.h" #define SDIOH_API_ACCESS_RETRY_LIMIT 2 @@ -1064,6 +1064,16 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, if (!sdiodev->pdata) brcmf_of_probe(sdiodev); +#ifdef CONFIG_PM_SLEEP + /* wowl can be supported when KEEP_POWER is true and (WAKE_SDIO_IRQ + * is true or when platform data OOB irq is true). + */ + if ((sdio_get_host_pm_caps(sdiodev->func[1]) & MMC_PM_KEEP_POWER) && + ((sdio_get_host_pm_caps(sdiodev->func[1]) & MMC_PM_WAKE_SDIO_IRQ) || + (sdiodev->pdata->oob_irq_supported))) + bus_if->wowl_supported = true; +#endif + atomic_set(&sdiodev->suspend, false); init_waitqueue_head(&sdiodev->request_word_wait); init_waitqueue_head(&sdiodev->request_buffer_wait); @@ -1116,34 +1126,39 @@ static void brcmf_ops_sdio_remove(struct sdio_func *func) brcmf_dbg(SDIO, "Exit\n"); } +void brcmf_sdio_wowl_config(struct device *dev, bool enabled) +{ + struct brcmf_bus *bus_if = dev_get_drvdata(dev); + struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; + + brcmf_dbg(SDIO, "Configuring WOWL, enabled=%d\n", enabled); + sdiodev->wowl_enabled = enabled; +} + #ifdef CONFIG_PM_SLEEP static int brcmf_ops_sdio_suspend(struct device *dev) { - mmc_pm_flag_t sdio_flags; struct brcmf_bus *bus_if = dev_get_drvdata(dev); struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; - int ret = 0; + mmc_pm_flag_t sdio_flags; brcmf_dbg(SDIO, "Enter\n"); - sdio_flags = sdio_get_host_pm_caps(sdiodev->func[1]); - if (!(sdio_flags & MMC_PM_KEEP_POWER)) { - brcmf_err("Host can't keep power while suspended\n"); - return -EINVAL; - } - atomic_set(&sdiodev->suspend, true); - ret = sdio_set_host_pm_flags(sdiodev->func[1], MMC_PM_KEEP_POWER); - if (ret) { - brcmf_err("Failed to set pm_flags\n"); - atomic_set(&sdiodev->suspend, false); - return ret; + if (sdiodev->wowl_enabled) { + sdio_flags = MMC_PM_KEEP_POWER; + if (sdiodev->pdata->oob_irq_supported) + enable_irq_wake(sdiodev->pdata->oob_irq_nr); + else + sdio_flags = MMC_PM_WAKE_SDIO_IRQ; + if (sdio_set_host_pm_flags(sdiodev->func[1], sdio_flags)) + brcmf_err("Failed to set pm_flags %x\n", sdio_flags); } brcmf_sdio_wd_timer(sdiodev->bus, 0); - return ret; + return 0; } static int brcmf_ops_sdio_resume(struct device *dev) @@ -1152,6 +1167,8 @@ static int brcmf_ops_sdio_resume(struct device *dev) struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; brcmf_dbg(SDIO, "Enter\n"); + if (sdiodev->pdata->oob_irq_supported) + disable_irq_wake(sdiodev->pdata->oob_irq_nr); brcmf_sdio_wd_timer(sdiodev->bus, BRCMF_WD_POLL_MS); atomic_set(&sdiodev->suspend, false); return 0; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c b/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c index a29ac4977b3a..0445163991b7 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c @@ -20,13 +20,13 @@ #include <brcmu_wifi.h> #include <brcmu_utils.h> #include <defs.h> -#include <dhd.h> -#include <dhd_dbg.h> +#include "core.h" +#include "debug.h" #include "fwil.h" #include "fwil_types.h" #include "btcoex.h" #include "p2p.h" -#include "wl_cfg80211.h" +#include "cfg80211.h" /* T1 start SCO/eSCO priority suppression */ #define BRCMF_BTCOEX_OPPR_WIN_TIME 2000 diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/bus.h index 80e73a1262be..ef344e47218a 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/bus.h @@ -14,10 +14,10 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#ifndef _BRCMF_BUS_H_ -#define _BRCMF_BUS_H_ +#ifndef BRCMFMAC_BUS_H +#define BRCMFMAC_BUS_H -#include "dhd_dbg.h" +#include "debug.h" /* IDs of the 6 default common rings of msgbuf protocol */ #define BRCMF_H2D_MSGRING_CONTROL_SUBMIT 0 @@ -227,8 +227,7 @@ void brcmf_txflowblock(struct device *dev, bool state); void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success); int brcmf_bus_start(struct device *dev); -s32 brcmf_iovar_data_set(struct device *dev, char *name, void *data, - u32 len); +s32 brcmf_iovar_data_set(struct device *dev, char *name, void *data, u32 len); void brcmf_bus_add_txhdrlen(struct device *dev, uint len); #ifdef CONFIG_BRCMFMAC_SDIO @@ -241,4 +240,4 @@ void brcmf_usb_exit(void); void brcmf_usb_register(void); #endif -#endif /* _BRCMF_BUS_H_ */ +#endif /* BRCMFMAC_BUS_H */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c index 39b45c038a93..f8a9dfa657ba 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c @@ -26,18 +26,18 @@ #include <brcmu_utils.h> #include <defs.h> #include <brcmu_wifi.h> -#include "dhd.h" -#include "dhd_dbg.h" +#include "core.h" +#include "debug.h" #include "tracepoint.h" #include "fwil_types.h" #include "p2p.h" #include "btcoex.h" -#include "wl_cfg80211.h" +#include "cfg80211.h" #include "feature.h" #include "fwil.h" #include "proto.h" #include "vendor.h" -#include "dhd_bus.h" +#include "bus.h" #define BRCMF_SCAN_IE_LEN_MAX 2048 #define BRCMF_PNO_VERSION 2 @@ -2785,6 +2785,44 @@ static __always_inline void brcmf_delay(u32 ms) } } +static s32 brcmf_config_wowl_pattern(struct brcmf_if *ifp, u8 cmd[4], + u8 *pattern, u32 patternsize, u8 *mask, + u32 packet_offset) +{ + struct brcmf_fil_wowl_pattern_le *filter; + u32 masksize; + u32 patternoffset; + u8 *buf; + u32 bufsize; + s32 ret; + + masksize = (patternsize + 7) / 8; + patternoffset = sizeof(*filter) - sizeof(filter->cmd) + masksize; + + bufsize = sizeof(*filter) + patternsize + masksize; + buf = kzalloc(bufsize, GFP_KERNEL); + if (!buf) + return -ENOMEM; + filter = (struct brcmf_fil_wowl_pattern_le *)buf; + + memcpy(filter->cmd, cmd, 4); + filter->masksize = cpu_to_le32(masksize); + filter->offset = cpu_to_le32(packet_offset); + filter->patternoffset = cpu_to_le32(patternoffset); + filter->patternsize = cpu_to_le32(patternsize); + filter->type = cpu_to_le32(BRCMF_WOWL_PATTERN_TYPE_BITMAP); + + if ((mask) && (masksize)) + memcpy(buf + sizeof(*filter), mask, masksize); + if ((pattern) && (patternsize)) + memcpy(buf + sizeof(*filter) + masksize, pattern, patternsize); + + ret = brcmf_fil_iovar_data_set(ifp, "wowl_pattern", buf, bufsize); + + kfree(buf); + return ret; +} + static s32 brcmf_cfg80211_resume(struct wiphy *wiphy) { struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); @@ -2794,10 +2832,11 @@ static s32 brcmf_cfg80211_resume(struct wiphy *wiphy) brcmf_dbg(TRACE, "Enter\n"); if (cfg->wowl_enabled) { + brcmf_configure_arp_offload(ifp, true); brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, cfg->pre_wowl_pmmode); - brcmf_fil_iovar_data_set(ifp, "wowl_pattern", "clr", 4); brcmf_fil_iovar_int_set(ifp, "wowl_clear", 0); + brcmf_config_wowl_pattern(ifp, "clr", NULL, 0, NULL, 0); cfg->wowl_enabled = false; } return 0; @@ -2808,21 +2847,29 @@ static void brcmf_configure_wowl(struct brcmf_cfg80211_info *cfg, struct cfg80211_wowlan *wowl) { u32 wowl_config; + u32 i; brcmf_dbg(TRACE, "Suspend, wowl config.\n"); + brcmf_configure_arp_offload(ifp, false); brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_PM, &cfg->pre_wowl_pmmode); brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, PM_MAX); wowl_config = 0; if (wowl->disconnect) - wowl_config |= WL_WOWL_DIS | WL_WOWL_BCN | WL_WOWL_RETR; - /* Note: if "wowl" target and not "wowlpf" then wowl_bcn_loss - * should be configured. This paramater is not supported by - * wowlpf. - */ + wowl_config = BRCMF_WOWL_DIS | BRCMF_WOWL_BCN | BRCMF_WOWL_RETR; if (wowl->magic_pkt) - wowl_config |= WL_WOWL_MAGIC; + wowl_config |= BRCMF_WOWL_MAGIC; + if ((wowl->patterns) && (wowl->n_patterns)) { + wowl_config |= BRCMF_WOWL_NET; + for (i = 0; i < wowl->n_patterns; i++) { + brcmf_config_wowl_pattern(ifp, "add", + (u8 *)wowl->patterns[i].pattern, + wowl->patterns[i].pattern_len, + (u8 *)wowl->patterns[i].mask, + wowl->patterns[i].pkt_offset); + } + } brcmf_fil_iovar_int_set(ifp, "wowl", wowl_config); brcmf_fil_iovar_int_set(ifp, "wowl_activate", 1); brcmf_bus_wowl_config(cfg->pub->bus_if, true); @@ -4004,24 +4051,24 @@ brcmf_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *ndev, static int brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, - const u8 *mac) + struct station_del_parameters *params) { struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_scb_val_le scbval; struct brcmf_if *ifp = netdev_priv(ndev); s32 err; - if (!mac) + if (!params->mac) return -EFAULT; - brcmf_dbg(TRACE, "Enter %pM\n", mac); + brcmf_dbg(TRACE, "Enter %pM\n", params->mac); if (ifp->vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif) ifp = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; if (!check_vif_up(ifp->vif)) return -EIO; - memcpy(&scbval.ea, mac, ETH_ALEN); + memcpy(&scbval.ea, params->mac, ETH_ALEN); scbval.val = cpu_to_le32(WLAN_REASON_DEAUTH_LEAVING); err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON, &scbval, sizeof(scbval)); @@ -5446,10 +5493,13 @@ static void brcmf_wiphy_pno_params(struct wiphy *wiphy) wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; } - #ifdef CONFIG_PM static const struct wiphy_wowlan_support brcmf_wowlan_support = { .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT, + .n_patterns = BRCMF_WOWL_MAXPATTERNS, + .pattern_max_len = BRCMF_WOWL_MAXPATTERNSIZE, + .pattern_min_len = 1, + .max_pkt_offset = 1500, }; #endif @@ -5613,7 +5663,8 @@ enum nl80211_iftype brcmf_cfg80211_get_iftype(struct brcmf_if *ifp) return wdev->iftype; } -bool brcmf_get_vif_state_any(struct brcmf_cfg80211_info *cfg, unsigned long state) +bool brcmf_get_vif_state_any(struct brcmf_cfg80211_info *cfg, + unsigned long state) { struct brcmf_cfg80211_vif *vif; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h index 6abf94e41d3d..2a5b22cb3fef 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h @@ -14,8 +14,8 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#ifndef _wl_cfg80211_h_ -#define _wl_cfg80211_h_ +#ifndef BRCMFMAC_CFG80211_H +#define BRCMFMAC_CFG80211_H /* for brcmu_d11inf */ #include <brcmu_d11.h> @@ -480,7 +480,8 @@ const struct brcmf_tlv * brcmf_parse_tlvs(const void *buf, int buflen, uint key); u16 channel_to_chanspec(struct brcmu_d11inf *d11inf, struct ieee80211_channel *ch); -bool brcmf_get_vif_state_any(struct brcmf_cfg80211_info *cfg, unsigned long state); +bool brcmf_get_vif_state_any(struct brcmf_cfg80211_info *cfg, + unsigned long state); void brcmf_cfg80211_arm_vif_event(struct brcmf_cfg80211_info *cfg, struct brcmf_cfg80211_vif *vif); bool brcmf_cfg80211_vif_event_armed(struct brcmf_cfg80211_info *cfg); @@ -493,4 +494,4 @@ void brcmf_set_mpc(struct brcmf_if *ndev, int mpc); void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg); void brcmf_cfg80211_free_netdev(struct net_device *ndev); -#endif /* _wl_cfg80211_h_ */ +#endif /* BRCMFMAC_CFG80211_H */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/brcm80211/brcmfmac/chip.c index 95efde868db8..ddae0b5e56ec 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c @@ -25,7 +25,7 @@ #include <brcm_hw_ids.h> #include <brcmu_utils.h> #include <chipcommon.h> -#include "dhd_dbg.h" +#include "debug.h" #include "chip.h" /* SOC Interconnect types (aka chip types) */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/common.c b/drivers/net/wireless/brcm80211/brcmfmac/common.c new file mode 100644 index 000000000000..1861a13e8d03 --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmfmac/common.c @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2010 Broadcom Corporation + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/netdevice.h> +#include <brcmu_wifi.h> +#include <brcmu_utils.h> +#include "core.h" +#include "bus.h" +#include "debug.h" +#include "fwil.h" +#include "fwil_types.h" +#include "tracepoint.h" + +#define BRCMF_DEFAULT_BCN_TIMEOUT 3 +#define BRCMF_DEFAULT_SCAN_CHANNEL_TIME 40 +#define BRCMF_DEFAULT_SCAN_UNASSOC_TIME 40 + +/* boost value for RSSI_DELTA in preferred join selection */ +#define BRCMF_JOIN_PREF_RSSI_BOOST 8 + +int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) +{ + s8 eventmask[BRCMF_EVENTING_MASK_LEN]; + u8 buf[BRCMF_DCMD_SMLEN]; + struct brcmf_join_pref_params join_pref_params[2]; + char *ptr; + s32 err; + + /* retreive mac address */ + err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr, + sizeof(ifp->mac_addr)); + if (err < 0) { + brcmf_err("Retreiving cur_etheraddr failed, %d\n", + err); + goto done; + } + memcpy(ifp->drvr->mac, ifp->mac_addr, sizeof(ifp->drvr->mac)); + + /* query for 'ver' to get version info from firmware */ + memset(buf, 0, sizeof(buf)); + strcpy(buf, "ver"); + err = brcmf_fil_iovar_data_get(ifp, "ver", buf, sizeof(buf)); + if (err < 0) { + brcmf_err("Retreiving version information failed, %d\n", + err); + goto done; + } + ptr = (char *)buf; + strsep(&ptr, "\n"); + + /* Print fw version info */ + brcmf_err("Firmware version = %s\n", buf); + + /* locate firmware version number for ethtool */ + ptr = strrchr(buf, ' ') + 1; + strlcpy(ifp->drvr->fwver, ptr, sizeof(ifp->drvr->fwver)); + + /* set mpc */ + err = brcmf_fil_iovar_int_set(ifp, "mpc", 1); + if (err) { + brcmf_err("failed setting mpc\n"); + goto done; + } + + /* + * Setup timeout if Beacons are lost and roam is off to report + * link down + */ + err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout", + BRCMF_DEFAULT_BCN_TIMEOUT); + if (err) { + brcmf_err("bcn_timeout error (%d)\n", err); + goto done; + } + + /* Enable/Disable build-in roaming to allowed ext supplicant to take + * of romaing + */ + err = brcmf_fil_iovar_int_set(ifp, "roam_off", 1); + if (err) { + brcmf_err("roam_off error (%d)\n", err); + goto done; + } + + /* Setup join_pref to select target by RSSI(with boost on 5GHz) */ + join_pref_params[0].type = BRCMF_JOIN_PREF_RSSI_DELTA; + join_pref_params[0].len = 2; + join_pref_params[0].rssi_gain = BRCMF_JOIN_PREF_RSSI_BOOST; + join_pref_params[0].band = WLC_BAND_5G; + join_pref_params[1].type = BRCMF_JOIN_PREF_RSSI; + join_pref_params[1].len = 2; + join_pref_params[1].rssi_gain = 0; + join_pref_params[1].band = 0; + err = brcmf_fil_iovar_data_set(ifp, "join_pref", join_pref_params, + sizeof(join_pref_params)); + if (err) + brcmf_err("Set join_pref error (%d)\n", err); + + /* Setup event_msgs, enable E_IF */ + err = brcmf_fil_iovar_data_get(ifp, "event_msgs", eventmask, + BRCMF_EVENTING_MASK_LEN); + if (err) { + brcmf_err("Get event_msgs error (%d)\n", err); + goto done; + } + setbit(eventmask, BRCMF_E_IF); + err = brcmf_fil_iovar_data_set(ifp, "event_msgs", eventmask, + BRCMF_EVENTING_MASK_LEN); + if (err) { + brcmf_err("Set event_msgs error (%d)\n", err); + goto done; + } + + /* Setup default scan channel time */ + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME, + BRCMF_DEFAULT_SCAN_CHANNEL_TIME); + if (err) { + brcmf_err("BRCMF_C_SET_SCAN_CHANNEL_TIME error (%d)\n", + err); + goto done; + } + + /* Setup default scan unassoc time */ + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_UNASSOC_TIME, + BRCMF_DEFAULT_SCAN_UNASSOC_TIME); + if (err) { + brcmf_err("BRCMF_C_SET_SCAN_UNASSOC_TIME error (%d)\n", + err); + goto done; + } + + /* do bus specific preinit here */ + err = brcmf_bus_preinit(ifp->drvr->bus_if); +done: + return err; +} + +#if defined(CONFIG_BRCM_TRACING) || defined(CONFIG_BRCMDBG) +void __brcmf_dbg(u32 level, const char *func, const char *fmt, ...) +{ + struct va_format vaf = { + .fmt = fmt, + }; + va_list args; + + va_start(args, fmt); + vaf.va = &args; + if (brcmf_msg_level & level) + pr_debug("%s %pV", func, &vaf); + trace_brcmf_dbg(level, func, &vaf); + va_end(args); +} +#endif diff --git a/drivers/net/wireless/brcm80211/brcmfmac/commonring.c b/drivers/net/wireless/brcm80211/brcmfmac/commonring.c index c6d65b8e1e15..77656c711bed 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/commonring.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/commonring.c @@ -19,7 +19,7 @@ #include <brcmu_utils.h> #include <brcmu_wifi.h> -#include "dhd.h" +#include "core.h" #include "commonring.h" diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/core.c index fb1043908a23..f407665cb1ea 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c @@ -22,12 +22,12 @@ #include <brcmu_utils.h> #include <brcmu_wifi.h> -#include "dhd.h" -#include "dhd_bus.h" -#include "dhd_dbg.h" +#include "core.h" +#include "bus.h" +#include "debug.h" #include "fwil_types.h" #include "p2p.h" -#include "wl_cfg80211.h" +#include "cfg80211.h" #include "fwil.h" #include "fwsignal.h" #include "feature.h" diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/core.h index 5e4317dbc2b0..98228e922d3a 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h @@ -18,8 +18,8 @@ * Common types * */ -#ifndef _BRCMF_H_ -#define _BRCMF_H_ +#ifndef BRCMFMAC_CORE_H +#define BRCMFMAC_CORE_H #include "fweh.h" @@ -83,7 +83,6 @@ struct brcmf_pub { /* Internal brcmf items */ uint hdrlen; /* Total BRCMF header length (proto + bus) */ uint rxsz; /* Rx buffer size bus module should use */ - u8 wme_dp; /* wme discard priority */ /* Dongle media info */ char fwver[BRCMF_DRIVER_FIRMWARE_VERSION_LEN]; @@ -186,4 +185,4 @@ void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb); /* Sets dongle media info (drv_version, mac address). */ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp); -#endif /* _BRCMF_H_ */ +#endif /* BRCMFMAC_CORE_H */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c b/drivers/net/wireless/brcm80211/brcmfmac/debug.c index be9f4f829192..9b473d50b005 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/debug.c @@ -19,9 +19,9 @@ #include <brcmu_wifi.h> #include <brcmu_utils.h> -#include "dhd.h" -#include "dhd_bus.h" -#include "dhd_dbg.h" +#include "core.h" +#include "bus.h" +#include "debug.h" static struct dentry *root_folder; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h b/drivers/net/wireless/brcm80211/brcmfmac/debug.h index dec40d316c82..eb0b8c47479d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/debug.h @@ -14,8 +14,8 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#ifndef _BRCMF_DBG_H_ -#define _BRCMF_DBG_H_ +#ifndef BRCMFMAC_DEBUG_H +#define BRCMFMAC_DEBUG_H /* message levels */ #define BRCMF_TRACE_VAL 0x00000002 @@ -133,4 +133,4 @@ int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn, } #endif -#endif /* _BRCMF_DBG_H_ */ +#endif /* BRCMFMAC_DEBUG_H */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c deleted file mode 100644 index d991f8e3d9ec..000000000000 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c +++ /dev/null @@ -1,400 +0,0 @@ -/* - * Copyright (c) 2010 Broadcom Corporation - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <linux/kernel.h> -#include <linux/string.h> -#include <linux/netdevice.h> -#include <brcmu_wifi.h> -#include <brcmu_utils.h> -#include "dhd.h" -#include "dhd_bus.h" -#include "dhd_dbg.h" -#include "fwil.h" -#include "fwil_types.h" -#include "tracepoint.h" - -#define PKTFILTER_BUF_SIZE 128 -#define BRCMF_DEFAULT_BCN_TIMEOUT 3 -#define BRCMF_DEFAULT_SCAN_CHANNEL_TIME 40 -#define BRCMF_DEFAULT_SCAN_UNASSOC_TIME 40 -#define BRCMF_DEFAULT_PACKET_FILTER "100 0 0 0 0x01 0x00" - -/* boost value for RSSI_DELTA in preferred join selection */ -#define BRCMF_JOIN_PREF_RSSI_BOOST 8 - - -bool brcmf_c_prec_enq(struct device *dev, struct pktq *q, - struct sk_buff *pkt, int prec) -{ - struct sk_buff *p; - int eprec = -1; /* precedence to evict from */ - bool discard_oldest; - struct brcmf_bus *bus_if = dev_get_drvdata(dev); - struct brcmf_pub *drvr = bus_if->drvr; - - /* Fast case, precedence queue is not full and we are also not - * exceeding total queue length - */ - if (!pktq_pfull(q, prec) && !pktq_full(q)) { - brcmu_pktq_penq(q, prec, pkt); - return true; - } - - /* Determine precedence from which to evict packet, if any */ - if (pktq_pfull(q, prec)) - eprec = prec; - else if (pktq_full(q)) { - p = brcmu_pktq_peek_tail(q, &eprec); - if (eprec > prec) - return false; - } - - /* Evict if needed */ - if (eprec >= 0) { - /* Detect queueing to unconfigured precedence */ - discard_oldest = ac_bitmap_tst(drvr->wme_dp, eprec); - if (eprec == prec && !discard_oldest) - return false; /* refuse newer (incoming) packet */ - /* Evict packet according to discard policy */ - p = discard_oldest ? brcmu_pktq_pdeq(q, eprec) : - brcmu_pktq_pdeq_tail(q, eprec); - if (p == NULL) - brcmf_err("brcmu_pktq_penq() failed, oldest %d\n", - discard_oldest); - - brcmu_pkt_buf_free_skb(p); - } - - /* Enqueue */ - p = brcmu_pktq_penq(q, prec, pkt); - if (p == NULL) - brcmf_err("brcmu_pktq_penq() failed\n"); - - return p != NULL; -} - -/* Convert user's input in hex pattern to byte-size mask */ -static int brcmf_c_pattern_atoh(char *src, char *dst) -{ - int i; - if (strncmp(src, "0x", 2) != 0 && strncmp(src, "0X", 2) != 0) { - brcmf_err("Mask invalid format. Needs to start with 0x\n"); - return -EINVAL; - } - src = src + 2; /* Skip past 0x */ - if (strlen(src) % 2 != 0) { - brcmf_err("Mask invalid format. Length must be even.\n"); - return -EINVAL; - } - for (i = 0; *src != '\0'; i++) { - unsigned long res; - char num[3]; - strncpy(num, src, 2); - num[2] = '\0'; - if (kstrtoul(num, 16, &res)) - return -EINVAL; - dst[i] = (u8)res; - src += 2; - } - return i; -} - -static void -brcmf_c_pktfilter_offload_enable(struct brcmf_if *ifp, char *arg, int enable, - int master_mode) -{ - unsigned long res; - char *argv; - char *arg_save = NULL, *arg_org = NULL; - s32 err; - struct brcmf_pkt_filter_enable_le enable_parm; - - arg_save = kstrdup(arg, GFP_ATOMIC); - if (!arg_save) - goto fail; - - arg_org = arg_save; - - argv = strsep(&arg_save, " "); - - if (argv == NULL) { - brcmf_err("No args provided\n"); - goto fail; - } - - /* Parse packet filter id. */ - enable_parm.id = 0; - if (!kstrtoul(argv, 0, &res)) - enable_parm.id = cpu_to_le32((u32)res); - - /* Enable/disable the specified filter. */ - enable_parm.enable = cpu_to_le32(enable); - - err = brcmf_fil_iovar_data_set(ifp, "pkt_filter_enable", &enable_parm, - sizeof(enable_parm)); - if (err) - brcmf_err("Set pkt_filter_enable error (%d)\n", err); - - /* Control the master mode */ - err = brcmf_fil_iovar_int_set(ifp, "pkt_filter_mode", master_mode); - if (err) - brcmf_err("Set pkt_filter_mode error (%d)\n", err); - -fail: - kfree(arg_org); -} - -static void brcmf_c_pktfilter_offload_set(struct brcmf_if *ifp, char *arg) -{ - struct brcmf_pkt_filter_le *pkt_filter; - unsigned long res; - int buf_len; - s32 err; - u32 mask_size; - u32 pattern_size; - char *argv[8], *buf = NULL; - int i = 0; - char *arg_save = NULL, *arg_org = NULL; - - arg_save = kstrdup(arg, GFP_ATOMIC); - if (!arg_save) - goto fail; - - arg_org = arg_save; - - buf = kmalloc(PKTFILTER_BUF_SIZE, GFP_ATOMIC); - if (!buf) - goto fail; - - argv[i] = strsep(&arg_save, " "); - while (argv[i]) { - i++; - if (i >= 8) { - brcmf_err("Too many parameters\n"); - goto fail; - } - argv[i] = strsep(&arg_save, " "); - } - - if (i != 6) { - brcmf_err("Not enough args provided %d\n", i); - goto fail; - } - - pkt_filter = (struct brcmf_pkt_filter_le *)buf; - - /* Parse packet filter id. */ - pkt_filter->id = 0; - if (!kstrtoul(argv[0], 0, &res)) - pkt_filter->id = cpu_to_le32((u32)res); - - /* Parse filter polarity. */ - pkt_filter->negate_match = 0; - if (!kstrtoul(argv[1], 0, &res)) - pkt_filter->negate_match = cpu_to_le32((u32)res); - - /* Parse filter type. */ - pkt_filter->type = 0; - if (!kstrtoul(argv[2], 0, &res)) - pkt_filter->type = cpu_to_le32((u32)res); - - /* Parse pattern filter offset. */ - pkt_filter->u.pattern.offset = 0; - if (!kstrtoul(argv[3], 0, &res)) - pkt_filter->u.pattern.offset = cpu_to_le32((u32)res); - - /* Parse pattern filter mask. */ - mask_size = brcmf_c_pattern_atoh(argv[4], - (char *)pkt_filter->u.pattern.mask_and_pattern); - - /* Parse pattern filter pattern. */ - pattern_size = brcmf_c_pattern_atoh(argv[5], - (char *)&pkt_filter->u.pattern.mask_and_pattern[mask_size]); - - if (mask_size != pattern_size) { - brcmf_err("Mask and pattern not the same size\n"); - goto fail; - } - - pkt_filter->u.pattern.size_bytes = cpu_to_le32(mask_size); - buf_len = offsetof(struct brcmf_pkt_filter_le, - u.pattern.mask_and_pattern); - buf_len += mask_size + pattern_size; - - err = brcmf_fil_iovar_data_set(ifp, "pkt_filter_add", pkt_filter, - buf_len); - if (err) - brcmf_err("Set pkt_filter_add error (%d)\n", err); - -fail: - kfree(arg_org); - - kfree(buf); -} - -int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) -{ - s8 eventmask[BRCMF_EVENTING_MASK_LEN]; - u8 buf[BRCMF_DCMD_SMLEN]; - struct brcmf_join_pref_params join_pref_params[2]; - char *ptr; - s32 err; - - /* retreive mac address */ - err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr, - sizeof(ifp->mac_addr)); - if (err < 0) { - brcmf_err("Retreiving cur_etheraddr failed, %d\n", - err); - goto done; - } - memcpy(ifp->drvr->mac, ifp->mac_addr, sizeof(ifp->drvr->mac)); - - /* query for 'ver' to get version info from firmware */ - memset(buf, 0, sizeof(buf)); - strcpy(buf, "ver"); - err = brcmf_fil_iovar_data_get(ifp, "ver", buf, sizeof(buf)); - if (err < 0) { - brcmf_err("Retreiving version information failed, %d\n", - err); - goto done; - } - ptr = (char *)buf; - strsep(&ptr, "\n"); - - /* Print fw version info */ - brcmf_err("Firmware version = %s\n", buf); - - /* locate firmware version number for ethtool */ - ptr = strrchr(buf, ' ') + 1; - strlcpy(ifp->drvr->fwver, ptr, sizeof(ifp->drvr->fwver)); - - /* set mpc */ - err = brcmf_fil_iovar_int_set(ifp, "mpc", 1); - if (err) { - brcmf_err("failed setting mpc\n"); - goto done; - } - - /* - * Setup timeout if Beacons are lost and roam is off to report - * link down - */ - err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout", - BRCMF_DEFAULT_BCN_TIMEOUT); - if (err) { - brcmf_err("bcn_timeout error (%d)\n", err); - goto done; - } - - /* Enable/Disable build-in roaming to allowed ext supplicant to take - * of romaing - */ - err = brcmf_fil_iovar_int_set(ifp, "roam_off", 1); - if (err) { - brcmf_err("roam_off error (%d)\n", err); - goto done; - } - - /* Setup join_pref to select target by RSSI(with boost on 5GHz) */ - join_pref_params[0].type = BRCMF_JOIN_PREF_RSSI_DELTA; - join_pref_params[0].len = 2; - join_pref_params[0].rssi_gain = BRCMF_JOIN_PREF_RSSI_BOOST; - join_pref_params[0].band = WLC_BAND_5G; - join_pref_params[1].type = BRCMF_JOIN_PREF_RSSI; - join_pref_params[1].len = 2; - join_pref_params[1].rssi_gain = 0; - join_pref_params[1].band = 0; - err = brcmf_fil_iovar_data_set(ifp, "join_pref", join_pref_params, - sizeof(join_pref_params)); - if (err) - brcmf_err("Set join_pref error (%d)\n", err); - - /* Setup event_msgs, enable E_IF */ - err = brcmf_fil_iovar_data_get(ifp, "event_msgs", eventmask, - BRCMF_EVENTING_MASK_LEN); - if (err) { - brcmf_err("Get event_msgs error (%d)\n", err); - goto done; - } - setbit(eventmask, BRCMF_E_IF); - err = brcmf_fil_iovar_data_set(ifp, "event_msgs", eventmask, - BRCMF_EVENTING_MASK_LEN); - if (err) { - brcmf_err("Set event_msgs error (%d)\n", err); - goto done; - } - - /* Setup default scan channel time */ - err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME, - BRCMF_DEFAULT_SCAN_CHANNEL_TIME); - if (err) { - brcmf_err("BRCMF_C_SET_SCAN_CHANNEL_TIME error (%d)\n", - err); - goto done; - } - - /* Setup default scan unassoc time */ - err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_UNASSOC_TIME, - BRCMF_DEFAULT_SCAN_UNASSOC_TIME); - if (err) { - brcmf_err("BRCMF_C_SET_SCAN_UNASSOC_TIME error (%d)\n", - err); - goto done; - } - - /* Setup packet filter */ - brcmf_c_pktfilter_offload_set(ifp, BRCMF_DEFAULT_PACKET_FILTER); - brcmf_c_pktfilter_offload_enable(ifp, BRCMF_DEFAULT_PACKET_FILTER, - 0, true); - - /* do bus specific preinit here */ - err = brcmf_bus_preinit(ifp->drvr->bus_if); -done: - return err; -} - -#ifdef CONFIG_BRCM_TRACING -void __brcmf_err(const char *func, const char *fmt, ...) -{ - struct va_format vaf = { - .fmt = fmt, - }; - va_list args; - - va_start(args, fmt); - vaf.va = &args; - pr_err("%s: %pV", func, &vaf); - trace_brcmf_err(func, &vaf); - va_end(args); -} -#endif -#if defined(CONFIG_BRCM_TRACING) || defined(CONFIG_BRCMDBG) -void __brcmf_dbg(u32 level, const char *func, const char *fmt, ...) -{ - struct va_format vaf = { - .fmt = fmt, - }; - va_list args; - - va_start(args, fmt); - vaf.va = &args; - if (brcmf_msg_level & level) - pr_debug("%s %pV", func, &vaf); - trace_brcmf_dbg(level, func, &vaf); - va_end(args); -} -#endif diff --git a/drivers/net/wireless/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/brcm80211/brcmfmac/feature.c index aed53acef456..931f68aefaa4 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/feature.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.c @@ -17,18 +17,13 @@ #include <linux/netdevice.h> #include <brcm_hw_ids.h> -#include "dhd.h" -#include "dhd_bus.h" -#include "dhd_dbg.h" +#include "core.h" +#include "bus.h" +#include "debug.h" #include "fwil.h" #include "feature.h" /* - * firmware error code received if iovar is unsupported. - */ -#define EBRCMF_FEAT_UNSUPPORTED 23 - -/* * expand feature list to array of feature strings. */ #define BRCMF_FEAT_DEF(_f) \ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c index 8ea9f283d2b8..1ff787d1a36b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c @@ -20,7 +20,7 @@ #include <linux/firmware.h> #include <linux/module.h> -#include "dhd_dbg.h" +#include "debug.h" #include "firmware.h" char brcmf_firmware_path[BRCMF_FW_PATH_LEN]; @@ -262,8 +262,7 @@ static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx) fail: brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev)); - if (fwctx->code) - release_firmware(fwctx->code); + release_firmware(fwctx->code); device_release_driver(fwctx->dev); kfree(fwctx); } diff --git a/drivers/net/wireless/brcm80211/brcmfmac/flowring.c b/drivers/net/wireless/brcm80211/brcmfmac/flowring.c index 1faa929f5fff..44f3a84d1999 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/flowring.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/flowring.c @@ -19,9 +19,9 @@ #include <linux/etherdevice.h> #include <brcmu_utils.h> -#include "dhd.h" -#include "dhd_dbg.h" -#include "dhd_bus.h" +#include "core.h" +#include "debug.h" +#include "bus.h" #include "proto.h" #include "flowring.h" #include "msgbuf.h" diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c index 44fc85f68f7a..7338b335e153 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c @@ -18,8 +18,8 @@ #include "brcmu_wifi.h" #include "brcmu_utils.h" -#include "dhd.h" -#include "dhd_dbg.h" +#include "core.h" +#include "debug.h" #include "tracepoint.h" #include "fwsignal.h" #include "fweh.h" diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil.c b/drivers/net/wireless/brcm80211/brcmfmac/fwil.c index ded328f80cd1..51f88c11e642 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwil.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil.c @@ -22,9 +22,9 @@ #include <linux/netdevice.h> #include <brcmu_utils.h> #include <brcmu_wifi.h> -#include "dhd.h" -#include "dhd_bus.h" -#include "dhd_dbg.h" +#include "core.h" +#include "bus.h" +#include "debug.h" #include "tracepoint.h" #include "fwil.h" #include "proto.h" @@ -32,6 +32,76 @@ #define MAX_HEX_DUMP_LEN 64 +#ifdef DEBUG +static const char * const brcmf_fil_errstr[] = { + "BCME_OK", + "BCME_ERROR", + "BCME_BADARG", + "BCME_BADOPTION", + "BCME_NOTUP", + "BCME_NOTDOWN", + "BCME_NOTAP", + "BCME_NOTSTA", + "BCME_BADKEYIDX", + "BCME_RADIOOFF", + "BCME_NOTBANDLOCKED", + "BCME_NOCLK", + "BCME_BADRATESET", + "BCME_BADBAND", + "BCME_BUFTOOSHORT", + "BCME_BUFTOOLONG", + "BCME_BUSY", + "BCME_NOTASSOCIATED", + "BCME_BADSSIDLEN", + "BCME_OUTOFRANGECHAN", + "BCME_BADCHAN", + "BCME_BADADDR", + "BCME_NORESOURCE", + "BCME_UNSUPPORTED", + "BCME_BADLEN", + "BCME_NOTREADY", + "BCME_EPERM", + "BCME_NOMEM", + "BCME_ASSOCIATED", + "BCME_RANGE", + "BCME_NOTFOUND", + "BCME_WME_NOT_ENABLED", + "BCME_TSPEC_NOTFOUND", + "BCME_ACM_NOTSUPPORTED", + "BCME_NOT_WME_ASSOCIATION", + "BCME_SDIO_ERROR", + "BCME_DONGLE_DOWN", + "BCME_VERSION", + "BCME_TXFAIL", + "BCME_RXFAIL", + "BCME_NODEVICE", + "BCME_NMODE_DISABLED", + "BCME_NONRESIDENT", + "BCME_SCANREJECT", + "BCME_USAGE_ERROR", + "BCME_IOCTL_ERROR", + "BCME_SERIAL_PORT_ERR", + "BCME_DISABLED", + "BCME_DECERR", + "BCME_ENCERR", + "BCME_MICERR", + "BCME_REPLAY", + "BCME_IE_NOTFOUND", +}; + +static const char *brcmf_fil_get_errstr(u32 err) +{ + if (err >= ARRAY_SIZE(brcmf_fil_errstr)) + return "(unknown)"; + + return brcmf_fil_errstr[err]; +} +#else +static const char *brcmf_fil_get_errstr(u32 err) +{ + return ""; +} +#endif /* DEBUG */ static s32 brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set) @@ -52,11 +122,11 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set) err = brcmf_proto_query_dcmd(drvr, ifp->ifidx, cmd, data, len); if (err >= 0) - err = 0; - else - brcmf_dbg(FIL, "Failed err=%d\n", err); + return 0; - return err; + brcmf_dbg(FIL, "Failed: %s (%d)\n", + brcmf_fil_get_errstr((u32)(-err)), err); + return -EBADE; } s32 diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h index 5ff5cd0bb032..ba64b292f7a5 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h @@ -55,59 +55,63 @@ /* WOWL bits */ /* Wakeup on Magic packet: */ -#define WL_WOWL_MAGIC (1 << 0) +#define BRCMF_WOWL_MAGIC (1 << 0) /* Wakeup on Netpattern */ -#define WL_WOWL_NET (1 << 1) +#define BRCMF_WOWL_NET (1 << 1) /* Wakeup on loss-of-link due to Disassoc/Deauth: */ -#define WL_WOWL_DIS (1 << 2) +#define BRCMF_WOWL_DIS (1 << 2) /* Wakeup on retrograde TSF: */ -#define WL_WOWL_RETR (1 << 3) +#define BRCMF_WOWL_RETR (1 << 3) /* Wakeup on loss of beacon: */ -#define WL_WOWL_BCN (1 << 4) +#define BRCMF_WOWL_BCN (1 << 4) /* Wakeup after test: */ -#define WL_WOWL_TST (1 << 5) +#define BRCMF_WOWL_TST (1 << 5) /* Wakeup after PTK refresh: */ -#define WL_WOWL_M1 (1 << 6) +#define BRCMF_WOWL_M1 (1 << 6) /* Wakeup after receipt of EAP-Identity Req: */ -#define WL_WOWL_EAPID (1 << 7) +#define BRCMF_WOWL_EAPID (1 << 7) /* Wakeind via PME(0) or GPIO(1): */ -#define WL_WOWL_PME_GPIO (1 << 8) +#define BRCMF_WOWL_PME_GPIO (1 << 8) /* need tkip phase 1 key to be updated by the driver: */ -#define WL_WOWL_NEEDTKIP1 (1 << 9) +#define BRCMF_WOWL_NEEDTKIP1 (1 << 9) /* enable wakeup if GTK fails: */ -#define WL_WOWL_GTK_FAILURE (1 << 10) +#define BRCMF_WOWL_GTK_FAILURE (1 << 10) /* support extended magic packets: */ -#define WL_WOWL_EXTMAGPAT (1 << 11) +#define BRCMF_WOWL_EXTMAGPAT (1 << 11) /* support ARP/NS/keepalive offloading: */ -#define WL_WOWL_ARPOFFLOAD (1 << 12) +#define BRCMF_WOWL_ARPOFFLOAD (1 << 12) /* read protocol version for EAPOL frames: */ -#define WL_WOWL_WPA2 (1 << 13) +#define BRCMF_WOWL_WPA2 (1 << 13) /* If the bit is set, use key rotaton: */ -#define WL_WOWL_KEYROT (1 << 14) +#define BRCMF_WOWL_KEYROT (1 << 14) /* If the bit is set, frm received was bcast frame: */ -#define WL_WOWL_BCAST (1 << 15) +#define BRCMF_WOWL_BCAST (1 << 15) /* If the bit is set, scan offload is enabled: */ -#define WL_WOWL_SCANOL (1 << 16) +#define BRCMF_WOWL_SCANOL (1 << 16) /* Wakeup on tcpkeep alive timeout: */ -#define WL_WOWL_TCPKEEP_TIME (1 << 17) +#define BRCMF_WOWL_TCPKEEP_TIME (1 << 17) /* Wakeup on mDNS Conflict Resolution: */ -#define WL_WOWL_MDNS_CONFLICT (1 << 18) +#define BRCMF_WOWL_MDNS_CONFLICT (1 << 18) /* Wakeup on mDNS Service Connect: */ -#define WL_WOWL_MDNS_SERVICE (1 << 19) +#define BRCMF_WOWL_MDNS_SERVICE (1 << 19) /* tcp keepalive got data: */ -#define WL_WOWL_TCPKEEP_DATA (1 << 20) +#define BRCMF_WOWL_TCPKEEP_DATA (1 << 20) /* Firmware died in wowl mode: */ -#define WL_WOWL_FW_HALT (1 << 21) +#define BRCMF_WOWL_FW_HALT (1 << 21) /* Enable detection of radio button changes: */ -#define WL_WOWL_ENAB_HWRADIO (1 << 22) +#define BRCMF_WOWL_ENAB_HWRADIO (1 << 22) /* Offloads detected MIC failure(s): */ -#define WL_WOWL_MIC_FAIL (1 << 23) +#define BRCMF_WOWL_MIC_FAIL (1 << 23) /* Wakeup in Unassociated state (Net/Magic Pattern): */ -#define WL_WOWL_UNASSOC (1 << 24) +#define BRCMF_WOWL_UNASSOC (1 << 24) /* Wakeup if received matched secured pattern: */ -#define WL_WOWL_SECURE (1 << 25) +#define BRCMF_WOWL_SECURE (1 << 25) /* Link Down indication in WoWL mode: */ -#define WL_WOWL_LINKDOWN (1 << 31) +#define BRCMF_WOWL_LINKDOWN (1 << 31) + +#define BRCMF_WOWL_MAXPATTERNS 8 +#define BRCMF_WOWL_MAXPATTERNSIZE 128 + /* join preference types for join_pref iovar */ enum brcmf_join_pref_types { @@ -124,6 +128,12 @@ enum brcmf_fil_p2p_if_types { BRCMF_FIL_P2P_IF_DEV, }; +enum brcmf_wowl_pattern_type { + BRCMF_WOWL_PATTERN_TYPE_BITMAP = 0, + BRCMF_WOWL_PATTERN_TYPE_ARP, + BRCMF_WOWL_PATTERN_TYPE_NA +}; + struct brcmf_fil_p2p_if_le { u8 addr[ETH_ALEN]; __le16 type; @@ -484,4 +494,29 @@ struct brcmf_rx_mgmt_data { __be32 rate; }; +/** + * struct brcmf_fil_wowl_pattern_le - wowl pattern configuration struct. + * + * @cmd: "add", "del" or "clr". + * @masksize: Size of the mask in #of bytes + * @offset: Pattern byte offset in packet + * @patternoffset: Offset of start of pattern. Starting from field masksize. + * @patternsize: Size of the pattern itself in #of bytes + * @id: id + * @reasonsize: Size of the wakeup reason code + * @type: Type of pattern (enum brcmf_wowl_pattern_type) + */ +struct brcmf_fil_wowl_pattern_le { + u8 cmd[4]; + __le32 masksize; + __le32 offset; + __le32 patternoffset; + __le32 patternsize; + __le32 id; + __le32 reasonsize; + __le32 type; + /* u8 mask[] - Mask follows the structure above */ + /* u8 pattern[] - Pattern follows the mask is at 'patternoffset' */ +}; + #endif /* FWIL_TYPES_H_ */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index 183f08d7fc8c..f0dda0ecd23b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -26,15 +26,15 @@ #include <brcmu_utils.h> #include <brcmu_wifi.h> -#include "dhd.h" -#include "dhd_dbg.h" -#include "dhd_bus.h" +#include "core.h" +#include "debug.h" +#include "bus.h" #include "fwil.h" #include "fwil_types.h" #include "fweh.h" #include "fwsignal.h" #include "p2p.h" -#include "wl_cfg80211.h" +#include "cfg80211.h" #include "proto.h" /** diff --git a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c index 11cc051f97cd..9f783db34ae5 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c @@ -24,13 +24,13 @@ #include <brcmu_utils.h> #include <brcmu_wifi.h> -#include "dhd.h" -#include "dhd_dbg.h" +#include "core.h" +#include "debug.h" #include "proto.h" #include "msgbuf.h" #include "commonring.h" #include "flowring.h" -#include "dhd_bus.h" +#include "bus.h" #include "tracepoint.h" @@ -518,8 +518,7 @@ static int brcmf_msgbuf_query_dcmd(struct brcmf_pub *drvr, int ifidx, memcpy(buf, skb->data, (len < msgbuf->ioctl_resp_ret_len) ? len : msgbuf->ioctl_resp_ret_len); } - if (skb) - brcmu_pkt_buf_free_skb(skb); + brcmu_pkt_buf_free_skb(skb); return msgbuf->ioctl_resp_status; } diff --git a/drivers/net/wireless/brcm80211/brcmfmac/of.c b/drivers/net/wireless/brcm80211/brcmfmac/of.c index 927bffd5be64..c824570ddea3 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/of.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/of.c @@ -21,8 +21,8 @@ #include <linux/mmc/sdio_func.h> #include <defs.h> -#include "dhd_dbg.h" -#include "sdio_host.h" +#include "debug.h" +#include "sdio.h" void brcmf_of_probe(struct brcmf_sdio_dev *sdiodev) { diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c index d54c58a32faa..effb48ebd864 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c @@ -21,12 +21,12 @@ #include <brcmu_wifi.h> #include <brcmu_utils.h> #include <defs.h> -#include <dhd.h> -#include <dhd_dbg.h> +#include "core.h" +#include "debug.h" #include "fwil.h" #include "fwil_types.h" #include "p2p.h" -#include "wl_cfg80211.h" +#include "cfg80211.h" /* parameters used for p2p escan */ #define P2PAPI_SCAN_NPROBES 1 diff --git a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c index 16fef3382019..138691a1365a 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c @@ -30,8 +30,8 @@ #include <brcmu_wifi.h> #include <brcm_hw_ids.h> -#include "dhd_dbg.h" -#include "dhd_bus.h" +#include "debug.h" +#include "bus.h" #include "commonring.h" #include "msgbuf.h" #include "pcie.h" diff --git a/drivers/net/wireless/brcm80211/brcmfmac/proto.c b/drivers/net/wireless/brcm80211/brcmfmac/proto.c index 62b940723339..26b68c367f57 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/proto.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/proto.c @@ -20,9 +20,9 @@ #include <linux/netdevice.h> #include <brcmu_wifi.h> -#include "dhd.h" -#include "dhd_bus.h" -#include "dhd_dbg.h" +#include "core.h" +#include "bus.h" +#include "debug.h" #include "proto.h" #include "bcdc.h" #include "msgbuf.h" diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c index d20d4e6f391a..0b0d51a61060 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c @@ -40,7 +40,7 @@ #include <brcmu_utils.h> #include <brcm_hw_ids.h> #include <soc.h> -#include "sdio_host.h" +#include "sdio.h" #include "chip.h" #include "firmware.h" @@ -96,8 +96,8 @@ struct rte_console { #endif /* DEBUG */ #include <chipcommon.h> -#include "dhd_bus.h" -#include "dhd_dbg.h" +#include "bus.h" +#include "debug.h" #include "tracepoint.h" #define TXQLEN 2048 /* bulk tx queue length */ @@ -2762,6 +2762,48 @@ static struct pktq *brcmf_sdio_bus_gettxq(struct device *dev) return &bus->txq; } +static bool brcmf_sdio_prec_enq(struct pktq *q, struct sk_buff *pkt, int prec) +{ + struct sk_buff *p; + int eprec = -1; /* precedence to evict from */ + + /* Fast case, precedence queue is not full and we are also not + * exceeding total queue length + */ + if (!pktq_pfull(q, prec) && !pktq_full(q)) { + brcmu_pktq_penq(q, prec, pkt); + return true; + } + + /* Determine precedence from which to evict packet, if any */ + if (pktq_pfull(q, prec)) { + eprec = prec; + } else if (pktq_full(q)) { + p = brcmu_pktq_peek_tail(q, &eprec); + if (eprec > prec) + return false; + } + + /* Evict if needed */ + if (eprec >= 0) { + /* Detect queueing to unconfigured precedence */ + if (eprec == prec) + return false; /* refuse newer (incoming) packet */ + /* Evict packet according to discard policy */ + p = brcmu_pktq_pdeq_tail(q, eprec); + if (p == NULL) + brcmf_err("brcmu_pktq_pdeq_tail() failed\n"); + brcmu_pkt_buf_free_skb(p); + } + + /* Enqueue */ + p = brcmu_pktq_penq(q, prec, pkt); + if (p == NULL) + brcmf_err("brcmu_pktq_penq() failed\n"); + + return p != NULL; +} + static int brcmf_sdio_bus_txdata(struct device *dev, struct sk_buff *pkt) { int ret = -EBADE; @@ -2787,7 +2829,7 @@ static int brcmf_sdio_bus_txdata(struct device *dev, struct sk_buff *pkt) spin_lock_bh(&bus->txq_lock); /* reset bus_flags in packet cb */ *(u16 *)(pkt->cb) = 0; - if (!brcmf_c_prec_enq(bus->sdiodev->dev, &bus->txq, pkt, prec)) { + if (!brcmf_sdio_prec_enq(&bus->txq, pkt, prec)) { skb_pull(pkt, bus->tx_hdrlen); brcmf_err("out of bus->txq !!!\n"); ret = -ENOSR; @@ -2797,7 +2839,7 @@ static int brcmf_sdio_bus_txdata(struct device *dev, struct sk_buff *pkt) if (pktq_len(&bus->txq) >= TXHI) { bus->txoff = true; - brcmf_txflowblock(bus->sdiodev->dev, true); + brcmf_txflowblock(dev, true); } spin_unlock_bh(&bus->txq_lock); @@ -3948,6 +3990,7 @@ static struct brcmf_bus_ops brcmf_sdio_bus_ops = { .txctl = brcmf_sdio_bus_txctl, .rxctl = brcmf_sdio_bus_rxctl, .gettxq = brcmf_sdio_bus_gettxq, + .wowl_config = brcmf_sdio_wowl_config }; static void brcmf_sdio_firmware_callback(struct device *dev, @@ -4074,7 +4117,7 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) /* platform specific configuration: * alignments must be at least 4 bytes for ADMA - */ + */ bus->head_align = ALIGNMENT; bus->sgentry_align = ALIGNMENT; if (sdiodev->pdata) { diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio.h index f2d06cae366a..8eb42620129c 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.h @@ -14,8 +14,8 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#ifndef _BRCM_SDH_H_ -#define _BRCM_SDH_H_ +#ifndef BRCMFMAC_SDIO_H +#define BRCMFMAC_SDIO_H #include <linux/skbuff.h> #include <linux/firmware.h> @@ -186,6 +186,7 @@ struct brcmf_sdio_dev { struct sg_table sgtable; char fw_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN]; char nvram_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN]; + bool wowl_enabled; }; /* sdio core registers */ @@ -334,5 +335,6 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus); void brcmf_sdio_isr(struct brcmf_sdio *bus); void brcmf_sdio_wd_timer(struct brcmf_sdio *bus, uint wdtick); +void brcmf_sdio_wowl_config(struct device *dev, bool enabled); -#endif /* _BRCM_SDH_H_ */ +#endif /* BRCMFMAC_SDIO_H */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.c b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.c index b505db48c60d..a10f35c5eb3d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.c @@ -19,4 +19,19 @@ #ifndef __CHECKER__ #define CREATE_TRACE_POINTS #include "tracepoint.h" + +void __brcmf_err(const char *func, const char *fmt, ...) +{ + struct va_format vaf = { + .fmt = fmt, + }; + va_list args; + + va_start(args, fmt); + vaf.va = &args; + pr_err("%s: %pV", func, &vaf); + trace_brcmf_err(func, &vaf); + va_end(args); +} + #endif diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index 875d1142c8b0..4572defc280f 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c @@ -23,13 +23,12 @@ #include <brcmu_utils.h> #include <brcm_hw_ids.h> #include <brcmu_wifi.h> -#include <dhd_bus.h> -#include <dhd_dbg.h> - +#include "bus.h" +#include "debug.h" #include "firmware.h" -#include "usb_rdl.h" #include "usb.h" + #define IOCTL_RESP_TIMEOUT 2000 #define BRCMF_USB_RESET_GETVER_SPINWAIT 100 /* in unit of ms */ @@ -49,6 +48,71 @@ #define BRCMF_USB_43242_FW_NAME "brcm/brcmfmac43242a.bin" #define BRCMF_USB_43569_FW_NAME "brcm/brcmfmac43569.bin" +#define TRX_MAGIC 0x30524448 /* "HDR0" */ +#define TRX_MAX_OFFSET 3 /* Max number of file offsets */ +#define TRX_UNCOMP_IMAGE 0x20 /* Trx holds uncompressed img */ +#define TRX_RDL_CHUNK 1500 /* size of each dl transfer */ +#define TRX_OFFSETS_DLFWLEN_IDX 0 + +/* Control messages: bRequest values */ +#define DL_GETSTATE 0 /* returns the rdl_state_t struct */ +#define DL_CHECK_CRC 1 /* currently unused */ +#define DL_GO 2 /* execute downloaded image */ +#define DL_START 3 /* initialize dl state */ +#define DL_REBOOT 4 /* reboot the device in 2 seconds */ +#define DL_GETVER 5 /* returns the bootrom_id_t struct */ +#define DL_GO_PROTECTED 6 /* execute the downloaded code and set reset + * event to occur in 2 seconds. It is the + * responsibility of the downloaded code to + * clear this event + */ +#define DL_EXEC 7 /* jump to a supplied address */ +#define DL_RESETCFG 8 /* To support single enum on dongle + * - Not used by bootloader + */ +#define DL_DEFER_RESP_OK 9 /* Potentially defer the response to setup + * if resp unavailable + */ + +/* states */ +#define DL_WAITING 0 /* waiting to rx first pkt */ +#define DL_READY 1 /* hdr was good, waiting for more of the + * compressed image + */ +#define DL_BAD_HDR 2 /* hdr was corrupted */ +#define DL_BAD_CRC 3 /* compressed image was corrupted */ +#define DL_RUNNABLE 4 /* download was successful,waiting for go cmd */ +#define DL_START_FAIL 5 /* failed to initialize correctly */ +#define DL_NVRAM_TOOBIG 6 /* host specified nvram data exceeds DL_NVRAM + * value + */ +#define DL_IMAGE_TOOBIG 7 /* firmware image too big */ + + +struct trx_header_le { + __le32 magic; /* "HDR0" */ + __le32 len; /* Length of file including header */ + __le32 crc32; /* CRC from flag_version to end of file */ + __le32 flag_version; /* 0:15 flags, 16:31 version */ + __le32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of + * header + */ +}; + +struct rdl_state_le { + __le32 state; + __le32 bytes; +}; + +struct bootrom_id_le { + __le32 chip; /* Chip id */ + __le32 chiprev; /* Chip rev */ + __le32 ramsize; /* Size of RAM */ + __le32 remapbase; /* Current remap base address */ + __le32 boardtype; /* Type of board */ + __le32 boardrev; /* Board revision */ +}; + struct brcmf_usb_image { struct list_head list; s8 *fwname; @@ -93,6 +157,8 @@ struct brcmf_usbdev_info { u8 ifnum; struct urb *bulk_urb; /* used for FW download */ + + bool wowl_enabled; }; static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo, @@ -600,6 +666,16 @@ static int brcmf_usb_up(struct device *dev) return 0; } +static void brcmf_cancel_all_urbs(struct brcmf_usbdev_info *devinfo) +{ + if (devinfo->ctl_urb) + usb_kill_urb(devinfo->ctl_urb); + if (devinfo->bulk_urb) + usb_kill_urb(devinfo->bulk_urb); + brcmf_usb_free_q(&devinfo->tx_postq, true); + brcmf_usb_free_q(&devinfo->rx_postq, true); +} + static void brcmf_usb_down(struct device *dev) { struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev); @@ -613,14 +689,7 @@ static void brcmf_usb_down(struct device *dev) brcmf_usb_state_change(devinfo, BRCMFMAC_USB_STATE_DOWN); - if (devinfo->ctl_urb) - usb_kill_urb(devinfo->ctl_urb); - - if (devinfo->bulk_urb) - usb_kill_urb(devinfo->bulk_urb); - brcmf_usb_free_q(&devinfo->tx_postq, true); - - brcmf_usb_free_q(&devinfo->rx_postq, true); + brcmf_cancel_all_urbs(devinfo); } static void @@ -785,7 +854,7 @@ brcmf_usb_dl_writeimage(struct brcmf_usbdev_info *devinfo, u8 *fw, int fwlen) brcmf_dbg(USB, "Enter, fw %p, len %d\n", fw, fwlen); - bulkchunk = kmalloc(RDL_CHUNK, GFP_ATOMIC); + bulkchunk = kmalloc(TRX_RDL_CHUNK, GFP_ATOMIC); if (bulkchunk == NULL) { err = -ENOMEM; goto fail; @@ -812,10 +881,10 @@ brcmf_usb_dl_writeimage(struct brcmf_usbdev_info *devinfo, u8 *fw, int fwlen) /* Wait until the usb device reports it received all * the bytes we sent */ if ((rdlbytes == sent) && (rdlbytes != dllen)) { - if ((dllen-sent) < RDL_CHUNK) + if ((dllen-sent) < TRX_RDL_CHUNK) sendlen = dllen-sent; else - sendlen = RDL_CHUNK; + sendlen = TRX_RDL_CHUNK; /* simply avoid having to send a ZLP by ensuring we * never have an even @@ -980,21 +1049,6 @@ static void brcmf_usb_detach(struct brcmf_usbdev_info *devinfo) kfree(devinfo->rx_reqs); } -#define TRX_MAGIC 0x30524448 /* "HDR0" */ -#define TRX_VERSION 1 /* Version 1 */ -#define TRX_MAX_LEN 0x3B0000 /* Max length */ -#define TRX_NO_HEADER 1 /* Do not write TRX header */ -#define TRX_MAX_OFFSET 3 /* Max number of individual files */ -#define TRX_UNCOMP_IMAGE 0x20 /* Trx contains uncompressed image */ - -struct trx_header_le { - __le32 magic; /* "HDR0" */ - __le32 len; /* Length of file including header */ - __le32 crc32; /* CRC from flag_version to end of file */ - __le32 flag_version; /* 0:15 flags, 16:31 version */ - __le32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of - * header */ -}; static int check_file(const u8 *headers) { @@ -1096,11 +1150,24 @@ error: return NULL; } +static void brcmf_usb_wowl_config(struct device *dev, bool enabled) +{ + struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev); + + brcmf_dbg(USB, "Configuring WOWL, enabled=%d\n", enabled); + devinfo->wowl_enabled = enabled; + if (enabled) + device_set_wakeup_enable(devinfo->dev, true); + else + device_set_wakeup_enable(devinfo->dev, false); +} + static struct brcmf_bus_ops brcmf_usb_bus_ops = { .txdata = brcmf_usb_tx, .stop = brcmf_usb_down, .txctl = brcmf_usb_tx_ctlpkt, .rxctl = brcmf_usb_rx_ctlpkt, + .wowl_config = brcmf_usb_wowl_config, }; static int brcmf_usb_bus_setup(struct brcmf_usbdev_info *devinfo) @@ -1188,6 +1255,9 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo) bus->ops = &brcmf_usb_bus_ops; bus->proto_type = BRCMF_PROTO_BCDC; bus->always_use_fws_queue = true; +#ifdef CONFIG_PM + bus->wowl_supported = true; +#endif if (!brcmf_usb_dlneeded(devinfo)) { ret = brcmf_usb_bus_setup(devinfo); @@ -1341,7 +1411,10 @@ static int brcmf_usb_suspend(struct usb_interface *intf, pm_message_t state) brcmf_dbg(USB, "Enter\n"); devinfo->bus_pub.state = BRCMFMAC_USB_STATE_SLEEP; - brcmf_detach(&usb->dev); + if (devinfo->wowl_enabled) + brcmf_cancel_all_urbs(devinfo); + else + brcmf_detach(&usb->dev); return 0; } @@ -1354,7 +1427,12 @@ static int brcmf_usb_resume(struct usb_interface *intf) struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev); brcmf_dbg(USB, "Enter\n"); - return brcmf_usb_bus_setup(devinfo); + if (!devinfo->wowl_enabled) + return brcmf_usb_bus_setup(devinfo); + + devinfo->bus_pub.state = BRCMFMAC_USB_STATE_UP; + brcmf_usb_rx_fill_all(devinfo); + return 0; } static int brcmf_usb_reset_resume(struct usb_interface *intf) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb_rdl.h b/drivers/net/wireless/brcm80211/brcmfmac/usb_rdl.h deleted file mode 100644 index 0a35c51c3da2..000000000000 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb_rdl.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2011 Broadcom Corporation - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef _USB_RDL_H -#define _USB_RDL_H - -/* Control messages: bRequest values */ -#define DL_GETSTATE 0 /* returns the rdl_state_t struct */ -#define DL_CHECK_CRC 1 /* currently unused */ -#define DL_GO 2 /* execute downloaded image */ -#define DL_START 3 /* initialize dl state */ -#define DL_REBOOT 4 /* reboot the device in 2 seconds */ -#define DL_GETVER 5 /* returns the bootrom_id_t struct */ -#define DL_GO_PROTECTED 6 /* execute the downloaded code and set reset - * event to occur in 2 seconds. It is the - * responsibility of the downloaded code to - * clear this event - */ -#define DL_EXEC 7 /* jump to a supplied address */ -#define DL_RESETCFG 8 /* To support single enum on dongle - * - Not used by bootloader - */ -#define DL_DEFER_RESP_OK 9 /* Potentially defer the response to setup - * if resp unavailable - */ - -/* states */ -#define DL_WAITING 0 /* waiting to rx first pkt */ -#define DL_READY 1 /* hdr was good, waiting for more of the - * compressed image */ -#define DL_BAD_HDR 2 /* hdr was corrupted */ -#define DL_BAD_CRC 3 /* compressed image was corrupted */ -#define DL_RUNNABLE 4 /* download was successful,waiting for go cmd */ -#define DL_START_FAIL 5 /* failed to initialize correctly */ -#define DL_NVRAM_TOOBIG 6 /* host specified nvram data exceeds DL_NVRAM - * value */ -#define DL_IMAGE_TOOBIG 7 /* download image too big (exceeds DATA_START - * for rdl) */ - -struct rdl_state_le { - __le32 state; - __le32 bytes; -}; - -struct bootrom_id_le { - __le32 chip; /* Chip id */ - __le32 chiprev; /* Chip rev */ - __le32 ramsize; /* Size of RAM */ - __le32 remapbase; /* Current remap base address */ - __le32 boardtype; /* Type of board */ - __le32 boardrev; /* Board revision */ -}; - -#define RDL_CHUNK 1500 /* size of each dl transfer */ - -#define TRX_OFFSETS_DLFWLEN_IDX 0 -#define TRX_OFFSETS_JUMPTO_IDX 1 -#define TRX_OFFSETS_NVM_LEN_IDX 2 - -#define TRX_OFFSETS_DLBASE_IDX 0 - -#endif /* _USB_RDL_H */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/vendor.c b/drivers/net/wireless/brcm80211/brcmfmac/vendor.c index 5960d827508c..222f26a39642 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/vendor.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/vendor.c @@ -20,10 +20,10 @@ #include <brcmu_wifi.h> #include "fwil_types.h" -#include "dhd.h" +#include "core.h" #include "p2p.h" -#include "dhd_dbg.h" -#include "wl_cfg80211.h" +#include "debug.h" +#include "cfg80211.h" #include "vendor.h" #include "fwil.h" diff --git a/drivers/net/wireless/brcm80211/brcmsmac/debug.c b/drivers/net/wireless/brcm80211/brcmsmac/debug.c index a5d4add26f41..19740c1b1566 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/debug.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/debug.c @@ -71,48 +71,148 @@ struct dentry *brcms_debugfs_get_devdir(struct brcms_pub *drvr) } static -ssize_t brcms_debugfs_hardware_read(struct file *f, char __user *data, - size_t count, loff_t *ppos) +int brcms_debugfs_hardware_read(struct seq_file *s, void *data) { - char buf[128]; - int res; - struct brcms_pub *drvr = f->private_data; - - /* only allow read from start */ - if (*ppos > 0) - return 0; - - res = scnprintf(buf, sizeof(buf), - "board vendor: %x\n" - "board type: %x\n" - "board revision: %x\n" - "board flags: %x\n" - "board flags2: %x\n" - "firmware revision: %x\n", - drvr->wlc->hw->d11core->bus->boardinfo.vendor, - drvr->wlc->hw->d11core->bus->boardinfo.type, - drvr->wlc->hw->boardrev, - drvr->wlc->hw->boardflags, - drvr->wlc->hw->boardflags2, - drvr->wlc->ucode_rev - ); - - return simple_read_from_buffer(data, count, ppos, buf, res); + struct brcms_pub *drvr = s->private; + + seq_printf(s, "board vendor: %x\n" + "board type: %x\n" + "board revision: %x\n" + "board flags: %x\n" + "board flags2: %x\n" + "firmware revision: %x\n", + drvr->wlc->hw->d11core->bus->boardinfo.vendor, + drvr->wlc->hw->d11core->bus->boardinfo.type, + drvr->wlc->hw->boardrev, + drvr->wlc->hw->boardflags, + drvr->wlc->hw->boardflags2, + drvr->wlc->ucode_rev); + + return 0; +} + +static int brcms_debugfs_macstat_read(struct seq_file *s, void *data) +{ + struct brcms_pub *drvr = s->private; + struct brcms_info *wl = drvr->ieee_hw->priv; + struct macstat stats; + int i; + + spin_lock_bh(&wl->lock); + stats = *(drvr->wlc->core->macstat_snapshot); + spin_unlock_bh(&wl->lock); + + seq_printf(s, "txallfrm: %d\n", stats.txallfrm); + seq_printf(s, "txrtsfrm: %d\n", stats.txrtsfrm); + seq_printf(s, "txctsfrm: %d\n", stats.txctsfrm); + seq_printf(s, "txackfrm: %d\n", stats.txackfrm); + seq_printf(s, "txdnlfrm: %d\n", stats.txdnlfrm); + seq_printf(s, "txbcnfrm: %d\n", stats.txbcnfrm); + seq_printf(s, "txfunfl[8]:"); + for (i = 0; i < ARRAY_SIZE(stats.txfunfl); i++) + seq_printf(s, " %d", stats.txfunfl[i]); + seq_printf(s, "\ntxtplunfl: %d\n", stats.txtplunfl); + seq_printf(s, "txphyerr: %d\n", stats.txphyerr); + seq_printf(s, "pktengrxducast: %d\n", stats.pktengrxducast); + seq_printf(s, "pktengrxdmcast: %d\n", stats.pktengrxdmcast); + seq_printf(s, "rxfrmtoolong: %d\n", stats.rxfrmtoolong); + seq_printf(s, "rxfrmtooshrt: %d\n", stats.rxfrmtooshrt); + seq_printf(s, "rxinvmachdr: %d\n", stats.rxinvmachdr); + seq_printf(s, "rxbadfcs: %d\n", stats.rxbadfcs); + seq_printf(s, "rxbadplcp: %d\n", stats.rxbadplcp); + seq_printf(s, "rxcrsglitch: %d\n", stats.rxcrsglitch); + seq_printf(s, "rxstrt: %d\n", stats.rxstrt); + seq_printf(s, "rxdfrmucastmbss: %d\n", stats.rxdfrmucastmbss); + seq_printf(s, "rxmfrmucastmbss: %d\n", stats.rxmfrmucastmbss); + seq_printf(s, "rxcfrmucast: %d\n", stats.rxcfrmucast); + seq_printf(s, "rxrtsucast: %d\n", stats.rxrtsucast); + seq_printf(s, "rxctsucast: %d\n", stats.rxctsucast); + seq_printf(s, "rxackucast: %d\n", stats.rxackucast); + seq_printf(s, "rxdfrmocast: %d\n", stats.rxdfrmocast); + seq_printf(s, "rxmfrmocast: %d\n", stats.rxmfrmocast); + seq_printf(s, "rxcfrmocast: %d\n", stats.rxcfrmocast); + seq_printf(s, "rxrtsocast: %d\n", stats.rxrtsocast); + seq_printf(s, "rxctsocast: %d\n", stats.rxctsocast); + seq_printf(s, "rxdfrmmcast: %d\n", stats.rxdfrmmcast); + seq_printf(s, "rxmfrmmcast: %d\n", stats.rxmfrmmcast); + seq_printf(s, "rxcfrmmcast: %d\n", stats.rxcfrmmcast); + seq_printf(s, "rxbeaconmbss: %d\n", stats.rxbeaconmbss); + seq_printf(s, "rxdfrmucastobss: %d\n", stats.rxdfrmucastobss); + seq_printf(s, "rxbeaconobss: %d\n", stats.rxbeaconobss); + seq_printf(s, "rxrsptmout: %d\n", stats.rxrsptmout); + seq_printf(s, "bcntxcancl: %d\n", stats.bcntxcancl); + seq_printf(s, "rxf0ovfl: %d\n", stats.rxf0ovfl); + seq_printf(s, "rxf1ovfl: %d\n", stats.rxf1ovfl); + seq_printf(s, "rxf2ovfl: %d\n", stats.rxf2ovfl); + seq_printf(s, "txsfovfl: %d\n", stats.txsfovfl); + seq_printf(s, "pmqovfl: %d\n", stats.pmqovfl); + seq_printf(s, "rxcgprqfrm: %d\n", stats.rxcgprqfrm); + seq_printf(s, "rxcgprsqovfl: %d\n", stats.rxcgprsqovfl); + seq_printf(s, "txcgprsfail: %d\n", stats.txcgprsfail); + seq_printf(s, "txcgprssuc: %d\n", stats.txcgprssuc); + seq_printf(s, "prs_timeout: %d\n", stats.prs_timeout); + seq_printf(s, "rxnack: %d\n", stats.rxnack); + seq_printf(s, "frmscons: %d\n", stats.frmscons); + seq_printf(s, "txnack: %d\n", stats.txnack); + seq_printf(s, "txglitch_nack: %d\n", stats.txglitch_nack); + seq_printf(s, "txburst: %d\n", stats.txburst); + seq_printf(s, "bphy_rxcrsglitch: %d\n", stats.bphy_rxcrsglitch); + seq_printf(s, "phywatchdog: %d\n", stats.phywatchdog); + seq_printf(s, "bphy_badplcp: %d\n", stats.bphy_badplcp); + return 0; +} + +struct brcms_debugfs_entry { + int (*read)(struct seq_file *seq, void *data); + struct brcms_pub *drvr; +}; + +static int brcms_debugfs_entry_open(struct inode *inode, struct file *f) +{ + struct brcms_debugfs_entry *entry = inode->i_private; + + return single_open(f, entry->read, entry->drvr); } -static const struct file_operations brcms_debugfs_hardware_ops = { +static const struct file_operations brcms_debugfs_def_ops = { .owner = THIS_MODULE, - .open = simple_open, - .read = brcms_debugfs_hardware_read + .open = brcms_debugfs_entry_open, + .release = single_release, + .read = seq_read, + .llseek = seq_lseek }; +static int +brcms_debugfs_add_entry(struct brcms_pub *drvr, const char *fn, + int (*read_fn)(struct seq_file *seq, void *data)) +{ + struct device *dev = &drvr->wlc->hw->d11core->dev; + struct dentry *dentry = drvr->dbgfs_dir; + struct brcms_debugfs_entry *entry; + + if (IS_ERR_OR_NULL(dentry)) + return -ENOENT; + + entry = devm_kzalloc(dev, sizeof(*entry), GFP_KERNEL); + if (!entry) + return -ENOMEM; + + entry->read = read_fn; + entry->drvr = drvr; + + dentry = debugfs_create_file(fn, S_IRUGO, dentry, entry, + &brcms_debugfs_def_ops); + + return PTR_ERR_OR_ZERO(dentry); +} + void brcms_debugfs_create_files(struct brcms_pub *drvr) { - struct dentry *dentry = drvr->dbgfs_dir; + if (IS_ERR_OR_NULL(drvr->dbgfs_dir)) + return; - if (!IS_ERR_OR_NULL(dentry)) - debugfs_create_file("hardware", S_IRUGO, dentry, - drvr, &brcms_debugfs_hardware_ops); + brcms_debugfs_add_entry(drvr, "hardware", brcms_debugfs_hardware_read); + brcms_debugfs_add_entry(drvr, "macstat", brcms_debugfs_macstat_read); } #define __brcms_fn(fn) \ diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index 43c71bfaa474..f95b52442281 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c @@ -764,7 +764,9 @@ brcms_ops_configure_filter(struct ieee80211_hw *hw, return; } -static void brcms_ops_sw_scan_start(struct ieee80211_hw *hw) +static void brcms_ops_sw_scan_start(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + const u8 *mac_addr) { struct brcms_info *wl = hw->priv; spin_lock_bh(&wl->lock); @@ -773,7 +775,8 @@ static void brcms_ops_sw_scan_start(struct ieee80211_hw *hw) return; } -static void brcms_ops_sw_scan_complete(struct ieee80211_hw *hw) +static void brcms_ops_sw_scan_complete(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) { struct brcms_info *wl = hw->priv; spin_lock_bh(&wl->lock); diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c index 1b474828d5b8..738cfaca1e0f 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c @@ -1009,8 +1009,7 @@ brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs) if (txh) trace_brcms_txdesc(&wlc->hw->d11core->dev, txh, sizeof(*txh)); - if (p) - brcmu_pkt_buf_free_skb(p); + brcmu_pkt_buf_free_skb(p); } if (dma && queue < NFIFO) { @@ -3081,7 +3080,7 @@ static bool brcms_c_ps_allowed(struct brcms_c_info *wlc) static void brcms_c_statsupd(struct brcms_c_info *wlc) { int i; - struct macstat macstats; + struct macstat *macstats; #ifdef DEBUG u16 delta; u16 rxf0ovfl; @@ -3092,31 +3091,31 @@ static void brcms_c_statsupd(struct brcms_c_info *wlc) if (!wlc->pub->up) return; + macstats = wlc->core->macstat_snapshot; + #ifdef DEBUG /* save last rx fifo 0 overflow count */ - rxf0ovfl = wlc->core->macstat_snapshot->rxf0ovfl; + rxf0ovfl = macstats->rxf0ovfl; /* save last tx fifo underflow count */ for (i = 0; i < NFIFO; i++) - txfunfl[i] = wlc->core->macstat_snapshot->txfunfl[i]; + txfunfl[i] = macstats->txfunfl[i]; #endif /* DEBUG */ /* Read mac stats from contiguous shared memory */ - brcms_b_copyfrom_objmem(wlc->hw, M_UCODE_MACSTAT, &macstats, - sizeof(struct macstat), OBJADDR_SHM_SEL); + brcms_b_copyfrom_objmem(wlc->hw, M_UCODE_MACSTAT, macstats, + sizeof(*macstats), OBJADDR_SHM_SEL); #ifdef DEBUG /* check for rx fifo 0 overflow */ - delta = (u16) (wlc->core->macstat_snapshot->rxf0ovfl - rxf0ovfl); + delta = (u16)(macstats->rxf0ovfl - rxf0ovfl); if (delta) brcms_err(wlc->hw->d11core, "wl%d: %u rx fifo 0 overflows!\n", wlc->pub->unit, delta); /* check for tx fifo underflows */ for (i = 0; i < NFIFO; i++) { - delta = - (u16) (wlc->core->macstat_snapshot->txfunfl[i] - - txfunfl[i]); + delta = macstats->txfunfl[i] - txfunfl[i]; if (delta) brcms_err(wlc->hw->d11core, "wl%d: %u tx fifo %d underflows!\n", diff --git a/drivers/net/wireless/cw1200/scan.c b/drivers/net/wireless/cw1200/scan.c index b2fb6c632092..f2e276faca70 100644 --- a/drivers/net/wireless/cw1200/scan.c +++ b/drivers/net/wireless/cw1200/scan.c @@ -78,7 +78,7 @@ int cw1200_hw_scan(struct ieee80211_hw *hw, if (req->n_ssids > WSM_SCAN_MAX_NUM_OF_SSIDS) return -EINVAL; - frame.skb = ieee80211_probereq_get(hw, priv->vif, NULL, 0, + frame.skb = ieee80211_probereq_get(hw, priv->vif->addr, NULL, 0, req->ie_len); if (!frame.skb) return -ENOMEM; diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index edc344334a75..67cad9b05ad8 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -1363,7 +1363,7 @@ static ssize_t show_cmd_log(struct device *d, if (!priv->cmdlog) return 0; for (i = (priv->cmdlog_pos + 1) % priv->cmdlog_len; - (i != priv->cmdlog_pos) && (PAGE_SIZE - len); + (i != priv->cmdlog_pos) && (len < PAGE_SIZE); i = (i + 1) % priv->cmdlog_len) { len += snprintf(buf + len, PAGE_SIZE - len, diff --git a/drivers/net/wireless/ipw2x00/libipw.h b/drivers/net/wireless/ipw2x00/libipw.h index 5ce2f59d3378..b0571618c2ed 100644 --- a/drivers/net/wireless/ipw2x00/libipw.h +++ b/drivers/net/wireless/ipw2x00/libipw.h @@ -654,10 +654,6 @@ struct libipw_network { /* TPC Report - mandatory if spctrm mgmt required */ struct libipw_tpc_report tpc_report; - /* IBSS DFS - mandatory if spctrm mgmt required and IBSS - * NOTE: This is variable length and so must be allocated dynamically */ - struct libipw_ibss_dfs *ibss_dfs; - /* Channel Switch Announcement - optional if spctrm mgmt required */ struct libipw_csa csa; @@ -970,7 +966,6 @@ int libipw_rx(struct libipw_device *ieee, struct sk_buff *skb, /* make sure to set stats->len */ void libipw_rx_mgt(struct libipw_device *ieee, struct libipw_hdr_4addr *header, struct libipw_rx_stats *stats); -void libipw_network_reset(struct libipw_network *network); /* libipw_geo.c */ const struct libipw_geo *libipw_get_geo(struct libipw_device *ieee); diff --git a/drivers/net/wireless/ipw2x00/libipw_module.c b/drivers/net/wireless/ipw2x00/libipw_module.c index 5f31b72a4921..60f28740f6af 100644 --- a/drivers/net/wireless/ipw2x00/libipw_module.c +++ b/drivers/net/wireless/ipw2x00/libipw_module.c @@ -84,25 +84,12 @@ static int libipw_networks_allocate(struct libipw_device *ieee) return 0; } -void libipw_network_reset(struct libipw_network *network) -{ - if (!network) - return; - - if (network->ibss_dfs) { - kfree(network->ibss_dfs); - network->ibss_dfs = NULL; - } -} - static inline void libipw_networks_free(struct libipw_device *ieee) { int i; - for (i = 0; i < MAX_NETWORK_COUNT; i++) { - kfree(ieee->networks[i]->ibss_dfs); + for (i = 0; i < MAX_NETWORK_COUNT; i++) kfree(ieee->networks[i]); - } } void libipw_networks_age(struct libipw_device *ieee, diff --git a/drivers/net/wireless/ipw2x00/libipw_rx.c b/drivers/net/wireless/ipw2x00/libipw_rx.c index 2d66984079bb..a6877dd6ba73 100644 --- a/drivers/net/wireless/ipw2x00/libipw_rx.c +++ b/drivers/net/wireless/ipw2x00/libipw_rx.c @@ -1298,13 +1298,6 @@ static int libipw_parse_info_param(struct libipw_info_element break; case WLAN_EID_IBSS_DFS: - if (network->ibss_dfs) - break; - network->ibss_dfs = kmemdup(info_element->data, - info_element->len, - GFP_ATOMIC); - if (!network->ibss_dfs) - return 1; network->flags |= NETWORK_HAS_IBSS_DFS; break; @@ -1335,9 +1328,7 @@ static int libipw_parse_info_param(struct libipw_info_element static int libipw_handle_assoc_resp(struct libipw_device *ieee, struct libipw_assoc_response *frame, struct libipw_rx_stats *stats) { - struct libipw_network network_resp = { - .ibss_dfs = NULL, - }; + struct libipw_network network_resp = { }; struct libipw_network *network = &network_resp; struct net_device *dev = ieee->dev; @@ -1472,9 +1463,6 @@ static void update_network(struct libipw_network *dst, int qos_active; u8 old_param; - libipw_network_reset(dst); - dst->ibss_dfs = src->ibss_dfs; - /* We only update the statistics if they were created by receiving * the network information on the actual channel the network is on. * @@ -1548,9 +1536,7 @@ static void libipw_process_probe_response(struct libipw_device *stats) { struct net_device *dev = ieee->dev; - struct libipw_network network = { - .ibss_dfs = NULL, - }; + struct libipw_network network = { }; struct libipw_network *target; struct libipw_network *oldest = NULL; #ifdef CONFIG_LIBIPW_DEBUG @@ -1618,7 +1604,6 @@ static void libipw_process_probe_response(struct libipw_device LIBIPW_DEBUG_SCAN("Expired '%*pE' (%pM) from network list.\n", target->ssid_len, target->ssid, target->bssid); - libipw_network_reset(target); } else { /* Otherwise just pull from the free list */ target = list_entry(ieee->network_free_list.next, @@ -1634,7 +1619,6 @@ static void libipw_process_probe_response(struct libipw_device "BEACON" : "PROBE RESPONSE"); #endif memcpy(target, &network, sizeof(*target)); - network.ibss_dfs = NULL; list_add_tail(&target->list, &ieee->network_list); } else { LIBIPW_DEBUG_SCAN("Updating '%*pE' (%pM) via %s.\n", @@ -1643,7 +1627,6 @@ static void libipw_process_probe_response(struct libipw_device is_beacon(beacon->header.frame_ctl) ? "BEACON" : "PROBE RESPONSE"); update_network(target, &network); - network.ibss_dfs = NULL; } spin_unlock_irqrestore(&ieee->lock, flags); diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 26fec54dcd03..2748fde4b90c 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -6063,7 +6063,7 @@ il4965_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, } void -il4965_mac_channel_switch(struct ieee80211_hw *hw, +il4965_mac_channel_switch(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_channel_switch *ch_switch) { struct il_priv *il = hw->priv; diff --git a/drivers/net/wireless/iwlegacy/4965.h b/drivers/net/wireless/iwlegacy/4965.h index 337dfcf3bbde..3a57f71b8ed5 100644 --- a/drivers/net/wireless/iwlegacy/4965.h +++ b/drivers/net/wireless/iwlegacy/4965.h @@ -187,8 +187,9 @@ int il4965_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u8 buf_size); int il4965_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta); -void il4965_mac_channel_switch(struct ieee80211_hw *hw, - struct ieee80211_channel_switch *ch_switch); +void +il4965_mac_channel_switch(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_channel_switch *ch_switch); void il4965_led_enable(struct il_priv *il); diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index 267e48a2915e..139de90c2aaf 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -59,6 +59,7 @@ config IWLDVM config IWLMVM tristate "Intel Wireless WiFi MVM Firmware support" + select BACKPORT_WANT_DEV_COREDUMP help This is the driver that supports the MVM firmware which is currently only available for 7260 and 3160 devices. diff --git a/drivers/net/wireless/iwlwifi/dvm/lib.c b/drivers/net/wireless/iwlwifi/dvm/lib.c index 2191621d69c1..02e4ede2b042 100644 --- a/drivers/net/wireless/iwlwifi/dvm/lib.c +++ b/drivers/net/wireless/iwlwifi/dvm/lib.c @@ -418,8 +418,8 @@ void iwlagn_bt_adjust_rssi_monitor(struct iwl_priv *priv, bool rssi_ena) static bool iwlagn_bt_traffic_is_sco(struct iwl_bt_uart_msg *uart_msg) { - return BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3 >> - BT_UART_MSG_FRAME3SCOESCO_POS; + return (BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3) >> + BT_UART_MSG_FRAME3SCOESCO_POS; } static void iwlagn_bt_traffic_change_work(struct work_struct *work) diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index cae692ff1013..47e64e8b9517 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c @@ -941,6 +941,7 @@ static int iwlagn_mac_sta_state(struct ieee80211_hw *hw, } static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, struct ieee80211_channel_switch *ch_switch) { struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); diff --git a/drivers/net/wireless/iwlwifi/iwl-8000.c b/drivers/net/wireless/iwlwifi/iwl-8000.c index d2b7234b1c73..896ea906549c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-8000.c +++ b/drivers/net/wireless/iwlwifi/iwl-8000.c @@ -104,6 +104,7 @@ static const struct iwl_base_params iwl8000_base_params = { }; static const struct iwl_ht_params iwl8000_ht_params = { + .stbc = true, .ldpc = true, .ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ), }; diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h index 2ef83a39ff10..f8aa9cf08279 100644 --- a/drivers/net/wireless/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/iwlwifi/iwl-config.h @@ -87,6 +87,16 @@ enum iwl_device_family { IWL_DEVICE_FAMILY_8000, }; +static inline bool iwl_has_secure_boot(u32 hw_rev, + enum iwl_device_family family) +{ + /* return 1 only for family 8000 B0 */ + if ((family == IWL_DEVICE_FAMILY_8000) && (hw_rev & 0xC)) + return 1; + + return 0; +} + /* * LED mode * IWL_LED_DEFAULT: use device default @@ -246,6 +256,7 @@ struct iwl_pwr_tx_backoff { * @nvm_hw_section_num: the ID of the HW NVM section * @pwr_tx_backoffs: translation table between power limits and backoffs * @max_rx_agg_size: max RX aggregation size of the ADDBA request/response + * @max_tx_agg_size: max TX aggregation size of the ADDBA request/response * * We enable the driver to be backward compatible wrt. hardware features. * API differences in uCode shouldn't be handled here but through TLVs @@ -285,6 +296,7 @@ struct iwl_cfg { const char *default_nvm_file; unsigned int max_rx_agg_size; bool disable_dummy_notification; + unsigned int max_tx_agg_size; }; /* diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index 0f1084f09caa..d9fa8e034da2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c @@ -807,19 +807,16 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_REGULAR, tlv_len); drv->fw.mvm_fw = true; - drv->fw.img[IWL_UCODE_REGULAR].is_secure = true; break; case IWL_UCODE_TLV_SECURE_SEC_INIT: iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_INIT, tlv_len); drv->fw.mvm_fw = true; - drv->fw.img[IWL_UCODE_INIT].is_secure = true; break; case IWL_UCODE_TLV_SECURE_SEC_WOWLAN: iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_WOWLAN, tlv_len); drv->fw.mvm_fw = true; - drv->fw.img[IWL_UCODE_WOWLAN].is_secure = true; break; case IWL_UCODE_TLV_NUM_OF_CPU: if (tlv_len != sizeof(u32)) diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h index b894a84e8393..649fdae77383 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw.h @@ -229,7 +229,6 @@ struct fw_desc { struct fw_img { struct fw_desc sec[IWL_UCODE_SECTION_MAX]; - bool is_secure; bool is_dual_cpus; }; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index d8fc548c0d6c..0768f83e709d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -535,9 +535,7 @@ struct iwl_trans_ops { void (*ref)(struct iwl_trans *trans); void (*unref)(struct iwl_trans *trans); -#ifdef CONFIG_IWLWIFI_DEBUGFS struct iwl_trans_dump_data *(*dump_data)(struct iwl_trans *trans); -#endif }; /** @@ -704,7 +702,6 @@ static inline void iwl_trans_unref(struct iwl_trans *trans) trans->ops->unref(trans); } -#ifdef CONFIG_IWLWIFI_DEBUGFS static inline struct iwl_trans_dump_data * iwl_trans_dump_data(struct iwl_trans *trans) { @@ -712,7 +709,6 @@ iwl_trans_dump_data(struct iwl_trans *trans) return NULL; return trans->ops->dump_data(trans); } -#endif static inline int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) diff --git a/drivers/net/wireless/iwlwifi/mvm/coex.c b/drivers/net/wireless/iwlwifi/mvm/coex.c index da2ffb785194..508c81359e41 100644 --- a/drivers/net/wireless/iwlwifi/mvm/coex.c +++ b/drivers/net/wireless/iwlwifi/mvm/coex.c @@ -72,8 +72,6 @@ #include "mvm.h" #include "iwl-debug.h" -#define BT_ANTENNA_COUPLING_THRESHOLD (30) - const u32 iwl_bt_ctl_kill_msk[BT_KILL_MSK_MAX] = { [BT_KILL_MSK_DEFAULT] = 0xfffffc00, [BT_KILL_MSK_NEVER] = 0xffffffff, @@ -302,11 +300,6 @@ static const __le64 iwl_ci_mask[][3] = { }, }; -static const __le32 iwl_bt_mprio_lut[BT_COEX_MULTI_PRIO_LUT_SIZE] = { - cpu_to_le32(0x2e402280), - cpu_to_le32(0x7711a751), -}; - struct corunning_block_luts { u8 range; __le32 lut20[BT_COEX_CORUN_LUT_SIZE]; @@ -605,7 +598,7 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm) bt_cmd->max_kill = cpu_to_le32(5); bt_cmd->bt4_antenna_isolation_thr = - cpu_to_le32(BT_ANTENNA_COUPLING_THRESHOLD); + cpu_to_le32(IWL_MVM_BT_COEX_ANTENNA_COUPLING_THRS); bt_cmd->bt4_tx_tx_delta_freq_thr = cpu_to_le32(15); bt_cmd->bt4_tx_rx_max_freq0 = cpu_to_le32(15); bt_cmd->override_primary_lut = cpu_to_le32(BT_COEX_INVALID_LUT); @@ -638,8 +631,8 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm) memcpy(&bt_cmd->mplut_prio_boost, iwl_bt_prio_boost, sizeof(iwl_bt_prio_boost)); - memcpy(&bt_cmd->multiprio_lut, iwl_bt_mprio_lut, - sizeof(iwl_bt_mprio_lut)); + bt_cmd->multiprio_lut[0] = cpu_to_le32(IWL_MVM_BT_COEX_MPLUT_REG0); + bt_cmd->multiprio_lut[1] = cpu_to_le32(IWL_MVM_BT_COEX_MPLUT_REG1); send_cmd: memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif)); diff --git a/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c b/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c index 8a1d2f33d5b7..b571e1b0550c 100644 --- a/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c +++ b/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c @@ -102,8 +102,6 @@ static const u8 iwl_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = { #undef EVENT_PRIO_ANT -#define BT_ANTENNA_COUPLING_THRESHOLD (30) - static int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm) { if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS)) @@ -290,11 +288,6 @@ static const __le64 iwl_ci_mask[][3] = { }, }; -static const __le32 iwl_bt_mprio_lut[BT_COEX_MULTI_PRIO_LUT_SIZE] = { - cpu_to_le32(0x2e402280), - cpu_to_le32(0x7711a751), -}; - struct corunning_block_luts { u8 range; __le32 lut20[BT_COEX_CORUN_LUT_SIZE]; @@ -593,7 +586,8 @@ int iwl_send_bt_init_conf_old(struct iwl_mvm *mvm) } bt_cmd->max_kill = 5; - bt_cmd->bt4_antenna_isolation_thr = BT_ANTENNA_COUPLING_THRESHOLD; + bt_cmd->bt4_antenna_isolation_thr = + IWL_MVM_BT_COEX_ANTENNA_COUPLING_THRS; bt_cmd->bt4_antenna_isolation = iwlwifi_mod_params.ant_coupling; bt_cmd->bt4_tx_tx_delta_freq_thr = 15; bt_cmd->bt4_tx_rx_max_freq0 = 15; @@ -649,8 +643,8 @@ int iwl_send_bt_init_conf_old(struct iwl_mvm *mvm) memcpy(&bt_cmd->bt_prio_boost, iwl_bt_prio_boost, sizeof(iwl_bt_prio_boost)); - memcpy(&bt_cmd->bt4_multiprio_lut, iwl_bt_mprio_lut, - sizeof(iwl_bt_mprio_lut)); + bt_cmd->bt4_multiprio_lut[0] = cpu_to_le32(IWL_MVM_BT_COEX_MPLUT_REG0); + bt_cmd->bt4_multiprio_lut[1] = cpu_to_le32(IWL_MVM_BT_COEX_MPLUT_REG1); send_cmd: memset(&mvm->last_bt_notif_old, 0, sizeof(mvm->last_bt_notif_old)); diff --git a/drivers/net/wireless/iwlwifi/mvm/constants.h b/drivers/net/wireless/iwlwifi/mvm/constants.h index d4dfbe4cb66d..5c1ea80d5e3b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/constants.h +++ b/drivers/net/wireless/iwlwifi/mvm/constants.h @@ -92,8 +92,13 @@ #define IWL_MVM_BT_COEX_SYNC2SCO 1 #define IWL_MVM_BT_COEX_CORUNNING 0 #define IWL_MVM_BT_COEX_MPLUT 1 +#define IWL_MVM_BT_COEX_MPLUT_REG0 0x2e402280 +#define IWL_MVM_BT_COEX_MPLUT_REG1 0x7711a751 +#define IWL_MVM_BT_COEX_ANTENNA_COUPLING_THRS 30 #define IWL_MVM_FW_MCAST_FILTER_PASS_ALL 0 +#define IWL_MVM_FW_BCAST_FILTER_PASS_ALL 0 #define IWL_MVM_QUOTA_THRESHOLD 8 #define IWL_MVM_RS_RSSI_BASED_INIT_RATE 0 +#define IWL_MVM_RS_DISABLE_MIMO 0 #endif /* __MVM_CONSTANTS_H */ diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c index c17be0fb7283..3bbb511b0b38 100644 --- a/drivers/net/wireless/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/iwlwifi/mvm/d3.c @@ -601,33 +601,6 @@ static int iwl_mvm_send_remote_wake_cfg(struct iwl_mvm *mvm, return ret; } -struct iwl_d3_iter_data { - struct iwl_mvm *mvm; - struct ieee80211_vif *vif; - bool error; -}; - -static void iwl_mvm_d3_iface_iterator(void *_data, u8 *mac, - struct ieee80211_vif *vif) -{ - struct iwl_d3_iter_data *data = _data; - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - - if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) - return; - - if (mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT) - return; - - if (data->vif) { - IWL_ERR(data->mvm, "More than one managed interface active!\n"); - data->error = true; - return; - } - - data->vif = vif; -} - static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct ieee80211_sta *ap_sta) { @@ -783,6 +756,35 @@ void iwl_mvm_set_last_nonqos_seq(struct iwl_mvm *mvm, struct ieee80211_vif *vif) IWL_ERR(mvm, "failed to set non-QoS seqno\n"); } +static int iwl_mvm_switch_to_d3(struct iwl_mvm *mvm) +{ + iwl_mvm_cancel_scan(mvm); + + iwl_trans_stop_device(mvm->trans); + + /* + * Set the HW restart bit -- this is mostly true as we're + * going to load new firmware and reprogram that, though + * the reprogramming is going to be manual to avoid adding + * all the MACs that aren't support. + * We don't have to clear up everything though because the + * reprogramming is manual. When we resume, we'll actually + * go through a proper restart sequence again to switch + * back to the runtime firmware image. + */ + set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status); + + /* We reprogram keys and shouldn't allocate new key indices */ + memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table)); + + mvm->ptk_ivlen = 0; + mvm->ptk_icvlen = 0; + mvm->ptk_ivlen = 0; + mvm->ptk_icvlen = 0; + + return iwl_mvm_load_d3_fw(mvm); +} + static int iwl_mvm_send_wowlan_config_cmd(struct iwl_mvm *mvm, const struct iwl_wowlan_config_cmd_v3 *cmd) @@ -797,116 +799,52 @@ iwl_mvm_send_wowlan_config_cmd(struct iwl_mvm *mvm, cmd_len, cmd); } -static int __iwl_mvm_suspend(struct ieee80211_hw *hw, - struct cfg80211_wowlan *wowlan, - bool test) +static int +iwl_mvm_get_wowlan_config(struct iwl_mvm *mvm, + struct cfg80211_wowlan *wowlan, + struct iwl_wowlan_config_cmd_v3 *wowlan_config_cmd, + struct ieee80211_vif *vif, struct iwl_mvm_vif *mvmvif, + struct ieee80211_sta *ap_sta) { - struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); - struct iwl_d3_iter_data suspend_iter_data = { - .mvm = mvm, - }; - struct ieee80211_vif *vif; - struct iwl_mvm_vif *mvmvif; - struct ieee80211_sta *ap_sta; - struct iwl_mvm_sta *mvm_ap_sta; - struct iwl_wowlan_config_cmd_v3 wowlan_config_cmd = {}; - struct iwl_wowlan_kek_kck_material_cmd kek_kck_cmd = {}; - struct iwl_wowlan_tkip_params_cmd tkip_cmd = {}; - struct iwl_d3_manager_config d3_cfg_cmd_data = { - /* - * Program the minimum sleep time to 10 seconds, as many - * platforms have issues processing a wakeup signal while - * still being in the process of suspending. - */ - .min_sleep_time = cpu_to_le32(10 * 1000 * 1000), - }; - struct iwl_host_cmd d3_cfg_cmd = { - .id = D3_CONFIG_CMD, - .flags = CMD_WANT_SKB, - .data[0] = &d3_cfg_cmd_data, - .len[0] = sizeof(d3_cfg_cmd_data), - }; - struct wowlan_key_data key_data = { - .use_rsc_tsc = false, - .tkip = &tkip_cmd, - .use_tkip = false, - }; int ret; - int len __maybe_unused; - - if (!wowlan) { - /* - * mac80211 shouldn't get here, but for D3 test - * it doesn't warrant a warning - */ - WARN_ON(!test); - return -EINVAL; - } - - key_data.rsc_tsc = kzalloc(sizeof(*key_data.rsc_tsc), GFP_KERNEL); - if (!key_data.rsc_tsc) - return -ENOMEM; - - mutex_lock(&mvm->mutex); - - /* see if there's only a single BSS vif and it's associated */ - ieee80211_iterate_active_interfaces_atomic( - mvm->hw, IEEE80211_IFACE_ITER_NORMAL, - iwl_mvm_d3_iface_iterator, &suspend_iter_data); - - if (suspend_iter_data.error || !suspend_iter_data.vif) { - ret = 1; - goto out_noreset; - } - - vif = suspend_iter_data.vif; - mvmvif = iwl_mvm_vif_from_mac80211(vif); - - ap_sta = rcu_dereference_protected( - mvm->fw_id_to_mac_id[mvmvif->ap_sta_id], - lockdep_is_held(&mvm->mutex)); - if (IS_ERR_OR_NULL(ap_sta)) { - ret = -EINVAL; - goto out_noreset; - } - - mvm_ap_sta = (struct iwl_mvm_sta *)ap_sta->drv_priv; + struct iwl_mvm_sta *mvm_ap_sta = (struct iwl_mvm_sta *)ap_sta->drv_priv; - /* TODO: wowlan_config_cmd.common.wowlan_ba_teardown_tids */ + /* TODO: wowlan_config_cmd->common.wowlan_ba_teardown_tids */ - wowlan_config_cmd.common.is_11n_connection = + wowlan_config_cmd->common.is_11n_connection = ap_sta->ht_cap.ht_supported; /* Query the last used seqno and set it */ ret = iwl_mvm_get_last_nonqos_seq(mvm, vif); if (ret < 0) - goto out_noreset; - wowlan_config_cmd.common.non_qos_seq = cpu_to_le16(ret); + return ret; - iwl_mvm_set_wowlan_qos_seq(mvm_ap_sta, &wowlan_config_cmd.common); + wowlan_config_cmd->common.non_qos_seq = cpu_to_le16(ret); + + iwl_mvm_set_wowlan_qos_seq(mvm_ap_sta, &wowlan_config_cmd->common); if (wowlan->disconnect) - wowlan_config_cmd.common.wakeup_filter |= + wowlan_config_cmd->common.wakeup_filter |= cpu_to_le32(IWL_WOWLAN_WAKEUP_BEACON_MISS | IWL_WOWLAN_WAKEUP_LINK_CHANGE); if (wowlan->magic_pkt) - wowlan_config_cmd.common.wakeup_filter |= + wowlan_config_cmd->common.wakeup_filter |= cpu_to_le32(IWL_WOWLAN_WAKEUP_MAGIC_PACKET); if (wowlan->gtk_rekey_failure) - wowlan_config_cmd.common.wakeup_filter |= + wowlan_config_cmd->common.wakeup_filter |= cpu_to_le32(IWL_WOWLAN_WAKEUP_GTK_REKEY_FAIL); if (wowlan->eap_identity_req) - wowlan_config_cmd.common.wakeup_filter |= + wowlan_config_cmd->common.wakeup_filter |= cpu_to_le32(IWL_WOWLAN_WAKEUP_EAP_IDENT_REQ); if (wowlan->four_way_handshake) - wowlan_config_cmd.common.wakeup_filter |= + wowlan_config_cmd->common.wakeup_filter |= cpu_to_le32(IWL_WOWLAN_WAKEUP_4WAY_HANDSHAKE); if (wowlan->n_patterns) - wowlan_config_cmd.common.wakeup_filter |= + wowlan_config_cmd->common.wakeup_filter |= cpu_to_le32(IWL_WOWLAN_WAKEUP_PATTERN_MATCH); if (wowlan->rfkill_release) - wowlan_config_cmd.common.wakeup_filter |= + wowlan_config_cmd->common.wakeup_filter |= cpu_to_le32(IWL_WOWLAN_WAKEUP_RF_KILL_DEASSERT); if (wowlan->tcp) { @@ -914,44 +852,39 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, * Set the "link change" (really "link lost") flag as well * since that implies losing the TCP connection. */ - wowlan_config_cmd.common.wakeup_filter |= + wowlan_config_cmd->common.wakeup_filter |= cpu_to_le32(IWL_WOWLAN_WAKEUP_REMOTE_LINK_LOSS | IWL_WOWLAN_WAKEUP_REMOTE_SIGNATURE_TABLE | IWL_WOWLAN_WAKEUP_REMOTE_WAKEUP_PACKET | IWL_WOWLAN_WAKEUP_LINK_CHANGE); } - iwl_mvm_cancel_scan(mvm); - - iwl_trans_stop_device(mvm->trans); - - /* - * Set the HW restart bit -- this is mostly true as we're - * going to load new firmware and reprogram that, though - * the reprogramming is going to be manual to avoid adding - * all the MACs that aren't support. - * We don't have to clear up everything though because the - * reprogramming is manual. When we resume, we'll actually - * go through a proper restart sequence again to switch - * back to the runtime firmware image. - */ - set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status); - - /* We reprogram keys and shouldn't allocate new key indices */ - memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table)); - - mvm->ptk_ivlen = 0; - mvm->ptk_icvlen = 0; - mvm->ptk_ivlen = 0; - mvm->ptk_icvlen = 0; + return 0; +} - ret = iwl_mvm_load_d3_fw(mvm); - if (ret) - goto out; +static int +iwl_mvm_wowlan_config(struct iwl_mvm *mvm, + struct cfg80211_wowlan *wowlan, + struct iwl_wowlan_config_cmd_v3 *wowlan_config_cmd, + struct ieee80211_vif *vif, struct iwl_mvm_vif *mvmvif, + struct ieee80211_sta *ap_sta) +{ + struct iwl_wowlan_kek_kck_material_cmd kek_kck_cmd = {}; + struct iwl_wowlan_tkip_params_cmd tkip_cmd = {}; + struct wowlan_key_data key_data = { + .use_rsc_tsc = false, + .tkip = &tkip_cmd, + .use_tkip = false, + }; + int ret; ret = iwl_mvm_d3_reprogram(mvm, vif, ap_sta); if (ret) - goto out; + return ret; + + key_data.rsc_tsc = kzalloc(sizeof(*key_data.rsc_tsc), GFP_KERNEL); + if (!key_data.rsc_tsc) + return -ENOMEM; if (!iwlwifi_mod_params.sw_crypto) { /* @@ -1010,7 +943,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, } } - ret = iwl_mvm_send_wowlan_config_cmd(mvm, &wowlan_config_cmd); + ret = iwl_mvm_send_wowlan_config_cmd(mvm, wowlan_config_cmd); if (ret) goto out; @@ -1023,8 +956,93 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, goto out; ret = iwl_mvm_send_remote_wake_cfg(mvm, vif, wowlan->tcp); - if (ret) - goto out; + +out: + kfree(key_data.rsc_tsc); + return ret; +} + +static int __iwl_mvm_suspend(struct ieee80211_hw *hw, + struct cfg80211_wowlan *wowlan, + bool test) +{ + struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); + struct ieee80211_vif *vif = NULL; + struct iwl_mvm_vif *mvmvif = NULL; + struct ieee80211_sta *ap_sta = NULL; + struct iwl_wowlan_config_cmd_v3 wowlan_config_cmd = {}; + struct iwl_d3_manager_config d3_cfg_cmd_data = { + /* + * Program the minimum sleep time to 10 seconds, as many + * platforms have issues processing a wakeup signal while + * still being in the process of suspending. + */ + .min_sleep_time = cpu_to_le32(10 * 1000 * 1000), + }; + struct iwl_host_cmd d3_cfg_cmd = { + .id = D3_CONFIG_CMD, + .flags = CMD_WANT_SKB, + .data[0] = &d3_cfg_cmd_data, + .len[0] = sizeof(d3_cfg_cmd_data), + }; + int ret; + int len __maybe_unused; + + if (!wowlan) { + /* + * mac80211 shouldn't get here, but for D3 test + * it doesn't warrant a warning + */ + WARN_ON(!test); + return -EINVAL; + } + + mutex_lock(&mvm->mutex); + + vif = iwl_mvm_get_bss_vif(mvm); + if (IS_ERR_OR_NULL(vif)) { + ret = 1; + goto out_noreset; + } + + mvmvif = iwl_mvm_vif_from_mac80211(vif); + + /* if we're associated, this is wowlan */ + if (mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) { + ap_sta = rcu_dereference_protected( + mvm->fw_id_to_mac_id[mvmvif->ap_sta_id], + lockdep_is_held(&mvm->mutex)); + if (IS_ERR_OR_NULL(ap_sta)) { + ret = -EINVAL; + goto out_noreset; + } + + ret = iwl_mvm_get_wowlan_config(mvm, wowlan, &wowlan_config_cmd, + vif, mvmvif, ap_sta); + if (ret) + goto out_noreset; + + ret = iwl_mvm_switch_to_d3(mvm); + if (ret) + goto out; + + ret = iwl_mvm_wowlan_config(mvm, wowlan, &wowlan_config_cmd, + vif, mvmvif, ap_sta); + if (ret) + goto out; + } else if (mvm->nd_config) { + ret = iwl_mvm_switch_to_d3(mvm); + if (ret) + goto out; + + ret = iwl_mvm_scan_offload_start(mvm, vif, mvm->nd_config, + mvm->nd_ies); + if (ret) + goto out; + } else { + ret = 1; + goto out_noreset; + } ret = iwl_mvm_power_update_device(mvm); if (ret) @@ -1060,8 +1078,6 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, if (ret < 0) ieee80211_restart_hw(mvm->hw); out_noreset: - kfree(key_data.rsc_tsc); - mutex_unlock(&mvm->mutex); return ret; @@ -1592,9 +1608,6 @@ static void iwl_mvm_d3_disconnect_iter(void *data, u8 *mac, static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) { - struct iwl_d3_iter_data resume_iter_data = { - .mvm = mvm, - }; struct ieee80211_vif *vif = NULL; int ret; enum iwl_d3_status d3_status; @@ -1603,15 +1616,10 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) mutex_lock(&mvm->mutex); /* get the BSS vif pointer again */ - ieee80211_iterate_active_interfaces_atomic( - mvm->hw, IEEE80211_IFACE_ITER_NORMAL, - iwl_mvm_d3_iface_iterator, &resume_iter_data); - - if (WARN_ON(resume_iter_data.error || !resume_iter_data.vif)) + vif = iwl_mvm_get_bss_vif(mvm); + if (IS_ERR_OR_NULL(vif)) goto out_unlock; - vif = resume_iter_data.vif; - ret = iwl_trans_d3_resume(mvm->trans, &d3_status, test); if (ret) goto out_unlock; @@ -1741,7 +1749,9 @@ static int iwl_mvm_d3_test_release(struct inode *inode, struct file *file) int remaining_time = 10; mvm->d3_test_active = false; + rtnl_lock(); __iwl_mvm_resume(mvm, true); + rtnl_unlock(); iwl_abort_notification_waits(&mvm->notif_wait); ieee80211_restart_hw(mvm->hw); diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index 50527a9bb267..51b7116965ed 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c @@ -121,78 +121,6 @@ static ssize_t iwl_dbgfs_sta_drain_write(struct iwl_mvm *mvm, char *buf, return ret; } -static int iwl_dbgfs_fw_error_dump_open(struct inode *inode, struct file *file) -{ - struct iwl_mvm *mvm = inode->i_private; - int ret; - - if (!mvm) - return -EINVAL; - - mutex_lock(&mvm->mutex); - if (!mvm->fw_error_dump) { - ret = -ENODATA; - goto out; - } - - file->private_data = mvm->fw_error_dump; - mvm->fw_error_dump = NULL; - ret = 0; - -out: - mutex_unlock(&mvm->mutex); - return ret; -} - -static ssize_t iwl_dbgfs_fw_error_dump_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_mvm_dump_ptrs *dump_ptrs = (void *)file->private_data; - ssize_t bytes_read = 0; - ssize_t bytes_read_trans = 0; - - if (*ppos < dump_ptrs->op_mode_len) - bytes_read += - simple_read_from_buffer(user_buf, count, ppos, - dump_ptrs->op_mode_ptr, - dump_ptrs->op_mode_len); - - if (bytes_read < 0 || *ppos < dump_ptrs->op_mode_len) - return bytes_read; - - if (dump_ptrs->trans_ptr) { - *ppos -= dump_ptrs->op_mode_len; - bytes_read_trans = - simple_read_from_buffer(user_buf + bytes_read, - count - bytes_read, ppos, - dump_ptrs->trans_ptr->data, - dump_ptrs->trans_ptr->len); - *ppos += dump_ptrs->op_mode_len; - - if (bytes_read_trans >= 0) - bytes_read += bytes_read_trans; - else if (!bytes_read) - /* propagate the failure */ - return bytes_read_trans; - } - - return bytes_read; - -} - -static int iwl_dbgfs_fw_error_dump_release(struct inode *inode, - struct file *file) -{ - struct iwl_mvm_dump_ptrs *dump_ptrs = (void *)file->private_data; - - vfree(dump_ptrs->op_mode_ptr); - vfree(dump_ptrs->trans_ptr); - kfree(dump_ptrs); - - return 0; -} - static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -1250,6 +1178,126 @@ static ssize_t iwl_dbgfs_d3_sram_read(struct file *file, char __user *user_buf, return ret; } + +#define MAX_NUM_ND_MATCHSETS 10 + +static ssize_t iwl_dbgfs_netdetect_write(struct iwl_mvm *mvm, char *buf, + size_t count, loff_t *ppos) +{ + const char *seps = ",\n"; + char *buf_ptr = buf; + char *value_str = NULL; + int ret, i; + + /* TODO: don't free if write is being called several times in one go */ + if (mvm->nd_config) { + kfree(mvm->nd_config->match_sets); + kfree(mvm->nd_config); + mvm->nd_config = NULL; + kfree(mvm->nd_ies); + mvm->nd_ies = NULL; + } + + mvm->nd_ies = kzalloc(sizeof(*mvm->nd_ies), GFP_KERNEL); + if (!mvm->nd_ies) + return -ENOMEM; + + mvm->nd_config = kzalloc(sizeof(*mvm->nd_config) + + (11 * sizeof(struct ieee80211_channel *)), + GFP_KERNEL); + if (!mvm->nd_config) { + ret = -ENOMEM; + goto out_free; + } + + mvm->nd_config->n_channels = 11; + mvm->nd_config->scan_width = NL80211_BSS_CHAN_WIDTH_20; + mvm->nd_config->interval = 5; + mvm->nd_config->min_rssi_thold = -80; + for (i = 0; i < mvm->nd_config->n_channels; i++) + mvm->nd_config->channels[i] = &mvm->nvm_data->channels[i]; + + mvm->nd_config->match_sets = + kcalloc(MAX_NUM_ND_MATCHSETS, + sizeof(*mvm->nd_config->match_sets), + GFP_KERNEL); + if (!mvm->nd_config->match_sets) { + ret = -ENOMEM; + goto out_free; + } + + while ((value_str = strsep(&buf_ptr, seps)) && + strlen(value_str)) { + struct cfg80211_match_set *set; + + if (mvm->nd_config->n_match_sets >= MAX_NUM_ND_MATCHSETS) { + ret = -EINVAL; + goto out_free; + } + + set = &mvm->nd_config->match_sets[mvm->nd_config->n_match_sets]; + set->ssid.ssid_len = strlen(value_str); + + if (set->ssid.ssid_len > IEEE80211_MAX_SSID_LEN) { + ret = -EINVAL; + goto out_free; + } + + memcpy(set->ssid.ssid, value_str, set->ssid.ssid_len); + + mvm->nd_config->n_match_sets++; + } + + ret = count; + + if (mvm->nd_config->n_match_sets) + goto out; + +out_free: + if (mvm->nd_config) + kfree(mvm->nd_config->match_sets); + kfree(mvm->nd_config); + mvm->nd_config = NULL; + kfree(mvm->nd_ies); + mvm->nd_ies = NULL; +out: + return ret; +} + +static ssize_t +iwl_dbgfs_netdetect_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_mvm *mvm = file->private_data; + size_t bufsz, ret; + char *buf; + int i, n_match_sets, pos = 0; + + n_match_sets = mvm->nd_config ? mvm->nd_config->n_match_sets : 0; + + bufsz = n_match_sets * (IEEE80211_MAX_SSID_LEN + 1) + 1; + buf = kzalloc(bufsz, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + for (i = 0; i < n_match_sets; i++) { + if (pos + + mvm->nd_config->match_sets[i].ssid.ssid_len + 2 > bufsz) { + ret = -EIO; + goto out; + } + + memcpy(buf + pos, mvm->nd_config->match_sets[i].ssid.ssid, + mvm->nd_config->match_sets[i].ssid.ssid_len); + pos += mvm->nd_config->match_sets[i].ssid.ssid_len; + buf[pos++] = '\n'; + } + + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); +out: + kfree(buf); + return ret; +} #endif #define PRINT_MVM_REF(ref) do { \ @@ -1415,12 +1463,6 @@ MVM_DEBUGFS_WRITE_FILE_OPS(bt_force_ant, 10); MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8); MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8); -static const struct file_operations iwl_dbgfs_fw_error_dump_ops = { - .open = iwl_dbgfs_fw_error_dump_open, - .read = iwl_dbgfs_fw_error_dump_read, - .release = iwl_dbgfs_fw_error_dump_release, -}; - #ifdef CONFIG_IWLWIFI_BCAST_FILTERING MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256); MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters_macs, 256); @@ -1428,6 +1470,7 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters_macs, 256); #ifdef CONFIG_PM_SLEEP MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram, 8); +MVM_DEBUGFS_READ_WRITE_FILE_OPS(netdetect, 384); #endif int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) @@ -1446,7 +1489,6 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) S_IWUSR | S_IRUSR); MVM_DEBUGFS_ADD_FILE(nic_temp, dbgfs_dir, S_IRUSR); MVM_DEBUGFS_ADD_FILE(stations, dbgfs_dir, S_IRUSR); - MVM_DEBUGFS_ADD_FILE(fw_error_dump, dbgfs_dir, S_IRUSR); MVM_DEBUGFS_ADD_FILE(bt_notif, dbgfs_dir, S_IRUSR); MVM_DEBUGFS_ADD_FILE(bt_cmd, dbgfs_dir, S_IRUSR); MVM_DEBUGFS_ADD_FILE(disable_power_off, mvm->debugfs_dir, @@ -1487,6 +1529,7 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) if (!debugfs_create_bool("d3_wake_sysassert", S_IRUSR | S_IWUSR, mvm->debugfs_dir, &mvm->d3_wake_sysassert)) goto err; + MVM_DEBUGFS_ADD_FILE(netdetect, mvm->debugfs_dir, S_IRUSR | S_IWUSR); #endif if (!debugfs_create_u8("low_latency_agg_frame_limit", S_IRUSR | S_IWUSR, diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c index 0c5c0b0e23f5..b8ab4a108720 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c @@ -197,8 +197,7 @@ static void iwl_mvm_mac_tsf_id_iter(void *_data, u8 *mac, /* * Get the mask of the queues used by the vif */ -u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm, - struct ieee80211_vif *vif) +u32 iwl_mvm_mac_get_queues_mask(struct ieee80211_vif *vif) { u32 qmask = 0, ac; @@ -227,7 +226,7 @@ static void iwl_mvm_mac_iface_iterator(void *_data, u8 *mac, } /* Mark the queues used by the vif */ - data->used_hw_queues |= iwl_mvm_mac_get_queues_mask(data->mvm, vif); + data->used_hw_queues |= iwl_mvm_mac_get_queues_mask(vif); /* Mark MAC IDs as used by clearing the available bit, and * (below) mark TSFs as used if their existing use is not diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index b6d2683da3a9..1ee9dcd26ad9 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -69,6 +69,7 @@ #include <linux/etherdevice.h> #include <linux/ip.h> #include <linux/if_arp.h> +#include <linux/devcoredump.h> #include <net/mac80211.h> #include <net/ieee80211_radiotap.h> #include <net/tcp.h> @@ -679,10 +680,51 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac, memset(&mvmvif->bf_data, 0, sizeof(mvmvif->bf_data)); } -#ifdef CONFIG_IWLWIFI_DEBUGFS +static ssize_t iwl_mvm_read_coredump(char *buffer, loff_t offset, size_t count, + const void *data, size_t datalen) +{ + const struct iwl_mvm_dump_ptrs *dump_ptrs = data; + ssize_t bytes_read; + ssize_t bytes_read_trans; + + if (offset < dump_ptrs->op_mode_len) { + bytes_read = min_t(ssize_t, count, + dump_ptrs->op_mode_len - offset); + memcpy(buffer, (u8 *)dump_ptrs->op_mode_ptr + offset, + bytes_read); + offset += bytes_read; + count -= bytes_read; + + if (count == 0) + return bytes_read; + } else { + bytes_read = 0; + } + + if (!dump_ptrs->trans_ptr) + return bytes_read; + + offset -= dump_ptrs->op_mode_len; + bytes_read_trans = min_t(ssize_t, count, + dump_ptrs->trans_ptr->len - offset); + memcpy(buffer + bytes_read, + (u8 *)dump_ptrs->trans_ptr->data + offset, + bytes_read_trans); + + return bytes_read + bytes_read_trans; +} + +static void iwl_mvm_free_coredump(const void *data) +{ + const struct iwl_mvm_dump_ptrs *fw_error_dump = data; + + vfree(fw_error_dump->op_mode_ptr); + vfree(fw_error_dump->trans_ptr); + kfree(fw_error_dump); +} + void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) { - static char *env[] = { "DRIVER=iwlwifi", "EVENT=error_dump", NULL }; struct iwl_fw_error_dump_file *dump_file; struct iwl_fw_error_dump_data *dump_data; struct iwl_fw_error_dump_info *dump_info; @@ -695,10 +737,7 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) lockdep_assert_held(&mvm->mutex); - if (mvm->fw_error_dump) - return; - - fw_error_dump = kzalloc(sizeof(*mvm->fw_error_dump), GFP_KERNEL); + fw_error_dump = kzalloc(sizeof(*fw_error_dump), GFP_KERNEL); if (!fw_error_dump) return; @@ -773,12 +812,10 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) if (fw_error_dump->trans_ptr) file_len += fw_error_dump->trans_ptr->len; dump_file->file_len = cpu_to_le32(file_len); - mvm->fw_error_dump = fw_error_dump; - /* notify the userspace about the error we had */ - kobject_uevent_env(&mvm->hw->wiphy->dev.kobj, KOBJ_CHANGE, env); + dev_coredumpm(mvm->trans->dev, THIS_MODULE, fw_error_dump, 0, + GFP_KERNEL, iwl_mvm_read_coredump, iwl_mvm_free_coredump); } -#endif static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm) { @@ -859,9 +896,8 @@ static int iwl_mvm_mac_start(struct ieee80211_hw *hw) return ret; } -static void iwl_mvm_mac_restart_complete(struct ieee80211_hw *hw) +static void iwl_mvm_restart_complete(struct iwl_mvm *mvm) { - struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); int ret; mutex_lock(&mvm->mutex); @@ -879,6 +915,21 @@ static void iwl_mvm_mac_restart_complete(struct ieee80211_hw *hw) mutex_unlock(&mvm->mutex); } +static void +iwl_mvm_mac_reconfig_complete(struct ieee80211_hw *hw, + enum ieee80211_reconfig_type reconfig_type) +{ + struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); + + switch (reconfig_type) { + case IEEE80211_RECONFIG_TYPE_RESTART: + iwl_mvm_restart_complete(mvm); + break; + case IEEE80211_RECONFIG_TYPE_SUSPEND: + break; + } +} + void __iwl_mvm_mac_stop(struct iwl_mvm *mvm) { lockdep_assert_held(&mvm->mutex); @@ -1087,7 +1138,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, static void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm, struct ieee80211_vif *vif) { - u32 tfd_msk = iwl_mvm_mac_get_queues_mask(mvm, vif); + u32 tfd_msk = iwl_mvm_mac_get_queues_mask(vif); if (tfd_msk) { mutex_lock(&mvm->mutex); @@ -1383,6 +1434,9 @@ bool iwl_mvm_bcast_filter_build_cmd(struct iwl_mvm *mvm, .cmd = cmd, }; + if (IWL_MVM_FW_BCAST_FILTER_PASS_ALL) + return false; + memset(cmd, 0, sizeof(*cmd)); cmd->max_bcast_filters = ARRAY_SIZE(cmd->filters); cmd->max_macs = ARRAY_SIZE(cmd->macs); @@ -2171,25 +2225,9 @@ static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw, mvm->scan_status = IWL_MVM_SCAN_SCHED; - if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)) { - ret = iwl_mvm_config_sched_scan(mvm, vif, req, ies); - if (ret) - goto err; - } - - ret = iwl_mvm_config_sched_scan_profiles(mvm, req); + ret = iwl_mvm_scan_offload_start(mvm, vif, req, ies); if (ret) - goto err; - - if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN) - ret = iwl_mvm_unified_sched_scan_lmac(mvm, vif, req, ies); - else - ret = iwl_mvm_sched_scan_start(mvm, req); - - if (!ret) - goto out; -err: - mvm->scan_status = IWL_MVM_SCAN_NONE; + mvm->scan_status = IWL_MVM_SCAN_NONE; out: mutex_unlock(&mvm->mutex); return ret; @@ -3017,25 +3055,31 @@ static void iwl_mvm_mac_flush(struct ieee80211_hw *hw, mvmvif = iwl_mvm_vif_from_mac80211(vif); mvmsta = iwl_mvm_sta_from_staid_protected(mvm, mvmvif->ap_sta_id); - if (WARN_ON_ONCE(!mvmsta)) - goto done; + if (WARN_ON_ONCE(!mvmsta)) { + mutex_unlock(&mvm->mutex); + return; + } if (drop) { if (iwl_mvm_flush_tx_path(mvm, mvmsta->tfd_queue_msk, true)) IWL_ERR(mvm, "flush request fail\n"); + mutex_unlock(&mvm->mutex); } else { - iwl_trans_wait_tx_queue_empty(mvm->trans, - mvmsta->tfd_queue_msk); + u32 tfd_queue_msk = mvmsta->tfd_queue_msk; + mutex_unlock(&mvm->mutex); + + /* this can take a while, and we may need/want other operations + * to succeed while doing this, so do it without the mutex held + */ + iwl_trans_wait_tx_queue_empty(mvm->trans, tfd_queue_msk); } -done: - mutex_unlock(&mvm->mutex); } const struct ieee80211_ops iwl_mvm_hw_ops = { .tx = iwl_mvm_mac_tx, .ampdu_action = iwl_mvm_mac_ampdu_action, .start = iwl_mvm_mac_start, - .restart_complete = iwl_mvm_mac_restart_complete, + .reconfig_complete = iwl_mvm_mac_reconfig_complete, .stop = iwl_mvm_mac_stop, .add_interface = iwl_mvm_mac_add_interface, .remove_interface = iwl_mvm_mac_remove_interface, diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 845429c88cf4..d015fac06a62 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -649,7 +649,6 @@ struct iwl_mvm { /* -1 for always, 0 for never, >0 for that many times */ s8 restart_fw; struct work_struct fw_error_dump_wk; - struct iwl_mvm_dump_ptrs *fw_error_dump; #ifdef CONFIG_IWLWIFI_LEDS struct led_classdev led; @@ -660,6 +659,10 @@ struct iwl_mvm { #ifdef CONFIG_PM_SLEEP struct wiphy_wowlan_support wowlan; int gtk_ivlen, gtk_icvlen, ptk_ivlen, ptk_icvlen; + + /* sched scan settings for net detect */ + struct cfg80211_sched_scan_request *nd_config; + struct ieee80211_scan_ies *nd_ies; #ifdef CONFIG_IWLWIFI_DEBUGFS u32 d3_wake_sysassert; /* must be u32 for debugfs_create_bool */ bool d3_test_active; @@ -906,8 +909,7 @@ int iwl_mvm_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif); int iwl_mvm_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif, bool force_assoc_off, const u8 *bssid_override); int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif); -u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm, - struct ieee80211_vif *vif); +u32 iwl_mvm_mac_get_queues_mask(struct ieee80211_vif *vif); int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif); int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm, @@ -950,6 +952,10 @@ int iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm, struct cfg80211_sched_scan_request *req); int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, struct cfg80211_sched_scan_request *req); +int iwl_mvm_scan_offload_start(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct cfg80211_sched_scan_request *req, + struct ieee80211_scan_ies *ies); int iwl_mvm_scan_offload_stop(struct iwl_mvm *mvm, bool notify); int iwl_mvm_rx_scan_offload_results(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, @@ -1207,11 +1213,9 @@ void iwl_mvm_recalc_tdls_state(struct iwl_mvm *mvm, struct ieee80211_vif *vif, void iwl_mvm_mac_mgd_protect_tdls_discover(struct ieee80211_hw *hw, struct ieee80211_vif *vif); +struct ieee80211_vif *iwl_mvm_get_bss_vif(struct iwl_mvm *mvm); + void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error); -#ifdef CONFIG_IWLWIFI_DEBUGFS void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm); -#else -static inline void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) {} -#endif #endif /* __IWL_MVM_H__ */ diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index 5b719ee8e789..7a9578567f4f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c @@ -403,6 +403,9 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, if (cfg->max_rx_agg_size) hw->max_rx_aggregation_subframes = cfg->max_rx_agg_size; + if (cfg->max_tx_agg_size) + hw->max_tx_aggregation_subframes = cfg->max_tx_agg_size; + op_mode = hw->priv; op_mode->ops = &iwl_mvm_ops; @@ -585,16 +588,18 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode) ieee80211_unregister_hw(mvm->hw); kfree(mvm->scan_cmd); - if (mvm->fw_error_dump) { - vfree(mvm->fw_error_dump->op_mode_ptr); - vfree(mvm->fw_error_dump->trans_ptr); - kfree(mvm->fw_error_dump); - } kfree(mvm->mcast_filter_cmd); mvm->mcast_filter_cmd = NULL; #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_IWLWIFI_DEBUGFS) kfree(mvm->d3_resume_sram); + if (mvm->nd_config) { + kfree(mvm->nd_config->match_sets); + kfree(mvm->nd_config); + mvm->nd_config = NULL; + kfree(mvm->nd_ies); + mvm->nd_ies = NULL; + } #endif iwl_trans_op_mode_leave(mvm->trans); diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 18a539999580..ce884847cc8a 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -505,10 +505,11 @@ static const char *rs_pretty_lq_type(enum iwl_table_type type) static inline void rs_dump_rate(struct iwl_mvm *mvm, const struct rs_rate *rate, const char *prefix) { - IWL_DEBUG_RATE(mvm, "%s: (%s: %d) ANT: %s BW: %d SGI: %d LDPC: %d\n", + IWL_DEBUG_RATE(mvm, + "%s: (%s: %d) ANT: %s BW: %d SGI: %d LDPC: %d STBC %d\n", prefix, rs_pretty_lq_type(rate->type), rate->index, rs_pretty_ant(rate->ant), - rate->bw, rate->sgi, rate->ldpc); + rate->bw, rate->sgi, rate->ldpc, rate->stbc); } static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window) @@ -741,6 +742,12 @@ static u32 ucode_rate_from_rs_rate(struct iwl_mvm *mvm, IWL_ERR(mvm, "Invalid rate->type %d\n", rate->type); } + if (is_siso(rate) && rate->stbc) { + /* To enable STBC we need to set both a flag and ANT_AB */ + ucode_rate |= RATE_MCS_ANT_AB_MSK; + ucode_rate |= RATE_MCS_VHT_STBC_MSK; + } + ucode_rate |= rate->bw; if (rate->sgi) ucode_rate |= RATE_MCS_SGI_MSK; @@ -785,6 +792,8 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate, rate->sgi = true; if (ucode_rate & RATE_MCS_LDPC_MSK) rate->ldpc = true; + if (ucode_rate & RATE_MCS_VHT_STBC_MSK) + rate->stbc = true; rate->bw = ucode_rate & RATE_MCS_CHAN_WIDTH_MSK; @@ -794,7 +803,7 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate, if (nss == 1) { rate->type = LQ_HT_SISO; - WARN_ON_ONCE(num_of_ant != 1); + WARN_ON_ONCE(!rate->stbc && num_of_ant != 1); } else if (nss == 2) { rate->type = LQ_HT_MIMO2; WARN_ON_ONCE(num_of_ant != 2); @@ -992,7 +1001,15 @@ static void rs_get_lower_rate_down_column(struct iwl_lq_sta *lq_sta, static inline bool rs_rate_match(struct rs_rate *a, struct rs_rate *b) { - return (a->type == b->type) && (a->ant == b->ant) && (a->sgi == b->sgi); + bool ant_match; + + if (a->stbc) + ant_match = (b->ant == ANT_A || b->ant == ANT_B); + else + ant_match = (a->ant == b->ant); + + return (a->type == b->type) && (a->bw == b->bw) && (a->sgi == b->sgi) + && ant_match; } static u32 rs_ch_width_from_mac_flags(enum mac80211_rate_control_flags flags) @@ -1225,7 +1242,7 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta, IWL_DEBUG_RATE(mvm, "reduced txpower: %d\n", reduced_txp); done: /* See if there's a better rate or modulation mode to try. */ - if (sta && sta->supp_rates[info->band]) + if (sta->supp_rates[info->band]) rs_rate_scale_perform(mvm, sta, lq_sta, tid); } @@ -1623,6 +1640,8 @@ static int rs_switch_to_column(struct iwl_mvm *mvm, else rate->type = LQ_LEGACY_G; + rate->bw = RATE_MCS_CHAN_WIDTH_20; + rate->ldpc = false; rate_mask = lq_sta->active_legacy_rate; } else if (column->mode == RS_SISO) { rate->type = lq_sta->is_vht ? LQ_VHT_SISO : LQ_HT_SISO; @@ -1634,8 +1653,11 @@ static int rs_switch_to_column(struct iwl_mvm *mvm, WARN_ON_ONCE("Bad column mode"); } - rate->bw = rs_bw_from_sta_bw(sta); - rate->ldpc = lq_sta->ldpc; + if (column->mode != RS_LEGACY) { + rate->bw = rs_bw_from_sta_bw(sta); + rate->ldpc = lq_sta->ldpc; + } + search_tbl->column = col_id; rs_set_expected_tpt_table(lq_sta, search_tbl); @@ -1754,6 +1776,29 @@ out: return action; } +static bool rs_stbc_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta, + struct iwl_lq_sta *lq_sta) +{ + struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); + struct ieee80211_vif *vif = mvmsta->vif; + bool sta_ps_disabled = (vif->type == NL80211_IFTYPE_STATION && + !vif->bss_conf.ps); + + /* Our chip supports Tx STBC and the peer is an HT/VHT STA which + * supports STBC of at least 1*SS + */ + if (!lq_sta->stbc) + return false; + + if (!mvm->ps_disabled && !sta_ps_disabled) + return false; + + if (!iwl_mvm_bt_coex_is_mimo_allowed(mvm, sta)) + return false; + + return true; +} + static void rs_get_adjacent_txp(struct iwl_mvm *mvm, int index, int *weaker, int *stronger) { @@ -2675,6 +2720,11 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, if (mvm->cfg->ht_params->ldpc && (ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING)) lq_sta->ldpc = true; + + if (mvm->cfg->ht_params->stbc && + (num_of_ant(mvm->fw->valid_tx_ant) > 1) && + (ht_cap->cap & IEEE80211_HT_CAP_RX_STBC)) + lq_sta->stbc = true; } else { rs_vht_set_enabled_rates(sta, vht_cap, lq_sta); lq_sta->is_vht = true; @@ -2682,8 +2732,16 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, if (mvm->cfg->ht_params->ldpc && (vht_cap->cap & IEEE80211_VHT_CAP_RXLDPC)) lq_sta->ldpc = true; + + if (mvm->cfg->ht_params->stbc && + (num_of_ant(mvm->fw->valid_tx_ant) > 1) && + (vht_cap->cap & IEEE80211_VHT_CAP_RXSTBC_MASK)) + lq_sta->stbc = true; } + if (IWL_MVM_RS_DISABLE_MIMO) + lq_sta->active_mimo2_rate = 0; + lq_sta->max_legacy_rate_idx = find_last_bit(&lq_sta->active_legacy_rate, BITS_PER_LONG); lq_sta->max_siso_rate_idx = find_last_bit(&lq_sta->active_siso_rate, @@ -2692,11 +2750,11 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, BITS_PER_LONG); IWL_DEBUG_RATE(mvm, - "RATE MASK: LEGACY=%lX SISO=%lX MIMO2=%lX VHT=%d LDPC=%d\n", + "RATE MASK: LEGACY=%lX SISO=%lX MIMO2=%lX VHT=%d LDPC=%d STBC%d\n", lq_sta->active_legacy_rate, lq_sta->active_siso_rate, lq_sta->active_mimo2_rate, - lq_sta->is_vht, lq_sta->ldpc); + lq_sta->is_vht, lq_sta->ldpc, lq_sta->stbc); IWL_DEBUG_RATE(mvm, "MAX RATE: LEGACY=%d SISO=%d MIMO2=%d\n", lq_sta->max_legacy_rate_idx, lq_sta->max_siso_rate_idx, @@ -2820,6 +2878,7 @@ static void rs_fill_rates_for_column(struct iwl_mvm *mvm, * rate[15] 0x800D Legacy | ANT: B Rate: 6 Mbps */ static void rs_build_rates_table(struct iwl_mvm *mvm, + struct ieee80211_sta *sta, struct iwl_lq_sta *lq_sta, const struct rs_rate *initial_rate) { @@ -2832,6 +2891,7 @@ static void rs_build_rates_table(struct iwl_mvm *mvm, memcpy(&rate, initial_rate, sizeof(rate)); valid_tx_ant = mvm->fw->valid_tx_ant; + rate.stbc = rs_stbc_allow(mvm, sta, lq_sta); if (is_siso(&rate)) { num_rates = RS_INITIAL_SISO_NUM_RATES; @@ -2903,7 +2963,7 @@ static void rs_fill_lq_cmd(struct iwl_mvm *mvm, if (WARN_ON_ONCE(!sta || !initial_rate)) return; - rs_build_rates_table(mvm, lq_sta, initial_rate); + rs_build_rates_table(mvm, sta, lq_sta, initial_rate); if (num_of_ant(initial_rate->ant) == 1) lq_cmd->single_stream_ant_msk = initial_rate->ant; diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h index eb34c1209acc..defd70a6d9e6 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.h +++ b/drivers/net/wireless/iwlwifi/mvm/rs.h @@ -208,6 +208,7 @@ struct rs_rate { u32 bw; bool sgi; bool ldpc; + bool stbc; }; @@ -331,6 +332,7 @@ struct iwl_lq_sta { u64 last_tx; bool is_vht; bool ldpc; /* LDPC Rx is supported by the STA */ + bool stbc; /* Tx STBC is supported by chip and Rx by STA */ enum ieee80211_band band; /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index 7554f7053830..fb2a8628b8fc 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c @@ -270,7 +270,8 @@ static void iwl_mvm_scan_condition_iterator(void *data, u8 *mac, struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); bool *global_bound = data; - if (mvmvif->phy_ctxt && mvmvif->phy_ctxt->id < MAX_PHYS) + if (vif->type != NL80211_IFTYPE_P2P_DEVICE && mvmvif->phy_ctxt && + mvmvif->phy_ctxt->id < MAX_PHYS) *global_bound = true; } @@ -662,6 +663,7 @@ int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm, mvm->scan_status = IWL_MVM_SCAN_NONE; ieee80211_scan_completed(mvm->hw, status == IWL_SCAN_OFFLOAD_ABORTED); + iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); } mvm->last_ebs_successful = !ebs_status; @@ -997,6 +999,31 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, sizeof(scan_req), &scan_req); } +int iwl_mvm_scan_offload_start(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct cfg80211_sched_scan_request *req, + struct ieee80211_scan_ies *ies) +{ + int ret; + + if ((mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)) { + ret = iwl_mvm_config_sched_scan_profiles(mvm, req); + if (ret) + return ret; + ret = iwl_mvm_unified_sched_scan_lmac(mvm, vif, req, ies); + } else { + ret = iwl_mvm_config_sched_scan(mvm, vif, req, ies); + if (ret) + return ret; + ret = iwl_mvm_config_sched_scan_profiles(mvm, req); + if (ret) + return ret; + ret = iwl_mvm_sched_scan_start(mvm, req); + } + + return ret; +} + static int iwl_mvm_send_scan_offload_abort(struct iwl_mvm *mvm) { int ret; @@ -1071,8 +1098,12 @@ int iwl_mvm_scan_offload_stop(struct iwl_mvm *mvm, bool notify) /* * Clear the scan status so the next scan requests will succeed. This * also ensures the Rx handler doesn't do anything, as the scan was - * stopped from above. + * stopped from above. Since the rx handler won't do anything now, + * we have to release the scan reference here. */ + if (mvm->scan_status == IWL_MVM_SCAN_OS) + iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); + mvm->scan_status = IWL_MVM_SCAN_NONE; if (notify) { diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index 1731c205c81d..dd0dc5bf8583 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c @@ -609,7 +609,7 @@ int iwl_mvm_alloc_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) lockdep_assert_held(&mvm->mutex); - qmask = iwl_mvm_mac_get_queues_mask(mvm, vif); + qmask = iwl_mvm_mac_get_queues_mask(vif); /* * The firmware defines the TFD queue mask to only be relevant diff --git a/drivers/net/wireless/iwlwifi/mvm/tt.c b/drivers/net/wireless/iwlwifi/mvm/tt.c index acca44a45086..d4f2c29025c7 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tt.c +++ b/drivers/net/wireless/iwlwifi/mvm/tt.c @@ -64,10 +64,6 @@ *****************************************************************************/ #include "mvm.h" -#include "iwl-config.h" -#include "iwl-io.h" -#include "iwl-csr.h" -#include "iwl-prph.h" #define IWL_MVM_TEMP_NOTIF_WAIT_TIMEOUT HZ diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index c6a517c771df..8d848735cdb8 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c @@ -189,8 +189,10 @@ static void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, /* HT rate doesn't make sense for a non data frame */ WARN_ONCE(info->control.rates[0].flags & IEEE80211_TX_RC_MCS, - "Got an HT rate for a non data frame 0x%x\n", - info->control.rates[0].flags); + "Got an HT rate (flags:0x%x/mcs:%d) for a non data frame (fc:0x%x)\n", + info->control.rates[0].flags, + info->control.rates[0].idx, + le16_to_cpu(fc)); rate_idx = info->control.rates[0].idx; /* if the rate isn't a well known legacy rate, take the lowest one */ diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c index 8021f6eec27f..e56e77ef5d2e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/iwlwifi/mvm/utils.c @@ -734,3 +734,40 @@ bool iwl_mvm_is_idle(struct iwl_mvm *mvm) return idle; } + +struct iwl_bss_iter_data { + struct ieee80211_vif *vif; + bool error; +}; + +static void iwl_mvm_bss_iface_iterator(void *_data, u8 *mac, + struct ieee80211_vif *vif) +{ + struct iwl_bss_iter_data *data = _data; + + if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) + return; + + if (data->vif) { + data->error = true; + return; + } + + data->vif = vif; +} + +struct ieee80211_vif *iwl_mvm_get_bss_vif(struct iwl_mvm *mvm) +{ + struct iwl_bss_iter_data bss_iter_data = {}; + + ieee80211_iterate_active_interfaces_atomic( + mvm->hw, IEEE80211_IFACE_ITER_NORMAL, + iwl_mvm_bss_iface_iterator, &bss_iter_data); + + if (bss_iter_data.error) { + IWL_ERR(mvm, "More than one managed interface active!\n"); + return ERR_PTR(-EINVAL); + } + + return bss_iter_data.vif; +} diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index dd2f3f8baa9d..ea8efed25c6a 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c @@ -133,7 +133,7 @@ static void iwl_pcie_alloc_fw_monitor(struct iwl_trans *trans) break; } - if (!page) + if (WARN_ON_ONCE(!page)) return; trans_pcie->fw_mon_page = page; @@ -747,14 +747,11 @@ static int iwl_pcie_load_given_ucode(struct iwl_trans *trans, int first_ucode_section; IWL_DEBUG_FW(trans, - "working with %s image\n", - image->is_secure ? "Secured" : "Non Secured"); - IWL_DEBUG_FW(trans, "working with %s CPU\n", image->is_dual_cpus ? "Dual" : "Single"); /* configure the ucode to be ready to get the secured image */ - if (image->is_secure) { + if (iwl_has_secure_boot(trans->hw_rev, trans->cfg->device_family)) { /* set secure boot inspector addresses */ iwl_write_prph(trans, LMPM_SECURE_INSPECTOR_CODE_ADDR, @@ -790,7 +787,8 @@ static int iwl_pcie_load_given_ucode(struct iwl_trans *trans, LMPM_SECURE_CPU2_HDR_MEM_SPACE); /* load to FW the binary sections of CPU2 */ - if (image->is_secure) + if (iwl_has_secure_boot(trans->hw_rev, + trans->cfg->device_family)) ret = iwl_pcie_load_cpu_secured_sections( trans, image, 2, &first_ucode_section); @@ -821,7 +819,7 @@ static int iwl_pcie_load_given_ucode(struct iwl_trans *trans, else iwl_write32(trans, CSR_RESET, 0); - if (image->is_secure) { + if (iwl_has_secure_boot(trans->hw_rev, trans->cfg->device_family)) { /* wait for image verification to complete */ ret = iwl_poll_prph_bit(trans, LMPM_SECURE_BOOT_CPU1_STATUS_ADDR, @@ -1023,14 +1021,6 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, return 0; } - iwl_pcie_set_pwr(trans, false); - - val = iwl_read32(trans, CSR_RESET); - if (val & CSR_RESET_REG_FLAG_NEVO_RESET) { - *status = IWL_D3_STATUS_RESET; - return 0; - } - /* * Also enables interrupts - none will happen as the device doesn't * know we're waking it up, only when the opmode actually tells it @@ -1050,6 +1040,8 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, return ret; } + iwl_pcie_set_pwr(trans, false); + iwl_trans_pcie_tx_reset(trans); ret = iwl_pcie_rx_init(trans); @@ -1058,7 +1050,12 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, return ret; } - *status = IWL_D3_STATUS_ALIVE; + val = iwl_read32(trans, CSR_RESET); + if (val & CSR_RESET_REG_FLAG_NEVO_RESET) + *status = IWL_D3_STATUS_RESET; + else + *status = IWL_D3_STATUS_ALIVE; + return 0; } @@ -1767,6 +1764,13 @@ err: IWL_ERR(trans, "failed to create the trans debugfs entry\n"); return -ENOMEM; } +#else +static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, + struct dentry *dir) +{ + return 0; +} +#endif /*CONFIG_IWLWIFI_DEBUGFS */ static u32 iwl_trans_pcie_get_cmdlen(struct iwl_tfd *tfd) { @@ -2044,13 +2048,6 @@ struct iwl_trans_dump_data *iwl_trans_pcie_dump_data(struct iwl_trans *trans) return dump_data; } -#else -static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, - struct dentry *dir) -{ - return 0; -} -#endif /*CONFIG_IWLWIFI_DEBUGFS */ static const struct iwl_trans_ops trans_ops_pcie = { .start_hw = iwl_trans_pcie_start_hw, @@ -2087,9 +2084,7 @@ static const struct iwl_trans_ops trans_ops_pcie = { .release_nic_access = iwl_trans_pcie_release_nic_access, .set_bits_mask = iwl_trans_pcie_set_bits_mask, -#ifdef CONFIG_IWLWIFI_DEBUGFS .dump_data = iwl_trans_pcie_dump_data, -#endif }; struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index c9ad4cf1adfb..2371d11e4190 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -412,6 +412,11 @@ struct mac80211_hwsim_data { struct mac_address addresses[2]; int channels, idx; bool use_chanctx; + bool destroy_on_close; + struct work_struct destroy_work; + u32 portid; + char alpha2[2]; + const struct ieee80211_regdomain *regd; struct ieee80211_channel *tmp_chan; struct delayed_work roc_done; @@ -419,6 +424,7 @@ struct mac80211_hwsim_data { struct cfg80211_scan_request *hw_scan_request; struct ieee80211_vif *hw_scan_vif; int scan_chan_idx; + u8 scan_addr[ETH_ALEN]; struct ieee80211_channel *channel; u64 beacon_int /* beacon interval in us */; @@ -436,7 +442,7 @@ struct mac80211_hwsim_data { /* * Only radios in the same group can communicate together (the * channel has to match too). Each bit represents a group. A - * radio can be in more then one group. + * radio can be in more than one group. */ u64 group; @@ -447,6 +453,14 @@ struct mac80211_hwsim_data { s64 bcn_delta; /* absolute beacon transmission time. Used to cover up "tx" delay. */ u64 abs_bcn_ts; + + /* Stats */ + u64 tx_pkts; + u64 rx_pkts; + u64 tx_bytes; + u64 rx_bytes; + u64 tx_dropped; + u64 tx_failed; }; @@ -476,6 +490,14 @@ static struct genl_family hwsim_genl_family = { .maxattr = HWSIM_ATTR_MAX, }; +enum hwsim_multicast_groups { + HWSIM_MCGRP_CONFIG, +}; + +static const struct genl_multicast_group hwsim_mcgrps[] = { + [HWSIM_MCGRP_CONFIG] = { .name = "config", }, +}; + /* MAC80211_HWSIM netlink policy */ static const struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = { @@ -496,6 +518,10 @@ static const struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = { [HWSIM_ATTR_REG_CUSTOM_REG] = { .type = NLA_U32 }, [HWSIM_ATTR_REG_STRICT_REG] = { .type = NLA_FLAG }, [HWSIM_ATTR_SUPPORT_P2P_DEVICE] = { .type = NLA_FLAG }, + [HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE] = { .type = NLA_FLAG }, + [HWSIM_ATTR_RADIO_NAME] = { .type = NLA_STRING }, + [HWSIM_ATTR_NO_VIF] = { .type = NLA_FLAG }, + [HWSIM_ATTR_FREQ] = { .type = NLA_U32 }, }; static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, @@ -807,6 +833,9 @@ static bool mac80211_hwsim_addr_match(struct mac80211_hwsim_data *data, .ret = false, }; + if (data->scanning && memcmp(addr, data->scan_addr, ETH_ALEN) == 0) + return true; + memcpy(md.addr, addr, ETH_ALEN); ieee80211_iterate_active_interfaces_atomic(data->hw, @@ -861,8 +890,10 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw, /* If the queue contains MAX_QUEUE skb's drop some */ if (skb_queue_len(&data->pending) >= MAX_QUEUE) { /* Droping until WARN_QUEUE level */ - while (skb_queue_len(&data->pending) >= WARN_QUEUE) - skb_dequeue(&data->pending); + while (skb_queue_len(&data->pending) >= WARN_QUEUE) { + ieee80211_free_txskb(hw, skb_dequeue(&data->pending)); + data->tx_dropped++; + } } skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_ATOMIC); @@ -896,6 +927,9 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw, if (nla_put_u32(skb, HWSIM_ATTR_FLAGS, hwsim_flags)) goto nla_put_failure; + if (nla_put_u32(skb, HWSIM_ATTR_FREQ, data->channel->center_freq)) + goto nla_put_failure; + /* We get the tx control (rate and retries) info*/ for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { @@ -917,10 +951,14 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw, /* Enqueue the packet */ skb_queue_tail(&data->pending, my_skb); + data->tx_pkts++; + data->tx_bytes += my_skb->len; return; nla_put_failure: printk(KERN_DEBUG "mac80211_hwsim: error occurred in %s\n", __func__); + ieee80211_free_txskb(hw, my_skb); + data->tx_failed++; } static bool hwsim_chans_compat(struct ieee80211_channel *c1, @@ -952,6 +990,53 @@ static void mac80211_hwsim_tx_iter(void *_data, u8 *addr, data->receive = true; } +static void mac80211_hwsim_add_vendor_rtap(struct sk_buff *skb) +{ + /* + * To enable this code, #define the HWSIM_RADIOTAP_OUI, + * e.g. like this: + * #define HWSIM_RADIOTAP_OUI "\x02\x00\x00" + * (but you should use a valid OUI, not that) + * + * If anyone wants to 'donate' a radiotap OUI/subns code + * please send a patch removing this #ifdef and changing + * the values accordingly. + */ +#ifdef HWSIM_RADIOTAP_OUI + struct ieee80211_vendor_radiotap *rtap; + + /* + * Note that this code requires the headroom in the SKB + * that was allocated earlier. + */ + rtap = (void *)skb_push(skb, sizeof(*rtap) + 8 + 4); + rtap->oui[0] = HWSIM_RADIOTAP_OUI[0]; + rtap->oui[1] = HWSIM_RADIOTAP_OUI[1]; + rtap->oui[2] = HWSIM_RADIOTAP_OUI[2]; + rtap->subns = 127; + + /* + * Radiotap vendor namespaces can (and should) also be + * split into fields by using the standard radiotap + * presence bitmap mechanism. Use just BIT(0) here for + * the presence bitmap. + */ + rtap->present = BIT(0); + /* We have 8 bytes of (dummy) data */ + rtap->len = 8; + /* For testing, also require it to be aligned */ + rtap->align = 8; + /* And also test that padding works, 4 bytes */ + rtap->pad = 4; + /* push the data */ + memcpy(rtap->data, "ABCDEFGH", 8); + /* make sure to clear padding, mac80211 doesn't */ + memset(rtap->data + 8, 0, 4); + + IEEE80211_SKB_RXCB(skb)->flag |= RX_FLAG_RADIOTAP_VENDOR_DATA; +#endif +} + static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, struct sk_buff *skb, struct ieee80211_channel *chan) @@ -1066,6 +1151,11 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, rx_status.mactime = now + data2->tsf_offset; memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status)); + + mac80211_hwsim_add_vendor_rtap(nskb); + + data2->rx_pkts++; + data2->rx_bytes += nskb->len; ieee80211_rx_irqsafe(data2->hw, nskb); } spin_unlock(&hwsim_radio_lock); @@ -1133,6 +1223,8 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, return mac80211_hwsim_tx_frame_nl(hw, skb, _portid); /* NO wmediumd detected, perfect medium simulation */ + data->tx_pkts++; + data->tx_bytes += skb->len; ack = mac80211_hwsim_tx_frame_no_nl(hw, skb, channel); if (ack && skb->len >= 16) { @@ -1716,7 +1808,7 @@ static void hw_scan_work(struct work_struct *work) struct sk_buff *probe; probe = ieee80211_probereq_get(hwsim->hw, - hwsim->hw_scan_vif, + hwsim->scan_addr, req->ssids[i].ssid, req->ssids[i].ssid_len, req->ie_len); @@ -1754,6 +1846,12 @@ static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw, hwsim->hw_scan_request = req; hwsim->hw_scan_vif = vif; hwsim->scan_chan_idx = 0; + if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) + get_random_mask_addr(hwsim->scan_addr, + hw_req->req.mac_addr, + hw_req->req.mac_addr_mask); + else + memcpy(hwsim->scan_addr, vif->addr, ETH_ALEN); mutex_unlock(&hwsim->mutex); wiphy_debug(hw->wiphy, "hwsim hw_scan request\n"); @@ -1780,7 +1878,9 @@ static void mac80211_hwsim_cancel_hw_scan(struct ieee80211_hw *hw, mutex_unlock(&hwsim->mutex); } -static void mac80211_hwsim_sw_scan(struct ieee80211_hw *hw) +static void mac80211_hwsim_sw_scan(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + const u8 *mac_addr) { struct mac80211_hwsim_data *hwsim = hw->priv; @@ -1792,13 +1892,16 @@ static void mac80211_hwsim_sw_scan(struct ieee80211_hw *hw) } printk(KERN_DEBUG "hwsim sw_scan request, prepping stuff\n"); + + memcpy(hwsim->scan_addr, mac_addr, ETH_ALEN); hwsim->scanning = true; out: mutex_unlock(&hwsim->mutex); } -static void mac80211_hwsim_sw_scan_complete(struct ieee80211_hw *hw) +static void mac80211_hwsim_sw_scan_complete(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) { struct mac80211_hwsim_data *hwsim = hw->priv; @@ -1806,6 +1909,7 @@ static void mac80211_hwsim_sw_scan_complete(struct ieee80211_hw *hw) printk(KERN_DEBUG "hwsim sw_scan_complete\n"); hwsim->scanning = false; + memset(hwsim->scan_addr, 0, ETH_ALEN); mutex_unlock(&hwsim->mutex); } @@ -1916,6 +2020,57 @@ static void mac80211_hwsim_unassign_vif_chanctx(struct ieee80211_hw *hw, hwsim_check_chanctx_magic(ctx); } +static const char mac80211_hwsim_gstrings_stats[][ETH_GSTRING_LEN] = { + "tx_pkts_nic", + "tx_bytes_nic", + "rx_pkts_nic", + "rx_bytes_nic", + "d_tx_dropped", + "d_tx_failed", + "d_ps_mode", + "d_group", + "d_tx_power", +}; + +#define MAC80211_HWSIM_SSTATS_LEN ARRAY_SIZE(mac80211_hwsim_gstrings_stats) + +static void mac80211_hwsim_get_et_strings(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + u32 sset, u8 *data) +{ + if (sset == ETH_SS_STATS) + memcpy(data, *mac80211_hwsim_gstrings_stats, + sizeof(mac80211_hwsim_gstrings_stats)); +} + +static int mac80211_hwsim_get_et_sset_count(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, int sset) +{ + if (sset == ETH_SS_STATS) + return MAC80211_HWSIM_SSTATS_LEN; + return 0; +} + +static void mac80211_hwsim_get_et_stats(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ethtool_stats *stats, u64 *data) +{ + struct mac80211_hwsim_data *ar = hw->priv; + int i = 0; + + data[i++] = ar->tx_pkts; + data[i++] = ar->tx_bytes; + data[i++] = ar->rx_pkts; + data[i++] = ar->rx_bytes; + data[i++] = ar->tx_dropped; + data[i++] = ar->tx_failed; + data[i++] = ar->ps; + data[i++] = ar->group; + data[i++] = ar->power_level; + + WARN_ON(i != MAC80211_HWSIM_SSTATS_LEN); +} + static const struct ieee80211_ops mac80211_hwsim_ops = { .tx = mac80211_hwsim_tx, .start = mac80211_hwsim_start, @@ -1939,14 +2094,131 @@ static const struct ieee80211_ops mac80211_hwsim_ops = { .flush = mac80211_hwsim_flush, .get_tsf = mac80211_hwsim_get_tsf, .set_tsf = mac80211_hwsim_set_tsf, + .get_et_sset_count = mac80211_hwsim_get_et_sset_count, + .get_et_stats = mac80211_hwsim_get_et_stats, + .get_et_strings = mac80211_hwsim_get_et_strings, }; static struct ieee80211_ops mac80211_hwsim_mchan_ops; -static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, - const struct ieee80211_regdomain *regd, - bool reg_strict, bool p2p_device, - bool use_chanctx) +struct hwsim_new_radio_params { + unsigned int channels; + const char *reg_alpha2; + const struct ieee80211_regdomain *regd; + bool reg_strict; + bool p2p_device; + bool use_chanctx; + bool destroy_on_close; + const char *hwname; + bool no_vif; +}; + +static void hwsim_mcast_config_msg(struct sk_buff *mcast_skb, + struct genl_info *info) +{ + if (info) + genl_notify(&hwsim_genl_family, mcast_skb, + genl_info_net(info), info->snd_portid, + HWSIM_MCGRP_CONFIG, info->nlhdr, GFP_KERNEL); + else + genlmsg_multicast(&hwsim_genl_family, mcast_skb, 0, + HWSIM_MCGRP_CONFIG, GFP_KERNEL); +} + +static int append_radio_msg(struct sk_buff *skb, int id, + struct hwsim_new_radio_params *param) +{ + int ret; + + ret = nla_put_u32(skb, HWSIM_ATTR_RADIO_ID, id); + if (ret < 0) + return ret; + + if (param->channels) { + ret = nla_put_u32(skb, HWSIM_ATTR_CHANNELS, param->channels); + if (ret < 0) + return ret; + } + + if (param->reg_alpha2) { + ret = nla_put(skb, HWSIM_ATTR_REG_HINT_ALPHA2, 2, + param->reg_alpha2); + if (ret < 0) + return ret; + } + + if (param->regd) { + int i; + + for (i = 0; hwsim_world_regdom_custom[i] != param->regd && + i < ARRAY_SIZE(hwsim_world_regdom_custom); i++) + ; + + if (i < ARRAY_SIZE(hwsim_world_regdom_custom)) { + ret = nla_put_u32(skb, HWSIM_ATTR_REG_CUSTOM_REG, i); + if (ret < 0) + return ret; + } + } + + if (param->reg_strict) { + ret = nla_put_flag(skb, HWSIM_ATTR_REG_STRICT_REG); + if (ret < 0) + return ret; + } + + if (param->p2p_device) { + ret = nla_put_flag(skb, HWSIM_ATTR_SUPPORT_P2P_DEVICE); + if (ret < 0) + return ret; + } + + if (param->use_chanctx) { + ret = nla_put_flag(skb, HWSIM_ATTR_USE_CHANCTX); + if (ret < 0) + return ret; + } + + if (param->hwname) { + ret = nla_put(skb, HWSIM_ATTR_RADIO_NAME, + strlen(param->hwname), param->hwname); + if (ret < 0) + return ret; + } + + return 0; +} + +static void hwsim_mcast_new_radio(int id, struct genl_info *info, + struct hwsim_new_radio_params *param) +{ + struct sk_buff *mcast_skb; + void *data; + + mcast_skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!mcast_skb) + return; + + data = genlmsg_put(mcast_skb, 0, 0, &hwsim_genl_family, 0, + HWSIM_CMD_NEW_RADIO); + if (!data) + goto out_err; + + if (append_radio_msg(mcast_skb, id, param) < 0) + goto out_err; + + genlmsg_end(mcast_skb, data); + + hwsim_mcast_config_msg(mcast_skb, info); + return; + +out_err: + genlmsg_cancel(mcast_skb, data); + nlmsg_free(mcast_skb); +} + +static int mac80211_hwsim_new_radio(struct genl_info *info, + struct hwsim_new_radio_params *param) { int err; u8 addr[ETH_ALEN]; @@ -1956,16 +2228,16 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, const struct ieee80211_ops *ops = &mac80211_hwsim_ops; int idx; - if (WARN_ON(channels > 1 && !use_chanctx)) + if (WARN_ON(param->channels > 1 && !param->use_chanctx)) return -EINVAL; spin_lock_bh(&hwsim_radio_lock); idx = hwsim_radio_idx++; spin_unlock_bh(&hwsim_radio_lock); - if (use_chanctx) + if (param->use_chanctx) ops = &mac80211_hwsim_mchan_ops; - hw = ieee80211_alloc_hw(sizeof(*data), ops); + hw = ieee80211_alloc_hw_nm(sizeof(*data), ops, param->hwname); if (!hw) { printk(KERN_DEBUG "mac80211_hwsim: ieee80211_alloc_hw failed\n"); err = -ENOMEM; @@ -2003,9 +2275,12 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, hw->wiphy->n_addresses = 2; hw->wiphy->addresses = data->addresses; - data->channels = channels; - data->use_chanctx = use_chanctx; + data->channels = param->channels; + data->use_chanctx = param->use_chanctx; data->idx = idx; + data->destroy_on_close = param->destroy_on_close; + if (info) + data->portid = info->snd_portid; if (data->use_chanctx) { hw->wiphy->max_scan_ssids = 255; @@ -2014,12 +2289,12 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, /* For channels > 1 DFS is not allowed */ hw->wiphy->n_iface_combinations = 1; hw->wiphy->iface_combinations = &data->if_combination; - if (p2p_device) + if (param->p2p_device) data->if_combination = hwsim_if_comb_p2p_dev[0]; else data->if_combination = hwsim_if_comb[0]; data->if_combination.num_different_channels = data->channels; - } else if (p2p_device) { + } else if (param->p2p_device) { hw->wiphy->iface_combinations = hwsim_if_comb_p2p_dev; hw->wiphy->n_iface_combinations = ARRAY_SIZE(hwsim_if_comb_p2p_dev); @@ -2040,7 +2315,7 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_MESH_POINT); - if (p2p_device) + if (param->p2p_device) hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_DEVICE); hw->flags = IEEE80211_HW_MFP_CAPABLE | @@ -2060,7 +2335,8 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, hw->wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR | NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE | NL80211_FEATURE_STATIC_SMPS | - NL80211_FEATURE_DYNAMIC_SMPS; + NL80211_FEATURE_DYNAMIC_SMPS | + NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR; /* ask mac80211 to reserve space for magic */ hw->vif_data_size = sizeof(struct hwsim_vif_priv); @@ -2095,6 +2371,7 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, sband->ht_cap.ht_supported = true; sband->ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | IEEE80211_HT_CAP_GRN_FLD | + IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_DSSSCCK40; sband->ht_cap.ampdu_factor = 0x3; @@ -2142,15 +2419,19 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, hw->max_rates = 4; hw->max_rate_tries = 11; - if (reg_strict) + if (param->reg_strict) hw->wiphy->regulatory_flags |= REGULATORY_STRICT_REG; - if (regd) { + if (param->regd) { + data->regd = param->regd; hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; - wiphy_apply_custom_regulatory(hw->wiphy, regd); + wiphy_apply_custom_regulatory(hw->wiphy, param->regd); /* give the regulatory workqueue a chance to run */ schedule_timeout_interruptible(1); } + if (param->no_vif) + hw->flags |= IEEE80211_HW_NO_AUTO_VIF; + err = ieee80211_register_hw(hw); if (err < 0) { printk(KERN_DEBUG "mac80211_hwsim: ieee80211_register_hw failed (%d)\n", @@ -2160,8 +2441,11 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, wiphy_debug(hw->wiphy, "hwaddr %pM registered\n", hw->wiphy->perm_addr); - if (reg_alpha2) - regulatory_hint(hw->wiphy, reg_alpha2); + if (param->reg_alpha2) { + data->alpha2[0] = param->reg_alpha2[0]; + data->alpha2[1] = param->reg_alpha2[1]; + regulatory_hint(hw->wiphy, param->reg_alpha2); + } data->debugfs = debugfs_create_dir("hwsim", hw->wiphy->debugfsdir); debugfs_create_file("ps", 0666, data->debugfs, data, &hwsim_fops_ps); @@ -2180,6 +2464,9 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, list_add_tail(&data->list, &hwsim_radios); spin_unlock_bh(&hwsim_radio_lock); + if (idx > 0) + hwsim_mcast_new_radio(idx, info, param); + return idx; failed_hw: @@ -2192,8 +2479,46 @@ failed: return err; } -static void mac80211_hwsim_destroy_radio(struct mac80211_hwsim_data *data) +static void hwsim_mcast_del_radio(int id, const char *hwname, + struct genl_info *info) +{ + struct sk_buff *skb; + void *data; + int ret; + + skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!skb) + return; + + data = genlmsg_put(skb, 0, 0, &hwsim_genl_family, 0, + HWSIM_CMD_DEL_RADIO); + if (!data) + goto error; + + ret = nla_put_u32(skb, HWSIM_ATTR_RADIO_ID, id); + if (ret < 0) + goto error; + + ret = nla_put(skb, HWSIM_ATTR_RADIO_NAME, strlen(hwname), + hwname); + if (ret < 0) + goto error; + + genlmsg_end(skb, data); + + hwsim_mcast_config_msg(skb, info); + + return; + +error: + nlmsg_free(skb); +} + +static void mac80211_hwsim_del_radio(struct mac80211_hwsim_data *data, + const char *hwname, + struct genl_info *info) { + hwsim_mcast_del_radio(data->idx, hwname, info); debugfs_remove_recursive(data->debugfs); ieee80211_unregister_hw(data->hw); device_release_driver(data->dev); @@ -2201,6 +2526,44 @@ static void mac80211_hwsim_destroy_radio(struct mac80211_hwsim_data *data) ieee80211_free_hw(data->hw); } +static int mac80211_hwsim_get_radio(struct sk_buff *skb, + struct mac80211_hwsim_data *data, + u32 portid, u32 seq, + struct netlink_callback *cb, int flags) +{ + void *hdr; + struct hwsim_new_radio_params param = { }; + int res = -EMSGSIZE; + + hdr = genlmsg_put(skb, portid, seq, &hwsim_genl_family, flags, + HWSIM_CMD_GET_RADIO); + if (!hdr) + return -EMSGSIZE; + + if (cb) + genl_dump_check_consistent(cb, hdr, &hwsim_genl_family); + + param.reg_alpha2 = data->alpha2; + param.reg_strict = !!(data->hw->wiphy->regulatory_flags & + REGULATORY_STRICT_REG); + param.p2p_device = !!(data->hw->wiphy->interface_modes & + BIT(NL80211_IFTYPE_P2P_DEVICE)); + param.use_chanctx = data->use_chanctx; + param.regd = data->regd; + param.channels = data->channels; + param.hwname = wiphy_name(data->hw->wiphy); + + res = append_radio_msg(skb, data->idx, ¶m); + if (res < 0) + goto out_err; + + return genlmsg_end(skb, hdr); + +out_err: + genlmsg_cancel(skb, hdr); + return res; +} + static void mac80211_hwsim_free(void) { struct mac80211_hwsim_data *data; @@ -2211,7 +2574,8 @@ static void mac80211_hwsim_free(void) list))) { list_del(&data->list); spin_unlock_bh(&hwsim_radio_lock); - mac80211_hwsim_destroy_radio(data); + mac80211_hwsim_del_radio(data, wiphy_name(data->hw->wiphy), + NULL); spin_lock_bh(&hwsim_radio_lock); } spin_unlock_bh(&hwsim_radio_lock); @@ -2339,7 +2703,6 @@ out: static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2, struct genl_info *info) { - struct mac80211_hwsim_data *data2; struct ieee80211_rx_status rx_status; const u8 *dst; @@ -2382,18 +2745,22 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2, /* A frame is received from user space */ memset(&rx_status, 0, sizeof(rx_status)); + /* TODO: Check ATTR_FREQ if it exists, and maybe throw away off-channel + * packets? + */ rx_status.freq = data2->channel->center_freq; rx_status.band = data2->channel->band; rx_status.rate_idx = nla_get_u32(info->attrs[HWSIM_ATTR_RX_RATE]); rx_status.signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]); memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); + data2->rx_pkts++; + data2->rx_bytes += skb->len; ieee80211_rx_irqsafe(data2->hw, skb); return 0; err: printk(KERN_DEBUG "mac80211_hwsim: error occurred in %s\n", __func__); - goto out; out: dev_kfree_skb(skb); return -EINVAL; @@ -2429,54 +2796,72 @@ static int hwsim_register_received_nl(struct sk_buff *skb_2, return 0; } -static int hwsim_create_radio_nl(struct sk_buff *msg, struct genl_info *info) +static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info) { - unsigned int chans = channels; - const char *alpha2 = NULL; - const struct ieee80211_regdomain *regd = NULL; - bool reg_strict = info->attrs[HWSIM_ATTR_REG_STRICT_REG]; - bool p2p_device = info->attrs[HWSIM_ATTR_SUPPORT_P2P_DEVICE]; - bool use_chanctx; + struct hwsim_new_radio_params param = { 0 }; + + param.reg_strict = info->attrs[HWSIM_ATTR_REG_STRICT_REG]; + param.p2p_device = info->attrs[HWSIM_ATTR_SUPPORT_P2P_DEVICE]; + param.channels = channels; + param.destroy_on_close = + info->attrs[HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE]; if (info->attrs[HWSIM_ATTR_CHANNELS]) - chans = nla_get_u32(info->attrs[HWSIM_ATTR_CHANNELS]); + param.channels = nla_get_u32(info->attrs[HWSIM_ATTR_CHANNELS]); + + if (info->attrs[HWSIM_ATTR_NO_VIF]) + param.no_vif = true; + + if (info->attrs[HWSIM_ATTR_RADIO_NAME]) + param.hwname = nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME]); if (info->attrs[HWSIM_ATTR_USE_CHANCTX]) - use_chanctx = true; + param.use_chanctx = true; else - use_chanctx = (chans > 1); + param.use_chanctx = (param.channels > 1); if (info->attrs[HWSIM_ATTR_REG_HINT_ALPHA2]) - alpha2 = nla_data(info->attrs[HWSIM_ATTR_REG_HINT_ALPHA2]); + param.reg_alpha2 = + nla_data(info->attrs[HWSIM_ATTR_REG_HINT_ALPHA2]); if (info->attrs[HWSIM_ATTR_REG_CUSTOM_REG]) { u32 idx = nla_get_u32(info->attrs[HWSIM_ATTR_REG_CUSTOM_REG]); if (idx >= ARRAY_SIZE(hwsim_world_regdom_custom)) return -EINVAL; - regd = hwsim_world_regdom_custom[idx]; + param.regd = hwsim_world_regdom_custom[idx]; } - return mac80211_hwsim_create_radio(chans, alpha2, regd, reg_strict, - p2p_device, use_chanctx); + return mac80211_hwsim_new_radio(info, ¶m); } -static int hwsim_destroy_radio_nl(struct sk_buff *msg, struct genl_info *info) +static int hwsim_del_radio_nl(struct sk_buff *msg, struct genl_info *info) { struct mac80211_hwsim_data *data; - int idx; + s64 idx = -1; + const char *hwname = NULL; - if (!info->attrs[HWSIM_ATTR_RADIO_ID]) + if (info->attrs[HWSIM_ATTR_RADIO_ID]) + idx = nla_get_u32(info->attrs[HWSIM_ATTR_RADIO_ID]); + else if (info->attrs[HWSIM_ATTR_RADIO_NAME]) + hwname = (void *)nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME]); + else return -EINVAL; - idx = nla_get_u32(info->attrs[HWSIM_ATTR_RADIO_ID]); spin_lock_bh(&hwsim_radio_lock); list_for_each_entry(data, &hwsim_radios, list) { - if (data->idx != idx) - continue; + if (idx >= 0) { + if (data->idx != idx) + continue; + } else { + if (strcmp(hwname, wiphy_name(data->hw->wiphy))) + continue; + } + list_del(&data->list); spin_unlock_bh(&hwsim_radio_lock); - mac80211_hwsim_destroy_radio(data); + mac80211_hwsim_del_radio(data, wiphy_name(data->hw->wiphy), + info); return 0; } spin_unlock_bh(&hwsim_radio_lock); @@ -2484,6 +2869,77 @@ static int hwsim_destroy_radio_nl(struct sk_buff *msg, struct genl_info *info) return -ENODEV; } +static int hwsim_get_radio_nl(struct sk_buff *msg, struct genl_info *info) +{ + struct mac80211_hwsim_data *data; + struct sk_buff *skb; + int idx, res = -ENODEV; + + if (!info->attrs[HWSIM_ATTR_RADIO_ID]) + return -EINVAL; + idx = nla_get_u32(info->attrs[HWSIM_ATTR_RADIO_ID]); + + spin_lock_bh(&hwsim_radio_lock); + list_for_each_entry(data, &hwsim_radios, list) { + if (data->idx != idx) + continue; + + skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!skb) { + res = -ENOMEM; + goto out_err; + } + + res = mac80211_hwsim_get_radio(skb, data, info->snd_portid, + info->snd_seq, NULL, 0); + if (res < 0) { + nlmsg_free(skb); + goto out_err; + } + + genlmsg_reply(skb, info); + break; + } + +out_err: + spin_unlock_bh(&hwsim_radio_lock); + + return res; +} + +static int hwsim_dump_radio_nl(struct sk_buff *skb, + struct netlink_callback *cb) +{ + int idx = cb->args[0]; + struct mac80211_hwsim_data *data = NULL; + int res; + + spin_lock_bh(&hwsim_radio_lock); + + if (idx == hwsim_radio_idx) + goto done; + + list_for_each_entry(data, &hwsim_radios, list) { + if (data->idx < idx) + continue; + + res = mac80211_hwsim_get_radio(skb, data, + NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, cb, + NLM_F_MULTI); + if (res < 0) + break; + + idx = data->idx + 1; + } + + cb->args[0] = idx; + +done: + spin_unlock_bh(&hwsim_radio_lock); + return skb->len; +} + /* Generic Netlink operations array */ static const struct genl_ops hwsim_ops[] = { { @@ -2503,19 +2959,48 @@ static const struct genl_ops hwsim_ops[] = { .doit = hwsim_tx_info_frame_received_nl, }, { - .cmd = HWSIM_CMD_CREATE_RADIO, + .cmd = HWSIM_CMD_NEW_RADIO, .policy = hwsim_genl_policy, - .doit = hwsim_create_radio_nl, + .doit = hwsim_new_radio_nl, .flags = GENL_ADMIN_PERM, }, { - .cmd = HWSIM_CMD_DESTROY_RADIO, + .cmd = HWSIM_CMD_DEL_RADIO, .policy = hwsim_genl_policy, - .doit = hwsim_destroy_radio_nl, + .doit = hwsim_del_radio_nl, .flags = GENL_ADMIN_PERM, }, + { + .cmd = HWSIM_CMD_GET_RADIO, + .policy = hwsim_genl_policy, + .doit = hwsim_get_radio_nl, + .dumpit = hwsim_dump_radio_nl, + }, }; +static void destroy_radio(struct work_struct *work) +{ + struct mac80211_hwsim_data *data = + container_of(work, struct mac80211_hwsim_data, destroy_work); + + mac80211_hwsim_del_radio(data, wiphy_name(data->hw->wiphy), NULL); +} + +static void remove_user_radios(u32 portid) +{ + struct mac80211_hwsim_data *entry, *tmp; + + spin_lock_bh(&hwsim_radio_lock); + list_for_each_entry_safe(entry, tmp, &hwsim_radios, list) { + if (entry->destroy_on_close && entry->portid == portid) { + list_del(&entry->list); + INIT_WORK(&entry->destroy_work, destroy_radio); + schedule_work(&entry->destroy_work); + } + } + spin_unlock_bh(&hwsim_radio_lock); +} + static int mac80211_hwsim_netlink_notify(struct notifier_block *nb, unsigned long state, void *_notify) @@ -2525,6 +3010,8 @@ static int mac80211_hwsim_netlink_notify(struct notifier_block *nb, if (state != NETLINK_URELEASE) return NOTIFY_DONE; + remove_user_radios(notify->portid); + if (notify->portid == wmediumd_portid) { printk(KERN_INFO "mac80211_hwsim: wmediumd released netlink" " socket, switching to perfect channel medium\n"); @@ -2544,7 +3031,9 @@ static int hwsim_init_netlink(void) printk(KERN_INFO "mac80211_hwsim: initializing netlink\n"); - rc = genl_register_family_with_ops(&hwsim_genl_family, hwsim_ops); + rc = genl_register_family_with_ops_groups(&hwsim_genl_family, + hwsim_ops, + hwsim_mcgrps); if (rc) goto failure; @@ -2605,69 +3094,73 @@ static int __init init_mac80211_hwsim(void) goto out_unregister_driver; } + err = hwsim_init_netlink(); + if (err < 0) + goto out_unregister_driver; + for (i = 0; i < radios; i++) { - const char *reg_alpha2 = NULL; - const struct ieee80211_regdomain *regd = NULL; - bool reg_strict = false; + struct hwsim_new_radio_params param = { 0 }; + + param.channels = channels; switch (regtest) { case HWSIM_REGTEST_DIFF_COUNTRY: if (i < ARRAY_SIZE(hwsim_alpha2s)) - reg_alpha2 = hwsim_alpha2s[i]; + param.reg_alpha2 = hwsim_alpha2s[i]; break; case HWSIM_REGTEST_DRIVER_REG_FOLLOW: if (!i) - reg_alpha2 = hwsim_alpha2s[0]; + param.reg_alpha2 = hwsim_alpha2s[0]; break; case HWSIM_REGTEST_STRICT_ALL: - reg_strict = true; + param.reg_strict = true; case HWSIM_REGTEST_DRIVER_REG_ALL: - reg_alpha2 = hwsim_alpha2s[0]; + param.reg_alpha2 = hwsim_alpha2s[0]; break; case HWSIM_REGTEST_WORLD_ROAM: if (i == 0) - regd = &hwsim_world_regdom_custom_01; + param.regd = &hwsim_world_regdom_custom_01; break; case HWSIM_REGTEST_CUSTOM_WORLD: - regd = &hwsim_world_regdom_custom_01; + param.regd = &hwsim_world_regdom_custom_01; break; case HWSIM_REGTEST_CUSTOM_WORLD_2: if (i == 0) - regd = &hwsim_world_regdom_custom_01; + param.regd = &hwsim_world_regdom_custom_01; else if (i == 1) - regd = &hwsim_world_regdom_custom_02; + param.regd = &hwsim_world_regdom_custom_02; break; case HWSIM_REGTEST_STRICT_FOLLOW: if (i == 0) { - reg_strict = true; - reg_alpha2 = hwsim_alpha2s[0]; + param.reg_strict = true; + param.reg_alpha2 = hwsim_alpha2s[0]; } break; case HWSIM_REGTEST_STRICT_AND_DRIVER_REG: if (i == 0) { - reg_strict = true; - reg_alpha2 = hwsim_alpha2s[0]; + param.reg_strict = true; + param.reg_alpha2 = hwsim_alpha2s[0]; } else if (i == 1) { - reg_alpha2 = hwsim_alpha2s[1]; + param.reg_alpha2 = hwsim_alpha2s[1]; } break; case HWSIM_REGTEST_ALL: switch (i) { case 0: - regd = &hwsim_world_regdom_custom_01; + param.regd = &hwsim_world_regdom_custom_01; break; case 1: - regd = &hwsim_world_regdom_custom_02; + param.regd = &hwsim_world_regdom_custom_02; break; case 2: - reg_alpha2 = hwsim_alpha2s[0]; + param.reg_alpha2 = hwsim_alpha2s[0]; break; case 3: - reg_alpha2 = hwsim_alpha2s[1]; + param.reg_alpha2 = hwsim_alpha2s[1]; break; case 4: - reg_strict = true; - reg_alpha2 = hwsim_alpha2s[2]; + param.reg_strict = true; + param.reg_alpha2 = hwsim_alpha2s[2]; break; } break; @@ -2675,10 +3168,10 @@ static int __init init_mac80211_hwsim(void) break; } - err = mac80211_hwsim_create_radio(channels, reg_alpha2, - regd, reg_strict, - support_p2p_device, - channels > 1); + param.p2p_device = support_p2p_device; + param.use_chanctx = channels > 1; + + err = mac80211_hwsim_new_radio(NULL, ¶m); if (err < 0) goto out_free_radios; } @@ -2704,10 +3197,6 @@ static int __init init_mac80211_hwsim(void) } rtnl_unlock(); - err = hwsim_init_netlink(); - if (err < 0) - goto out_free_mon; - return 0; out_free_mon: diff --git a/drivers/net/wireless/mac80211_hwsim.h b/drivers/net/wireless/mac80211_hwsim.h index c9d0315575ba..66e1c73bd507 100644 --- a/drivers/net/wireless/mac80211_hwsim.h +++ b/drivers/net/wireless/mac80211_hwsim.h @@ -60,14 +60,17 @@ enum hwsim_tx_control_flags { * space, uses: * %HWSIM_ATTR_ADDR_TRANSMITTER, %HWSIM_ATTR_ADDR_RECEIVER, * %HWSIM_ATTR_FRAME, %HWSIM_ATTR_FLAGS, %HWSIM_ATTR_RX_RATE, - * %HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_COOKIE + * %HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_COOKIE, %HWSIM_ATTR_FREQ (optional) * @HWSIM_CMD_TX_INFO_FRAME: Transmission info report from user space to * kernel, uses: * %HWSIM_ATTR_ADDR_TRANSMITTER, %HWSIM_ATTR_FLAGS, * %HWSIM_ATTR_TX_INFO, %HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_COOKIE - * @HWSIM_CMD_CREATE_RADIO: create a new radio with the given parameters, - * returns the radio ID (>= 0) or negative on errors - * @HWSIM_CMD_DESTROY_RADIO: destroy a radio + * @HWSIM_CMD_NEW_RADIO: create a new radio with the given parameters, + * returns the radio ID (>= 0) or negative on errors, if successful + * then multicast the result + * @HWSIM_CMD_DEL_RADIO: destroy a radio, reply is multicasted + * @HWSIM_CMD_GET_RADIO: fetch information about existing radios, uses: + * %HWSIM_ATTR_RADIO_ID * @__HWSIM_CMD_MAX: enum limit */ enum { @@ -75,12 +78,16 @@ enum { HWSIM_CMD_REGISTER, HWSIM_CMD_FRAME, HWSIM_CMD_TX_INFO_FRAME, - HWSIM_CMD_CREATE_RADIO, - HWSIM_CMD_DESTROY_RADIO, + HWSIM_CMD_NEW_RADIO, + HWSIM_CMD_DEL_RADIO, + HWSIM_CMD_GET_RADIO, __HWSIM_CMD_MAX, }; #define HWSIM_CMD_MAX (_HWSIM_CMD_MAX - 1) +#define HWSIM_CMD_CREATE_RADIO HWSIM_CMD_NEW_RADIO +#define HWSIM_CMD_DESTROY_RADIO HWSIM_CMD_DEL_RADIO + /** * enum hwsim_attrs - hwsim netlink attributes * @@ -111,6 +118,11 @@ enum { * @HWSIM_ATTR_USE_CHANCTX: used with the %HWSIM_CMD_CREATE_RADIO * command to force use of channel contexts even when only a * single channel is supported + * @HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE: used with the %HWSIM_CMD_CREATE_RADIO + * command to force radio removal when process that created the radio dies + * @HWSIM_ATTR_RADIO_NAME: Name of radio, e.g. phy666 + * @HWSIM_ATTR_NO_VIF: Do not create vif (wlanX) when creating radio. + * @HWSIM_ATTR_FREQ: Frequency at which packet is transmitted or received. * @__HWSIM_ATTR_MAX: enum limit */ @@ -132,6 +144,10 @@ enum { HWSIM_ATTR_REG_STRICT_REG, HWSIM_ATTR_SUPPORT_P2P_DEVICE, HWSIM_ATTR_USE_CHANCTX, + HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE, + HWSIM_ATTR_RADIO_NAME, + HWSIM_ATTR_NO_VIF, + HWSIM_ATTR_FREQ, __HWSIM_ATTR_MAX, }; #define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1) diff --git a/drivers/net/wireless/mwifiex/11n.h b/drivers/net/wireless/mwifiex/11n.h index 2ee268b632be..f275675cdbd3 100644 --- a/drivers/net/wireless/mwifiex/11n.h +++ b/drivers/net/wireless/mwifiex/11n.h @@ -84,6 +84,8 @@ mwifiex_is_amsdu_in_ampdu_allowed(struct mwifiex_private *priv, { struct mwifiex_tx_ba_stream_tbl *tx_tbl; + if (is_broadcast_ether_addr(ptr->ra)) + return false; tx_tbl = mwifiex_get_ba_tbl(priv, tid, ptr->ra); if (tx_tbl) return tx_tbl->amsdu; @@ -96,6 +98,8 @@ static inline u8 mwifiex_is_ampdu_allowed(struct mwifiex_private *priv, struct mwifiex_ra_list_tbl *ptr, int tid) { + if (is_broadcast_ether_addr(ptr->ra)) + return false; if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) { return mwifiex_is_station_ampdu_allowed(priv, ptr, tid); } else { diff --git a/drivers/net/wireless/mwifiex/Kconfig b/drivers/net/wireless/mwifiex/Kconfig index e70d0df9b0da..aa01c9bc77f9 100644 --- a/drivers/net/wireless/mwifiex/Kconfig +++ b/drivers/net/wireless/mwifiex/Kconfig @@ -31,7 +31,7 @@ config MWIFIEX_PCIE mwifiex_pcie. config MWIFIEX_USB - tristate "Marvell WiFi-Ex Driver for USB8797/8897" + tristate "Marvell WiFi-Ex Driver for USB8766/8797/8897" depends on MWIFIEX && USB select FW_LOADER ---help--- diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 0dd672954ad1..17f0ee02d6e7 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -992,6 +992,52 @@ mwifiex_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *dev, return mwifiex_dump_station_info(priv, sinfo); } +static int +mwifiex_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *dev, + int idx, struct survey_info *survey) +{ + struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); + struct mwifiex_chan_stats *pchan_stats = priv->adapter->chan_stats; + enum ieee80211_band band; + + dev_dbg(priv->adapter->dev, "dump_survey idx=%d\n", idx); + + memset(survey, 0, sizeof(struct survey_info)); + + if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) && + priv->media_connected && idx == 0) { + u8 curr_bss_band = priv->curr_bss_params.band; + u32 chan = priv->curr_bss_params.bss_descriptor.channel; + + band = mwifiex_band_to_radio_type(curr_bss_band); + survey->channel = ieee80211_get_channel(wiphy, + ieee80211_channel_to_frequency(chan, band)); + + if (priv->bcn_nf_last) { + survey->filled = SURVEY_INFO_NOISE_DBM; + survey->noise = priv->bcn_nf_last; + } + return 0; + } + + if (idx >= priv->adapter->num_in_chan_stats) + return -ENOENT; + + if (!pchan_stats[idx].cca_scan_dur) + return 0; + + band = pchan_stats[idx].bandcfg; + survey->channel = ieee80211_get_channel(wiphy, + ieee80211_channel_to_frequency(pchan_stats[idx].chan_num, band)); + survey->filled = SURVEY_INFO_NOISE_DBM | + SURVEY_INFO_CHANNEL_TIME | SURVEY_INFO_CHANNEL_TIME_BUSY; + survey->noise = pchan_stats[idx].noise; + survey->channel_time = pchan_stats[idx].cca_scan_dur; + survey->channel_time_busy = pchan_stats[idx].cca_busy_dur; + + return 0; +} + /* Supported rates to be advertised to the cfg80211 */ static struct ieee80211_rate mwifiex_rates[] = { {.bitrate = 10, .hw_value = 2, }, @@ -1239,7 +1285,7 @@ static int mwifiex_cfg80211_change_beacon(struct wiphy *wiphy, */ static int mwifiex_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, - const u8 *mac) + struct station_del_parameters *params) { struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); struct mwifiex_sta_node *sta_node; @@ -1248,7 +1294,7 @@ mwifiex_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, if (list_empty(&priv->sta_list) || !priv->bss_started) return 0; - if (!mac || is_broadcast_ether_addr(mac)) { + if (!params->mac || is_broadcast_ether_addr(params->mac)) { wiphy_dbg(wiphy, "%s: NULL/broadcast mac address\n", __func__); list_for_each_entry(sta_node, &priv->sta_list, list) { if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_STA_DEAUTH, @@ -1258,9 +1304,10 @@ mwifiex_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, mwifiex_uap_del_sta_data(priv, sta_node); } } else { - wiphy_dbg(wiphy, "%s: mac address %pM\n", __func__, mac); + wiphy_dbg(wiphy, "%s: mac address %pM\n", __func__, + params->mac); spin_lock_irqsave(&priv->sta_list_spinlock, flags); - sta_node = mwifiex_get_sta_entry(priv, mac); + sta_node = mwifiex_get_sta_entry(priv, params->mac); spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); if (sta_node) { if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_STA_DEAUTH, @@ -1759,6 +1806,10 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, dev_dbg(priv->adapter->dev, "info: associated to bssid %pM successfully\n", priv->cfg_bssid); + if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) && + priv->adapter->auto_tdls && + priv->bss_type == MWIFIEX_BSS_TYPE_STA) + mwifiex_setup_auto_tdls_timer(priv); } else { dev_dbg(priv->adapter->dev, "info: association to bssid %pM failed\n", @@ -2630,11 +2681,13 @@ mwifiex_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, dev_dbg(priv->adapter->dev, "Send TDLS Setup Request to %pM status_code=%d\n", peer, status_code); + mwifiex_add_auto_tdls_peer(priv, peer); ret = mwifiex_send_tdls_data_frame(priv, peer, action_code, dialog_token, status_code, extra_ies, extra_ies_len); break; case WLAN_TDLS_SETUP_RESPONSE: + mwifiex_add_auto_tdls_peer(priv, peer); dev_dbg(priv->adapter->dev, "Send TDLS Setup Response to %pM status_code=%d\n", peer, status_code); @@ -2779,6 +2832,7 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { .disconnect = mwifiex_cfg80211_disconnect, .get_station = mwifiex_cfg80211_get_station, .dump_station = mwifiex_cfg80211_dump_station, + .dump_survey = mwifiex_cfg80211_dump_survey, .set_wiphy_params = mwifiex_cfg80211_set_wiphy_params, .join_ibss = mwifiex_cfg80211_join_ibss, .leave_ibss = mwifiex_cfg80211_leave_ibss, @@ -2840,6 +2894,25 @@ static const struct wiphy_coalesce_support mwifiex_coalesce_support = { .max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN, }; +int mwifiex_init_channel_scan_gap(struct mwifiex_adapter *adapter) +{ + u32 n_channels_bg, n_channels_a = 0; + + n_channels_bg = mwifiex_band_2ghz.n_channels; + + if (adapter->config_bands & BAND_A) + n_channels_a = mwifiex_band_5ghz.n_channels; + + adapter->num_in_chan_stats = max_t(u32, n_channels_bg, n_channels_a); + adapter->chan_stats = vmalloc(sizeof(*adapter->chan_stats) * + adapter->num_in_chan_stats); + + if (!adapter->chan_stats) + return -ENOMEM; + + return 0; +} + /* * This function registers the device with CFG802.11 subsystem. * diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h index e0d00a7f0ec3..fc0b1ed80a6a 100644 --- a/drivers/net/wireless/mwifiex/decl.h +++ b/drivers/net/wireless/mwifiex/decl.h @@ -85,6 +85,11 @@ #define MWIFIEX_TDLS_CREATE_LINK 0x02 #define MWIFIEX_TDLS_CONFIG_LINK 0x03 +#define MWIFIEX_TDLS_RSSI_HIGH 50 +#define MWIFIEX_TDLS_RSSI_LOW 55 +#define MWIFIEX_TDLS_MAX_FAIL_COUNT 4 +#define MWIFIEX_AUTO_TDLS_IDLE_TIME 10 + enum mwifiex_bss_type { MWIFIEX_BSS_TYPE_STA = 0, MWIFIEX_BSS_TYPE_UAP = 1, @@ -185,4 +190,14 @@ struct mwifiex_arp_eth_header { u8 ar_tha[ETH_ALEN]; u8 ar_tip[4]; } __packed; + +struct mwifiex_chan_stats { + u8 chan_num; + u8 bandcfg; + u8 flags; + s8 noise; + u16 total_bss; + u16 cca_scan_dur; + u16 cca_busy_dur; +} __packed; #endif /* !_MWIFIEX_DECL_H_ */ diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 1eb61739071f..e095f371545a 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -172,6 +172,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { #define TLV_TYPE_TDLS_IDLE_TIMEOUT (PROPRIETARY_TLV_BASE_ID + 194) #define TLV_TYPE_SCAN_CHANNEL_GAP (PROPRIETARY_TLV_BASE_ID + 197) #define TLV_TYPE_API_REV (PROPRIETARY_TLV_BASE_ID + 199) +#define TLV_TYPE_CHANNEL_STATS (PROPRIETARY_TLV_BASE_ID + 198) #define MWIFIEX_TX_DATA_BUF_SIZE_2K 2048 @@ -583,6 +584,7 @@ struct rxpd { * [Bit 7] Reserved */ u8 ht_info; + u8 reserved[3]; u8 flags; } __packed; @@ -611,6 +613,16 @@ struct uap_rxpd { u8 reserved1; }; +struct mwifiex_fw_chan_stats { + u8 chan_num; + u8 bandcfg; + u8 flags; + s8 noise; + __le16 total_bss; + __le16 cca_scan_dur; + __le16 cca_busy_dur; +} __packed; + enum mwifiex_chan_scan_mode_bitmasks { MWIFIEX_PASSIVE_SCAN = BIT(0), MWIFIEX_DISABLE_CHAN_FILT = BIT(1), @@ -660,6 +672,11 @@ struct mwifiex_ie_types_scan_chan_gap { __le16 chan_gap; } __packed; +struct mwifiex_ietypes_chanstats { + struct mwifiex_ie_types_header header; + struct mwifiex_fw_chan_stats chanstats[0]; +} __packed; + struct mwifiex_ie_types_wildcard_ssid_params { struct mwifiex_ie_types_header header; u8 max_ssid_length; diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index 580aa45ec4bc..cc15ab81aa66 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c @@ -137,6 +137,7 @@ int mwifiex_init_priv(struct mwifiex_private *priv) priv->csa_expire_time = 0; priv->del_list_idx = 0; priv->hs2_enabled = false; + priv->check_tdls_tx = false; memcpy(priv->tos_to_tid_inv, tos_to_tid_inv, MAX_NUM_TID); return mwifiex_add_bss_prio_tbl(priv); @@ -366,6 +367,7 @@ static void mwifiex_free_lock_list(struct mwifiex_adapter *adapter) list_del(&priv->tx_ba_stream_tbl_ptr); list_del(&priv->rx_reorder_tbl_ptr); list_del(&priv->sta_list); + list_del(&priv->auto_tdls_list); } } } @@ -434,6 +436,7 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter) spin_lock_init(&priv->wmm.ra_list_spinlock); spin_lock_init(&priv->curr_bcn_buf_lock); spin_lock_init(&priv->sta_list_spinlock); + spin_lock_init(&priv->auto_tdls_lock); } } @@ -449,7 +452,6 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter) spin_lock_init(&adapter->scan_pending_q_lock); spin_lock_init(&adapter->rx_proc_lock); - skb_queue_head_init(&adapter->usb_rx_data_q); skb_queue_head_init(&adapter->rx_data_q); for (i = 0; i < adapter->priv_num; ++i) { @@ -466,6 +468,7 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter) INIT_LIST_HEAD(&priv->tx_ba_stream_tbl_ptr); INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr); INIT_LIST_HEAD(&priv->sta_list); + INIT_LIST_HEAD(&priv->auto_tdls_list); skb_queue_head_init(&priv->tdls_txq); spin_lock_init(&priv->tx_ba_stream_tbl_lock); @@ -646,6 +649,7 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter) if (adapter->priv[i]) { priv = adapter->priv[i]; + mwifiex_clean_auto_tdls(priv); mwifiex_clean_txrx(priv); mwifiex_delete_bss_prio_tbl(priv); } @@ -668,19 +672,6 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter) spin_lock(&adapter->mwifiex_lock); - if (adapter->if_ops.data_complete) { - while ((skb = skb_dequeue(&adapter->usb_rx_data_q))) { - struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); - - priv = adapter->priv[rx_info->bss_num]; - if (priv) - priv->stats.rx_dropped++; - - dev_kfree_skb_any(skb); - adapter->if_ops.data_complete(adapter); - } - } - mwifiex_adapter_cleanup(adapter); spin_unlock(&adapter->mwifiex_lock); diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index 8d6c25908b6d..411a6c2f4aca 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c @@ -880,9 +880,7 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv, /* Set Capability info */ bss_desc->cap_info_bitmap |= WLAN_CAPABILITY_IBSS; - tmp_cap = le16_to_cpu(adhoc_start->cap_info_bitmap); - tmp_cap &= ~WLAN_CAPABILITY_ESS; - tmp_cap |= WLAN_CAPABILITY_IBSS; + tmp_cap = WLAN_CAPABILITY_IBSS; /* Set up privacy in bss_desc */ if (priv->sec_info.encryption_mode) { diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index d5070c444fe1..0e50120eb807 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -28,6 +28,11 @@ const char driver_version[] = "mwifiex " VERSION " (%s) "; static char *cal_data_cfg; module_param(cal_data_cfg, charp, 0); +static unsigned short driver_mode; +module_param(driver_mode, ushort, 0); +MODULE_PARM_DESC(driver_mode, + "station=0x1(default), ap-sta=0x3, station-p2p=0x5, ap-sta-p2p=0x7"); + /* * This function registers the device and performs all the necessary * initializations. @@ -122,6 +127,7 @@ static int mwifiex_unregister(struct mwifiex_adapter *adapter) } } + vfree(adapter->chan_stats); kfree(adapter); return 0; } @@ -145,6 +151,8 @@ static int mwifiex_process_rx(struct mwifiex_adapter *adapter) atomic_dec(&adapter->rx_pending); if (adapter->delay_main_work && (atomic_read(&adapter->rx_pending) < LOW_RX_PENDING)) { + if (adapter->if_ops.submit_rem_rx_urbs) + adapter->if_ops.submit_rem_rx_urbs(adapter); adapter->delay_main_work = false; queue_work(adapter->workqueue, &adapter->main_work); } @@ -177,7 +185,6 @@ int mwifiex_main_process(struct mwifiex_adapter *adapter) { int ret = 0; unsigned long flags; - struct sk_buff *skb; spin_lock_irqsave(&adapter->main_proc_lock, flags); @@ -252,11 +259,6 @@ process_start: } } - /* Check Rx data for USB */ - if (adapter->iface_type == MWIFIEX_USB) - while ((skb = skb_dequeue(&adapter->usb_rx_data_q))) - mwifiex_handle_rx_packet(adapter, skb); - /* Check for event */ if (adapter->event_received) { adapter->event_received = false; @@ -447,6 +449,16 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context) goto err_init_fw; } + if (mwifiex_init_channel_scan_gap(adapter)) { + dev_err(adapter->dev, "could not init channel stats table\n"); + goto err_init_fw; + } + + if (driver_mode) { + driver_mode &= MWIFIEX_DRIVER_MODE_BITMASK; + driver_mode |= MWIFIEX_DRIVER_MODE_STA; + } + rtnl_lock(); /* Create station interface by default */ wdev = mwifiex_add_virtual_intf(adapter->wiphy, "mlan%d", @@ -456,6 +468,28 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context) rtnl_unlock(); goto err_add_intf; } + + if (driver_mode & MWIFIEX_DRIVER_MODE_UAP) { + wdev = mwifiex_add_virtual_intf(adapter->wiphy, "uap%d", + NL80211_IFTYPE_AP, NULL, NULL); + if (IS_ERR(wdev)) { + dev_err(adapter->dev, "cannot create AP interface\n"); + rtnl_unlock(); + goto err_add_intf; + } + } + + if (driver_mode & MWIFIEX_DRIVER_MODE_P2P) { + wdev = mwifiex_add_virtual_intf(adapter->wiphy, "p2p%d", + NL80211_IFTYPE_P2P_CLIENT, NULL, + NULL); + if (IS_ERR(wdev)) { + dev_err(adapter->dev, + "cannot create p2p client interface\n"); + rtnl_unlock(); + goto err_add_intf; + } + } rtnl_unlock(); mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1); @@ -628,6 +662,13 @@ mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) */ __net_timestamp(skb); + if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) && + priv->bss_type == MWIFIEX_BSS_TYPE_STA && + !ether_addr_equal_unaligned(priv->cfg_bssid, skb->data)) { + if (priv->adapter->auto_tdls && priv->check_tdls_tx) + mwifiex_tdls_check_tx(priv, skb); + } + mwifiex_queue_tx_pkt(priv, skb); return 0; @@ -858,7 +899,7 @@ mwifiex_add_card(void *card, struct semaphore *sem, adapter->cmd_wait_q.status = 0; adapter->scan_wait_q_woken = false; - if (num_possible_cpus() > 1) { + if ((num_possible_cpus() > 1) || adapter->iface_type == MWIFIEX_USB) { adapter->rx_work_enabled = true; pr_notice("rx work enabled, cpus %d\n", num_possible_cpus()); } diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index f55658d15c60..5a690d5210f0 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -48,6 +48,11 @@ enum { MWIFIEX_SYNC_CMD }; +#define MWIFIEX_DRIVER_MODE_STA BIT(0) +#define MWIFIEX_DRIVER_MODE_UAP BIT(1) +#define MWIFIEX_DRIVER_MODE_P2P BIT(2) +#define MWIFIEX_DRIVER_MODE_BITMASK (BIT(0) | BIT(1) | BIT(2)) + #define MWIFIEX_MAX_AP 64 #define MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT (5 * HZ) @@ -106,10 +111,7 @@ enum { */ #define IS_CARD_RX_RCVD(adapter) (adapter->cmd_resp_received || \ adapter->event_received || \ - ((adapter->iface_type != MWIFIEX_USB) && \ - adapter->data_received) || \ - ((adapter->iface_type == MWIFIEX_USB) && \ - !skb_queue_empty(&adapter->usb_rx_data_q))) + adapter->data_received) #define MWIFIEX_TYPE_CMD 1 #define MWIFIEX_TYPE_DATA 0 @@ -504,8 +506,11 @@ struct mwifiex_private { struct mwifiex_wmm_desc wmm; atomic_t wmm_tx_pending[IEEE80211_NUM_ACS]; struct list_head sta_list; - /* spin lock for associated station list */ + /* spin lock for associated station/TDLS peers list */ spinlock_t sta_list_spinlock; + struct list_head auto_tdls_list; + /* spin lock for auto TDLS peer list */ + spinlock_t auto_tdls_lock; struct list_head tx_ba_stream_tbl_ptr; /* spin lock for tx_ba_stream_tbl_ptr queue */ spinlock_t tx_ba_stream_tbl_lock; @@ -570,6 +575,9 @@ struct mwifiex_private { bool hs2_enabled; struct station_parameters *sta_params; struct sk_buff_head tdls_txq; + u8 check_tdls_tx; + struct timer_list auto_tdls_timer; + bool auto_tdls_timer_active; }; enum mwifiex_ba_status { @@ -670,6 +678,17 @@ struct mwifiex_sta_node { struct mwifiex_tdls_capab tdls_cap; }; +struct mwifiex_auto_tdls_peer { + struct list_head list; + u8 mac_addr[ETH_ALEN]; + u8 tdls_status; + int rssi; + long rssi_jiffies; + u8 failure_count; + u8 do_discover; + u8 do_setup; +}; + struct mwifiex_if_ops { int (*init_if) (struct mwifiex_adapter *); void (*cleanup_if) (struct mwifiex_adapter *); @@ -690,13 +709,13 @@ struct mwifiex_if_ops { void (*cleanup_mpa_buf) (struct mwifiex_adapter *); int (*cmdrsp_complete) (struct mwifiex_adapter *, struct sk_buff *); int (*event_complete) (struct mwifiex_adapter *, struct sk_buff *); - int (*data_complete) (struct mwifiex_adapter *); int (*init_fw_port) (struct mwifiex_adapter *); int (*dnld_fw) (struct mwifiex_adapter *, struct mwifiex_fw_image *); void (*card_reset) (struct mwifiex_adapter *); void (*fw_dump)(struct mwifiex_adapter *); int (*clean_pcie_ring) (struct mwifiex_adapter *adapter); void (*iface_work)(struct work_struct *work); + void (*submit_rem_rx_urbs)(struct mwifiex_adapter *adapter); }; struct mwifiex_adapter { @@ -767,7 +786,6 @@ struct mwifiex_adapter { spinlock_t scan_pending_q_lock; /* spin lock for RX processing routine */ spinlock_t rx_proc_lock; - struct sk_buff_head usb_rx_data_q; u32 scan_processing; u16 region_code; struct mwifiex_802_11d_domain_reg domain_reg; @@ -845,6 +863,10 @@ struct mwifiex_adapter { u8 curr_mem_idx; bool scan_chan_gap_enabled; struct sk_buff_head rx_data_q; + struct mwifiex_chan_stats *chan_stats; + u32 num_in_chan_stats; + int survey_idx; + bool auto_tdls; }; int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); @@ -1031,7 +1053,8 @@ void mwifiex_set_11ac_ba_params(struct mwifiex_private *priv); int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv, struct host_cmd_ds_command *cmd, void *data_buf); -int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv); +int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp); int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv, void *buf); @@ -1301,6 +1324,17 @@ u8 mwifiex_get_center_freq_index(struct mwifiex_private *priv, u8 band, u32 pri_chan, u8 chan_bw); int mwifiex_init_channel_scan_gap(struct mwifiex_adapter *adapter); +int mwifiex_tdls_check_tx(struct mwifiex_private *priv, struct sk_buff *skb); +void mwifiex_flush_auto_tdls_list(struct mwifiex_private *priv); +void mwifiex_auto_tdls_update_peer_status(struct mwifiex_private *priv, + const u8 *mac, u8 link_status); +void mwifiex_auto_tdls_update_peer_signal(struct mwifiex_private *priv, + u8 *mac, s8 snr, s8 nflr); +void mwifiex_check_auto_tdls(unsigned long context); +void mwifiex_add_auto_tdls_peer(struct mwifiex_private *priv, const u8 *mac); +void mwifiex_setup_auto_tdls_timer(struct mwifiex_private *priv); +void mwifiex_clean_auto_tdls(struct mwifiex_private *priv); + #ifdef CONFIG_DEBUG_FS void mwifiex_debugfs_init(void); void mwifiex_debugfs_remove(void); diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index ca64d4c94112..3a17821157d7 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -1755,6 +1755,7 @@ static void mwifiex_complete_scan(struct mwifiex_private *priv) { struct mwifiex_adapter *adapter = priv->adapter; + adapter->survey_idx = 0; if (adapter->curr_cmd->wait_q_enabled) { adapter->cmd_wait_q.status = 0; if (!priv->scan_request) { @@ -1976,10 +1977,53 @@ int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv, return 0; } +static void +mwifiex_update_chan_statistics(struct mwifiex_private *priv, + struct mwifiex_ietypes_chanstats *tlv_stat) +{ + struct mwifiex_adapter *adapter = priv->adapter; + u8 i, num_chan; + struct mwifiex_fw_chan_stats *fw_chan_stats; + struct mwifiex_chan_stats chan_stats; + + fw_chan_stats = (void *)((u8 *)tlv_stat + + sizeof(struct mwifiex_ie_types_header)); + num_chan = le16_to_cpu(tlv_stat->header.len) / + sizeof(struct mwifiex_chan_stats); + + for (i = 0 ; i < num_chan; i++) { + chan_stats.chan_num = fw_chan_stats->chan_num; + chan_stats.bandcfg = fw_chan_stats->bandcfg; + chan_stats.flags = fw_chan_stats->flags; + chan_stats.noise = fw_chan_stats->noise; + chan_stats.total_bss = le16_to_cpu(fw_chan_stats->total_bss); + chan_stats.cca_scan_dur = + le16_to_cpu(fw_chan_stats->cca_scan_dur); + chan_stats.cca_busy_dur = + le16_to_cpu(fw_chan_stats->cca_busy_dur); + dev_dbg(adapter->dev, + "chan=%d, noise=%d, total_network=%d scan_duration=%d, busy_duration=%d\n", + chan_stats.chan_num, + chan_stats.noise, + chan_stats.total_bss, + chan_stats.cca_scan_dur, + chan_stats.cca_busy_dur); + memcpy(&adapter->chan_stats[adapter->survey_idx++], &chan_stats, + sizeof(struct mwifiex_chan_stats)); + fw_chan_stats++; + } +} + /* This function handles the command response of extended scan */ -int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv) +int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp) { struct mwifiex_adapter *adapter = priv->adapter; + struct host_cmd_ds_802_11_scan_ext *ext_scan_resp; + struct mwifiex_ie_types_header *tlv; + struct mwifiex_ietypes_chanstats *tlv_stat; + u16 buf_left, type, len; + struct host_cmd_ds_command *cmd_ptr; struct cmd_ctrl_node *cmd_node; unsigned long cmd_flags, scan_flags; @@ -1987,6 +2031,36 @@ int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv) dev_dbg(priv->adapter->dev, "info: EXT scan returns successfully\n"); + ext_scan_resp = &resp->params.ext_scan; + + tlv = (void *)ext_scan_resp->tlv_buffer; + buf_left = le16_to_cpu(resp->size) - (sizeof(*ext_scan_resp) + S_DS_GEN + - 1); + + while (buf_left >= sizeof(struct mwifiex_ie_types_header)) { + type = le16_to_cpu(tlv->type); + len = le16_to_cpu(tlv->len); + + if (buf_left < (sizeof(struct mwifiex_ie_types_header) + len)) { + dev_err(adapter->dev, + "error processing scan response TLVs"); + break; + } + + switch (type) { + case TLV_TYPE_CHANNEL_STATS: + tlv_stat = (void *)tlv; + mwifiex_update_chan_statistics(priv, tlv_stat); + break; + default: + break; + } + + buf_left -= len + sizeof(struct mwifiex_ie_types_header); + tlv = (void *)((u8 *)tlv + len + + sizeof(struct mwifiex_ie_types_header)); + } + spin_lock_irqsave(&adapter->cmd_pending_q_lock, cmd_flags); spin_lock_irqsave(&adapter->scan_pending_q_lock, scan_flags); if (list_empty(&adapter->scan_pending_q)) { diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index b25766b43b9f..933dae137850 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c @@ -106,6 +106,7 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) card->mp_tx_agg_buf_size = data->mp_tx_agg_buf_size; card->mp_rx_agg_buf_size = data->mp_rx_agg_buf_size; card->supports_fw_dump = data->supports_fw_dump; + card->auto_tdls = data->auto_tdls; } sdio_claim_host(func); @@ -1880,6 +1881,7 @@ static int mwifiex_init_sdio(struct mwifiex_adapter *adapter) return -1; } + adapter->auto_tdls = card->auto_tdls; return ret; } diff --git a/drivers/net/wireless/mwifiex/sdio.h b/drivers/net/wireless/mwifiex/sdio.h index 20cd9adc98d3..54c07156dd78 100644 --- a/drivers/net/wireless/mwifiex/sdio.h +++ b/drivers/net/wireless/mwifiex/sdio.h @@ -246,6 +246,7 @@ struct sdio_mmc_card { u8 curr_wr_port; u8 *mp_regs; + u8 auto_tdls; struct mwifiex_sdio_mpa_tx mpa_tx; struct mwifiex_sdio_mpa_rx mpa_rx; @@ -262,6 +263,7 @@ struct mwifiex_sdio_device { u16 tx_buf_size; u32 mp_tx_agg_buf_size; u32 mp_rx_agg_buf_size; + u8 auto_tdls; }; static const struct mwifiex_sdio_card_reg mwifiex_reg_sd87xx = { @@ -387,6 +389,7 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8786 = { .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, .supports_fw_dump = false, + .auto_tdls = false, }; static const struct mwifiex_sdio_device mwifiex_sdio_sd8787 = { @@ -400,6 +403,7 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8787 = { .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, .supports_fw_dump = false, + .auto_tdls = false, }; static const struct mwifiex_sdio_device mwifiex_sdio_sd8797 = { @@ -413,6 +417,7 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8797 = { .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, .supports_fw_dump = false, + .auto_tdls = false, }; static const struct mwifiex_sdio_device mwifiex_sdio_sd8897 = { @@ -426,6 +431,7 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8897 = { .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K, .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K, .supports_fw_dump = true, + .auto_tdls = false, }; static const struct mwifiex_sdio_device mwifiex_sdio_sd8887 = { @@ -439,6 +445,7 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8887 = { .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K, .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K, .supports_fw_dump = false, + .auto_tdls = true, }; /* diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index 4aad44685f8d..b65e1014b0fc 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c @@ -983,7 +983,7 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, adapter->curr_cmd->wait_q_enabled = false; break; case HostCmd_CMD_802_11_SCAN_EXT: - ret = mwifiex_ret_802_11_scan_ext(priv); + ret = mwifiex_ret_802_11_scan_ext(priv, resp); adapter->curr_cmd->wait_q_enabled = false; break; case HostCmd_CMD_802_11_BG_SCAN_QUERY: diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c index f1c240eca0cd..204ecc8faa5b 100644 --- a/drivers/net/wireless/mwifiex/sta_event.c +++ b/drivers/net/wireless/mwifiex/sta_event.c @@ -55,9 +55,13 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason_code) priv->scan_block = false; if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) && - ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info)) + 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); @@ -163,9 +167,6 @@ static int mwifiex_parse_tdls_event(struct mwifiex_private *priv, NL80211_TDLS_TEARDOWN, le16_to_cpu(tdls_evt->u.reason_code), GFP_KERNEL); - ret = mwifiex_tdls_oper(priv, tdls_evt->peer_mac, - MWIFIEX_TDLS_DISABLE_LINK); - queue_work(adapter->workqueue, &adapter->main_work); break; default: break; diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 92f3eb839866..1626868a4b5c 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -1026,12 +1026,12 @@ mwifiex_drv_get_driver_version(struct mwifiex_adapter *adapter, char *version, int max_len) { union { - u32 l; + __le32 l; u8 c[4]; } ver; char fw_ver[32]; - ver.l = adapter->fw_release_number; + ver.l = cpu_to_le32(adapter->fw_release_number); sprintf(fw_ver, "%u.%u.%u.p%u", ver.c[2], ver.c[1], ver.c[0], ver.c[3]); snprintf(version, max_len, driver_version, fw_ver); diff --git a/drivers/net/wireless/mwifiex/sta_rx.c b/drivers/net/wireless/mwifiex/sta_rx.c index 9ceb1dbe34c5..c2ad3b63ae70 100644 --- a/drivers/net/wireless/mwifiex/sta_rx.c +++ b/drivers/net/wireless/mwifiex/sta_rx.c @@ -232,6 +232,9 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv, if (sta_ptr) sta_ptr->rx_seq[local_rx_pd->priority] = le16_to_cpu(local_rx_pd->seq_num); + mwifiex_auto_tdls_update_peer_signal(priv, ta, + local_rx_pd->snr, + local_rx_pd->nf); } } else { if (rx_pkt_type != PKT_TYPE_BAR) diff --git a/drivers/net/wireless/mwifiex/tdls.c b/drivers/net/wireless/mwifiex/tdls.c index e2949077f5b5..22884b429be7 100644 --- a/drivers/net/wireless/mwifiex/tdls.c +++ b/drivers/net/wireless/mwifiex/tdls.c @@ -24,6 +24,7 @@ #define TDLS_REQ_FIX_LEN 6 #define TDLS_RESP_FIX_LEN 8 #define TDLS_CONFIRM_FIX_LEN 6 +#define MWIFIEX_TDLS_WMM_INFO_SIZE 7 static void mwifiex_restore_tdls_packets(struct mwifiex_private *priv, const u8 *mac, u8 status) @@ -367,6 +368,55 @@ static void mwifiex_tdls_add_qos_capab(struct sk_buff *skb) *pos++ = MWIFIEX_TDLS_DEF_QOS_CAPAB; } +static void +mwifiex_tdls_add_wmm_param_ie(struct mwifiex_private *priv, struct sk_buff *skb) +{ + struct ieee80211_wmm_param_ie *wmm; + u8 ac_vi[] = {0x42, 0x43, 0x5e, 0x00}; + u8 ac_vo[] = {0x62, 0x32, 0x2f, 0x00}; + u8 ac_be[] = {0x03, 0xa4, 0x00, 0x00}; + u8 ac_bk[] = {0x27, 0xa4, 0x00, 0x00}; + + wmm = (void *)skb_put(skb, sizeof(*wmm)); + memset(wmm, 0, sizeof(*wmm)); + + wmm->element_id = WLAN_EID_VENDOR_SPECIFIC; + wmm->len = sizeof(*wmm) - 2; + wmm->oui[0] = 0x00; /* Microsoft OUI 00:50:F2 */ + wmm->oui[1] = 0x50; + wmm->oui[2] = 0xf2; + wmm->oui_type = 2; /* WME */ + wmm->oui_subtype = 1; /* WME param */ + wmm->version = 1; /* WME ver */ + wmm->qos_info = 0; /* U-APSD not in use */ + + /* use default WMM AC parameters for TDLS link*/ + memcpy(&wmm->ac[0], ac_be, sizeof(ac_be)); + memcpy(&wmm->ac[1], ac_bk, sizeof(ac_bk)); + memcpy(&wmm->ac[2], ac_vi, sizeof(ac_vi)); + memcpy(&wmm->ac[3], ac_vo, sizeof(ac_vo)); +} + +static void +mwifiex_add_wmm_info_ie(struct mwifiex_private *priv, struct sk_buff *skb, + u8 qosinfo) +{ + u8 *buf; + + buf = (void *)skb_put(skb, MWIFIEX_TDLS_WMM_INFO_SIZE + + sizeof(struct ieee_types_header)); + + *buf++ = WLAN_EID_VENDOR_SPECIFIC; + *buf++ = 7; /* len */ + *buf++ = 0x00; /* Microsoft OUI 00:50:F2 */ + *buf++ = 0x50; + *buf++ = 0xf2; + *buf++ = 2; /* WME */ + *buf++ = 0; /* WME info */ + *buf++ = 1; /* WME ver */ + *buf++ = qosinfo; /* U-APSD no in use */ +} + static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv, const u8 *peer, u8 action_code, u8 dialog_token, @@ -421,6 +471,7 @@ static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv, mwifiex_tdls_add_ext_capab(priv, skb); mwifiex_tdls_add_qos_capab(skb); + mwifiex_add_wmm_info_ie(priv, skb, 0); break; case WLAN_TDLS_SETUP_RESPONSE: @@ -458,6 +509,7 @@ static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv, mwifiex_tdls_add_ext_capab(priv, skb); mwifiex_tdls_add_qos_capab(skb); + mwifiex_add_wmm_info_ie(priv, skb, 0); break; case WLAN_TDLS_SETUP_CONFIRM: @@ -466,6 +518,8 @@ static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv, skb_put(skb, sizeof(tf->u.setup_cfm)); tf->u.setup_cfm.status_code = cpu_to_le16(status_code); tf->u.setup_cfm.dialog_token = dialog_token; + + mwifiex_tdls_add_wmm_param_ie(priv, skb); if (priv->adapter->is_hw_11ac_capable) { ret = mwifiex_tdls_add_vht_oper(priv, peer, skb); if (ret) { @@ -544,6 +598,7 @@ int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, const u8 *peer, sizeof(struct ieee_types_bss_co_2040) + sizeof(struct ieee80211_ht_operation) + sizeof(struct ieee80211_tdls_lnkie) + + sizeof(struct ieee80211_wmm_param_ie) + extra_ies_len; if (priv->adapter->is_hw_11ac_capable) @@ -973,6 +1028,7 @@ mwifiex_tdls_process_disable_link(struct mwifiex_private *priv, const u8 *peer) } mwifiex_restore_tdls_packets(priv, peer, TDLS_LINK_TEARDOWN); + mwifiex_auto_tdls_update_peer_status(priv, peer, TDLS_NOT_SETUP); memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN); tdls_oper.tdls_action = MWIFIEX_TDLS_DISABLE_LINK; return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER, @@ -1017,6 +1073,8 @@ mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, const u8 *peer) memset(sta_ptr->rx_seq, 0xff, sizeof(sta_ptr->rx_seq)); mwifiex_restore_tdls_packets(priv, peer, TDLS_SETUP_COMPLETE); + mwifiex_auto_tdls_update_peer_status(priv, peer, + TDLS_SETUP_COMPLETE); } else { dev_dbg(priv->adapter->dev, "tdls: enable link %pM failed\n", peer); @@ -1030,6 +1088,8 @@ mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, const u8 *peer) mwifiex_del_sta_entry(priv, peer); } mwifiex_restore_tdls_packets(priv, peer, TDLS_LINK_TEARDOWN); + mwifiex_auto_tdls_update_peer_status(priv, peer, + TDLS_NOT_SETUP); return -1; } @@ -1097,3 +1157,231 @@ void mwifiex_disable_all_tdls_links(struct mwifiex_private *priv) mwifiex_del_all_sta_list(priv); } + +int mwifiex_tdls_check_tx(struct mwifiex_private *priv, struct sk_buff *skb) +{ + struct mwifiex_auto_tdls_peer *peer; + unsigned long flags; + u8 mac[ETH_ALEN]; + + ether_addr_copy(mac, skb->data); + + spin_lock_irqsave(&priv->auto_tdls_lock, flags); + list_for_each_entry(peer, &priv->auto_tdls_list, list) { + if (!memcmp(mac, peer->mac_addr, ETH_ALEN)) { + if (peer->rssi <= MWIFIEX_TDLS_RSSI_HIGH && + peer->tdls_status == TDLS_NOT_SETUP && + (peer->failure_count < + MWIFIEX_TDLS_MAX_FAIL_COUNT)) { + peer->tdls_status = TDLS_SETUP_INPROGRESS; + dev_dbg(priv->adapter->dev, + "setup TDLS link, peer=%pM rssi=%d\n", + peer->mac_addr, peer->rssi); + + cfg80211_tdls_oper_request(priv->netdev, + peer->mac_addr, + NL80211_TDLS_SETUP, + 0, GFP_ATOMIC); + peer->do_setup = false; + priv->check_tdls_tx = false; + } else if (peer->failure_count < + MWIFIEX_TDLS_MAX_FAIL_COUNT && + peer->do_discover) { + mwifiex_send_tdls_data_frame(priv, + peer->mac_addr, + WLAN_TDLS_DISCOVERY_REQUEST, + 1, 0, NULL, 0); + peer->do_discover = false; + } + } + } + spin_unlock_irqrestore(&priv->auto_tdls_lock, flags); + + return 0; +} + +void mwifiex_flush_auto_tdls_list(struct mwifiex_private *priv) +{ + struct mwifiex_auto_tdls_peer *peer, *tmp_node; + unsigned long flags; + + spin_lock_irqsave(&priv->auto_tdls_lock, flags); + list_for_each_entry_safe(peer, tmp_node, &priv->auto_tdls_list, list) { + list_del(&peer->list); + kfree(peer); + } + + INIT_LIST_HEAD(&priv->auto_tdls_list); + spin_unlock_irqrestore(&priv->auto_tdls_lock, flags); + priv->check_tdls_tx = false; +} + +void mwifiex_add_auto_tdls_peer(struct mwifiex_private *priv, const u8 *mac) +{ + struct mwifiex_auto_tdls_peer *tdls_peer; + unsigned long flags; + + if (!priv->adapter->auto_tdls) + return; + + spin_lock_irqsave(&priv->auto_tdls_lock, flags); + list_for_each_entry(tdls_peer, &priv->auto_tdls_list, list) { + if (!memcmp(tdls_peer->mac_addr, mac, ETH_ALEN)) { + tdls_peer->tdls_status = TDLS_SETUP_INPROGRESS; + tdls_peer->rssi_jiffies = jiffies; + spin_unlock_irqrestore(&priv->auto_tdls_lock, flags); + return; + } + } + + /* create new TDLS peer */ + tdls_peer = kzalloc(sizeof(*tdls_peer), GFP_ATOMIC); + if (tdls_peer) { + ether_addr_copy(tdls_peer->mac_addr, mac); + tdls_peer->tdls_status = TDLS_SETUP_INPROGRESS; + tdls_peer->rssi_jiffies = jiffies; + INIT_LIST_HEAD(&tdls_peer->list); + list_add_tail(&tdls_peer->list, &priv->auto_tdls_list); + dev_dbg(priv->adapter->dev, "Add auto TDLS peer= %pM to list\n", + mac); + } + + spin_unlock_irqrestore(&priv->auto_tdls_lock, flags); +} + +void mwifiex_auto_tdls_update_peer_status(struct mwifiex_private *priv, + const u8 *mac, u8 link_status) +{ + struct mwifiex_auto_tdls_peer *peer; + unsigned long flags; + + if (!priv->adapter->auto_tdls) + return; + + spin_lock_irqsave(&priv->auto_tdls_lock, flags); + list_for_each_entry(peer, &priv->auto_tdls_list, list) { + if (!memcmp(peer->mac_addr, mac, ETH_ALEN)) { + if ((link_status == TDLS_NOT_SETUP) && + (peer->tdls_status == TDLS_SETUP_INPROGRESS)) + peer->failure_count++; + else if (link_status == TDLS_SETUP_COMPLETE) + peer->failure_count = 0; + + peer->tdls_status = link_status; + break; + } + } + spin_unlock_irqrestore(&priv->auto_tdls_lock, flags); +} + +void mwifiex_auto_tdls_update_peer_signal(struct mwifiex_private *priv, + u8 *mac, s8 snr, s8 nflr) +{ + struct mwifiex_auto_tdls_peer *peer; + unsigned long flags; + + if (!priv->adapter->auto_tdls) + return; + + spin_lock_irqsave(&priv->auto_tdls_lock, flags); + list_for_each_entry(peer, &priv->auto_tdls_list, list) { + if (!memcmp(peer->mac_addr, mac, ETH_ALEN)) { + peer->rssi = nflr - snr; + peer->rssi_jiffies = jiffies; + break; + } + } + spin_unlock_irqrestore(&priv->auto_tdls_lock, flags); +} + +void mwifiex_check_auto_tdls(unsigned long context) +{ + struct mwifiex_private *priv = (struct mwifiex_private *)context; + struct mwifiex_auto_tdls_peer *tdls_peer; + unsigned long flags; + u16 reason = WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED; + + if (WARN_ON_ONCE(!priv || !priv->adapter)) { + pr_err("mwifiex: %s: adapter or private structure is NULL\n", + __func__); + return; + } + + if (unlikely(!priv->adapter->auto_tdls)) + return; + + if (!priv->auto_tdls_timer_active) { + dev_dbg(priv->adapter->dev, + "auto TDLS timer inactive; return"); + return; + } + + priv->check_tdls_tx = false; + + if (list_empty(&priv->auto_tdls_list)) { + mod_timer(&priv->auto_tdls_timer, + jiffies + + msecs_to_jiffies(MWIFIEX_TIMER_10S)); + return; + } + + spin_lock_irqsave(&priv->auto_tdls_lock, flags); + list_for_each_entry(tdls_peer, &priv->auto_tdls_list, list) { + if ((jiffies - tdls_peer->rssi_jiffies) > + (MWIFIEX_AUTO_TDLS_IDLE_TIME * HZ)) { + tdls_peer->rssi = 0; + tdls_peer->do_discover = true; + priv->check_tdls_tx = true; + } + + if (((tdls_peer->rssi >= MWIFIEX_TDLS_RSSI_LOW) || + !tdls_peer->rssi) && + tdls_peer->tdls_status == TDLS_SETUP_COMPLETE) { + tdls_peer->tdls_status = TDLS_LINK_TEARDOWN; + dev_dbg(priv->adapter->dev, + "teardown TDLS link,peer=%pM rssi=%d\n", + tdls_peer->mac_addr, -tdls_peer->rssi); + tdls_peer->do_discover = true; + priv->check_tdls_tx = true; + cfg80211_tdls_oper_request(priv->netdev, + tdls_peer->mac_addr, + NL80211_TDLS_TEARDOWN, + reason, GFP_ATOMIC); + } else if (tdls_peer->rssi && + tdls_peer->rssi <= MWIFIEX_TDLS_RSSI_HIGH && + tdls_peer->tdls_status == TDLS_NOT_SETUP && + tdls_peer->failure_count < + MWIFIEX_TDLS_MAX_FAIL_COUNT) { + priv->check_tdls_tx = true; + tdls_peer->do_setup = true; + dev_dbg(priv->adapter->dev, + "check TDLS with peer=%pM rssi=%d\n", + tdls_peer->mac_addr, -tdls_peer->rssi); + } + } + spin_unlock_irqrestore(&priv->auto_tdls_lock, flags); + + mod_timer(&priv->auto_tdls_timer, + jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S)); +} + +void mwifiex_setup_auto_tdls_timer(struct mwifiex_private *priv) +{ + init_timer(&priv->auto_tdls_timer); + priv->auto_tdls_timer.function = mwifiex_check_auto_tdls; + priv->auto_tdls_timer.data = (unsigned long)priv; + priv->auto_tdls_timer_active = true; + mod_timer(&priv->auto_tdls_timer, + jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S)); +} + +void mwifiex_clean_auto_tdls(struct mwifiex_private *priv) +{ + if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) && + priv->adapter->auto_tdls && + priv->bss_type == MWIFIEX_BSS_TYPE_STA) { + priv->auto_tdls_timer_active = false; + del_timer(&priv->auto_tdls_timer); + mwifiex_flush_auto_tdls_list(priv); + } +} diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c index 96a2126cc44b..a5983fc4e83a 100644 --- a/drivers/net/wireless/mwifiex/txrx.c +++ b/drivers/net/wireless/mwifiex/txrx.c @@ -64,10 +64,6 @@ int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter, else ret = mwifiex_process_sta_rx_packet(priv, skb); - /* Decrement RX pending counter for each packet */ - if (adapter->if_ops.data_complete) - adapter->if_ops.data_complete(adapter); - return ret; } EXPORT_SYMBOL_GPL(mwifiex_handle_rx_packet); diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c index 300bab438011..0f347fdefa0a 100644 --- a/drivers/net/wireless/mwifiex/uap_cmd.c +++ b/drivers/net/wireless/mwifiex/uap_cmd.c @@ -167,7 +167,7 @@ mwifiex_set_ht_params(struct mwifiex_private *priv, ht_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, params->beacon.tail, params->beacon.tail_len); if (ht_ie) { - memcpy(&bss_cfg->ht_cap, ht_ie + 2, + memcpy(&bss_cfg->ht_cap, ht_ie, sizeof(struct ieee80211_ht_cap)); cap_info = le16_to_cpu(bss_cfg->ht_cap.cap_info); memset(&bss_cfg->ht_cap.mcs, 0, diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c index 4371e12b36f3..1b56495ec872 100644 --- a/drivers/net/wireless/mwifiex/usb.c +++ b/drivers/net/wireless/mwifiex/usb.c @@ -27,6 +27,11 @@ static struct mwifiex_if_ops usb_ops; static struct semaphore add_remove_card_sem; static struct usb_device_id mwifiex_usb_table[] = { + /* 8766 */ + {USB_DEVICE(USB8XXX_VID, USB8766_PID_1)}, + {USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8766_PID_2, + USB_CLASS_VENDOR_SPEC, + USB_SUBCLASS_VENDOR_SPEC, 0xff)}, /* 8797 */ {USB_DEVICE(USB8XXX_VID, USB8797_PID_1)}, {USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8797_PID_2, @@ -125,8 +130,10 @@ static int mwifiex_usb_recv(struct mwifiex_adapter *adapter, dev_err(dev, "DATA: skb->len too large\n"); return -1; } - skb_queue_tail(&adapter->usb_rx_data_q, skb); + + skb_queue_tail(&adapter->rx_data_q, skb); adapter->data_received = true; + atomic_inc(&adapter->rx_pending); break; default: dev_err(dev, "%s: unknown endport %#x\n", __func__, ep); @@ -176,7 +183,6 @@ static void mwifiex_usb_rx_complete(struct urb *urb) else skb_put(skb, recv_length - skb->len); - atomic_inc(&adapter->rx_pending); status = mwifiex_usb_recv(adapter, skb, context->ep); dev_dbg(adapter->dev, "info: recv_length=%d, status=%d\n", @@ -191,7 +197,6 @@ static void mwifiex_usb_rx_complete(struct urb *urb) if (card->rx_cmd_ep == context->ep) return; } else { - atomic_dec(&adapter->rx_pending); if (status == -1) dev_err(adapter->dev, "received data processing failed!\n"); @@ -222,7 +227,13 @@ setup_for_next: else size = MWIFIEX_RX_DATA_BUF_SIZE; - mwifiex_usb_submit_rx_urb(context, size); + if (card->rx_cmd_ep == context->ep) { + mwifiex_usb_submit_rx_urb(context, size); + } else { + context->skb = NULL; + if (atomic_read(&adapter->rx_pending) <= HIGH_RX_PENDING) + mwifiex_usb_submit_rx_urb(context, size); + } return; } @@ -348,10 +359,12 @@ static int mwifiex_usb_probe(struct usb_interface *intf, /* PID_1 is used for firmware downloading only */ switch (id_product) { + case USB8766_PID_1: case USB8797_PID_1: case USB8897_PID_1: card->usb_boot_state = USB8XXX_FW_DNLD; break; + case USB8766_PID_2: case USB8797_PID_2: case USB8897_PID_2: card->usb_boot_state = USB8XXX_FW_READY; @@ -780,6 +793,11 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter) adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K; strcpy(adapter->fw_name, USB8897_DEFAULT_FW_NAME); break; + case USB8766_PID_1: + case USB8766_PID_2: + adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; + strcpy(adapter->fw_name, USB8766_DEFAULT_FW_NAME); + break; case USB8797_PID_1: case USB8797_PID_2: default: @@ -962,19 +980,11 @@ static void mwifiex_submit_rx_urb(struct mwifiex_adapter *adapter, u8 ep) static int mwifiex_usb_cmd_event_complete(struct mwifiex_adapter *adapter, struct sk_buff *skb) { - atomic_dec(&adapter->rx_pending); mwifiex_submit_rx_urb(adapter, MWIFIEX_USB_EP_CMD_EVENT); return 0; } -static int mwifiex_usb_data_complete(struct mwifiex_adapter *adapter) -{ - atomic_dec(&adapter->rx_pending); - - return 0; -} - /* This function wakes up the card. */ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) { @@ -986,6 +996,20 @@ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) return 0; } +static void mwifiex_usb_submit_rem_rx_urbs(struct mwifiex_adapter *adapter) +{ + struct usb_card_rec *card = (struct usb_card_rec *)adapter->card; + int i; + struct urb_context *ctx; + + for (i = 0; i < MWIFIEX_RX_DATA_URB; i++) { + if (card->rx_data_list[i].skb) + continue; + ctx = &card->rx_data_list[i]; + mwifiex_usb_submit_rx_urb(ctx, MWIFIEX_RX_DATA_BUF_SIZE); + } +} + static struct mwifiex_if_ops usb_ops = { .register_dev = mwifiex_register_dev, .unregister_dev = mwifiex_unregister_dev, @@ -996,8 +1020,8 @@ static struct mwifiex_if_ops usb_ops = { .dnld_fw = mwifiex_usb_dnld_fw, .cmdrsp_complete = mwifiex_usb_cmd_event_complete, .event_complete = mwifiex_usb_cmd_event_complete, - .data_complete = mwifiex_usb_data_complete, .host_to_card = mwifiex_usb_host_to_card, + .submit_rem_rx_urbs = mwifiex_usb_submit_rem_rx_urbs, }; /* This function initializes the USB driver module. @@ -1048,5 +1072,6 @@ MODULE_AUTHOR("Marvell International Ltd."); MODULE_DESCRIPTION("Marvell WiFi-Ex USB Driver version" USB_VERSION); MODULE_VERSION(USB_VERSION); MODULE_LICENSE("GPL v2"); +MODULE_FIRMWARE(USB8766_DEFAULT_FW_NAME); MODULE_FIRMWARE(USB8797_DEFAULT_FW_NAME); MODULE_FIRMWARE(USB8897_DEFAULT_FW_NAME); diff --git a/drivers/net/wireless/mwifiex/usb.h b/drivers/net/wireless/mwifiex/usb.h index 4c41c2a193c5..a7cbba1355af 100644 --- a/drivers/net/wireless/mwifiex/usb.h +++ b/drivers/net/wireless/mwifiex/usb.h @@ -24,6 +24,8 @@ #define USB8XXX_VID 0x1286 +#define USB8766_PID_1 0x2041 +#define USB8766_PID_2 0x2042 #define USB8797_PID_1 0x2043 #define USB8797_PID_2 0x2044 #define USB8897_PID_1 0x2045 @@ -37,6 +39,7 @@ #define MWIFIEX_RX_DATA_URB 6 #define MWIFIEX_USB_TIMEOUT 100 +#define USB8766_DEFAULT_FW_NAME "mrvl/usb8766_uapsta.bin" #define USB8797_DEFAULT_FW_NAME "mrvl/usb8797_uapsta.bin" #define USB8897_DEFAULT_FW_NAME "mrvl/usb8897_uapsta.bin" diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c index ec79c49de097..a113ef8f0b8b 100644 --- a/drivers/net/wireless/mwifiex/util.c +++ b/drivers/net/wireless/mwifiex/util.c @@ -141,6 +141,38 @@ int mwifiex_get_debug_info(struct mwifiex_private *priv, return 0; } +static int +mwifiex_parse_mgmt_packet(struct mwifiex_private *priv, u8 *payload, u16 len, + struct rxpd *rx_pd) +{ + u16 stype; + u8 category, action_code; + struct ieee80211_hdr *ieee_hdr = (void *)payload; + + stype = (cpu_to_le16(ieee_hdr->frame_control) & IEEE80211_FCTL_STYPE); + + switch (stype) { + case IEEE80211_STYPE_ACTION: + category = *(payload + sizeof(struct ieee80211_hdr)); + action_code = *(payload + sizeof(struct ieee80211_hdr) + 1); + if (category == WLAN_CATEGORY_PUBLIC && + action_code == WLAN_PUB_ACTION_TDLS_DISCOVER_RES) { + dev_dbg(priv->adapter->dev, + "TDLS discovery response %pM nf=%d, snr=%d\n", + ieee_hdr->addr2, rx_pd->nf, rx_pd->snr); + mwifiex_auto_tdls_update_peer_signal(priv, + ieee_hdr->addr2, + rx_pd->snr, + rx_pd->nf); + } + break; + default: + dev_dbg(priv->adapter->dev, + "unknown mgmt frame subytpe %#x\n", stype); + } + + return 0; +} /* * This function processes the received management packet and send it * to the kernel. @@ -151,6 +183,7 @@ mwifiex_process_mgmt_packet(struct mwifiex_private *priv, { struct rxpd *rx_pd; u16 pkt_len; + struct ieee80211_hdr *ieee_hdr; if (!skb) return -1; @@ -162,6 +195,11 @@ mwifiex_process_mgmt_packet(struct mwifiex_private *priv, pkt_len = le16_to_cpu(rx_pd->rx_pkt_length); + ieee_hdr = (void *)skb->data; + if (ieee80211_is_mgmt(ieee_hdr->frame_control)) { + mwifiex_parse_mgmt_packet(priv, (u8 *)ieee_hdr, + pkt_len, rx_pd); + } /* Remove address4 */ memmove(skb->data + sizeof(struct ieee80211_hdr_3addr), skb->data + sizeof(struct ieee80211_hdr), diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index ef1104476bd8..b8d1e04aa9b9 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -5548,7 +5548,9 @@ mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, return rc; } -static void mwl8k_sw_scan_start(struct ieee80211_hw *hw) +static void mwl8k_sw_scan_start(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + const u8 *mac_addr) { struct mwl8k_priv *priv = hw->priv; u8 tmp; @@ -5565,7 +5567,8 @@ static void mwl8k_sw_scan_start(struct ieee80211_hw *hw) priv->sw_scan_start = true; } -static void mwl8k_sw_scan_complete(struct ieee80211_hw *hw) +static void mwl8k_sw_scan_complete(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) { struct mwl8k_priv *priv = hw->priv; u8 tmp; diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index d849d590de25..c878e3f3993c 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -62,7 +62,7 @@ static inline void rt2500usb_register_read(struct rt2x00_dev *rt2x00dev, __le16 reg; rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, USB_VENDOR_REQUEST_IN, offset, - ®, sizeof(reg), REGISTER_TIMEOUT); + ®, sizeof(reg)); *value = le16_to_cpu(reg); } @@ -83,8 +83,7 @@ static inline void rt2500usb_register_multiread(struct rt2x00_dev *rt2x00dev, { rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, USB_VENDOR_REQUEST_IN, offset, - value, length, - REGISTER_TIMEOUT16(length)); + value, length); } static inline void rt2500usb_register_write(struct rt2x00_dev *rt2x00dev, @@ -94,7 +93,7 @@ static inline void rt2500usb_register_write(struct rt2x00_dev *rt2x00dev, __le16 reg = cpu_to_le16(value); rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, USB_VENDOR_REQUEST_OUT, offset, - ®, sizeof(reg), REGISTER_TIMEOUT); + ®, sizeof(reg)); } static inline void rt2500usb_register_write_lock(struct rt2x00_dev *rt2x00dev, @@ -113,8 +112,7 @@ static inline void rt2500usb_register_multiwrite(struct rt2x00_dev *rt2x00dev, { rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, USB_VENDOR_REQUEST_OUT, offset, - value, length, - REGISTER_TIMEOUT16(length)); + value, length); } static int rt2500usb_regbusy_read(struct rt2x00_dev *rt2x00dev, diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index d13f25cd70d5..1ff81afb672c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -1437,8 +1437,11 @@ int rt2x00mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta); int rt2x00mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta); -void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw); -void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw); +void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + const u8 *mac_addr); +void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw, + struct ieee80211_vif *vif); int rt2x00mac_get_stats(struct ieee80211_hw *hw, struct ieee80211_low_level_stats *stats); void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index ad6e5a8d1e10..cb40245a0695 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -568,7 +568,9 @@ int rt2x00mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, } EXPORT_SYMBOL_GPL(rt2x00mac_sta_remove); -void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw) +void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + const u8 *mac_addr) { struct rt2x00_dev *rt2x00dev = hw->priv; set_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags); @@ -576,7 +578,8 @@ void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw) } EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_start); -void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw) +void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) { struct rt2x00_dev *rt2x00dev = hw->priv; clear_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags); diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 86c43d112a4b..dc85d3e0ffe5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -116,7 +116,7 @@ EXPORT_SYMBOL_GPL(rt2x00usb_vendor_req_buff_lock); int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev, const u8 request, const u8 requesttype, const u16 offset, void *buffer, - const u16 buffer_length, const int timeout) + const u16 buffer_length) { int status = 0; unsigned char *tb; @@ -131,7 +131,7 @@ int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev, bsize = min_t(u16, CSR_CACHE_SIZE, len); status = rt2x00usb_vendor_req_buff_lock(rt2x00dev, request, requesttype, off, tb, - bsize, timeout); + bsize, REGISTER_TIMEOUT); tb += bsize; len -= bsize; diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h index 831b65f93feb..819690e978c0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/drivers/net/wireless/rt2x00/rt2x00usb.h @@ -33,27 +33,14 @@ }) /* - * For USB vendor requests we need to pass a timeout - * time in ms, for this we use the REGISTER_TIMEOUT, - * however when loading firmware a higher value is - * required. In that case we use the REGISTER_TIMEOUT_FIRMWARE. + * For USB vendor requests we need to pass a timeout time in ms, for this we + * use the REGISTER_TIMEOUT, however when loading firmware or read EEPROM + * a higher value is required. In that case we use the REGISTER_TIMEOUT_FIRMWARE + * and EEPROM_TIMEOUT. */ #define REGISTER_TIMEOUT 500 #define REGISTER_TIMEOUT_FIRMWARE 1000 - -/** - * REGISTER_TIMEOUT16 - Determine the timeout for 16bit register access - * @__datalen: Data length - */ -#define REGISTER_TIMEOUT16(__datalen) \ - ( REGISTER_TIMEOUT * ((__datalen) / sizeof(u16)) ) - -/** - * REGISTER_TIMEOUT32 - Determine the timeout for 32bit register access - * @__datalen: Data length - */ -#define REGISTER_TIMEOUT32(__datalen) \ - ( REGISTER_TIMEOUT * ((__datalen) / sizeof(u32)) ) +#define EEPROM_TIMEOUT 2000 /* * Cache size @@ -126,7 +113,6 @@ int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev, * @offset: Register offset to perform action on * @buffer: Buffer where information will be read/written to by device * @buffer_length: Size of &buffer - * @timeout: Operation timeout * * This function will use a previously with kmalloc allocated cache * to communicate with the device. The contents of the buffer pointer @@ -139,7 +125,7 @@ int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev, int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev, const u8 request, const u8 requesttype, const u16 offset, void *buffer, - const u16 buffer_length, const int timeout); + const u16 buffer_length); /** * rt2x00usb_vendor_request_buff - Send register command to device (buffered) @@ -197,8 +183,7 @@ static inline int rt2x00usb_eeprom_read(struct rt2x00_dev *rt2x00dev, { return rt2x00usb_vendor_request(rt2x00dev, USB_EEPROM_READ, USB_VENDOR_REQUEST_IN, 0, 0, - eeprom, length, - REGISTER_TIMEOUT16(length)); + eeprom, length, EEPROM_TIMEOUT); } /** @@ -217,7 +202,7 @@ static inline void rt2x00usb_register_read(struct rt2x00_dev *rt2x00dev, __le32 reg; rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, USB_VENDOR_REQUEST_IN, offset, - ®, sizeof(reg), REGISTER_TIMEOUT); + ®, sizeof(reg)); *value = le32_to_cpu(reg); } @@ -257,8 +242,7 @@ static inline void rt2x00usb_register_multiread(struct rt2x00_dev *rt2x00dev, { rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, USB_VENDOR_REQUEST_IN, offset, - value, length, - REGISTER_TIMEOUT32(length)); + value, length); } /** @@ -277,7 +261,7 @@ static inline void rt2x00usb_register_write(struct rt2x00_dev *rt2x00dev, __le32 reg = cpu_to_le32(value); rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, USB_VENDOR_REQUEST_OUT, offset, - ®, sizeof(reg), REGISTER_TIMEOUT); + ®, sizeof(reg)); } /** @@ -316,8 +300,7 @@ static inline void rt2x00usb_register_multiwrite(struct rt2x00_dev *rt2x00dev, { rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, USB_VENDOR_REQUEST_OUT, offset, - (void *)value, length, - REGISTER_TIMEOUT32(length)); + (void *)value, length); } /** diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c index 07dae0d44abc..af52f0bdb71e 100644 --- a/drivers/net/wireless/rtlwifi/core.c +++ b/drivers/net/wireless/rtlwifi/core.c @@ -1361,7 +1361,9 @@ static int rtl_op_ampdu_action(struct ieee80211_hw *hw, return 0; } -static void rtl_op_sw_scan_start(struct ieee80211_hw *hw) +static void rtl_op_sw_scan_start(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + const u8 *mac_addr) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); @@ -1396,7 +1398,8 @@ static void rtl_op_sw_scan_start(struct ieee80211_hw *hw) rtlpriv->cfg->ops->scan_operation_backup(hw, SCAN_OPT_BACKUP_BAND0); } -static void rtl_op_sw_scan_complete(struct ieee80211_hw *hw) +static void rtl_op_sw_scan_complete(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/phy.c b/drivers/net/wireless/rtlwifi/rtl8821ae/phy.c index 1e9570fa874f..9b4d8a637915 100644 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8821ae/phy.c @@ -800,7 +800,7 @@ static void _rtl8821ae_phy_set_txpower_by_rate_base(struct ieee80211_hw *hw, "Invalid RateSection %d in Band 2.4G,Rf Path %d, %dTx in PHY_SetTxPowerByRateBase()\n", rate_section, path, txnum); break; - }; + } } else if (band == BAND_ON_5G) { switch (rate_section) { case OFDM: @@ -823,7 +823,7 @@ static void _rtl8821ae_phy_set_txpower_by_rate_base(struct ieee80211_hw *hw, "Invalid RateSection %d in Band 5G, Rf Path %d, %dTx in PHY_SetTxPowerByRateBase()\n", rate_section, path, txnum); break; - }; + } } else { RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Invalid Band %d in PHY_SetTxPowerByRateBase()\n", band); @@ -870,7 +870,7 @@ static u8 _rtl8821ae_phy_get_txpower_by_rate_base(struct ieee80211_hw *hw, "Invalid RateSection %d in Band 2.4G, Rf Path %d, %dTx in PHY_GetTxPowerByRateBase()\n", rate_section, path, txnum); break; - }; + } } else if (band == BAND_ON_5G) { switch (rate_section) { case OFDM: @@ -893,7 +893,7 @@ static u8 _rtl8821ae_phy_get_txpower_by_rate_base(struct ieee80211_hw *hw, "Invalid RateSection %d in Band 5G, Rf Path %d, %dTx in PHY_GetTxPowerByRateBase()\n", rate_section, path, txnum); break; - }; + } } else { RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Invalid Band %d in PHY_GetTxPowerByRateBase()\n", band); @@ -3746,7 +3746,7 @@ static void _rtl8821ae_iqk_tx_fill_iqc(struct ieee80211_hw *hw, break; default: break; - }; + } } static void _rtl8821ae_iqk_rx_fill_iqc(struct ieee80211_hw *hw, @@ -3767,7 +3767,7 @@ static void _rtl8821ae_iqk_rx_fill_iqc(struct ieee80211_hw *hw, break; default: break; - }; + } } #define cal_num 10 diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c index 38234851457e..0b30a7b4d663 100644 --- a/drivers/net/wireless/ti/wl1251/main.c +++ b/drivers/net/wireless/ti/wl1251/main.c @@ -1029,7 +1029,7 @@ static int wl1251_op_hw_scan(struct ieee80211_hw *hw, goto out_sleep; } - skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len, + skb = ieee80211_probereq_get(wl->hw, wl->vif->addr, ssid, ssid_len, req->ie_len); if (!skb) { ret = -ENOMEM; diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index 05604ee31224..b82661962d33 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c @@ -64,6 +64,9 @@ static int __wlcore_cmd_send(struct wl1271 *wl, u16 id, void *buf, id != CMD_STOP_FWLOGGER)) return -EIO; + if (WARN_ON_ONCE(len < sizeof(*cmd))) + return -EIO; + cmd = buf; cmd->id = cpu_to_le16(id); cmd->status = 0; @@ -128,8 +131,9 @@ static int __wlcore_cmd_send(struct wl1271 *wl, u16 id, void *buf, * send command to fw and return cmd status on success * valid_rets contains a bitmap of allowed error codes */ -int wlcore_cmd_send_failsafe(struct wl1271 *wl, u16 id, void *buf, size_t len, - size_t res_len, unsigned long valid_rets) +static int wlcore_cmd_send_failsafe(struct wl1271 *wl, u16 id, void *buf, + size_t len, size_t res_len, + unsigned long valid_rets) { int ret = __wlcore_cmd_send(wl, id, buf, len, res_len); @@ -150,7 +154,6 @@ fail: wl12xx_queue_recovery_work(wl); return ret; } -EXPORT_SYMBOL_GPL(wl1271_cmd_send); /* * wrapper for wlcore_cmd_send that accept only CMD_STATUS_SUCCESS @@ -165,6 +168,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, return ret; return 0; } +EXPORT_SYMBOL_GPL(wl1271_cmd_send); /* * Poll the mailbox event field until any of the bits in the mask is set or a @@ -891,6 +895,9 @@ int wlcore_cmd_configure_failsafe(struct wl1271 *wl, u16 id, void *buf, wl1271_debug(DEBUG_CMD, "cmd configure (%d)", id); + if (WARN_ON_ONCE(len < sizeof(*acx))) + return -EIO; + acx->id = cpu_to_le16(id); /* payload length, does not include any headers */ @@ -1138,7 +1145,7 @@ int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif, wl1271_debug(DEBUG_SCAN, "build probe request band %d", band); - skb = ieee80211_probereq_get(wl->hw, vif, ssid, ssid_len, + skb = ieee80211_probereq_get(wl->hw, vif->addr, ssid, ssid_len, ie0_len + ie1_len); if (!skb) { ret = -ENOMEM; diff --git a/drivers/net/wireless/ti/wlcore/cmd.h b/drivers/net/wireless/ti/wlcore/cmd.h index ca6a28b03f8f..453684a71d30 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.h +++ b/drivers/net/wireless/ti/wlcore/cmd.h @@ -31,8 +31,6 @@ struct acx_header; int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, size_t res_len); -int wlcore_cmd_send_failsafe(struct wl1271 *wl, u16 id, void *buf, size_t len, - size_t res_len, unsigned long valid_rets); int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 *addr, u8 role_type, u8 *role_id); int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id); diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 575c8f6d4009..6ad3fcedab9b 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -5177,10 +5177,11 @@ out: } static void wl12xx_op_channel_switch(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, struct ieee80211_channel_switch *ch_switch) { struct wl1271 *wl = hw->priv; - struct wl12xx_vif *wlvif; + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); int ret; wl1271_debug(DEBUG_MAC80211, "mac80211 channel switch"); @@ -5190,14 +5191,8 @@ static void wl12xx_op_channel_switch(struct ieee80211_hw *hw, mutex_lock(&wl->mutex); if (unlikely(wl->state == WLCORE_STATE_OFF)) { - wl12xx_for_each_wlvif_sta(wl, wlvif) { - struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); - - if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) - continue; - + if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) ieee80211_chswitch_done(vif, false); - } goto out; } else if (unlikely(wl->state != WLCORE_STATE_ON)) { goto out; @@ -5208,11 +5203,9 @@ static void wl12xx_op_channel_switch(struct ieee80211_hw *hw, goto out; /* TODO: change mac80211 to pass vif as param */ - wl12xx_for_each_wlvif_sta(wl, wlvif) { - unsigned long delay_usec; - if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) - continue; + if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) { + unsigned long delay_usec; ret = wl->ops->channel_switch(wl, wlvif, ch_switch); if (ret) @@ -5222,10 +5215,10 @@ static void wl12xx_op_channel_switch(struct ieee80211_hw *hw, /* indicate failure 5 seconds after channel switch time */ delay_usec = ieee80211_tu_to_usec(wlvif->beacon_int) * - ch_switch->count; + ch_switch->count; ieee80211_queue_delayed_work(hw, &wlvif->channel_switch_work, - usecs_to_jiffies(delay_usec) + - msecs_to_jiffies(5000)); + usecs_to_jiffies(delay_usec) + + msecs_to_jiffies(5000)); } out_sleep: diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index 895fe84011e7..a6a32d337bbb 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -235,10 +235,10 @@ static void xenvif_down(struct xenvif *vif) for (queue_index = 0; queue_index < num_queues; ++queue_index) { queue = &vif->queues[queue_index]; - napi_disable(&queue->napi); disable_irq(queue->tx_irq); if (queue->tx_irq != queue->rx_irq) disable_irq(queue->rx_irq); + napi_disable(&queue->napi); del_timer_sync(&queue->credit_timeout); } } diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 6563f0713fc0..4a509f715fe8 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -82,6 +82,16 @@ MODULE_PARM_DESC(max_queues, static unsigned int fatal_skb_slots = FATAL_SKB_SLOTS_DEFAULT; module_param(fatal_skb_slots, uint, 0444); +/* The amount to copy out of the first guest Tx slot into the skb's + * linear area. If the first slot has more data, it will be mapped + * and put into the first frag. + * + * This is sized to avoid pulling headers from the frags for most + * TCP/IP packets. + */ +#define XEN_NETBACK_TX_COPY_LEN 128 + + static void xenvif_idx_release(struct xenvif_queue *queue, u16 pending_idx, u8 status); @@ -125,13 +135,6 @@ static inline struct xenvif_queue *ubuf_to_queue(const struct ubuf_info *ubuf) pending_tx_info[0]); } -/* This is a miniumum size for the linear area to avoid lots of - * calls to __pskb_pull_tail() as we set up checksum offsets. The - * value 128 was chosen as it covers all IPv4 and most likely - * IPv6 headers. - */ -#define PKT_PROT_LEN 128 - static u16 frag_get_pending_idx(skb_frag_t *frag) { return (u16)frag->page_offset; @@ -1446,9 +1449,9 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue, index = pending_index(queue->pending_cons); pending_idx = queue->pending_ring[index]; - data_len = (txreq.size > PKT_PROT_LEN && + data_len = (txreq.size > XEN_NETBACK_TX_COPY_LEN && ret < XEN_NETBK_LEGACY_SLOTS_MAX) ? - PKT_PROT_LEN : txreq.size; + XEN_NETBACK_TX_COPY_LEN : txreq.size; skb = xenvif_alloc_skb(data_len); if (unlikely(skb == NULL)) { @@ -1550,7 +1553,7 @@ static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *s unsigned int len; BUG_ON(i >= MAX_SKB_FRAGS); - page = alloc_page(GFP_ATOMIC|__GFP_COLD); + page = alloc_page(GFP_ATOMIC); if (!page) { int j; skb->truesize += skb->data_len; @@ -1653,11 +1656,6 @@ static int xenvif_tx_submit(struct xenvif_queue *queue) } } - if (skb_is_nonlinear(skb) && skb_headlen(skb) < PKT_PROT_LEN) { - int target = min_t(int, skb->len, PKT_PROT_LEN); - __pskb_pull_tail(skb, target - skb_headlen(skb)); - } - skb->dev = queue->vif->dev; skb->protocol = eth_type_trans(skb, skb->dev); skb_reset_network_header(skb); diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index cca871346a0f..88a70f5ed594 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -77,7 +77,9 @@ struct netfront_cb { #define NET_TX_RING_SIZE __CONST_RING_SIZE(xen_netif_tx, PAGE_SIZE) #define NET_RX_RING_SIZE __CONST_RING_SIZE(xen_netif_rx, PAGE_SIZE) -#define TX_MAX_TARGET min_t(int, NET_TX_RING_SIZE, 256) + +/* Minimum number of Rx slots (includes slot for GSO metadata). */ +#define NET_RX_SLOTS_MIN (XEN_NETIF_NR_SLOTS_MIN + 1) /* Queue name is interface name with "-qNNN" appended */ #define QUEUE_NAME_SIZE (IFNAMSIZ + 6) @@ -137,13 +139,6 @@ struct netfront_queue { struct xen_netif_rx_front_ring rx; int rx_ring_ref; - /* Receive-ring batched refills. */ -#define RX_MIN_TARGET 8 -#define RX_DFL_MIN_TARGET 64 -#define RX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256) - unsigned rx_min_target, rx_max_target, rx_target; - struct sk_buff_head rx_batch; - struct timer_list rx_refill_timer; struct sk_buff *rx_skbs[NET_RX_RING_SIZE]; @@ -251,7 +246,7 @@ static void rx_refill_timeout(unsigned long data) static int netfront_tx_slot_available(struct netfront_queue *queue) { return (queue->tx.req_prod_pvt - queue->tx.rsp_cons) < - (TX_MAX_TARGET - MAX_SKB_FRAGS - 2); + (NET_TX_RING_SIZE - MAX_SKB_FRAGS - 2); } static void xennet_maybe_wake_tx(struct netfront_queue *queue) @@ -265,77 +260,55 @@ static void xennet_maybe_wake_tx(struct netfront_queue *queue) netif_tx_wake_queue(netdev_get_tx_queue(dev, queue->id)); } -static void xennet_alloc_rx_buffers(struct netfront_queue *queue) + +static struct sk_buff *xennet_alloc_one_rx_buffer(struct netfront_queue *queue) { - unsigned short id; struct sk_buff *skb; struct page *page; - int i, batch_target, notify; - RING_IDX req_prod = queue->rx.req_prod_pvt; - grant_ref_t ref; - unsigned long pfn; - void *vaddr; - struct xen_netif_rx_request *req; - if (unlikely(!netif_carrier_ok(queue->info->netdev))) - return; + skb = __netdev_alloc_skb(queue->info->netdev, + RX_COPY_THRESHOLD + NET_IP_ALIGN, + GFP_ATOMIC | __GFP_NOWARN); + if (unlikely(!skb)) + return NULL; - /* - * Allocate skbuffs greedily, even though we batch updates to the - * receive ring. This creates a less bursty demand on the memory - * allocator, so should reduce the chance of failed allocation requests - * both for ourself and for other kernel subsystems. - */ - batch_target = queue->rx_target - (req_prod - queue->rx.rsp_cons); - for (i = skb_queue_len(&queue->rx_batch); i < batch_target; i++) { - skb = __netdev_alloc_skb(queue->info->netdev, - RX_COPY_THRESHOLD + NET_IP_ALIGN, - GFP_ATOMIC | __GFP_NOWARN); - if (unlikely(!skb)) - goto no_skb; - - /* Align ip header to a 16 bytes boundary */ - skb_reserve(skb, NET_IP_ALIGN); - - page = alloc_page(GFP_ATOMIC | __GFP_NOWARN); - if (!page) { - kfree_skb(skb); -no_skb: - /* Could not allocate any skbuffs. Try again later. */ - mod_timer(&queue->rx_refill_timer, - jiffies + (HZ/10)); - - /* Any skbuffs queued for refill? Force them out. */ - if (i != 0) - goto refill; - break; - } - - skb_add_rx_frag(skb, 0, page, 0, 0, PAGE_SIZE); - __skb_queue_tail(&queue->rx_batch, skb); + page = alloc_page(GFP_ATOMIC | __GFP_NOWARN); + if (!page) { + kfree_skb(skb); + return NULL; } + skb_add_rx_frag(skb, 0, page, 0, 0, PAGE_SIZE); + + /* Align ip header to a 16 bytes boundary */ + skb_reserve(skb, NET_IP_ALIGN); + skb->dev = queue->info->netdev; + + return skb; +} + - /* Is the batch large enough to be worthwhile? */ - if (i < (queue->rx_target/2)) { - if (req_prod > queue->rx.sring->req_prod) - goto push; +static void xennet_alloc_rx_buffers(struct netfront_queue *queue) +{ + RING_IDX req_prod = queue->rx.req_prod_pvt; + int notify; + + if (unlikely(!netif_carrier_ok(queue->info->netdev))) return; - } - /* Adjust our fill target if we risked running out of buffers. */ - if (((req_prod - queue->rx.sring->rsp_prod) < (queue->rx_target / 4)) && - ((queue->rx_target *= 2) > queue->rx_max_target)) - queue->rx_target = queue->rx_max_target; + for (req_prod = queue->rx.req_prod_pvt; + req_prod - queue->rx.rsp_cons < NET_RX_RING_SIZE; + req_prod++) { + struct sk_buff *skb; + unsigned short id; + grant_ref_t ref; + unsigned long pfn; + struct xen_netif_rx_request *req; - refill: - for (i = 0; ; i++) { - skb = __skb_dequeue(&queue->rx_batch); - if (skb == NULL) + skb = xennet_alloc_one_rx_buffer(queue); + if (!skb) break; - skb->dev = queue->info->netdev; - - id = xennet_rxidx(req_prod + i); + id = xennet_rxidx(req_prod); BUG_ON(queue->rx_skbs[id]); queue->rx_skbs[id] = skb; @@ -345,9 +318,8 @@ no_skb: queue->grant_rx_ref[id] = ref; pfn = page_to_pfn(skb_frag_page(&skb_shinfo(skb)->frags[0])); - vaddr = page_address(skb_frag_page(&skb_shinfo(skb)->frags[0])); - req = RING_GET_REQUEST(&queue->rx, req_prod + i); + req = RING_GET_REQUEST(&queue->rx, req_prod); gnttab_grant_foreign_access_ref(ref, queue->info->xbdev->otherend_id, pfn_to_mfn(pfn), @@ -357,11 +329,16 @@ no_skb: req->gref = ref; } + queue->rx.req_prod_pvt = req_prod; + + /* Not enough requests? Try again later. */ + if (req_prod - queue->rx.rsp_cons < NET_RX_SLOTS_MIN) { + mod_timer(&queue->rx_refill_timer, jiffies + (HZ/10)); + return; + } + wmb(); /* barrier so backend seens requests */ - /* Above is a suitable barrier to ensure backend will see requests. */ - queue->rx.req_prod_pvt = req_prod + i; - push: RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&queue->rx, notify); if (notify) notify_remote_via_irq(queue->rx_irq); @@ -1070,13 +1047,6 @@ err: work_done -= handle_incoming_queue(queue, &rxq); - /* If we get a callback with very few responses, reduce fill target. */ - /* NB. Note exponential increase, linear decrease. */ - if (((queue->rx.req_prod_pvt - queue->rx.sring->rsp_prod) > - ((3*queue->rx_target) / 4)) && - (--queue->rx_target < queue->rx_min_target)) - queue->rx_target = queue->rx_min_target; - xennet_alloc_rx_buffers(queue); if (work_done < budget) { @@ -1643,11 +1613,6 @@ static int xennet_init_queue(struct netfront_queue *queue) spin_lock_init(&queue->tx_lock); spin_lock_init(&queue->rx_lock); - skb_queue_head_init(&queue->rx_batch); - queue->rx_target = RX_DFL_MIN_TARGET; - queue->rx_min_target = RX_DFL_MIN_TARGET; - queue->rx_max_target = RX_MAX_TARGET; - init_timer(&queue->rx_refill_timer); queue->rx_refill_timer.data = (unsigned long)queue; queue->rx_refill_timer.function = rx_refill_timeout; @@ -1670,7 +1635,7 @@ static int xennet_init_queue(struct netfront_queue *queue) } /* A grant for every tx ring slot */ - if (gnttab_alloc_grant_references(TX_MAX_TARGET, + if (gnttab_alloc_grant_references(NET_TX_RING_SIZE, &queue->gref_tx_head) < 0) { pr_alert("can't alloc tx grant refs\n"); err = -ENOMEM; @@ -1678,7 +1643,7 @@ static int xennet_init_queue(struct netfront_queue *queue) } /* A grant for every rx ring slot */ - if (gnttab_alloc_grant_references(RX_MAX_TARGET, + if (gnttab_alloc_grant_references(NET_RX_RING_SIZE, &queue->gref_rx_head) < 0) { pr_alert("can't alloc rx grant refs\n"); err = -ENOMEM; @@ -2146,83 +2111,18 @@ static const struct ethtool_ops xennet_ethtool_ops = }; #ifdef CONFIG_SYSFS -static ssize_t show_rxbuf_min(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct net_device *netdev = to_net_dev(dev); - struct netfront_info *info = netdev_priv(netdev); - unsigned int num_queues = netdev->real_num_tx_queues; - - if (num_queues) - return sprintf(buf, "%u\n", info->queues[0].rx_min_target); - else - return sprintf(buf, "%u\n", RX_MIN_TARGET); -} - -static ssize_t store_rxbuf_min(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) +static ssize_t show_rxbuf(struct device *dev, + struct device_attribute *attr, char *buf) { - struct net_device *netdev = to_net_dev(dev); - struct netfront_info *np = netdev_priv(netdev); - unsigned int num_queues = netdev->real_num_tx_queues; - char *endp; - unsigned long target; - unsigned int i; - struct netfront_queue *queue; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - target = simple_strtoul(buf, &endp, 0); - if (endp == buf) - return -EBADMSG; - - if (target < RX_MIN_TARGET) - target = RX_MIN_TARGET; - if (target > RX_MAX_TARGET) - target = RX_MAX_TARGET; - - for (i = 0; i < num_queues; ++i) { - queue = &np->queues[i]; - spin_lock_bh(&queue->rx_lock); - if (target > queue->rx_max_target) - queue->rx_max_target = target; - queue->rx_min_target = target; - if (target > queue->rx_target) - queue->rx_target = target; - - xennet_alloc_rx_buffers(queue); - - spin_unlock_bh(&queue->rx_lock); - } - return len; -} - -static ssize_t show_rxbuf_max(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct net_device *netdev = to_net_dev(dev); - struct netfront_info *info = netdev_priv(netdev); - unsigned int num_queues = netdev->real_num_tx_queues; - - if (num_queues) - return sprintf(buf, "%u\n", info->queues[0].rx_max_target); - else - return sprintf(buf, "%u\n", RX_MAX_TARGET); + return sprintf(buf, "%lu\n", NET_RX_RING_SIZE); } -static ssize_t store_rxbuf_max(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) +static ssize_t store_rxbuf(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) { - struct net_device *netdev = to_net_dev(dev); - struct netfront_info *np = netdev_priv(netdev); - unsigned int num_queues = netdev->real_num_tx_queues; char *endp; unsigned long target; - unsigned int i = 0; - struct netfront_queue *queue = NULL; if (!capable(CAP_NET_ADMIN)) return -EPERM; @@ -2231,44 +2131,15 @@ static ssize_t store_rxbuf_max(struct device *dev, if (endp == buf) return -EBADMSG; - if (target < RX_MIN_TARGET) - target = RX_MIN_TARGET; - if (target > RX_MAX_TARGET) - target = RX_MAX_TARGET; - - for (i = 0; i < num_queues; ++i) { - queue = &np->queues[i]; - spin_lock_bh(&queue->rx_lock); - if (target < queue->rx_min_target) - queue->rx_min_target = target; - queue->rx_max_target = target; - if (target < queue->rx_target) - queue->rx_target = target; - - xennet_alloc_rx_buffers(queue); + /* rxbuf_min and rxbuf_max are no longer configurable. */ - spin_unlock_bh(&queue->rx_lock); - } return len; } -static ssize_t show_rxbuf_cur(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct net_device *netdev = to_net_dev(dev); - struct netfront_info *info = netdev_priv(netdev); - unsigned int num_queues = netdev->real_num_tx_queues; - - if (num_queues) - return sprintf(buf, "%u\n", info->queues[0].rx_target); - else - return sprintf(buf, "0\n"); -} - static struct device_attribute xennet_attrs[] = { - __ATTR(rxbuf_min, S_IRUGO|S_IWUSR, show_rxbuf_min, store_rxbuf_min), - __ATTR(rxbuf_max, S_IRUGO|S_IWUSR, show_rxbuf_max, store_rxbuf_max), - __ATTR(rxbuf_cur, S_IRUGO, show_rxbuf_cur, NULL), + __ATTR(rxbuf_min, S_IRUGO|S_IWUSR, show_rxbuf, store_rxbuf), + __ATTR(rxbuf_max, S_IRUGO|S_IWUSR, show_rxbuf, store_rxbuf), + __ATTR(rxbuf_cur, S_IRUGO, show_rxbuf, NULL), }; static int xennet_sysfs_addif(struct net_device *netdev) |