Merge branch 'master' of /repos/git/net-next-2.6
Conflicts: include/net/netfilter/xt_rateest.h net/bridge/br_netfilter.c net/netfilter/nf_conntrack_core.c Signed-off-by: Patrick McHardy <kaber@trash.net>
This commit is contained in:
commit
f9181f4ffc
531 changed files with 14834 additions and 8681 deletions
|
@ -124,6 +124,8 @@ ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>
|
|||
|
||||
<hostname> Name of the client. May be supplied by autoconfiguration,
|
||||
but its absence will not trigger autoconfiguration.
|
||||
If specified and DHCP is used, the user provided hostname will
|
||||
be carried in the DHCP request to hopefully update DNS record.
|
||||
|
||||
Default: Client IP address is used in ASCII notation.
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ Table of Contents
|
|||
3.3 Configuring Bonding Manually with Ifenslave
|
||||
3.3.1 Configuring Multiple Bonds Manually
|
||||
3.4 Configuring Bonding Manually via Sysfs
|
||||
3.5 Overriding Configuration for Special Cases
|
||||
|
||||
4. Querying Bonding Configuration
|
||||
4.1 Bonding Configuration
|
||||
|
@ -1318,8 +1319,87 @@ echo 2000 > /sys/class/net/bond1/bonding/arp_interval
|
|||
echo +eth2 > /sys/class/net/bond1/bonding/slaves
|
||||
echo +eth3 > /sys/class/net/bond1/bonding/slaves
|
||||
|
||||
3.5 Overriding Configuration for Special Cases
|
||||
----------------------------------------------
|
||||
When using the bonding driver, the physical port which transmits a frame is
|
||||
typically selected by the bonding driver, and is not relevant to the user or
|
||||
system administrator. The output port is simply selected using the policies of
|
||||
the selected bonding mode. On occasion however, it is helpful to direct certain
|
||||
classes of traffic to certain physical interfaces on output to implement
|
||||
slightly more complex policies. For example, to reach a web server over a
|
||||
bonded interface in which eth0 connects to a private network, while eth1
|
||||
connects via a public network, it may be desirous to bias the bond to send said
|
||||
traffic over eth0 first, using eth1 only as a fall back, while all other traffic
|
||||
can safely be sent over either interface. Such configurations may be achieved
|
||||
using the traffic control utilities inherent in linux.
|
||||
|
||||
4. Querying Bonding Configuration
|
||||
By default the bonding driver is multiqueue aware and 16 queues are created
|
||||
when the driver initializes (see Documentation/networking/multiqueue.txt
|
||||
for details). If more or less queues are desired the module parameter
|
||||
tx_queues can be used to change this value. There is no sysfs parameter
|
||||
available as the allocation is done at module init time.
|
||||
|
||||
The output of the file /proc/net/bonding/bondX has changed so the output Queue
|
||||
ID is now printed for each slave:
|
||||
|
||||
Bonding Mode: fault-tolerance (active-backup)
|
||||
Primary Slave: None
|
||||
Currently Active Slave: eth0
|
||||
MII Status: up
|
||||
MII Polling Interval (ms): 0
|
||||
Up Delay (ms): 0
|
||||
Down Delay (ms): 0
|
||||
|
||||
Slave Interface: eth0
|
||||
MII Status: up
|
||||
Link Failure Count: 0
|
||||
Permanent HW addr: 00:1a:a0:12:8f:cb
|
||||
Slave queue ID: 0
|
||||
|
||||
Slave Interface: eth1
|
||||
MII Status: up
|
||||
Link Failure Count: 0
|
||||
Permanent HW addr: 00:1a:a0:12:8f:cc
|
||||
Slave queue ID: 2
|
||||
|
||||
The queue_id for a slave can be set using the command:
|
||||
|
||||
# echo "eth1:2" > /sys/class/net/bond0/bonding/queue_id
|
||||
|
||||
Any interface that needs a queue_id set should set it with multiple calls
|
||||
like the one above until proper priorities are set for all interfaces. On
|
||||
distributions that allow configuration via initscripts, multiple 'queue_id'
|
||||
arguments can be added to BONDING_OPTS to set all needed slave queues.
|
||||
|
||||
These queue id's can be used in conjunction with the tc utility to configure
|
||||
a multiqueue qdisc and filters to bias certain traffic to transmit on certain
|
||||
slave devices. For instance, say we wanted, in the above configuration to
|
||||
force all traffic bound to 192.168.1.100 to use eth1 in the bond as its output
|
||||
device. The following commands would accomplish this:
|
||||
|
||||
# tc qdisc add dev bond0 handle 1 root multiq
|
||||
|
||||
# tc filter add dev bond0 protocol ip parent 1: prio 1 u32 match ip dst \
|
||||
192.168.1.100 action skbedit queue_mapping 2
|
||||
|
||||
These commands tell the kernel to attach a multiqueue queue discipline to the
|
||||
bond0 interface and filter traffic enqueued to it, such that packets with a dst
|
||||
ip of 192.168.1.100 have their output queue mapping value overwritten to 2.
|
||||
This value is then passed into the driver, causing the normal output path
|
||||
selection policy to be overridden, selecting instead qid 2, which maps to eth1.
|
||||
|
||||
Note that qid values begin at 1. Qid 0 is reserved to initiate to the driver
|
||||
that normal output policy selection should take place. One benefit to simply
|
||||
leaving the qid for a slave to 0 is the multiqueue awareness in the bonding
|
||||
driver that is now present. This awareness allows tc filters to be placed on
|
||||
slave devices as well as bond devices and the bonding driver will simply act as
|
||||
a pass-through for selecting output queues on the slave device rather than
|
||||
output port selection.
|
||||
|
||||
This feature first appeared in bonding driver version 3.7.0 and support for
|
||||
output slave selection was limited to round-robin and active-backup modes.
|
||||
|
||||
4 Querying Bonding Configuration
|
||||
=================================
|
||||
|
||||
4.1 Bonding Configuration
|
||||
|
|
|
@ -493,6 +493,32 @@ The user can also use poll() to check if a buffer is available:
|
|||
pfd.events = POLLOUT;
|
||||
retval = poll(&pfd, 1, timeout);
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
+ PACKET_TIMESTAMP
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
The PACKET_TIMESTAMP setting determines the source of the timestamp in
|
||||
the packet meta information. If your NIC is capable of timestamping
|
||||
packets in hardware, you can request those hardware timestamps to used.
|
||||
Note: you may need to enable the generation of hardware timestamps with
|
||||
SIOCSHWTSTAMP.
|
||||
|
||||
PACKET_TIMESTAMP accepts the same integer bit field as
|
||||
SO_TIMESTAMPING. However, only the SOF_TIMESTAMPING_SYS_HARDWARE
|
||||
and SOF_TIMESTAMPING_RAW_HARDWARE values are recognized by
|
||||
PACKET_TIMESTAMP. SOF_TIMESTAMPING_SYS_HARDWARE takes precedence over
|
||||
SOF_TIMESTAMPING_RAW_HARDWARE if both bits are set.
|
||||
|
||||
int req = 0;
|
||||
req |= SOF_TIMESTAMPING_SYS_HARDWARE;
|
||||
setsockopt(fd, SOL_PACKET, PACKET_TIMESTAMP, (void *) &req, sizeof(req))
|
||||
|
||||
If PACKET_TIMESTAMP is not set, a software timestamp generated inside
|
||||
the networking stack is used (the behavior before this setting was added).
|
||||
|
||||
See include/linux/net_tstamp.h and Documentation/networking/timestamping
|
||||
for more information on hardware timestamps.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
+ THANKS
|
||||
--------------------------------------------------------------------------------
|
||||
|
|
|
@ -151,6 +151,8 @@ Examples:
|
|||
|
||||
pgset stop aborts injection. Also, ^C aborts generator.
|
||||
|
||||
pgset "rate 300M" set rate to 300 Mb/s
|
||||
pgset "ratep 1000000" set rate to 1Mpps
|
||||
|
||||
Example scripts
|
||||
===============
|
||||
|
@ -241,6 +243,9 @@ src6
|
|||
flows
|
||||
flowlen
|
||||
|
||||
rate
|
||||
ratep
|
||||
|
||||
References:
|
||||
ftp://robur.slu.se/pub/Linux/net-development/pktgen-testing/
|
||||
ftp://robur.slu.se/pub/Linux/net-development/pktgen-testing/examples/
|
||||
|
|
|
@ -2978,7 +2978,6 @@ F: drivers/net/ixgb/
|
|||
F: drivers/net/ixgbe/
|
||||
|
||||
INTEL PRO/WIRELESS 2100 NETWORK CONNECTION SUPPORT
|
||||
M: Zhu Yi <yi.zhu@intel.com>
|
||||
M: Reinette Chatre <reinette.chatre@intel.com>
|
||||
M: Intel Linux Wireless <ilw@linux.intel.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
|
@ -2988,7 +2987,6 @@ F: Documentation/networking/README.ipw2100
|
|||
F: drivers/net/wireless/ipw2x00/ipw2100.*
|
||||
|
||||
INTEL PRO/WIRELESS 2915ABG NETWORK CONNECTION SUPPORT
|
||||
M: Zhu Yi <yi.zhu@intel.com>
|
||||
M: Reinette Chatre <reinette.chatre@intel.com>
|
||||
M: Intel Linux Wireless <ilw@linux.intel.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
|
@ -3019,8 +3017,8 @@ F: drivers/net/wimax/i2400m/
|
|||
F: include/linux/wimax/i2400m.h
|
||||
|
||||
INTEL WIRELESS WIFI LINK (iwlwifi)
|
||||
M: Zhu Yi <yi.zhu@intel.com>
|
||||
M: Reinette Chatre <reinette.chatre@intel.com>
|
||||
M: Wey-Yi Guy <wey-yi.w.guy@intel.com>
|
||||
M: Intel Linux Wireless <ilw@linux.intel.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
W: http://intellinuxwireless.org
|
||||
|
@ -3030,7 +3028,6 @@ F: drivers/net/wireless/iwlwifi/
|
|||
|
||||
INTEL WIRELESS MULTICOMM 3200 WIFI (iwmc3200wifi)
|
||||
M: Samuel Ortiz <samuel.ortiz@intel.com>
|
||||
M: Zhu Yi <yi.zhu@intel.com>
|
||||
M: Intel Linux Wireless <ilw@linux.intel.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
S: Supported
|
||||
|
|
|
@ -215,7 +215,7 @@ static int addr4_resolve(struct sockaddr_in *src_in,
|
|||
|
||||
neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->idev->dev);
|
||||
if (!neigh || !(neigh->nud_state & NUD_VALID)) {
|
||||
neigh_event_send(rt->u.dst.neighbour, NULL);
|
||||
neigh_event_send(rt->dst.neighbour, NULL);
|
||||
ret = -ENODATA;
|
||||
if (neigh)
|
||||
goto release;
|
||||
|
|
|
@ -1364,7 +1364,7 @@ static int pass_accept_req(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
|
|||
__func__);
|
||||
goto reject;
|
||||
}
|
||||
dst = &rt->u.dst;
|
||||
dst = &rt->dst;
|
||||
l2t = t3_l2t_get(tdev, dst->neighbour, dst->neighbour->dev);
|
||||
if (!l2t) {
|
||||
printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n",
|
||||
|
@ -1932,7 +1932,7 @@ int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
|
|||
err = -EHOSTUNREACH;
|
||||
goto fail3;
|
||||
}
|
||||
ep->dst = &rt->u.dst;
|
||||
ep->dst = &rt->dst;
|
||||
|
||||
/* get a l2t entry */
|
||||
ep->l2t = t3_l2t_get(ep->com.tdev, ep->dst->neighbour,
|
||||
|
|
|
@ -1364,7 +1364,7 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
|
|||
__func__);
|
||||
goto reject;
|
||||
}
|
||||
dst = &rt->u.dst;
|
||||
dst = &rt->dst;
|
||||
if (dst->neighbour->dev->flags & IFF_LOOPBACK) {
|
||||
pdev = ip_dev_find(&init_net, peer_ip);
|
||||
BUG_ON(!pdev);
|
||||
|
@ -1938,7 +1938,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
|
|||
err = -EHOSTUNREACH;
|
||||
goto fail3;
|
||||
}
|
||||
ep->dst = &rt->u.dst;
|
||||
ep->dst = &rt->dst;
|
||||
|
||||
/* get a l2t entry */
|
||||
if (ep->dst->neighbour->dev->flags & IFF_LOOPBACK) {
|
||||
|
|
|
@ -1146,7 +1146,7 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi
|
|||
}
|
||||
|
||||
if ((neigh == NULL) || (!(neigh->nud_state & NUD_VALID)))
|
||||
neigh_event_send(rt->u.dst.neighbour, NULL);
|
||||
neigh_event_send(rt->dst.neighbour, NULL);
|
||||
|
||||
ip_rt_put(rt);
|
||||
return rc;
|
||||
|
|
|
@ -1020,12 +1020,12 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data)
|
|||
if (cmd == AVMB1_ADDCARD) {
|
||||
if ((retval = copy_from_user(&cdef, data,
|
||||
sizeof(avmb1_carddef))))
|
||||
return retval;
|
||||
return -EFAULT;
|
||||
cdef.cardtype = AVM_CARDTYPE_B1;
|
||||
} else {
|
||||
if ((retval = copy_from_user(&cdef, data,
|
||||
sizeof(avmb1_extcarddef))))
|
||||
return retval;
|
||||
return -EFAULT;
|
||||
}
|
||||
cparams.port = cdef.port;
|
||||
cparams.irq = cdef.irq;
|
||||
|
@ -1218,7 +1218,7 @@ int capi20_manufacturer(unsigned int cmd, void __user *data)
|
|||
kcapi_carddef cdef;
|
||||
|
||||
if ((retval = copy_from_user(&cdef, data, sizeof(cdef))))
|
||||
return retval;
|
||||
return -EFAULT;
|
||||
|
||||
cparams.port = cdef.port;
|
||||
cparams.irq = cdef.irq;
|
||||
|
|
|
@ -320,12 +320,12 @@ inittiger(struct tiger_hw *card)
|
|||
return -ENOMEM;
|
||||
}
|
||||
for (i = 0; i < 2; i++) {
|
||||
card->bc[i].hsbuf = kmalloc(NJ_DMA_TXSIZE, GFP_KERNEL);
|
||||
card->bc[i].hsbuf = kmalloc(NJ_DMA_TXSIZE, GFP_ATOMIC);
|
||||
if (!card->bc[i].hsbuf) {
|
||||
pr_info("%s: no B%d send buffer\n", card->name, i + 1);
|
||||
return -ENOMEM;
|
||||
}
|
||||
card->bc[i].hrbuf = kmalloc(NJ_DMA_RXSIZE, GFP_KERNEL);
|
||||
card->bc[i].hrbuf = kmalloc(NJ_DMA_RXSIZE, GFP_ATOMIC);
|
||||
if (!card->bc[i].hrbuf) {
|
||||
pr_info("%s: no B%d recv buffer\n", card->name, i + 1);
|
||||
return -ENOMEM;
|
||||
|
|
|
@ -34,7 +34,7 @@ struct mc32_mailbox
|
|||
{
|
||||
u16 mbox;
|
||||
u16 data[1];
|
||||
} __attribute((packed));
|
||||
} __packed;
|
||||
|
||||
struct skb_header
|
||||
{
|
||||
|
@ -43,7 +43,7 @@ struct skb_header
|
|||
u16 next; /* Do not change! */
|
||||
u16 length;
|
||||
u32 data;
|
||||
} __attribute((packed));
|
||||
} __packed;
|
||||
|
||||
struct mc32_stats
|
||||
{
|
||||
|
@ -68,7 +68,7 @@ struct mc32_stats
|
|||
u32 dataA[6];
|
||||
u16 dataB[5];
|
||||
u32 dataC[14];
|
||||
} __attribute((packed));
|
||||
} __packed;
|
||||
|
||||
#define STATUS_MASK 0x0F
|
||||
#define COMPLETED (1<<7)
|
||||
|
|
|
@ -322,7 +322,7 @@ struct cp_dma_stats {
|
|||
__le32 rx_ok_mcast;
|
||||
__le16 tx_abort;
|
||||
__le16 tx_underrun;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct cp_extra_stats {
|
||||
unsigned long rx_frags;
|
||||
|
@ -598,8 +598,8 @@ static int cp_rx_poll(struct napi_struct *napi, int budget)
|
|||
goto rx_status_loop;
|
||||
|
||||
spin_lock_irqsave(&cp->lock, flags);
|
||||
cpw16_f(IntrMask, cp_intr_mask);
|
||||
__napi_complete(napi);
|
||||
cpw16_f(IntrMask, cp_intr_mask);
|
||||
spin_unlock_irqrestore(&cp->lock, flags);
|
||||
}
|
||||
|
||||
|
|
|
@ -860,6 +860,7 @@ static __devinit struct net_device * rtl8139_init_board (struct pci_dev *pdev)
|
|||
}
|
||||
|
||||
/* if unknown chip, assume array element #0, original RTL-8139 in this case */
|
||||
i = 0;
|
||||
dev_dbg(&pdev->dev, "unknown chip version, assuming RTL-8139\n");
|
||||
dev_dbg(&pdev->dev, "TxConfig = 0x%x\n", RTL_R32 (TxConfig));
|
||||
tp->chipset = 0;
|
||||
|
@ -2088,8 +2089,8 @@ static int rtl8139_poll(struct napi_struct *napi, int budget)
|
|||
* again when we think we are done.
|
||||
*/
|
||||
spin_lock_irqsave(&tp->lock, flags);
|
||||
RTL_W16_F(IntrMask, rtl8139_intr_mask);
|
||||
__napi_complete(napi);
|
||||
RTL_W16_F(IntrMask, rtl8139_intr_mask);
|
||||
spin_unlock_irqrestore(&tp->lock, flags);
|
||||
}
|
||||
spin_unlock(&tp->rx_lock);
|
||||
|
|
|
@ -1659,6 +1659,7 @@ config R6040
|
|||
depends on NET_PCI && PCI
|
||||
select CRC32
|
||||
select MII
|
||||
select PHYLIB
|
||||
help
|
||||
This is a driver for the R6040 Fast Ethernet MACs found in the
|
||||
the RDC R-321x System-on-chips.
|
||||
|
|
|
@ -738,6 +738,17 @@ static void eth_set_mcast_list(struct net_device *dev)
|
|||
struct netdev_hw_addr *ha;
|
||||
u8 diffs[ETH_ALEN], *addr;
|
||||
int i;
|
||||
static const u8 allmulti[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
if (dev->flags & IFF_ALLMULTI) {
|
||||
for (i = 0; i < ETH_ALEN; i++) {
|
||||
__raw_writel(allmulti[i], &port->regs->mcast_addr[i]);
|
||||
__raw_writel(allmulti[i], &port->regs->mcast_mask[i]);
|
||||
}
|
||||
__raw_writel(DEFAULT_RX_CNTRL0 | RX_CNTRL0_ADDR_FLTR_EN,
|
||||
&port->regs->rx_control[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((dev->flags & IFF_PROMISC) || netdev_mc_empty(dev)) {
|
||||
__raw_writel(DEFAULT_RX_CNTRL0 & ~RX_CNTRL0_ADDR_FLTR_EN,
|
||||
|
|
|
@ -73,7 +73,8 @@
|
|||
#define FULL_DUPLEX 2
|
||||
|
||||
#define AT_RX_BUF_SIZE (ETH_FRAME_LEN + VLAN_HLEN + ETH_FCS_LEN)
|
||||
#define MAX_JUMBO_FRAME_SIZE (9*1024)
|
||||
#define MAX_JUMBO_FRAME_SIZE (6*1024)
|
||||
#define MAX_TSO_FRAME_SIZE (7*1024)
|
||||
#define MAX_TX_OFFLOAD_THRESH (9*1024)
|
||||
|
||||
#define AT_MAX_RECEIVE_QUEUE 4
|
||||
|
@ -87,10 +88,11 @@
|
|||
#define AT_MAX_INT_WORK 5
|
||||
#define AT_TWSI_EEPROM_TIMEOUT 100
|
||||
#define AT_HW_MAX_IDLE_DELAY 10
|
||||
#define AT_SUSPEND_LINK_TIMEOUT 28
|
||||
#define AT_SUSPEND_LINK_TIMEOUT 100
|
||||
|
||||
#define AT_ASPM_L0S_TIMER 6
|
||||
#define AT_ASPM_L1_TIMER 12
|
||||
#define AT_LCKDET_TIMER 12
|
||||
|
||||
#define ATL1C_PCIE_L0S_L1_DISABLE 0x01
|
||||
#define ATL1C_PCIE_PHY_RESET 0x02
|
||||
|
@ -316,6 +318,7 @@ enum atl1c_nic_type {
|
|||
athr_l2c_b,
|
||||
athr_l2c_b2,
|
||||
athr_l1d,
|
||||
athr_l1d_2,
|
||||
};
|
||||
|
||||
enum atl1c_trans_queue {
|
||||
|
@ -392,6 +395,8 @@ struct atl1c_hw {
|
|||
u16 subsystem_id;
|
||||
u16 subsystem_vendor_id;
|
||||
u8 revision_id;
|
||||
u16 phy_id1;
|
||||
u16 phy_id2;
|
||||
|
||||
u32 intr_mask;
|
||||
u8 dmaw_dly_cnt;
|
||||
|
|
|
@ -37,6 +37,9 @@ int atl1c_check_eeprom_exist(struct atl1c_hw *hw)
|
|||
if (data & TWSI_DEBUG_DEV_EXIST)
|
||||
return 1;
|
||||
|
||||
AT_READ_REG(hw, REG_MASTER_CTRL, &data);
|
||||
if (data & MASTER_CTRL_OTP_SEL)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -69,6 +72,8 @@ static int atl1c_get_permanent_address(struct atl1c_hw *hw)
|
|||
u32 i;
|
||||
u32 otp_ctrl_data;
|
||||
u32 twsi_ctrl_data;
|
||||
u32 ltssm_ctrl_data;
|
||||
u32 wol_data;
|
||||
u8 eth_addr[ETH_ALEN];
|
||||
u16 phy_data;
|
||||
bool raise_vol = false;
|
||||
|
@ -104,6 +109,15 @@ static int atl1c_get_permanent_address(struct atl1c_hw *hw)
|
|||
udelay(20);
|
||||
raise_vol = true;
|
||||
}
|
||||
/* close open bit of ReadOnly*/
|
||||
AT_READ_REG(hw, REG_LTSSM_ID_CTRL, <ssm_ctrl_data);
|
||||
ltssm_ctrl_data &= ~LTSSM_ID_EN_WRO;
|
||||
AT_WRITE_REG(hw, REG_LTSSM_ID_CTRL, ltssm_ctrl_data);
|
||||
|
||||
/* clear any WOL settings */
|
||||
AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
|
||||
AT_READ_REG(hw, REG_WOL_CTRL, &wol_data);
|
||||
|
||||
|
||||
AT_READ_REG(hw, REG_TWSI_CTRL, &twsi_ctrl_data);
|
||||
twsi_ctrl_data |= TWSI_CTRL_SW_LDSTART;
|
||||
|
@ -119,17 +133,15 @@ static int atl1c_get_permanent_address(struct atl1c_hw *hw)
|
|||
}
|
||||
/* Disable OTP_CLK */
|
||||
if ((hw->nic_type == athr_l1c || hw->nic_type == athr_l2c)) {
|
||||
if (otp_ctrl_data & OTP_CTRL_CLK_EN) {
|
||||
otp_ctrl_data &= ~OTP_CTRL_CLK_EN;
|
||||
AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data);
|
||||
AT_WRITE_FLUSH(hw);
|
||||
msleep(1);
|
||||
}
|
||||
otp_ctrl_data &= ~OTP_CTRL_CLK_EN;
|
||||
AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data);
|
||||
msleep(1);
|
||||
}
|
||||
if (raise_vol) {
|
||||
if (hw->nic_type == athr_l2c_b ||
|
||||
hw->nic_type == athr_l2c_b2 ||
|
||||
hw->nic_type == athr_l1d) {
|
||||
hw->nic_type == athr_l1d ||
|
||||
hw->nic_type == athr_l1d_2) {
|
||||
atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x00);
|
||||
if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data))
|
||||
goto out;
|
||||
|
@ -456,14 +468,22 @@ int atl1c_phy_reset(struct atl1c_hw *hw)
|
|||
|
||||
if (hw->nic_type == athr_l2c_b ||
|
||||
hw->nic_type == athr_l2c_b2 ||
|
||||
hw->nic_type == athr_l1d) {
|
||||
hw->nic_type == athr_l1d ||
|
||||
hw->nic_type == athr_l1d_2) {
|
||||
atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x3B);
|
||||
atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data);
|
||||
atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data & 0xFFF7);
|
||||
msleep(20);
|
||||
}
|
||||
|
||||
/*Enable PHY LinkChange Interrupt */
|
||||
if (hw->nic_type == athr_l1d) {
|
||||
atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x29);
|
||||
atl1c_write_phy_reg(hw, MII_DBG_DATA, 0x929D);
|
||||
}
|
||||
if (hw->nic_type == athr_l1c || hw->nic_type == athr_l2c_b2
|
||||
|| hw->nic_type == athr_l2c || hw->nic_type == athr_l2c) {
|
||||
atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x29);
|
||||
atl1c_write_phy_reg(hw, MII_DBG_DATA, 0xB6DD);
|
||||
}
|
||||
err = atl1c_write_phy_reg(hw, MII_IER, mii_ier_data);
|
||||
if (err) {
|
||||
if (netif_msg_hw(adapter))
|
||||
|
@ -482,12 +502,10 @@ int atl1c_phy_init(struct atl1c_hw *hw)
|
|||
struct pci_dev *pdev = adapter->pdev;
|
||||
int ret_val;
|
||||
u16 mii_bmcr_data = BMCR_RESET;
|
||||
u16 phy_id1, phy_id2;
|
||||
|
||||
if ((atl1c_read_phy_reg(hw, MII_PHYSID1, &phy_id1) != 0) ||
|
||||
(atl1c_read_phy_reg(hw, MII_PHYSID2, &phy_id2) != 0)) {
|
||||
if (netif_msg_link(adapter))
|
||||
dev_err(&pdev->dev, "Error get phy ID\n");
|
||||
if ((atl1c_read_phy_reg(hw, MII_PHYSID1, &hw->phy_id1) != 0) ||
|
||||
(atl1c_read_phy_reg(hw, MII_PHYSID2, &hw->phy_id2) != 0)) {
|
||||
dev_err(&pdev->dev, "Error get phy ID\n");
|
||||
return -1;
|
||||
}
|
||||
switch (hw->media_type) {
|
||||
|
@ -572,6 +590,65 @@ int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int atl1c_phy_power_saving(struct atl1c_hw *hw)
|
||||
{
|
||||
struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter;
|
||||
struct pci_dev *pdev = adapter->pdev;
|
||||
int ret = 0;
|
||||
u16 autoneg_advertised = ADVERTISED_10baseT_Half;
|
||||
u16 save_autoneg_advertised;
|
||||
u16 phy_data;
|
||||
u16 mii_lpa_data;
|
||||
u16 speed = SPEED_0;
|
||||
u16 duplex = FULL_DUPLEX;
|
||||
int i;
|
||||
|
||||
atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
|
||||
atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
|
||||
if (phy_data & BMSR_LSTATUS) {
|
||||
atl1c_read_phy_reg(hw, MII_LPA, &mii_lpa_data);
|
||||
if (mii_lpa_data & LPA_10FULL)
|
||||
autoneg_advertised = ADVERTISED_10baseT_Full;
|
||||
else if (mii_lpa_data & LPA_10HALF)
|
||||
autoneg_advertised = ADVERTISED_10baseT_Half;
|
||||
else if (mii_lpa_data & LPA_100HALF)
|
||||
autoneg_advertised = ADVERTISED_100baseT_Half;
|
||||
else if (mii_lpa_data & LPA_100FULL)
|
||||
autoneg_advertised = ADVERTISED_100baseT_Full;
|
||||
|
||||
save_autoneg_advertised = hw->autoneg_advertised;
|
||||
hw->phy_configured = false;
|
||||
hw->autoneg_advertised = autoneg_advertised;
|
||||
if (atl1c_restart_autoneg(hw) != 0) {
|
||||
dev_dbg(&pdev->dev, "phy autoneg failed\n");
|
||||
ret = -1;
|
||||
}
|
||||
hw->autoneg_advertised = save_autoneg_advertised;
|
||||
|
||||
if (mii_lpa_data) {
|
||||
for (i = 0; i < AT_SUSPEND_LINK_TIMEOUT; i++) {
|
||||
mdelay(100);
|
||||
atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
|
||||
atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
|
||||
if (phy_data & BMSR_LSTATUS) {
|
||||
if (atl1c_get_speed_and_duplex(hw, &speed,
|
||||
&duplex) != 0)
|
||||
dev_dbg(&pdev->dev,
|
||||
"get speed and duplex failed\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
speed = SPEED_10;
|
||||
duplex = HALF_DUPLEX;
|
||||
}
|
||||
adapter->link_speed = speed;
|
||||
adapter->link_duplex = duplex;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int atl1c_restart_autoneg(struct atl1c_hw *hw)
|
||||
{
|
||||
int err = 0;
|
||||
|
|
|
@ -42,7 +42,7 @@ bool atl1c_read_eeprom(struct atl1c_hw *hw, u32 offset, u32 *p_value);
|
|||
int atl1c_phy_init(struct atl1c_hw *hw);
|
||||
int atl1c_check_eeprom_exist(struct atl1c_hw *hw);
|
||||
int atl1c_restart_autoneg(struct atl1c_hw *hw);
|
||||
|
||||
int atl1c_phy_power_saving(struct atl1c_hw *hw);
|
||||
/* register definition */
|
||||
#define REG_DEVICE_CAP 0x5C
|
||||
#define DEVICE_CAP_MAX_PAYLOAD_MASK 0x7
|
||||
|
@ -120,6 +120,12 @@ int atl1c_restart_autoneg(struct atl1c_hw *hw);
|
|||
#define REG_PCIE_PHYMISC 0x1000
|
||||
#define PCIE_PHYMISC_FORCE_RCV_DET 0x4
|
||||
|
||||
#define REG_PCIE_PHYMISC2 0x1004
|
||||
#define PCIE_PHYMISC2_SERDES_CDR_MASK 0x3
|
||||
#define PCIE_PHYMISC2_SERDES_CDR_SHIFT 16
|
||||
#define PCIE_PHYMISC2_SERDES_TH_MASK 0x3
|
||||
#define PCIE_PHYMISC2_SERDES_TH_SHIFT 18
|
||||
|
||||
#define REG_TWSI_DEBUG 0x1108
|
||||
#define TWSI_DEBUG_DEV_EXIST 0x20000000
|
||||
|
||||
|
@ -150,24 +156,28 @@ int atl1c_restart_autoneg(struct atl1c_hw *hw);
|
|||
#define PM_CTRL_ASPM_L0S_EN 0x00001000
|
||||
#define PM_CTRL_CLK_SWH_L1 0x00002000
|
||||
#define PM_CTRL_CLK_PWM_VER1_1 0x00004000
|
||||
#define PM_CTRL_PCIE_RECV 0x00008000
|
||||
#define PM_CTRL_RCVR_WT_TIMER 0x00008000
|
||||
#define PM_CTRL_L1_ENTRY_TIMER_MASK 0xF
|
||||
#define PM_CTRL_L1_ENTRY_TIMER_SHIFT 16
|
||||
#define PM_CTRL_PM_REQ_TIMER_MASK 0xF
|
||||
#define PM_CTRL_PM_REQ_TIMER_SHIFT 20
|
||||
#define PM_CTRL_LCKDET_TIMER_MASK 0x3F
|
||||
#define PM_CTRL_LCKDET_TIMER_MASK 0xF
|
||||
#define PM_CTRL_LCKDET_TIMER_SHIFT 24
|
||||
#define PM_CTRL_EN_BUFS_RX_L0S 0x10000000
|
||||
#define PM_CTRL_SA_DLY_EN 0x20000000
|
||||
#define PM_CTRL_MAC_ASPM_CHK 0x40000000
|
||||
#define PM_CTRL_HOTRST 0x80000000
|
||||
|
||||
#define REG_LTSSM_ID_CTRL 0x12FC
|
||||
#define LTSSM_ID_EN_WRO 0x1000
|
||||
/* Selene Master Control Register */
|
||||
#define REG_MASTER_CTRL 0x1400
|
||||
#define MASTER_CTRL_SOFT_RST 0x1
|
||||
#define MASTER_CTRL_TEST_MODE_MASK 0x3
|
||||
#define MASTER_CTRL_TEST_MODE_SHIFT 2
|
||||
#define MASTER_CTRL_BERT_START 0x10
|
||||
#define MASTER_CTRL_OOB_DIS_OFF 0x40
|
||||
#define MASTER_CTRL_SA_TIMER_EN 0x80
|
||||
#define MASTER_CTRL_MTIMER_EN 0x100
|
||||
#define MASTER_CTRL_MANUAL_INT 0x200
|
||||
#define MASTER_CTRL_TX_ITIMER_EN 0x400
|
||||
|
@ -220,6 +230,12 @@ int atl1c_restart_autoneg(struct atl1c_hw *hw);
|
|||
GPHY_CTRL_PWDOWN_HW |\
|
||||
GPHY_CTRL_PHY_IDDQ)
|
||||
|
||||
#define GPHY_CTRL_POWER_SAVING ( \
|
||||
GPHY_CTRL_SEL_ANA_RST |\
|
||||
GPHY_CTRL_HIB_EN |\
|
||||
GPHY_CTRL_HIB_PULSE |\
|
||||
GPHY_CTRL_PWDOWN_HW |\
|
||||
GPHY_CTRL_PHY_IDDQ)
|
||||
/* Block IDLE Status Register */
|
||||
#define REG_IDLE_STATUS 0x1410
|
||||
#define IDLE_STATUS_MASK 0x00FF
|
||||
|
@ -287,6 +303,14 @@ int atl1c_restart_autoneg(struct atl1c_hw *hw);
|
|||
#define SERDES_LOCK_DETECT 0x1 /* SerDes lock detected. This signal
|
||||
* comes from Analog SerDes */
|
||||
#define SERDES_LOCK_DETECT_EN 0x2 /* 1: Enable SerDes Lock detect function */
|
||||
#define SERDES_LOCK_STS_SELFB_PLL_SHIFT 0xE
|
||||
#define SERDES_LOCK_STS_SELFB_PLL_MASK 0x3
|
||||
#define SERDES_OVCLK_18_25 0x0
|
||||
#define SERDES_OVCLK_12_18 0x1
|
||||
#define SERDES_OVCLK_0_4 0x2
|
||||
#define SERDES_OVCLK_4_12 0x3
|
||||
#define SERDES_MAC_CLK_SLOWDOWN 0x20000
|
||||
#define SERDES_PYH_CLK_SLOWDOWN 0x40000
|
||||
|
||||
/* MAC Control Register */
|
||||
#define REG_MAC_CTRL 0x1480
|
||||
|
@ -693,6 +717,21 @@ int atl1c_restart_autoneg(struct atl1c_hw *hw);
|
|||
#define REG_MAC_TX_STATUS_BIN 0x1760
|
||||
#define REG_MAC_TX_STATUS_END 0x17c0
|
||||
|
||||
#define REG_CLK_GATING_CTRL 0x1814
|
||||
#define CLK_GATING_DMAW_EN 0x0001
|
||||
#define CLK_GATING_DMAR_EN 0x0002
|
||||
#define CLK_GATING_TXQ_EN 0x0004
|
||||
#define CLK_GATING_RXQ_EN 0x0008
|
||||
#define CLK_GATING_TXMAC_EN 0x0010
|
||||
#define CLK_GATING_RXMAC_EN 0x0020
|
||||
|
||||
#define CLK_GATING_EN_ALL (CLK_GATING_DMAW_EN |\
|
||||
CLK_GATING_DMAR_EN |\
|
||||
CLK_GATING_TXQ_EN |\
|
||||
CLK_GATING_RXQ_EN |\
|
||||
CLK_GATING_TXMAC_EN|\
|
||||
CLK_GATING_RXMAC_EN)
|
||||
|
||||
/* DEBUG ADDR */
|
||||
#define REG_DEBUG_DATA0 0x1900
|
||||
#define REG_DEBUG_DATA1 0x1904
|
||||
|
@ -734,6 +773,10 @@ int atl1c_restart_autoneg(struct atl1c_hw *hw);
|
|||
|
||||
#define MII_PHYSID1 0x02
|
||||
#define MII_PHYSID2 0x03
|
||||
#define L1D_MPW_PHYID1 0xD01C /* V7 */
|
||||
#define L1D_MPW_PHYID2 0xD01D /* V1-V6 */
|
||||
#define L1D_MPW_PHYID3 0xD01E /* V8 */
|
||||
|
||||
|
||||
/* Autoneg Advertisement Register */
|
||||
#define MII_ADVERTISE 0x04
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
#include "atl1c.h"
|
||||
|
||||
#define ATL1C_DRV_VERSION "1.0.0.2-NAPI"
|
||||
#define ATL1C_DRV_VERSION "1.0.1.0-NAPI"
|
||||
char atl1c_driver_name[] = "atl1c";
|
||||
char atl1c_driver_version[] = ATL1C_DRV_VERSION;
|
||||
#define PCI_DEVICE_ID_ATTANSIC_L2C 0x1062
|
||||
|
@ -29,7 +29,7 @@ char atl1c_driver_version[] = ATL1C_DRV_VERSION;
|
|||
#define PCI_DEVICE_ID_ATHEROS_L2C_B 0x2060 /* AR8152 v1.1 Fast 10/100 */
|
||||
#define PCI_DEVICE_ID_ATHEROS_L2C_B2 0x2062 /* AR8152 v2.0 Fast 10/100 */
|
||||
#define PCI_DEVICE_ID_ATHEROS_L1D 0x1073 /* AR8151 v1.0 Gigabit 1000 */
|
||||
|
||||
#define PCI_DEVICE_ID_ATHEROS_L1D_2_0 0x1083 /* AR8151 v2.0 Gigabit 1000 */
|
||||
#define L2CB_V10 0xc0
|
||||
#define L2CB_V11 0xc1
|
||||
|
||||
|
@ -97,7 +97,28 @@ static const u16 atl1c_rrd_addr_lo_regs[AT_MAX_RECEIVE_QUEUE] =
|
|||
|
||||
static const u32 atl1c_default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE |
|
||||
NETIF_MSG_LINK | NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP;
|
||||
static void atl1c_pcie_patch(struct atl1c_hw *hw)
|
||||
{
|
||||
u32 data;
|
||||
|
||||
AT_READ_REG(hw, REG_PCIE_PHYMISC, &data);
|
||||
data |= PCIE_PHYMISC_FORCE_RCV_DET;
|
||||
AT_WRITE_REG(hw, REG_PCIE_PHYMISC, data);
|
||||
|
||||
if (hw->nic_type == athr_l2c_b && hw->revision_id == L2CB_V10) {
|
||||
AT_READ_REG(hw, REG_PCIE_PHYMISC2, &data);
|
||||
|
||||
data &= ~(PCIE_PHYMISC2_SERDES_CDR_MASK <<
|
||||
PCIE_PHYMISC2_SERDES_CDR_SHIFT);
|
||||
data |= 3 << PCIE_PHYMISC2_SERDES_CDR_SHIFT;
|
||||
data &= ~(PCIE_PHYMISC2_SERDES_TH_MASK <<
|
||||
PCIE_PHYMISC2_SERDES_TH_SHIFT);
|
||||
data |= 3 << PCIE_PHYMISC2_SERDES_TH_SHIFT;
|
||||
AT_WRITE_REG(hw, REG_PCIE_PHYMISC2, data);
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: no need any more ? */
|
||||
/*
|
||||
* atl1c_init_pcie - init PCIE module
|
||||
*/
|
||||
|
@ -127,6 +148,11 @@ static void atl1c_reset_pcie(struct atl1c_hw *hw, u32 flag)
|
|||
data &= ~PCIE_UC_SERVRITY_FCP;
|
||||
AT_WRITE_REG(hw, REG_PCIE_UC_SEVERITY, data);
|
||||
|
||||
AT_READ_REG(hw, REG_LTSSM_ID_CTRL, &data);
|
||||
data &= ~LTSSM_ID_EN_WRO;
|
||||
AT_WRITE_REG(hw, REG_LTSSM_ID_CTRL, data);
|
||||
|
||||
atl1c_pcie_patch(hw);
|
||||
if (flag & ATL1C_PCIE_L0S_L1_DISABLE)
|
||||
atl1c_disable_l0s_l1(hw);
|
||||
if (flag & ATL1C_PCIE_PHY_RESET)
|
||||
|
@ -135,7 +161,7 @@ static void atl1c_reset_pcie(struct atl1c_hw *hw, u32 flag)
|
|||
AT_WRITE_REG(hw, REG_GPHY_CTRL,
|
||||
GPHY_CTRL_DEFAULT | GPHY_CTRL_EXT_RESET);
|
||||
|
||||
msleep(1);
|
||||
msleep(5);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -159,6 +185,7 @@ static inline void atl1c_irq_disable(struct atl1c_adapter *adapter)
|
|||
{
|
||||
atomic_inc(&adapter->irq_sem);
|
||||
AT_WRITE_REG(&adapter->hw, REG_IMR, 0);
|
||||
AT_WRITE_REG(&adapter->hw, REG_ISR, ISR_DIS_INT);
|
||||
AT_WRITE_FLUSH(&adapter->hw);
|
||||
synchronize_irq(adapter->pdev->irq);
|
||||
}
|
||||
|
@ -231,15 +258,15 @@ static void atl1c_check_link_status(struct atl1c_adapter *adapter)
|
|||
|
||||
if ((phy_data & BMSR_LSTATUS) == 0) {
|
||||
/* link down */
|
||||
if (netif_carrier_ok(netdev)) {
|
||||
hw->hibernate = true;
|
||||
if (atl1c_stop_mac(hw) != 0)
|
||||
if (netif_msg_hw(adapter))
|
||||
dev_warn(&pdev->dev,
|
||||
"stop mac failed\n");
|
||||
atl1c_set_aspm(hw, false);
|
||||
}
|
||||
hw->hibernate = true;
|
||||
if (atl1c_stop_mac(hw) != 0)
|
||||
if (netif_msg_hw(adapter))
|
||||
dev_warn(&pdev->dev, "stop mac failed\n");
|
||||
atl1c_set_aspm(hw, false);
|
||||
netif_carrier_off(netdev);
|
||||
netif_stop_queue(netdev);
|
||||
atl1c_phy_reset(hw);
|
||||
atl1c_phy_init(&adapter->hw);
|
||||
} else {
|
||||
/* Link Up */
|
||||
hw->hibernate = false;
|
||||
|
@ -308,6 +335,7 @@ static void atl1c_common_task(struct work_struct *work)
|
|||
netdev = adapter->netdev;
|
||||
|
||||
if (adapter->work_event & ATL1C_WORK_EVENT_RESET) {
|
||||
adapter->work_event &= ~ATL1C_WORK_EVENT_RESET;
|
||||
netif_device_detach(netdev);
|
||||
atl1c_down(adapter);
|
||||
atl1c_up(adapter);
|
||||
|
@ -315,8 +343,11 @@ static void atl1c_common_task(struct work_struct *work)
|
|||
return;
|
||||
}
|
||||
|
||||
if (adapter->work_event & ATL1C_WORK_EVENT_LINK_CHANGE)
|
||||
if (adapter->work_event & ATL1C_WORK_EVENT_LINK_CHANGE) {
|
||||
adapter->work_event &= ~ATL1C_WORK_EVENT_LINK_CHANGE;
|
||||
atl1c_check_link_status(adapter);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
@ -476,6 +507,13 @@ static int atl1c_change_mtu(struct net_device *netdev, int new_mtu)
|
|||
netdev->mtu = new_mtu;
|
||||
adapter->hw.max_frame_size = new_mtu;
|
||||
atl1c_set_rxbufsize(adapter, netdev);
|
||||
if (new_mtu > MAX_TSO_FRAME_SIZE) {
|
||||
adapter->netdev->features &= ~NETIF_F_TSO;
|
||||
adapter->netdev->features &= ~NETIF_F_TSO6;
|
||||
} else {
|
||||
adapter->netdev->features |= NETIF_F_TSO;
|
||||
adapter->netdev->features |= NETIF_F_TSO6;
|
||||
}
|
||||
atl1c_down(adapter);
|
||||
atl1c_up(adapter);
|
||||
clear_bit(__AT_RESETTING, &adapter->flags);
|
||||
|
@ -613,6 +651,9 @@ static void atl1c_set_mac_type(struct atl1c_hw *hw)
|
|||
case PCI_DEVICE_ID_ATHEROS_L1D:
|
||||
hw->nic_type = athr_l1d;
|
||||
break;
|
||||
case PCI_DEVICE_ID_ATHEROS_L1D_2_0:
|
||||
hw->nic_type = athr_l1d_2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -627,9 +668,7 @@ static int atl1c_setup_mac_funcs(struct atl1c_hw *hw)
|
|||
AT_READ_REG(hw, REG_PHY_STATUS, &phy_status_data);
|
||||
AT_READ_REG(hw, REG_LINK_CTRL, &link_ctrl_data);
|
||||
|
||||
hw->ctrl_flags = ATL1C_INTR_CLEAR_ON_READ |
|
||||
ATL1C_INTR_MODRT_ENABLE |
|
||||
ATL1C_RX_IPV6_CHKSUM |
|
||||
hw->ctrl_flags = ATL1C_INTR_MODRT_ENABLE |
|
||||
ATL1C_TXQ_MODE_ENHANCE;
|
||||
if (link_ctrl_data & LINK_CTRL_L0S_EN)
|
||||
hw->ctrl_flags |= ATL1C_ASPM_L0S_SUPPORT;
|
||||
|
@ -637,12 +676,12 @@ static int atl1c_setup_mac_funcs(struct atl1c_hw *hw)
|
|||
hw->ctrl_flags |= ATL1C_ASPM_L1_SUPPORT;
|
||||
if (link_ctrl_data & LINK_CTRL_EXT_SYNC)
|
||||
hw->ctrl_flags |= ATL1C_LINK_EXT_SYNC;
|
||||
hw->ctrl_flags |= ATL1C_ASPM_CTRL_MON;
|
||||
|
||||
if (hw->nic_type == athr_l1c ||
|
||||
hw->nic_type == athr_l1d) {
|
||||
hw->ctrl_flags |= ATL1C_ASPM_CTRL_MON;
|
||||
hw->nic_type == athr_l1d ||
|
||||
hw->nic_type == athr_l1d_2)
|
||||
hw->link_cap_flags |= ATL1C_LINK_CAP_1000M;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
|
@ -657,6 +696,8 @@ static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter)
|
|||
{
|
||||
struct atl1c_hw *hw = &adapter->hw;
|
||||
struct pci_dev *pdev = adapter->pdev;
|
||||
u32 revision;
|
||||
|
||||
|
||||
adapter->wol = 0;
|
||||
adapter->link_speed = SPEED_0;
|
||||
|
@ -669,7 +710,8 @@ static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter)
|
|||
hw->device_id = pdev->device;
|
||||
hw->subsystem_vendor_id = pdev->subsystem_vendor;
|
||||
hw->subsystem_id = pdev->subsystem_device;
|
||||
|
||||
AT_READ_REG(hw, PCI_CLASS_REVISION, &revision);
|
||||
hw->revision_id = revision & 0xFF;
|
||||
/* before link up, we assume hibernate is true */
|
||||
hw->hibernate = true;
|
||||
hw->media_type = MEDIA_TYPE_AUTO_SENSOR;
|
||||
|
@ -974,6 +1016,7 @@ static void atl1c_configure_des_ring(struct atl1c_adapter *adapter)
|
|||
struct atl1c_cmb *cmb = (struct atl1c_cmb *) &adapter->cmb;
|
||||
struct atl1c_smb *smb = (struct atl1c_smb *) &adapter->smb;
|
||||
int i;
|
||||
u32 data;
|
||||
|
||||
/* TPD */
|
||||
AT_WRITE_REG(hw, REG_TX_BASE_ADDR_HI,
|
||||
|
@ -1017,6 +1060,23 @@ static void atl1c_configure_des_ring(struct atl1c_adapter *adapter)
|
|||
(u32)((smb->dma & AT_DMA_HI_ADDR_MASK) >> 32));
|
||||
AT_WRITE_REG(hw, REG_SMB_BASE_ADDR_LO,
|
||||
(u32)(smb->dma & AT_DMA_LO_ADDR_MASK));
|
||||
if (hw->nic_type == athr_l2c_b) {
|
||||
AT_WRITE_REG(hw, REG_SRAM_RXF_LEN, 0x02a0L);
|
||||
AT_WRITE_REG(hw, REG_SRAM_TXF_LEN, 0x0100L);
|
||||
AT_WRITE_REG(hw, REG_SRAM_RXF_ADDR, 0x029f0000L);
|
||||
AT_WRITE_REG(hw, REG_SRAM_RFD0_INFO, 0x02bf02a0L);
|
||||
AT_WRITE_REG(hw, REG_SRAM_TXF_ADDR, 0x03bf02c0L);
|
||||
AT_WRITE_REG(hw, REG_SRAM_TRD_ADDR, 0x03df03c0L);
|
||||
AT_WRITE_REG(hw, REG_TXF_WATER_MARK, 0); /* TX watermark, to enter l1 state.*/
|
||||
AT_WRITE_REG(hw, REG_RXD_DMA_CTRL, 0); /* RXD threshold.*/
|
||||
}
|
||||
if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d_2) {
|
||||
/* Power Saving for L2c_B */
|
||||
AT_READ_REG(hw, REG_SERDES_LOCK, &data);
|
||||
data |= SERDES_MAC_CLK_SLOWDOWN;
|
||||
data |= SERDES_PYH_CLK_SLOWDOWN;
|
||||
AT_WRITE_REG(hw, REG_SERDES_LOCK, data);
|
||||
}
|
||||
/* Load all of base address above */
|
||||
AT_WRITE_REG(hw, REG_LOAD_PTR, 1);
|
||||
}
|
||||
|
@ -1029,6 +1089,7 @@ static void atl1c_configure_tx(struct atl1c_adapter *adapter)
|
|||
u16 tx_offload_thresh;
|
||||
u32 txq_ctrl_data;
|
||||
u32 extra_size = 0; /* Jumbo frame threshold in QWORD unit */
|
||||
u32 max_pay_load_data;
|
||||
|
||||
extra_size = ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN;
|
||||
tx_offload_thresh = MAX_TX_OFFLOAD_THRESH;
|
||||
|
@ -1046,8 +1107,11 @@ static void atl1c_configure_tx(struct atl1c_adapter *adapter)
|
|||
TXQ_NUM_TPD_BURST_SHIFT;
|
||||
if (hw->ctrl_flags & ATL1C_TXQ_MODE_ENHANCE)
|
||||
txq_ctrl_data |= TXQ_CTRL_ENH_MODE;
|
||||
txq_ctrl_data |= (atl1c_pay_load_size[hw->dmar_block] &
|
||||
max_pay_load_data = (atl1c_pay_load_size[hw->dmar_block] &
|
||||
TXQ_TXF_BURST_NUM_MASK) << TXQ_TXF_BURST_NUM_SHIFT;
|
||||
if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2)
|
||||
max_pay_load_data >>= 1;
|
||||
txq_ctrl_data |= max_pay_load_data;
|
||||
|
||||
AT_WRITE_REG(hw, REG_TXQ_CTRL, txq_ctrl_data);
|
||||
}
|
||||
|
@ -1078,7 +1142,7 @@ static void atl1c_configure_rx(struct atl1c_adapter *adapter)
|
|||
rxq_ctrl_data |= (hw->rss_hash_bits & RSS_HASH_BITS_MASK) <<
|
||||
RSS_HASH_BITS_SHIFT;
|
||||
if (hw->ctrl_flags & ATL1C_ASPM_CTRL_MON)
|
||||
rxq_ctrl_data |= (ASPM_THRUPUT_LIMIT_100M &
|
||||
rxq_ctrl_data |= (ASPM_THRUPUT_LIMIT_1M &
|
||||
ASPM_THRUPUT_LIMIT_MASK) << ASPM_THRUPUT_LIMIT_SHIFT;
|
||||
|
||||
AT_WRITE_REG(hw, REG_RXQ_CTRL, rxq_ctrl_data);
|
||||
|
@ -1198,21 +1262,23 @@ static int atl1c_reset_mac(struct atl1c_hw *hw)
|
|||
{
|
||||
struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter;
|
||||
struct pci_dev *pdev = adapter->pdev;
|
||||
int ret;
|
||||
u32 master_ctrl_data = 0;
|
||||
|
||||
AT_WRITE_REG(hw, REG_IMR, 0);
|
||||
AT_WRITE_REG(hw, REG_ISR, ISR_DIS_INT);
|
||||
|
||||
ret = atl1c_stop_mac(hw);
|
||||
if (ret)
|
||||
return ret;
|
||||
atl1c_stop_mac(hw);
|
||||
/*
|
||||
* Issue Soft Reset to the MAC. This will reset the chip's
|
||||
* transmit, receive, DMA. It will not effect
|
||||
* the current PCI configuration. The global reset bit is self-
|
||||
* clearing, and should clear within a microsecond.
|
||||
*/
|
||||
AT_WRITE_REGW(hw, REG_MASTER_CTRL, MASTER_CTRL_SOFT_RST);
|
||||
AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl_data);
|
||||
master_ctrl_data |= MASTER_CTRL_OOB_DIS_OFF;
|
||||
AT_WRITE_REGW(hw, REG_MASTER_CTRL, ((master_ctrl_data | MASTER_CTRL_SOFT_RST)
|
||||
& 0xFFFF));
|
||||
|
||||
AT_WRITE_FLUSH(hw);
|
||||
msleep(10);
|
||||
/* Wait at least 10ms for All module to be Idle */
|
||||
|
@ -1253,42 +1319,39 @@ static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup)
|
|||
{
|
||||
u32 pm_ctrl_data;
|
||||
u32 link_ctrl_data;
|
||||
u32 link_l1_timer = 0xF;
|
||||
|
||||
AT_READ_REG(hw, REG_PM_CTRL, &pm_ctrl_data);
|
||||
AT_READ_REG(hw, REG_LINK_CTRL, &link_ctrl_data);
|
||||
pm_ctrl_data &= ~PM_CTRL_SERDES_PD_EX_L1;
|
||||
|
||||
pm_ctrl_data &= ~PM_CTRL_SERDES_PD_EX_L1;
|
||||
pm_ctrl_data &= ~(PM_CTRL_L1_ENTRY_TIMER_MASK <<
|
||||
PM_CTRL_L1_ENTRY_TIMER_SHIFT);
|
||||
pm_ctrl_data &= ~(PM_CTRL_LCKDET_TIMER_MASK <<
|
||||
PM_CTRL_LCKDET_TIMER_SHIFT);
|
||||
PM_CTRL_LCKDET_TIMER_SHIFT);
|
||||
pm_ctrl_data |= AT_LCKDET_TIMER << PM_CTRL_LCKDET_TIMER_SHIFT;
|
||||
|
||||
pm_ctrl_data |= PM_CTRL_MAC_ASPM_CHK;
|
||||
pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN;
|
||||
pm_ctrl_data |= PM_CTRL_RBER_EN;
|
||||
pm_ctrl_data |= PM_CTRL_SDES_EN;
|
||||
|
||||
if (hw->nic_type == athr_l2c_b ||
|
||||
hw->nic_type == athr_l1d ||
|
||||
hw->nic_type == athr_l2c_b2) {
|
||||
if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d ||
|
||||
hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) {
|
||||
link_ctrl_data &= ~LINK_CTRL_EXT_SYNC;
|
||||
if (!(hw->ctrl_flags & ATL1C_APS_MODE_ENABLE)) {
|
||||
if (hw->nic_type == athr_l2c_b &&
|
||||
hw->revision_id == L2CB_V10)
|
||||
if (hw->nic_type == athr_l2c_b && hw->revision_id == L2CB_V10)
|
||||
link_ctrl_data |= LINK_CTRL_EXT_SYNC;
|
||||
}
|
||||
|
||||
AT_WRITE_REG(hw, REG_LINK_CTRL, link_ctrl_data);
|
||||
|
||||
pm_ctrl_data |= PM_CTRL_PCIE_RECV;
|
||||
pm_ctrl_data |= AT_ASPM_L1_TIMER << PM_CTRL_PM_REQ_TIMER_SHIFT;
|
||||
pm_ctrl_data &= ~PM_CTRL_EN_BUFS_RX_L0S;
|
||||
pm_ctrl_data |= PM_CTRL_RCVR_WT_TIMER;
|
||||
pm_ctrl_data &= ~(PM_CTRL_PM_REQ_TIMER_MASK <<
|
||||
PM_CTRL_PM_REQ_TIMER_SHIFT);
|
||||
pm_ctrl_data |= AT_ASPM_L1_TIMER <<
|
||||
PM_CTRL_PM_REQ_TIMER_SHIFT;
|
||||
pm_ctrl_data &= ~PM_CTRL_SA_DLY_EN;
|
||||
pm_ctrl_data &= ~PM_CTRL_HOTRST;
|
||||
pm_ctrl_data |= 1 << PM_CTRL_L1_ENTRY_TIMER_SHIFT;
|
||||
pm_ctrl_data |= PM_CTRL_SERDES_PD_EX_L1;
|
||||
}
|
||||
|
||||
pm_ctrl_data |= PM_CTRL_MAC_ASPM_CHK;
|
||||
if (linkup) {
|
||||
pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN;
|
||||
pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN;
|
||||
|
@ -1297,27 +1360,26 @@ static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup)
|
|||
if (hw->ctrl_flags & ATL1C_ASPM_L0S_SUPPORT)
|
||||
pm_ctrl_data |= PM_CTRL_ASPM_L0S_EN;
|
||||
|
||||
if (hw->nic_type == athr_l2c_b ||
|
||||
hw->nic_type == athr_l1d ||
|
||||
hw->nic_type == athr_l2c_b2) {
|
||||
if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d ||
|
||||
hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) {
|
||||
if (hw->nic_type == athr_l2c_b)
|
||||
if (!(hw->ctrl_flags & ATL1C_APS_MODE_ENABLE))
|
||||
pm_ctrl_data &= PM_CTRL_ASPM_L0S_EN;
|
||||
pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN;
|
||||
pm_ctrl_data &= ~PM_CTRL_SERDES_L1_EN;
|
||||
pm_ctrl_data &= ~PM_CTRL_SERDES_PLL_L1_EN;
|
||||
pm_ctrl_data &= ~PM_CTRL_SERDES_BUDS_RX_L1_EN;
|
||||
pm_ctrl_data |= PM_CTRL_CLK_SWH_L1;
|
||||
if (hw->adapter->link_speed == SPEED_100 ||
|
||||
hw->adapter->link_speed == SPEED_1000) {
|
||||
pm_ctrl_data &=
|
||||
~(PM_CTRL_L1_ENTRY_TIMER_MASK <<
|
||||
PM_CTRL_L1_ENTRY_TIMER_SHIFT);
|
||||
if (hw->nic_type == athr_l1d)
|
||||
pm_ctrl_data |= 0xF <<
|
||||
PM_CTRL_L1_ENTRY_TIMER_SHIFT;
|
||||
else
|
||||
pm_ctrl_data |= 7 <<
|
||||
PM_CTRL_L1_ENTRY_TIMER_SHIFT;
|
||||
if (hw->adapter->link_speed == SPEED_100 ||
|
||||
hw->adapter->link_speed == SPEED_1000) {
|
||||
pm_ctrl_data &= ~(PM_CTRL_L1_ENTRY_TIMER_MASK <<
|
||||
PM_CTRL_L1_ENTRY_TIMER_SHIFT);
|
||||
if (hw->nic_type == athr_l2c_b)
|
||||
link_l1_timer = 7;
|
||||
else if (hw->nic_type == athr_l2c_b2 ||
|
||||
hw->nic_type == athr_l1d_2)
|
||||
link_l1_timer = 4;
|
||||
pm_ctrl_data |= link_l1_timer <<
|
||||
PM_CTRL_L1_ENTRY_TIMER_SHIFT;
|
||||
}
|
||||
} else {
|
||||
pm_ctrl_data |= PM_CTRL_SERDES_L1_EN;
|
||||
|
@ -1326,24 +1388,12 @@ static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup)
|
|||
pm_ctrl_data &= ~PM_CTRL_CLK_SWH_L1;
|
||||
pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN;
|
||||
pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN;
|
||||
}
|
||||
atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x29);
|
||||
if (hw->adapter->link_speed == SPEED_10)
|
||||
if (hw->nic_type == athr_l1d)
|
||||
atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0xB69D);
|
||||
else
|
||||
atl1c_write_phy_reg(hw, MII_DBG_DATA, 0xB6DD);
|
||||
else if (hw->adapter->link_speed == SPEED_100)
|
||||
atl1c_write_phy_reg(hw, MII_DBG_DATA, 0xB2DD);
|
||||
else
|
||||
atl1c_write_phy_reg(hw, MII_DBG_DATA, 0x96DD);
|
||||
|
||||
}
|
||||
} else {
|
||||
pm_ctrl_data &= ~PM_CTRL_SERDES_BUDS_RX_L1_EN;
|
||||
pm_ctrl_data &= ~PM_CTRL_SERDES_L1_EN;
|
||||
pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN;
|
||||
pm_ctrl_data &= ~PM_CTRL_SERDES_PLL_L1_EN;
|
||||
|
||||
pm_ctrl_data |= PM_CTRL_CLK_SWH_L1;
|
||||
|
||||
if (hw->ctrl_flags & ATL1C_ASPM_L1_SUPPORT)
|
||||
|
@ -1351,8 +1401,9 @@ static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup)
|
|||
else
|
||||
pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN;
|
||||
}
|
||||
|
||||
AT_WRITE_REG(hw, REG_PM_CTRL, pm_ctrl_data);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void atl1c_setup_mac_ctrl(struct atl1c_adapter *adapter)
|
||||
|
@ -1391,7 +1442,8 @@ static void atl1c_setup_mac_ctrl(struct atl1c_adapter *adapter)
|
|||
mac_ctrl_data |= MAC_CTRL_MC_ALL_EN;
|
||||
|
||||
mac_ctrl_data |= MAC_CTRL_SINGLE_PAUSE_EN;
|
||||
if (hw->nic_type == athr_l1d || hw->nic_type == athr_l2c_b2) {
|
||||
if (hw->nic_type == athr_l1d || hw->nic_type == athr_l2c_b2 ||
|
||||
hw->nic_type == athr_l1d_2) {
|
||||
mac_ctrl_data |= MAC_CTRL_SPEED_MODE_SW;
|
||||
mac_ctrl_data |= MAC_CTRL_HASH_ALG_CRC32;
|
||||
}
|
||||
|
@ -1409,6 +1461,7 @@ static int atl1c_configure(struct atl1c_adapter *adapter)
|
|||
struct atl1c_hw *hw = &adapter->hw;
|
||||
u32 master_ctrl_data = 0;
|
||||
u32 intr_modrt_data;
|
||||
u32 data;
|
||||
|
||||
/* clear interrupt status */
|
||||
AT_WRITE_REG(hw, REG_ISR, 0xFFFFFFFF);
|
||||
|
@ -1418,6 +1471,15 @@ static int atl1c_configure(struct atl1c_adapter *adapter)
|
|||
* HW will enable self to assert interrupt event to system after
|
||||
* waiting x-time for software to notify it accept interrupt.
|
||||
*/
|
||||
|
||||
data = CLK_GATING_EN_ALL;
|
||||
if (hw->ctrl_flags & ATL1C_CLK_GATING_EN) {
|
||||
if (hw->nic_type == athr_l2c_b)
|
||||
data &= ~CLK_GATING_RXMAC_EN;
|
||||
} else
|
||||
data = 0;
|
||||
AT_WRITE_REG(hw, REG_CLK_GATING_CTRL, data);
|
||||
|
||||
AT_WRITE_REG(hw, REG_INT_RETRIG_TIMER,
|
||||
hw->ict & INT_RETRIG_TIMER_MASK);
|
||||
|
||||
|
@ -1436,6 +1498,7 @@ static int atl1c_configure(struct atl1c_adapter *adapter)
|
|||
if (hw->ctrl_flags & ATL1C_INTR_CLEAR_ON_READ)
|
||||
master_ctrl_data |= MASTER_CTRL_INT_RDCLR;
|
||||
|
||||
master_ctrl_data |= MASTER_CTRL_SA_TIMER_EN;
|
||||
AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data);
|
||||
|
||||
if (hw->ctrl_flags & ATL1C_CMB_ENABLE) {
|
||||
|
@ -1624,11 +1687,9 @@ static irqreturn_t atl1c_intr(int irq, void *data)
|
|||
"atl1c hardware error (status = 0x%x)\n",
|
||||
status & ISR_ERROR);
|
||||
/* reset MAC */
|
||||
hw->intr_mask &= ~ISR_ERROR;
|
||||
AT_WRITE_REG(hw, REG_IMR, hw->intr_mask);
|
||||
adapter->work_event |= ATL1C_WORK_EVENT_RESET;
|
||||
schedule_work(&adapter->common_task);
|
||||
break;
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
if (status & ISR_OVER)
|
||||
|
@ -2303,7 +2364,6 @@ void atl1c_down(struct atl1c_adapter *adapter)
|
|||
napi_disable(&adapter->napi);
|
||||
atl1c_irq_disable(adapter);
|
||||
atl1c_free_irq(adapter);
|
||||
AT_WRITE_REG(&adapter->hw, REG_ISR, ISR_DIS_INT);
|
||||
/* reset MAC to disable all RX/TX */
|
||||
atl1c_reset_mac(&adapter->hw);
|
||||
msleep(1);
|
||||
|
@ -2387,79 +2447,68 @@ static int atl1c_suspend(struct pci_dev *pdev, pm_message_t state)
|
|||
struct net_device *netdev = pci_get_drvdata(pdev);
|
||||
struct atl1c_adapter *adapter = netdev_priv(netdev);
|
||||
struct atl1c_hw *hw = &adapter->hw;
|
||||
u32 ctrl;
|
||||
u32 mac_ctrl_data;
|
||||
u32 master_ctrl_data;
|
||||
u32 mac_ctrl_data = 0;
|
||||
u32 master_ctrl_data = 0;
|
||||
u32 wol_ctrl_data = 0;
|
||||
u16 mii_bmsr_data;
|
||||
u16 save_autoneg_advertised;
|
||||
u16 mii_intr_status_data;
|
||||
u16 mii_intr_status_data = 0;
|
||||
u32 wufc = adapter->wol;
|
||||
u32 i;
|
||||
int retval = 0;
|
||||
|
||||
atl1c_disable_l0s_l1(hw);
|
||||
if (netif_running(netdev)) {
|
||||
WARN_ON(test_bit(__AT_RESETTING, &adapter->flags));
|
||||
atl1c_down(adapter);
|
||||
}
|
||||
netif_device_detach(netdev);
|
||||
atl1c_disable_l0s_l1(hw);
|
||||
retval = pci_save_state(pdev);
|
||||
if (retval)
|
||||
return retval;
|
||||
if (wufc) {
|
||||
AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl_data);
|
||||
master_ctrl_data &= ~MASTER_CTRL_CLK_SEL_DIS;
|
||||
|
||||
/* get link status */
|
||||
atl1c_read_phy_reg(hw, MII_BMSR, (u16 *)&mii_bmsr_data);
|
||||
atl1c_read_phy_reg(hw, MII_BMSR, (u16 *)&mii_bmsr_data);
|
||||
save_autoneg_advertised = hw->autoneg_advertised;
|
||||
hw->autoneg_advertised = ADVERTISED_10baseT_Half;
|
||||
if (atl1c_restart_autoneg(hw) != 0)
|
||||
if (netif_msg_link(adapter))
|
||||
dev_warn(&pdev->dev, "phy autoneg failed\n");
|
||||
hw->phy_configured = false; /* re-init PHY when resume */
|
||||
hw->autoneg_advertised = save_autoneg_advertised;
|
||||
if (wufc)
|
||||
if (atl1c_phy_power_saving(hw) != 0)
|
||||
dev_dbg(&pdev->dev, "phy power saving failed");
|
||||
|
||||
AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl_data);
|
||||
AT_READ_REG(hw, REG_MAC_CTRL, &mac_ctrl_data);
|
||||
|
||||
master_ctrl_data &= ~MASTER_CTRL_CLK_SEL_DIS;
|
||||
mac_ctrl_data &= ~(MAC_CTRL_PRMLEN_MASK << MAC_CTRL_PRMLEN_SHIFT);
|
||||
mac_ctrl_data |= (((u32)adapter->hw.preamble_len &
|
||||
MAC_CTRL_PRMLEN_MASK) <<
|
||||
MAC_CTRL_PRMLEN_SHIFT);
|
||||
mac_ctrl_data &= ~(MAC_CTRL_SPEED_MASK << MAC_CTRL_SPEED_SHIFT);
|
||||
mac_ctrl_data &= ~MAC_CTRL_DUPLX;
|
||||
|
||||
if (wufc) {
|
||||
mac_ctrl_data |= MAC_CTRL_RX_EN;
|
||||
if (adapter->link_speed == SPEED_1000 ||
|
||||
adapter->link_speed == SPEED_0) {
|
||||
mac_ctrl_data |= atl1c_mac_speed_1000 <<
|
||||
MAC_CTRL_SPEED_SHIFT;
|
||||
mac_ctrl_data |= MAC_CTRL_DUPLX;
|
||||
} else
|
||||
mac_ctrl_data |= atl1c_mac_speed_10_100 <<
|
||||
MAC_CTRL_SPEED_SHIFT;
|
||||
|
||||
if (adapter->link_duplex == DUPLEX_FULL)
|
||||
mac_ctrl_data |= MAC_CTRL_DUPLX;
|
||||
|
||||
/* turn on magic packet wol */
|
||||
if (wufc & AT_WUFC_MAG)
|
||||
wol_ctrl_data = WOL_MAGIC_EN | WOL_MAGIC_PME_EN;
|
||||
wol_ctrl_data |= WOL_MAGIC_EN | WOL_MAGIC_PME_EN;
|
||||
|
||||
if (wufc & AT_WUFC_LNKC) {
|
||||
for (i = 0; i < AT_SUSPEND_LINK_TIMEOUT; i++) {
|
||||
msleep(100);
|
||||
atl1c_read_phy_reg(hw, MII_BMSR,
|
||||
(u16 *)&mii_bmsr_data);
|
||||
if (mii_bmsr_data & BMSR_LSTATUS)
|
||||
break;
|
||||
}
|
||||
if ((mii_bmsr_data & BMSR_LSTATUS) == 0)
|
||||
if (netif_msg_link(adapter))
|
||||
dev_warn(&pdev->dev,
|
||||
"%s: Link may change"
|
||||
"when suspend\n",
|
||||
atl1c_driver_name);
|
||||
wol_ctrl_data |= WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN;
|
||||
/* only link up can wake up */
|
||||
if (atl1c_write_phy_reg(hw, MII_IER, IER_LINK_UP) != 0) {
|
||||
if (netif_msg_link(adapter))
|
||||
dev_err(&pdev->dev,
|
||||
"%s: read write phy "
|
||||
"register failed.\n",
|
||||
atl1c_driver_name);
|
||||
goto wol_dis;
|
||||
dev_dbg(&pdev->dev, "%s: read write phy "
|
||||
"register failed.\n",
|
||||
atl1c_driver_name);
|
||||
}
|
||||
}
|
||||
/* clear phy interrupt */
|
||||
atl1c_read_phy_reg(hw, MII_ISR, &mii_intr_status_data);
|
||||
/* Config MAC Ctrl register */
|
||||
mac_ctrl_data = MAC_CTRL_RX_EN;
|
||||
/* set to 10/100M halt duplex */
|
||||
mac_ctrl_data |= atl1c_mac_speed_10_100 << MAC_CTRL_SPEED_SHIFT;
|
||||
mac_ctrl_data |= (((u32)adapter->hw.preamble_len &
|
||||
MAC_CTRL_PRMLEN_MASK) <<
|
||||
MAC_CTRL_PRMLEN_SHIFT);
|
||||
|
||||
if (adapter->vlgrp)
|
||||
mac_ctrl_data |= MAC_CTRL_RMV_VLAN;
|
||||
|
||||
|
@ -2467,37 +2516,30 @@ static int atl1c_suspend(struct pci_dev *pdev, pm_message_t state)
|
|||
if (wufc & AT_WUFC_MAG)
|
||||
mac_ctrl_data |= MAC_CTRL_BC_EN;
|
||||
|
||||
if (netif_msg_hw(adapter))
|
||||
dev_dbg(&pdev->dev,
|
||||
"%s: suspend MAC=0x%x\n",
|
||||
atl1c_driver_name, mac_ctrl_data);
|
||||
dev_dbg(&pdev->dev,
|
||||
"%s: suspend MAC=0x%x\n",
|
||||
atl1c_driver_name, mac_ctrl_data);
|
||||
AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data);
|
||||
AT_WRITE_REG(hw, REG_WOL_CTRL, wol_ctrl_data);
|
||||
AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);
|
||||
|
||||
/* pcie patch */
|
||||
AT_READ_REG(hw, REG_PCIE_PHYMISC, &ctrl);
|
||||
ctrl |= PCIE_PHYMISC_FORCE_RCV_DET;
|
||||
AT_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl);
|
||||
device_set_wakeup_enable(&pdev->dev, 1);
|
||||
|
||||
pci_enable_wake(pdev, pci_choose_state(pdev, state), 1);
|
||||
goto suspend_exit;
|
||||
AT_WRITE_REG(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT |
|
||||
GPHY_CTRL_EXT_RESET);
|
||||
pci_prepare_to_sleep(pdev);
|
||||
} else {
|
||||
AT_WRITE_REG(hw, REG_GPHY_CTRL, GPHY_CTRL_POWER_SAVING);
|
||||
master_ctrl_data |= MASTER_CTRL_CLK_SEL_DIS;
|
||||
mac_ctrl_data |= atl1c_mac_speed_10_100 << MAC_CTRL_SPEED_SHIFT;
|
||||
mac_ctrl_data |= MAC_CTRL_DUPLX;
|
||||
AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data);
|
||||
AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);
|
||||
AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
|
||||
hw->phy_configured = false; /* re-init PHY when resume */
|
||||
pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
|
||||
}
|
||||
wol_dis:
|
||||
|
||||
/* WOL disabled */
|
||||
AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
|
||||
|
||||
/* pcie patch */
|
||||
AT_READ_REG(hw, REG_PCIE_PHYMISC, &ctrl);
|
||||
ctrl |= PCIE_PHYMISC_FORCE_RCV_DET;
|
||||
AT_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl);
|
||||
|
||||
atl1c_phy_disable(hw);
|
||||
hw->phy_configured = false; /* re-init PHY when resume */
|
||||
|
||||
pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
|
||||
suspend_exit:
|
||||
|
||||
pci_disable_device(pdev);
|
||||
pci_set_power_state(pdev, pci_choose_state(pdev, state));
|
||||
|
@ -2516,9 +2558,19 @@ static int atl1c_resume(struct pci_dev *pdev)
|
|||
pci_enable_wake(pdev, PCI_D3cold, 0);
|
||||
|
||||
AT_WRITE_REG(&adapter->hw, REG_WOL_CTRL, 0);
|
||||
atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE |
|
||||
ATL1C_PCIE_PHY_RESET);
|
||||
|
||||
atl1c_phy_reset(&adapter->hw);
|
||||
atl1c_reset_mac(&adapter->hw);
|
||||
atl1c_phy_init(&adapter->hw);
|
||||
|
||||
#if 0
|
||||
AT_READ_REG(&adapter->hw, REG_PM_CTRLSTAT, &pm_data);
|
||||
pm_data &= ~PM_CTRLSTAT_PME_EN;
|
||||
AT_WRITE_REG(&adapter->hw, REG_PM_CTRLSTAT, pm_data);
|
||||
#endif
|
||||
|
||||
netif_device_attach(netdev);
|
||||
if (netif_running(netdev))
|
||||
atl1c_up(adapter);
|
||||
|
|
|
@ -436,8 +436,8 @@ struct rx_free_desc {
|
|||
__le16 buf_len; /* Size of the receive buffer in host memory */
|
||||
u16 coalese; /* Update consumer index to host after the
|
||||
* reception of this frame */
|
||||
/* __attribute__ ((packed)) is required */
|
||||
} __attribute__ ((packed));
|
||||
/* __packed is required */
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* The L1 transmit packet descriptor is comprised of four 32-bit words.
|
||||
|
|
|
@ -150,9 +150,8 @@ static inline void b44_sync_dma_desc_for_device(struct ssb_device *sdev,
|
|||
unsigned long offset,
|
||||
enum dma_data_direction dir)
|
||||
{
|
||||
ssb_dma_sync_single_range_for_device(sdev, dma_base,
|
||||
offset & dma_desc_align_mask,
|
||||
dma_desc_sync_size, dir);
|
||||
dma_sync_single_for_device(sdev->dma_dev, dma_base + offset,
|
||||
dma_desc_sync_size, dir);
|
||||
}
|
||||
|
||||
static inline void b44_sync_dma_desc_for_cpu(struct ssb_device *sdev,
|
||||
|
@ -160,9 +159,8 @@ static inline void b44_sync_dma_desc_for_cpu(struct ssb_device *sdev,
|
|||
unsigned long offset,
|
||||
enum dma_data_direction dir)
|
||||
{
|
||||
ssb_dma_sync_single_range_for_cpu(sdev, dma_base,
|
||||
offset & dma_desc_align_mask,
|
||||
dma_desc_sync_size, dir);
|
||||
dma_sync_single_for_cpu(sdev->dma_dev, dma_base + offset,
|
||||
dma_desc_sync_size, dir);
|
||||
}
|
||||
|
||||
static inline unsigned long br32(const struct b44 *bp, unsigned long reg)
|
||||
|
@ -608,10 +606,10 @@ static void b44_tx(struct b44 *bp)
|
|||
|
||||
BUG_ON(skb == NULL);
|
||||
|
||||
ssb_dma_unmap_single(bp->sdev,
|
||||
rp->mapping,
|
||||
skb->len,
|
||||
DMA_TO_DEVICE);
|
||||
dma_unmap_single(bp->sdev->dma_dev,
|
||||
rp->mapping,
|
||||
skb->len,
|
||||
DMA_TO_DEVICE);
|
||||
rp->skb = NULL;
|
||||
dev_kfree_skb_irq(skb);
|
||||
}
|
||||
|
@ -648,29 +646,29 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
|
|||
if (skb == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
mapping = ssb_dma_map_single(bp->sdev, skb->data,
|
||||
RX_PKT_BUF_SZ,
|
||||
DMA_FROM_DEVICE);
|
||||
mapping = dma_map_single(bp->sdev->dma_dev, skb->data,
|
||||
RX_PKT_BUF_SZ,
|
||||
DMA_FROM_DEVICE);
|
||||
|
||||
/* Hardware bug work-around, the chip is unable to do PCI DMA
|
||||
to/from anything above 1GB :-( */
|
||||
if (ssb_dma_mapping_error(bp->sdev, mapping) ||
|
||||
if (dma_mapping_error(bp->sdev->dma_dev, mapping) ||
|
||||
mapping + RX_PKT_BUF_SZ > DMA_BIT_MASK(30)) {
|
||||
/* Sigh... */
|
||||
if (!ssb_dma_mapping_error(bp->sdev, mapping))
|
||||
ssb_dma_unmap_single(bp->sdev, mapping,
|
||||
if (!dma_mapping_error(bp->sdev->dma_dev, mapping))
|
||||
dma_unmap_single(bp->sdev->dma_dev, mapping,
|
||||
RX_PKT_BUF_SZ, DMA_FROM_DEVICE);
|
||||
dev_kfree_skb_any(skb);
|
||||
skb = __netdev_alloc_skb(bp->dev, RX_PKT_BUF_SZ, GFP_ATOMIC|GFP_DMA);
|
||||
if (skb == NULL)
|
||||
return -ENOMEM;
|
||||
mapping = ssb_dma_map_single(bp->sdev, skb->data,
|
||||
RX_PKT_BUF_SZ,
|
||||
DMA_FROM_DEVICE);
|
||||
if (ssb_dma_mapping_error(bp->sdev, mapping) ||
|
||||
mapping + RX_PKT_BUF_SZ > DMA_BIT_MASK(30)) {
|
||||
if (!ssb_dma_mapping_error(bp->sdev, mapping))
|
||||
ssb_dma_unmap_single(bp->sdev, mapping, RX_PKT_BUF_SZ,DMA_FROM_DEVICE);
|
||||
mapping = dma_map_single(bp->sdev->dma_dev, skb->data,
|
||||
RX_PKT_BUF_SZ,
|
||||
DMA_FROM_DEVICE);
|
||||
if (dma_mapping_error(bp->sdev->dma_dev, mapping) ||
|
||||
mapping + RX_PKT_BUF_SZ > DMA_BIT_MASK(30)) {
|
||||
if (!dma_mapping_error(bp->sdev->dma_dev, mapping))
|
||||
dma_unmap_single(bp->sdev->dma_dev, mapping, RX_PKT_BUF_SZ,DMA_FROM_DEVICE);
|
||||
dev_kfree_skb_any(skb);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -745,9 +743,9 @@ static void b44_recycle_rx(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
|
|||
dest_idx * sizeof(*dest_desc),
|
||||
DMA_BIDIRECTIONAL);
|
||||
|
||||
ssb_dma_sync_single_for_device(bp->sdev, dest_map->mapping,
|
||||
RX_PKT_BUF_SZ,
|
||||
DMA_FROM_DEVICE);
|
||||
dma_sync_single_for_device(bp->sdev->dma_dev, dest_map->mapping,
|
||||
RX_PKT_BUF_SZ,
|
||||
DMA_FROM_DEVICE);
|
||||
}
|
||||
|
||||
static int b44_rx(struct b44 *bp, int budget)
|
||||
|
@ -767,9 +765,9 @@ static int b44_rx(struct b44 *bp, int budget)
|
|||
struct rx_header *rh;
|
||||
u16 len;
|
||||
|
||||
ssb_dma_sync_single_for_cpu(bp->sdev, map,
|
||||
RX_PKT_BUF_SZ,
|
||||
DMA_FROM_DEVICE);
|
||||
dma_sync_single_for_cpu(bp->sdev->dma_dev, map,
|
||||
RX_PKT_BUF_SZ,
|
||||
DMA_FROM_DEVICE);
|
||||
rh = (struct rx_header *) skb->data;
|
||||
len = le16_to_cpu(rh->len);
|
||||
if ((len > (RX_PKT_BUF_SZ - RX_PKT_OFFSET)) ||
|
||||
|
@ -801,8 +799,8 @@ static int b44_rx(struct b44 *bp, int budget)
|
|||
skb_size = b44_alloc_rx_skb(bp, cons, bp->rx_prod);
|
||||
if (skb_size < 0)
|
||||
goto drop_it;
|
||||
ssb_dma_unmap_single(bp->sdev, map,
|
||||
skb_size, DMA_FROM_DEVICE);
|
||||
dma_unmap_single(bp->sdev->dma_dev, map,
|
||||
skb_size, DMA_FROM_DEVICE);
|
||||
/* Leave out rx_header */
|
||||
skb_put(skb, len + RX_PKT_OFFSET);
|
||||
skb_pull(skb, RX_PKT_OFFSET);
|
||||
|
@ -954,24 +952,24 @@ static netdev_tx_t b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
goto err_out;
|
||||
}
|
||||
|
||||
mapping = ssb_dma_map_single(bp->sdev, skb->data, len, DMA_TO_DEVICE);
|
||||
if (ssb_dma_mapping_error(bp->sdev, mapping) || mapping + len > DMA_BIT_MASK(30)) {
|
||||
mapping = dma_map_single(bp->sdev->dma_dev, skb->data, len, DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(bp->sdev->dma_dev, mapping) || mapping + len > DMA_BIT_MASK(30)) {
|
||||
struct sk_buff *bounce_skb;
|
||||
|
||||
/* Chip can't handle DMA to/from >1GB, use bounce buffer */
|
||||
if (!ssb_dma_mapping_error(bp->sdev, mapping))
|
||||
ssb_dma_unmap_single(bp->sdev, mapping, len,
|
||||
if (!dma_mapping_error(bp->sdev->dma_dev, mapping))
|
||||
dma_unmap_single(bp->sdev->dma_dev, mapping, len,
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
bounce_skb = __netdev_alloc_skb(dev, len, GFP_ATOMIC | GFP_DMA);
|
||||
if (!bounce_skb)
|
||||
goto err_out;
|
||||
|
||||
mapping = ssb_dma_map_single(bp->sdev, bounce_skb->data,
|
||||
len, DMA_TO_DEVICE);
|
||||
if (ssb_dma_mapping_error(bp->sdev, mapping) || mapping + len > DMA_BIT_MASK(30)) {
|
||||
if (!ssb_dma_mapping_error(bp->sdev, mapping))
|
||||
ssb_dma_unmap_single(bp->sdev, mapping,
|
||||
mapping = dma_map_single(bp->sdev->dma_dev, bounce_skb->data,
|
||||
len, DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(bp->sdev->dma_dev, mapping) || mapping + len > DMA_BIT_MASK(30)) {
|
||||
if (!dma_mapping_error(bp->sdev->dma_dev, mapping))
|
||||
dma_unmap_single(bp->sdev->dma_dev, mapping,
|
||||
len, DMA_TO_DEVICE);
|
||||
dev_kfree_skb_any(bounce_skb);
|
||||
goto err_out;
|
||||
|
@ -1068,8 +1066,8 @@ static void b44_free_rings(struct b44 *bp)
|
|||
|
||||
if (rp->skb == NULL)
|
||||
continue;
|
||||
ssb_dma_unmap_single(bp->sdev, rp->mapping, RX_PKT_BUF_SZ,
|
||||
DMA_FROM_DEVICE);
|
||||
dma_unmap_single(bp->sdev->dma_dev, rp->mapping, RX_PKT_BUF_SZ,
|
||||
DMA_FROM_DEVICE);
|
||||
dev_kfree_skb_any(rp->skb);
|
||||
rp->skb = NULL;
|
||||
}
|
||||
|
@ -1080,8 +1078,8 @@ static void b44_free_rings(struct b44 *bp)
|
|||
|
||||
if (rp->skb == NULL)
|
||||
continue;
|
||||
ssb_dma_unmap_single(bp->sdev, rp->mapping, rp->skb->len,
|
||||
DMA_TO_DEVICE);
|
||||
dma_unmap_single(bp->sdev->dma_dev, rp->mapping, rp->skb->len,
|
||||
DMA_TO_DEVICE);
|
||||
dev_kfree_skb_any(rp->skb);
|
||||
rp->skb = NULL;
|
||||
}
|
||||
|
@ -1103,14 +1101,12 @@ static void b44_init_rings(struct b44 *bp)
|
|||
memset(bp->tx_ring, 0, B44_TX_RING_BYTES);
|
||||
|
||||
if (bp->flags & B44_FLAG_RX_RING_HACK)
|
||||
ssb_dma_sync_single_for_device(bp->sdev, bp->rx_ring_dma,
|
||||
DMA_TABLE_BYTES,
|
||||
DMA_BIDIRECTIONAL);
|
||||
dma_sync_single_for_device(bp->sdev->dma_dev, bp->rx_ring_dma,
|
||||
DMA_TABLE_BYTES, DMA_BIDIRECTIONAL);
|
||||
|
||||
if (bp->flags & B44_FLAG_TX_RING_HACK)
|
||||
ssb_dma_sync_single_for_device(bp->sdev, bp->tx_ring_dma,
|
||||
DMA_TABLE_BYTES,
|
||||
DMA_TO_DEVICE);
|
||||
dma_sync_single_for_device(bp->sdev->dma_dev, bp->tx_ring_dma,
|
||||
DMA_TABLE_BYTES, DMA_TO_DEVICE);
|
||||
|
||||
for (i = 0; i < bp->rx_pending; i++) {
|
||||
if (b44_alloc_rx_skb(bp, -1, i) < 0)
|
||||
|
@ -1130,27 +1126,23 @@ static void b44_free_consistent(struct b44 *bp)
|
|||
bp->tx_buffers = NULL;
|
||||
if (bp->rx_ring) {
|
||||
if (bp->flags & B44_FLAG_RX_RING_HACK) {
|
||||
ssb_dma_unmap_single(bp->sdev, bp->rx_ring_dma,
|
||||
DMA_TABLE_BYTES,
|
||||
DMA_BIDIRECTIONAL);
|
||||
dma_unmap_single(bp->sdev->dma_dev, bp->rx_ring_dma,
|
||||
DMA_TABLE_BYTES, DMA_BIDIRECTIONAL);
|
||||
kfree(bp->rx_ring);
|
||||
} else
|
||||
ssb_dma_free_consistent(bp->sdev, DMA_TABLE_BYTES,
|
||||
bp->rx_ring, bp->rx_ring_dma,
|
||||
GFP_KERNEL);
|
||||
dma_free_coherent(bp->sdev->dma_dev, DMA_TABLE_BYTES,
|
||||
bp->rx_ring, bp->rx_ring_dma);
|
||||
bp->rx_ring = NULL;
|
||||
bp->flags &= ~B44_FLAG_RX_RING_HACK;
|
||||
}
|
||||
if (bp->tx_ring) {
|
||||
if (bp->flags & B44_FLAG_TX_RING_HACK) {
|
||||
ssb_dma_unmap_single(bp->sdev, bp->tx_ring_dma,
|
||||
DMA_TABLE_BYTES,
|
||||
DMA_TO_DEVICE);
|
||||
dma_unmap_single(bp->sdev->dma_dev, bp->tx_ring_dma,
|
||||
DMA_TABLE_BYTES, DMA_TO_DEVICE);
|
||||
kfree(bp->tx_ring);
|
||||
} else
|
||||
ssb_dma_free_consistent(bp->sdev, DMA_TABLE_BYTES,
|
||||
bp->tx_ring, bp->tx_ring_dma,
|
||||
GFP_KERNEL);
|
||||
dma_free_coherent(bp->sdev->dma_dev, DMA_TABLE_BYTES,
|
||||
bp->tx_ring, bp->tx_ring_dma);
|
||||
bp->tx_ring = NULL;
|
||||
bp->flags &= ~B44_FLAG_TX_RING_HACK;
|
||||
}
|
||||
|
@ -1175,7 +1167,8 @@ static int b44_alloc_consistent(struct b44 *bp, gfp_t gfp)
|
|||
goto out_err;
|
||||
|
||||
size = DMA_TABLE_BYTES;
|
||||
bp->rx_ring = ssb_dma_alloc_consistent(bp->sdev, size, &bp->rx_ring_dma, gfp);
|
||||
bp->rx_ring = dma_alloc_coherent(bp->sdev->dma_dev, size,
|
||||
&bp->rx_ring_dma, gfp);
|
||||
if (!bp->rx_ring) {
|
||||
/* Allocation may have failed due to pci_alloc_consistent
|
||||
insisting on use of GFP_DMA, which is more restrictive
|
||||
|
@ -1187,11 +1180,11 @@ static int b44_alloc_consistent(struct b44 *bp, gfp_t gfp)
|
|||
if (!rx_ring)
|
||||
goto out_err;
|
||||
|
||||
rx_ring_dma = ssb_dma_map_single(bp->sdev, rx_ring,
|
||||
DMA_TABLE_BYTES,
|
||||
DMA_BIDIRECTIONAL);
|
||||
rx_ring_dma = dma_map_single(bp->sdev->dma_dev, rx_ring,
|
||||
DMA_TABLE_BYTES,
|
||||
DMA_BIDIRECTIONAL);
|
||||
|
||||
if (ssb_dma_mapping_error(bp->sdev, rx_ring_dma) ||
|
||||
if (dma_mapping_error(bp->sdev->dma_dev, rx_ring_dma) ||
|
||||
rx_ring_dma + size > DMA_BIT_MASK(30)) {
|
||||
kfree(rx_ring);
|
||||
goto out_err;
|
||||
|
@ -1202,7 +1195,8 @@ static int b44_alloc_consistent(struct b44 *bp, gfp_t gfp)
|
|||
bp->flags |= B44_FLAG_RX_RING_HACK;
|
||||
}
|
||||
|
||||
bp->tx_ring = ssb_dma_alloc_consistent(bp->sdev, size, &bp->tx_ring_dma, gfp);
|
||||
bp->tx_ring = dma_alloc_coherent(bp->sdev->dma_dev, size,
|
||||
&bp->tx_ring_dma, gfp);
|
||||
if (!bp->tx_ring) {
|
||||
/* Allocation may have failed due to ssb_dma_alloc_consistent
|
||||
insisting on use of GFP_DMA, which is more restrictive
|
||||
|
@ -1214,11 +1208,11 @@ static int b44_alloc_consistent(struct b44 *bp, gfp_t gfp)
|
|||
if (!tx_ring)
|
||||
goto out_err;
|
||||
|
||||
tx_ring_dma = ssb_dma_map_single(bp->sdev, tx_ring,
|
||||
DMA_TABLE_BYTES,
|
||||
DMA_TO_DEVICE);
|
||||
tx_ring_dma = dma_map_single(bp->sdev->dma_dev, tx_ring,
|
||||
DMA_TABLE_BYTES,
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
if (ssb_dma_mapping_error(bp->sdev, tx_ring_dma) ||
|
||||
if (dma_mapping_error(bp->sdev->dma_dev, tx_ring_dma) ||
|
||||
tx_ring_dma + size > DMA_BIT_MASK(30)) {
|
||||
kfree(tx_ring);
|
||||
goto out_err;
|
||||
|
@ -2176,12 +2170,14 @@ static int __devinit b44_init_one(struct ssb_device *sdev,
|
|||
"Failed to powerup the bus\n");
|
||||
goto err_out_free_dev;
|
||||
}
|
||||
err = ssb_dma_set_mask(sdev, DMA_BIT_MASK(30));
|
||||
if (err) {
|
||||
|
||||
if (dma_set_mask(sdev->dma_dev, DMA_BIT_MASK(30)) ||
|
||||
dma_set_coherent_mask(sdev->dma_dev, DMA_BIT_MASK(30))) {
|
||||
dev_err(sdev->dev,
|
||||
"Required 30BIT DMA mask unsupported by the system\n");
|
||||
goto err_out_powerdown;
|
||||
}
|
||||
|
||||
err = b44_get_invariants(bp);
|
||||
if (err) {
|
||||
dev_err(sdev->dev,
|
||||
|
|
|
@ -186,7 +186,7 @@ static int be_mcc_notify_wait(struct be_adapter *adapter)
|
|||
|
||||
static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db)
|
||||
{
|
||||
int cnt = 0, wait = 5;
|
||||
int msecs = 0;
|
||||
u32 ready;
|
||||
|
||||
do {
|
||||
|
@ -201,15 +201,14 @@ static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db)
|
|||
if (ready)
|
||||
break;
|
||||
|
||||
if (cnt > 4000000) {
|
||||
if (msecs > 4000) {
|
||||
dev_err(&adapter->pdev->dev, "mbox poll timed out\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cnt > 50)
|
||||
wait = 200;
|
||||
cnt += wait;
|
||||
udelay(wait);
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule_timeout(msecs_to_jiffies(1));
|
||||
msecs++;
|
||||
} while (true);
|
||||
|
||||
return 0;
|
||||
|
@ -1593,7 +1592,7 @@ int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
|
|||
|
||||
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
|
||||
OPCODE_LOWLEVEL_LOOPBACK_TEST, sizeof(*req));
|
||||
req->hdr.timeout = 4;
|
||||
req->hdr.timeout = cpu_to_le32(4);
|
||||
|
||||
req->pattern = cpu_to_le64(pattern);
|
||||
req->src_port = cpu_to_le32(port_num);
|
||||
|
|
|
@ -1735,6 +1735,44 @@ static void be_irq_unregister(struct be_adapter *adapter)
|
|||
adapter->isr_registered = false;
|
||||
}
|
||||
|
||||
static int be_close(struct net_device *netdev)
|
||||
{
|
||||
struct be_adapter *adapter = netdev_priv(netdev);
|
||||
struct be_eq_obj *rx_eq = &adapter->rx_eq;
|
||||
struct be_eq_obj *tx_eq = &adapter->tx_eq;
|
||||
int vec;
|
||||
|
||||
cancel_delayed_work_sync(&adapter->work);
|
||||
|
||||
be_async_mcc_disable(adapter);
|
||||
|
||||
netif_stop_queue(netdev);
|
||||
netif_carrier_off(netdev);
|
||||
adapter->link_up = false;
|
||||
|
||||
be_intr_set(adapter, false);
|
||||
|
||||
if (adapter->msix_enabled) {
|
||||
vec = be_msix_vec_get(adapter, tx_eq->q.id);
|
||||
synchronize_irq(vec);
|
||||
vec = be_msix_vec_get(adapter, rx_eq->q.id);
|
||||
synchronize_irq(vec);
|
||||
} else {
|
||||
synchronize_irq(netdev->irq);
|
||||
}
|
||||
be_irq_unregister(adapter);
|
||||
|
||||
napi_disable(&rx_eq->napi);
|
||||
napi_disable(&tx_eq->napi);
|
||||
|
||||
/* Wait for all pending tx completions to arrive so that
|
||||
* all tx skbs are freed.
|
||||
*/
|
||||
be_tx_compl_clean(adapter);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int be_open(struct net_device *netdev)
|
||||
{
|
||||
struct be_adapter *adapter = netdev_priv(netdev);
|
||||
|
@ -1765,27 +1803,29 @@ static int be_open(struct net_device *netdev)
|
|||
/* Now that interrupts are on we can process async mcc */
|
||||
be_async_mcc_enable(adapter);
|
||||
|
||||
schedule_delayed_work(&adapter->work, msecs_to_jiffies(100));
|
||||
|
||||
status = be_cmd_link_status_query(adapter, &link_up, &mac_speed,
|
||||
&link_speed);
|
||||
if (status)
|
||||
goto ret_sts;
|
||||
goto err;
|
||||
be_link_status_update(adapter, link_up);
|
||||
|
||||
if (be_physfn(adapter))
|
||||
status = be_vid_config(adapter);
|
||||
if (status)
|
||||
goto ret_sts;
|
||||
|
||||
if (be_physfn(adapter)) {
|
||||
status = be_vid_config(adapter);
|
||||
if (status)
|
||||
goto err;
|
||||
|
||||
status = be_cmd_set_flow_control(adapter,
|
||||
adapter->tx_fc, adapter->rx_fc);
|
||||
if (status)
|
||||
goto ret_sts;
|
||||
goto err;
|
||||
}
|
||||
|
||||
schedule_delayed_work(&adapter->work, msecs_to_jiffies(100));
|
||||
ret_sts:
|
||||
return status;
|
||||
return 0;
|
||||
err:
|
||||
be_close(adapter->netdev);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static int be_setup_wol(struct be_adapter *adapter, bool enable)
|
||||
|
@ -1913,43 +1953,6 @@ static int be_clear(struct be_adapter *adapter)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int be_close(struct net_device *netdev)
|
||||
{
|
||||
struct be_adapter *adapter = netdev_priv(netdev);
|
||||
struct be_eq_obj *rx_eq = &adapter->rx_eq;
|
||||
struct be_eq_obj *tx_eq = &adapter->tx_eq;
|
||||
int vec;
|
||||
|
||||
cancel_delayed_work_sync(&adapter->work);
|
||||
|
||||
be_async_mcc_disable(adapter);
|
||||
|
||||
netif_stop_queue(netdev);
|
||||
netif_carrier_off(netdev);
|
||||
adapter->link_up = false;
|
||||
|
||||
be_intr_set(adapter, false);
|
||||
|
||||
if (adapter->msix_enabled) {
|
||||
vec = be_msix_vec_get(adapter, tx_eq->q.id);
|
||||
synchronize_irq(vec);
|
||||
vec = be_msix_vec_get(adapter, rx_eq->q.id);
|
||||
synchronize_irq(vec);
|
||||
} else {
|
||||
synchronize_irq(netdev->irq);
|
||||
}
|
||||
be_irq_unregister(adapter);
|
||||
|
||||
napi_disable(&rx_eq->napi);
|
||||
napi_disable(&tx_eq->napi);
|
||||
|
||||
/* Wait for all pending tx completions to arrive so that
|
||||
* all tx skbs are freed.
|
||||
*/
|
||||
be_tx_compl_clean(adapter);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define FW_FILE_HDR_SIGN "ServerEngines Corp. "
|
||||
char flash_cookie[2][16] = {"*** SE FLAS",
|
||||
|
|
|
@ -247,6 +247,7 @@ static const struct flash_spec flash_5709 = {
|
|||
MODULE_DEVICE_TABLE(pci, bnx2_pci_tbl);
|
||||
|
||||
static void bnx2_init_napi(struct bnx2 *bp);
|
||||
static void bnx2_del_napi(struct bnx2 *bp);
|
||||
|
||||
static inline u32 bnx2_tx_avail(struct bnx2 *bp, struct bnx2_tx_ring_info *txr)
|
||||
{
|
||||
|
@ -1445,7 +1446,8 @@ bnx2_test_and_disable_2g5(struct bnx2 *bp)
|
|||
static void
|
||||
bnx2_enable_forced_2g5(struct bnx2 *bp)
|
||||
{
|
||||
u32 bmcr;
|
||||
u32 uninitialized_var(bmcr);
|
||||
int err;
|
||||
|
||||
if (!(bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE))
|
||||
return;
|
||||
|
@ -1455,22 +1457,28 @@ bnx2_enable_forced_2g5(struct bnx2 *bp)
|
|||
|
||||
bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
|
||||
MII_BNX2_BLK_ADDR_SERDES_DIG);
|
||||
bnx2_read_phy(bp, MII_BNX2_SERDES_DIG_MISC1, &val);
|
||||
val &= ~MII_BNX2_SD_MISC1_FORCE_MSK;
|
||||
val |= MII_BNX2_SD_MISC1_FORCE | MII_BNX2_SD_MISC1_FORCE_2_5G;
|
||||
bnx2_write_phy(bp, MII_BNX2_SERDES_DIG_MISC1, val);
|
||||
if (!bnx2_read_phy(bp, MII_BNX2_SERDES_DIG_MISC1, &val)) {
|
||||
val &= ~MII_BNX2_SD_MISC1_FORCE_MSK;
|
||||
val |= MII_BNX2_SD_MISC1_FORCE |
|
||||
MII_BNX2_SD_MISC1_FORCE_2_5G;
|
||||
bnx2_write_phy(bp, MII_BNX2_SERDES_DIG_MISC1, val);
|
||||
}
|
||||
|
||||
bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
|
||||
MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
|
||||
bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
|
||||
err = bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
|
||||
|
||||
} else if (CHIP_NUM(bp) == CHIP_NUM_5708) {
|
||||
bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
|
||||
bmcr |= BCM5708S_BMCR_FORCE_2500;
|
||||
err = bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
|
||||
if (!err)
|
||||
bmcr |= BCM5708S_BMCR_FORCE_2500;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if (err)
|
||||
return;
|
||||
|
||||
if (bp->autoneg & AUTONEG_SPEED) {
|
||||
bmcr &= ~BMCR_ANENABLE;
|
||||
if (bp->req_duplex == DUPLEX_FULL)
|
||||
|
@ -1482,7 +1490,8 @@ bnx2_enable_forced_2g5(struct bnx2 *bp)
|
|||
static void
|
||||
bnx2_disable_forced_2g5(struct bnx2 *bp)
|
||||
{
|
||||
u32 bmcr;
|
||||
u32 uninitialized_var(bmcr);
|
||||
int err;
|
||||
|
||||
if (!(bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE))
|
||||
return;
|
||||
|
@ -1492,21 +1501,26 @@ bnx2_disable_forced_2g5(struct bnx2 *bp)
|
|||
|
||||
bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
|
||||
MII_BNX2_BLK_ADDR_SERDES_DIG);
|
||||
bnx2_read_phy(bp, MII_BNX2_SERDES_DIG_MISC1, &val);
|
||||
val &= ~MII_BNX2_SD_MISC1_FORCE;
|
||||
bnx2_write_phy(bp, MII_BNX2_SERDES_DIG_MISC1, val);
|
||||
if (!bnx2_read_phy(bp, MII_BNX2_SERDES_DIG_MISC1, &val)) {
|
||||
val &= ~MII_BNX2_SD_MISC1_FORCE;
|
||||
bnx2_write_phy(bp, MII_BNX2_SERDES_DIG_MISC1, val);
|
||||
}
|
||||
|
||||
bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
|
||||
MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
|
||||
bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
|
||||
err = bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
|
||||
|
||||
} else if (CHIP_NUM(bp) == CHIP_NUM_5708) {
|
||||
bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
|
||||
bmcr &= ~BCM5708S_BMCR_FORCE_2500;
|
||||
err = bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
|
||||
if (!err)
|
||||
bmcr &= ~BCM5708S_BMCR_FORCE_2500;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if (err)
|
||||
return;
|
||||
|
||||
if (bp->autoneg & AUTONEG_SPEED)
|
||||
bmcr |= BMCR_SPEED1000 | BMCR_ANENABLE | BMCR_ANRESTART;
|
||||
bnx2_write_phy(bp, bp->mii_bmcr, bmcr);
|
||||
|
@ -6270,6 +6284,7 @@ bnx2_open(struct net_device *dev)
|
|||
bnx2_free_skbs(bp);
|
||||
bnx2_free_irq(bp);
|
||||
bnx2_free_mem(bp);
|
||||
bnx2_del_napi(bp);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -6537,6 +6552,7 @@ bnx2_close(struct net_device *dev)
|
|||
bnx2_free_irq(bp);
|
||||
bnx2_free_skbs(bp);
|
||||
bnx2_free_mem(bp);
|
||||
bnx2_del_napi(bp);
|
||||
bp->link_up = 0;
|
||||
netif_carrier_off(bp->dev);
|
||||
bnx2_set_power_state(bp, PCI_D3hot);
|
||||
|
@ -8227,7 +8243,16 @@ bnx2_bus_string(struct bnx2 *bp, char *str)
|
|||
return str;
|
||||
}
|
||||
|
||||
static void __devinit
|
||||
static void
|
||||
bnx2_del_napi(struct bnx2 *bp)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < bp->irq_nvecs; i++)
|
||||
netif_napi_del(&bp->bnx2_napi[i].napi);
|
||||
}
|
||||
|
||||
static void
|
||||
bnx2_init_napi(struct bnx2 *bp)
|
||||
{
|
||||
int i;
|
||||
|
|
|
@ -4266,14 +4266,16 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
|
|||
MDIO_PMA_REG_10G_CTRL2, 0x0008);
|
||||
}
|
||||
|
||||
/* Set 2-wire transfer rate to 400Khz since 100Khz
|
||||
is not operational */
|
||||
/* Set 2-wire transfer rate of SFP+ module EEPROM
|
||||
* to 100Khz since some DACs(direct attached cables) do
|
||||
* not work at 400Khz.
|
||||
*/
|
||||
bnx2x_cl45_write(bp, params->port,
|
||||
ext_phy_type,
|
||||
ext_phy_addr,
|
||||
MDIO_PMA_DEVAD,
|
||||
MDIO_PMA_REG_8727_TWO_WIRE_SLAVE_ADDR,
|
||||
0xa101);
|
||||
0xa001);
|
||||
|
||||
/* Set TX PreEmphasis if needed */
|
||||
if ((params->feature_config_flags &
|
||||
|
|
|
@ -233,34 +233,27 @@ static void tlb_deinitialize(struct bonding *bond)
|
|||
_unlock_tx_hashtbl(bond);
|
||||
}
|
||||
|
||||
static long long compute_gap(struct slave *slave)
|
||||
{
|
||||
return (s64) (slave->speed << 20) - /* Convert to Megabit per sec */
|
||||
(s64) (SLAVE_TLB_INFO(slave).load << 3); /* Bytes to bits */
|
||||
}
|
||||
|
||||
/* Caller must hold bond lock for read */
|
||||
static struct slave *tlb_get_least_loaded_slave(struct bonding *bond)
|
||||
{
|
||||
struct slave *slave, *least_loaded;
|
||||
s64 max_gap;
|
||||
int i, found = 0;
|
||||
long long max_gap;
|
||||
int i;
|
||||
|
||||
/* Find the first enabled slave */
|
||||
bond_for_each_slave(bond, slave, i) {
|
||||
if (SLAVE_IS_OK(slave)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
least_loaded = slave;
|
||||
max_gap = (s64)(slave->speed << 20) - /* Convert to Megabit per sec */
|
||||
(s64)(SLAVE_TLB_INFO(slave).load << 3); /* Bytes to bits */
|
||||
least_loaded = NULL;
|
||||
max_gap = LLONG_MIN;
|
||||
|
||||
/* Find the slave with the largest gap */
|
||||
bond_for_each_slave_from(bond, slave, i, least_loaded) {
|
||||
bond_for_each_slave(bond, slave, i) {
|
||||
if (SLAVE_IS_OK(slave)) {
|
||||
s64 gap = (s64)(slave->speed << 20) -
|
||||
(s64)(SLAVE_TLB_INFO(slave).load << 3);
|
||||
long long gap = compute_gap(slave);
|
||||
|
||||
if (max_gap < gap) {
|
||||
least_loaded = slave;
|
||||
max_gap = gap;
|
||||
|
|
|
@ -90,6 +90,7 @@
|
|||
#define BOND_LINK_ARP_INTERV 0
|
||||
|
||||
static int max_bonds = BOND_DEFAULT_MAX_BONDS;
|
||||
static int tx_queues = BOND_DEFAULT_TX_QUEUES;
|
||||
static int num_grat_arp = 1;
|
||||
static int num_unsol_na = 1;
|
||||
static int miimon = BOND_LINK_MON_INTERV;
|
||||
|
@ -106,10 +107,13 @@ static int arp_interval = BOND_LINK_ARP_INTERV;
|
|||
static char *arp_ip_target[BOND_MAX_ARP_TARGETS];
|
||||
static char *arp_validate;
|
||||
static char *fail_over_mac;
|
||||
static int all_slaves_active = 0;
|
||||
static struct bond_params bonding_defaults;
|
||||
|
||||
module_param(max_bonds, int, 0);
|
||||
MODULE_PARM_DESC(max_bonds, "Max number of bonded devices");
|
||||
module_param(tx_queues, int, 0);
|
||||
MODULE_PARM_DESC(tx_queues, "Max number of transmit queues (default = 16)");
|
||||
module_param(num_grat_arp, int, 0644);
|
||||
MODULE_PARM_DESC(num_grat_arp, "Number of gratuitous ARP packets to send on failover event");
|
||||
module_param(num_unsol_na, int, 0644);
|
||||
|
@ -155,6 +159,10 @@ module_param(arp_validate, charp, 0);
|
|||
MODULE_PARM_DESC(arp_validate, "validate src/dst of ARP probes: none (default), active, backup or all");
|
||||
module_param(fail_over_mac, charp, 0);
|
||||
MODULE_PARM_DESC(fail_over_mac, "For active-backup, do not set all slaves to the same MAC. none (default), active or follow");
|
||||
module_param(all_slaves_active, int, 0);
|
||||
MODULE_PARM_DESC(all_slaves_active, "Keep all frames received on an interface"
|
||||
"by setting active flag for all slaves. "
|
||||
"0 for never (default), 1 for always.");
|
||||
|
||||
/*----------------------------- Global variables ----------------------------*/
|
||||
|
||||
|
@ -1522,16 +1530,32 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
|
|||
}
|
||||
}
|
||||
|
||||
/* If this is the first slave, then we need to set the master's hardware
|
||||
* address to be the same as the slave's. */
|
||||
if (bond->slave_cnt == 0)
|
||||
memcpy(bond->dev->dev_addr, slave_dev->dev_addr,
|
||||
slave_dev->addr_len);
|
||||
|
||||
|
||||
new_slave = kzalloc(sizeof(struct slave), GFP_KERNEL);
|
||||
if (!new_slave) {
|
||||
res = -ENOMEM;
|
||||
goto err_undo_flags;
|
||||
}
|
||||
|
||||
/* save slave's original flags before calling
|
||||
* netdev_set_master and dev_open
|
||||
/*
|
||||
* Set the new_slave's queue_id to be zero. Queue ID mapping
|
||||
* is set via sysfs or module option if desired.
|
||||
*/
|
||||
new_slave->original_flags = slave_dev->flags;
|
||||
new_slave->queue_id = 0;
|
||||
|
||||
/* Save slave's original mtu and then set it to match the bond */
|
||||
new_slave->original_mtu = slave_dev->mtu;
|
||||
res = dev_set_mtu(slave_dev, bond->dev->mtu);
|
||||
if (res) {
|
||||
pr_debug("Error %d calling dev_set_mtu\n", res);
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
/*
|
||||
* Save slave's original ("permanent") mac address for modes
|
||||
|
@ -1550,7 +1574,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
|
|||
res = dev_set_mac_address(slave_dev, &addr);
|
||||
if (res) {
|
||||
pr_debug("Error %d calling set_mac_address\n", res);
|
||||
goto err_free;
|
||||
goto err_restore_mtu;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1785,6 +1809,9 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
|
|||
dev_set_mac_address(slave_dev, &addr);
|
||||
}
|
||||
|
||||
err_restore_mtu:
|
||||
dev_set_mtu(slave_dev, new_slave->original_mtu);
|
||||
|
||||
err_free:
|
||||
kfree(new_slave);
|
||||
|
||||
|
@ -1969,6 +1996,8 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
|
|||
dev_set_mac_address(slave_dev, &addr);
|
||||
}
|
||||
|
||||
dev_set_mtu(slave_dev, slave->original_mtu);
|
||||
|
||||
slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB |
|
||||
IFF_SLAVE_INACTIVE | IFF_BONDING |
|
||||
IFF_SLAVE_NEEDARP);
|
||||
|
@ -2555,7 +2584,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
|
|||
/*
|
||||
* This target is not on a VLAN
|
||||
*/
|
||||
if (rt->u.dst.dev == bond->dev) {
|
||||
if (rt->dst.dev == bond->dev) {
|
||||
ip_rt_put(rt);
|
||||
pr_debug("basa: rtdev == bond->dev: arp_send\n");
|
||||
bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
|
||||
|
@ -2566,7 +2595,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
|
|||
vlan_id = 0;
|
||||
list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
|
||||
vlan_dev = vlan_group_get_device(bond->vlgrp, vlan->vlan_id);
|
||||
if (vlan_dev == rt->u.dst.dev) {
|
||||
if (vlan_dev == rt->dst.dev) {
|
||||
vlan_id = vlan->vlan_id;
|
||||
pr_debug("basa: vlan match on %s %d\n",
|
||||
vlan_dev->name, vlan_id);
|
||||
|
@ -2584,7 +2613,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
|
|||
if (net_ratelimit()) {
|
||||
pr_warning("%s: no path to arp_ip_target %pI4 via rt.dev %s\n",
|
||||
bond->dev->name, &fl.fl4_dst,
|
||||
rt->u.dst.dev ? rt->u.dst.dev->name : "NULL");
|
||||
rt->dst.dev ? rt->dst.dev->name : "NULL");
|
||||
}
|
||||
ip_rt_put(rt);
|
||||
}
|
||||
|
@ -3265,6 +3294,7 @@ static void bond_info_show_slave(struct seq_file *seq,
|
|||
else
|
||||
seq_puts(seq, "Aggregator ID: N/A\n");
|
||||
}
|
||||
seq_printf(seq, "Slave queue ID: %d\n", slave->queue_id);
|
||||
}
|
||||
|
||||
static int bond_info_seq_show(struct seq_file *seq, void *v)
|
||||
|
@ -3774,20 +3804,21 @@ static int bond_close(struct net_device *bond_dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct net_device_stats *bond_get_stats(struct net_device *bond_dev)
|
||||
static struct rtnl_link_stats64 *bond_get_stats(struct net_device *bond_dev)
|
||||
{
|
||||
struct bonding *bond = netdev_priv(bond_dev);
|
||||
struct net_device_stats *stats = &bond_dev->stats;
|
||||
struct net_device_stats local_stats;
|
||||
struct rtnl_link_stats64 *stats = &bond_dev->stats64;
|
||||
struct rtnl_link_stats64 local_stats;
|
||||
struct slave *slave;
|
||||
int i;
|
||||
|
||||
memset(&local_stats, 0, sizeof(struct net_device_stats));
|
||||
memset(&local_stats, 0, sizeof(local_stats));
|
||||
|
||||
read_lock_bh(&bond->lock);
|
||||
|
||||
bond_for_each_slave(bond, slave, i) {
|
||||
const struct net_device_stats *sstats = dev_get_stats(slave->dev);
|
||||
const struct rtnl_link_stats64 *sstats =
|
||||
dev_get_stats(slave->dev);
|
||||
|
||||
local_stats.rx_packets += sstats->rx_packets;
|
||||
local_stats.rx_bytes += sstats->rx_bytes;
|
||||
|
@ -4401,9 +4432,59 @@ static void bond_set_xmit_hash_policy(struct bonding *bond)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Lookup the slave that corresponds to a qid
|
||||
*/
|
||||
static inline int bond_slave_override(struct bonding *bond,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
int i, res = 1;
|
||||
struct slave *slave = NULL;
|
||||
struct slave *check_slave;
|
||||
|
||||
read_lock(&bond->lock);
|
||||
|
||||
if (!BOND_IS_OK(bond) || !skb->queue_mapping)
|
||||
goto out;
|
||||
|
||||
/* Find out if any slaves have the same mapping as this skb. */
|
||||
bond_for_each_slave(bond, check_slave, i) {
|
||||
if (check_slave->queue_id == skb->queue_mapping) {
|
||||
slave = check_slave;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the slave isn't UP, use default transmit policy. */
|
||||
if (slave && slave->queue_id && IS_UP(slave->dev) &&
|
||||
(slave->link == BOND_LINK_UP)) {
|
||||
res = bond_dev_queue_xmit(bond, skb, slave->dev);
|
||||
}
|
||||
|
||||
out:
|
||||
read_unlock(&bond->lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb)
|
||||
{
|
||||
/*
|
||||
* This helper function exists to help dev_pick_tx get the correct
|
||||
* destination queue. Using a helper function skips the a call to
|
||||
* skb_tx_hash and will put the skbs in the queue we expect on their
|
||||
* way down to the bonding driver.
|
||||
*/
|
||||
return skb->queue_mapping;
|
||||
}
|
||||
|
||||
static netdev_tx_t bond_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
const struct bonding *bond = netdev_priv(dev);
|
||||
struct bonding *bond = netdev_priv(dev);
|
||||
|
||||
if (TX_QUEUE_OVERRIDE(bond->params.mode)) {
|
||||
if (!bond_slave_override(bond, skb))
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
switch (bond->params.mode) {
|
||||
case BOND_MODE_ROUNDROBIN:
|
||||
|
@ -4488,7 +4569,8 @@ static const struct net_device_ops bond_netdev_ops = {
|
|||
.ndo_open = bond_open,
|
||||
.ndo_stop = bond_close,
|
||||
.ndo_start_xmit = bond_start_xmit,
|
||||
.ndo_get_stats = bond_get_stats,
|
||||
.ndo_select_queue = bond_select_queue,
|
||||
.ndo_get_stats64 = bond_get_stats,
|
||||
.ndo_do_ioctl = bond_do_ioctl,
|
||||
.ndo_set_multicast_list = bond_set_multicast_list,
|
||||
.ndo_change_mtu = bond_change_mtu,
|
||||
|
@ -4756,6 +4838,20 @@ static int bond_check_params(struct bond_params *params)
|
|||
}
|
||||
}
|
||||
|
||||
if (tx_queues < 1 || tx_queues > 255) {
|
||||
pr_warning("Warning: tx_queues (%d) should be between "
|
||||
"1 and 255, resetting to %d\n",
|
||||
tx_queues, BOND_DEFAULT_TX_QUEUES);
|
||||
tx_queues = BOND_DEFAULT_TX_QUEUES;
|
||||
}
|
||||
|
||||
if ((all_slaves_active != 0) && (all_slaves_active != 1)) {
|
||||
pr_warning("Warning: all_slaves_active module parameter (%d), "
|
||||
"not of valid value (0/1), so it was set to "
|
||||
"0\n", all_slaves_active);
|
||||
all_slaves_active = 0;
|
||||
}
|
||||
|
||||
/* reset values for TLB/ALB */
|
||||
if ((bond_mode == BOND_MODE_TLB) ||
|
||||
(bond_mode == BOND_MODE_ALB)) {
|
||||
|
@ -4926,6 +5022,8 @@ static int bond_check_params(struct bond_params *params)
|
|||
params->primary[0] = 0;
|
||||
params->primary_reselect = primary_reselect_value;
|
||||
params->fail_over_mac = fail_over_mac_value;
|
||||
params->tx_queues = tx_queues;
|
||||
params->all_slaves_active = all_slaves_active;
|
||||
|
||||
if (primary) {
|
||||
strncpy(params->primary, primary, IFNAMSIZ);
|
||||
|
@ -5012,8 +5110,8 @@ int bond_create(struct net *net, const char *name)
|
|||
|
||||
rtnl_lock();
|
||||
|
||||
bond_dev = alloc_netdev(sizeof(struct bonding), name ? name : "",
|
||||
bond_setup);
|
||||
bond_dev = alloc_netdev_mq(sizeof(struct bonding), name ? name : "",
|
||||
bond_setup, tx_queues);
|
||||
if (!bond_dev) {
|
||||
pr_err("%s: eek! can't alloc netdev!\n", name);
|
||||
rtnl_unlock();
|
||||
|
|
|
@ -211,7 +211,8 @@ static ssize_t bonding_show_slaves(struct device *d,
|
|||
/*
|
||||
* Set the slaves in the current bond. The bond interface must be
|
||||
* up for this to succeed.
|
||||
* This function is largely the same flow as bonding_update_bonds().
|
||||
* This is supposed to be only thin wrapper for bond_enslave and bond_release.
|
||||
* All hard work should be done there.
|
||||
*/
|
||||
static ssize_t bonding_store_slaves(struct device *d,
|
||||
struct device_attribute *attr,
|
||||
|
@ -219,10 +220,8 @@ static ssize_t bonding_store_slaves(struct device *d,
|
|||
{
|
||||
char command[IFNAMSIZ + 1] = { 0, };
|
||||
char *ifname;
|
||||
int i, res, found, ret = count;
|
||||
u32 original_mtu;
|
||||
struct slave *slave;
|
||||
struct net_device *dev = NULL;
|
||||
int res, ret = count;
|
||||
struct net_device *dev;
|
||||
struct bonding *bond = to_bond(d);
|
||||
|
||||
/* Quick sanity check -- is the bond interface up? */
|
||||
|
@ -231,8 +230,6 @@ static ssize_t bonding_store_slaves(struct device *d,
|
|||
bond->dev->name);
|
||||
}
|
||||
|
||||
/* Note: We can't hold bond->lock here, as bond_create grabs it. */
|
||||
|
||||
if (!rtnl_trylock())
|
||||
return restart_syscall();
|
||||
|
||||
|
@ -242,90 +239,32 @@ static ssize_t bonding_store_slaves(struct device *d,
|
|||
!dev_valid_name(ifname))
|
||||
goto err_no_cmd;
|
||||
|
||||
if (command[0] == '+') {
|
||||
|
||||
/* Got a slave name in ifname. Is it already in the list? */
|
||||
found = 0;
|
||||
|
||||
dev = __dev_get_by_name(dev_net(bond->dev), ifname);
|
||||
if (!dev) {
|
||||
pr_info("%s: Interface %s does not exist!\n",
|
||||
bond->dev->name, ifname);
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (dev->flags & IFF_UP) {
|
||||
pr_err("%s: Error: Unable to enslave %s because it is already up.\n",
|
||||
bond->dev->name, dev->name);
|
||||
ret = -EPERM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
read_lock(&bond->lock);
|
||||
bond_for_each_slave(bond, slave, i)
|
||||
if (slave->dev == dev) {
|
||||
pr_err("%s: Interface %s is already enslaved!\n",
|
||||
bond->dev->name, ifname);
|
||||
ret = -EPERM;
|
||||
read_unlock(&bond->lock);
|
||||
goto out;
|
||||
}
|
||||
read_unlock(&bond->lock);
|
||||
|
||||
pr_info("%s: Adding slave %s.\n", bond->dev->name, ifname);
|
||||
|
||||
/* If this is the first slave, then we need to set
|
||||
the master's hardware address to be the same as the
|
||||
slave's. */
|
||||
if (is_zero_ether_addr(bond->dev->dev_addr))
|
||||
memcpy(bond->dev->dev_addr, dev->dev_addr,
|
||||
dev->addr_len);
|
||||
|
||||
/* Set the slave's MTU to match the bond */
|
||||
original_mtu = dev->mtu;
|
||||
res = dev_set_mtu(dev, bond->dev->mtu);
|
||||
if (res) {
|
||||
ret = res;
|
||||
goto out;
|
||||
}
|
||||
dev = __dev_get_by_name(dev_net(bond->dev), ifname);
|
||||
if (!dev) {
|
||||
pr_info("%s: Interface %s does not exist!\n",
|
||||
bond->dev->name, ifname);
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (command[0]) {
|
||||
case '+':
|
||||
pr_info("%s: Adding slave %s.\n", bond->dev->name, dev->name);
|
||||
res = bond_enslave(bond->dev, dev);
|
||||
bond_for_each_slave(bond, slave, i)
|
||||
if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0)
|
||||
slave->original_mtu = original_mtu;
|
||||
if (res)
|
||||
ret = res;
|
||||
break;
|
||||
|
||||
goto out;
|
||||
case '-':
|
||||
pr_info("%s: Removing slave %s.\n", bond->dev->name, dev->name);
|
||||
res = bond_release(bond->dev, dev);
|
||||
break;
|
||||
|
||||
default:
|
||||
goto err_no_cmd;
|
||||
}
|
||||
|
||||
if (command[0] == '-') {
|
||||
dev = NULL;
|
||||
original_mtu = 0;
|
||||
bond_for_each_slave(bond, slave, i)
|
||||
if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0) {
|
||||
dev = slave->dev;
|
||||
original_mtu = slave->original_mtu;
|
||||
break;
|
||||
}
|
||||
if (dev) {
|
||||
pr_info("%s: Removing slave %s\n",
|
||||
bond->dev->name, dev->name);
|
||||
res = bond_release(bond->dev, dev);
|
||||
if (res) {
|
||||
ret = res;
|
||||
goto out;
|
||||
}
|
||||
/* set the slave MTU to the default */
|
||||
dev_set_mtu(dev, original_mtu);
|
||||
} else {
|
||||
pr_err("unable to remove non-existent slave %s for bond %s.\n",
|
||||
ifname, bond->dev->name);
|
||||
ret = -ENODEV;
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
if (res)
|
||||
ret = res;
|
||||
goto out;
|
||||
|
||||
err_no_cmd:
|
||||
pr_err("no command found in slaves file for bond %s. Use +ifname or -ifname.\n",
|
||||
|
@ -1472,7 +1411,173 @@ static ssize_t bonding_show_ad_partner_mac(struct device *d,
|
|||
}
|
||||
static DEVICE_ATTR(ad_partner_mac, S_IRUGO, bonding_show_ad_partner_mac, NULL);
|
||||
|
||||
/*
|
||||
* Show the queue_ids of the slaves in the current bond.
|
||||
*/
|
||||
static ssize_t bonding_show_queue_id(struct device *d,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct slave *slave;
|
||||
int i, res = 0;
|
||||
struct bonding *bond = to_bond(d);
|
||||
|
||||
if (!rtnl_trylock())
|
||||
return restart_syscall();
|
||||
|
||||
read_lock(&bond->lock);
|
||||
bond_for_each_slave(bond, slave, i) {
|
||||
if (res > (PAGE_SIZE - 6)) {
|
||||
/* not enough space for another interface name */
|
||||
if ((PAGE_SIZE - res) > 10)
|
||||
res = PAGE_SIZE - 10;
|
||||
res += sprintf(buf + res, "++more++ ");
|
||||
break;
|
||||
}
|
||||
res += sprintf(buf + res, "%s:%d ",
|
||||
slave->dev->name, slave->queue_id);
|
||||
}
|
||||
read_unlock(&bond->lock);
|
||||
if (res)
|
||||
buf[res-1] = '\n'; /* eat the leftover space */
|
||||
rtnl_unlock();
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the queue_ids of the slaves in the current bond. The bond
|
||||
* interface must be enslaved for this to work.
|
||||
*/
|
||||
static ssize_t bonding_store_queue_id(struct device *d,
|
||||
struct device_attribute *attr,
|
||||
const char *buffer, size_t count)
|
||||
{
|
||||
struct slave *slave, *update_slave;
|
||||
struct bonding *bond = to_bond(d);
|
||||
u16 qid;
|
||||
int i, ret = count;
|
||||
char *delim;
|
||||
struct net_device *sdev = NULL;
|
||||
|
||||
if (!rtnl_trylock())
|
||||
return restart_syscall();
|
||||
|
||||
/* delim will point to queue id if successful */
|
||||
delim = strchr(buffer, ':');
|
||||
if (!delim)
|
||||
goto err_no_cmd;
|
||||
|
||||
/*
|
||||
* Terminate string that points to device name and bump it
|
||||
* up one, so we can read the queue id there.
|
||||
*/
|
||||
*delim = '\0';
|
||||
if (sscanf(++delim, "%hd\n", &qid) != 1)
|
||||
goto err_no_cmd;
|
||||
|
||||
/* Check buffer length, valid ifname and queue id */
|
||||
if (strlen(buffer) > IFNAMSIZ ||
|
||||
!dev_valid_name(buffer) ||
|
||||
qid > bond->params.tx_queues)
|
||||
goto err_no_cmd;
|
||||
|
||||
/* Get the pointer to that interface if it exists */
|
||||
sdev = __dev_get_by_name(dev_net(bond->dev), buffer);
|
||||
if (!sdev)
|
||||
goto err_no_cmd;
|
||||
|
||||
read_lock(&bond->lock);
|
||||
|
||||
/* Search for thes slave and check for duplicate qids */
|
||||
update_slave = NULL;
|
||||
bond_for_each_slave(bond, slave, i) {
|
||||
if (sdev == slave->dev)
|
||||
/*
|
||||
* We don't need to check the matching
|
||||
* slave for dups, since we're overwriting it
|
||||
*/
|
||||
update_slave = slave;
|
||||
else if (qid && qid == slave->queue_id) {
|
||||
goto err_no_cmd_unlock;
|
||||
}
|
||||
}
|
||||
|
||||
if (!update_slave)
|
||||
goto err_no_cmd_unlock;
|
||||
|
||||
/* Actually set the qids for the slave */
|
||||
update_slave->queue_id = qid;
|
||||
|
||||
read_unlock(&bond->lock);
|
||||
out:
|
||||
rtnl_unlock();
|
||||
return ret;
|
||||
|
||||
err_no_cmd_unlock:
|
||||
read_unlock(&bond->lock);
|
||||
err_no_cmd:
|
||||
pr_info("invalid input for queue_id set for %s.\n",
|
||||
bond->dev->name);
|
||||
ret = -EPERM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(queue_id, S_IRUGO | S_IWUSR, bonding_show_queue_id,
|
||||
bonding_store_queue_id);
|
||||
|
||||
|
||||
/*
|
||||
* Show and set the all_slaves_active flag.
|
||||
*/
|
||||
static ssize_t bonding_show_slaves_active(struct device *d,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct bonding *bond = to_bond(d);
|
||||
|
||||
return sprintf(buf, "%d\n", bond->params.all_slaves_active);
|
||||
}
|
||||
|
||||
static ssize_t bonding_store_slaves_active(struct device *d,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int i, new_value, ret = count;
|
||||
struct bonding *bond = to_bond(d);
|
||||
struct slave *slave;
|
||||
|
||||
if (sscanf(buf, "%d", &new_value) != 1) {
|
||||
pr_err("%s: no all_slaves_active value specified.\n",
|
||||
bond->dev->name);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (new_value == bond->params.all_slaves_active)
|
||||
goto out;
|
||||
|
||||
if ((new_value == 0) || (new_value == 1)) {
|
||||
bond->params.all_slaves_active = new_value;
|
||||
} else {
|
||||
pr_info("%s: Ignoring invalid all_slaves_active value %d.\n",
|
||||
bond->dev->name, new_value);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
bond_for_each_slave(bond, slave, i) {
|
||||
if (slave->state == BOND_STATE_BACKUP) {
|
||||
if (new_value)
|
||||
slave->dev->priv_flags &= ~IFF_SLAVE_INACTIVE;
|
||||
else
|
||||
slave->dev->priv_flags |= IFF_SLAVE_INACTIVE;
|
||||
}
|
||||
}
|
||||
out:
|
||||
return count;
|
||||
}
|
||||
static DEVICE_ATTR(all_slaves_active, S_IRUGO | S_IWUSR,
|
||||
bonding_show_slaves_active, bonding_store_slaves_active);
|
||||
|
||||
static struct attribute *per_bond_attrs[] = {
|
||||
&dev_attr_slaves.attr,
|
||||
|
@ -1499,6 +1604,8 @@ static struct attribute *per_bond_attrs[] = {
|
|||
&dev_attr_ad_actor_key.attr,
|
||||
&dev_attr_ad_partner_key.attr,
|
||||
&dev_attr_ad_partner_mac.attr,
|
||||
&dev_attr_queue_id.attr,
|
||||
&dev_attr_all_slaves_active.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
|
|
@ -23,8 +23,8 @@
|
|||
#include "bond_3ad.h"
|
||||
#include "bond_alb.h"
|
||||
|
||||
#define DRV_VERSION "3.6.0"
|
||||
#define DRV_RELDATE "September 26, 2009"
|
||||
#define DRV_VERSION "3.7.0"
|
||||
#define DRV_RELDATE "June 2, 2010"
|
||||
#define DRV_NAME "bonding"
|
||||
#define DRV_DESCRIPTION "Ethernet Channel Bonding Driver"
|
||||
|
||||
|
@ -60,6 +60,9 @@
|
|||
((mode) == BOND_MODE_TLB) || \
|
||||
((mode) == BOND_MODE_ALB))
|
||||
|
||||
#define TX_QUEUE_OVERRIDE(mode) \
|
||||
(((mode) == BOND_MODE_ACTIVEBACKUP) || \
|
||||
((mode) == BOND_MODE_ROUNDROBIN))
|
||||
/*
|
||||
* 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.
|
||||
|
@ -131,6 +134,8 @@ struct bond_params {
|
|||
char primary[IFNAMSIZ];
|
||||
int primary_reselect;
|
||||
__be32 arp_targets[BOND_MAX_ARP_TARGETS];
|
||||
int tx_queues;
|
||||
int all_slaves_active;
|
||||
};
|
||||
|
||||
struct bond_parm_tbl {
|
||||
|
@ -159,12 +164,12 @@ struct slave {
|
|||
s8 link; /* one of BOND_LINK_XXXX */
|
||||
s8 new_link;
|
||||
s8 state; /* one of BOND_STATE_XXXX */
|
||||
u32 original_flags;
|
||||
u32 original_mtu;
|
||||
u32 link_failure_count;
|
||||
u8 perm_hwaddr[ETH_ALEN];
|
||||
u16 speed;
|
||||
u8 duplex;
|
||||
u16 queue_id;
|
||||
struct ad_slave_info ad_info; /* HUGE - better to dynamically alloc */
|
||||
struct tlb_slave_info tlb_info;
|
||||
};
|
||||
|
@ -291,7 +296,8 @@ static inline void bond_set_slave_inactive_flags(struct slave *slave)
|
|||
struct bonding *bond = netdev_priv(slave->dev->master);
|
||||
if (!bond_is_lb(bond))
|
||||
slave->state = BOND_STATE_BACKUP;
|
||||
slave->dev->priv_flags |= IFF_SLAVE_INACTIVE;
|
||||
if (!bond->params.all_slaves_active)
|
||||
slave->dev->priv_flags |= IFF_SLAVE_INACTIVE;
|
||||
if (slave_do_arp_validate(bond, slave))
|
||||
slave->dev->priv_flags |= IFF_SLAVE_NEEDARP;
|
||||
}
|
||||
|
|
|
@ -174,6 +174,7 @@ static void ldisc_receive(struct tty_struct *tty, const u8 *data,
|
|||
struct ser_device *ser;
|
||||
int ret;
|
||||
u8 *p;
|
||||
|
||||
ser = tty->disc_data;
|
||||
|
||||
/*
|
||||
|
@ -221,6 +222,7 @@ static int handle_tx(struct ser_device *ser)
|
|||
struct tty_struct *tty;
|
||||
struct sk_buff *skb;
|
||||
int tty_wr, len, room;
|
||||
|
||||
tty = ser->tty;
|
||||
ser->tx_started = true;
|
||||
|
||||
|
@ -281,6 +283,7 @@ static int handle_tx(struct ser_device *ser)
|
|||
static int caif_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct ser_device *ser;
|
||||
|
||||
BUG_ON(dev == NULL);
|
||||
ser = netdev_priv(dev);
|
||||
|
||||
|
@ -299,6 +302,7 @@ static int caif_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
static void ldisc_tx_wakeup(struct tty_struct *tty)
|
||||
{
|
||||
struct ser_device *ser;
|
||||
|
||||
ser = tty->disc_data;
|
||||
BUG_ON(ser == NULL);
|
||||
BUG_ON(ser->tty != tty);
|
||||
|
@ -348,6 +352,7 @@ static void ldisc_close(struct tty_struct *tty)
|
|||
struct ser_device *ser = tty->disc_data;
|
||||
/* Remove may be called inside or outside of rtnl_lock */
|
||||
int islocked = rtnl_is_locked();
|
||||
|
||||
if (!islocked)
|
||||
rtnl_lock();
|
||||
/* device is freed automagically by net-sysfs */
|
||||
|
@ -374,6 +379,7 @@ static struct tty_ldisc_ops caif_ldisc = {
|
|||
static int register_ldisc(void)
|
||||
{
|
||||
int result;
|
||||
|
||||
result = tty_register_ldisc(N_CAIF, &caif_ldisc);
|
||||
if (result < 0) {
|
||||
pr_err("cannot register CAIF ldisc=%d err=%d\n", N_CAIF,
|
||||
|
@ -391,6 +397,7 @@ static const struct net_device_ops netdev_ops = {
|
|||
static void caifdev_setup(struct net_device *dev)
|
||||
{
|
||||
struct ser_device *serdev = netdev_priv(dev);
|
||||
|
||||
dev->features = 0;
|
||||
dev->netdev_ops = &netdev_ops;
|
||||
dev->type = ARPHRD_CAIF;
|
||||
|
@ -410,8 +417,6 @@ static void caifdev_setup(struct net_device *dev)
|
|||
|
||||
static int caif_net_open(struct net_device *dev)
|
||||
{
|
||||
struct ser_device *ser;
|
||||
ser = netdev_priv(dev);
|
||||
netif_wake_queue(dev);
|
||||
return 0;
|
||||
}
|
||||
|
@ -425,6 +430,7 @@ static int caif_net_close(struct net_device *dev)
|
|||
static int __init caif_ser_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = register_ldisc();
|
||||
debugfsdir = debugfs_create_dir("caif_serial", NULL);
|
||||
return ret;
|
||||
|
@ -435,6 +441,7 @@ static void __exit caif_ser_exit(void)
|
|||
struct ser_device *ser = NULL;
|
||||
struct list_head *node;
|
||||
struct list_head *_tmp;
|
||||
|
||||
list_for_each_safe(node, _tmp, &ser_list) {
|
||||
ser = list_entry(node, struct ser_device, node);
|
||||
dev_close(ser->dev);
|
||||
|
|
|
@ -73,7 +73,7 @@ static u32 __devinit mpc52xx_can_get_clock(struct of_device *ofdev,
|
|||
else
|
||||
*mscan_clksrc = MSCAN_CLKSRC_XTAL;
|
||||
|
||||
freq = mpc5xxx_get_bus_frequency(ofdev->node);
|
||||
freq = mpc5xxx_get_bus_frequency(ofdev->dev.of_node);
|
||||
if (!freq)
|
||||
return 0;
|
||||
|
||||
|
@ -152,7 +152,7 @@ static u32 __devinit mpc512x_can_get_clock(struct of_device *ofdev,
|
|||
}
|
||||
|
||||
/* Determine the MSCAN device index from the physical address */
|
||||
pval = of_get_property(ofdev->node, "reg", &plen);
|
||||
pval = of_get_property(ofdev->dev.of_node, "reg", &plen);
|
||||
BUG_ON(!pval || plen < sizeof(*pval));
|
||||
clockidx = (*pval & 0x80) ? 1 : 0;
|
||||
if (*pval & 0x2000)
|
||||
|
@ -168,11 +168,11 @@ static u32 __devinit mpc512x_can_get_clock(struct of_device *ofdev,
|
|||
*/
|
||||
if (clock_name && !strcmp(clock_name, "ip")) {
|
||||
*mscan_clksrc = MSCAN_CLKSRC_IPS;
|
||||
freq = mpc5xxx_get_bus_frequency(ofdev->node);
|
||||
freq = mpc5xxx_get_bus_frequency(ofdev->dev.of_node);
|
||||
} else {
|
||||
*mscan_clksrc = MSCAN_CLKSRC_BUS;
|
||||
|
||||
pval = of_get_property(ofdev->node,
|
||||
pval = of_get_property(ofdev->dev.of_node,
|
||||
"fsl,mscan-clock-divider", &plen);
|
||||
if (pval && plen == sizeof(*pval))
|
||||
clockdiv = *pval;
|
||||
|
@ -251,7 +251,7 @@ static int __devinit mpc5xxx_can_probe(struct of_device *ofdev,
|
|||
const struct of_device_id *id)
|
||||
{
|
||||
struct mpc5xxx_can_data *data = (struct mpc5xxx_can_data *)id->data;
|
||||
struct device_node *np = ofdev->node;
|
||||
struct device_node *np = ofdev->dev.of_node;
|
||||
struct net_device *dev;
|
||||
struct mscan_priv *priv;
|
||||
void __iomem *base;
|
||||
|
|
|
@ -227,7 +227,7 @@ struct mscan_regs {
|
|||
u16 time; /* + 0x7c 0x3e */
|
||||
} tx;
|
||||
_MSCAN_RESERVED_(32, 2); /* + 0x7e */
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#undef _MSCAN_RESERVED_
|
||||
#define MSCAN_REGION sizeof(struct mscan)
|
||||
|
|
|
@ -197,7 +197,7 @@ struct cpc_can_err_counter {
|
|||
};
|
||||
|
||||
/* Main message type used between library and application */
|
||||
struct __attribute__ ((packed)) ems_cpc_msg {
|
||||
struct __packed ems_cpc_msg {
|
||||
u8 type; /* type of message */
|
||||
u8 length; /* length of data within union 'msg' */
|
||||
u8 msgid; /* confirmation handle */
|
||||
|
|
|
@ -286,7 +286,6 @@ struct board_info {
|
|||
unsigned int clock_mc3;
|
||||
unsigned int clock_mc4;
|
||||
unsigned int espi_nports;
|
||||
unsigned int clock_cspi;
|
||||
unsigned int clock_elmer0;
|
||||
unsigned char mdio_mdien;
|
||||
unsigned char mdio_mdiinv;
|
||||
|
|
|
@ -185,9 +185,6 @@ static int t1_pci_intr_handler(adapter_t *adapter)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CHELSIO_T1_COUGAR
|
||||
#include "cspi.h"
|
||||
#endif
|
||||
#ifdef CONFIG_CHELSIO_T1_1G
|
||||
#include "fpga_defs.h"
|
||||
|
||||
|
@ -280,7 +277,7 @@ static void mi1_mdio_init(adapter_t *adapter, const struct board_info *bi)
|
|||
t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_CFG, val);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_CHELSIO_T1_1G) || defined(CONFIG_CHELSIO_T1_COUGAR)
|
||||
#if defined(CONFIG_CHELSIO_T1_1G)
|
||||
/*
|
||||
* Elmer MI1 MDIO read/write operations.
|
||||
*/
|
||||
|
@ -317,7 +314,7 @@ static int mi1_mdio_write(struct net_device *dev, int phy_addr, int mmd_addr,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_CHELSIO_T1_1G) || defined(CONFIG_CHELSIO_T1_COUGAR)
|
||||
#if defined(CONFIG_CHELSIO_T1_1G)
|
||||
static const struct mdio_ops mi1_mdio_ops = {
|
||||
.init = mi1_mdio_init,
|
||||
.read = mi1_mdio_read,
|
||||
|
@ -752,31 +749,6 @@ int t1_elmer0_ext_intr_handler(adapter_t *adapter)
|
|||
mod_detect ? "removed" : "inserted");
|
||||
}
|
||||
break;
|
||||
#ifdef CONFIG_CHELSIO_T1_COUGAR
|
||||
case CHBT_BOARD_COUGAR:
|
||||
if (adapter->params.nports == 1) {
|
||||
if (cause & ELMER0_GP_BIT1) { /* Vitesse MAC */
|
||||
struct cmac *mac = adapter->port[0].mac;
|
||||
mac->ops->interrupt_handler(mac);
|
||||
}
|
||||
if (cause & ELMER0_GP_BIT5) { /* XPAK MOD_DETECT */
|
||||
}
|
||||
} else {
|
||||
int i, port_bit;
|
||||
|
||||
for_each_port(adapter, i) {
|
||||
port_bit = i ? i + 1 : 0;
|
||||
if (!(cause & (1 << port_bit)))
|
||||
continue;
|
||||
|
||||
phy = adapter->port[i].phy;
|
||||
phy_cause = phy->ops->interrupt_handler(phy);
|
||||
if (phy_cause & cphy_cause_link_change)
|
||||
t1_link_changed(adapter, i);
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
t1_tpi_write(adapter, A_ELMER0_INT_CAUSE, cause);
|
||||
return 0;
|
||||
|
@ -955,7 +927,6 @@ static int board_init(adapter_t *adapter, const struct board_info *bi)
|
|||
case CHBT_BOARD_N110:
|
||||
case CHBT_BOARD_N210:
|
||||
case CHBT_BOARD_CHT210:
|
||||
case CHBT_BOARD_COUGAR:
|
||||
t1_tpi_par(adapter, 0xf);
|
||||
t1_tpi_write(adapter, A_ELMER0_GPO, 0x800);
|
||||
break;
|
||||
|
@ -1004,10 +975,6 @@ int t1_init_hw_modules(adapter_t *adapter)
|
|||
adapter->regs + A_MC5_CONFIG);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CHELSIO_T1_COUGAR
|
||||
if (adapter->cspi && t1_cspi_init(adapter->cspi))
|
||||
goto out_err;
|
||||
#endif
|
||||
if (adapter->espi && t1_espi_init(adapter->espi, bi->chip_mac,
|
||||
bi->espi_nports))
|
||||
goto out_err;
|
||||
|
@ -1061,10 +1028,6 @@ void t1_free_sw_modules(adapter_t *adapter)
|
|||
t1_tp_destroy(adapter->tp);
|
||||
if (adapter->espi)
|
||||
t1_espi_destroy(adapter->espi);
|
||||
#ifdef CONFIG_CHELSIO_T1_COUGAR
|
||||
if (adapter->cspi)
|
||||
t1_cspi_destroy(adapter->cspi);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __devinit init_link_config(struct link_config *lc,
|
||||
|
@ -1084,14 +1047,6 @@ static void __devinit init_link_config(struct link_config *lc,
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CHELSIO_T1_COUGAR
|
||||
if (bi->clock_cspi && !(adapter->cspi = t1_cspi_create(adapter))) {
|
||||
pr_err("%s: CSPI initialization failed\n",
|
||||
adapter->name);
|
||||
goto error;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Allocate and initialize the data structures that hold the SW state of
|
||||
* the Terminator HW modules.
|
||||
|
|
|
@ -2824,7 +2824,7 @@ static int cnic_get_v4_route(struct sockaddr_in *dst_addr,
|
|||
|
||||
err = ip_route_output_key(&init_net, &rt, &fl);
|
||||
if (!err)
|
||||
*dst = &rt->u.dst;
|
||||
*dst = &rt->dst;
|
||||
return err;
|
||||
#else
|
||||
return -ENETUNREACH;
|
||||
|
|
|
@ -961,7 +961,7 @@ struct dm9000_rxhdr {
|
|||
u8 RxPktReady;
|
||||
u8 RxStatus;
|
||||
__le16 RxLen;
|
||||
} __attribute__((__packed__));
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* Received a packet and pass to upper layer
|
||||
|
|
|
@ -1047,15 +1047,14 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
|
|||
goto err_register;
|
||||
|
||||
/* print bus type/speed/width info */
|
||||
e_info("(PCI%s:%s:%s) ",
|
||||
((hw->bus_type == e1000_bus_type_pcix) ? "-X" : ""),
|
||||
((hw->bus_speed == e1000_bus_speed_133) ? "133MHz" :
|
||||
(hw->bus_speed == e1000_bus_speed_120) ? "120MHz" :
|
||||
(hw->bus_speed == e1000_bus_speed_100) ? "100MHz" :
|
||||
(hw->bus_speed == e1000_bus_speed_66) ? "66MHz" : "33MHz"),
|
||||
((hw->bus_width == e1000_bus_width_64) ? "64-bit" : "32-bit"));
|
||||
|
||||
e_info("%pM\n", netdev->dev_addr);
|
||||
e_info("(PCI%s:%dMHz:%d-bit) %pM\n",
|
||||
((hw->bus_type == e1000_bus_type_pcix) ? "-X" : ""),
|
||||
((hw->bus_speed == e1000_bus_speed_133) ? 133 :
|
||||
(hw->bus_speed == e1000_bus_speed_120) ? 120 :
|
||||
(hw->bus_speed == e1000_bus_speed_100) ? 100 :
|
||||
(hw->bus_speed == e1000_bus_speed_66) ? 66 : 33),
|
||||
((hw->bus_width == e1000_bus_width_64) ? 64 : 32),
|
||||
netdev->dev_addr);
|
||||
|
||||
/* carrier off reporting is important to ethtool even BEFORE open */
|
||||
netif_carrier_off(netdev);
|
||||
|
|
|
@ -2554,7 +2554,7 @@ static void e1000_init_manageability_pt(struct e1000_adapter *adapter)
|
|||
mdef = er32(MDEF(i));
|
||||
|
||||
/* Ignore filters with anything other than IPMI ports */
|
||||
if (mdef & !(E1000_MDEF_PORT_623 | E1000_MDEF_PORT_664))
|
||||
if (mdef & ~(E1000_MDEF_PORT_623 | E1000_MDEF_PORT_664))
|
||||
continue;
|
||||
|
||||
/* Enable this decision filter in MANC2H */
|
||||
|
|
|
@ -126,7 +126,7 @@ struct ehea_swqe {
|
|||
u8 immediate_data[SWQE2_MAX_IMM];
|
||||
/* 0xd0 */
|
||||
struct ehea_vsgentry sg_list[EHEA_MAX_WQE_SG_ENTRIES-1];
|
||||
} immdata_desc __attribute__ ((packed));
|
||||
} immdata_desc __packed;
|
||||
|
||||
/* Send WQE Format 3 */
|
||||
struct {
|
||||
|
|
|
@ -74,7 +74,14 @@ struct enic_msix_entry {
|
|||
void *devid;
|
||||
};
|
||||
|
||||
#define ENIC_SET_APPLIED (1 << 0)
|
||||
#define ENIC_SET_REQUEST (1 << 1)
|
||||
#define ENIC_SET_NAME (1 << 2)
|
||||
#define ENIC_SET_INSTANCE (1 << 3)
|
||||
#define ENIC_SET_HOST (1 << 4)
|
||||
|
||||
struct enic_port_profile {
|
||||
u32 set;
|
||||
u8 request;
|
||||
char name[PORT_PROFILE_MAX];
|
||||
u8 instance_uuid[PORT_UUID_MAX];
|
||||
|
|
|
@ -1029,8 +1029,7 @@ static int enic_dev_init_done(struct enic *enic, int *done, int *error)
|
|||
return err;
|
||||
}
|
||||
|
||||
static int enic_set_port_profile(struct enic *enic, u8 request, u8 *mac,
|
||||
char *name, u8 *instance_uuid, u8 *host_uuid)
|
||||
static int enic_set_port_profile(struct enic *enic, u8 *mac)
|
||||
{
|
||||
struct vic_provinfo *vp;
|
||||
u8 oui[3] = VIC_PROVINFO_CISCO_OUI;
|
||||
|
@ -1040,97 +1039,112 @@ static int enic_set_port_profile(struct enic *enic, u8 request, u8 *mac,
|
|||
"%02X%02X-%02X%02X%02X%02X%0X%02X";
|
||||
int err;
|
||||
|
||||
if (!name)
|
||||
return -EINVAL;
|
||||
|
||||
if (!is_valid_ether_addr(mac))
|
||||
return -EADDRNOTAVAIL;
|
||||
|
||||
vp = vic_provinfo_alloc(GFP_KERNEL, oui, VIC_PROVINFO_LINUX_TYPE);
|
||||
if (!vp)
|
||||
return -ENOMEM;
|
||||
|
||||
vic_provinfo_add_tlv(vp,
|
||||
VIC_LINUX_PROV_TLV_PORT_PROFILE_NAME_STR,
|
||||
strlen(name) + 1, name);
|
||||
|
||||
vic_provinfo_add_tlv(vp,
|
||||
VIC_LINUX_PROV_TLV_CLIENT_MAC_ADDR,
|
||||
ETH_ALEN, mac);
|
||||
|
||||
if (instance_uuid) {
|
||||
uuid = instance_uuid;
|
||||
sprintf(uuid_str, uuid_fmt,
|
||||
uuid[0], uuid[1], uuid[2], uuid[3],
|
||||
uuid[4], uuid[5], uuid[6], uuid[7],
|
||||
uuid[8], uuid[9], uuid[10], uuid[11],
|
||||
uuid[12], uuid[13], uuid[14], uuid[15]);
|
||||
vic_provinfo_add_tlv(vp,
|
||||
VIC_LINUX_PROV_TLV_CLIENT_UUID_STR,
|
||||
sizeof(uuid_str), uuid_str);
|
||||
}
|
||||
|
||||
if (host_uuid) {
|
||||
uuid = host_uuid;
|
||||
sprintf(uuid_str, uuid_fmt,
|
||||
uuid[0], uuid[1], uuid[2], uuid[3],
|
||||
uuid[4], uuid[5], uuid[6], uuid[7],
|
||||
uuid[8], uuid[9], uuid[10], uuid[11],
|
||||
uuid[12], uuid[13], uuid[14], uuid[15]);
|
||||
vic_provinfo_add_tlv(vp,
|
||||
VIC_LINUX_PROV_TLV_HOST_UUID_STR,
|
||||
sizeof(uuid_str), uuid_str);
|
||||
}
|
||||
|
||||
err = enic_vnic_dev_deinit(enic);
|
||||
if (err)
|
||||
goto err_out;
|
||||
return err;
|
||||
|
||||
memset(&enic->pp, 0, sizeof(enic->pp));
|
||||
switch (enic->pp.request) {
|
||||
|
||||
err = enic_dev_init_prov(enic, vp);
|
||||
if (err)
|
||||
goto err_out;
|
||||
case PORT_REQUEST_ASSOCIATE:
|
||||
|
||||
enic->pp.request = request;
|
||||
memcpy(enic->pp.name, name, PORT_PROFILE_MAX);
|
||||
if (instance_uuid)
|
||||
memcpy(enic->pp.instance_uuid,
|
||||
instance_uuid, PORT_UUID_MAX);
|
||||
if (host_uuid)
|
||||
memcpy(enic->pp.host_uuid,
|
||||
host_uuid, PORT_UUID_MAX);
|
||||
if (!(enic->pp.set & ENIC_SET_NAME) || !strlen(enic->pp.name))
|
||||
return -EINVAL;
|
||||
|
||||
err_out:
|
||||
vic_provinfo_free(vp);
|
||||
if (!is_valid_ether_addr(mac))
|
||||
return -EADDRNOTAVAIL;
|
||||
|
||||
return err;
|
||||
}
|
||||
vp = vic_provinfo_alloc(GFP_KERNEL, oui,
|
||||
VIC_PROVINFO_LINUX_TYPE);
|
||||
if (!vp)
|
||||
return -ENOMEM;
|
||||
|
||||
static int enic_unset_port_profile(struct enic *enic)
|
||||
{
|
||||
memset(&enic->pp, 0, sizeof(enic->pp));
|
||||
return enic_vnic_dev_deinit(enic);
|
||||
vic_provinfo_add_tlv(vp,
|
||||
VIC_LINUX_PROV_TLV_PORT_PROFILE_NAME_STR,
|
||||
strlen(enic->pp.name) + 1, enic->pp.name);
|
||||
|
||||
vic_provinfo_add_tlv(vp,
|
||||
VIC_LINUX_PROV_TLV_CLIENT_MAC_ADDR,
|
||||
ETH_ALEN, mac);
|
||||
|
||||
if (enic->pp.set & ENIC_SET_INSTANCE) {
|
||||
uuid = enic->pp.instance_uuid;
|
||||
sprintf(uuid_str, uuid_fmt,
|
||||
uuid[0], uuid[1], uuid[2], uuid[3],
|
||||
uuid[4], uuid[5], uuid[6], uuid[7],
|
||||
uuid[8], uuid[9], uuid[10], uuid[11],
|
||||
uuid[12], uuid[13], uuid[14], uuid[15]);
|
||||
vic_provinfo_add_tlv(vp,
|
||||
VIC_LINUX_PROV_TLV_CLIENT_UUID_STR,
|
||||
sizeof(uuid_str), uuid_str);
|
||||
}
|
||||
|
||||
if (enic->pp.set & ENIC_SET_HOST) {
|
||||
uuid = enic->pp.host_uuid;
|
||||
sprintf(uuid_str, uuid_fmt,
|
||||
uuid[0], uuid[1], uuid[2], uuid[3],
|
||||
uuid[4], uuid[5], uuid[6], uuid[7],
|
||||
uuid[8], uuid[9], uuid[10], uuid[11],
|
||||
uuid[12], uuid[13], uuid[14], uuid[15]);
|
||||
vic_provinfo_add_tlv(vp,
|
||||
VIC_LINUX_PROV_TLV_HOST_UUID_STR,
|
||||
sizeof(uuid_str), uuid_str);
|
||||
}
|
||||
|
||||
err = enic_dev_init_prov(enic, vp);
|
||||
vic_provinfo_free(vp);
|
||||
if (err)
|
||||
return err;
|
||||
break;
|
||||
|
||||
case PORT_REQUEST_DISASSOCIATE:
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
enic->pp.set |= ENIC_SET_APPLIED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int enic_set_vf_port(struct net_device *netdev, int vf,
|
||||
struct nlattr *port[])
|
||||
{
|
||||
struct enic *enic = netdev_priv(netdev);
|
||||
char *name = NULL;
|
||||
u8 *instance_uuid = NULL;
|
||||
u8 *host_uuid = NULL;
|
||||
u8 request = PORT_REQUEST_DISASSOCIATE;
|
||||
|
||||
memset(&enic->pp, 0, sizeof(enic->pp));
|
||||
|
||||
if (port[IFLA_PORT_REQUEST]) {
|
||||
enic->pp.set |= ENIC_SET_REQUEST;
|
||||
enic->pp.request = nla_get_u8(port[IFLA_PORT_REQUEST]);
|
||||
}
|
||||
|
||||
if (port[IFLA_PORT_PROFILE]) {
|
||||
enic->pp.set |= ENIC_SET_NAME;
|
||||
memcpy(enic->pp.name, nla_data(port[IFLA_PORT_PROFILE]),
|
||||
PORT_PROFILE_MAX);
|
||||
}
|
||||
|
||||
if (port[IFLA_PORT_INSTANCE_UUID]) {
|
||||
enic->pp.set |= ENIC_SET_INSTANCE;
|
||||
memcpy(enic->pp.instance_uuid,
|
||||
nla_data(port[IFLA_PORT_INSTANCE_UUID]), PORT_UUID_MAX);
|
||||
}
|
||||
|
||||
if (port[IFLA_PORT_HOST_UUID]) {
|
||||
enic->pp.set |= ENIC_SET_HOST;
|
||||
memcpy(enic->pp.host_uuid,
|
||||
nla_data(port[IFLA_PORT_HOST_UUID]), PORT_UUID_MAX);
|
||||
}
|
||||
|
||||
/* don't support VFs, yet */
|
||||
if (vf != PORT_SELF_VF)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (port[IFLA_PORT_REQUEST])
|
||||
request = nla_get_u8(port[IFLA_PORT_REQUEST]);
|
||||
if (!(enic->pp.set & ENIC_SET_REQUEST))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
switch (request) {
|
||||
case PORT_REQUEST_ASSOCIATE:
|
||||
if (enic->pp.request == PORT_REQUEST_ASSOCIATE) {
|
||||
|
||||
/* If the interface mac addr hasn't been assigned,
|
||||
* assign a random mac addr before setting port-
|
||||
|
@ -1139,30 +1153,9 @@ static int enic_set_vf_port(struct net_device *netdev, int vf,
|
|||
|
||||
if (is_zero_ether_addr(netdev->dev_addr))
|
||||
random_ether_addr(netdev->dev_addr);
|
||||
|
||||
if (port[IFLA_PORT_PROFILE])
|
||||
name = nla_data(port[IFLA_PORT_PROFILE]);
|
||||
|
||||
if (port[IFLA_PORT_INSTANCE_UUID])
|
||||
instance_uuid =
|
||||
nla_data(port[IFLA_PORT_INSTANCE_UUID]);
|
||||
|
||||
if (port[IFLA_PORT_HOST_UUID])
|
||||
host_uuid = nla_data(port[IFLA_PORT_HOST_UUID]);
|
||||
|
||||
return enic_set_port_profile(enic, request,
|
||||
netdev->dev_addr, name,
|
||||
instance_uuid, host_uuid);
|
||||
|
||||
case PORT_REQUEST_DISASSOCIATE:
|
||||
|
||||
return enic_unset_port_profile(enic);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
return enic_set_port_profile(enic, netdev->dev_addr);
|
||||
}
|
||||
|
||||
static int enic_get_vf_port(struct net_device *netdev, int vf,
|
||||
|
@ -1172,14 +1165,12 @@ static int enic_get_vf_port(struct net_device *netdev, int vf,
|
|||
int err, error, done;
|
||||
u16 response = PORT_PROFILE_RESPONSE_SUCCESS;
|
||||
|
||||
/* don't support VFs, yet */
|
||||
if (vf != PORT_SELF_VF)
|
||||
return -EOPNOTSUPP;
|
||||
if (!(enic->pp.set & ENIC_SET_APPLIED))
|
||||
return -ENODATA;
|
||||
|
||||
err = enic_dev_init_done(enic, &done, &error);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
error = err;
|
||||
|
||||
switch (error) {
|
||||
case ERR_SUCCESS:
|
||||
|
@ -1202,12 +1193,15 @@ static int enic_get_vf_port(struct net_device *netdev, int vf,
|
|||
|
||||
NLA_PUT_U16(skb, IFLA_PORT_REQUEST, enic->pp.request);
|
||||
NLA_PUT_U16(skb, IFLA_PORT_RESPONSE, response);
|
||||
NLA_PUT(skb, IFLA_PORT_PROFILE, PORT_PROFILE_MAX,
|
||||
enic->pp.name);
|
||||
NLA_PUT(skb, IFLA_PORT_INSTANCE_UUID, PORT_UUID_MAX,
|
||||
enic->pp.instance_uuid);
|
||||
NLA_PUT(skb, IFLA_PORT_HOST_UUID, PORT_UUID_MAX,
|
||||
enic->pp.host_uuid);
|
||||
if (enic->pp.set & ENIC_SET_NAME)
|
||||
NLA_PUT(skb, IFLA_PORT_PROFILE, PORT_PROFILE_MAX,
|
||||
enic->pp.name);
|
||||
if (enic->pp.set & ENIC_SET_INSTANCE)
|
||||
NLA_PUT(skb, IFLA_PORT_INSTANCE_UUID, PORT_UUID_MAX,
|
||||
enic->pp.instance_uuid);
|
||||
if (enic->pp.set & ENIC_SET_HOST)
|
||||
NLA_PUT(skb, IFLA_PORT_HOST_UUID, PORT_UUID_MAX,
|
||||
enic->pp.host_uuid);
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -709,7 +709,7 @@ int vnic_dev_init_prov(struct vnic_dev *vdev, u8 *buf, u32 len)
|
|||
{
|
||||
u64 a0, a1 = len;
|
||||
int wait = 1000;
|
||||
u64 prov_pa;
|
||||
dma_addr_t prov_pa;
|
||||
void *prov_buf;
|
||||
int ret;
|
||||
|
||||
|
|
|
@ -25,9 +25,10 @@
|
|||
|
||||
struct vic_provinfo *vic_provinfo_alloc(gfp_t flags, u8 *oui, u8 type)
|
||||
{
|
||||
struct vic_provinfo *vp = kzalloc(VIC_PROVINFO_MAX_DATA, flags);
|
||||
struct vic_provinfo *vp;
|
||||
|
||||
if (!vp || !oui)
|
||||
vp = kzalloc(VIC_PROVINFO_MAX_DATA, flags);
|
||||
if (!vp)
|
||||
return NULL;
|
||||
|
||||
memcpy(vp->oui, oui, sizeof(vp->oui));
|
||||
|
|
|
@ -44,7 +44,7 @@ struct vic_provinfo {
|
|||
u16 length;
|
||||
u8 value[0];
|
||||
} tlv[0];
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define VIC_PROVINFO_MAX_DATA 1385
|
||||
#define VIC_PROVINFO_MAX_TLV_DATA (VIC_PROVINFO_MAX_DATA - \
|
||||
|
|
|
@ -87,6 +87,7 @@ static int rx_copybreak;
|
|||
#include <linux/bitops.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
/* These identify the driver base version and may not be removed. */
|
||||
static char version[] __devinitdata =
|
||||
|
@ -230,7 +231,7 @@ static const u16 media2miictl[16] = {
|
|||
* The EPIC100 Rx and Tx buffer descriptors. Note that these
|
||||
* really ARE host-endian; it's not a misannotation. We tell
|
||||
* the card to byteswap them internally on big-endian hosts -
|
||||
* look for #ifdef CONFIG_BIG_ENDIAN in epic_open().
|
||||
* look for #ifdef __BIG_ENDIAN in epic_open().
|
||||
*/
|
||||
|
||||
struct epic_tx_desc {
|
||||
|
@ -690,7 +691,7 @@ static int epic_open(struct net_device *dev)
|
|||
outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
|
||||
|
||||
/* Tell the chip to byteswap descriptors on big-endian hosts */
|
||||
#ifdef CONFIG_BIG_ENDIAN
|
||||
#ifdef __BIG_ENDIAN
|
||||
outl(0x4432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
|
||||
inl(ioaddr + GENCTL);
|
||||
outl(0x0432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
|
||||
|
@ -806,7 +807,7 @@ static void epic_restart(struct net_device *dev)
|
|||
for (i = 16; i > 0; i--)
|
||||
outl(0x0008, ioaddr + TEST1);
|
||||
|
||||
#ifdef CONFIG_BIG_ENDIAN
|
||||
#ifdef __BIG_ENDIAN
|
||||
outl(0x0432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
|
||||
#else
|
||||
outl(0x0412 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
|
||||
|
|
|
@ -180,6 +180,7 @@ MODULE_PARM_DESC(buffer_size, "DMA buffer allocation size");
|
|||
* @dty_tx: last buffer actually sent
|
||||
* @num_rx: number of receive buffers
|
||||
* @cur_rx: current receive buffer
|
||||
* @vma: pointer to array of virtual memory addresses for buffers
|
||||
* @netdev: pointer to network device structure
|
||||
* @napi: NAPI structure
|
||||
* @stats: network device statistics
|
||||
|
@ -203,6 +204,8 @@ struct ethoc {
|
|||
unsigned int num_rx;
|
||||
unsigned int cur_rx;
|
||||
|
||||
void** vma;
|
||||
|
||||
struct net_device *netdev;
|
||||
struct napi_struct napi;
|
||||
struct net_device_stats stats;
|
||||
|
@ -285,18 +288,22 @@ static inline void ethoc_disable_rx_and_tx(struct ethoc *dev)
|
|||
ethoc_write(dev, MODER, mode);
|
||||
}
|
||||
|
||||
static int ethoc_init_ring(struct ethoc *dev)
|
||||
static int ethoc_init_ring(struct ethoc *dev, void* mem_start)
|
||||
{
|
||||
struct ethoc_bd bd;
|
||||
int i;
|
||||
void* vma;
|
||||
|
||||
dev->cur_tx = 0;
|
||||
dev->dty_tx = 0;
|
||||
dev->cur_rx = 0;
|
||||
|
||||
ethoc_write(dev, TX_BD_NUM, dev->num_tx);
|
||||
|
||||
/* setup transmission buffers */
|
||||
bd.addr = virt_to_phys(dev->membase);
|
||||
bd.addr = mem_start;
|
||||
bd.stat = TX_BD_IRQ | TX_BD_CRC;
|
||||
vma = dev->membase;
|
||||
|
||||
for (i = 0; i < dev->num_tx; i++) {
|
||||
if (i == dev->num_tx - 1)
|
||||
|
@ -304,6 +311,9 @@ static int ethoc_init_ring(struct ethoc *dev)
|
|||
|
||||
ethoc_write_bd(dev, i, &bd);
|
||||
bd.addr += ETHOC_BUFSIZ;
|
||||
|
||||
dev->vma[i] = vma;
|
||||
vma += ETHOC_BUFSIZ;
|
||||
}
|
||||
|
||||
bd.stat = RX_BD_EMPTY | RX_BD_IRQ;
|
||||
|
@ -314,6 +324,9 @@ static int ethoc_init_ring(struct ethoc *dev)
|
|||
|
||||
ethoc_write_bd(dev, dev->num_tx + i, &bd);
|
||||
bd.addr += ETHOC_BUFSIZ;
|
||||
|
||||
dev->vma[dev->num_tx + i] = vma;
|
||||
vma += ETHOC_BUFSIZ;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -415,7 +428,7 @@ static int ethoc_rx(struct net_device *dev, int limit)
|
|||
skb = netdev_alloc_skb_ip_align(dev, size);
|
||||
|
||||
if (likely(skb)) {
|
||||
void *src = phys_to_virt(bd.addr);
|
||||
void *src = priv->vma[entry];
|
||||
memcpy_fromio(skb_put(skb, size), src, size);
|
||||
skb->protocol = eth_type_trans(skb, dev);
|
||||
priv->stats.rx_packets++;
|
||||
|
@ -600,8 +613,11 @@ static int ethoc_mdio_write(struct mii_bus *bus, int phy, int reg, u16 val)
|
|||
|
||||
while (time_before(jiffies, timeout)) {
|
||||
u32 stat = ethoc_read(priv, MIISTATUS);
|
||||
if (!(stat & MIISTATUS_BUSY))
|
||||
if (!(stat & MIISTATUS_BUSY)) {
|
||||
/* reset MII command register */
|
||||
ethoc_write(priv, MIICOMMAND, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
schedule();
|
||||
}
|
||||
|
@ -622,21 +638,12 @@ static int ethoc_mdio_probe(struct net_device *dev)
|
|||
{
|
||||
struct ethoc *priv = netdev_priv(dev);
|
||||
struct phy_device *phy;
|
||||
int i;
|
||||
int err;
|
||||
|
||||
for (i = 0; i < PHY_MAX_ADDR; i++) {
|
||||
phy = priv->mdio->phy_map[i];
|
||||
if (phy) {
|
||||
if (priv->phy_id != -1) {
|
||||
/* attach to specified PHY */
|
||||
if (priv->phy_id == phy->addr)
|
||||
break;
|
||||
} else {
|
||||
/* autoselect PHY if none was specified */
|
||||
if (phy->addr != 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (priv->phy_id != -1) {
|
||||
phy = priv->mdio->phy_map[priv->phy_id];
|
||||
} else {
|
||||
phy = phy_find_first(priv->mdio);
|
||||
}
|
||||
|
||||
if (!phy) {
|
||||
|
@ -644,11 +651,11 @@ static int ethoc_mdio_probe(struct net_device *dev)
|
|||
return -ENXIO;
|
||||
}
|
||||
|
||||
phy = phy_connect(dev, dev_name(&phy->dev), ethoc_mdio_poll, 0,
|
||||
err = phy_connect_direct(dev, phy, ethoc_mdio_poll, 0,
|
||||
PHY_INTERFACE_MODE_GMII);
|
||||
if (IS_ERR(phy)) {
|
||||
if (err) {
|
||||
dev_err(&dev->dev, "could not attach to PHY\n");
|
||||
return PTR_ERR(phy);
|
||||
return err;
|
||||
}
|
||||
|
||||
priv->phy = phy;
|
||||
|
@ -658,8 +665,6 @@ static int ethoc_mdio_probe(struct net_device *dev)
|
|||
static int ethoc_open(struct net_device *dev)
|
||||
{
|
||||
struct ethoc *priv = netdev_priv(dev);
|
||||
unsigned int min_tx = 2;
|
||||
unsigned int num_bd;
|
||||
int ret;
|
||||
|
||||
ret = request_irq(dev->irq, ethoc_interrupt, IRQF_SHARED,
|
||||
|
@ -667,14 +672,7 @@ static int ethoc_open(struct net_device *dev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* calculate the number of TX/RX buffers, maximum 128 supported */
|
||||
num_bd = min_t(unsigned int,
|
||||
128, (dev->mem_end - dev->mem_start + 1) / ETHOC_BUFSIZ);
|
||||
priv->num_tx = max(min_tx, num_bd / 4);
|
||||
priv->num_rx = num_bd - priv->num_tx;
|
||||
ethoc_write(priv, TX_BD_NUM, priv->num_tx);
|
||||
|
||||
ethoc_init_ring(priv);
|
||||
ethoc_init_ring(priv, (void*)dev->mem_start);
|
||||
ethoc_reset(priv);
|
||||
|
||||
if (netif_queue_stopped(dev)) {
|
||||
|
@ -838,7 +836,7 @@ static netdev_tx_t ethoc_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
else
|
||||
bd.stat &= ~TX_BD_PAD;
|
||||
|
||||
dest = phys_to_virt(bd.addr);
|
||||
dest = priv->vma[entry];
|
||||
memcpy_toio(dest, skb->data, skb->len);
|
||||
|
||||
bd.stat &= ~(TX_BD_STATS | TX_BD_LEN_MASK);
|
||||
|
@ -884,6 +882,7 @@ static int ethoc_probe(struct platform_device *pdev)
|
|||
struct resource *mem = NULL;
|
||||
struct ethoc *priv = NULL;
|
||||
unsigned int phy;
|
||||
int num_bd;
|
||||
int ret = 0;
|
||||
|
||||
/* allocate networking device */
|
||||
|
@ -965,7 +964,7 @@ static int ethoc_probe(struct platform_device *pdev)
|
|||
}
|
||||
} else {
|
||||
/* Allocate buffer memory */
|
||||
priv->membase = dma_alloc_coherent(NULL,
|
||||
priv->membase = dmam_alloc_coherent(&pdev->dev,
|
||||
buffer_size, (void *)&netdev->mem_start,
|
||||
GFP_KERNEL);
|
||||
if (!priv->membase) {
|
||||
|
@ -978,6 +977,18 @@ static int ethoc_probe(struct platform_device *pdev)
|
|||
priv->dma_alloc = buffer_size;
|
||||
}
|
||||
|
||||
/* calculate the number of TX/RX buffers, maximum 128 supported */
|
||||
num_bd = min_t(unsigned int,
|
||||
128, (netdev->mem_end - netdev->mem_start + 1) / ETHOC_BUFSIZ);
|
||||
priv->num_tx = max(2, num_bd / 4);
|
||||
priv->num_rx = num_bd - priv->num_tx;
|
||||
|
||||
priv->vma = devm_kzalloc(&pdev->dev, num_bd*sizeof(void*), GFP_KERNEL);
|
||||
if (!priv->vma) {
|
||||
ret = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Allow the platform setup code to pass in a MAC address. */
|
||||
if (pdev->dev.platform_data) {
|
||||
struct ethoc_platform_data *pdata =
|
||||
|
@ -1063,21 +1074,6 @@ static int ethoc_probe(struct platform_device *pdev)
|
|||
kfree(priv->mdio->irq);
|
||||
mdiobus_free(priv->mdio);
|
||||
free:
|
||||
if (priv) {
|
||||
if (priv->dma_alloc)
|
||||
dma_free_coherent(NULL, priv->dma_alloc, priv->membase,
|
||||
netdev->mem_start);
|
||||
else if (priv->membase)
|
||||
devm_iounmap(&pdev->dev, priv->membase);
|
||||
if (priv->iobase)
|
||||
devm_iounmap(&pdev->dev, priv->iobase);
|
||||
}
|
||||
if (mem)
|
||||
devm_release_mem_region(&pdev->dev, mem->start,
|
||||
mem->end - mem->start + 1);
|
||||
if (mmio)
|
||||
devm_release_mem_region(&pdev->dev, mmio->start,
|
||||
mmio->end - mmio->start + 1);
|
||||
free_netdev(netdev);
|
||||
out:
|
||||
return ret;
|
||||
|
@ -1104,17 +1100,6 @@ static int ethoc_remove(struct platform_device *pdev)
|
|||
kfree(priv->mdio->irq);
|
||||
mdiobus_free(priv->mdio);
|
||||
}
|
||||
if (priv->dma_alloc)
|
||||
dma_free_coherent(NULL, priv->dma_alloc, priv->membase,
|
||||
netdev->mem_start);
|
||||
else {
|
||||
devm_iounmap(&pdev->dev, priv->membase);
|
||||
devm_release_mem_region(&pdev->dev, netdev->mem_start,
|
||||
netdev->mem_end - netdev->mem_start + 1);
|
||||
}
|
||||
devm_iounmap(&pdev->dev, priv->iobase);
|
||||
devm_release_mem_region(&pdev->dev, netdev->base_addr,
|
||||
priv->io_region_size);
|
||||
unregister_netdev(netdev);
|
||||
free_netdev(netdev);
|
||||
}
|
||||
|
|
|
@ -210,7 +210,7 @@ static void fec_stop(struct net_device *dev);
|
|||
/* Transmitter timeout */
|
||||
#define TX_TIMEOUT (2 * HZ)
|
||||
|
||||
static int
|
||||
static netdev_tx_t
|
||||
fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct fec_enet_private *fep = netdev_priv(dev);
|
||||
|
@ -679,30 +679,24 @@ static int fec_enet_mii_probe(struct net_device *dev)
|
|||
{
|
||||
struct fec_enet_private *fep = netdev_priv(dev);
|
||||
struct phy_device *phy_dev = NULL;
|
||||
int phy_addr;
|
||||
int ret;
|
||||
|
||||
fep->phy_dev = NULL;
|
||||
|
||||
/* find the first phy */
|
||||
for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
|
||||
if (fep->mii_bus->phy_map[phy_addr]) {
|
||||
phy_dev = fep->mii_bus->phy_map[phy_addr];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
phy_dev = phy_find_first(fep->mii_bus);
|
||||
if (!phy_dev) {
|
||||
printk(KERN_ERR "%s: no PHY found\n", dev->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* attach the mac to the phy */
|
||||
phy_dev = phy_connect(dev, dev_name(&phy_dev->dev),
|
||||
ret = phy_connect_direct(dev, phy_dev,
|
||||
&fec_enet_adjust_link, 0,
|
||||
PHY_INTERFACE_MODE_MII);
|
||||
if (IS_ERR(phy_dev)) {
|
||||
if (ret) {
|
||||
printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
|
||||
return PTR_ERR(phy_dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* mask with MAC supported features */
|
||||
|
@ -1365,6 +1359,8 @@ fec_drv_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
static int
|
||||
fec_suspend(struct platform_device *dev, pm_message_t state)
|
||||
{
|
||||
|
@ -1373,10 +1369,9 @@ fec_suspend(struct platform_device *dev, pm_message_t state)
|
|||
|
||||
if (ndev) {
|
||||
fep = netdev_priv(ndev);
|
||||
if (netif_running(ndev)) {
|
||||
netif_device_detach(ndev);
|
||||
fec_stop(ndev);
|
||||
}
|
||||
if (netif_running(ndev))
|
||||
fec_enet_close(ndev);
|
||||
clk_disable(fep->clk);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1385,25 +1380,42 @@ static int
|
|||
fec_resume(struct platform_device *dev)
|
||||
{
|
||||
struct net_device *ndev = platform_get_drvdata(dev);
|
||||
struct fec_enet_private *fep;
|
||||
|
||||
if (ndev) {
|
||||
if (netif_running(ndev)) {
|
||||
fec_enet_init(ndev, 0);
|
||||
netif_device_attach(ndev);
|
||||
}
|
||||
fep = netdev_priv(ndev);
|
||||
clk_enable(fep->clk);
|
||||
if (netif_running(ndev))
|
||||
fec_enet_open(ndev);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops fec_pm_ops = {
|
||||
.suspend = fec_suspend,
|
||||
.resume = fec_resume,
|
||||
.freeze = fec_suspend,
|
||||
.thaw = fec_resume,
|
||||
.poweroff = fec_suspend,
|
||||
.restore = fec_resume,
|
||||
};
|
||||
|
||||
#define FEC_PM_OPS (&fec_pm_ops)
|
||||
|
||||
#else /* !CONFIG_PM */
|
||||
|
||||
#define FEC_PM_OPS NULL
|
||||
|
||||
#endif /* !CONFIG_PM */
|
||||
|
||||
static struct platform_driver fec_driver = {
|
||||
.driver = {
|
||||
.name = "fec",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = FEC_PM_OPS,
|
||||
},
|
||||
.probe = fec_probe,
|
||||
.remove = __devexit_p(fec_drv_remove),
|
||||
.suspend = fec_suspend,
|
||||
.resume = fec_resume,
|
||||
};
|
||||
|
||||
static int __init
|
||||
|
|
|
@ -29,15 +29,14 @@ static int mpc52xx_fec_mdio_transfer(struct mii_bus *bus, int phy_id,
|
|||
int reg, u32 value)
|
||||
{
|
||||
struct mpc52xx_fec_mdio_priv *priv = bus->priv;
|
||||
struct mpc52xx_fec __iomem *fec;
|
||||
struct mpc52xx_fec __iomem *fec = priv->regs;
|
||||
int tries = 3;
|
||||
|
||||
value |= (phy_id << FEC_MII_DATA_PA_SHIFT) & FEC_MII_DATA_PA_MSK;
|
||||
value |= (reg << FEC_MII_DATA_RA_SHIFT) & FEC_MII_DATA_RA_MSK;
|
||||
|
||||
fec = priv->regs;
|
||||
out_be32(&fec->ievent, FEC_IEVENT_MII);
|
||||
out_be32(&priv->regs->mii_data, value);
|
||||
out_be32(&fec->mii_data, value);
|
||||
|
||||
/* wait for it to finish, this takes about 23 us on lite5200b */
|
||||
while (!(in_be32(&fec->ievent) & FEC_IEVENT_MII) && --tries)
|
||||
|
@ -47,7 +46,7 @@ static int mpc52xx_fec_mdio_transfer(struct mii_bus *bus, int phy_id,
|
|||
return -ETIMEDOUT;
|
||||
|
||||
return value & FEC_MII_DATA_OP_RD ?
|
||||
in_be32(&priv->regs->mii_data) & FEC_MII_DATA_DATAMSK : 0;
|
||||
in_be32(&fec->mii_data) & FEC_MII_DATA_DATAMSK : 0;
|
||||
}
|
||||
|
||||
static int mpc52xx_fec_mdio_read(struct mii_bus *bus, int phy_id, int reg)
|
||||
|
@ -69,9 +68,8 @@ static int mpc52xx_fec_mdio_probe(struct of_device *of,
|
|||
struct device_node *np = of->dev.of_node;
|
||||
struct mii_bus *bus;
|
||||
struct mpc52xx_fec_mdio_priv *priv;
|
||||
struct resource res = {};
|
||||
struct resource res;
|
||||
int err;
|
||||
int i;
|
||||
|
||||
bus = mdiobus_alloc();
|
||||
if (bus == NULL)
|
||||
|
@ -93,7 +91,7 @@ static int mpc52xx_fec_mdio_probe(struct of_device *of,
|
|||
err = of_address_to_resource(np, 0, &res);
|
||||
if (err)
|
||||
goto out_free;
|
||||
priv->regs = ioremap(res.start, res.end - res.start + 1);
|
||||
priv->regs = ioremap(res.start, resource_size(&res));
|
||||
if (priv->regs == NULL) {
|
||||
err = -ENOMEM;
|
||||
goto out_free;
|
||||
|
@ -118,10 +116,6 @@ static int mpc52xx_fec_mdio_probe(struct of_device *of,
|
|||
out_unmap:
|
||||
iounmap(priv->regs);
|
||||
out_free:
|
||||
for (i=0; i<PHY_MAX_ADDR; i++)
|
||||
if (bus->irq[i] != PHY_POLL)
|
||||
irq_dispose_mapping(bus->irq[i]);
|
||||
kfree(bus->irq);
|
||||
kfree(priv);
|
||||
mdiobus_free(bus);
|
||||
|
||||
|
@ -133,23 +127,16 @@ static int mpc52xx_fec_mdio_remove(struct of_device *of)
|
|||
struct device *dev = &of->dev;
|
||||
struct mii_bus *bus = dev_get_drvdata(dev);
|
||||
struct mpc52xx_fec_mdio_priv *priv = bus->priv;
|
||||
int i;
|
||||
|
||||
mdiobus_unregister(bus);
|
||||
dev_set_drvdata(dev, NULL);
|
||||
|
||||
iounmap(priv->regs);
|
||||
for (i=0; i<PHY_MAX_ADDR; i++)
|
||||
if (bus->irq[i] != PHY_POLL)
|
||||
irq_dispose_mapping(bus->irq[i]);
|
||||
kfree(priv);
|
||||
kfree(bus->irq);
|
||||
mdiobus_free(bus);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static struct of_device_id mpc52xx_fec_mdio_match[] = {
|
||||
{ .compatible = "fsl,mpc5200b-mdio", },
|
||||
{ .compatible = "fsl,mpc5200-mdio", },
|
||||
|
@ -171,5 +158,4 @@ struct of_platform_driver mpc52xx_fec_mdio_driver = {
|
|||
/* let fec driver call it, since this has to be registered before it */
|
||||
EXPORT_SYMBOL_GPL(mpc52xx_fec_mdio_driver);
|
||||
|
||||
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
|
|
|
@ -39,7 +39,7 @@ struct fsl_pq_mdio {
|
|||
u8 reserved[28]; /* Space holder */
|
||||
u32 utbipar; /* TBI phy address reg (only on UCC) */
|
||||
u8 res4[2728];
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
int fsl_pq_mdio_read(struct mii_bus *bus, int mii_id, int regnum);
|
||||
int fsl_pq_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value);
|
||||
|
|
|
@ -681,8 +681,8 @@ static int gfar_of_init(struct of_device *ofdev, struct net_device **pdev)
|
|||
priv->rx_queue[i] = NULL;
|
||||
|
||||
for (i = 0; i < priv->num_tx_queues; i++) {
|
||||
priv->tx_queue[i] = (struct gfar_priv_tx_q *)kzalloc(
|
||||
sizeof (struct gfar_priv_tx_q), GFP_KERNEL);
|
||||
priv->tx_queue[i] = kzalloc(sizeof(struct gfar_priv_tx_q),
|
||||
GFP_KERNEL);
|
||||
if (!priv->tx_queue[i]) {
|
||||
err = -ENOMEM;
|
||||
goto tx_alloc_failed;
|
||||
|
@ -694,8 +694,8 @@ static int gfar_of_init(struct of_device *ofdev, struct net_device **pdev)
|
|||
}
|
||||
|
||||
for (i = 0; i < priv->num_rx_queues; i++) {
|
||||
priv->rx_queue[i] = (struct gfar_priv_rx_q *)kzalloc(
|
||||
sizeof (struct gfar_priv_rx_q), GFP_KERNEL);
|
||||
priv->rx_queue[i] = kzalloc(sizeof(struct gfar_priv_rx_q),
|
||||
GFP_KERNEL);
|
||||
if (!priv->rx_queue[i]) {
|
||||
err = -ENOMEM;
|
||||
goto rx_alloc_failed;
|
||||
|
@ -747,8 +747,7 @@ static int gfar_of_init(struct of_device *ofdev, struct net_device **pdev)
|
|||
FSL_GIANFAR_DEV_HAS_CSUM |
|
||||
FSL_GIANFAR_DEV_HAS_VLAN |
|
||||
FSL_GIANFAR_DEV_HAS_MAGIC_PACKET |
|
||||
FSL_GIANFAR_DEV_HAS_EXTENDED_HASH |
|
||||
FSL_GIANFAR_DEV_HAS_TIMER;
|
||||
FSL_GIANFAR_DEV_HAS_EXTENDED_HASH;
|
||||
|
||||
ctype = of_get_property(np, "phy-connection-type", NULL);
|
||||
|
||||
|
|
|
@ -1555,7 +1555,6 @@ static int __devinit greth_of_probe(struct of_device *ofdev, const struct of_dev
|
|||
}
|
||||
|
||||
/* setup NAPI */
|
||||
memset(&greth->napi, 0, sizeof(greth->napi));
|
||||
netif_napi_add(dev, &greth->napi, greth_poll, 64);
|
||||
|
||||
return 0;
|
||||
|
@ -1607,14 +1606,13 @@ static struct of_device_id greth_of_match[] = {
|
|||
MODULE_DEVICE_TABLE(of, greth_of_match);
|
||||
|
||||
static struct of_platform_driver greth_of_driver = {
|
||||
.name = "grlib-greth",
|
||||
.match_table = greth_of_match,
|
||||
.driver = {
|
||||
.name = "grlib-greth",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = greth_of_match,
|
||||
},
|
||||
.probe = greth_of_probe,
|
||||
.remove = __devexit_p(greth_of_remove),
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "grlib-greth",
|
||||
},
|
||||
};
|
||||
|
||||
static int __init greth_init(void)
|
||||
|
|
|
@ -273,7 +273,7 @@ struct OboeSlot
|
|||
__u8 control; /*Slot control/status see below */
|
||||
__u32 address; /*Slot buffer address */
|
||||
}
|
||||
__attribute__ ((packed));
|
||||
__packed;
|
||||
|
||||
#define OBOE_NTASKS OBOE_TXRING_OFFSET_IN_SLOTS
|
||||
|
||||
|
|
|
@ -125,7 +125,7 @@ struct irda_class_desc {
|
|||
__u8 bmAdditionalBOFs;
|
||||
__u8 bIrdaRateSniff;
|
||||
__u8 bMaxUnicastList;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
/* class specific interface request to get the IrDA-USB class descriptor
|
||||
* (6.2.5, USB-IrDA class spec 1.0) */
|
||||
|
|
|
@ -154,7 +154,7 @@ struct ks959_speedparams {
|
|||
__le32 baudrate; /* baud rate, little endian */
|
||||
__u8 flags;
|
||||
__u8 reserved[3];
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define KS_DATA_5_BITS 0x00
|
||||
#define KS_DATA_6_BITS 0x01
|
||||
|
|
|
@ -117,7 +117,7 @@ struct ksdazzle_speedparams {
|
|||
__le32 baudrate; /* baud rate, little endian */
|
||||
__u8 flags;
|
||||
__u8 reserved[3];
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define KS_DATA_5_BITS 0x00
|
||||
#define KS_DATA_6_BITS 0x01
|
||||
|
|
|
@ -544,9 +544,9 @@ struct ring_descr_hw {
|
|||
struct {
|
||||
u8 addr_res[3];
|
||||
volatile u8 status; /* descriptor status */
|
||||
} __attribute__((packed)) rd_s;
|
||||
} __attribute((packed)) rd_u;
|
||||
} __attribute__ ((packed));
|
||||
} __packed rd_s;
|
||||
} __packed rd_u;
|
||||
} __packed;
|
||||
|
||||
#define rd_addr rd_u.addr
|
||||
#define rd_status rd_u.rd_s.status
|
||||
|
|
|
@ -44,11 +44,9 @@
|
|||
#include <linux/dca.h>
|
||||
#endif
|
||||
|
||||
#define PFX "ixgbe: "
|
||||
#define DPRINTK(nlevel, klevel, fmt, args...) \
|
||||
((void)((NETIF_MSG_##nlevel & adapter->msg_enable) && \
|
||||
printk(KERN_##klevel PFX "%s: %s: " fmt, adapter->netdev->name, \
|
||||
__func__ , ## args)))
|
||||
/* common prefix used by pr_<> macros */
|
||||
#undef pr_fmt
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
/* TX/RX descriptor defines */
|
||||
#define IXGBE_DEFAULT_TXD 512
|
||||
|
|
|
@ -707,9 +707,8 @@ static s32 ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw,
|
|||
|
||||
out:
|
||||
if (link_up && (link_speed == IXGBE_LINK_SPEED_1GB_FULL))
|
||||
netif_info(adapter, hw, adapter->netdev, "Smartspeed has"
|
||||
" downgraded the link speed from the maximum"
|
||||
" advertised\n");
|
||||
e_info("Smartspeed has downgraded the link speed from "
|
||||
"the maximum advertised\n");
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
|
@ -1188,6 +1188,7 @@ s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq,
|
|||
IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
|
||||
} else {
|
||||
hw_dbg(hw, "RAR index %d is out of range.\n", index);
|
||||
return IXGBE_ERR_RAR_INDEX;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1219,6 +1220,7 @@ s32 ixgbe_clear_rar_generic(struct ixgbe_hw *hw, u32 index)
|
|||
IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
|
||||
} else {
|
||||
hw_dbg(hw, "RAR index %d is out of range.\n", index);
|
||||
return IXGBE_ERR_RAR_INDEX;
|
||||
}
|
||||
|
||||
/* clear VMDq pool/queue selection for this RAR */
|
||||
|
|
|
@ -105,12 +105,26 @@ s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index);
|
|||
|
||||
#define IXGBE_WRITE_FLUSH(a) IXGBE_READ_REG(a, IXGBE_STATUS)
|
||||
|
||||
#ifdef DEBUG
|
||||
extern char *ixgbe_get_hw_dev_name(struct ixgbe_hw *hw);
|
||||
extern struct net_device *ixgbe_get_hw_dev(struct ixgbe_hw *hw);
|
||||
#define hw_dbg(hw, format, arg...) \
|
||||
printk(KERN_DEBUG "%s: " format, ixgbe_get_hw_dev_name(hw), ##arg)
|
||||
#else
|
||||
#define hw_dbg(hw, format, arg...) do {} while (0)
|
||||
#endif
|
||||
netdev_dbg(ixgbe_get_hw_dev(hw), format, ##arg)
|
||||
#define e_err(format, arg...) \
|
||||
netdev_err(adapter->netdev, format, ## arg)
|
||||
#define e_info(format, arg...) \
|
||||
netdev_info(adapter->netdev, format, ## arg)
|
||||
#define e_warn(format, arg...) \
|
||||
netdev_warn(adapter->netdev, format, ## arg)
|
||||
#define e_notice(format, arg...) \
|
||||
netdev_notice(adapter->netdev, format, ## arg)
|
||||
#define e_crit(format, arg...) \
|
||||
netdev_crit(adapter->netdev, format, ## arg)
|
||||
#define e_dev_info(format, arg...) \
|
||||
dev_info(&adapter->pdev->dev, format, ## arg)
|
||||
#define e_dev_warn(format, arg...) \
|
||||
dev_warn(&adapter->pdev->dev, format, ## arg)
|
||||
#define e_dev_err(format, arg...) \
|
||||
dev_err(&adapter->pdev->dev, format, ## arg)
|
||||
#define e_dev_notice(format, arg...) \
|
||||
dev_notice(&adapter->pdev->dev, format, ## arg)
|
||||
|
||||
#endif /* IXGBE_COMMON */
|
||||
|
|
|
@ -121,7 +121,7 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)
|
|||
goto out;
|
||||
|
||||
if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) {
|
||||
DPRINTK(DRV, ERR, "Enable failed, needs MSI-X\n");
|
||||
e_err("Enable failed, needs MSI-X\n");
|
||||
err = 1;
|
||||
goto out;
|
||||
}
|
||||
|
|
|
@ -294,8 +294,7 @@ static int ixgbe_set_settings(struct net_device *netdev,
|
|||
hw->mac.autotry_restart = true;
|
||||
err = hw->mac.ops.setup_link(hw, advertised, true, true);
|
||||
if (err) {
|
||||
DPRINTK(PROBE, INFO,
|
||||
"setup link failed with code %d\n", err);
|
||||
e_info("setup link failed with code %d\n", err);
|
||||
hw->mac.ops.setup_link(hw, old, true, true);
|
||||
}
|
||||
} else {
|
||||
|
@ -1188,9 +1187,9 @@ static struct ixgbe_reg_test reg_test_82598[] = {
|
|||
writel((_test[pat] & W), (adapter->hw.hw_addr + R)); \
|
||||
val = readl(adapter->hw.hw_addr + R); \
|
||||
if (val != (_test[pat] & W & M)) { \
|
||||
DPRINTK(DRV, ERR, "pattern test reg %04X failed: got "\
|
||||
"0x%08X expected 0x%08X\n", \
|
||||
R, val, (_test[pat] & W & M)); \
|
||||
e_err("pattern test reg %04X failed: got " \
|
||||
"0x%08X expected 0x%08X\n", \
|
||||
R, val, (_test[pat] & W & M)); \
|
||||
*data = R; \
|
||||
writel(before, adapter->hw.hw_addr + R); \
|
||||
return 1; \
|
||||
|
@ -1206,8 +1205,8 @@ static struct ixgbe_reg_test reg_test_82598[] = {
|
|||
writel((W & M), (adapter->hw.hw_addr + R)); \
|
||||
val = readl(adapter->hw.hw_addr + R); \
|
||||
if ((W & M) != (val & M)) { \
|
||||
DPRINTK(DRV, ERR, "set/check reg %04X test failed: got 0x%08X "\
|
||||
"expected 0x%08X\n", R, (val & M), (W & M)); \
|
||||
e_err("set/check reg %04X test failed: got 0x%08X " \
|
||||
"expected 0x%08X\n", R, (val & M), (W & M)); \
|
||||
*data = R; \
|
||||
writel(before, (adapter->hw.hw_addr + R)); \
|
||||
return 1; \
|
||||
|
@ -1240,8 +1239,8 @@ static int ixgbe_reg_test(struct ixgbe_adapter *adapter, u64 *data)
|
|||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_STATUS, toggle);
|
||||
after = IXGBE_READ_REG(&adapter->hw, IXGBE_STATUS) & toggle;
|
||||
if (value != after) {
|
||||
DPRINTK(DRV, ERR, "failed STATUS register test got: "
|
||||
"0x%08X expected: 0x%08X\n", after, value);
|
||||
e_err("failed STATUS register test got: 0x%08X expected: "
|
||||
"0x%08X\n", after, value);
|
||||
*data = 1;
|
||||
return 1;
|
||||
}
|
||||
|
@ -1341,8 +1340,8 @@ static int ixgbe_intr_test(struct ixgbe_adapter *adapter, u64 *data)
|
|||
*data = 1;
|
||||
return -1;
|
||||
}
|
||||
DPRINTK(HW, INFO, "testing %s interrupt\n",
|
||||
(shared_int ? "shared" : "unshared"));
|
||||
e_info("testing %s interrupt\n", shared_int ?
|
||||
"shared" : "unshared");
|
||||
|
||||
/* Disable all the interrupts */
|
||||
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFFFFFF);
|
||||
|
@ -1847,7 +1846,7 @@ static void ixgbe_diag_test(struct net_device *netdev,
|
|||
if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
|
||||
/* Offline tests */
|
||||
|
||||
DPRINTK(HW, INFO, "offline testing starting\n");
|
||||
e_info("offline testing starting\n");
|
||||
|
||||
/* Link test performed before hardware reset so autoneg doesn't
|
||||
* interfere with test result */
|
||||
|
@ -1880,17 +1879,17 @@ static void ixgbe_diag_test(struct net_device *netdev,
|
|||
else
|
||||
ixgbe_reset(adapter);
|
||||
|
||||
DPRINTK(HW, INFO, "register testing starting\n");
|
||||
e_info("register testing starting\n");
|
||||
if (ixgbe_reg_test(adapter, &data[0]))
|
||||
eth_test->flags |= ETH_TEST_FL_FAILED;
|
||||
|
||||
ixgbe_reset(adapter);
|
||||
DPRINTK(HW, INFO, "eeprom testing starting\n");
|
||||
e_info("eeprom testing starting\n");
|
||||
if (ixgbe_eeprom_test(adapter, &data[1]))
|
||||
eth_test->flags |= ETH_TEST_FL_FAILED;
|
||||
|
||||
ixgbe_reset(adapter);
|
||||
DPRINTK(HW, INFO, "interrupt testing starting\n");
|
||||
e_info("interrupt testing starting\n");
|
||||
if (ixgbe_intr_test(adapter, &data[2]))
|
||||
eth_test->flags |= ETH_TEST_FL_FAILED;
|
||||
|
||||
|
@ -1898,14 +1897,13 @@ static void ixgbe_diag_test(struct net_device *netdev,
|
|||
* loopback diagnostic. */
|
||||
if (adapter->flags & (IXGBE_FLAG_SRIOV_ENABLED |
|
||||
IXGBE_FLAG_VMDQ_ENABLED)) {
|
||||
DPRINTK(HW, INFO, "Skip MAC loopback diagnostic in VT "
|
||||
"mode\n");
|
||||
e_info("Skip MAC loopback diagnostic in VT mode\n");
|
||||
data[3] = 0;
|
||||
goto skip_loopback;
|
||||
}
|
||||
|
||||
ixgbe_reset(adapter);
|
||||
DPRINTK(HW, INFO, "loopback testing starting\n");
|
||||
e_info("loopback testing starting\n");
|
||||
if (ixgbe_loopback_test(adapter, &data[3]))
|
||||
eth_test->flags |= ETH_TEST_FL_FAILED;
|
||||
|
||||
|
@ -1916,7 +1914,7 @@ static void ixgbe_diag_test(struct net_device *netdev,
|
|||
if (if_running)
|
||||
dev_open(netdev);
|
||||
} else {
|
||||
DPRINTK(HW, INFO, "online testing starting\n");
|
||||
e_info("online testing starting\n");
|
||||
/* Online tests */
|
||||
if (ixgbe_link_test(adapter, &data[4]))
|
||||
eth_test->flags |= ETH_TEST_FL_FAILED;
|
||||
|
@ -2077,25 +2075,6 @@ static int ixgbe_get_coalesce(struct net_device *netdev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* this function must be called before setting the new value of
|
||||
* rx_itr_setting
|
||||
*/
|
||||
static bool ixgbe_reenable_rsc(struct ixgbe_adapter *adapter,
|
||||
struct ethtool_coalesce *ec)
|
||||
{
|
||||
/* check the old value and enable RSC if necessary */
|
||||
if ((adapter->rx_itr_setting == 0) &&
|
||||
(adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE)) {
|
||||
adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED;
|
||||
adapter->netdev->features |= NETIF_F_LRO;
|
||||
DPRINTK(PROBE, INFO, "rx-usecs set to %d, re-enabling RSC\n",
|
||||
ec->rx_coalesce_usecs);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int ixgbe_set_coalesce(struct net_device *netdev,
|
||||
struct ethtool_coalesce *ec)
|
||||
{
|
||||
|
@ -2124,9 +2103,6 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
|
|||
(1000000/ec->rx_coalesce_usecs < IXGBE_MIN_INT_RATE))
|
||||
return -EINVAL;
|
||||
|
||||
/* check the old value and enable RSC if necessary */
|
||||
need_reset = ixgbe_reenable_rsc(adapter, ec);
|
||||
|
||||
/* store the value in ints/second */
|
||||
adapter->rx_eitr_param = 1000000/ec->rx_coalesce_usecs;
|
||||
|
||||
|
@ -2135,9 +2111,6 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
|
|||
/* clear the lower bit as its used for dynamic state */
|
||||
adapter->rx_itr_setting &= ~1;
|
||||
} else if (ec->rx_coalesce_usecs == 1) {
|
||||
/* check the old value and enable RSC if necessary */
|
||||
need_reset = ixgbe_reenable_rsc(adapter, ec);
|
||||
|
||||
/* 1 means dynamic mode */
|
||||
adapter->rx_eitr_param = 20000;
|
||||
adapter->rx_itr_setting = 1;
|
||||
|
@ -2157,10 +2130,10 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
|
|||
*/
|
||||
if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
|
||||
adapter->flags2 &= ~IXGBE_FLAG2_RSC_ENABLED;
|
||||
netdev->features &= ~NETIF_F_LRO;
|
||||
DPRINTK(PROBE, INFO,
|
||||
"rx-usecs set to 0, disabling RSC\n");
|
||||
|
||||
if (netdev->features & NETIF_F_LRO) {
|
||||
netdev->features &= ~NETIF_F_LRO;
|
||||
e_info("rx-usecs set to 0, disabling RSC\n");
|
||||
}
|
||||
need_reset = true;
|
||||
}
|
||||
}
|
||||
|
@ -2255,6 +2228,9 @@ static int ixgbe_set_flags(struct net_device *netdev, u32 data)
|
|||
}
|
||||
} else if (!adapter->rx_itr_setting) {
|
||||
netdev->features &= ~ETH_FLAG_LRO;
|
||||
if (data & ETH_FLAG_LRO)
|
||||
e_info("rx-usecs set to 0, "
|
||||
"LRO/RSC cannot be enabled.\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
#include "ixgbe.h"
|
||||
#ifdef CONFIG_IXGBE_DCB
|
||||
#include "ixgbe_dcb_82599.h"
|
||||
|
@ -165,20 +164,20 @@ int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid,
|
|||
|
||||
adapter = netdev_priv(netdev);
|
||||
if (xid >= IXGBE_FCOE_DDP_MAX) {
|
||||
DPRINTK(DRV, WARNING, "xid=0x%x out-of-range\n", xid);
|
||||
e_warn("xid=0x%x out-of-range\n", xid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fcoe = &adapter->fcoe;
|
||||
if (!fcoe->pool) {
|
||||
DPRINTK(DRV, WARNING, "xid=0x%x no ddp pool for fcoe\n", xid);
|
||||
e_warn("xid=0x%x no ddp pool for fcoe\n", xid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ddp = &fcoe->ddp[xid];
|
||||
if (ddp->sgl) {
|
||||
DPRINTK(DRV, ERR, "xid 0x%x w/ non-null sgl=%p nents=%d\n",
|
||||
xid, ddp->sgl, ddp->sgc);
|
||||
e_err("xid 0x%x w/ non-null sgl=%p nents=%d\n",
|
||||
xid, ddp->sgl, ddp->sgc);
|
||||
return 0;
|
||||
}
|
||||
ixgbe_fcoe_clear_ddp(ddp);
|
||||
|
@ -186,14 +185,14 @@ int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid,
|
|||
/* setup dma from scsi command sgl */
|
||||
dmacount = pci_map_sg(adapter->pdev, sgl, sgc, DMA_FROM_DEVICE);
|
||||
if (dmacount == 0) {
|
||||
DPRINTK(DRV, ERR, "xid 0x%x DMA map error\n", xid);
|
||||
e_err("xid 0x%x DMA map error\n", xid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* alloc the udl from our ddp pool */
|
||||
ddp->udl = pci_pool_alloc(fcoe->pool, GFP_KERNEL, &ddp->udp);
|
||||
if (!ddp->udl) {
|
||||
DPRINTK(DRV, ERR, "failed allocated ddp context\n");
|
||||
e_err("failed allocated ddp context\n");
|
||||
goto out_noddp_unmap;
|
||||
}
|
||||
ddp->sgl = sgl;
|
||||
|
@ -206,10 +205,9 @@ int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid,
|
|||
while (len) {
|
||||
/* max number of buffers allowed in one DDP context */
|
||||
if (j >= IXGBE_BUFFCNT_MAX) {
|
||||
netif_err(adapter, drv, adapter->netdev,
|
||||
"xid=%x:%d,%d,%d:addr=%llx "
|
||||
"not enough descriptors\n",
|
||||
xid, i, j, dmacount, (u64)addr);
|
||||
e_err("xid=%x:%d,%d,%d:addr=%llx "
|
||||
"not enough descriptors\n",
|
||||
xid, i, j, dmacount, (u64)addr);
|
||||
goto out_noddp_free;
|
||||
}
|
||||
|
||||
|
@ -387,8 +385,8 @@ int ixgbe_fso(struct ixgbe_adapter *adapter,
|
|||
struct fc_frame_header *fh;
|
||||
|
||||
if (skb_is_gso(skb) && (skb_shinfo(skb)->gso_type != SKB_GSO_FCOE)) {
|
||||
DPRINTK(DRV, ERR, "Wrong gso type %d:expecting SKB_GSO_FCOE\n",
|
||||
skb_shinfo(skb)->gso_type);
|
||||
e_err("Wrong gso type %d:expecting SKB_GSO_FCOE\n",
|
||||
skb_shinfo(skb)->gso_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -414,7 +412,7 @@ int ixgbe_fso(struct ixgbe_adapter *adapter,
|
|||
fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_SOF;
|
||||
break;
|
||||
default:
|
||||
DPRINTK(DRV, WARNING, "unknown sof = 0x%x\n", sof);
|
||||
e_warn("unknown sof = 0x%x\n", sof);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -441,7 +439,7 @@ int ixgbe_fso(struct ixgbe_adapter *adapter,
|
|||
fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_A;
|
||||
break;
|
||||
default:
|
||||
DPRINTK(DRV, WARNING, "unknown eof = 0x%x\n", eof);
|
||||
e_warn("unknown eof = 0x%x\n", eof);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -517,8 +515,7 @@ void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter)
|
|||
adapter->pdev, IXGBE_FCPTR_MAX,
|
||||
IXGBE_FCPTR_ALIGN, PAGE_SIZE);
|
||||
if (!fcoe->pool)
|
||||
DPRINTK(DRV, ERR,
|
||||
"failed to allocated FCoE DDP pool\n");
|
||||
e_err("failed to allocated FCoE DDP pool\n");
|
||||
|
||||
spin_lock_init(&fcoe->lock);
|
||||
}
|
||||
|
@ -614,7 +611,7 @@ int ixgbe_fcoe_enable(struct net_device *netdev)
|
|||
if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED)
|
||||
goto out_enable;
|
||||
|
||||
DPRINTK(DRV, INFO, "Enabling FCoE offload features.\n");
|
||||
e_info("Enabling FCoE offload features.\n");
|
||||
if (netif_running(netdev))
|
||||
netdev->netdev_ops->ndo_stop(netdev);
|
||||
|
||||
|
@ -660,7 +657,7 @@ int ixgbe_fcoe_disable(struct net_device *netdev)
|
|||
if (!(adapter->flags & IXGBE_FLAG_FCOE_ENABLED))
|
||||
goto out_disable;
|
||||
|
||||
DPRINTK(DRV, INFO, "Disabling FCoE offload features.\n");
|
||||
e_info("Disabling FCoE offload features.\n");
|
||||
if (netif_running(netdev))
|
||||
netdev->netdev_ops->ndo_stop(netdev);
|
||||
|
||||
|
|
|
@ -642,7 +642,7 @@ static inline bool ixgbe_tx_xon_state(struct ixgbe_adapter *adapter,
|
|||
u32 txoff = IXGBE_TFCS_TXOFF;
|
||||
|
||||
#ifdef CONFIG_IXGBE_DCB
|
||||
if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
|
||||
if (adapter->dcb_cfg.pfc_mode_enable) {
|
||||
int tc;
|
||||
int reg_idx = tx_ring->reg_idx;
|
||||
int dcb_i = adapter->ring_feature[RING_F_DCB].indices;
|
||||
|
@ -696,19 +696,19 @@ static inline bool ixgbe_check_tx_hang(struct ixgbe_adapter *adapter,
|
|||
/* detected Tx unit hang */
|
||||
union ixgbe_adv_tx_desc *tx_desc;
|
||||
tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop);
|
||||
DPRINTK(DRV, ERR, "Detected Tx Unit Hang\n"
|
||||
" Tx Queue <%d>\n"
|
||||
" TDH, TDT <%x>, <%x>\n"
|
||||
" next_to_use <%x>\n"
|
||||
" next_to_clean <%x>\n"
|
||||
"tx_buffer_info[next_to_clean]\n"
|
||||
" time_stamp <%lx>\n"
|
||||
" jiffies <%lx>\n",
|
||||
tx_ring->queue_index,
|
||||
IXGBE_READ_REG(hw, tx_ring->head),
|
||||
IXGBE_READ_REG(hw, tx_ring->tail),
|
||||
tx_ring->next_to_use, eop,
|
||||
tx_ring->tx_buffer_info[eop].time_stamp, jiffies);
|
||||
e_err("Detected Tx Unit Hang\n"
|
||||
" Tx Queue <%d>\n"
|
||||
" TDH, TDT <%x>, <%x>\n"
|
||||
" next_to_use <%x>\n"
|
||||
" next_to_clean <%x>\n"
|
||||
"tx_buffer_info[next_to_clean]\n"
|
||||
" time_stamp <%lx>\n"
|
||||
" jiffies <%lx>\n",
|
||||
tx_ring->queue_index,
|
||||
IXGBE_READ_REG(hw, tx_ring->head),
|
||||
IXGBE_READ_REG(hw, tx_ring->tail),
|
||||
tx_ring->next_to_use, eop,
|
||||
tx_ring->tx_buffer_info[eop].time_stamp, jiffies);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -812,9 +812,8 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
|
|||
if (adapter->detect_tx_hung) {
|
||||
if (ixgbe_check_tx_hang(adapter, tx_ring, i)) {
|
||||
/* schedule immediate reset if we believe we hung */
|
||||
DPRINTK(PROBE, INFO,
|
||||
"tx hang %d detected, resetting adapter\n",
|
||||
adapter->tx_timeout_count + 1);
|
||||
e_info("tx hang %d detected, resetting adapter\n",
|
||||
adapter->tx_timeout_count + 1);
|
||||
ixgbe_tx_timeout(adapter->netdev);
|
||||
}
|
||||
}
|
||||
|
@ -1653,10 +1652,10 @@ static void ixgbe_check_overtemp_task(struct work_struct *work)
|
|||
return;
|
||||
break;
|
||||
}
|
||||
DPRINTK(DRV, ERR, "Network adapter has been stopped because it "
|
||||
"has over heated. Restart the computer. If the problem "
|
||||
"persists, power off the system and replace the "
|
||||
"adapter\n");
|
||||
e_crit("Network adapter has been stopped because it "
|
||||
"has over heated. Restart the computer. If the problem "
|
||||
"persists, power off the system and replace the "
|
||||
"adapter\n");
|
||||
/* write to clear the interrupt */
|
||||
IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP0);
|
||||
}
|
||||
|
@ -1668,7 +1667,7 @@ static void ixgbe_check_fan_failure(struct ixgbe_adapter *adapter, u32 eicr)
|
|||
|
||||
if ((adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) &&
|
||||
(eicr & IXGBE_EICR_GPI_SDP1)) {
|
||||
DPRINTK(PROBE, CRIT, "Fan has stopped, replace the adapter\n");
|
||||
e_crit("Fan has stopped, replace the adapter\n");
|
||||
/* write to clear the interrupt */
|
||||
IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1);
|
||||
}
|
||||
|
@ -2154,9 +2153,8 @@ static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter)
|
|||
handler, 0, adapter->name[vector],
|
||||
adapter->q_vector[vector]);
|
||||
if (err) {
|
||||
DPRINTK(PROBE, ERR,
|
||||
"request_irq failed for MSIX interrupt "
|
||||
"Error: %d\n", err);
|
||||
e_err("request_irq failed for MSIX interrupt: "
|
||||
"Error: %d\n", err);
|
||||
goto free_queue_irqs;
|
||||
}
|
||||
}
|
||||
|
@ -2165,8 +2163,7 @@ static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter)
|
|||
err = request_irq(adapter->msix_entries[vector].vector,
|
||||
ixgbe_msix_lsc, 0, adapter->name[vector], netdev);
|
||||
if (err) {
|
||||
DPRINTK(PROBE, ERR,
|
||||
"request_irq for msix_lsc failed: %d\n", err);
|
||||
e_err("request_irq for msix_lsc failed: %d\n", err);
|
||||
goto free_queue_irqs;
|
||||
}
|
||||
|
||||
|
@ -2352,7 +2349,7 @@ static int ixgbe_request_irq(struct ixgbe_adapter *adapter)
|
|||
}
|
||||
|
||||
if (err)
|
||||
DPRINTK(PROBE, ERR, "request_irq failed, Error %d\n", err);
|
||||
e_err("request_irq failed, Error %d\n", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -2423,7 +2420,7 @@ static void ixgbe_configure_msi_and_legacy(struct ixgbe_adapter *adapter)
|
|||
map_vector_to_rxq(adapter, 0, 0);
|
||||
map_vector_to_txq(adapter, 0, 0);
|
||||
|
||||
DPRINTK(HW, INFO, "Legacy interrupt IVAR setup done\n");
|
||||
e_info("Legacy interrupt IVAR setup done\n");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3257,8 +3254,8 @@ static inline void ixgbe_rx_desc_queue_enable(struct ixgbe_adapter *adapter,
|
|||
msleep(1);
|
||||
}
|
||||
if (k >= IXGBE_MAX_RX_DESC_POLL) {
|
||||
DPRINTK(DRV, ERR, "RXDCTL.ENABLE on Rx queue %d "
|
||||
"not set within the polling period\n", rxr);
|
||||
e_err("RXDCTL.ENABLE on Rx queue %d not set within "
|
||||
"the polling period\n", rxr);
|
||||
}
|
||||
ixgbe_release_rx_desc(&adapter->hw, adapter->rx_ring[rxr],
|
||||
(adapter->rx_ring[rxr]->count - 1));
|
||||
|
@ -3387,8 +3384,7 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
|
|||
} while (--wait_loop &&
|
||||
!(txdctl & IXGBE_TXDCTL_ENABLE));
|
||||
if (!wait_loop)
|
||||
DPRINTK(DRV, ERR, "Could not enable "
|
||||
"Tx Queue %d\n", j);
|
||||
e_err("Could not enable Tx Queue %d\n", j);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3436,8 +3432,7 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
|
|||
if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) {
|
||||
u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
|
||||
if (esdp & IXGBE_ESDP_SDP1)
|
||||
DPRINTK(DRV, CRIT,
|
||||
"Fan has stopped, replace the adapter\n");
|
||||
e_crit("Fan has stopped, replace the adapter\n");
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3466,7 +3461,7 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
|
|||
} else {
|
||||
err = ixgbe_non_sfp_link_config(hw);
|
||||
if (err)
|
||||
DPRINTK(PROBE, ERR, "link_config FAILED %d\n", err);
|
||||
e_err("link_config FAILED %d\n", err);
|
||||
}
|
||||
|
||||
for (i = 0; i < adapter->num_tx_queues; i++)
|
||||
|
@ -3527,19 +3522,19 @@ void ixgbe_reset(struct ixgbe_adapter *adapter)
|
|||
case IXGBE_ERR_SFP_NOT_PRESENT:
|
||||
break;
|
||||
case IXGBE_ERR_MASTER_REQUESTS_PENDING:
|
||||
dev_err(&adapter->pdev->dev, "master disable timed out\n");
|
||||
e_dev_err("master disable timed out\n");
|
||||
break;
|
||||
case IXGBE_ERR_EEPROM_VERSION:
|
||||
/* We are running on a pre-production device, log a warning */
|
||||
dev_warn(&adapter->pdev->dev, "This device is a pre-production "
|
||||
"adapter/LOM. Please be aware there may be issues "
|
||||
"associated with your hardware. If you are "
|
||||
"experiencing problems please contact your Intel or "
|
||||
"hardware representative who provided you with this "
|
||||
"hardware.\n");
|
||||
e_dev_warn("This device is a pre-production adapter/LOM. "
|
||||
"Please be aware there may be issuesassociated with "
|
||||
"your hardware. If you are experiencing problems "
|
||||
"please contact your Intel or hardware "
|
||||
"representative who provided you with this "
|
||||
"hardware.\n");
|
||||
break;
|
||||
default:
|
||||
dev_err(&adapter->pdev->dev, "Hardware Error: %d\n", err);
|
||||
e_dev_err("Hardware Error: %d\n", err);
|
||||
}
|
||||
|
||||
/* reprogram the RAR[0] in case user changed it. */
|
||||
|
@ -3920,12 +3915,12 @@ static inline bool ixgbe_set_fcoe_queues(struct ixgbe_adapter *adapter)
|
|||
adapter->num_tx_queues = 1;
|
||||
#ifdef CONFIG_IXGBE_DCB
|
||||
if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
|
||||
DPRINTK(PROBE, INFO, "FCoE enabled with DCB\n");
|
||||
e_info("FCoE enabled with DCB\n");
|
||||
ixgbe_set_dcb_queues(adapter);
|
||||
}
|
||||
#endif
|
||||
if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) {
|
||||
DPRINTK(PROBE, INFO, "FCoE enabled with RSS\n");
|
||||
e_info("FCoE enabled with RSS\n");
|
||||
if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) ||
|
||||
(adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE))
|
||||
ixgbe_set_fdir_queues(adapter);
|
||||
|
@ -4038,7 +4033,8 @@ static void ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter,
|
|||
* This just means we'll go with either a single MSI
|
||||
* vector or fall back to legacy interrupts.
|
||||
*/
|
||||
DPRINTK(HW, DEBUG, "Unable to allocate MSI-X interrupts\n");
|
||||
netif_printk(adapter, hw, KERN_DEBUG, adapter->netdev,
|
||||
"Unable to allocate MSI-X interrupts\n");
|
||||
adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED;
|
||||
kfree(adapter->msix_entries);
|
||||
adapter->msix_entries = NULL;
|
||||
|
@ -4435,8 +4431,9 @@ static int ixgbe_set_interrupt_capability(struct ixgbe_adapter *adapter)
|
|||
if (!err) {
|
||||
adapter->flags |= IXGBE_FLAG_MSI_ENABLED;
|
||||
} else {
|
||||
DPRINTK(HW, DEBUG, "Unable to allocate MSI interrupt, "
|
||||
"falling back to legacy. Error: %d\n", err);
|
||||
netif_printk(adapter, hw, KERN_DEBUG, adapter->netdev,
|
||||
"Unable to allocate MSI interrupt, "
|
||||
"falling back to legacy. Error: %d\n", err);
|
||||
/* reset err */
|
||||
err = 0;
|
||||
}
|
||||
|
@ -4557,27 +4554,25 @@ int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter)
|
|||
|
||||
err = ixgbe_set_interrupt_capability(adapter);
|
||||
if (err) {
|
||||
DPRINTK(PROBE, ERR, "Unable to setup interrupt capabilities\n");
|
||||
e_dev_err("Unable to setup interrupt capabilities\n");
|
||||
goto err_set_interrupt;
|
||||
}
|
||||
|
||||
err = ixgbe_alloc_q_vectors(adapter);
|
||||
if (err) {
|
||||
DPRINTK(PROBE, ERR, "Unable to allocate memory for queue "
|
||||
"vectors\n");
|
||||
e_dev_err("Unable to allocate memory for queue vectors\n");
|
||||
goto err_alloc_q_vectors;
|
||||
}
|
||||
|
||||
err = ixgbe_alloc_queues(adapter);
|
||||
if (err) {
|
||||
DPRINTK(PROBE, ERR, "Unable to allocate memory for queues\n");
|
||||
e_dev_err("Unable to allocate memory for queues\n");
|
||||
goto err_alloc_queues;
|
||||
}
|
||||
|
||||
DPRINTK(DRV, INFO, "Multiqueue %s: Rx Queue count = %u, "
|
||||
"Tx Queue count = %u\n",
|
||||
(adapter->num_rx_queues > 1) ? "Enabled" :
|
||||
"Disabled", adapter->num_rx_queues, adapter->num_tx_queues);
|
||||
e_dev_info("Multiqueue %s: Rx Queue count = %u, Tx Queue count = %u\n",
|
||||
(adapter->num_rx_queues > 1) ? "Enabled" : "Disabled",
|
||||
adapter->num_rx_queues, adapter->num_tx_queues);
|
||||
|
||||
set_bit(__IXGBE_DOWN, &adapter->state);
|
||||
|
||||
|
@ -4648,15 +4643,13 @@ static void ixgbe_sfp_task(struct work_struct *work)
|
|||
goto reschedule;
|
||||
ret = hw->phy.ops.reset(hw);
|
||||
if (ret == IXGBE_ERR_SFP_NOT_SUPPORTED) {
|
||||
dev_err(&adapter->pdev->dev, "failed to initialize "
|
||||
"because an unsupported SFP+ module type "
|
||||
"was detected.\n"
|
||||
"Reload the driver after installing a "
|
||||
"supported module.\n");
|
||||
e_dev_err("failed to initialize because an unsupported "
|
||||
"SFP+ module type was detected.\n");
|
||||
e_dev_err("Reload the driver after installing a "
|
||||
"supported module.\n");
|
||||
unregister_netdev(adapter->netdev);
|
||||
} else {
|
||||
DPRINTK(PROBE, INFO, "detected SFP+: %d\n",
|
||||
hw->phy.sfp_type);
|
||||
e_info("detected SFP+: %d\n", hw->phy.sfp_type);
|
||||
}
|
||||
/* don't need this routine any more */
|
||||
clear_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state);
|
||||
|
@ -4783,7 +4776,7 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
|
|||
|
||||
/* initialize eeprom parameters */
|
||||
if (ixgbe_init_eeprom_params_generic(hw)) {
|
||||
dev_err(&pdev->dev, "EEPROM initialization failed\n");
|
||||
e_dev_err("EEPROM initialization failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
@ -4836,8 +4829,7 @@ int ixgbe_setup_tx_resources(struct ixgbe_adapter *adapter,
|
|||
err:
|
||||
vfree(tx_ring->tx_buffer_info);
|
||||
tx_ring->tx_buffer_info = NULL;
|
||||
DPRINTK(PROBE, ERR, "Unable to allocate memory for the transmit "
|
||||
"descriptor ring\n");
|
||||
e_err("Unable to allocate memory for the Tx descriptor ring\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
@ -4859,7 +4851,7 @@ static int ixgbe_setup_all_tx_resources(struct ixgbe_adapter *adapter)
|
|||
err = ixgbe_setup_tx_resources(adapter, adapter->tx_ring[i]);
|
||||
if (!err)
|
||||
continue;
|
||||
DPRINTK(PROBE, ERR, "Allocation for Tx Queue %u failed\n", i);
|
||||
e_err("Allocation for Tx Queue %u failed\n", i);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -4884,8 +4876,7 @@ int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter,
|
|||
if (!rx_ring->rx_buffer_info)
|
||||
rx_ring->rx_buffer_info = vmalloc(size);
|
||||
if (!rx_ring->rx_buffer_info) {
|
||||
DPRINTK(PROBE, ERR,
|
||||
"vmalloc allocation failed for the rx desc ring\n");
|
||||
e_err("vmalloc allocation failed for the Rx desc ring\n");
|
||||
goto alloc_failed;
|
||||
}
|
||||
memset(rx_ring->rx_buffer_info, 0, size);
|
||||
|
@ -4898,8 +4889,7 @@ int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter,
|
|||
&rx_ring->dma, GFP_KERNEL);
|
||||
|
||||
if (!rx_ring->desc) {
|
||||
DPRINTK(PROBE, ERR,
|
||||
"Memory allocation failed for the rx desc ring\n");
|
||||
e_err("Memory allocation failed for the Rx desc ring\n");
|
||||
vfree(rx_ring->rx_buffer_info);
|
||||
goto alloc_failed;
|
||||
}
|
||||
|
@ -4932,7 +4922,7 @@ static int ixgbe_setup_all_rx_resources(struct ixgbe_adapter *adapter)
|
|||
err = ixgbe_setup_rx_resources(adapter, adapter->rx_ring[i]);
|
||||
if (!err)
|
||||
continue;
|
||||
DPRINTK(PROBE, ERR, "Allocation for Rx Queue %u failed\n", i);
|
||||
e_err("Allocation for Rx Queue %u failed\n", i);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -5031,8 +5021,7 @@ static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu)
|
|||
if ((new_mtu < 68) || (max_frame > IXGBE_MAX_JUMBO_FRAME_SIZE))
|
||||
return -EINVAL;
|
||||
|
||||
DPRINTK(PROBE, INFO, "changing MTU from %d to %d\n",
|
||||
netdev->mtu, new_mtu);
|
||||
e_info("changing MTU from %d to %d\n", netdev->mtu, new_mtu);
|
||||
/* must set new MTU before calling down or up */
|
||||
netdev->mtu = new_mtu;
|
||||
|
||||
|
@ -5145,8 +5134,7 @@ static int ixgbe_resume(struct pci_dev *pdev)
|
|||
|
||||
err = pci_enable_device_mem(pdev);
|
||||
if (err) {
|
||||
printk(KERN_ERR "ixgbe: Cannot enable PCI device from "
|
||||
"suspend\n");
|
||||
e_dev_err("Cannot enable PCI device from suspend\n");
|
||||
return err;
|
||||
}
|
||||
pci_set_master(pdev);
|
||||
|
@ -5155,8 +5143,7 @@ static int ixgbe_resume(struct pci_dev *pdev)
|
|||
|
||||
err = ixgbe_init_interrupt_scheme(adapter);
|
||||
if (err) {
|
||||
printk(KERN_ERR "ixgbe: Cannot initialize interrupts for "
|
||||
"device\n");
|
||||
e_dev_err("Cannot initialize interrupts for device\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -5282,6 +5269,10 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
|
|||
u32 i, missed_rx = 0, mpc, bprc, lxon, lxoff, xon_off_tot;
|
||||
u64 non_eop_descs = 0, restart_queue = 0;
|
||||
|
||||
if (test_bit(__IXGBE_DOWN, &adapter->state) ||
|
||||
test_bit(__IXGBE_RESETTING, &adapter->state))
|
||||
return;
|
||||
|
||||
if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
|
||||
u64 rsc_count = 0;
|
||||
u64 rsc_flush = 0;
|
||||
|
@ -5512,10 +5503,10 @@ static void ixgbe_sfp_config_module_task(struct work_struct *work)
|
|||
err = hw->phy.ops.identify_sfp(hw);
|
||||
|
||||
if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
|
||||
dev_err(&adapter->pdev->dev, "failed to initialize because "
|
||||
"an unsupported SFP+ module type was detected.\n"
|
||||
"Reload the driver after installing a supported "
|
||||
"module.\n");
|
||||
e_dev_err("failed to initialize because an unsupported SFP+ "
|
||||
"module type was detected.\n");
|
||||
e_dev_err("Reload the driver after installing a supported "
|
||||
"module.\n");
|
||||
unregister_netdev(adapter->netdev);
|
||||
return;
|
||||
}
|
||||
|
@ -5544,8 +5535,8 @@ static void ixgbe_fdir_reinit_task(struct work_struct *work)
|
|||
set_bit(__IXGBE_FDIR_INIT_DONE,
|
||||
&(adapter->tx_ring[i]->reinit_state));
|
||||
} else {
|
||||
DPRINTK(PROBE, ERR, "failed to finish FDIR re-initialization, "
|
||||
"ignored adding FDIR ATR filters\n");
|
||||
e_err("failed to finish FDIR re-initialization, "
|
||||
"ignored adding FDIR ATR filters\n");
|
||||
}
|
||||
/* Done FDIR Re-initialization, enable transmits */
|
||||
netif_tx_start_all_queues(adapter->netdev);
|
||||
|
@ -5616,16 +5607,14 @@ static void ixgbe_watchdog_task(struct work_struct *work)
|
|||
flow_tx = !!(rmcs & IXGBE_RMCS_TFCE_802_3X);
|
||||
}
|
||||
|
||||
printk(KERN_INFO "ixgbe: %s NIC Link is Up %s, "
|
||||
"Flow Control: %s\n",
|
||||
netdev->name,
|
||||
e_info("NIC Link is Up %s, Flow Control: %s\n",
|
||||
(link_speed == IXGBE_LINK_SPEED_10GB_FULL ?
|
||||
"10 Gbps" :
|
||||
(link_speed == IXGBE_LINK_SPEED_1GB_FULL ?
|
||||
"1 Gbps" : "unknown speed")),
|
||||
"10 Gbps" :
|
||||
(link_speed == IXGBE_LINK_SPEED_1GB_FULL ?
|
||||
"1 Gbps" : "unknown speed")),
|
||||
((flow_rx && flow_tx) ? "RX/TX" :
|
||||
(flow_rx ? "RX" :
|
||||
(flow_tx ? "TX" : "None"))));
|
||||
(flow_rx ? "RX" :
|
||||
(flow_tx ? "TX" : "None"))));
|
||||
|
||||
netif_carrier_on(netdev);
|
||||
} else {
|
||||
|
@ -5636,8 +5625,7 @@ static void ixgbe_watchdog_task(struct work_struct *work)
|
|||
adapter->link_up = false;
|
||||
adapter->link_speed = 0;
|
||||
if (netif_carrier_ok(netdev)) {
|
||||
printk(KERN_INFO "ixgbe: %s NIC Link is Down\n",
|
||||
netdev->name);
|
||||
e_info("NIC Link is Down\n");
|
||||
netif_carrier_off(netdev);
|
||||
}
|
||||
}
|
||||
|
@ -5813,9 +5801,8 @@ static bool ixgbe_tx_csum(struct ixgbe_adapter *adapter,
|
|||
break;
|
||||
default:
|
||||
if (unlikely(net_ratelimit())) {
|
||||
DPRINTK(PROBE, WARNING,
|
||||
"partial checksum but proto=%x!\n",
|
||||
skb->protocol);
|
||||
e_warn("partial checksum but "
|
||||
"proto=%x!\n", skb->protocol);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -5926,7 +5913,7 @@ static int ixgbe_tx_map(struct ixgbe_adapter *adapter,
|
|||
return count;
|
||||
|
||||
dma_error:
|
||||
dev_err(&pdev->dev, "TX DMA map failed\n");
|
||||
e_dev_err("TX DMA map failed\n");
|
||||
|
||||
/* clear timestamp and dma mappings for failed tx_buffer_info map */
|
||||
tx_buffer_info->dma = 0;
|
||||
|
@ -6423,8 +6410,7 @@ static void __devinit ixgbe_probe_vf(struct ixgbe_adapter *adapter,
|
|||
adapter->flags |= IXGBE_FLAG_SRIOV_ENABLED;
|
||||
err = pci_enable_sriov(adapter->pdev, adapter->num_vfs);
|
||||
if (err) {
|
||||
DPRINTK(PROBE, ERR,
|
||||
"Failed to enable PCI sriov: %d\n", err);
|
||||
e_err("Failed to enable PCI sriov: %d\n", err);
|
||||
goto err_novfs;
|
||||
}
|
||||
/* If call to enable VFs succeeded then allocate memory
|
||||
|
@ -6448,9 +6434,8 @@ static void __devinit ixgbe_probe_vf(struct ixgbe_adapter *adapter,
|
|||
}
|
||||
|
||||
/* Oh oh */
|
||||
DPRINTK(PROBE, ERR,
|
||||
"Unable to allocate memory for VF "
|
||||
"Data Storage - SRIOV disabled\n");
|
||||
e_err("Unable to allocate memory for VF Data Storage - SRIOV "
|
||||
"disabled\n");
|
||||
pci_disable_sriov(adapter->pdev);
|
||||
|
||||
err_novfs:
|
||||
|
@ -6498,8 +6483,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
|
|||
err = dma_set_coherent_mask(&pdev->dev,
|
||||
DMA_BIT_MASK(32));
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "No usable DMA "
|
||||
"configuration, aborting\n");
|
||||
e_dev_err("No usable DMA configuration, "
|
||||
"aborting\n");
|
||||
goto err_dma;
|
||||
}
|
||||
}
|
||||
|
@ -6509,8 +6494,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
|
|||
err = pci_request_selected_regions(pdev, pci_select_bars(pdev,
|
||||
IORESOURCE_MEM), ixgbe_driver_name);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev,
|
||||
"pci_request_selected_regions failed 0x%x\n", err);
|
||||
e_dev_err("pci_request_selected_regions failed 0x%x\n", err);
|
||||
goto err_pci_reg;
|
||||
}
|
||||
|
||||
|
@ -6621,8 +6605,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
|
|||
if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) {
|
||||
u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
|
||||
if (esdp & IXGBE_ESDP_SDP1)
|
||||
DPRINTK(PROBE, CRIT,
|
||||
"Fan has stopped, replace the adapter\n");
|
||||
e_crit("Fan has stopped, replace the adapter\n");
|
||||
}
|
||||
|
||||
/* reset_hw fills in the perm_addr as well */
|
||||
|
@ -6641,19 +6624,19 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
|
|||
round_jiffies(jiffies + (2 * HZ)));
|
||||
err = 0;
|
||||
} else if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
|
||||
dev_err(&adapter->pdev->dev, "failed to initialize because "
|
||||
"an unsupported SFP+ module type was detected.\n"
|
||||
"Reload the driver after installing a supported "
|
||||
"module.\n");
|
||||
e_dev_err("failed to initialize because an unsupported SFP+ "
|
||||
"module type was detected.\n");
|
||||
e_dev_err("Reload the driver after installing a supported "
|
||||
"module.\n");
|
||||
goto err_sw_init;
|
||||
} else if (err) {
|
||||
dev_err(&adapter->pdev->dev, "HW Init failed: %d\n", err);
|
||||
e_dev_err("HW Init failed: %d\n", err);
|
||||
goto err_sw_init;
|
||||
}
|
||||
|
||||
ixgbe_probe_vf(adapter, ii);
|
||||
|
||||
netdev->features = NETIF_F_SG |
|
||||
netdev->features = NETIF_F_SG |
|
||||
NETIF_F_IP_CSUM |
|
||||
NETIF_F_HW_VLAN_TX |
|
||||
NETIF_F_HW_VLAN_RX |
|
||||
|
@ -6700,7 +6683,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
|
|||
|
||||
/* make sure the EEPROM is good */
|
||||
if (hw->eeprom.ops.validate_checksum(hw, NULL) < 0) {
|
||||
dev_err(&pdev->dev, "The EEPROM Checksum Is Not Valid\n");
|
||||
e_dev_err("The EEPROM Checksum Is Not Valid\n");
|
||||
err = -EIO;
|
||||
goto err_eeprom;
|
||||
}
|
||||
|
@ -6709,7 +6692,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
|
|||
memcpy(netdev->perm_addr, hw->mac.perm_addr, netdev->addr_len);
|
||||
|
||||
if (ixgbe_validate_mac_addr(netdev->perm_addr)) {
|
||||
dev_err(&pdev->dev, "invalid MAC address\n");
|
||||
e_dev_err("invalid MAC address\n");
|
||||
err = -EIO;
|
||||
goto err_eeprom;
|
||||
}
|
||||
|
@ -6744,7 +6727,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
|
|||
hw->mac.ops.get_bus_info(hw);
|
||||
|
||||
/* print bus type/speed/width info */
|
||||
dev_info(&pdev->dev, "(PCI Express:%s:%s) %pM\n",
|
||||
e_dev_info("(PCI Express:%s:%s) %pM\n",
|
||||
((hw->bus.speed == ixgbe_bus_speed_5000) ? "5.0Gb/s":
|
||||
(hw->bus.speed == ixgbe_bus_speed_2500) ? "2.5Gb/s":"Unknown"),
|
||||
((hw->bus.width == ixgbe_bus_width_pcie_x8) ? "Width x8" :
|
||||
|
@ -6754,20 +6737,20 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
|
|||
netdev->dev_addr);
|
||||
ixgbe_read_pba_num_generic(hw, &part_num);
|
||||
if (ixgbe_is_sfp(hw) && hw->phy.sfp_type != ixgbe_sfp_type_not_present)
|
||||
dev_info(&pdev->dev, "MAC: %d, PHY: %d, SFP+: %d, PBA No: %06x-%03x\n",
|
||||
hw->mac.type, hw->phy.type, hw->phy.sfp_type,
|
||||
(part_num >> 8), (part_num & 0xff));
|
||||
e_dev_info("MAC: %d, PHY: %d, SFP+: %d, "
|
||||
"PBA No: %06x-%03x\n",
|
||||
hw->mac.type, hw->phy.type, hw->phy.sfp_type,
|
||||
(part_num >> 8), (part_num & 0xff));
|
||||
else
|
||||
dev_info(&pdev->dev, "MAC: %d, PHY: %d, PBA No: %06x-%03x\n",
|
||||
hw->mac.type, hw->phy.type,
|
||||
(part_num >> 8), (part_num & 0xff));
|
||||
e_dev_info("MAC: %d, PHY: %d, PBA No: %06x-%03x\n",
|
||||
hw->mac.type, hw->phy.type,
|
||||
(part_num >> 8), (part_num & 0xff));
|
||||
|
||||
if (hw->bus.width <= ixgbe_bus_width_pcie_x4) {
|
||||
dev_warn(&pdev->dev, "PCI-Express bandwidth available for "
|
||||
"this card is not sufficient for optimal "
|
||||
"performance.\n");
|
||||
dev_warn(&pdev->dev, "For optimal performance a x8 "
|
||||
"PCI-Express slot is required.\n");
|
||||
e_dev_warn("PCI-Express bandwidth available for this card is "
|
||||
"not sufficient for optimal performance.\n");
|
||||
e_dev_warn("For optimal performance a x8 PCI-Express slot "
|
||||
"is required.\n");
|
||||
}
|
||||
|
||||
/* save off EEPROM version number */
|
||||
|
@ -6778,12 +6761,12 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
|
|||
|
||||
if (err == IXGBE_ERR_EEPROM_VERSION) {
|
||||
/* We are running on a pre-production device, log a warning */
|
||||
dev_warn(&pdev->dev, "This device is a pre-production "
|
||||
"adapter/LOM. Please be aware there may be issues "
|
||||
"associated with your hardware. If you are "
|
||||
"experiencing problems please contact your Intel or "
|
||||
"hardware representative who provided you with this "
|
||||
"hardware.\n");
|
||||
e_dev_warn("This device is a pre-production adapter/LOM. "
|
||||
"Please be aware there may be issues associated "
|
||||
"with your hardware. If you are experiencing "
|
||||
"problems please contact your Intel or hardware "
|
||||
"representative who provided you with this "
|
||||
"hardware.\n");
|
||||
}
|
||||
strcpy(netdev->name, "eth%d");
|
||||
err = register_netdev(netdev);
|
||||
|
@ -6806,8 +6789,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
|
|||
}
|
||||
#endif
|
||||
if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) {
|
||||
DPRINTK(PROBE, INFO, "IOV is enabled with %d VFs\n",
|
||||
adapter->num_vfs);
|
||||
e_info("IOV is enabled with %d VFs\n", adapter->num_vfs);
|
||||
for (i = 0; i < adapter->num_vfs; i++)
|
||||
ixgbe_vf_configuration(pdev, (i | 0x10000000));
|
||||
}
|
||||
|
@ -6815,7 +6797,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
|
|||
/* add san mac addr to netdev */
|
||||
ixgbe_add_sanmac_netdev(netdev);
|
||||
|
||||
dev_info(&pdev->dev, "Intel(R) 10 Gigabit Network Connection\n");
|
||||
e_dev_info("Intel(R) 10 Gigabit Network Connection\n");
|
||||
cards_found++;
|
||||
return 0;
|
||||
|
||||
|
@ -6905,7 +6887,7 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev)
|
|||
pci_release_selected_regions(pdev, pci_select_bars(pdev,
|
||||
IORESOURCE_MEM));
|
||||
|
||||
DPRINTK(PROBE, INFO, "complete\n");
|
||||
e_dev_info("complete\n");
|
||||
|
||||
free_netdev(netdev);
|
||||
|
||||
|
@ -6955,8 +6937,7 @@ static pci_ers_result_t ixgbe_io_slot_reset(struct pci_dev *pdev)
|
|||
int err;
|
||||
|
||||
if (pci_enable_device_mem(pdev)) {
|
||||
DPRINTK(PROBE, ERR,
|
||||
"Cannot re-enable PCI device after reset.\n");
|
||||
e_err("Cannot re-enable PCI device after reset.\n");
|
||||
result = PCI_ERS_RESULT_DISCONNECT;
|
||||
} else {
|
||||
pci_set_master(pdev);
|
||||
|
@ -6972,8 +6953,8 @@ static pci_ers_result_t ixgbe_io_slot_reset(struct pci_dev *pdev)
|
|||
|
||||
err = pci_cleanup_aer_uncorrect_error_status(pdev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev,
|
||||
"pci_cleanup_aer_uncorrect_error_status failed 0x%0x\n", err);
|
||||
e_dev_err("pci_cleanup_aer_uncorrect_error_status "
|
||||
"failed 0x%0x\n", err);
|
||||
/* non-fatal, continue */
|
||||
}
|
||||
|
||||
|
@ -6994,7 +6975,7 @@ static void ixgbe_io_resume(struct pci_dev *pdev)
|
|||
|
||||
if (netif_running(netdev)) {
|
||||
if (ixgbe_up(adapter)) {
|
||||
DPRINTK(PROBE, INFO, "ixgbe_up failed after reset\n");
|
||||
e_info("ixgbe_up failed after reset\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -7030,10 +7011,9 @@ static struct pci_driver ixgbe_driver = {
|
|||
static int __init ixgbe_init_module(void)
|
||||
{
|
||||
int ret;
|
||||
printk(KERN_INFO "%s: %s - version %s\n", ixgbe_driver_name,
|
||||
ixgbe_driver_string, ixgbe_driver_version);
|
||||
|
||||
printk(KERN_INFO "%s: %s\n", ixgbe_driver_name, ixgbe_copyright);
|
||||
pr_info("%s - version %s\n", ixgbe_driver_string,
|
||||
ixgbe_driver_version);
|
||||
pr_info("%s\n", ixgbe_copyright);
|
||||
|
||||
#ifdef CONFIG_IXGBE_DCA
|
||||
dca_register_notify(&dca_notifier);
|
||||
|
@ -7072,18 +7052,17 @@ static int ixgbe_notify_dca(struct notifier_block *nb, unsigned long event,
|
|||
}
|
||||
|
||||
#endif /* CONFIG_IXGBE_DCA */
|
||||
#ifdef DEBUG
|
||||
|
||||
/**
|
||||
* ixgbe_get_hw_dev_name - return device name string
|
||||
* ixgbe_get_hw_dev return device
|
||||
* used by hardware layer to print debugging information
|
||||
**/
|
||||
char *ixgbe_get_hw_dev_name(struct ixgbe_hw *hw)
|
||||
struct net_device *ixgbe_get_hw_dev(struct ixgbe_hw *hw)
|
||||
{
|
||||
struct ixgbe_adapter *adapter = hw->back;
|
||||
return adapter->netdev->name;
|
||||
return adapter->netdev;
|
||||
}
|
||||
|
||||
#endif
|
||||
module_exit(ixgbe_exit_module);
|
||||
|
||||
/* ixgbe_main.c */
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
|
@ -174,7 +173,7 @@ int ixgbe_set_vf_mac(struct ixgbe_adapter *adapter,
|
|||
adapter->vfinfo[vf].rar = hw->mac.ops.set_rar(hw, vf + 1, mac_addr,
|
||||
vf, IXGBE_RAH_AV);
|
||||
if (adapter->vfinfo[vf].rar < 0) {
|
||||
DPRINTK(DRV, ERR, "Could not set MAC Filter for VF %d\n", vf);
|
||||
e_err("Could not set MAC Filter for VF %d\n", vf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -194,11 +193,7 @@ int ixgbe_vf_configuration(struct pci_dev *pdev, unsigned int event_mask)
|
|||
|
||||
if (enable) {
|
||||
random_ether_addr(vf_mac_addr);
|
||||
DPRINTK(PROBE, INFO, "IOV: VF %d is enabled "
|
||||
"mac %02X:%02X:%02X:%02X:%02X:%02X\n",
|
||||
vfn,
|
||||
vf_mac_addr[0], vf_mac_addr[1], vf_mac_addr[2],
|
||||
vf_mac_addr[3], vf_mac_addr[4], vf_mac_addr[5]);
|
||||
e_info("IOV: VF %d is enabled MAC %pM\n", vfn, vf_mac_addr);
|
||||
/*
|
||||
* Store away the VF "permananet" MAC address, it will ask
|
||||
* for it later.
|
||||
|
@ -243,7 +238,7 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
|
|||
retval = ixgbe_read_mbx(hw, msgbuf, mbx_size, vf);
|
||||
|
||||
if (retval)
|
||||
printk(KERN_ERR "Error receiving message from VF\n");
|
||||
pr_err("Error receiving message from VF\n");
|
||||
|
||||
/* this is a message we already processed, do nothing */
|
||||
if (msgbuf[0] & (IXGBE_VT_MSGTYPE_ACK | IXGBE_VT_MSGTYPE_NACK))
|
||||
|
@ -257,7 +252,7 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
|
|||
if (msgbuf[0] == IXGBE_VF_RESET) {
|
||||
unsigned char *vf_mac = adapter->vfinfo[vf].vf_mac_addresses;
|
||||
u8 *addr = (u8 *)(&msgbuf[1]);
|
||||
DPRINTK(PROBE, INFO, "VF Reset msg received from vf %d\n", vf);
|
||||
e_info("VF Reset msg received from vf %d\n", vf);
|
||||
adapter->vfinfo[vf].clear_to_send = false;
|
||||
ixgbe_vf_reset_msg(adapter, vf);
|
||||
adapter->vfinfo[vf].clear_to_send = true;
|
||||
|
@ -310,7 +305,7 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
|
|||
retval = ixgbe_set_vf_vlan(adapter, add, vid, vf);
|
||||
break;
|
||||
default:
|
||||
DPRINTK(DRV, ERR, "Unhandled Msg %8.8x\n", msgbuf[0]);
|
||||
e_err("Unhandled Msg %8.8x\n", msgbuf[0]);
|
||||
retval = IXGBE_ERR_MBX;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -2609,6 +2609,7 @@ struct ixgbe_info {
|
|||
#define IXGBE_ERR_EEPROM_VERSION -24
|
||||
#define IXGBE_ERR_NO_SPACE -25
|
||||
#define IXGBE_ERR_OVERTEMP -26
|
||||
#define IXGBE_ERR_RAR_INDEX -27
|
||||
#define IXGBE_NOT_IMPLEMENTED 0x7FFFFFFF
|
||||
|
||||
#endif /* _IXGBE_TYPE_H_ */
|
||||
|
|
|
@ -3411,6 +3411,7 @@ static int __devinit ixgbevf_probe(struct pci_dev *pdev,
|
|||
netdev->features |= NETIF_F_IPV6_CSUM;
|
||||
netdev->features |= NETIF_F_TSO;
|
||||
netdev->features |= NETIF_F_TSO6;
|
||||
netdev->features |= NETIF_F_GRO;
|
||||
netdev->vlan_features |= NETIF_F_TSO;
|
||||
netdev->vlan_features |= NETIF_F_TSO6;
|
||||
netdev->vlan_features |= NETIF_F_IP_CSUM;
|
||||
|
|
|
@ -135,6 +135,7 @@ struct korina_private {
|
|||
struct napi_struct napi;
|
||||
struct timer_list media_check_timer;
|
||||
struct mii_if_info mii_if;
|
||||
struct work_struct restart_task;
|
||||
struct net_device *dev;
|
||||
int phy_addr;
|
||||
};
|
||||
|
@ -375,7 +376,7 @@ static int korina_rx(struct net_device *dev, int limit)
|
|||
if (devcs & ETH_RX_LE)
|
||||
dev->stats.rx_length_errors++;
|
||||
if (devcs & ETH_RX_OVR)
|
||||
dev->stats.rx_over_errors++;
|
||||
dev->stats.rx_fifo_errors++;
|
||||
if (devcs & ETH_RX_CV)
|
||||
dev->stats.rx_frame_errors++;
|
||||
if (devcs & ETH_RX_CES)
|
||||
|
@ -764,10 +765,9 @@ static int korina_alloc_ring(struct net_device *dev)
|
|||
|
||||
/* Initialize the receive descriptors */
|
||||
for (i = 0; i < KORINA_NUM_RDS; i++) {
|
||||
skb = dev_alloc_skb(KORINA_RBSIZE + 2);
|
||||
skb = netdev_alloc_skb_ip_align(dev, KORINA_RBSIZE);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
skb_reserve(skb, 2);
|
||||
lp->rx_skb[i] = skb;
|
||||
lp->rd_ring[i].control = DMA_DESC_IOD |
|
||||
DMA_COUNT(KORINA_RBSIZE);
|
||||
|
@ -890,12 +890,12 @@ static int korina_init(struct net_device *dev)
|
|||
|
||||
/*
|
||||
* Restart the RC32434 ethernet controller.
|
||||
* FIXME: check the return status where we call it
|
||||
*/
|
||||
static int korina_restart(struct net_device *dev)
|
||||
static void korina_restart_task(struct work_struct *work)
|
||||
{
|
||||
struct korina_private *lp = netdev_priv(dev);
|
||||
int ret;
|
||||
struct korina_private *lp = container_of(work,
|
||||
struct korina_private, restart_task);
|
||||
struct net_device *dev = lp->dev;
|
||||
|
||||
/*
|
||||
* Disable interrupts
|
||||
|
@ -916,10 +916,9 @@ static int korina_restart(struct net_device *dev)
|
|||
|
||||
napi_disable(&lp->napi);
|
||||
|
||||
ret = korina_init(dev);
|
||||
if (ret < 0) {
|
||||
if (korina_init(dev) < 0) {
|
||||
printk(KERN_ERR "%s: cannot restart device\n", dev->name);
|
||||
return ret;
|
||||
return;
|
||||
}
|
||||
korina_multicast_list(dev);
|
||||
|
||||
|
@ -927,8 +926,6 @@ static int korina_restart(struct net_device *dev)
|
|||
enable_irq(lp->ovr_irq);
|
||||
enable_irq(lp->tx_irq);
|
||||
enable_irq(lp->rx_irq);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void korina_clear_and_restart(struct net_device *dev, u32 value)
|
||||
|
@ -937,7 +934,7 @@ static void korina_clear_and_restart(struct net_device *dev, u32 value)
|
|||
|
||||
netif_stop_queue(dev);
|
||||
writel(value, &lp->eth_regs->ethintfc);
|
||||
korina_restart(dev);
|
||||
schedule_work(&lp->restart_task);
|
||||
}
|
||||
|
||||
/* Ethernet Tx Underflow interrupt */
|
||||
|
@ -962,11 +959,8 @@ static irqreturn_t korina_und_interrupt(int irq, void *dev_id)
|
|||
static void korina_tx_timeout(struct net_device *dev)
|
||||
{
|
||||
struct korina_private *lp = netdev_priv(dev);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&lp->lock, flags);
|
||||
korina_restart(dev);
|
||||
spin_unlock_irqrestore(&lp->lock, flags);
|
||||
schedule_work(&lp->restart_task);
|
||||
}
|
||||
|
||||
/* Ethernet Rx Overflow interrupt */
|
||||
|
@ -1086,6 +1080,8 @@ static int korina_close(struct net_device *dev)
|
|||
|
||||
napi_disable(&lp->napi);
|
||||
|
||||
cancel_work_sync(&lp->restart_task);
|
||||
|
||||
free_irq(lp->rx_irq, dev);
|
||||
free_irq(lp->tx_irq, dev);
|
||||
free_irq(lp->ovr_irq, dev);
|
||||
|
@ -1198,6 +1194,8 @@ static int korina_probe(struct platform_device *pdev)
|
|||
}
|
||||
setup_timer(&lp->media_check_timer, korina_poll_media, (unsigned long) dev);
|
||||
|
||||
INIT_WORK(&lp->restart_task, korina_restart_task);
|
||||
|
||||
printk(KERN_INFO "%s: " DRV_NAME "-" DRV_VERSION " " DRV_RELDATE "\n",
|
||||
dev->name);
|
||||
out:
|
||||
|
|
|
@ -4854,7 +4854,7 @@ static inline void copy_old_skb(struct sk_buff *old, struct sk_buff *skb)
|
|||
*
|
||||
* Return 0 if successful; otherwise an error code indicating failure.
|
||||
*/
|
||||
static int netdev_tx(struct sk_buff *skb, struct net_device *dev)
|
||||
static netdev_tx_t netdev_tx(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct dev_priv *priv = netdev_priv(dev);
|
||||
struct dev_info *hw_priv = priv->adapter;
|
||||
|
@ -6863,6 +6863,7 @@ static const struct net_device_ops netdev_ops = {
|
|||
.ndo_tx_timeout = netdev_tx_timeout,
|
||||
.ndo_change_mtu = netdev_change_mtu,
|
||||
.ndo_set_mac_address = netdev_set_mac_address,
|
||||
.ndo_validate_addr = eth_validate_addr,
|
||||
.ndo_do_ioctl = netdev_ioctl,
|
||||
.ndo_set_rx_mode = netdev_set_rx_mode,
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
|
|
|
@ -60,11 +60,51 @@
|
|||
#include <net/net_namespace.h>
|
||||
|
||||
struct pcpu_lstats {
|
||||
unsigned long packets;
|
||||
unsigned long bytes;
|
||||
u64 packets;
|
||||
u64 bytes;
|
||||
#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
|
||||
seqcount_t seq;
|
||||
#endif
|
||||
unsigned long drops;
|
||||
};
|
||||
|
||||
#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
|
||||
static void inline lstats_update_begin(struct pcpu_lstats *lstats)
|
||||
{
|
||||
write_seqcount_begin(&lstats->seq);
|
||||
}
|
||||
static void inline lstats_update_end(struct pcpu_lstats *lstats)
|
||||
{
|
||||
write_seqcount_end(&lstats->seq);
|
||||
}
|
||||
static void inline lstats_fetch_and_add(u64 *packets, u64 *bytes, const struct pcpu_lstats *lstats)
|
||||
{
|
||||
u64 tpackets, tbytes;
|
||||
unsigned int seq;
|
||||
|
||||
do {
|
||||
seq = read_seqcount_begin(&lstats->seq);
|
||||
tpackets = lstats->packets;
|
||||
tbytes = lstats->bytes;
|
||||
} while (read_seqcount_retry(&lstats->seq, seq));
|
||||
|
||||
*packets += tpackets;
|
||||
*bytes += tbytes;
|
||||
}
|
||||
#else
|
||||
static void inline lstats_update_begin(struct pcpu_lstats *lstats)
|
||||
{
|
||||
}
|
||||
static void inline lstats_update_end(struct pcpu_lstats *lstats)
|
||||
{
|
||||
}
|
||||
static void inline lstats_fetch_and_add(u64 *packets, u64 *bytes, const struct pcpu_lstats *lstats)
|
||||
{
|
||||
*packets += lstats->packets;
|
||||
*bytes += lstats->bytes;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The higher levels take care of making this non-reentrant (it's
|
||||
* called with bh's disabled).
|
||||
|
@ -86,21 +126,23 @@ static netdev_tx_t loopback_xmit(struct sk_buff *skb,
|
|||
|
||||
len = skb->len;
|
||||
if (likely(netif_rx(skb) == NET_RX_SUCCESS)) {
|
||||
lstats_update_begin(lb_stats);
|
||||
lb_stats->bytes += len;
|
||||
lb_stats->packets++;
|
||||
lstats_update_end(lb_stats);
|
||||
} else
|
||||
lb_stats->drops++;
|
||||
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
static struct net_device_stats *loopback_get_stats(struct net_device *dev)
|
||||
static struct rtnl_link_stats64 *loopback_get_stats64(struct net_device *dev)
|
||||
{
|
||||
const struct pcpu_lstats __percpu *pcpu_lstats;
|
||||
struct net_device_stats *stats = &dev->stats;
|
||||
unsigned long bytes = 0;
|
||||
unsigned long packets = 0;
|
||||
unsigned long drops = 0;
|
||||
struct rtnl_link_stats64 *stats = &dev->stats64;
|
||||
u64 bytes = 0;
|
||||
u64 packets = 0;
|
||||
u64 drops = 0;
|
||||
int i;
|
||||
|
||||
pcpu_lstats = (void __percpu __force *)dev->ml_priv;
|
||||
|
@ -108,8 +150,7 @@ static struct net_device_stats *loopback_get_stats(struct net_device *dev)
|
|||
const struct pcpu_lstats *lb_stats;
|
||||
|
||||
lb_stats = per_cpu_ptr(pcpu_lstats, i);
|
||||
bytes += lb_stats->bytes;
|
||||
packets += lb_stats->packets;
|
||||
lstats_fetch_and_add(&packets, &bytes, lb_stats);
|
||||
drops += lb_stats->drops;
|
||||
}
|
||||
stats->rx_packets = packets;
|
||||
|
@ -158,7 +199,7 @@ static void loopback_dev_free(struct net_device *dev)
|
|||
static const struct net_device_ops loopback_ops = {
|
||||
.ndo_init = loopback_dev_init,
|
||||
.ndo_start_xmit= loopback_xmit,
|
||||
.ndo_get_stats = loopback_get_stats,
|
||||
.ndo_get_stats64 = loopback_get_stats64,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -157,6 +157,8 @@ static void dayna_block_output(struct net_device *dev, int count,
|
|||
#define memcpy_fromio(a, b, c) memcpy((a), (void *)(b), (c))
|
||||
#define memcpy_toio(a, b, c) memcpy((void *)(a), (b), (c))
|
||||
|
||||
#define memcmp_withio(a, b, c) memcmp((a), (void *)(b), (c))
|
||||
|
||||
/* Slow Sane (16-bit chunk memory read/write) Cabletron uses this */
|
||||
static void slow_sane_get_8390_hdr(struct net_device *dev,
|
||||
struct e8390_pkt_hdr *hdr, int ring_page);
|
||||
|
@ -164,8 +166,8 @@ static void slow_sane_block_input(struct net_device *dev, int count,
|
|||
struct sk_buff *skb, int ring_offset);
|
||||
static void slow_sane_block_output(struct net_device *dev, int count,
|
||||
const unsigned char *buf, int start_page);
|
||||
static void word_memcpy_tocard(void *tp, const void *fp, int count);
|
||||
static void word_memcpy_fromcard(void *tp, const void *fp, int count);
|
||||
static void word_memcpy_tocard(unsigned long tp, const void *fp, int count);
|
||||
static void word_memcpy_fromcard(void *tp, unsigned long fp, int count);
|
||||
|
||||
static enum mac8390_type __init mac8390_ident(struct nubus_dev *dev)
|
||||
{
|
||||
|
@ -245,9 +247,9 @@ static enum mac8390_access __init mac8390_testio(volatile unsigned long membase)
|
|||
unsigned long outdata = 0xA5A0B5B0;
|
||||
unsigned long indata = 0x00000000;
|
||||
/* Try writing 32 bits */
|
||||
memcpy(membase, &outdata, 4);
|
||||
memcpy_toio(membase, &outdata, 4);
|
||||
/* Now compare them */
|
||||
if (memcmp((char *)&outdata, (char *)membase, 4) == 0)
|
||||
if (memcmp_withio(&outdata, membase, 4) == 0)
|
||||
return ACCESS_32;
|
||||
/* Write 16 bit output */
|
||||
word_memcpy_tocard(membase, &outdata, 4);
|
||||
|
@ -554,7 +556,7 @@ static int __init mac8390_initdev(struct net_device *dev,
|
|||
case MAC8390_APPLE:
|
||||
switch (mac8390_testio(dev->mem_start)) {
|
||||
case ACCESS_UNKNOWN:
|
||||
pr_info("Don't know how to access card memory!\n");
|
||||
pr_err("Don't know how to access card memory!\n");
|
||||
return -ENODEV;
|
||||
break;
|
||||
|
||||
|
@ -641,12 +643,13 @@ static int __init mac8390_initdev(struct net_device *dev,
|
|||
|
||||
static int mac8390_open(struct net_device *dev)
|
||||
{
|
||||
int err;
|
||||
|
||||
__ei_open(dev);
|
||||
if (request_irq(dev->irq, __ei_interrupt, 0, "8390 Ethernet", dev)) {
|
||||
pr_info("%s: unable to get IRQ %d.\n", dev->name, dev->irq);
|
||||
return -EAGAIN;
|
||||
}
|
||||
return 0;
|
||||
err = request_irq(dev->irq, __ei_interrupt, 0, "8390 Ethernet", dev);
|
||||
if (err)
|
||||
pr_err("%s: unable to get IRQ %d\n", dev->name, dev->irq);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mac8390_close(struct net_device *dev)
|
||||
|
@ -731,7 +734,7 @@ static void sane_get_8390_hdr(struct net_device *dev,
|
|||
struct e8390_pkt_hdr *hdr, int ring_page)
|
||||
{
|
||||
unsigned long hdr_start = (ring_page - WD_START_PG)<<8;
|
||||
memcpy_fromio((void *)hdr, (char *)dev->mem_start + hdr_start, 4);
|
||||
memcpy_fromio(hdr, dev->mem_start + hdr_start, 4);
|
||||
/* Fix endianness */
|
||||
hdr->count = swab16(hdr->count);
|
||||
}
|
||||
|
@ -745,14 +748,13 @@ static void sane_block_input(struct net_device *dev, int count,
|
|||
if (xfer_start + count > ei_status.rmem_end) {
|
||||
/* We must wrap the input move. */
|
||||
int semi_count = ei_status.rmem_end - xfer_start;
|
||||
memcpy_fromio(skb->data, (char *)dev->mem_start + xfer_base,
|
||||
memcpy_fromio(skb->data, dev->mem_start + xfer_base,
|
||||
semi_count);
|
||||
count -= semi_count;
|
||||
memcpy_toio(skb->data + semi_count,
|
||||
(char *)ei_status.rmem_start, count);
|
||||
} else {
|
||||
memcpy_fromio(skb->data, (char *)dev->mem_start + xfer_base,
|
||||
memcpy_fromio(skb->data + semi_count, ei_status.rmem_start,
|
||||
count);
|
||||
} else {
|
||||
memcpy_fromio(skb->data, dev->mem_start + xfer_base, count);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -761,7 +763,7 @@ static void sane_block_output(struct net_device *dev, int count,
|
|||
{
|
||||
long shmem = (start_page - WD_START_PG)<<8;
|
||||
|
||||
memcpy_toio((char *)dev->mem_start + shmem, buf, count);
|
||||
memcpy_toio(dev->mem_start + shmem, buf, count);
|
||||
}
|
||||
|
||||
/* dayna block input/output */
|
||||
|
@ -812,7 +814,7 @@ static void slow_sane_get_8390_hdr(struct net_device *dev,
|
|||
int ring_page)
|
||||
{
|
||||
unsigned long hdr_start = (ring_page - WD_START_PG)<<8;
|
||||
word_memcpy_fromcard(hdr, (char *)dev->mem_start + hdr_start, 4);
|
||||
word_memcpy_fromcard(hdr, dev->mem_start + hdr_start, 4);
|
||||
/* Register endianism - fix here rather than 8390.c */
|
||||
hdr->count = (hdr->count&0xFF)<<8|(hdr->count>>8);
|
||||
}
|
||||
|
@ -826,15 +828,14 @@ static void slow_sane_block_input(struct net_device *dev, int count,
|
|||
if (xfer_start + count > ei_status.rmem_end) {
|
||||
/* We must wrap the input move. */
|
||||
int semi_count = ei_status.rmem_end - xfer_start;
|
||||
word_memcpy_fromcard(skb->data,
|
||||
(char *)dev->mem_start + xfer_base,
|
||||
word_memcpy_fromcard(skb->data, dev->mem_start + xfer_base,
|
||||
semi_count);
|
||||
count -= semi_count;
|
||||
word_memcpy_fromcard(skb->data + semi_count,
|
||||
(char *)ei_status.rmem_start, count);
|
||||
ei_status.rmem_start, count);
|
||||
} else {
|
||||
word_memcpy_fromcard(skb->data,
|
||||
(char *)dev->mem_start + xfer_base, count);
|
||||
word_memcpy_fromcard(skb->data, dev->mem_start + xfer_base,
|
||||
count);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -843,12 +844,12 @@ static void slow_sane_block_output(struct net_device *dev, int count,
|
|||
{
|
||||
long shmem = (start_page - WD_START_PG)<<8;
|
||||
|
||||
word_memcpy_tocard((char *)dev->mem_start + shmem, buf, count);
|
||||
word_memcpy_tocard(dev->mem_start + shmem, buf, count);
|
||||
}
|
||||
|
||||
static void word_memcpy_tocard(void *tp, const void *fp, int count)
|
||||
static void word_memcpy_tocard(unsigned long tp, const void *fp, int count)
|
||||
{
|
||||
volatile unsigned short *to = tp;
|
||||
volatile unsigned short *to = (void *)tp;
|
||||
const unsigned short *from = fp;
|
||||
|
||||
count++;
|
||||
|
@ -858,10 +859,10 @@ static void word_memcpy_tocard(void *tp, const void *fp, int count)
|
|||
*to++ = *from++;
|
||||
}
|
||||
|
||||
static void word_memcpy_fromcard(void *tp, const void *fp, int count)
|
||||
static void word_memcpy_fromcard(void *tp, unsigned long fp, int count)
|
||||
{
|
||||
unsigned short *to = tp;
|
||||
const volatile unsigned short *from = fp;
|
||||
const volatile unsigned short *from = (const void *)fp;
|
||||
|
||||
count++;
|
||||
count /= 2;
|
||||
|
|
|
@ -37,6 +37,7 @@ struct macvlan_port {
|
|||
struct net_device *dev;
|
||||
struct hlist_head vlan_hash[MACVLAN_HASH_SIZE];
|
||||
struct list_head vlans;
|
||||
struct rcu_head rcu;
|
||||
};
|
||||
|
||||
static struct macvlan_dev *macvlan_hash_lookup(const struct macvlan_port *port,
|
||||
|
@ -145,15 +146,16 @@ static void macvlan_broadcast(struct sk_buff *skb,
|
|||
}
|
||||
|
||||
/* called under rcu_read_lock() from netif_receive_skb */
|
||||
static struct sk_buff *macvlan_handle_frame(struct macvlan_port *port,
|
||||
struct sk_buff *skb)
|
||||
static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb)
|
||||
{
|
||||
struct macvlan_port *port;
|
||||
const struct ethhdr *eth = eth_hdr(skb);
|
||||
const struct macvlan_dev *vlan;
|
||||
const struct macvlan_dev *src;
|
||||
struct net_device *dev;
|
||||
unsigned int len;
|
||||
|
||||
port = rcu_dereference(skb->dev->macvlan_port);
|
||||
if (is_multicast_ether_addr(eth->h_dest)) {
|
||||
src = macvlan_hash_lookup(port, eth->h_source);
|
||||
if (!src)
|
||||
|
@ -515,6 +517,7 @@ static int macvlan_port_create(struct net_device *dev)
|
|||
{
|
||||
struct macvlan_port *port;
|
||||
unsigned int i;
|
||||
int err;
|
||||
|
||||
if (dev->type != ARPHRD_ETHER || dev->flags & IFF_LOOPBACK)
|
||||
return -EINVAL;
|
||||
|
@ -528,16 +531,31 @@ static int macvlan_port_create(struct net_device *dev)
|
|||
for (i = 0; i < MACVLAN_HASH_SIZE; i++)
|
||||
INIT_HLIST_HEAD(&port->vlan_hash[i]);
|
||||
rcu_assign_pointer(dev->macvlan_port, port);
|
||||
return 0;
|
||||
|
||||
err = netdev_rx_handler_register(dev, macvlan_handle_frame);
|
||||
if (err) {
|
||||
rcu_assign_pointer(dev->macvlan_port, NULL);
|
||||
kfree(port);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void macvlan_port_rcu_free(struct rcu_head *head)
|
||||
{
|
||||
struct macvlan_port *port;
|
||||
|
||||
port = container_of(head, struct macvlan_port, rcu);
|
||||
kfree(port);
|
||||
}
|
||||
|
||||
static void macvlan_port_destroy(struct net_device *dev)
|
||||
{
|
||||
struct macvlan_port *port = dev->macvlan_port;
|
||||
|
||||
netdev_rx_handler_unregister(dev);
|
||||
rcu_assign_pointer(dev->macvlan_port, NULL);
|
||||
synchronize_rcu();
|
||||
kfree(port);
|
||||
call_rcu(&port->rcu, macvlan_port_rcu_free);
|
||||
}
|
||||
|
||||
static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[])
|
||||
|
@ -767,14 +785,12 @@ static int __init macvlan_init_module(void)
|
|||
int err;
|
||||
|
||||
register_netdevice_notifier(&macvlan_notifier_block);
|
||||
macvlan_handle_frame_hook = macvlan_handle_frame;
|
||||
|
||||
err = macvlan_link_register(&macvlan_link_ops);
|
||||
if (err < 0)
|
||||
goto err1;
|
||||
return 0;
|
||||
err1:
|
||||
macvlan_handle_frame_hook = NULL;
|
||||
unregister_netdevice_notifier(&macvlan_notifier_block);
|
||||
return err;
|
||||
}
|
||||
|
@ -782,7 +798,6 @@ static int __init macvlan_init_module(void)
|
|||
static void __exit macvlan_cleanup_module(void)
|
||||
{
|
||||
rtnl_link_unregister(&macvlan_link_ops);
|
||||
macvlan_handle_frame_hook = NULL;
|
||||
unregister_netdevice_notifier(&macvlan_notifier_block);
|
||||
}
|
||||
|
||||
|
|
|
@ -110,7 +110,7 @@ struct mlx4_eqe {
|
|||
u32 raw[6];
|
||||
struct {
|
||||
__be32 cqn;
|
||||
} __attribute__((packed)) comp;
|
||||
} __packed comp;
|
||||
struct {
|
||||
u16 reserved1;
|
||||
__be16 token;
|
||||
|
@ -118,27 +118,27 @@ struct mlx4_eqe {
|
|||
u8 reserved3[3];
|
||||
u8 status;
|
||||
__be64 out_param;
|
||||
} __attribute__((packed)) cmd;
|
||||
} __packed cmd;
|
||||
struct {
|
||||
__be32 qpn;
|
||||
} __attribute__((packed)) qp;
|
||||
} __packed qp;
|
||||
struct {
|
||||
__be32 srqn;
|
||||
} __attribute__((packed)) srq;
|
||||
} __packed srq;
|
||||
struct {
|
||||
__be32 cqn;
|
||||
u32 reserved1;
|
||||
u8 reserved2[3];
|
||||
u8 syndrome;
|
||||
} __attribute__((packed)) cq_err;
|
||||
} __packed cq_err;
|
||||
struct {
|
||||
u32 reserved1[2];
|
||||
__be32 port;
|
||||
} __attribute__((packed)) port_change;
|
||||
} __packed port_change;
|
||||
} event;
|
||||
u8 reserved3[3];
|
||||
u8 owner;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
static void eq_set_ci(struct mlx4_eq *eq, int req_not)
|
||||
{
|
||||
|
|
|
@ -58,7 +58,7 @@ struct mlx4_mpt_entry {
|
|||
__be32 mtt_sz;
|
||||
__be32 entity_size;
|
||||
__be32 first_byte_offset;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
#define MLX4_MPT_FLAG_SW_OWNS (0xfUL << 28)
|
||||
#define MLX4_MPT_FLAG_FREE (0x3UL << 28)
|
||||
|
|
|
@ -53,6 +53,9 @@
|
|||
|
||||
#define MII_LXT971_ISR 19 /* Interrupt Status Register */
|
||||
|
||||
/* register definitions for the 973 */
|
||||
#define MII_LXT973_PCR 16 /* Port Configuration Register */
|
||||
#define PCR_FIBER_SELECT 1
|
||||
|
||||
MODULE_DESCRIPTION("Intel LXT PHY driver");
|
||||
MODULE_AUTHOR("Andy Fleming");
|
||||
|
@ -119,6 +122,33 @@ static int lxt971_config_intr(struct phy_device *phydev)
|
|||
return err;
|
||||
}
|
||||
|
||||
static int lxt973_probe(struct phy_device *phydev)
|
||||
{
|
||||
int val = phy_read(phydev, MII_LXT973_PCR);
|
||||
|
||||
if (val & PCR_FIBER_SELECT) {
|
||||
/*
|
||||
* If fiber is selected, then the only correct setting
|
||||
* is 100Mbps, full duplex, and auto negotiation off.
|
||||
*/
|
||||
val = phy_read(phydev, MII_BMCR);
|
||||
val |= (BMCR_SPEED100 | BMCR_FULLDPLX);
|
||||
val &= ~BMCR_ANENABLE;
|
||||
phy_write(phydev, MII_BMCR, val);
|
||||
/* Remember that the port is in fiber mode. */
|
||||
phydev->priv = lxt973_probe;
|
||||
} else {
|
||||
phydev->priv = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lxt973_config_aneg(struct phy_device *phydev)
|
||||
{
|
||||
/* Do nothing if port is in fiber mode. */
|
||||
return phydev->priv ? 0 : genphy_config_aneg(phydev);
|
||||
}
|
||||
|
||||
static struct phy_driver lxt970_driver = {
|
||||
.phy_id = 0x78100000,
|
||||
.name = "LXT970",
|
||||
|
@ -146,6 +176,18 @@ static struct phy_driver lxt971_driver = {
|
|||
.driver = { .owner = THIS_MODULE,},
|
||||
};
|
||||
|
||||
static struct phy_driver lxt973_driver = {
|
||||
.phy_id = 0x00137a10,
|
||||
.name = "LXT973",
|
||||
.phy_id_mask = 0xfffffff0,
|
||||
.features = PHY_BASIC_FEATURES,
|
||||
.flags = 0,
|
||||
.probe = lxt973_probe,
|
||||
.config_aneg = lxt973_config_aneg,
|
||||
.read_status = genphy_read_status,
|
||||
.driver = { .owner = THIS_MODULE,},
|
||||
};
|
||||
|
||||
static int __init lxt_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
@ -157,9 +199,15 @@ static int __init lxt_init(void)
|
|||
ret = phy_driver_register(&lxt971_driver);
|
||||
if (ret)
|
||||
goto err2;
|
||||
|
||||
ret = phy_driver_register(&lxt973_driver);
|
||||
if (ret)
|
||||
goto err3;
|
||||
return 0;
|
||||
|
||||
err2:
|
||||
err3:
|
||||
phy_driver_unregister(&lxt971_driver);
|
||||
err2:
|
||||
phy_driver_unregister(&lxt970_driver);
|
||||
err1:
|
||||
return ret;
|
||||
|
@ -169,6 +217,7 @@ static void __exit lxt_exit(void)
|
|||
{
|
||||
phy_driver_unregister(&lxt970_driver);
|
||||
phy_driver_unregister(&lxt971_driver);
|
||||
phy_driver_unregister(&lxt973_driver);
|
||||
}
|
||||
|
||||
module_init(lxt_init);
|
||||
|
|
|
@ -1416,7 +1416,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
|
|||
flen = len;
|
||||
if (nfree > 0) {
|
||||
if (pch->speed == 0) {
|
||||
flen = totlen/nfree;
|
||||
flen = len/nfree;
|
||||
if (nbigger > 0) {
|
||||
flen++;
|
||||
nbigger--;
|
||||
|
@ -1927,9 +1927,9 @@ ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
|
|||
/* If the queue is getting long, don't wait any longer for packets
|
||||
before the start of the queue. */
|
||||
if (skb_queue_len(&ppp->mrq) >= PPP_MP_MAX_QLEN) {
|
||||
struct sk_buff *skb = skb_peek(&ppp->mrq);
|
||||
if (seq_before(ppp->minseq, skb->sequence))
|
||||
ppp->minseq = skb->sequence;
|
||||
struct sk_buff *mskb = skb_peek(&ppp->mrq);
|
||||
if (seq_before(ppp->minseq, mskb->sequence))
|
||||
ppp->minseq = mskb->sequence;
|
||||
}
|
||||
|
||||
/* Pull completed packets off the queue and receive them. */
|
||||
|
|
|
@ -89,7 +89,6 @@
|
|||
#define PPPOE_HASH_SIZE (1 << PPPOE_HASH_BITS)
|
||||
#define PPPOE_HASH_MASK (PPPOE_HASH_SIZE - 1)
|
||||
|
||||
static int pppoe_xmit(struct ppp_channel *chan, struct sk_buff *skb);
|
||||
static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb);
|
||||
|
||||
static const struct proto_ops pppoe_ops;
|
||||
|
@ -949,7 +948,7 @@ static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb)
|
|||
|
||||
abort:
|
||||
kfree_skb(skb);
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
|
|
|
@ -74,7 +74,7 @@ struct gelic_eurus_common_cfg {
|
|||
u16 bss_type; /* infra or adhoc */
|
||||
u16 auth_method; /* shared key or open */
|
||||
u16 op_mode; /* B/G */
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
|
||||
/* for GELIC_EURUS_CMD_WEP_CFG */
|
||||
|
@ -88,7 +88,7 @@ struct gelic_eurus_wep_cfg {
|
|||
/* all fields are big endian */
|
||||
u16 security;
|
||||
u8 key[4][16];
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
/* for GELIC_EURUS_CMD_WPA_CFG */
|
||||
enum gelic_eurus_wpa_security {
|
||||
|
@ -120,7 +120,7 @@ struct gelic_eurus_wpa_cfg {
|
|||
u16 security;
|
||||
u16 psk_type; /* psk key encoding type */
|
||||
u8 psk[GELIC_WL_EURUS_PSK_MAX_LEN]; /* psk key; hex or passphrase */
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
/* for GELIC_EURUS_CMD_{START,GET}_SCAN */
|
||||
enum gelic_eurus_scan_capability {
|
||||
|
@ -171,7 +171,7 @@ struct gelic_eurus_scan_info {
|
|||
__be32 reserved3;
|
||||
__be32 reserved4;
|
||||
u8 elements[0]; /* ie */
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
/* the hypervisor returns bbs up to 16 */
|
||||
#define GELIC_EURUS_MAX_SCAN (16)
|
||||
|
@ -193,7 +193,7 @@ struct gelic_wl_scan_info {
|
|||
struct gelic_eurus_rssi_info {
|
||||
/* big endian */
|
||||
__be16 rssi;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
|
||||
/* for 'stat' member of gelic_wl_info */
|
||||
|
|
|
@ -51,8 +51,8 @@
|
|||
|
||||
#define _QLCNIC_LINUX_MAJOR 5
|
||||
#define _QLCNIC_LINUX_MINOR 0
|
||||
#define _QLCNIC_LINUX_SUBVERSION 2
|
||||
#define QLCNIC_LINUX_VERSIONID "5.0.2"
|
||||
#define _QLCNIC_LINUX_SUBVERSION 3
|
||||
#define QLCNIC_LINUX_VERSIONID "5.0.3"
|
||||
#define QLCNIC_DRV_IDC_VER 0x01
|
||||
|
||||
#define QLCNIC_VERSION_CODE(a, b, c) (((a) << 24) + ((b) << 16) + (c))
|
||||
|
@ -197,8 +197,7 @@ struct cmd_desc_type0 {
|
|||
|
||||
__le64 addr_buffer4;
|
||||
|
||||
__le32 reserved2;
|
||||
__le16 reserved;
|
||||
u8 eth_addr[ETH_ALEN];
|
||||
__le16 vlan_TCI;
|
||||
|
||||
} __attribute__ ((aligned(64)));
|
||||
|
@ -315,6 +314,8 @@ struct uni_data_desc{
|
|||
#define QLCNIC_BRDTYPE_P3_10G_XFP 0x0032
|
||||
#define QLCNIC_BRDTYPE_P3_10G_TP 0x0080
|
||||
|
||||
#define QLCNIC_MSIX_TABLE_OFFSET 0x44
|
||||
|
||||
/* Flash memory map */
|
||||
#define QLCNIC_BRDCFG_START 0x4000 /* board config */
|
||||
#define QLCNIC_BOOTLD_START 0x10000 /* bootld */
|
||||
|
@ -542,7 +543,17 @@ struct qlcnic_recv_context {
|
|||
#define QLCNIC_CDRP_CMD_READ_PEXQ_PARAMETERS 0x0000001c
|
||||
#define QLCNIC_CDRP_CMD_GET_LIC_CAPABILITIES 0x0000001d
|
||||
#define QLCNIC_CDRP_CMD_READ_MAX_LRO_PER_BOARD 0x0000001e
|
||||
#define QLCNIC_CDRP_CMD_MAX 0x0000001f
|
||||
#define QLCNIC_CDRP_CMD_MAC_ADDRESS 0x0000001f
|
||||
|
||||
#define QLCNIC_CDRP_CMD_GET_PCI_INFO 0x00000020
|
||||
#define QLCNIC_CDRP_CMD_GET_NIC_INFO 0x00000021
|
||||
#define QLCNIC_CDRP_CMD_SET_NIC_INFO 0x00000022
|
||||
#define QLCNIC_CDRP_CMD_RESET_NPAR 0x00000023
|
||||
#define QLCNIC_CDRP_CMD_GET_ESWITCH_CAPABILITY 0x00000024
|
||||
#define QLCNIC_CDRP_CMD_TOGGLE_ESWITCH 0x00000025
|
||||
#define QLCNIC_CDRP_CMD_GET_ESWITCH_STATUS 0x00000026
|
||||
#define QLCNIC_CDRP_CMD_SET_PORTMIRRORING 0x00000027
|
||||
#define QLCNIC_CDRP_CMD_CONFIGURE_ESWITCH 0x00000028
|
||||
|
||||
#define QLCNIC_RCODE_SUCCESS 0
|
||||
#define QLCNIC_RCODE_TIMEOUT 17
|
||||
|
@ -560,7 +571,6 @@ struct qlcnic_recv_context {
|
|||
/*
|
||||
* Context state
|
||||
*/
|
||||
#define QLCHAL_VERSION 1
|
||||
|
||||
#define QLCNIC_HOST_CTX_STATE_ACTIVE 2
|
||||
|
||||
|
@ -881,12 +891,14 @@ struct qlcnic_mac_req {
|
|||
#define QLCNIC_LRO_ENABLED 0x08
|
||||
#define QLCNIC_BRIDGE_ENABLED 0X10
|
||||
#define QLCNIC_DIAG_ENABLED 0x20
|
||||
#define QLCNIC_NPAR_ENABLED 0x40
|
||||
#define QLCNIC_IS_MSI_FAMILY(adapter) \
|
||||
((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED))
|
||||
|
||||
#define MSIX_ENTRIES_PER_ADAPTER NUM_STS_DESC_RINGS
|
||||
#define QLCNIC_MSIX_TBL_SPACE 8192
|
||||
#define QLCNIC_PCI_REG_MSIX_TBL 0x44
|
||||
#define QLCNIC_MSIX_TBL_PGSIZE 4096
|
||||
|
||||
#define QLCNIC_NETDEV_WEIGHT 128
|
||||
#define QLCNIC_ADAPTER_UP_MAGIC 777
|
||||
|
@ -923,7 +935,6 @@ struct qlcnic_adapter {
|
|||
u8 mc_enabled;
|
||||
u8 max_mc_count;
|
||||
u8 rss_supported;
|
||||
u8 rsrvd1;
|
||||
u8 fw_wait_cnt;
|
||||
u8 fw_fail_cnt;
|
||||
u8 tx_timeo_cnt;
|
||||
|
@ -940,6 +951,15 @@ struct qlcnic_adapter {
|
|||
u16 link_autoneg;
|
||||
u16 module_type;
|
||||
|
||||
u16 op_mode;
|
||||
u16 switch_mode;
|
||||
u16 max_tx_ques;
|
||||
u16 max_rx_ques;
|
||||
u16 min_tx_bw;
|
||||
u16 max_tx_bw;
|
||||
u16 max_mtu;
|
||||
|
||||
u32 fw_hal_version;
|
||||
u32 capabilities;
|
||||
u32 flags;
|
||||
u32 irq;
|
||||
|
@ -948,18 +968,22 @@ struct qlcnic_adapter {
|
|||
u32 int_vec_bit;
|
||||
u32 heartbit;
|
||||
|
||||
u8 max_mac_filters;
|
||||
u8 dev_state;
|
||||
u8 diag_test;
|
||||
u8 diag_cnt;
|
||||
u8 reset_ack_timeo;
|
||||
u8 dev_init_timeo;
|
||||
u8 rsrd1;
|
||||
u16 msg_enable;
|
||||
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
|
||||
u64 dev_rst_time;
|
||||
|
||||
struct qlcnic_pci_info *npars;
|
||||
struct qlcnic_eswitch *eswitch;
|
||||
struct qlcnic_nic_template *nic_ops;
|
||||
|
||||
struct qlcnic_adapter_stats stats;
|
||||
|
||||
struct qlcnic_recv_context recv_ctx;
|
||||
|
@ -984,6 +1008,53 @@ struct qlcnic_adapter {
|
|||
const struct firmware *fw;
|
||||
};
|
||||
|
||||
struct qlcnic_info {
|
||||
__le16 pci_func;
|
||||
__le16 op_mode; /* 1 = Priv, 2 = NP, 3 = NP passthru */
|
||||
__le16 phys_port;
|
||||
__le16 switch_mode; /* 0 = disabled, 1 = int, 2 = ext */
|
||||
|
||||
__le32 capabilities;
|
||||
u8 max_mac_filters;
|
||||
u8 reserved1;
|
||||
__le16 max_mtu;
|
||||
|
||||
__le16 max_tx_ques;
|
||||
__le16 max_rx_ques;
|
||||
__le16 min_tx_bw;
|
||||
__le16 max_tx_bw;
|
||||
u8 reserved2[104];
|
||||
};
|
||||
|
||||
struct qlcnic_pci_info {
|
||||
__le16 id; /* pci function id */
|
||||
__le16 active; /* 1 = Enabled */
|
||||
__le16 type; /* 1 = NIC, 2 = FCoE, 3 = iSCSI */
|
||||
__le16 default_port; /* default port number */
|
||||
|
||||
__le16 tx_min_bw; /* Multiple of 100mbpc */
|
||||
__le16 tx_max_bw;
|
||||
__le16 reserved1[2];
|
||||
|
||||
u8 mac[ETH_ALEN];
|
||||
u8 reserved2[106];
|
||||
};
|
||||
|
||||
struct qlcnic_eswitch {
|
||||
u8 port;
|
||||
u8 active_vports;
|
||||
u8 active_vlans;
|
||||
u8 active_ucast_filters;
|
||||
u8 max_ucast_filters;
|
||||
u8 max_active_vlans;
|
||||
|
||||
u32 flags;
|
||||
#define QLCNIC_SWITCH_ENABLE BIT_1
|
||||
#define QLCNIC_SWITCH_VLAN_FILTERING BIT_2
|
||||
#define QLCNIC_SWITCH_PROMISC_MODE BIT_3
|
||||
#define QLCNIC_SWITCH_PORT_MIRRORING BIT_4
|
||||
};
|
||||
|
||||
int qlcnic_fw_cmd_query_phy(struct qlcnic_adapter *adapter, u32 reg, u32 *val);
|
||||
int qlcnic_fw_cmd_set_phy(struct qlcnic_adapter *adapter, u32 reg, u32 val);
|
||||
|
||||
|
@ -1070,13 +1141,14 @@ void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup);
|
|||
int qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu);
|
||||
int qlcnic_change_mtu(struct net_device *netdev, int new_mtu);
|
||||
int qlcnic_config_hw_lro(struct qlcnic_adapter *adapter, int enable);
|
||||
int qlcnic_config_bridged_mode(struct qlcnic_adapter *adapter, int enable);
|
||||
int qlcnic_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable);
|
||||
int qlcnic_send_lro_cleanup(struct qlcnic_adapter *adapter);
|
||||
void qlcnic_update_cmd_producer(struct qlcnic_adapter *adapter,
|
||||
struct qlcnic_host_tx_ring *tx_ring);
|
||||
int qlcnic_get_mac_addr(struct qlcnic_adapter *adapter, u64 *mac);
|
||||
int qlcnic_get_mac_addr(struct qlcnic_adapter *adapter, u8 *mac);
|
||||
void qlcnic_clear_ilb_mode(struct qlcnic_adapter *adapter);
|
||||
int qlcnic_set_ilb_mode(struct qlcnic_adapter *adapter);
|
||||
void qlcnic_fetch_mac(struct qlcnic_adapter *, u32, u32, u8, u8 *);
|
||||
|
||||
/* Functions from qlcnic_main.c */
|
||||
int qlcnic_reset_context(struct qlcnic_adapter *);
|
||||
|
@ -1088,6 +1160,25 @@ int qlcnic_check_loopback_buff(unsigned char *data);
|
|||
netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
|
||||
void qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring);
|
||||
|
||||
/* Management functions */
|
||||
int qlcnic_set_mac_address(struct qlcnic_adapter *, u8*);
|
||||
int qlcnic_get_mac_address(struct qlcnic_adapter *, u8*);
|
||||
int qlcnic_get_nic_info(struct qlcnic_adapter *, u8);
|
||||
int qlcnic_set_nic_info(struct qlcnic_adapter *, struct qlcnic_info *);
|
||||
int qlcnic_get_pci_info(struct qlcnic_adapter *);
|
||||
int qlcnic_reset_partition(struct qlcnic_adapter *, u8);
|
||||
|
||||
/* eSwitch management functions */
|
||||
int qlcnic_get_eswitch_capabilities(struct qlcnic_adapter *, u8,
|
||||
struct qlcnic_eswitch *);
|
||||
int qlcnic_get_eswitch_status(struct qlcnic_adapter *, u8,
|
||||
struct qlcnic_eswitch *);
|
||||
int qlcnic_toggle_eswitch(struct qlcnic_adapter *, u8, u8);
|
||||
int qlcnic_config_switch_port(struct qlcnic_adapter *, u8, int, u8, u8,
|
||||
u8, u8, u16);
|
||||
int qlcnic_config_port_mirroring(struct qlcnic_adapter *, u8, u8, u8);
|
||||
extern int qlcnic_config_tso;
|
||||
|
||||
/*
|
||||
* QLOGIC Board information
|
||||
*/
|
||||
|
@ -1131,6 +1222,15 @@ static inline u32 qlcnic_tx_avail(struct qlcnic_host_tx_ring *tx_ring)
|
|||
|
||||
extern const struct ethtool_ops qlcnic_ethtool_ops;
|
||||
|
||||
struct qlcnic_nic_template {
|
||||
int (*get_mac_addr) (struct qlcnic_adapter *, u8*);
|
||||
int (*config_bridged_mode) (struct qlcnic_adapter *, u32);
|
||||
int (*config_led) (struct qlcnic_adapter *, u32, u32);
|
||||
int (*set_ilb_mode) (struct qlcnic_adapter *);
|
||||
void (*clear_ilb_mode) (struct qlcnic_adapter *);
|
||||
int (*start_firmware) (struct qlcnic_adapter *);
|
||||
};
|
||||
|
||||
#define QLCDB(adapter, lvl, _fmt, _args...) do { \
|
||||
if (NETIF_MSG_##lvl & adapter->msg_enable) \
|
||||
printk(KERN_INFO "%s: %s: " _fmt, \
|
||||
|
|
|
@ -88,12 +88,12 @@ qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu)
|
|||
|
||||
if (recv_ctx->state == QLCNIC_HOST_CTX_STATE_ACTIVE) {
|
||||
if (qlcnic_issue_cmd(adapter,
|
||||
adapter->ahw.pci_func,
|
||||
QLCHAL_VERSION,
|
||||
recv_ctx->context_id,
|
||||
mtu,
|
||||
0,
|
||||
QLCNIC_CDRP_CMD_SET_MTU)) {
|
||||
adapter->ahw.pci_func,
|
||||
adapter->fw_hal_version,
|
||||
recv_ctx->context_id,
|
||||
mtu,
|
||||
0,
|
||||
QLCNIC_CDRP_CMD_SET_MTU)) {
|
||||
|
||||
dev_err(&adapter->pdev->dev, "Failed to set mtu\n");
|
||||
return -EIO;
|
||||
|
@ -121,7 +121,7 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
|
|||
|
||||
int i, nrds_rings, nsds_rings;
|
||||
size_t rq_size, rsp_size;
|
||||
u32 cap, reg, val;
|
||||
u32 cap, reg, val, reg2;
|
||||
int err;
|
||||
|
||||
struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx;
|
||||
|
@ -197,7 +197,7 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
|
|||
phys_addr = hostrq_phys_addr;
|
||||
err = qlcnic_issue_cmd(adapter,
|
||||
adapter->ahw.pci_func,
|
||||
QLCHAL_VERSION,
|
||||
adapter->fw_hal_version,
|
||||
(u32)(phys_addr >> 32),
|
||||
(u32)(phys_addr & 0xffffffff),
|
||||
rq_size,
|
||||
|
@ -216,8 +216,12 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
|
|||
rds_ring = &recv_ctx->rds_rings[i];
|
||||
|
||||
reg = le32_to_cpu(prsp_rds[i].host_producer_crb);
|
||||
rds_ring->crb_rcv_producer = qlcnic_get_ioaddr(adapter,
|
||||
if (adapter->fw_hal_version == QLCNIC_FW_BASE)
|
||||
rds_ring->crb_rcv_producer = qlcnic_get_ioaddr(adapter,
|
||||
QLCNIC_REG(reg - 0x200));
|
||||
else
|
||||
rds_ring->crb_rcv_producer = adapter->ahw.pci_base0 +
|
||||
reg;
|
||||
}
|
||||
|
||||
prsp_sds = ((struct qlcnic_cardrsp_sds_ring *)
|
||||
|
@ -227,12 +231,18 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
|
|||
sds_ring = &recv_ctx->sds_rings[i];
|
||||
|
||||
reg = le32_to_cpu(prsp_sds[i].host_consumer_crb);
|
||||
sds_ring->crb_sts_consumer = qlcnic_get_ioaddr(adapter,
|
||||
QLCNIC_REG(reg - 0x200));
|
||||
reg2 = le32_to_cpu(prsp_sds[i].interrupt_crb);
|
||||
|
||||
reg = le32_to_cpu(prsp_sds[i].interrupt_crb);
|
||||
sds_ring->crb_intr_mask = qlcnic_get_ioaddr(adapter,
|
||||
if (adapter->fw_hal_version == QLCNIC_FW_BASE) {
|
||||
sds_ring->crb_sts_consumer = qlcnic_get_ioaddr(adapter,
|
||||
QLCNIC_REG(reg - 0x200));
|
||||
sds_ring->crb_intr_mask = qlcnic_get_ioaddr(adapter,
|
||||
QLCNIC_REG(reg2 - 0x200));
|
||||
} else {
|
||||
sds_ring->crb_sts_consumer = adapter->ahw.pci_base0 +
|
||||
reg;
|
||||
sds_ring->crb_intr_mask = adapter->ahw.pci_base0 + reg2;
|
||||
}
|
||||
}
|
||||
|
||||
recv_ctx->state = le32_to_cpu(prsp->host_ctx_state);
|
||||
|
@ -253,7 +263,7 @@ qlcnic_fw_cmd_destroy_rx_ctx(struct qlcnic_adapter *adapter)
|
|||
|
||||
if (qlcnic_issue_cmd(adapter,
|
||||
adapter->ahw.pci_func,
|
||||
QLCHAL_VERSION,
|
||||
adapter->fw_hal_version,
|
||||
recv_ctx->context_id,
|
||||
QLCNIC_DESTROY_CTX_RESET,
|
||||
0,
|
||||
|
@ -319,7 +329,7 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter)
|
|||
phys_addr = rq_phys_addr;
|
||||
err = qlcnic_issue_cmd(adapter,
|
||||
adapter->ahw.pci_func,
|
||||
QLCHAL_VERSION,
|
||||
adapter->fw_hal_version,
|
||||
(u32)(phys_addr >> 32),
|
||||
((u32)phys_addr & 0xffffffff),
|
||||
rq_size,
|
||||
|
@ -327,8 +337,12 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter)
|
|||
|
||||
if (err == QLCNIC_RCODE_SUCCESS) {
|
||||
temp = le32_to_cpu(prsp->cds_ring.host_producer_crb);
|
||||
tx_ring->crb_cmd_producer = qlcnic_get_ioaddr(adapter,
|
||||
if (adapter->fw_hal_version == QLCNIC_FW_BASE)
|
||||
tx_ring->crb_cmd_producer = qlcnic_get_ioaddr(adapter,
|
||||
QLCNIC_REG(temp - 0x200));
|
||||
else
|
||||
tx_ring->crb_cmd_producer = adapter->ahw.pci_base0 +
|
||||
temp;
|
||||
|
||||
adapter->tx_context_id =
|
||||
le16_to_cpu(prsp->context_id);
|
||||
|
@ -351,7 +365,7 @@ qlcnic_fw_cmd_destroy_tx_ctx(struct qlcnic_adapter *adapter)
|
|||
{
|
||||
if (qlcnic_issue_cmd(adapter,
|
||||
adapter->ahw.pci_func,
|
||||
QLCHAL_VERSION,
|
||||
adapter->fw_hal_version,
|
||||
adapter->tx_context_id,
|
||||
QLCNIC_DESTROY_CTX_RESET,
|
||||
0,
|
||||
|
@ -368,7 +382,7 @@ qlcnic_fw_cmd_query_phy(struct qlcnic_adapter *adapter, u32 reg, u32 *val)
|
|||
|
||||
if (qlcnic_issue_cmd(adapter,
|
||||
adapter->ahw.pci_func,
|
||||
QLCHAL_VERSION,
|
||||
adapter->fw_hal_version,
|
||||
reg,
|
||||
0,
|
||||
0,
|
||||
|
@ -385,7 +399,7 @@ qlcnic_fw_cmd_set_phy(struct qlcnic_adapter *adapter, u32 reg, u32 val)
|
|||
{
|
||||
return qlcnic_issue_cmd(adapter,
|
||||
adapter->ahw.pci_func,
|
||||
QLCHAL_VERSION,
|
||||
adapter->fw_hal_version,
|
||||
reg,
|
||||
val,
|
||||
0,
|
||||
|
@ -533,3 +547,464 @@ void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter)
|
|||
}
|
||||
}
|
||||
|
||||
/* Set MAC address of a NIC partition */
|
||||
int qlcnic_set_mac_address(struct qlcnic_adapter *adapter, u8* mac)
|
||||
{
|
||||
int err = 0;
|
||||
u32 arg1, arg2, arg3;
|
||||
|
||||
arg1 = adapter->ahw.pci_func | BIT_9;
|
||||
arg2 = mac[0] | (mac[1] << 8) | (mac[2] << 16) | (mac[3] << 24);
|
||||
arg3 = mac[4] | (mac[5] << 16);
|
||||
|
||||
err = qlcnic_issue_cmd(adapter,
|
||||
adapter->ahw.pci_func,
|
||||
adapter->fw_hal_version,
|
||||
arg1,
|
||||
arg2,
|
||||
arg3,
|
||||
QLCNIC_CDRP_CMD_MAC_ADDRESS);
|
||||
|
||||
if (err != QLCNIC_RCODE_SUCCESS) {
|
||||
dev_err(&adapter->pdev->dev,
|
||||
"Failed to set mac address%d\n", err);
|
||||
err = -EIO;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Get MAC address of a NIC partition */
|
||||
int qlcnic_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac)
|
||||
{
|
||||
int err;
|
||||
u32 arg1;
|
||||
|
||||
arg1 = adapter->ahw.pci_func | BIT_8;
|
||||
err = qlcnic_issue_cmd(adapter,
|
||||
adapter->ahw.pci_func,
|
||||
adapter->fw_hal_version,
|
||||
arg1,
|
||||
0,
|
||||
0,
|
||||
QLCNIC_CDRP_CMD_MAC_ADDRESS);
|
||||
|
||||
if (err == QLCNIC_RCODE_SUCCESS) {
|
||||
qlcnic_fetch_mac(adapter, QLCNIC_ARG1_CRB_OFFSET,
|
||||
QLCNIC_ARG2_CRB_OFFSET, 0, mac);
|
||||
dev_info(&adapter->pdev->dev, "MAC address: %pM\n", mac);
|
||||
} else {
|
||||
dev_err(&adapter->pdev->dev,
|
||||
"Failed to get mac address%d\n", err);
|
||||
err = -EIO;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Get info of a NIC partition */
|
||||
int qlcnic_get_nic_info(struct qlcnic_adapter *adapter, u8 func_id)
|
||||
{
|
||||
int err;
|
||||
dma_addr_t nic_dma_t;
|
||||
struct qlcnic_info *nic_info;
|
||||
void *nic_info_addr;
|
||||
size_t nic_size = sizeof(struct qlcnic_info);
|
||||
|
||||
nic_info_addr = pci_alloc_consistent(adapter->pdev,
|
||||
nic_size, &nic_dma_t);
|
||||
if (!nic_info_addr)
|
||||
return -ENOMEM;
|
||||
memset(nic_info_addr, 0, nic_size);
|
||||
|
||||
nic_info = (struct qlcnic_info *) nic_info_addr;
|
||||
err = qlcnic_issue_cmd(adapter,
|
||||
adapter->ahw.pci_func,
|
||||
adapter->fw_hal_version,
|
||||
MSD(nic_dma_t),
|
||||
LSD(nic_dma_t),
|
||||
(func_id << 16 | nic_size),
|
||||
QLCNIC_CDRP_CMD_GET_NIC_INFO);
|
||||
|
||||
if (err == QLCNIC_RCODE_SUCCESS) {
|
||||
adapter->physical_port = le16_to_cpu(nic_info->phys_port);
|
||||
adapter->switch_mode = le16_to_cpu(nic_info->switch_mode);
|
||||
adapter->max_tx_ques = le16_to_cpu(nic_info->max_tx_ques);
|
||||
adapter->max_rx_ques = le16_to_cpu(nic_info->max_rx_ques);
|
||||
adapter->min_tx_bw = le16_to_cpu(nic_info->min_tx_bw);
|
||||
adapter->max_tx_bw = le16_to_cpu(nic_info->max_tx_bw);
|
||||
adapter->max_mtu = le16_to_cpu(nic_info->max_mtu);
|
||||
adapter->capabilities = le32_to_cpu(nic_info->capabilities);
|
||||
adapter->max_mac_filters = nic_info->max_mac_filters;
|
||||
|
||||
dev_info(&adapter->pdev->dev,
|
||||
"phy port: %d switch_mode: %d,\n"
|
||||
"\tmax_tx_q: %d max_rx_q: %d min_tx_bw: 0x%x,\n"
|
||||
"\tmax_tx_bw: 0x%x max_mtu:0x%x, capabilities: 0x%x\n",
|
||||
adapter->physical_port, adapter->switch_mode,
|
||||
adapter->max_tx_ques, adapter->max_rx_ques,
|
||||
adapter->min_tx_bw, adapter->max_tx_bw,
|
||||
adapter->max_mtu, adapter->capabilities);
|
||||
} else {
|
||||
dev_err(&adapter->pdev->dev,
|
||||
"Failed to get nic info%d\n", err);
|
||||
err = -EIO;
|
||||
}
|
||||
|
||||
pci_free_consistent(adapter->pdev, nic_size, nic_info_addr, nic_dma_t);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Configure a NIC partition */
|
||||
int qlcnic_set_nic_info(struct qlcnic_adapter *adapter, struct qlcnic_info *nic)
|
||||
{
|
||||
int err = -EIO;
|
||||
u32 func_state;
|
||||
dma_addr_t nic_dma_t;
|
||||
void *nic_info_addr;
|
||||
struct qlcnic_info *nic_info;
|
||||
size_t nic_size = sizeof(struct qlcnic_info);
|
||||
|
||||
if (adapter->op_mode != QLCNIC_MGMT_FUNC)
|
||||
return err;
|
||||
|
||||
if (qlcnic_api_lock(adapter))
|
||||
return err;
|
||||
|
||||
func_state = QLCRD32(adapter, QLCNIC_CRB_DEV_REF_COUNT);
|
||||
if (QLC_DEV_CHECK_ACTIVE(func_state, nic->pci_func)) {
|
||||
qlcnic_api_unlock(adapter);
|
||||
return err;
|
||||
}
|
||||
|
||||
qlcnic_api_unlock(adapter);
|
||||
|
||||
nic_info_addr = pci_alloc_consistent(adapter->pdev, nic_size,
|
||||
&nic_dma_t);
|
||||
if (!nic_info_addr)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(nic_info_addr, 0, nic_size);
|
||||
nic_info = (struct qlcnic_info *)nic_info_addr;
|
||||
|
||||
nic_info->pci_func = cpu_to_le16(nic->pci_func);
|
||||
nic_info->op_mode = cpu_to_le16(nic->op_mode);
|
||||
nic_info->phys_port = cpu_to_le16(nic->phys_port);
|
||||
nic_info->switch_mode = cpu_to_le16(nic->switch_mode);
|
||||
nic_info->capabilities = cpu_to_le32(nic->capabilities);
|
||||
nic_info->max_mac_filters = nic->max_mac_filters;
|
||||
nic_info->max_tx_ques = cpu_to_le16(nic->max_tx_ques);
|
||||
nic_info->max_rx_ques = cpu_to_le16(nic->max_rx_ques);
|
||||
nic_info->min_tx_bw = cpu_to_le16(nic->min_tx_bw);
|
||||
nic_info->max_tx_bw = cpu_to_le16(nic->max_tx_bw);
|
||||
|
||||
err = qlcnic_issue_cmd(adapter,
|
||||
adapter->ahw.pci_func,
|
||||
adapter->fw_hal_version,
|
||||
MSD(nic_dma_t),
|
||||
LSD(nic_dma_t),
|
||||
nic_size,
|
||||
QLCNIC_CDRP_CMD_SET_NIC_INFO);
|
||||
|
||||
if (err != QLCNIC_RCODE_SUCCESS) {
|
||||
dev_err(&adapter->pdev->dev,
|
||||
"Failed to set nic info%d\n", err);
|
||||
err = -EIO;
|
||||
}
|
||||
|
||||
pci_free_consistent(adapter->pdev, nic_size, nic_info_addr, nic_dma_t);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Get PCI Info of a partition */
|
||||
int qlcnic_get_pci_info(struct qlcnic_adapter *adapter)
|
||||
{
|
||||
int err = 0, i;
|
||||
dma_addr_t pci_info_dma_t;
|
||||
struct qlcnic_pci_info *npar;
|
||||
void *pci_info_addr;
|
||||
size_t npar_size = sizeof(struct qlcnic_pci_info);
|
||||
size_t pci_size = npar_size * QLCNIC_MAX_PCI_FUNC;
|
||||
|
||||
pci_info_addr = pci_alloc_consistent(adapter->pdev, pci_size,
|
||||
&pci_info_dma_t);
|
||||
if (!pci_info_addr)
|
||||
return -ENOMEM;
|
||||
memset(pci_info_addr, 0, pci_size);
|
||||
|
||||
if (!adapter->npars)
|
||||
adapter->npars = kzalloc(pci_size, GFP_KERNEL);
|
||||
if (!adapter->npars) {
|
||||
err = -ENOMEM;
|
||||
goto err_npar;
|
||||
}
|
||||
|
||||
if (!adapter->eswitch)
|
||||
adapter->eswitch = kzalloc(sizeof(struct qlcnic_eswitch) *
|
||||
QLCNIC_NIU_MAX_XG_PORTS, GFP_KERNEL);
|
||||
if (!adapter->eswitch) {
|
||||
err = -ENOMEM;
|
||||
goto err_eswitch;
|
||||
}
|
||||
|
||||
npar = (struct qlcnic_pci_info *) pci_info_addr;
|
||||
err = qlcnic_issue_cmd(adapter,
|
||||
adapter->ahw.pci_func,
|
||||
adapter->fw_hal_version,
|
||||
MSD(pci_info_dma_t),
|
||||
LSD(pci_info_dma_t),
|
||||
pci_size,
|
||||
QLCNIC_CDRP_CMD_GET_PCI_INFO);
|
||||
|
||||
if (err == QLCNIC_RCODE_SUCCESS) {
|
||||
for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++, npar++) {
|
||||
adapter->npars[i].id = le32_to_cpu(npar->id);
|
||||
adapter->npars[i].active = le32_to_cpu(npar->active);
|
||||
adapter->npars[i].type = le32_to_cpu(npar->type);
|
||||
adapter->npars[i].default_port =
|
||||
le32_to_cpu(npar->default_port);
|
||||
adapter->npars[i].tx_min_bw =
|
||||
le32_to_cpu(npar->tx_min_bw);
|
||||
adapter->npars[i].tx_max_bw =
|
||||
le32_to_cpu(npar->tx_max_bw);
|
||||
memcpy(adapter->npars[i].mac, npar->mac, ETH_ALEN);
|
||||
}
|
||||
} else {
|
||||
dev_err(&adapter->pdev->dev,
|
||||
"Failed to get PCI Info%d\n", err);
|
||||
kfree(adapter->npars);
|
||||
err = -EIO;
|
||||
}
|
||||
goto err_npar;
|
||||
|
||||
err_eswitch:
|
||||
kfree(adapter->npars);
|
||||
adapter->npars = NULL;
|
||||
|
||||
err_npar:
|
||||
pci_free_consistent(adapter->pdev, pci_size, pci_info_addr,
|
||||
pci_info_dma_t);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Reset a NIC partition */
|
||||
|
||||
int qlcnic_reset_partition(struct qlcnic_adapter *adapter, u8 func_no)
|
||||
{
|
||||
int err = -EIO;
|
||||
|
||||
if (adapter->op_mode != QLCNIC_MGMT_FUNC)
|
||||
return err;
|
||||
|
||||
err = qlcnic_issue_cmd(adapter,
|
||||
adapter->ahw.pci_func,
|
||||
adapter->fw_hal_version,
|
||||
func_no,
|
||||
0,
|
||||
0,
|
||||
QLCNIC_CDRP_CMD_RESET_NPAR);
|
||||
|
||||
if (err != QLCNIC_RCODE_SUCCESS) {
|
||||
dev_err(&adapter->pdev->dev,
|
||||
"Failed to issue reset partition%d\n", err);
|
||||
err = -EIO;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Get eSwitch Capabilities */
|
||||
int qlcnic_get_eswitch_capabilities(struct qlcnic_adapter *adapter, u8 port,
|
||||
struct qlcnic_eswitch *eswitch)
|
||||
{
|
||||
int err = -EIO;
|
||||
u32 arg1, arg2;
|
||||
|
||||
if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC)
|
||||
return err;
|
||||
|
||||
err = qlcnic_issue_cmd(adapter,
|
||||
adapter->ahw.pci_func,
|
||||
adapter->fw_hal_version,
|
||||
port,
|
||||
0,
|
||||
0,
|
||||
QLCNIC_CDRP_CMD_GET_ESWITCH_CAPABILITY);
|
||||
|
||||
if (err == QLCNIC_RCODE_SUCCESS) {
|
||||
arg1 = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET);
|
||||
arg2 = QLCRD32(adapter, QLCNIC_ARG2_CRB_OFFSET);
|
||||
|
||||
eswitch->port = arg1 & 0xf;
|
||||
eswitch->active_vports = LSB(arg2);
|
||||
eswitch->max_ucast_filters = MSB(arg2);
|
||||
eswitch->max_active_vlans = LSB(MSW(arg2));
|
||||
if (arg1 & BIT_6)
|
||||
eswitch->flags |= QLCNIC_SWITCH_VLAN_FILTERING;
|
||||
if (arg1 & BIT_7)
|
||||
eswitch->flags |= QLCNIC_SWITCH_PROMISC_MODE;
|
||||
if (arg1 & BIT_8)
|
||||
eswitch->flags |= QLCNIC_SWITCH_PORT_MIRRORING;
|
||||
} else {
|
||||
dev_err(&adapter->pdev->dev,
|
||||
"Failed to get eswitch capabilities%d\n", err);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Get current status of eswitch */
|
||||
int qlcnic_get_eswitch_status(struct qlcnic_adapter *adapter, u8 port,
|
||||
struct qlcnic_eswitch *eswitch)
|
||||
{
|
||||
int err = -EIO;
|
||||
u32 arg1, arg2;
|
||||
|
||||
if (adapter->op_mode != QLCNIC_MGMT_FUNC)
|
||||
return err;
|
||||
|
||||
err = qlcnic_issue_cmd(adapter,
|
||||
adapter->ahw.pci_func,
|
||||
adapter->fw_hal_version,
|
||||
port,
|
||||
0,
|
||||
0,
|
||||
QLCNIC_CDRP_CMD_GET_ESWITCH_STATUS);
|
||||
|
||||
if (err == QLCNIC_RCODE_SUCCESS) {
|
||||
arg1 = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET);
|
||||
arg2 = QLCRD32(adapter, QLCNIC_ARG2_CRB_OFFSET);
|
||||
|
||||
eswitch->port = arg1 & 0xf;
|
||||
eswitch->active_vports = LSB(arg2);
|
||||
eswitch->active_ucast_filters = MSB(arg2);
|
||||
eswitch->active_vlans = LSB(MSW(arg2));
|
||||
if (arg1 & BIT_6)
|
||||
eswitch->flags |= QLCNIC_SWITCH_VLAN_FILTERING;
|
||||
if (arg1 & BIT_8)
|
||||
eswitch->flags |= QLCNIC_SWITCH_PORT_MIRRORING;
|
||||
|
||||
} else {
|
||||
dev_err(&adapter->pdev->dev,
|
||||
"Failed to get eswitch status%d\n", err);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Enable/Disable eSwitch */
|
||||
int qlcnic_toggle_eswitch(struct qlcnic_adapter *adapter, u8 id, u8 enable)
|
||||
{
|
||||
int err = -EIO;
|
||||
u32 arg1, arg2;
|
||||
struct qlcnic_eswitch *eswitch;
|
||||
|
||||
if (adapter->op_mode != QLCNIC_MGMT_FUNC)
|
||||
return err;
|
||||
|
||||
eswitch = &adapter->eswitch[id];
|
||||
if (!eswitch)
|
||||
return err;
|
||||
|
||||
arg1 = eswitch->port | (enable ? BIT_4 : 0);
|
||||
arg2 = eswitch->active_vports | (eswitch->max_ucast_filters << 8) |
|
||||
(eswitch->max_active_vlans << 16);
|
||||
err = qlcnic_issue_cmd(adapter,
|
||||
adapter->ahw.pci_func,
|
||||
adapter->fw_hal_version,
|
||||
arg1,
|
||||
arg2,
|
||||
0,
|
||||
QLCNIC_CDRP_CMD_TOGGLE_ESWITCH);
|
||||
|
||||
if (err != QLCNIC_RCODE_SUCCESS) {
|
||||
dev_err(&adapter->pdev->dev,
|
||||
"Failed to enable eswitch%d\n", eswitch->port);
|
||||
eswitch->flags &= ~QLCNIC_SWITCH_ENABLE;
|
||||
err = -EIO;
|
||||
} else {
|
||||
eswitch->flags |= QLCNIC_SWITCH_ENABLE;
|
||||
dev_info(&adapter->pdev->dev,
|
||||
"Enabled eSwitch for port %d\n", eswitch->port);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Configure eSwitch for port mirroring */
|
||||
int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id,
|
||||
u8 enable_mirroring, u8 pci_func)
|
||||
{
|
||||
int err = -EIO;
|
||||
u32 arg1;
|
||||
|
||||
if (adapter->op_mode != QLCNIC_MGMT_FUNC ||
|
||||
!(adapter->eswitch[id].flags & QLCNIC_SWITCH_ENABLE))
|
||||
return err;
|
||||
|
||||
arg1 = id | (enable_mirroring ? BIT_4 : 0);
|
||||
arg1 |= pci_func << 8;
|
||||
|
||||
err = qlcnic_issue_cmd(adapter,
|
||||
adapter->ahw.pci_func,
|
||||
adapter->fw_hal_version,
|
||||
arg1,
|
||||
0,
|
||||
0,
|
||||
QLCNIC_CDRP_CMD_SET_PORTMIRRORING);
|
||||
|
||||
if (err != QLCNIC_RCODE_SUCCESS) {
|
||||
dev_err(&adapter->pdev->dev,
|
||||
"Failed to configure port mirroring%d on eswitch:%d\n",
|
||||
pci_func, id);
|
||||
} else {
|
||||
dev_info(&adapter->pdev->dev,
|
||||
"Configured eSwitch %d for port mirroring:%d\n",
|
||||
id, pci_func);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Configure eSwitch port */
|
||||
int qlcnic_config_switch_port(struct qlcnic_adapter *adapter, u8 id,
|
||||
int vlan_tagging, u8 discard_tagged, u8 promsc_mode,
|
||||
u8 mac_learn, u8 pci_func, u16 vlan_id)
|
||||
{
|
||||
int err = -EIO;
|
||||
u32 arg1;
|
||||
struct qlcnic_eswitch *eswitch;
|
||||
|
||||
if (adapter->op_mode != QLCNIC_MGMT_FUNC)
|
||||
return err;
|
||||
|
||||
eswitch = &adapter->eswitch[id];
|
||||
if (!(eswitch->flags & QLCNIC_SWITCH_ENABLE))
|
||||
return err;
|
||||
|
||||
arg1 = eswitch->port | (discard_tagged ? BIT_4 : 0);
|
||||
arg1 |= (promsc_mode ? BIT_6 : 0) | (mac_learn ? BIT_7 : 0);
|
||||
arg1 |= pci_func << 8;
|
||||
if (vlan_tagging)
|
||||
arg1 |= BIT_5 | (vlan_id << 16);
|
||||
|
||||
err = qlcnic_issue_cmd(adapter,
|
||||
adapter->ahw.pci_func,
|
||||
adapter->fw_hal_version,
|
||||
arg1,
|
||||
0,
|
||||
0,
|
||||
QLCNIC_CDRP_CMD_CONFIGURE_ESWITCH);
|
||||
|
||||
if (err != QLCNIC_RCODE_SUCCESS) {
|
||||
dev_err(&adapter->pdev->dev,
|
||||
"Failed to configure eswitch port%d\n", eswitch->port);
|
||||
eswitch->flags |= QLCNIC_SWITCH_ENABLE;
|
||||
} else {
|
||||
eswitch->flags &= ~QLCNIC_SWITCH_ENABLE;
|
||||
dev_info(&adapter->pdev->dev,
|
||||
"Configured eSwitch for port %d\n", eswitch->port);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -683,13 +683,13 @@ static int qlcnic_loopback_test(struct net_device *netdev)
|
|||
if (ret)
|
||||
goto clear_it;
|
||||
|
||||
ret = qlcnic_set_ilb_mode(adapter);
|
||||
ret = adapter->nic_ops->set_ilb_mode(adapter);
|
||||
if (ret)
|
||||
goto done;
|
||||
|
||||
ret = qlcnic_do_ilb_test(adapter);
|
||||
|
||||
qlcnic_clear_ilb_mode(adapter);
|
||||
adapter->nic_ops->clear_ilb_mode(adapter);
|
||||
|
||||
done:
|
||||
qlcnic_diag_free_res(netdev, max_sds_rings);
|
||||
|
@ -715,7 +715,8 @@ static int qlcnic_irq_test(struct net_device *netdev)
|
|||
|
||||
adapter->diag_cnt = 0;
|
||||
ret = qlcnic_issue_cmd(adapter, adapter->ahw.pci_func,
|
||||
QLCHAL_VERSION, adapter->portnum, 0, 0, 0x00000011);
|
||||
adapter->fw_hal_version, adapter->portnum,
|
||||
0, 0, 0x00000011);
|
||||
if (ret)
|
||||
goto done;
|
||||
|
||||
|
@ -834,7 +835,7 @@ static int qlcnic_blink_led(struct net_device *dev, u32 val)
|
|||
struct qlcnic_adapter *adapter = netdev_priv(dev);
|
||||
int ret;
|
||||
|
||||
ret = qlcnic_config_led(adapter, 1, 0xf);
|
||||
ret = adapter->nic_ops->config_led(adapter, 1, 0xf);
|
||||
if (ret) {
|
||||
dev_err(&adapter->pdev->dev,
|
||||
"Failed to set LED blink state.\n");
|
||||
|
@ -843,7 +844,7 @@ static int qlcnic_blink_led(struct net_device *dev, u32 val)
|
|||
|
||||
msleep_interruptible(val * 1000);
|
||||
|
||||
ret = qlcnic_config_led(adapter, 0, 0xf);
|
||||
ret = adapter->nic_ops->config_led(adapter, 0, 0xf);
|
||||
if (ret) {
|
||||
dev_err(&adapter->pdev->dev,
|
||||
"Failed to reset LED blink state.\n");
|
||||
|
|
|
@ -208,6 +208,39 @@ enum {
|
|||
QLCNIC_HW_PX_MAP_CRB_PGR0
|
||||
};
|
||||
|
||||
#define BIT_0 0x1
|
||||
#define BIT_1 0x2
|
||||
#define BIT_2 0x4
|
||||
#define BIT_3 0x8
|
||||
#define BIT_4 0x10
|
||||
#define BIT_5 0x20
|
||||
#define BIT_6 0x40
|
||||
#define BIT_7 0x80
|
||||
#define BIT_8 0x100
|
||||
#define BIT_9 0x200
|
||||
#define BIT_10 0x400
|
||||
#define BIT_11 0x800
|
||||
#define BIT_12 0x1000
|
||||
#define BIT_13 0x2000
|
||||
#define BIT_14 0x4000
|
||||
#define BIT_15 0x8000
|
||||
#define BIT_16 0x10000
|
||||
#define BIT_17 0x20000
|
||||
#define BIT_18 0x40000
|
||||
#define BIT_19 0x80000
|
||||
#define BIT_20 0x100000
|
||||
#define BIT_21 0x200000
|
||||
#define BIT_22 0x400000
|
||||
#define BIT_23 0x800000
|
||||
#define BIT_24 0x1000000
|
||||
#define BIT_25 0x2000000
|
||||
#define BIT_26 0x4000000
|
||||
#define BIT_27 0x8000000
|
||||
#define BIT_28 0x10000000
|
||||
#define BIT_29 0x20000000
|
||||
#define BIT_30 0x40000000
|
||||
#define BIT_31 0x80000000
|
||||
|
||||
/* This field defines CRB adr [31:20] of the agents */
|
||||
|
||||
#define QLCNIC_HW_CRB_HUB_AGT_ADR_MN \
|
||||
|
@ -668,10 +701,11 @@ enum {
|
|||
#define QLCNIC_CRB_DEV_REF_COUNT (QLCNIC_CAM_RAM(0x138))
|
||||
#define QLCNIC_CRB_DEV_STATE (QLCNIC_CAM_RAM(0x140))
|
||||
|
||||
#define QLCNIC_CRB_DRV_STATE (QLCNIC_CAM_RAM(0x144))
|
||||
#define QLCNIC_CRB_DRV_SCRATCH (QLCNIC_CAM_RAM(0x148))
|
||||
#define QLCNIC_CRB_DEV_PARTITION_INFO (QLCNIC_CAM_RAM(0x14c))
|
||||
#define QLCNIC_CRB_DRV_STATE (QLCNIC_CAM_RAM(0x144))
|
||||
#define QLCNIC_CRB_DRV_SCRATCH (QLCNIC_CAM_RAM(0x148))
|
||||
#define QLCNIC_CRB_DEV_PARTITION_INFO (QLCNIC_CAM_RAM(0x14c))
|
||||
#define QLCNIC_CRB_DRV_IDC_VER (QLCNIC_CAM_RAM(0x174))
|
||||
#define QLCNIC_CRB_DEV_NPAR_STATE (QLCNIC_CAM_RAM(0x19c))
|
||||
#define QLCNIC_ROM_DEV_INIT_TIMEOUT (0x3e885c)
|
||||
#define QLCNIC_ROM_DRV_RESET_TIMEOUT (0x3e8860)
|
||||
|
||||
|
@ -684,15 +718,26 @@ enum {
|
|||
#define QLCNIC_DEV_FAILED 0x6
|
||||
#define QLCNIC_DEV_QUISCENT 0x7
|
||||
|
||||
#define QLCNIC_DEV_NPAR_NOT_RDY 0
|
||||
#define QLCNIC_DEV_NPAR_RDY 1
|
||||
|
||||
#define QLC_DEV_CHECK_ACTIVE(VAL, FN) ((VAL) &= (1 << (FN * 4)))
|
||||
#define QLC_DEV_SET_REF_CNT(VAL, FN) ((VAL) |= (1 << (FN * 4)))
|
||||
#define QLC_DEV_CLR_REF_CNT(VAL, FN) ((VAL) &= ~(1 << (FN * 4)))
|
||||
#define QLC_DEV_SET_RST_RDY(VAL, FN) ((VAL) |= (1 << (FN * 4)))
|
||||
#define QLC_DEV_SET_QSCNT_RDY(VAL, FN) ((VAL) |= (2 << (FN * 4)))
|
||||
#define QLC_DEV_CLR_RST_QSCNT(VAL, FN) ((VAL) &= ~(3 << (FN * 4)))
|
||||
|
||||
#define QLC_DEV_GET_DRV(VAL, FN) (0xf & ((VAL) >> (FN * 4)))
|
||||
#define QLC_DEV_SET_DRV(VAL, FN) ((VAL) << (FN * 4))
|
||||
|
||||
#define QLCNIC_TYPE_NIC 1
|
||||
#define QLCNIC_TYPE_FCOE 2
|
||||
#define QLCNIC_TYPE_ISCSI 3
|
||||
|
||||
#define QLCNIC_RCODE_DRIVER_INFO 0x20000000
|
||||
#define QLCNIC_RCODE_DRIVER_CAN_RELOAD 0x40000000
|
||||
#define QLCNIC_RCODE_FATAL_ERROR 0x80000000
|
||||
#define QLCNIC_RCODE_DRIVER_CAN_RELOAD BIT_30
|
||||
#define QLCNIC_RCODE_FATAL_ERROR BIT_31
|
||||
#define QLCNIC_FWERROR_PEGNUM(code) ((code) & 0xff)
|
||||
#define QLCNIC_FWERROR_CODE(code) ((code >> 8) & 0xfffff)
|
||||
|
||||
|
@ -721,6 +766,35 @@ struct qlcnic_legacy_intr_set {
|
|||
u32 pci_int_reg;
|
||||
};
|
||||
|
||||
#define QLCNIC_FW_API 0x1b216c
|
||||
#define QLCNIC_DRV_OP_MODE 0x1b2170
|
||||
#define QLCNIC_MSIX_BASE 0x132110
|
||||
#define QLCNIC_MAX_PCI_FUNC 8
|
||||
|
||||
/* PCI function operational mode */
|
||||
enum {
|
||||
QLCNIC_MGMT_FUNC = 0,
|
||||
QLCNIC_PRIV_FUNC = 1,
|
||||
QLCNIC_NON_PRIV_FUNC = 2
|
||||
};
|
||||
|
||||
/* FW HAL api version */
|
||||
enum {
|
||||
QLCNIC_FW_BASE = 1,
|
||||
QLCNIC_FW_NPAR = 2
|
||||
};
|
||||
|
||||
#define QLC_DEV_DRV_DEFAULT 0x11111111
|
||||
|
||||
#define LSB(x) ((uint8_t)(x))
|
||||
#define MSB(x) ((uint8_t)((uint16_t)(x) >> 8))
|
||||
|
||||
#define LSW(x) ((uint16_t)((uint32_t)(x)))
|
||||
#define MSW(x) ((uint16_t)((uint32_t)(x) >> 16))
|
||||
|
||||
#define LSD(x) ((uint32_t)((uint64_t)(x)))
|
||||
#define MSD(x) ((uint32_t)((((uint64_t)(x)) >> 16) >> 16))
|
||||
|
||||
#define QLCNIC_LEGACY_INTR_CONFIG \
|
||||
{ \
|
||||
{ \
|
||||
|
|
|
@ -538,7 +538,7 @@ int qlcnic_config_hw_lro(struct qlcnic_adapter *adapter, int enable)
|
|||
return rv;
|
||||
}
|
||||
|
||||
int qlcnic_config_bridged_mode(struct qlcnic_adapter *adapter, int enable)
|
||||
int qlcnic_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable)
|
||||
{
|
||||
struct qlcnic_nic_req req;
|
||||
u64 word;
|
||||
|
@ -704,21 +704,15 @@ int qlcnic_change_mtu(struct net_device *netdev, int mtu)
|
|||
return rc;
|
||||
}
|
||||
|
||||
int qlcnic_get_mac_addr(struct qlcnic_adapter *adapter, u64 *mac)
|
||||
int qlcnic_get_mac_addr(struct qlcnic_adapter *adapter, u8 *mac)
|
||||
{
|
||||
u32 crbaddr, mac_hi, mac_lo;
|
||||
u32 crbaddr;
|
||||
int pci_func = adapter->ahw.pci_func;
|
||||
|
||||
crbaddr = CRB_MAC_BLOCK_START +
|
||||
(4 * ((pci_func/2) * 3)) + (4 * (pci_func & 1));
|
||||
|
||||
mac_lo = QLCRD32(adapter, crbaddr);
|
||||
mac_hi = QLCRD32(adapter, crbaddr+4);
|
||||
|
||||
if (pci_func & 1)
|
||||
*mac = le64_to_cpu((mac_lo >> 16) | ((u64)mac_hi << 16));
|
||||
else
|
||||
*mac = le64_to_cpu((u64)mac_lo | ((u64)mac_hi << 32));
|
||||
qlcnic_fetch_mac(adapter, crbaddr, crbaddr+4, pci_func & 1, mac);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -520,17 +520,16 @@ qlcnic_setup_idc_param(struct qlcnic_adapter *adapter) {
|
|||
int timeo;
|
||||
u32 val;
|
||||
|
||||
val = QLCRD32(adapter, QLCNIC_CRB_DEV_PARTITION_INFO);
|
||||
val = (val >> (adapter->portnum * 4)) & 0xf;
|
||||
|
||||
if ((val & 0x3) != 1) {
|
||||
dev_err(&adapter->pdev->dev, "Not an Ethernet NIC func=%u\n",
|
||||
val);
|
||||
return -EIO;
|
||||
if (adapter->fw_hal_version == QLCNIC_FW_BASE) {
|
||||
val = QLCRD32(adapter, QLCNIC_CRB_DEV_PARTITION_INFO);
|
||||
val = QLC_DEV_GET_DRV(val, adapter->portnum);
|
||||
if ((val & 0x3) != QLCNIC_TYPE_NIC) {
|
||||
dev_err(&adapter->pdev->dev,
|
||||
"Not an Ethernet NIC func=%u\n", val);
|
||||
return -EIO;
|
||||
}
|
||||
adapter->physical_port = (val >> 2);
|
||||
}
|
||||
|
||||
adapter->physical_port = (val >> 2);
|
||||
|
||||
if (qlcnic_rom_fast_read(adapter, QLCNIC_ROM_DEV_INIT_TIMEOUT, &timeo))
|
||||
timeo = 30;
|
||||
|
||||
|
@ -1701,3 +1700,24 @@ qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring)
|
|||
sds_ring->consumer = consumer;
|
||||
writel(consumer, sds_ring->crb_sts_consumer);
|
||||
}
|
||||
|
||||
void
|
||||
qlcnic_fetch_mac(struct qlcnic_adapter *adapter, u32 off1, u32 off2,
|
||||
u8 alt_mac, u8 *mac)
|
||||
{
|
||||
u32 mac_low, mac_high;
|
||||
int i;
|
||||
|
||||
mac_low = QLCRD32(adapter, off1);
|
||||
mac_high = QLCRD32(adapter, off2);
|
||||
|
||||
if (alt_mac) {
|
||||
mac_low |= (mac_low >> 16) | (mac_high << 16);
|
||||
mac_high >>= 16;
|
||||
}
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
mac[i] = (u8)(mac_high >> ((1 - i) * 8));
|
||||
for (i = 2; i < 6; i++)
|
||||
mac[i] = (u8)(mac_low >> ((5 - i) * 8));
|
||||
}
|
||||
|
|
|
@ -65,6 +65,10 @@ static int load_fw_file;
|
|||
module_param(load_fw_file, int, 0644);
|
||||
MODULE_PARM_DESC(load_fw_file, "Load firmware from (0=flash, 1=file");
|
||||
|
||||
static int qlcnic_config_npars;
|
||||
module_param(qlcnic_config_npars, int, 0644);
|
||||
MODULE_PARM_DESC(qlcnic_config_npars, "Configure NPARs (0=disabled, 1=enabled");
|
||||
|
||||
static int __devinit qlcnic_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *ent);
|
||||
static void __devexit qlcnic_remove(struct pci_dev *pdev);
|
||||
|
@ -99,7 +103,14 @@ static irqreturn_t qlcnic_msix_intr(int irq, void *data);
|
|||
|
||||
static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev);
|
||||
static void qlcnic_config_indev_addr(struct net_device *dev, unsigned long);
|
||||
static int qlcnic_start_firmware(struct qlcnic_adapter *);
|
||||
|
||||
static void qlcnic_dev_set_npar_ready(struct qlcnic_adapter *);
|
||||
static void qlcnicvf_clear_ilb_mode(struct qlcnic_adapter *);
|
||||
static int qlcnicvf_set_ilb_mode(struct qlcnic_adapter *);
|
||||
static int qlcnicvf_config_led(struct qlcnic_adapter *, u32, u32);
|
||||
static int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *, u32);
|
||||
static int qlcnicvf_start_firmware(struct qlcnic_adapter *);
|
||||
/* PCI Device ID Table */
|
||||
#define ENTRY(device) \
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, (device)), \
|
||||
|
@ -307,19 +318,14 @@ static void qlcnic_init_msix_entries(struct qlcnic_adapter *adapter, int count)
|
|||
static int
|
||||
qlcnic_read_mac_addr(struct qlcnic_adapter *adapter)
|
||||
{
|
||||
int i;
|
||||
unsigned char *p;
|
||||
u64 mac_addr;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
struct net_device *netdev = adapter->netdev;
|
||||
struct pci_dev *pdev = adapter->pdev;
|
||||
|
||||
if (qlcnic_get_mac_addr(adapter, &mac_addr) != 0)
|
||||
if (adapter->nic_ops->get_mac_addr(adapter, mac_addr) != 0)
|
||||
return -EIO;
|
||||
|
||||
p = (unsigned char *)&mac_addr;
|
||||
for (i = 0; i < 6; i++)
|
||||
netdev->dev_addr[i] = *(p + 5 - i);
|
||||
|
||||
memcpy(netdev->dev_addr, mac_addr, ETH_ALEN);
|
||||
memcpy(netdev->perm_addr, netdev->dev_addr, netdev->addr_len);
|
||||
memcpy(adapter->mac_addr, netdev->dev_addr, netdev->addr_len);
|
||||
|
||||
|
@ -371,6 +377,33 @@ static const struct net_device_ops qlcnic_netdev_ops = {
|
|||
#endif
|
||||
};
|
||||
|
||||
static struct qlcnic_nic_template qlcnic_ops = {
|
||||
.get_mac_addr = qlcnic_get_mac_addr,
|
||||
.config_bridged_mode = qlcnic_config_bridged_mode,
|
||||
.config_led = qlcnic_config_led,
|
||||
.set_ilb_mode = qlcnic_set_ilb_mode,
|
||||
.clear_ilb_mode = qlcnic_clear_ilb_mode,
|
||||
.start_firmware = qlcnic_start_firmware
|
||||
};
|
||||
|
||||
static struct qlcnic_nic_template qlcnic_pf_ops = {
|
||||
.get_mac_addr = qlcnic_get_mac_address,
|
||||
.config_bridged_mode = qlcnic_config_bridged_mode,
|
||||
.config_led = qlcnic_config_led,
|
||||
.set_ilb_mode = qlcnic_set_ilb_mode,
|
||||
.clear_ilb_mode = qlcnic_clear_ilb_mode,
|
||||
.start_firmware = qlcnic_start_firmware
|
||||
};
|
||||
|
||||
static struct qlcnic_nic_template qlcnic_vf_ops = {
|
||||
.get_mac_addr = qlcnic_get_mac_address,
|
||||
.config_bridged_mode = qlcnicvf_config_bridged_mode,
|
||||
.config_led = qlcnicvf_config_led,
|
||||
.set_ilb_mode = qlcnicvf_set_ilb_mode,
|
||||
.clear_ilb_mode = qlcnicvf_clear_ilb_mode,
|
||||
.start_firmware = qlcnicvf_start_firmware
|
||||
};
|
||||
|
||||
static void
|
||||
qlcnic_setup_intr(struct qlcnic_adapter *adapter)
|
||||
{
|
||||
|
@ -452,6 +485,132 @@ qlcnic_cleanup_pci_map(struct qlcnic_adapter *adapter)
|
|||
iounmap(adapter->ahw.pci_base0);
|
||||
}
|
||||
|
||||
static int
|
||||
qlcnic_set_function_modes(struct qlcnic_adapter *adapter)
|
||||
{
|
||||
u8 id;
|
||||
u32 ref_count;
|
||||
int i, ret = 1;
|
||||
u32 data = QLCNIC_MGMT_FUNC;
|
||||
void __iomem *priv_op = adapter->ahw.pci_base0 + QLCNIC_DRV_OP_MODE;
|
||||
|
||||
/* If other drivers are not in use set their privilege level */
|
||||
ref_count = QLCRD32(adapter, QLCNIC_CRB_DEV_REF_COUNT);
|
||||
ret = qlcnic_api_lock(adapter);
|
||||
if (ret)
|
||||
goto err_lock;
|
||||
if (QLC_DEV_CLR_REF_CNT(ref_count, adapter->ahw.pci_func))
|
||||
goto err_npar;
|
||||
|
||||
for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
|
||||
id = adapter->npars[i].id;
|
||||
if (adapter->npars[i].type != QLCNIC_TYPE_NIC ||
|
||||
id == adapter->ahw.pci_func)
|
||||
continue;
|
||||
data |= (qlcnic_config_npars & QLC_DEV_SET_DRV(0xf, id));
|
||||
}
|
||||
writel(data, priv_op);
|
||||
|
||||
err_npar:
|
||||
qlcnic_api_unlock(adapter);
|
||||
err_lock:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u8
|
||||
qlcnic_set_mgmt_driver(struct qlcnic_adapter *adapter)
|
||||
{
|
||||
u8 i, ret = 0;
|
||||
|
||||
if (qlcnic_get_pci_info(adapter))
|
||||
return ret;
|
||||
/* Set the eswitch */
|
||||
for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++) {
|
||||
if (!qlcnic_get_eswitch_capabilities(adapter, i,
|
||||
&adapter->eswitch[i])) {
|
||||
ret++;
|
||||
qlcnic_toggle_eswitch(adapter, i, ret);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u32
|
||||
qlcnic_get_driver_mode(struct qlcnic_adapter *adapter)
|
||||
{
|
||||
void __iomem *msix_base_addr;
|
||||
void __iomem *priv_op;
|
||||
u32 func;
|
||||
u32 msix_base;
|
||||
u32 op_mode, priv_level;
|
||||
|
||||
/* Determine FW API version */
|
||||
adapter->fw_hal_version = readl(adapter->ahw.pci_base0 + QLCNIC_FW_API);
|
||||
if (adapter->fw_hal_version == ~0) {
|
||||
adapter->nic_ops = &qlcnic_ops;
|
||||
adapter->fw_hal_version = QLCNIC_FW_BASE;
|
||||
adapter->ahw.pci_func = PCI_FUNC(adapter->pdev->devfn);
|
||||
dev_info(&adapter->pdev->dev,
|
||||
"FW does not support nic partion\n");
|
||||
return adapter->fw_hal_version;
|
||||
}
|
||||
|
||||
/* Find PCI function number */
|
||||
pci_read_config_dword(adapter->pdev, QLCNIC_MSIX_TABLE_OFFSET, &func);
|
||||
msix_base_addr = adapter->ahw.pci_base0 + QLCNIC_MSIX_BASE;
|
||||
msix_base = readl(msix_base_addr);
|
||||
func = (func - msix_base)/QLCNIC_MSIX_TBL_PGSIZE;
|
||||
adapter->ahw.pci_func = func;
|
||||
|
||||
/* Determine function privilege level */
|
||||
priv_op = adapter->ahw.pci_base0 + QLCNIC_DRV_OP_MODE;
|
||||
op_mode = readl(priv_op);
|
||||
if (op_mode == QLC_DEV_DRV_DEFAULT) {
|
||||
priv_level = QLCNIC_MGMT_FUNC;
|
||||
if (qlcnic_api_lock(adapter))
|
||||
return 0;
|
||||
op_mode = (op_mode & ~QLC_DEV_SET_DRV(0xf, func)) |
|
||||
(QLC_DEV_SET_DRV(QLCNIC_MGMT_FUNC, func));
|
||||
writel(op_mode, priv_op);
|
||||
qlcnic_api_unlock(adapter);
|
||||
|
||||
} else
|
||||
priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw.pci_func);
|
||||
|
||||
switch (priv_level) {
|
||||
case QLCNIC_MGMT_FUNC:
|
||||
adapter->op_mode = QLCNIC_MGMT_FUNC;
|
||||
adapter->nic_ops = &qlcnic_pf_ops;
|
||||
/* Set privilege level for other functions */
|
||||
if (qlcnic_config_npars)
|
||||
qlcnic_set_function_modes(adapter);
|
||||
qlcnic_dev_set_npar_ready(adapter);
|
||||
dev_info(&adapter->pdev->dev,
|
||||
"HAL Version: %d, Management function\n",
|
||||
adapter->fw_hal_version);
|
||||
break;
|
||||
case QLCNIC_PRIV_FUNC:
|
||||
adapter->op_mode = QLCNIC_PRIV_FUNC;
|
||||
dev_info(&adapter->pdev->dev,
|
||||
"HAL Version: %d, Privileged function\n",
|
||||
adapter->fw_hal_version);
|
||||
adapter->nic_ops = &qlcnic_pf_ops;
|
||||
break;
|
||||
case QLCNIC_NON_PRIV_FUNC:
|
||||
adapter->op_mode = QLCNIC_NON_PRIV_FUNC;
|
||||
dev_info(&adapter->pdev->dev,
|
||||
"HAL Version: %d Non Privileged function\n",
|
||||
adapter->fw_hal_version);
|
||||
adapter->nic_ops = &qlcnic_vf_ops;
|
||||
break;
|
||||
default:
|
||||
dev_info(&adapter->pdev->dev, "Unknown function mode: %d\n",
|
||||
priv_level);
|
||||
return 0;
|
||||
}
|
||||
return adapter->fw_hal_version;
|
||||
}
|
||||
|
||||
static int
|
||||
qlcnic_setup_pci_map(struct qlcnic_adapter *adapter)
|
||||
{
|
||||
|
@ -460,7 +619,6 @@ qlcnic_setup_pci_map(struct qlcnic_adapter *adapter)
|
|||
unsigned long mem_len, pci_len0 = 0;
|
||||
|
||||
struct pci_dev *pdev = adapter->pdev;
|
||||
int pci_func = adapter->ahw.pci_func;
|
||||
|
||||
/* remap phys address */
|
||||
mem_base = pci_resource_start(pdev, 0); /* 0 is for BAR 0 */
|
||||
|
@ -483,8 +641,13 @@ qlcnic_setup_pci_map(struct qlcnic_adapter *adapter)
|
|||
adapter->ahw.pci_base0 = mem_ptr0;
|
||||
adapter->ahw.pci_len0 = pci_len0;
|
||||
|
||||
if (!qlcnic_get_driver_mode(adapter)) {
|
||||
iounmap(adapter->ahw.pci_base0);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
adapter->ahw.ocm_win_crb = qlcnic_get_ioaddr(adapter,
|
||||
QLCNIC_PCIX_PS_REG(PCIX_OCM_WINDOW_REG(pci_func)));
|
||||
QLCNIC_PCIX_PS_REG(PCIX_OCM_WINDOW_REG(adapter->ahw.pci_func)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -553,7 +716,10 @@ qlcnic_check_options(struct qlcnic_adapter *adapter)
|
|||
dev_info(&pdev->dev, "firmware v%d.%d.%d\n",
|
||||
fw_major, fw_minor, fw_build);
|
||||
|
||||
adapter->capabilities = QLCRD32(adapter, CRB_FW_CAPABILITIES_1);
|
||||
if (adapter->fw_hal_version == QLCNIC_FW_NPAR)
|
||||
qlcnic_get_nic_info(adapter, adapter->ahw.pci_func);
|
||||
else
|
||||
adapter->capabilities = QLCRD32(adapter, CRB_FW_CAPABILITIES_1);
|
||||
|
||||
adapter->flags &= ~QLCNIC_LRO_ENABLED;
|
||||
|
||||
|
@ -631,8 +797,14 @@ qlcnic_start_firmware(struct qlcnic_adapter *adapter)
|
|||
QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_READY);
|
||||
qlcnic_idc_debug_info(adapter, 1);
|
||||
|
||||
qlcnic_dev_set_npar_ready(adapter);
|
||||
|
||||
qlcnic_check_options(adapter);
|
||||
|
||||
if (adapter->fw_hal_version != QLCNIC_FW_BASE &&
|
||||
adapter->op_mode == QLCNIC_MGMT_FUNC)
|
||||
qlcnic_set_mgmt_driver(adapter);
|
||||
|
||||
adapter->need_fw_reset = 0;
|
||||
|
||||
qlcnic_release_firmware(adapter);
|
||||
|
@ -977,12 +1149,11 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter,
|
|||
|
||||
SET_ETHTOOL_OPS(netdev, &qlcnic_ethtool_ops);
|
||||
|
||||
netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO);
|
||||
netdev->features |= (NETIF_F_GRO);
|
||||
netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO);
|
||||
netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM |
|
||||
NETIF_F_IPV6_CSUM | NETIF_F_GRO | NETIF_F_TSO | NETIF_F_TSO6);
|
||||
|
||||
netdev->features |= (NETIF_F_IPV6_CSUM | NETIF_F_TSO6);
|
||||
netdev->vlan_features |= (NETIF_F_IPV6_CSUM | NETIF_F_TSO6);
|
||||
netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM |
|
||||
NETIF_F_IPV6_CSUM | NETIF_F_TSO | NETIF_F_TSO6);
|
||||
|
||||
if (pci_using_dac) {
|
||||
netdev->features |= NETIF_F_HIGHDMA;
|
||||
|
@ -1036,7 +1207,6 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
struct net_device *netdev = NULL;
|
||||
struct qlcnic_adapter *adapter = NULL;
|
||||
int err;
|
||||
int pci_func_id = PCI_FUNC(pdev->devfn);
|
||||
uint8_t revision_id;
|
||||
uint8_t pci_using_dac;
|
||||
|
||||
|
@ -1072,7 +1242,6 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
adapter->netdev = netdev;
|
||||
adapter->pdev = pdev;
|
||||
adapter->dev_rst_time = jiffies;
|
||||
adapter->ahw.pci_func = pci_func_id;
|
||||
|
||||
revision_id = pdev->revision;
|
||||
adapter->ahw.revision_id = revision_id;
|
||||
|
@ -1088,7 +1257,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
goto err_out_free_netdev;
|
||||
|
||||
/* This will be reset for mezz cards */
|
||||
adapter->portnum = pci_func_id;
|
||||
adapter->portnum = adapter->ahw.pci_func;
|
||||
|
||||
err = qlcnic_get_board_info(adapter);
|
||||
if (err) {
|
||||
|
@ -1102,7 +1271,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
if (qlcnic_setup_idc_param(adapter))
|
||||
goto err_out_iounmap;
|
||||
|
||||
err = qlcnic_start_firmware(adapter);
|
||||
err = adapter->nic_ops->start_firmware(adapter);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Loading fw failed.Please Reboot\n");
|
||||
goto err_out_decr_ref;
|
||||
|
@ -1175,6 +1344,11 @@ static void __devexit qlcnic_remove(struct pci_dev *pdev)
|
|||
|
||||
qlcnic_detach(adapter);
|
||||
|
||||
if (adapter->npars != NULL)
|
||||
kfree(adapter->npars);
|
||||
if (adapter->eswitch != NULL)
|
||||
kfree(adapter->eswitch);
|
||||
|
||||
qlcnic_clr_all_drv_state(adapter);
|
||||
|
||||
clear_bit(__QLCNIC_RESETTING, &adapter->state);
|
||||
|
@ -1263,7 +1437,7 @@ qlcnic_resume(struct pci_dev *pdev)
|
|||
pci_set_master(pdev);
|
||||
pci_restore_state(pdev);
|
||||
|
||||
err = qlcnic_start_firmware(adapter);
|
||||
err = adapter->nic_ops->start_firmware(adapter);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "failed to start firmware\n");
|
||||
return err;
|
||||
|
@ -1340,11 +1514,11 @@ qlcnic_tso_check(struct net_device *netdev,
|
|||
u8 opcode = TX_ETHER_PKT;
|
||||
__be16 protocol = skb->protocol;
|
||||
u16 flags = 0, vid = 0;
|
||||
u32 producer;
|
||||
int copied, offset, copy_len, hdr_len = 0, tso = 0, vlan_oob = 0;
|
||||
struct cmd_desc_type0 *hwdesc;
|
||||
struct vlan_ethhdr *vh;
|
||||
struct qlcnic_adapter *adapter = netdev_priv(netdev);
|
||||
u32 producer = tx_ring->producer;
|
||||
|
||||
if (protocol == cpu_to_be16(ETH_P_8021Q)) {
|
||||
|
||||
|
@ -1360,6 +1534,11 @@ qlcnic_tso_check(struct net_device *netdev,
|
|||
vlan_oob = 1;
|
||||
}
|
||||
|
||||
if (*(skb->data) & BIT_0) {
|
||||
flags |= BIT_0;
|
||||
memcpy(&first_desc->eth_addr, skb->data, ETH_ALEN);
|
||||
}
|
||||
|
||||
if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) &&
|
||||
skb_shinfo(skb)->gso_size > 0) {
|
||||
|
||||
|
@ -1409,7 +1588,6 @@ qlcnic_tso_check(struct net_device *netdev,
|
|||
/* For LSO, we need to copy the MAC/IP/TCP headers into
|
||||
* the descriptor ring
|
||||
*/
|
||||
producer = tx_ring->producer;
|
||||
copied = 0;
|
||||
offset = 2;
|
||||
|
||||
|
@ -2109,7 +2287,7 @@ qlcnic_fwinit_work(struct work_struct *work)
|
|||
{
|
||||
struct qlcnic_adapter *adapter = container_of(work,
|
||||
struct qlcnic_adapter, fw_work.work);
|
||||
u32 dev_state = 0xf;
|
||||
u32 dev_state = 0xf, npar_state;
|
||||
|
||||
if (qlcnic_api_lock(adapter))
|
||||
goto err_ret;
|
||||
|
@ -2122,6 +2300,19 @@ qlcnic_fwinit_work(struct work_struct *work)
|
|||
return;
|
||||
}
|
||||
|
||||
if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) {
|
||||
npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
|
||||
if (npar_state == QLCNIC_DEV_NPAR_RDY) {
|
||||
qlcnic_api_unlock(adapter);
|
||||
goto wait_npar;
|
||||
} else {
|
||||
qlcnic_schedule_work(adapter, qlcnic_fwinit_work,
|
||||
FW_POLL_DELAY);
|
||||
qlcnic_api_unlock(adapter);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (adapter->fw_wait_cnt++ > adapter->reset_ack_timeo) {
|
||||
dev_err(&adapter->pdev->dev, "Reset:Failed to get ack %d sec\n",
|
||||
adapter->reset_ack_timeo);
|
||||
|
@ -2154,7 +2345,7 @@ qlcnic_fwinit_work(struct work_struct *work)
|
|||
|
||||
qlcnic_api_unlock(adapter);
|
||||
|
||||
if (!qlcnic_start_firmware(adapter)) {
|
||||
if (!adapter->nic_ops->start_firmware(adapter)) {
|
||||
qlcnic_schedule_work(adapter, qlcnic_attach_work, 0);
|
||||
return;
|
||||
}
|
||||
|
@ -2163,6 +2354,7 @@ qlcnic_fwinit_work(struct work_struct *work)
|
|||
|
||||
qlcnic_api_unlock(adapter);
|
||||
|
||||
wait_npar:
|
||||
dev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
|
||||
QLCDB(adapter, HW, "Func waiting: Device state=%u\n", dev_state);
|
||||
|
||||
|
@ -2177,7 +2369,7 @@ qlcnic_fwinit_work(struct work_struct *work)
|
|||
break;
|
||||
|
||||
default:
|
||||
if (!qlcnic_start_firmware(adapter)) {
|
||||
if (!adapter->nic_ops->start_firmware(adapter)) {
|
||||
qlcnic_schedule_work(adapter, qlcnic_attach_work, 0);
|
||||
return;
|
||||
}
|
||||
|
@ -2251,6 +2443,30 @@ qlcnic_dev_request_reset(struct qlcnic_adapter *adapter)
|
|||
qlcnic_api_unlock(adapter);
|
||||
}
|
||||
|
||||
/* Transit to NPAR READY state from NPAR NOT READY state */
|
||||
static void
|
||||
qlcnic_dev_set_npar_ready(struct qlcnic_adapter *adapter)
|
||||
{
|
||||
u32 state;
|
||||
|
||||
if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC ||
|
||||
adapter->fw_hal_version == QLCNIC_FW_BASE)
|
||||
return;
|
||||
|
||||
if (qlcnic_api_lock(adapter))
|
||||
return;
|
||||
|
||||
state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
|
||||
|
||||
if (state != QLCNIC_DEV_NPAR_RDY) {
|
||||
QLCWR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE,
|
||||
QLCNIC_DEV_NPAR_RDY);
|
||||
QLCDB(adapter, DRV, "NPAR READY state set\n");
|
||||
}
|
||||
|
||||
qlcnic_api_unlock(adapter);
|
||||
}
|
||||
|
||||
static void
|
||||
qlcnic_schedule_work(struct qlcnic_adapter *adapter,
|
||||
work_func_t func, int delay)
|
||||
|
@ -2365,6 +2581,46 @@ qlcnic_fw_poll_work(struct work_struct *work)
|
|||
qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY);
|
||||
}
|
||||
|
||||
static int
|
||||
qlcnicvf_start_firmware(struct qlcnic_adapter *adapter)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = qlcnic_can_start_firmware(adapter);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
qlcnic_check_options(adapter);
|
||||
|
||||
adapter->need_fw_reset = 0;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
qlcnicvf_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static int
|
||||
qlcnicvf_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static int
|
||||
qlcnicvf_set_ilb_mode(struct qlcnic_adapter *adapter)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static void
|
||||
qlcnicvf_clear_ilb_mode(struct qlcnic_adapter *adapter)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
qlcnic_store_bridged_mode(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t len)
|
||||
|
@ -2382,7 +2638,7 @@ qlcnic_store_bridged_mode(struct device *dev,
|
|||
if (strict_strtoul(buf, 2, &new))
|
||||
goto err_out;
|
||||
|
||||
if (!qlcnic_config_bridged_mode(adapter, !!new))
|
||||
if (!adapter->nic_ops->config_bridged_mode(adapter, !!new))
|
||||
ret = len;
|
||||
|
||||
err_out:
|
||||
|
|
|
@ -1062,7 +1062,7 @@ struct tx_buf_desc {
|
|||
#define TX_DESC_LEN_MASK 0x000fffff
|
||||
#define TX_DESC_C 0x40000000
|
||||
#define TX_DESC_E 0x80000000
|
||||
} __attribute((packed));
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* IOCB Definitions...
|
||||
|
@ -1095,7 +1095,7 @@ struct ob_mac_iocb_req {
|
|||
__le16 vlan_tci;
|
||||
__le16 reserved4;
|
||||
struct tx_buf_desc tbd[TX_DESC_PER_IOCB];
|
||||
} __attribute((packed));
|
||||
} __packed;
|
||||
|
||||
struct ob_mac_iocb_rsp {
|
||||
u8 opcode; /* */
|
||||
|
@ -1112,7 +1112,7 @@ struct ob_mac_iocb_rsp {
|
|||
u32 tid;
|
||||
u32 txq_idx;
|
||||
__le32 reserved[13];
|
||||
} __attribute((packed));
|
||||
} __packed;
|
||||
|
||||
struct ob_mac_tso_iocb_req {
|
||||
u8 opcode;
|
||||
|
@ -1140,7 +1140,7 @@ struct ob_mac_tso_iocb_req {
|
|||
__le16 vlan_tci;
|
||||
__le16 mss;
|
||||
struct tx_buf_desc tbd[TX_DESC_PER_IOCB];
|
||||
} __attribute((packed));
|
||||
} __packed;
|
||||
|
||||
struct ob_mac_tso_iocb_rsp {
|
||||
u8 opcode;
|
||||
|
@ -1157,7 +1157,7 @@ struct ob_mac_tso_iocb_rsp {
|
|||
u32 tid;
|
||||
u32 txq_idx;
|
||||
__le32 reserved2[13];
|
||||
} __attribute((packed));
|
||||
} __packed;
|
||||
|
||||
struct ib_mac_iocb_rsp {
|
||||
u8 opcode; /* 0x20 */
|
||||
|
@ -1216,7 +1216,7 @@ struct ib_mac_iocb_rsp {
|
|||
#define IB_MAC_IOCB_RSP_HL 0x80
|
||||
__le32 hdr_len; /* */
|
||||
__le64 hdr_addr; /* */
|
||||
} __attribute((packed));
|
||||
} __packed;
|
||||
|
||||
struct ib_ae_iocb_rsp {
|
||||
u8 opcode;
|
||||
|
@ -1237,7 +1237,7 @@ struct ib_ae_iocb_rsp {
|
|||
#define PCI_ERR_ANON_BUF_RD 0x40
|
||||
u8 q_id;
|
||||
__le32 reserved[15];
|
||||
} __attribute((packed));
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* These three structures are for generic
|
||||
|
@ -1249,7 +1249,7 @@ struct ql_net_rsp_iocb {
|
|||
__le16 length;
|
||||
__le32 tid;
|
||||
__le32 reserved[14];
|
||||
} __attribute((packed));
|
||||
} __packed;
|
||||
|
||||
struct net_req_iocb {
|
||||
u8 opcode;
|
||||
|
@ -1257,7 +1257,7 @@ struct net_req_iocb {
|
|||
__le16 flags1;
|
||||
__le32 tid;
|
||||
__le32 reserved1[30];
|
||||
} __attribute((packed));
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* tx ring initialization control block for chip.
|
||||
|
@ -1283,7 +1283,7 @@ struct wqicb {
|
|||
__le16 rid;
|
||||
__le64 addr;
|
||||
__le64 cnsmr_idx_addr;
|
||||
} __attribute((packed));
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* rx ring initialization control block for chip.
|
||||
|
@ -1317,7 +1317,7 @@ struct cqicb {
|
|||
__le64 sbq_addr;
|
||||
__le16 sbq_buf_size;
|
||||
__le16 sbq_len; /* entry count */
|
||||
} __attribute((packed));
|
||||
} __packed;
|
||||
|
||||
struct ricb {
|
||||
u8 base_cq;
|
||||
|
@ -1335,7 +1335,7 @@ struct ricb {
|
|||
u8 hash_cq_id[1024];
|
||||
__le32 ipv6_hash_key[10];
|
||||
__le32 ipv4_hash_key[4];
|
||||
} __attribute((packed));
|
||||
} __packed;
|
||||
|
||||
/* SOFTWARE/DRIVER DATA STRUCTURES. */
|
||||
|
||||
|
|
|
@ -44,12 +44,13 @@
|
|||
#include <linux/io.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/phy.h>
|
||||
|
||||
#include <asm/processor.h>
|
||||
|
||||
#define DRV_NAME "r6040"
|
||||
#define DRV_VERSION "0.25"
|
||||
#define DRV_RELDATE "20Aug2009"
|
||||
#define DRV_VERSION "0.26"
|
||||
#define DRV_RELDATE "30May2010"
|
||||
|
||||
/* PHY CHIP Address */
|
||||
#define PHY1_ADDR 1 /* For MAC1 */
|
||||
|
@ -179,7 +180,6 @@ struct r6040_descriptor {
|
|||
|
||||
struct r6040_private {
|
||||
spinlock_t lock; /* driver lock */
|
||||
struct timer_list timer;
|
||||
struct pci_dev *pdev;
|
||||
struct r6040_descriptor *rx_insert_ptr;
|
||||
struct r6040_descriptor *rx_remove_ptr;
|
||||
|
@ -189,13 +189,15 @@ struct r6040_private {
|
|||
struct r6040_descriptor *tx_ring;
|
||||
dma_addr_t rx_ring_dma;
|
||||
dma_addr_t tx_ring_dma;
|
||||
u16 tx_free_desc, phy_addr, phy_mode;
|
||||
u16 tx_free_desc, phy_addr;
|
||||
u16 mcr0, mcr1;
|
||||
u16 switch_sig;
|
||||
struct net_device *dev;
|
||||
struct mii_if_info mii_if;
|
||||
struct mii_bus *mii_bus;
|
||||
struct napi_struct napi;
|
||||
void __iomem *base;
|
||||
struct phy_device *phydev;
|
||||
int old_link;
|
||||
int old_duplex;
|
||||
};
|
||||
|
||||
static char version[] __devinitdata = KERN_INFO DRV_NAME
|
||||
|
@ -238,20 +240,30 @@ static void r6040_phy_write(void __iomem *ioaddr, int phy_addr, int reg, u16 val
|
|||
}
|
||||
}
|
||||
|
||||
static int r6040_mdio_read(struct net_device *dev, int mii_id, int reg)
|
||||
static int r6040_mdiobus_read(struct mii_bus *bus, int phy_addr, int reg)
|
||||
{
|
||||
struct net_device *dev = bus->priv;
|
||||
struct r6040_private *lp = netdev_priv(dev);
|
||||
void __iomem *ioaddr = lp->base;
|
||||
|
||||
return (r6040_phy_read(ioaddr, lp->phy_addr, reg));
|
||||
return r6040_phy_read(ioaddr, phy_addr, reg);
|
||||
}
|
||||
|
||||
static void r6040_mdio_write(struct net_device *dev, int mii_id, int reg, int val)
|
||||
static int r6040_mdiobus_write(struct mii_bus *bus, int phy_addr,
|
||||
int reg, u16 value)
|
||||
{
|
||||
struct net_device *dev = bus->priv;
|
||||
struct r6040_private *lp = netdev_priv(dev);
|
||||
void __iomem *ioaddr = lp->base;
|
||||
|
||||
r6040_phy_write(ioaddr, lp->phy_addr, reg, val);
|
||||
r6040_phy_write(ioaddr, phy_addr, reg, value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int r6040_mdiobus_reset(struct mii_bus *bus)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void r6040_free_txbufs(struct net_device *dev)
|
||||
|
@ -408,10 +420,9 @@ static void r6040_tx_timeout(struct net_device *dev)
|
|||
void __iomem *ioaddr = priv->base;
|
||||
|
||||
netdev_warn(dev, "transmit timed out, int enable %4.4x "
|
||||
"status %4.4x, PHY status %4.4x\n",
|
||||
"status %4.4x\n",
|
||||
ioread16(ioaddr + MIER),
|
||||
ioread16(ioaddr + MISR),
|
||||
r6040_mdio_read(dev, priv->mii_if.phy_id, MII_BMSR));
|
||||
ioread16(ioaddr + MISR));
|
||||
|
||||
dev->stats.tx_errors++;
|
||||
|
||||
|
@ -463,9 +474,6 @@ static int r6040_close(struct net_device *dev)
|
|||
struct r6040_private *lp = netdev_priv(dev);
|
||||
struct pci_dev *pdev = lp->pdev;
|
||||
|
||||
/* deleted timer */
|
||||
del_timer_sync(&lp->timer);
|
||||
|
||||
spin_lock_irq(&lp->lock);
|
||||
napi_disable(&lp->napi);
|
||||
netif_stop_queue(dev);
|
||||
|
@ -495,64 +503,14 @@ static int r6040_close(struct net_device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Status of PHY CHIP */
|
||||
static int r6040_phy_mode_chk(struct net_device *dev)
|
||||
{
|
||||
struct r6040_private *lp = netdev_priv(dev);
|
||||
void __iomem *ioaddr = lp->base;
|
||||
int phy_dat;
|
||||
|
||||
/* PHY Link Status Check */
|
||||
phy_dat = r6040_phy_read(ioaddr, lp->phy_addr, 1);
|
||||
if (!(phy_dat & 0x4))
|
||||
phy_dat = 0x8000; /* Link Failed, full duplex */
|
||||
|
||||
/* PHY Chip Auto-Negotiation Status */
|
||||
phy_dat = r6040_phy_read(ioaddr, lp->phy_addr, 1);
|
||||
if (phy_dat & 0x0020) {
|
||||
/* Auto Negotiation Mode */
|
||||
phy_dat = r6040_phy_read(ioaddr, lp->phy_addr, 5);
|
||||
phy_dat &= r6040_phy_read(ioaddr, lp->phy_addr, 4);
|
||||
if (phy_dat & 0x140)
|
||||
/* Force full duplex */
|
||||
phy_dat = 0x8000;
|
||||
else
|
||||
phy_dat = 0;
|
||||
} else {
|
||||
/* Force Mode */
|
||||
phy_dat = r6040_phy_read(ioaddr, lp->phy_addr, 0);
|
||||
if (phy_dat & 0x100)
|
||||
phy_dat = 0x8000;
|
||||
else
|
||||
phy_dat = 0x0000;
|
||||
}
|
||||
|
||||
return phy_dat;
|
||||
};
|
||||
|
||||
static void r6040_set_carrier(struct mii_if_info *mii)
|
||||
{
|
||||
if (r6040_phy_mode_chk(mii->dev)) {
|
||||
/* autoneg is off: Link is always assumed to be up */
|
||||
if (!netif_carrier_ok(mii->dev))
|
||||
netif_carrier_on(mii->dev);
|
||||
} else
|
||||
r6040_phy_mode_chk(mii->dev);
|
||||
}
|
||||
|
||||
static int r6040_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
|
||||
{
|
||||
struct r6040_private *lp = netdev_priv(dev);
|
||||
struct mii_ioctl_data *data = if_mii(rq);
|
||||
int rc;
|
||||
|
||||
if (!netif_running(dev))
|
||||
if (!lp->phydev)
|
||||
return -EINVAL;
|
||||
spin_lock_irq(&lp->lock);
|
||||
rc = generic_mii_ioctl(&lp->mii_if, data, cmd, NULL);
|
||||
spin_unlock_irq(&lp->lock);
|
||||
r6040_set_carrier(&lp->mii_if);
|
||||
return rc;
|
||||
|
||||
return phy_mii_ioctl(lp->phydev, if_mii(rq), cmd);
|
||||
}
|
||||
|
||||
static int r6040_rx(struct net_device *dev, int limit)
|
||||
|
@ -751,26 +709,6 @@ static int r6040_up(struct net_device *dev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Read the PHY ID */
|
||||
lp->switch_sig = r6040_phy_read(ioaddr, 0, 2);
|
||||
|
||||
if (lp->switch_sig == ICPLUS_PHY_ID) {
|
||||
r6040_phy_write(ioaddr, 29, 31, 0x175C); /* Enable registers */
|
||||
lp->phy_mode = 0x8000;
|
||||
} else {
|
||||
/* PHY Mode Check */
|
||||
r6040_phy_write(ioaddr, lp->phy_addr, 4, PHY_CAP);
|
||||
r6040_phy_write(ioaddr, lp->phy_addr, 0, PHY_MODE);
|
||||
|
||||
if (PHY_MODE == 0x3100)
|
||||
lp->phy_mode = r6040_phy_mode_chk(dev);
|
||||
else
|
||||
lp->phy_mode = (PHY_MODE & 0x0100) ? 0x8000:0x0;
|
||||
}
|
||||
|
||||
/* Set duplex mode */
|
||||
lp->mcr0 |= lp->phy_mode;
|
||||
|
||||
/* improve performance (by RDC guys) */
|
||||
r6040_phy_write(ioaddr, 30, 17, (r6040_phy_read(ioaddr, 30, 17) | 0x4000));
|
||||
r6040_phy_write(ioaddr, 30, 17, ~((~r6040_phy_read(ioaddr, 30, 17)) | 0x2000));
|
||||
|
@ -783,35 +721,6 @@ static int r6040_up(struct net_device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
A periodic timer routine
|
||||
Polling PHY Chip Link Status
|
||||
*/
|
||||
static void r6040_timer(unsigned long data)
|
||||
{
|
||||
struct net_device *dev = (struct net_device *)data;
|
||||
struct r6040_private *lp = netdev_priv(dev);
|
||||
void __iomem *ioaddr = lp->base;
|
||||
u16 phy_mode;
|
||||
|
||||
/* Polling PHY Chip Status */
|
||||
if (PHY_MODE == 0x3100)
|
||||
phy_mode = r6040_phy_mode_chk(dev);
|
||||
else
|
||||
phy_mode = (PHY_MODE & 0x0100) ? 0x8000:0x0;
|
||||
|
||||
if (phy_mode != lp->phy_mode) {
|
||||
lp->phy_mode = phy_mode;
|
||||
lp->mcr0 = (lp->mcr0 & 0x7fff) | phy_mode;
|
||||
iowrite16(lp->mcr0, ioaddr);
|
||||
}
|
||||
|
||||
/* Timer active again */
|
||||
mod_timer(&lp->timer, round_jiffies(jiffies + HZ));
|
||||
|
||||
/* Check media */
|
||||
mii_check_media(&lp->mii_if, 1, 1);
|
||||
}
|
||||
|
||||
/* Read/set MAC address routines */
|
||||
static void r6040_mac_address(struct net_device *dev)
|
||||
|
@ -873,10 +782,6 @@ static int r6040_open(struct net_device *dev)
|
|||
napi_enable(&lp->napi);
|
||||
netif_start_queue(dev);
|
||||
|
||||
/* set and active a timer process */
|
||||
setup_timer(&lp->timer, r6040_timer, (unsigned long) dev);
|
||||
if (lp->switch_sig != ICPLUS_PHY_ID)
|
||||
mod_timer(&lp->timer, jiffies + HZ);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1015,40 +920,22 @@ static void netdev_get_drvinfo(struct net_device *dev,
|
|||
static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
|
||||
{
|
||||
struct r6040_private *rp = netdev_priv(dev);
|
||||
int rc;
|
||||
|
||||
spin_lock_irq(&rp->lock);
|
||||
rc = mii_ethtool_gset(&rp->mii_if, cmd);
|
||||
spin_unlock_irq(&rp->lock);
|
||||
|
||||
return rc;
|
||||
return phy_ethtool_gset(rp->phydev, cmd);
|
||||
}
|
||||
|
||||
static int netdev_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
|
||||
{
|
||||
struct r6040_private *rp = netdev_priv(dev);
|
||||
int rc;
|
||||
|
||||
spin_lock_irq(&rp->lock);
|
||||
rc = mii_ethtool_sset(&rp->mii_if, cmd);
|
||||
spin_unlock_irq(&rp->lock);
|
||||
r6040_set_carrier(&rp->mii_if);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static u32 netdev_get_link(struct net_device *dev)
|
||||
{
|
||||
struct r6040_private *rp = netdev_priv(dev);
|
||||
|
||||
return mii_link_ok(&rp->mii_if);
|
||||
return phy_ethtool_sset(rp->phydev, cmd);
|
||||
}
|
||||
|
||||
static const struct ethtool_ops netdev_ethtool_ops = {
|
||||
.get_drvinfo = netdev_get_drvinfo,
|
||||
.get_settings = netdev_get_settings,
|
||||
.set_settings = netdev_set_settings,
|
||||
.get_link = netdev_get_link,
|
||||
.get_link = ethtool_op_get_link,
|
||||
};
|
||||
|
||||
static const struct net_device_ops r6040_netdev_ops = {
|
||||
|
@ -1067,6 +954,79 @@ static const struct net_device_ops r6040_netdev_ops = {
|
|||
#endif
|
||||
};
|
||||
|
||||
static void r6040_adjust_link(struct net_device *dev)
|
||||
{
|
||||
struct r6040_private *lp = netdev_priv(dev);
|
||||
struct phy_device *phydev = lp->phydev;
|
||||
int status_changed = 0;
|
||||
void __iomem *ioaddr = lp->base;
|
||||
|
||||
BUG_ON(!phydev);
|
||||
|
||||
if (lp->old_link != phydev->link) {
|
||||
status_changed = 1;
|
||||
lp->old_link = phydev->link;
|
||||
}
|
||||
|
||||
/* reflect duplex change */
|
||||
if (phydev->link && (lp->old_duplex != phydev->duplex)) {
|
||||
lp->mcr0 |= (phydev->duplex == DUPLEX_FULL ? 0x8000 : 0);
|
||||
iowrite16(lp->mcr0, ioaddr);
|
||||
|
||||
status_changed = 1;
|
||||
lp->old_duplex = phydev->duplex;
|
||||
}
|
||||
|
||||
if (status_changed) {
|
||||
pr_info("%s: link %s", dev->name, phydev->link ?
|
||||
"UP" : "DOWN");
|
||||
if (phydev->link)
|
||||
pr_cont(" - %d/%s", phydev->speed,
|
||||
DUPLEX_FULL == phydev->duplex ? "full" : "half");
|
||||
pr_cont("\n");
|
||||
}
|
||||
}
|
||||
|
||||
static int r6040_mii_probe(struct net_device *dev)
|
||||
{
|
||||
struct r6040_private *lp = netdev_priv(dev);
|
||||
struct phy_device *phydev = NULL;
|
||||
|
||||
phydev = phy_find_first(lp->mii_bus);
|
||||
if (!phydev) {
|
||||
dev_err(&lp->pdev->dev, "no PHY found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
phydev = phy_connect(dev, dev_name(&phydev->dev), &r6040_adjust_link,
|
||||
0, PHY_INTERFACE_MODE_MII);
|
||||
|
||||
if (IS_ERR(phydev)) {
|
||||
dev_err(&lp->pdev->dev, "could not attach to PHY\n");
|
||||
return PTR_ERR(phydev);
|
||||
}
|
||||
|
||||
/* mask with MAC supported features */
|
||||
phydev->supported &= (SUPPORTED_10baseT_Half
|
||||
| SUPPORTED_10baseT_Full
|
||||
| SUPPORTED_100baseT_Half
|
||||
| SUPPORTED_100baseT_Full
|
||||
| SUPPORTED_Autoneg
|
||||
| SUPPORTED_MII
|
||||
| SUPPORTED_TP);
|
||||
|
||||
phydev->advertising = phydev->supported;
|
||||
lp->phydev = phydev;
|
||||
lp->old_link = 0;
|
||||
lp->old_duplex = -1;
|
||||
|
||||
dev_info(&lp->pdev->dev, "attached PHY driver [%s] "
|
||||
"(mii_bus:phy_addr=%s)\n",
|
||||
phydev->drv->name, dev_name(&phydev->dev));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit r6040_init_one(struct pci_dev *pdev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
|
@ -1077,6 +1037,7 @@ static int __devinit r6040_init_one(struct pci_dev *pdev,
|
|||
static int card_idx = -1;
|
||||
int bar = 0;
|
||||
u16 *adrp;
|
||||
int i;
|
||||
|
||||
printk("%s\n", version);
|
||||
|
||||
|
@ -1163,7 +1124,6 @@ static int __devinit r6040_init_one(struct pci_dev *pdev,
|
|||
/* Init RDC private data */
|
||||
lp->mcr0 = 0x1002;
|
||||
lp->phy_addr = phy_table[card_idx];
|
||||
lp->switch_sig = 0;
|
||||
|
||||
/* The RDC-specific entries in the device structure. */
|
||||
dev->netdev_ops = &r6040_netdev_ops;
|
||||
|
@ -1171,28 +1131,54 @@ static int __devinit r6040_init_one(struct pci_dev *pdev,
|
|||
dev->watchdog_timeo = TX_TIMEOUT;
|
||||
|
||||
netif_napi_add(dev, &lp->napi, r6040_poll, 64);
|
||||
lp->mii_if.dev = dev;
|
||||
lp->mii_if.mdio_read = r6040_mdio_read;
|
||||
lp->mii_if.mdio_write = r6040_mdio_write;
|
||||
lp->mii_if.phy_id = lp->phy_addr;
|
||||
lp->mii_if.phy_id_mask = 0x1f;
|
||||
lp->mii_if.reg_num_mask = 0x1f;
|
||||
|
||||
/* Check the vendor ID on the PHY, if 0xffff assume none attached */
|
||||
if (r6040_phy_read(ioaddr, lp->phy_addr, 2) == 0xffff) {
|
||||
dev_err(&pdev->dev, "Failed to detect an attached PHY\n");
|
||||
err = -ENODEV;
|
||||
lp->mii_bus = mdiobus_alloc();
|
||||
if (!lp->mii_bus) {
|
||||
dev_err(&pdev->dev, "mdiobus_alloc() failed\n");
|
||||
goto err_out_unmap;
|
||||
}
|
||||
|
||||
lp->mii_bus->priv = dev;
|
||||
lp->mii_bus->read = r6040_mdiobus_read;
|
||||
lp->mii_bus->write = r6040_mdiobus_write;
|
||||
lp->mii_bus->reset = r6040_mdiobus_reset;
|
||||
lp->mii_bus->name = "r6040_eth_mii";
|
||||
snprintf(lp->mii_bus->id, MII_BUS_ID_SIZE, "%x", card_idx);
|
||||
lp->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
|
||||
if (!lp->mii_bus->irq) {
|
||||
dev_err(&pdev->dev, "mii_bus irq allocation failed\n");
|
||||
goto err_out_mdio;
|
||||
}
|
||||
|
||||
for (i = 0; i < PHY_MAX_ADDR; i++)
|
||||
lp->mii_bus->irq[i] = PHY_POLL;
|
||||
|
||||
err = mdiobus_register(lp->mii_bus);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "failed to register MII bus\n");
|
||||
goto err_out_mdio_irq;
|
||||
}
|
||||
|
||||
err = r6040_mii_probe(dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "failed to probe MII bus\n");
|
||||
goto err_out_mdio_unregister;
|
||||
}
|
||||
|
||||
/* Register net device. After this dev->name assign */
|
||||
err = register_netdev(dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Failed to register net device\n");
|
||||
goto err_out_unmap;
|
||||
goto err_out_mdio_unregister;
|
||||
}
|
||||
return 0;
|
||||
|
||||
err_out_mdio_unregister:
|
||||
mdiobus_unregister(lp->mii_bus);
|
||||
err_out_mdio_irq:
|
||||
kfree(lp->mii_bus->irq);
|
||||
err_out_mdio:
|
||||
mdiobus_free(lp->mii_bus);
|
||||
err_out_unmap:
|
||||
pci_iounmap(pdev, ioaddr);
|
||||
err_out_free_res:
|
||||
|
@ -1206,8 +1192,12 @@ static int __devinit r6040_init_one(struct pci_dev *pdev,
|
|||
static void __devexit r6040_remove_one(struct pci_dev *pdev)
|
||||
{
|
||||
struct net_device *dev = pci_get_drvdata(pdev);
|
||||
struct r6040_private *lp = netdev_priv(dev);
|
||||
|
||||
unregister_netdev(dev);
|
||||
mdiobus_unregister(lp->mii_bus);
|
||||
kfree(lp->mii_bus->irq);
|
||||
mdiobus_free(lp->mii_bus);
|
||||
pci_release_regions(pdev);
|
||||
free_netdev(dev);
|
||||
pci_disable_device(pdev);
|
||||
|
|
|
@ -559,6 +559,11 @@ static void mdio_write(void __iomem *ioaddr, int reg_addr, int value)
|
|||
break;
|
||||
udelay(25);
|
||||
}
|
||||
/*
|
||||
* According to hardware specs a 20us delay is required after write
|
||||
* complete indication, but before sending next command.
|
||||
*/
|
||||
udelay(20);
|
||||
}
|
||||
|
||||
static int mdio_read(void __iomem *ioaddr, int reg_addr)
|
||||
|
@ -578,6 +583,12 @@ static int mdio_read(void __iomem *ioaddr, int reg_addr)
|
|||
}
|
||||
udelay(25);
|
||||
}
|
||||
/*
|
||||
* According to hardware specs a 20us delay is required after read
|
||||
* complete indication, but before sending next command.
|
||||
*/
|
||||
udelay(20);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "nic.h"
|
||||
|
||||
#include "mcdi.h"
|
||||
#include "workarounds.h"
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
|
@ -92,13 +93,6 @@ const char *efx_reset_type_names[] = {
|
|||
|
||||
#define EFX_MAX_MTU (9 * 1024)
|
||||
|
||||
/* RX slow fill workqueue. If memory allocation fails in the fast path,
|
||||
* a work item is pushed onto this work queue to retry the allocation later,
|
||||
* to avoid the NIC being starved of RX buffers. Since this is a per cpu
|
||||
* workqueue, there is nothing to be gained in making it per NIC
|
||||
*/
|
||||
static struct workqueue_struct *refill_workqueue;
|
||||
|
||||
/* Reset workqueue. If any NIC has a hardware failure then a reset will be
|
||||
* queued onto this work queue. This is not a per-nic work queue, because
|
||||
* efx_reset_work() acquires the rtnl lock, so resets are naturally serialised.
|
||||
|
@ -475,7 +469,8 @@ static void efx_init_channels(struct efx_nic *efx)
|
|||
efx->rx_buffer_len = (max(EFX_PAGE_IP_ALIGN, NET_IP_ALIGN) +
|
||||
EFX_MAX_FRAME_LEN(efx->net_dev->mtu) +
|
||||
efx->type->rx_buffer_padding);
|
||||
efx->rx_buffer_order = get_order(efx->rx_buffer_len);
|
||||
efx->rx_buffer_order = get_order(efx->rx_buffer_len +
|
||||
sizeof(struct efx_rx_page_state));
|
||||
|
||||
/* Initialise the channels */
|
||||
efx_for_each_channel(channel, efx) {
|
||||
|
@ -515,11 +510,11 @@ static void efx_start_channel(struct efx_channel *channel)
|
|||
channel->enabled = true;
|
||||
smp_wmb();
|
||||
|
||||
napi_enable(&channel->napi_str);
|
||||
|
||||
/* Load up RX descriptors */
|
||||
/* Fill the queues before enabling NAPI */
|
||||
efx_for_each_channel_rx_queue(rx_queue, channel)
|
||||
efx_fast_push_rx_descriptors(rx_queue);
|
||||
|
||||
napi_enable(&channel->napi_str);
|
||||
}
|
||||
|
||||
/* This disables event queue processing and packet transmission.
|
||||
|
@ -528,8 +523,6 @@ static void efx_start_channel(struct efx_channel *channel)
|
|||
*/
|
||||
static void efx_stop_channel(struct efx_channel *channel)
|
||||
{
|
||||
struct efx_rx_queue *rx_queue;
|
||||
|
||||
if (!channel->enabled)
|
||||
return;
|
||||
|
||||
|
@ -537,12 +530,6 @@ static void efx_stop_channel(struct efx_channel *channel)
|
|||
|
||||
channel->enabled = false;
|
||||
napi_disable(&channel->napi_str);
|
||||
|
||||
/* Ensure that any worker threads have exited or will be no-ops */
|
||||
efx_for_each_channel_rx_queue(rx_queue, channel) {
|
||||
spin_lock_bh(&rx_queue->add_lock);
|
||||
spin_unlock_bh(&rx_queue->add_lock);
|
||||
}
|
||||
}
|
||||
|
||||
static void efx_fini_channels(struct efx_nic *efx)
|
||||
|
@ -556,10 +543,18 @@ static void efx_fini_channels(struct efx_nic *efx)
|
|||
BUG_ON(efx->port_enabled);
|
||||
|
||||
rc = efx_nic_flush_queues(efx);
|
||||
if (rc)
|
||||
if (rc && EFX_WORKAROUND_7803(efx)) {
|
||||
/* Schedule a reset to recover from the flush failure. The
|
||||
* descriptor caches reference memory we're about to free,
|
||||
* but falcon_reconfigure_mac_wrapper() won't reconnect
|
||||
* the MACs because of the pending reset. */
|
||||
EFX_ERR(efx, "Resetting to recover from flush failure\n");
|
||||
efx_schedule_reset(efx, RESET_TYPE_ALL);
|
||||
} else if (rc) {
|
||||
EFX_ERR(efx, "failed to flush queues\n");
|
||||
else
|
||||
} else {
|
||||
EFX_LOG(efx, "successfully flushed all queues\n");
|
||||
}
|
||||
|
||||
efx_for_each_channel(channel, efx) {
|
||||
EFX_LOG(channel->efx, "shut down chan %d\n", channel->channel);
|
||||
|
@ -586,9 +581,9 @@ static void efx_remove_channel(struct efx_channel *channel)
|
|||
efx_remove_eventq(channel);
|
||||
}
|
||||
|
||||
void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue, int delay)
|
||||
void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue)
|
||||
{
|
||||
queue_delayed_work(refill_workqueue, &rx_queue->work, delay);
|
||||
mod_timer(&rx_queue->slow_fill, jiffies + msecs_to_jiffies(100));
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
|
@ -1233,15 +1228,8 @@ static void efx_start_all(struct efx_nic *efx)
|
|||
* since we're holding the rtnl_lock at this point. */
|
||||
static void efx_flush_all(struct efx_nic *efx)
|
||||
{
|
||||
struct efx_rx_queue *rx_queue;
|
||||
|
||||
/* Make sure the hardware monitor is stopped */
|
||||
cancel_delayed_work_sync(&efx->monitor_work);
|
||||
|
||||
/* Ensure that all RX slow refills are complete. */
|
||||
efx_for_each_rx_queue(rx_queue, efx)
|
||||
cancel_delayed_work_sync(&rx_queue->work);
|
||||
|
||||
/* Stop scheduled port reconfigurations */
|
||||
cancel_work_sync(&efx->mac_work);
|
||||
}
|
||||
|
@ -1504,11 +1492,11 @@ static int efx_net_stop(struct net_device *net_dev)
|
|||
}
|
||||
|
||||
/* Context: process, dev_base_lock or RTNL held, non-blocking. */
|
||||
static struct net_device_stats *efx_net_stats(struct net_device *net_dev)
|
||||
static struct rtnl_link_stats64 *efx_net_stats(struct net_device *net_dev)
|
||||
{
|
||||
struct efx_nic *efx = netdev_priv(net_dev);
|
||||
struct efx_mac_stats *mac_stats = &efx->mac_stats;
|
||||
struct net_device_stats *stats = &net_dev->stats;
|
||||
struct rtnl_link_stats64 *stats = &net_dev->stats64;
|
||||
|
||||
spin_lock_bh(&efx->stats_lock);
|
||||
efx->type->update_stats(efx);
|
||||
|
@ -1530,11 +1518,8 @@ static struct net_device_stats *efx_net_stats(struct net_device *net_dev)
|
|||
stats->tx_window_errors = mac_stats->tx_late_collision;
|
||||
|
||||
stats->rx_errors = (stats->rx_length_errors +
|
||||
stats->rx_over_errors +
|
||||
stats->rx_crc_errors +
|
||||
stats->rx_frame_errors +
|
||||
stats->rx_fifo_errors +
|
||||
stats->rx_missed_errors +
|
||||
mac_stats->rx_symbol_error);
|
||||
stats->tx_errors = (stats->tx_window_errors +
|
||||
mac_stats->tx_bad);
|
||||
|
@ -1645,7 +1630,7 @@ static void efx_set_multicast_list(struct net_device *net_dev)
|
|||
static const struct net_device_ops efx_netdev_ops = {
|
||||
.ndo_open = efx_net_open,
|
||||
.ndo_stop = efx_net_stop,
|
||||
.ndo_get_stats = efx_net_stats,
|
||||
.ndo_get_stats64 = efx_net_stats,
|
||||
.ndo_tx_timeout = efx_watchdog,
|
||||
.ndo_start_xmit = efx_hard_start_xmit,
|
||||
.ndo_validate_addr = eth_validate_addr,
|
||||
|
@ -1886,6 +1871,9 @@ static void efx_reset_work(struct work_struct *data)
|
|||
{
|
||||
struct efx_nic *efx = container_of(data, struct efx_nic, reset_work);
|
||||
|
||||
if (efx->reset_pending == RESET_TYPE_NONE)
|
||||
return;
|
||||
|
||||
/* If we're not RUNNING then don't reset. Leave the reset_pending
|
||||
* flag set so that efx_pci_probe_main will be retried */
|
||||
if (efx->state != STATE_RUNNING) {
|
||||
|
@ -2052,8 +2040,8 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
|
|||
rx_queue->queue = i;
|
||||
rx_queue->channel = &efx->channel[0]; /* for safety */
|
||||
rx_queue->buffer = NULL;
|
||||
spin_lock_init(&rx_queue->add_lock);
|
||||
INIT_DELAYED_WORK(&rx_queue->work, efx_rx_work);
|
||||
setup_timer(&rx_queue->slow_fill, efx_rx_slow_fill,
|
||||
(unsigned long)rx_queue);
|
||||
}
|
||||
|
||||
efx->type = type;
|
||||
|
@ -2332,6 +2320,9 @@ static int efx_pm_thaw(struct device *dev)
|
|||
|
||||
efx->type->resume_wol(efx);
|
||||
|
||||
/* Reschedule any quenched resets scheduled during efx_pm_freeze() */
|
||||
queue_work(reset_workqueue, &efx->reset_work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2421,11 +2412,6 @@ static int __init efx_init_module(void)
|
|||
if (rc)
|
||||
goto err_notifier;
|
||||
|
||||
refill_workqueue = create_workqueue("sfc_refill");
|
||||
if (!refill_workqueue) {
|
||||
rc = -ENOMEM;
|
||||
goto err_refill;
|
||||
}
|
||||
reset_workqueue = create_singlethread_workqueue("sfc_reset");
|
||||
if (!reset_workqueue) {
|
||||
rc = -ENOMEM;
|
||||
|
@ -2441,8 +2427,6 @@ static int __init efx_init_module(void)
|
|||
err_pci:
|
||||
destroy_workqueue(reset_workqueue);
|
||||
err_reset:
|
||||
destroy_workqueue(refill_workqueue);
|
||||
err_refill:
|
||||
unregister_netdevice_notifier(&efx_netdev_notifier);
|
||||
err_notifier:
|
||||
return rc;
|
||||
|
@ -2454,7 +2438,6 @@ static void __exit efx_exit_module(void)
|
|||
|
||||
pci_unregister_driver(&efx_pci_driver);
|
||||
destroy_workqueue(reset_workqueue);
|
||||
destroy_workqueue(refill_workqueue);
|
||||
unregister_netdevice_notifier(&efx_netdev_notifier);
|
||||
|
||||
}
|
||||
|
|
|
@ -47,12 +47,12 @@ extern void efx_init_rx_queue(struct efx_rx_queue *rx_queue);
|
|||
extern void efx_fini_rx_queue(struct efx_rx_queue *rx_queue);
|
||||
extern void efx_rx_strategy(struct efx_channel *channel);
|
||||
extern void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue);
|
||||
extern void efx_rx_work(struct work_struct *data);
|
||||
extern void efx_rx_slow_fill(unsigned long context);
|
||||
extern void __efx_rx_packet(struct efx_channel *channel,
|
||||
struct efx_rx_buffer *rx_buf, bool checksummed);
|
||||
extern void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
|
||||
unsigned int len, bool checksummed, bool discard);
|
||||
extern void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue, int delay);
|
||||
extern void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue);
|
||||
#define EFX_RXQ_SIZE 1024
|
||||
#define EFX_RXQ_MASK (EFX_RXQ_SIZE - 1)
|
||||
|
||||
|
|
|
@ -548,7 +548,9 @@ void falcon_reconfigure_mac_wrapper(struct efx_nic *efx)
|
|||
{
|
||||
struct efx_link_state *link_state = &efx->link_state;
|
||||
efx_oword_t reg;
|
||||
int link_speed;
|
||||
int link_speed, isolate;
|
||||
|
||||
isolate = (efx->reset_pending != RESET_TYPE_NONE);
|
||||
|
||||
switch (link_state->speed) {
|
||||
case 10000: link_speed = 3; break;
|
||||
|
@ -570,7 +572,7 @@ void falcon_reconfigure_mac_wrapper(struct efx_nic *efx)
|
|||
* discarded. */
|
||||
if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) {
|
||||
EFX_SET_OWORD_FIELD(reg, FRF_BB_TXFIFO_DRAIN_EN,
|
||||
!link_state->up);
|
||||
!link_state->up || isolate);
|
||||
}
|
||||
|
||||
efx_writeo(efx, ®, FR_AB_MAC_CTRL);
|
||||
|
@ -584,7 +586,7 @@ void falcon_reconfigure_mac_wrapper(struct efx_nic *efx)
|
|||
EFX_SET_OWORD_FIELD(reg, FRF_AZ_RX_XOFF_MAC_EN, 1);
|
||||
/* Unisolate the MAC -> RX */
|
||||
if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0)
|
||||
EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_INGR_EN, 1);
|
||||
EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_INGR_EN, !isolate);
|
||||
efx_writeo(efx, ®, FR_AZ_RX_CFG);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "nic.h"
|
||||
#include "selftest.h"
|
||||
|
||||
struct efx_mcdi_phy_cfg {
|
||||
struct efx_mcdi_phy_data {
|
||||
u32 flags;
|
||||
u32 type;
|
||||
u32 supported_cap;
|
||||
|
@ -35,7 +35,7 @@ struct efx_mcdi_phy_cfg {
|
|||
};
|
||||
|
||||
static int
|
||||
efx_mcdi_get_phy_cfg(struct efx_nic *efx, struct efx_mcdi_phy_cfg *cfg)
|
||||
efx_mcdi_get_phy_cfg(struct efx_nic *efx, struct efx_mcdi_phy_data *cfg)
|
||||
{
|
||||
u8 outbuf[MC_CMD_GET_PHY_CFG_OUT_LEN];
|
||||
size_t outlen;
|
||||
|
@ -259,7 +259,7 @@ static u32 ethtool_to_mcdi_cap(u32 cap)
|
|||
|
||||
static u32 efx_get_mcdi_phy_flags(struct efx_nic *efx)
|
||||
{
|
||||
struct efx_mcdi_phy_cfg *phy_cfg = efx->phy_data;
|
||||
struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
|
||||
enum efx_phy_mode mode, supported;
|
||||
u32 flags;
|
||||
|
||||
|
@ -307,7 +307,7 @@ static u32 mcdi_to_ethtool_media(u32 media)
|
|||
|
||||
static int efx_mcdi_phy_probe(struct efx_nic *efx)
|
||||
{
|
||||
struct efx_mcdi_phy_cfg *phy_data;
|
||||
struct efx_mcdi_phy_data *phy_data;
|
||||
u8 outbuf[MC_CMD_GET_LINK_OUT_LEN];
|
||||
u32 caps;
|
||||
int rc;
|
||||
|
@ -395,6 +395,7 @@ static int efx_mcdi_phy_probe(struct efx_nic *efx)
|
|||
efx->wanted_fc = EFX_FC_RX | EFX_FC_TX;
|
||||
if (phy_data->supported_cap & (1 << MC_CMD_PHY_CAP_AN_LBN))
|
||||
efx->wanted_fc |= EFX_FC_AUTO;
|
||||
efx_link_set_wanted_fc(efx, efx->wanted_fc);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -405,7 +406,7 @@ static int efx_mcdi_phy_probe(struct efx_nic *efx)
|
|||
|
||||
int efx_mcdi_phy_reconfigure(struct efx_nic *efx)
|
||||
{
|
||||
struct efx_mcdi_phy_cfg *phy_cfg = efx->phy_data;
|
||||
struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
|
||||
u32 caps = (efx->link_advertising ?
|
||||
ethtool_to_mcdi_cap(efx->link_advertising) :
|
||||
phy_cfg->forced_cap);
|
||||
|
@ -446,7 +447,7 @@ void efx_mcdi_phy_decode_link(struct efx_nic *efx,
|
|||
*/
|
||||
void efx_mcdi_phy_check_fcntl(struct efx_nic *efx, u32 lpa)
|
||||
{
|
||||
struct efx_mcdi_phy_cfg *phy_cfg = efx->phy_data;
|
||||
struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
|
||||
u32 rmtadv;
|
||||
|
||||
/* The link partner capabilities are only relevent if the
|
||||
|
@ -505,7 +506,7 @@ static void efx_mcdi_phy_remove(struct efx_nic *efx)
|
|||
|
||||
static void efx_mcdi_phy_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
|
||||
{
|
||||
struct efx_mcdi_phy_cfg *phy_cfg = efx->phy_data;
|
||||
struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
|
||||
u8 outbuf[MC_CMD_GET_LINK_OUT_LEN];
|
||||
int rc;
|
||||
|
||||
|
@ -535,7 +536,7 @@ static void efx_mcdi_phy_get_settings(struct efx_nic *efx, struct ethtool_cmd *e
|
|||
|
||||
static int efx_mcdi_phy_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
|
||||
{
|
||||
struct efx_mcdi_phy_cfg *phy_cfg = efx->phy_data;
|
||||
struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
|
||||
u32 caps;
|
||||
int rc;
|
||||
|
||||
|
@ -674,7 +675,7 @@ static int efx_mcdi_bist(struct efx_nic *efx, unsigned int bist_mode,
|
|||
static int efx_mcdi_phy_run_tests(struct efx_nic *efx, int *results,
|
||||
unsigned flags)
|
||||
{
|
||||
struct efx_mcdi_phy_cfg *phy_cfg = efx->phy_data;
|
||||
struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
|
||||
u32 mode;
|
||||
int rc;
|
||||
|
||||
|
@ -712,7 +713,7 @@ static int efx_mcdi_phy_run_tests(struct efx_nic *efx, int *results,
|
|||
|
||||
const char *efx_mcdi_phy_test_name(struct efx_nic *efx, unsigned int index)
|
||||
{
|
||||
struct efx_mcdi_phy_cfg *phy_cfg = efx->phy_data;
|
||||
struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
|
||||
|
||||
if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_BIST_LBN)) {
|
||||
if (index == 0)
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/etherdevice.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/mdio.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/pci.h>
|
||||
|
@ -221,7 +222,6 @@ struct efx_tx_queue {
|
|||
* If both this and skb are %NULL, the buffer slot is currently free.
|
||||
* @data: Pointer to ethernet header
|
||||
* @len: Buffer length, in bytes.
|
||||
* @unmap_addr: DMA address to unmap
|
||||
*/
|
||||
struct efx_rx_buffer {
|
||||
dma_addr_t dma_addr;
|
||||
|
@ -229,7 +229,24 @@ struct efx_rx_buffer {
|
|||
struct page *page;
|
||||
char *data;
|
||||
unsigned int len;
|
||||
dma_addr_t unmap_addr;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct efx_rx_page_state - Page-based rx buffer state
|
||||
*
|
||||
* Inserted at the start of every page allocated for receive buffers.
|
||||
* Used to facilitate sharing dma mappings between recycled rx buffers
|
||||
* and those passed up to the kernel.
|
||||
*
|
||||
* @refcnt: Number of struct efx_rx_buffer's referencing this page.
|
||||
* When refcnt falls to zero, the page is unmapped for dma
|
||||
* @dma_addr: The dma address of this page.
|
||||
*/
|
||||
struct efx_rx_page_state {
|
||||
unsigned refcnt;
|
||||
dma_addr_t dma_addr;
|
||||
|
||||
unsigned int __pad[0] ____cacheline_aligned;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -242,10 +259,6 @@ struct efx_rx_buffer {
|
|||
* @added_count: Number of buffers added to the receive queue.
|
||||
* @notified_count: Number of buffers given to NIC (<= @added_count).
|
||||
* @removed_count: Number of buffers removed from the receive queue.
|
||||
* @add_lock: Receive queue descriptor add spin lock.
|
||||
* This lock must be held in order to add buffers to the RX
|
||||
* descriptor ring (rxd and buffer) and to update added_count (but
|
||||
* not removed_count).
|
||||
* @max_fill: RX descriptor maximum fill level (<= ring size)
|
||||
* @fast_fill_trigger: RX descriptor fill level that will trigger a fast fill
|
||||
* (<= @max_fill)
|
||||
|
@ -259,12 +272,7 @@ struct efx_rx_buffer {
|
|||
* overflow was observed. It should never be set.
|
||||
* @alloc_page_count: RX allocation strategy counter.
|
||||
* @alloc_skb_count: RX allocation strategy counter.
|
||||
* @work: Descriptor push work thread
|
||||
* @buf_page: Page for next RX buffer.
|
||||
* We can use a single page for multiple RX buffers. This tracks
|
||||
* the remaining space in the allocation.
|
||||
* @buf_dma_addr: Page's DMA address.
|
||||
* @buf_data: Page's host address.
|
||||
* @slow_fill: Timer used to defer efx_nic_generate_fill_event().
|
||||
* @flushed: Use when handling queue flushing
|
||||
*/
|
||||
struct efx_rx_queue {
|
||||
|
@ -277,7 +285,6 @@ struct efx_rx_queue {
|
|||
int added_count;
|
||||
int notified_count;
|
||||
int removed_count;
|
||||
spinlock_t add_lock;
|
||||
unsigned int max_fill;
|
||||
unsigned int fast_fill_trigger;
|
||||
unsigned int fast_fill_limit;
|
||||
|
@ -285,12 +292,9 @@ struct efx_rx_queue {
|
|||
unsigned int min_overfill;
|
||||
unsigned int alloc_page_count;
|
||||
unsigned int alloc_skb_count;
|
||||
struct delayed_work work;
|
||||
struct timer_list slow_fill;
|
||||
unsigned int slow_fill_count;
|
||||
|
||||
struct page *buf_page;
|
||||
dma_addr_t buf_dma_addr;
|
||||
char *buf_data;
|
||||
enum efx_flush_state flushed;
|
||||
};
|
||||
|
||||
|
@ -336,7 +340,7 @@ enum efx_rx_alloc_method {
|
|||
* @eventq: Event queue buffer
|
||||
* @eventq_read_ptr: Event queue read pointer
|
||||
* @last_eventq_read_ptr: Last event queue read pointer value.
|
||||
* @eventq_magic: Event queue magic value for driver-generated test events
|
||||
* @magic_count: Event queue test event count
|
||||
* @irq_count: Number of IRQs since last adaptive moderation decision
|
||||
* @irq_mod_score: IRQ moderation score
|
||||
* @rx_alloc_level: Watermark based heuristic counter for pushing descriptors
|
||||
|
@ -367,7 +371,7 @@ struct efx_channel {
|
|||
struct efx_special_buffer eventq;
|
||||
unsigned int eventq_read_ptr;
|
||||
unsigned int last_eventq_read_ptr;
|
||||
unsigned int eventq_magic;
|
||||
unsigned int magic_count;
|
||||
|
||||
unsigned int irq_count;
|
||||
unsigned int irq_mod_score;
|
||||
|
@ -645,6 +649,7 @@ union efx_multicast_hash {
|
|||
* struct efx_nic - an Efx NIC
|
||||
* @name: Device name (net device name or bus id before net device registered)
|
||||
* @pci_dev: The PCI device
|
||||
* @port_num: Index of this host port within the controller
|
||||
* @type: Controller type attributes
|
||||
* @legacy_irq: IRQ number
|
||||
* @workqueue: Workqueue for port reconfigures and the HW monitor.
|
||||
|
@ -728,6 +733,7 @@ union efx_multicast_hash {
|
|||
struct efx_nic {
|
||||
char name[IFNAMSIZ];
|
||||
struct pci_dev *pci_dev;
|
||||
unsigned port_num;
|
||||
const struct efx_nic_type *type;
|
||||
int legacy_irq;
|
||||
struct workqueue_struct *workqueue;
|
||||
|
@ -830,7 +836,7 @@ static inline const char *efx_dev_name(struct efx_nic *efx)
|
|||
|
||||
static inline unsigned int efx_port_num(struct efx_nic *efx)
|
||||
{
|
||||
return PCI_FUNC(efx->pci_dev->devfn);
|
||||
return efx->net_dev->dev_id;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -79,6 +79,14 @@ MODULE_PARM_DESC(rx_xon_thresh_bytes, "RX fifo XON threshold");
|
|||
/* Depth of RX flush request fifo */
|
||||
#define EFX_RX_FLUSH_COUNT 4
|
||||
|
||||
/* Generated event code for efx_generate_test_event() */
|
||||
#define EFX_CHANNEL_MAGIC_TEST(_channel) \
|
||||
(0x00010100 + (_channel)->channel)
|
||||
|
||||
/* Generated event code for efx_generate_fill_event() */
|
||||
#define EFX_CHANNEL_MAGIC_FILL(_channel) \
|
||||
(0x00010200 + (_channel)->channel)
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Solarstorm hardware access
|
||||
|
@ -850,6 +858,26 @@ efx_handle_rx_event(struct efx_channel *channel, const efx_qword_t *event)
|
|||
checksummed, discard);
|
||||
}
|
||||
|
||||
static void
|
||||
efx_handle_generated_event(struct efx_channel *channel, efx_qword_t *event)
|
||||
{
|
||||
struct efx_nic *efx = channel->efx;
|
||||
unsigned code;
|
||||
|
||||
code = EFX_QWORD_FIELD(*event, FSF_AZ_DRV_GEN_EV_MAGIC);
|
||||
if (code == EFX_CHANNEL_MAGIC_TEST(channel))
|
||||
++channel->magic_count;
|
||||
else if (code == EFX_CHANNEL_MAGIC_FILL(channel))
|
||||
/* The queue must be empty, so we won't receive any rx
|
||||
* events, so efx_process_channel() won't refill the
|
||||
* queue. Refill it here */
|
||||
efx_fast_push_rx_descriptors(&efx->rx_queue[channel->channel]);
|
||||
else
|
||||
EFX_LOG(efx, "channel %d received generated "
|
||||
"event "EFX_QWORD_FMT"\n", channel->channel,
|
||||
EFX_QWORD_VAL(*event));
|
||||
}
|
||||
|
||||
/* Global events are basically PHY events */
|
||||
static void
|
||||
efx_handle_global_event(struct efx_channel *channel, efx_qword_t *event)
|
||||
|
@ -993,11 +1021,7 @@ int efx_nic_process_eventq(struct efx_channel *channel, int budget)
|
|||
}
|
||||
break;
|
||||
case FSE_AZ_EV_CODE_DRV_GEN_EV:
|
||||
channel->eventq_magic = EFX_QWORD_FIELD(
|
||||
event, FSF_AZ_DRV_GEN_EV_MAGIC);
|
||||
EFX_LOG(channel->efx, "channel %d received generated "
|
||||
"event "EFX_QWORD_FMT"\n", channel->channel,
|
||||
EFX_QWORD_VAL(event));
|
||||
efx_handle_generated_event(channel, &event);
|
||||
break;
|
||||
case FSE_AZ_EV_CODE_GLOBAL_EV:
|
||||
efx_handle_global_event(channel, &event);
|
||||
|
@ -1088,12 +1112,20 @@ void efx_nic_remove_eventq(struct efx_channel *channel)
|
|||
}
|
||||
|
||||
|
||||
/* Generates a test event on the event queue. A subsequent call to
|
||||
* process_eventq() should pick up the event and place the value of
|
||||
* "magic" into channel->eventq_magic;
|
||||
*/
|
||||
void efx_nic_generate_test_event(struct efx_channel *channel, unsigned int magic)
|
||||
void efx_nic_generate_test_event(struct efx_channel *channel)
|
||||
{
|
||||
unsigned int magic = EFX_CHANNEL_MAGIC_TEST(channel);
|
||||
efx_qword_t test_event;
|
||||
|
||||
EFX_POPULATE_QWORD_2(test_event, FSF_AZ_EV_CODE,
|
||||
FSE_AZ_EV_CODE_DRV_GEN_EV,
|
||||
FSF_AZ_DRV_GEN_EV_MAGIC, magic);
|
||||
efx_generate_event(channel, &test_event);
|
||||
}
|
||||
|
||||
void efx_nic_generate_fill_event(struct efx_channel *channel)
|
||||
{
|
||||
unsigned int magic = EFX_CHANNEL_MAGIC_FILL(channel);
|
||||
efx_qword_t test_event;
|
||||
|
||||
EFX_POPULATE_QWORD_2(test_event, FSF_AZ_EV_CODE,
|
||||
|
@ -1219,9 +1251,6 @@ int efx_nic_flush_queues(struct efx_nic *efx)
|
|||
rx_queue->flushed = FLUSH_DONE;
|
||||
}
|
||||
|
||||
if (EFX_WORKAROUND_7803(efx))
|
||||
return 0;
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
|
|
|
@ -190,8 +190,8 @@ extern int efx_nic_rx_xoff_thresh, efx_nic_rx_xon_thresh;
|
|||
/* Interrupts and test events */
|
||||
extern int efx_nic_init_interrupt(struct efx_nic *efx);
|
||||
extern void efx_nic_enable_interrupts(struct efx_nic *efx);
|
||||
extern void efx_nic_generate_test_event(struct efx_channel *channel,
|
||||
unsigned int magic);
|
||||
extern void efx_nic_generate_test_event(struct efx_channel *channel);
|
||||
extern void efx_nic_generate_fill_event(struct efx_channel *channel);
|
||||
extern void efx_nic_generate_interrupt(struct efx_nic *efx);
|
||||
extern void efx_nic_disable_interrupts(struct efx_nic *efx);
|
||||
extern void efx_nic_fini_interrupt(struct efx_nic *efx);
|
||||
|
|
|
@ -25,6 +25,9 @@
|
|||
/* Number of RX descriptors pushed at once. */
|
||||
#define EFX_RX_BATCH 8
|
||||
|
||||
/* Maximum size of a buffer sharing a page */
|
||||
#define EFX_RX_HALF_PAGE ((PAGE_SIZE >> 1) - sizeof(struct efx_rx_page_state))
|
||||
|
||||
/* Size of buffer allocated for skb header area. */
|
||||
#define EFX_SKB_HEADERS 64u
|
||||
|
||||
|
@ -98,155 +101,138 @@ static inline unsigned int efx_rx_buf_size(struct efx_nic *efx)
|
|||
return PAGE_SIZE << efx->rx_buffer_order;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* efx_init_rx_buffer_skb - create new RX buffer using skb-based allocation
|
||||
* efx_init_rx_buffers_skb - create EFX_RX_BATCH skb-based RX buffers
|
||||
*
|
||||
* @rx_queue: Efx RX queue
|
||||
* @rx_buf: RX buffer structure to populate
|
||||
*
|
||||
* This allocates memory for a new receive buffer, maps it for DMA,
|
||||
* and populates a struct efx_rx_buffer with the relevant
|
||||
* information. Return a negative error code or 0 on success.
|
||||
* This allocates EFX_RX_BATCH skbs, maps them for DMA, and populates a
|
||||
* struct efx_rx_buffer for each one. Return a negative error code or 0
|
||||
* on success. May fail having only inserted fewer than EFX_RX_BATCH
|
||||
* buffers.
|
||||
*/
|
||||
static int efx_init_rx_buffer_skb(struct efx_rx_queue *rx_queue,
|
||||
struct efx_rx_buffer *rx_buf)
|
||||
static int efx_init_rx_buffers_skb(struct efx_rx_queue *rx_queue)
|
||||
{
|
||||
struct efx_nic *efx = rx_queue->efx;
|
||||
struct net_device *net_dev = efx->net_dev;
|
||||
struct efx_rx_buffer *rx_buf;
|
||||
int skb_len = efx->rx_buffer_len;
|
||||
unsigned index, count;
|
||||
|
||||
rx_buf->skb = netdev_alloc_skb(net_dev, skb_len);
|
||||
if (unlikely(!rx_buf->skb))
|
||||
return -ENOMEM;
|
||||
for (count = 0; count < EFX_RX_BATCH; ++count) {
|
||||
index = rx_queue->added_count & EFX_RXQ_MASK;
|
||||
rx_buf = efx_rx_buffer(rx_queue, index);
|
||||
|
||||
/* Adjust the SKB for padding and checksum */
|
||||
skb_reserve(rx_buf->skb, NET_IP_ALIGN);
|
||||
rx_buf->len = skb_len - NET_IP_ALIGN;
|
||||
rx_buf->data = (char *)rx_buf->skb->data;
|
||||
rx_buf->skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
rx_buf->skb = netdev_alloc_skb(net_dev, skb_len);
|
||||
if (unlikely(!rx_buf->skb))
|
||||
return -ENOMEM;
|
||||
rx_buf->page = NULL;
|
||||
|
||||
rx_buf->dma_addr = pci_map_single(efx->pci_dev,
|
||||
rx_buf->data, rx_buf->len,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
/* Adjust the SKB for padding and checksum */
|
||||
skb_reserve(rx_buf->skb, NET_IP_ALIGN);
|
||||
rx_buf->len = skb_len - NET_IP_ALIGN;
|
||||
rx_buf->data = (char *)rx_buf->skb->data;
|
||||
rx_buf->skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
|
||||
if (unlikely(pci_dma_mapping_error(efx->pci_dev, rx_buf->dma_addr))) {
|
||||
dev_kfree_skb_any(rx_buf->skb);
|
||||
rx_buf->skb = NULL;
|
||||
return -EIO;
|
||||
rx_buf->dma_addr = pci_map_single(efx->pci_dev,
|
||||
rx_buf->data, rx_buf->len,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
if (unlikely(pci_dma_mapping_error(efx->pci_dev,
|
||||
rx_buf->dma_addr))) {
|
||||
dev_kfree_skb_any(rx_buf->skb);
|
||||
rx_buf->skb = NULL;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
++rx_queue->added_count;
|
||||
++rx_queue->alloc_skb_count;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* efx_init_rx_buffer_page - create new RX buffer using page-based allocation
|
||||
* efx_init_rx_buffers_page - create EFX_RX_BATCH page-based RX buffers
|
||||
*
|
||||
* @rx_queue: Efx RX queue
|
||||
* @rx_buf: RX buffer structure to populate
|
||||
*
|
||||
* This allocates memory for a new receive buffer, maps it for DMA,
|
||||
* and populates a struct efx_rx_buffer with the relevant
|
||||
* information. Return a negative error code or 0 on success.
|
||||
* This allocates memory for EFX_RX_BATCH receive buffers, maps them for DMA,
|
||||
* and populates struct efx_rx_buffers for each one. Return a negative error
|
||||
* code or 0 on success. If a single page can be split between two buffers,
|
||||
* then the page will either be inserted fully, or not at at all.
|
||||
*/
|
||||
static int efx_init_rx_buffer_page(struct efx_rx_queue *rx_queue,
|
||||
struct efx_rx_buffer *rx_buf)
|
||||
static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue)
|
||||
{
|
||||
struct efx_nic *efx = rx_queue->efx;
|
||||
int bytes, space, offset;
|
||||
struct efx_rx_buffer *rx_buf;
|
||||
struct page *page;
|
||||
void *page_addr;
|
||||
struct efx_rx_page_state *state;
|
||||
dma_addr_t dma_addr;
|
||||
unsigned index, count;
|
||||
|
||||
bytes = efx->rx_buffer_len - EFX_PAGE_IP_ALIGN;
|
||||
/* We can split a page between two buffers */
|
||||
BUILD_BUG_ON(EFX_RX_BATCH & 1);
|
||||
|
||||
/* If there is space left in the previously allocated page,
|
||||
* then use it. Otherwise allocate a new one */
|
||||
rx_buf->page = rx_queue->buf_page;
|
||||
if (rx_buf->page == NULL) {
|
||||
dma_addr_t dma_addr;
|
||||
|
||||
rx_buf->page = alloc_pages(__GFP_COLD | __GFP_COMP | GFP_ATOMIC,
|
||||
efx->rx_buffer_order);
|
||||
if (unlikely(rx_buf->page == NULL))
|
||||
for (count = 0; count < EFX_RX_BATCH; ++count) {
|
||||
page = alloc_pages(__GFP_COLD | __GFP_COMP | GFP_ATOMIC,
|
||||
efx->rx_buffer_order);
|
||||
if (unlikely(page == NULL))
|
||||
return -ENOMEM;
|
||||
|
||||
dma_addr = pci_map_page(efx->pci_dev, rx_buf->page,
|
||||
0, efx_rx_buf_size(efx),
|
||||
dma_addr = pci_map_page(efx->pci_dev, page, 0,
|
||||
efx_rx_buf_size(efx),
|
||||
PCI_DMA_FROMDEVICE);
|
||||
|
||||
if (unlikely(pci_dma_mapping_error(efx->pci_dev, dma_addr))) {
|
||||
__free_pages(rx_buf->page, efx->rx_buffer_order);
|
||||
rx_buf->page = NULL;
|
||||
__free_pages(page, efx->rx_buffer_order);
|
||||
return -EIO;
|
||||
}
|
||||
page_addr = page_address(page);
|
||||
state = page_addr;
|
||||
state->refcnt = 0;
|
||||
state->dma_addr = dma_addr;
|
||||
|
||||
rx_queue->buf_page = rx_buf->page;
|
||||
rx_queue->buf_dma_addr = dma_addr;
|
||||
rx_queue->buf_data = (page_address(rx_buf->page) +
|
||||
EFX_PAGE_IP_ALIGN);
|
||||
}
|
||||
page_addr += sizeof(struct efx_rx_page_state);
|
||||
dma_addr += sizeof(struct efx_rx_page_state);
|
||||
|
||||
rx_buf->len = bytes;
|
||||
rx_buf->data = rx_queue->buf_data;
|
||||
offset = efx_rx_buf_offset(rx_buf);
|
||||
rx_buf->dma_addr = rx_queue->buf_dma_addr + offset;
|
||||
split:
|
||||
index = rx_queue->added_count & EFX_RXQ_MASK;
|
||||
rx_buf = efx_rx_buffer(rx_queue, index);
|
||||
rx_buf->dma_addr = dma_addr + EFX_PAGE_IP_ALIGN;
|
||||
rx_buf->skb = NULL;
|
||||
rx_buf->page = page;
|
||||
rx_buf->data = page_addr + EFX_PAGE_IP_ALIGN;
|
||||
rx_buf->len = efx->rx_buffer_len - EFX_PAGE_IP_ALIGN;
|
||||
++rx_queue->added_count;
|
||||
++rx_queue->alloc_page_count;
|
||||
++state->refcnt;
|
||||
|
||||
/* Try to pack multiple buffers per page */
|
||||
if (efx->rx_buffer_order == 0) {
|
||||
/* The next buffer starts on the next 512 byte boundary */
|
||||
rx_queue->buf_data += ((bytes + 0x1ff) & ~0x1ff);
|
||||
offset += ((bytes + 0x1ff) & ~0x1ff);
|
||||
|
||||
space = efx_rx_buf_size(efx) - offset;
|
||||
if (space >= bytes) {
|
||||
/* Refs dropped on kernel releasing each skb */
|
||||
get_page(rx_queue->buf_page);
|
||||
goto out;
|
||||
if ((~count & 1) && (efx->rx_buffer_len <= EFX_RX_HALF_PAGE)) {
|
||||
/* Use the second half of the page */
|
||||
get_page(page);
|
||||
dma_addr += (PAGE_SIZE >> 1);
|
||||
page_addr += (PAGE_SIZE >> 1);
|
||||
++count;
|
||||
goto split;
|
||||
}
|
||||
}
|
||||
|
||||
/* This is the final RX buffer for this page, so mark it for
|
||||
* unmapping */
|
||||
rx_queue->buf_page = NULL;
|
||||
rx_buf->unmap_addr = rx_queue->buf_dma_addr;
|
||||
|
||||
out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This allocates memory for a new receive buffer, maps it for DMA,
|
||||
* and populates a struct efx_rx_buffer with the relevant
|
||||
* information.
|
||||
*/
|
||||
static int efx_init_rx_buffer(struct efx_rx_queue *rx_queue,
|
||||
struct efx_rx_buffer *new_rx_buf)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (rx_queue->channel->rx_alloc_push_pages) {
|
||||
new_rx_buf->skb = NULL;
|
||||
rc = efx_init_rx_buffer_page(rx_queue, new_rx_buf);
|
||||
rx_queue->alloc_page_count++;
|
||||
} else {
|
||||
new_rx_buf->page = NULL;
|
||||
rc = efx_init_rx_buffer_skb(rx_queue, new_rx_buf);
|
||||
rx_queue->alloc_skb_count++;
|
||||
}
|
||||
|
||||
if (unlikely(rc < 0))
|
||||
EFX_LOG_RL(rx_queue->efx, "%s RXQ[%d] =%d\n", __func__,
|
||||
rx_queue->queue, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void efx_unmap_rx_buffer(struct efx_nic *efx,
|
||||
struct efx_rx_buffer *rx_buf)
|
||||
{
|
||||
if (rx_buf->page) {
|
||||
struct efx_rx_page_state *state;
|
||||
|
||||
EFX_BUG_ON_PARANOID(rx_buf->skb);
|
||||
if (rx_buf->unmap_addr) {
|
||||
pci_unmap_page(efx->pci_dev, rx_buf->unmap_addr,
|
||||
|
||||
state = page_address(rx_buf->page);
|
||||
if (--state->refcnt == 0) {
|
||||
pci_unmap_page(efx->pci_dev,
|
||||
state->dma_addr,
|
||||
efx_rx_buf_size(efx),
|
||||
PCI_DMA_FROMDEVICE);
|
||||
rx_buf->unmap_addr = 0;
|
||||
}
|
||||
} else if (likely(rx_buf->skb)) {
|
||||
pci_unmap_single(efx->pci_dev, rx_buf->dma_addr,
|
||||
|
@ -273,31 +259,84 @@ static void efx_fini_rx_buffer(struct efx_rx_queue *rx_queue,
|
|||
efx_free_rx_buffer(rx_queue->efx, rx_buf);
|
||||
}
|
||||
|
||||
/* Attempt to resurrect the other receive buffer that used to share this page,
|
||||
* which had previously been passed up to the kernel and freed. */
|
||||
static void efx_resurrect_rx_buffer(struct efx_rx_queue *rx_queue,
|
||||
struct efx_rx_buffer *rx_buf)
|
||||
{
|
||||
struct efx_rx_page_state *state = page_address(rx_buf->page);
|
||||
struct efx_rx_buffer *new_buf;
|
||||
unsigned fill_level, index;
|
||||
|
||||
/* +1 because efx_rx_packet() incremented removed_count. +1 because
|
||||
* we'd like to insert an additional descriptor whilst leaving
|
||||
* EFX_RXD_HEAD_ROOM for the non-recycle path */
|
||||
fill_level = (rx_queue->added_count - rx_queue->removed_count + 2);
|
||||
if (unlikely(fill_level >= EFX_RXQ_SIZE - EFX_RXD_HEAD_ROOM)) {
|
||||
/* We could place "state" on a list, and drain the list in
|
||||
* efx_fast_push_rx_descriptors(). For now, this will do. */
|
||||
return;
|
||||
}
|
||||
|
||||
++state->refcnt;
|
||||
get_page(rx_buf->page);
|
||||
|
||||
index = rx_queue->added_count & EFX_RXQ_MASK;
|
||||
new_buf = efx_rx_buffer(rx_queue, index);
|
||||
new_buf->dma_addr = rx_buf->dma_addr ^ (PAGE_SIZE >> 1);
|
||||
new_buf->skb = NULL;
|
||||
new_buf->page = rx_buf->page;
|
||||
new_buf->data = (void *)
|
||||
((__force unsigned long)rx_buf->data ^ (PAGE_SIZE >> 1));
|
||||
new_buf->len = rx_buf->len;
|
||||
++rx_queue->added_count;
|
||||
}
|
||||
|
||||
/* Recycle the given rx buffer directly back into the rx_queue. There is
|
||||
* always room to add this buffer, because we've just popped a buffer. */
|
||||
static void efx_recycle_rx_buffer(struct efx_channel *channel,
|
||||
struct efx_rx_buffer *rx_buf)
|
||||
{
|
||||
struct efx_nic *efx = channel->efx;
|
||||
struct efx_rx_queue *rx_queue = &efx->rx_queue[channel->channel];
|
||||
struct efx_rx_buffer *new_buf;
|
||||
unsigned index;
|
||||
|
||||
if (rx_buf->page != NULL && efx->rx_buffer_len <= EFX_RX_HALF_PAGE &&
|
||||
page_count(rx_buf->page) == 1)
|
||||
efx_resurrect_rx_buffer(rx_queue, rx_buf);
|
||||
|
||||
index = rx_queue->added_count & EFX_RXQ_MASK;
|
||||
new_buf = efx_rx_buffer(rx_queue, index);
|
||||
|
||||
memcpy(new_buf, rx_buf, sizeof(*new_buf));
|
||||
rx_buf->page = NULL;
|
||||
rx_buf->skb = NULL;
|
||||
++rx_queue->added_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* efx_fast_push_rx_descriptors - push new RX descriptors quickly
|
||||
* @rx_queue: RX descriptor queue
|
||||
* @retry: Recheck the fill level
|
||||
* This will aim to fill the RX descriptor queue up to
|
||||
* @rx_queue->@fast_fill_limit. If there is insufficient atomic
|
||||
* memory to do so, the caller should retry.
|
||||
* memory to do so, a slow fill will be scheduled.
|
||||
*
|
||||
* The caller must provide serialisation (none is used here). In practise,
|
||||
* this means this function must run from the NAPI handler, or be called
|
||||
* when NAPI is disabled.
|
||||
*/
|
||||
static int __efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue,
|
||||
int retry)
|
||||
void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue)
|
||||
{
|
||||
struct efx_rx_buffer *rx_buf;
|
||||
unsigned fill_level, index;
|
||||
int i, space, rc = 0;
|
||||
struct efx_channel *channel = rx_queue->channel;
|
||||
unsigned fill_level;
|
||||
int space, rc = 0;
|
||||
|
||||
/* Calculate current fill level. Do this outside the lock,
|
||||
* because most of the time we'll end up not wanting to do the
|
||||
* fill anyway.
|
||||
*/
|
||||
/* Calculate current fill level, and exit if we don't need to fill */
|
||||
fill_level = (rx_queue->added_count - rx_queue->removed_count);
|
||||
EFX_BUG_ON_PARANOID(fill_level > EFX_RXQ_SIZE);
|
||||
|
||||
/* Don't fill if we don't need to */
|
||||
if (fill_level >= rx_queue->fast_fill_trigger)
|
||||
return 0;
|
||||
goto out;
|
||||
|
||||
/* Record minimum fill level */
|
||||
if (unlikely(fill_level < rx_queue->min_fill)) {
|
||||
|
@ -305,34 +344,25 @@ static int __efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue,
|
|||
rx_queue->min_fill = fill_level;
|
||||
}
|
||||
|
||||
/* Acquire RX add lock. If this lock is contended, then a fast
|
||||
* fill must already be in progress (e.g. in the refill
|
||||
* tasklet), so we don't need to do anything
|
||||
*/
|
||||
if (!spin_trylock_bh(&rx_queue->add_lock))
|
||||
return -1;
|
||||
|
||||
retry:
|
||||
/* Recalculate current fill level now that we have the lock */
|
||||
fill_level = (rx_queue->added_count - rx_queue->removed_count);
|
||||
EFX_BUG_ON_PARANOID(fill_level > EFX_RXQ_SIZE);
|
||||
space = rx_queue->fast_fill_limit - fill_level;
|
||||
if (space < EFX_RX_BATCH)
|
||||
goto out_unlock;
|
||||
goto out;
|
||||
|
||||
EFX_TRACE(rx_queue->efx, "RX queue %d fast-filling descriptor ring from"
|
||||
" level %d to level %d using %s allocation\n",
|
||||
rx_queue->queue, fill_level, rx_queue->fast_fill_limit,
|
||||
rx_queue->channel->rx_alloc_push_pages ? "page" : "skb");
|
||||
channel->rx_alloc_push_pages ? "page" : "skb");
|
||||
|
||||
do {
|
||||
for (i = 0; i < EFX_RX_BATCH; ++i) {
|
||||
index = rx_queue->added_count & EFX_RXQ_MASK;
|
||||
rx_buf = efx_rx_buffer(rx_queue, index);
|
||||
rc = efx_init_rx_buffer(rx_queue, rx_buf);
|
||||
if (unlikely(rc))
|
||||
goto out;
|
||||
++rx_queue->added_count;
|
||||
if (channel->rx_alloc_push_pages)
|
||||
rc = efx_init_rx_buffers_page(rx_queue);
|
||||
else
|
||||
rc = efx_init_rx_buffers_skb(rx_queue);
|
||||
if (unlikely(rc)) {
|
||||
/* Ensure that we don't leave the rx queue empty */
|
||||
if (rx_queue->added_count == rx_queue->removed_count)
|
||||
efx_schedule_slow_fill(rx_queue);
|
||||
goto out;
|
||||
}
|
||||
} while ((space -= EFX_RX_BATCH) >= EFX_RX_BATCH);
|
||||
|
||||
|
@ -341,63 +371,18 @@ static int __efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue,
|
|||
rx_queue->added_count - rx_queue->removed_count);
|
||||
|
||||
out:
|
||||
/* Send write pointer to card. */
|
||||
efx_nic_notify_rx_desc(rx_queue);
|
||||
|
||||
/* If the fast fill is running inside from the refill tasklet, then
|
||||
* for SMP systems it may be running on a different CPU to
|
||||
* RX event processing, which means that the fill level may now be
|
||||
* out of date. */
|
||||
if (unlikely(retry && (rc == 0)))
|
||||
goto retry;
|
||||
|
||||
out_unlock:
|
||||
spin_unlock_bh(&rx_queue->add_lock);
|
||||
|
||||
return rc;
|
||||
if (rx_queue->notified_count != rx_queue->added_count)
|
||||
efx_nic_notify_rx_desc(rx_queue);
|
||||
}
|
||||
|
||||
/**
|
||||
* efx_fast_push_rx_descriptors - push new RX descriptors quickly
|
||||
* @rx_queue: RX descriptor queue
|
||||
*
|
||||
* This will aim to fill the RX descriptor queue up to
|
||||
* @rx_queue->@fast_fill_limit. If there is insufficient memory to do so,
|
||||
* it will schedule a work item to immediately continue the fast fill
|
||||
*/
|
||||
void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue)
|
||||
void efx_rx_slow_fill(unsigned long context)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = __efx_fast_push_rx_descriptors(rx_queue, 0);
|
||||
if (unlikely(rc)) {
|
||||
/* Schedule the work item to run immediately. The hope is
|
||||
* that work is immediately pending to free some memory
|
||||
* (e.g. an RX event or TX completion)
|
||||
*/
|
||||
efx_schedule_slow_fill(rx_queue, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void efx_rx_work(struct work_struct *data)
|
||||
{
|
||||
struct efx_rx_queue *rx_queue;
|
||||
int rc;
|
||||
|
||||
rx_queue = container_of(data, struct efx_rx_queue, work.work);
|
||||
|
||||
if (unlikely(!rx_queue->channel->enabled))
|
||||
return;
|
||||
|
||||
EFX_TRACE(rx_queue->efx, "RX queue %d worker thread executing on CPU "
|
||||
"%d\n", rx_queue->queue, raw_smp_processor_id());
|
||||
struct efx_rx_queue *rx_queue = (struct efx_rx_queue *)context;
|
||||
struct efx_channel *channel = rx_queue->channel;
|
||||
|
||||
/* Post an event to cause NAPI to run and refill the queue */
|
||||
efx_nic_generate_fill_event(channel);
|
||||
++rx_queue->slow_fill_count;
|
||||
/* Push new RX descriptors, allowing at least 1 jiffy for
|
||||
* the kernel to free some more memory. */
|
||||
rc = __efx_fast_push_rx_descriptors(rx_queue, 1);
|
||||
if (rc)
|
||||
efx_schedule_slow_fill(rx_queue, 1);
|
||||
}
|
||||
|
||||
static void efx_rx_packet__check_len(struct efx_rx_queue *rx_queue,
|
||||
|
@ -498,6 +483,7 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
|
|||
unsigned int len, bool checksummed, bool discard)
|
||||
{
|
||||
struct efx_nic *efx = rx_queue->efx;
|
||||
struct efx_channel *channel = rx_queue->channel;
|
||||
struct efx_rx_buffer *rx_buf;
|
||||
bool leak_packet = false;
|
||||
|
||||
|
@ -525,12 +511,13 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
|
|||
/* Discard packet, if instructed to do so */
|
||||
if (unlikely(discard)) {
|
||||
if (unlikely(leak_packet))
|
||||
rx_queue->channel->n_skbuff_leaks++;
|
||||
channel->n_skbuff_leaks++;
|
||||
else
|
||||
/* We haven't called efx_unmap_rx_buffer yet,
|
||||
* so fini the entire rx_buffer here */
|
||||
efx_fini_rx_buffer(rx_queue, rx_buf);
|
||||
return;
|
||||
efx_recycle_rx_buffer(channel, rx_buf);
|
||||
|
||||
/* Don't hold off the previous receive */
|
||||
rx_buf = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Release card resources - assumes all RX buffers consumed in-order
|
||||
|
@ -547,6 +534,7 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
|
|||
* prefetched into cache.
|
||||
*/
|
||||
rx_buf->len = len;
|
||||
out:
|
||||
if (rx_queue->channel->rx_pkt)
|
||||
__efx_rx_packet(rx_queue->channel,
|
||||
rx_queue->channel->rx_pkt,
|
||||
|
@ -682,6 +670,7 @@ void efx_fini_rx_queue(struct efx_rx_queue *rx_queue)
|
|||
|
||||
EFX_LOG(rx_queue->efx, "shutting down RX queue %d\n", rx_queue->queue);
|
||||
|
||||
del_timer_sync(&rx_queue->slow_fill);
|
||||
efx_nic_fini_rx(rx_queue);
|
||||
|
||||
/* Release RX buffers NB start at index 0 not current HW ptr */
|
||||
|
@ -691,16 +680,6 @@ void efx_fini_rx_queue(struct efx_rx_queue *rx_queue)
|
|||
efx_fini_rx_buffer(rx_queue, rx_buf);
|
||||
}
|
||||
}
|
||||
|
||||
/* For a page that is part-way through splitting into RX buffers */
|
||||
if (rx_queue->buf_page != NULL) {
|
||||
pci_unmap_page(rx_queue->efx->pci_dev, rx_queue->buf_dma_addr,
|
||||
efx_rx_buf_size(rx_queue->efx),
|
||||
PCI_DMA_FROMDEVICE);
|
||||
__free_pages(rx_queue->buf_page,
|
||||
rx_queue->efx->rx_buffer_order);
|
||||
rx_queue->buf_page = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void efx_remove_rx_queue(struct efx_rx_queue *rx_queue)
|
||||
|
|
|
@ -38,7 +38,7 @@ struct efx_loopback_payload {
|
|||
struct udphdr udp;
|
||||
__be16 iteration;
|
||||
const char msg[64];
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
/* Loopback test source MAC address */
|
||||
static const unsigned char payload_source[ETH_ALEN] = {
|
||||
|
@ -161,23 +161,17 @@ static int efx_test_interrupts(struct efx_nic *efx,
|
|||
static int efx_test_eventq_irq(struct efx_channel *channel,
|
||||
struct efx_self_tests *tests)
|
||||
{
|
||||
unsigned int magic, count;
|
||||
|
||||
/* Channel specific code, limited to 20 bits */
|
||||
magic = (0x00010150 + channel->channel);
|
||||
EFX_LOG(channel->efx, "channel %d testing event queue with code %x\n",
|
||||
channel->channel, magic);
|
||||
unsigned int magic_count, count;
|
||||
|
||||
tests->eventq_dma[channel->channel] = -1;
|
||||
tests->eventq_int[channel->channel] = -1;
|
||||
tests->eventq_poll[channel->channel] = -1;
|
||||
|
||||
/* Reset flag and zero magic word */
|
||||
magic_count = channel->magic_count;
|
||||
channel->efx->last_irq_cpu = -1;
|
||||
channel->eventq_magic = 0;
|
||||
smp_wmb();
|
||||
|
||||
efx_nic_generate_test_event(channel, magic);
|
||||
efx_nic_generate_test_event(channel);
|
||||
|
||||
/* Wait for arrival of interrupt */
|
||||
count = 0;
|
||||
|
@ -187,7 +181,7 @@ static int efx_test_eventq_irq(struct efx_channel *channel,
|
|||
if (channel->work_pending)
|
||||
efx_process_channel_now(channel);
|
||||
|
||||
if (channel->eventq_magic == magic)
|
||||
if (channel->magic_count != magic_count)
|
||||
goto eventq_ok;
|
||||
} while (++count < 2);
|
||||
|
||||
|
@ -204,7 +198,7 @@ static int efx_test_eventq_irq(struct efx_channel *channel,
|
|||
|
||||
/* Check to see if event was received even if interrupt wasn't */
|
||||
efx_process_channel_now(channel);
|
||||
if (channel->eventq_magic == magic) {
|
||||
if (channel->magic_count != magic_count) {
|
||||
EFX_ERR(channel->efx, "channel %d event was generated, but "
|
||||
"failed to trigger an interrupt\n", channel->channel);
|
||||
tests->eventq_dma[channel->channel] = 1;
|
||||
|
@ -545,7 +539,7 @@ efx_test_loopback(struct efx_tx_queue *tx_queue,
|
|||
static int efx_wait_for_link(struct efx_nic *efx)
|
||||
{
|
||||
struct efx_link_state *link_state = &efx->link_state;
|
||||
int count;
|
||||
int count, link_up_count = 0;
|
||||
bool link_up;
|
||||
|
||||
for (count = 0; count < 40; count++) {
|
||||
|
@ -567,8 +561,12 @@ static int efx_wait_for_link(struct efx_nic *efx)
|
|||
link_up = !efx->mac_op->check_fault(efx);
|
||||
mutex_unlock(&efx->mac_lock);
|
||||
|
||||
if (link_up)
|
||||
return 0;
|
||||
if (link_up) {
|
||||
if (++link_up_count == 2)
|
||||
return 0;
|
||||
} else {
|
||||
link_up_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -ETIMEDOUT;
|
||||
|
|
|
@ -206,6 +206,7 @@ static int siena_probe_nic(struct efx_nic *efx)
|
|||
{
|
||||
struct siena_nic_data *nic_data;
|
||||
bool already_attached = 0;
|
||||
efx_oword_t reg;
|
||||
int rc;
|
||||
|
||||
/* Allocate storage for hardware specific data */
|
||||
|
@ -220,6 +221,9 @@ static int siena_probe_nic(struct efx_nic *efx)
|
|||
goto fail1;
|
||||
}
|
||||
|
||||
efx_reado(efx, ®, FR_AZ_CS_DEBUG);
|
||||
efx->net_dev->dev_id = EFX_OWORD_FIELD(reg, FRF_CZ_CS_PORT_NUM) - 1;
|
||||
|
||||
efx_mcdi_init(efx);
|
||||
|
||||
/* Recover from a failed assertion before probing */
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue