Update to 3.18
Drop/refresh patches as necessary. Disable aufs. svn path=/dists/trunk/linux/; revision=22149
This commit is contained in:
parent
e0ff76482a
commit
dff5dedd0f
|
@ -1,3 +1,9 @@
|
|||
linux (3.18-1~exp1) UNRELEASED; urgency=medium
|
||||
|
||||
* New upstream release: http://kernelnewbies.org/Linux_3.18
|
||||
|
||||
-- Ben Hutchings <ben@decadent.org.uk> Tue, 09 Dec 2014 02:08:47 +0000
|
||||
|
||||
linux (3.17.4-1~exp1) experimental; urgency=medium
|
||||
|
||||
* New upstream stable update:
|
||||
|
|
|
@ -1,214 +0,0 @@
|
|||
From: Ben Hutchings <ben@decadent.org.uk>
|
||||
Date: Thu, 30 Oct 2014 18:27:12 +0000
|
||||
Subject: [1/2] drivers/net: Disable UFO through virtio
|
||||
Origin: https://git.kernel.org/cgit/linux/kernel/git/davem/net.git/commit?id=3d0ad09412ffe00c9afa201d01effdb6023d09b4
|
||||
|
||||
IPv6 does not allow fragmentation by routers, so there is no
|
||||
fragmentation ID in the fixed header. UFO for IPv6 requires the ID to
|
||||
be passed separately, but there is no provision for this in the virtio
|
||||
net protocol.
|
||||
|
||||
Until recently our software implementation of UFO/IPv6 generated a new
|
||||
ID, but this was a bug. Now we will use ID=0 for any UFO/IPv6 packet
|
||||
passed through a tap, which is even worse.
|
||||
|
||||
Unfortunately there is no distinction between UFO/IPv4 and v6
|
||||
features, so disable UFO on taps and virtio_net completely until we
|
||||
have a proper solution.
|
||||
|
||||
We cannot depend on VM managers respecting the tap feature flags, so
|
||||
keep accepting UFO packets but log a warning the first time we do
|
||||
this.
|
||||
|
||||
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
|
||||
Fixes: 916e4cf46d02 ("ipv6: reuse ip6_frag_id from ip6_ufo_append_data")
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/macvtap.c | 13 +++++--------
|
||||
drivers/net/tun.c | 19 +++++++++++--------
|
||||
drivers/net/virtio_net.c | 24 ++++++++++++++----------
|
||||
3 files changed, 30 insertions(+), 26 deletions(-)
|
||||
|
||||
--- a/drivers/net/macvtap.c
|
||||
+++ b/drivers/net/macvtap.c
|
||||
@@ -66,7 +66,7 @@ static struct cdev macvtap_cdev;
|
||||
static const struct proto_ops macvtap_socket_ops;
|
||||
|
||||
#define TUN_OFFLOADS (NETIF_F_HW_CSUM | NETIF_F_TSO_ECN | NETIF_F_TSO | \
|
||||
- NETIF_F_TSO6 | NETIF_F_UFO)
|
||||
+ NETIF_F_TSO6)
|
||||
#define RX_OFFLOADS (NETIF_F_GRO | NETIF_F_LRO)
|
||||
#define TAP_FEATURES (NETIF_F_GSO | NETIF_F_SG)
|
||||
|
||||
@@ -570,6 +570,8 @@ static int macvtap_skb_from_vnet_hdr(str
|
||||
gso_type = SKB_GSO_TCPV6;
|
||||
break;
|
||||
case VIRTIO_NET_HDR_GSO_UDP:
|
||||
+ pr_warn_once("macvtap: %s: using disabled UFO feature; please fix this program\n",
|
||||
+ current->comm);
|
||||
gso_type = SKB_GSO_UDP;
|
||||
if (skb->protocol == htons(ETH_P_IPV6))
|
||||
ipv6_proxy_select_ident(skb);
|
||||
@@ -617,8 +619,6 @@ static void macvtap_skb_to_vnet_hdr(cons
|
||||
vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
|
||||
else if (sinfo->gso_type & SKB_GSO_TCPV6)
|
||||
vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
|
||||
- else if (sinfo->gso_type & SKB_GSO_UDP)
|
||||
- vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_UDP;
|
||||
else
|
||||
BUG();
|
||||
if (sinfo->gso_type & SKB_GSO_TCP_ECN)
|
||||
@@ -955,9 +955,6 @@ static int set_offload(struct macvtap_qu
|
||||
if (arg & TUN_F_TSO6)
|
||||
feature_mask |= NETIF_F_TSO6;
|
||||
}
|
||||
-
|
||||
- if (arg & TUN_F_UFO)
|
||||
- feature_mask |= NETIF_F_UFO;
|
||||
}
|
||||
|
||||
/* tun/tap driver inverts the usage for TSO offloads, where
|
||||
@@ -968,7 +965,7 @@ static int set_offload(struct macvtap_qu
|
||||
* When user space turns off TSO, we turn off GSO/LRO so that
|
||||
* user-space will not receive TSO frames.
|
||||
*/
|
||||
- if (feature_mask & (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_UFO))
|
||||
+ if (feature_mask & (NETIF_F_TSO | NETIF_F_TSO6))
|
||||
features |= RX_OFFLOADS;
|
||||
else
|
||||
features &= ~RX_OFFLOADS;
|
||||
@@ -1069,7 +1066,7 @@ static long macvtap_ioctl(struct file *f
|
||||
case TUNSETOFFLOAD:
|
||||
/* let the user check for future flags */
|
||||
if (arg & ~(TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 |
|
||||
- TUN_F_TSO_ECN | TUN_F_UFO))
|
||||
+ TUN_F_TSO_ECN))
|
||||
return -EINVAL;
|
||||
|
||||
rtnl_lock();
|
||||
--- a/drivers/net/tun.c
|
||||
+++ b/drivers/net/tun.c
|
||||
@@ -175,7 +175,7 @@ struct tun_struct {
|
||||
struct net_device *dev;
|
||||
netdev_features_t set_features;
|
||||
#define TUN_USER_FEATURES (NETIF_F_HW_CSUM|NETIF_F_TSO_ECN|NETIF_F_TSO| \
|
||||
- NETIF_F_TSO6|NETIF_F_UFO)
|
||||
+ NETIF_F_TSO6)
|
||||
|
||||
int vnet_hdr_sz;
|
||||
int sndbuf;
|
||||
@@ -1152,10 +1152,20 @@ static ssize_t tun_get_user(struct tun_s
|
||||
skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
|
||||
break;
|
||||
case VIRTIO_NET_HDR_GSO_UDP:
|
||||
+ {
|
||||
+ static bool warned;
|
||||
+
|
||||
+ if (!warned) {
|
||||
+ warned = true;
|
||||
+ netdev_warn(tun->dev,
|
||||
+ "%s: using disabled UFO feature; please fix this program\n",
|
||||
+ current->comm);
|
||||
+ }
|
||||
skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
|
||||
if (skb->protocol == htons(ETH_P_IPV6))
|
||||
ipv6_proxy_select_ident(skb);
|
||||
break;
|
||||
+ }
|
||||
default:
|
||||
tun->dev->stats.rx_frame_errors++;
|
||||
kfree_skb(skb);
|
||||
@@ -1259,8 +1269,6 @@ static ssize_t tun_put_user(struct tun_s
|
||||
gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
|
||||
else if (sinfo->gso_type & SKB_GSO_TCPV6)
|
||||
gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
|
||||
- else if (sinfo->gso_type & SKB_GSO_UDP)
|
||||
- gso.gso_type = VIRTIO_NET_HDR_GSO_UDP;
|
||||
else {
|
||||
pr_err("unexpected GSO type: "
|
||||
"0x%x, gso_size %d, hdr_len %d\n",
|
||||
@@ -1768,11 +1776,6 @@ static int set_offload(struct tun_struct
|
||||
features |= NETIF_F_TSO6;
|
||||
arg &= ~(TUN_F_TSO4|TUN_F_TSO6);
|
||||
}
|
||||
-
|
||||
- if (arg & TUN_F_UFO) {
|
||||
- features |= NETIF_F_UFO;
|
||||
- arg &= ~TUN_F_UFO;
|
||||
- }
|
||||
}
|
||||
|
||||
/* This gives the user a way to test for new features in future by
|
||||
--- a/drivers/net/virtio_net.c
|
||||
+++ b/drivers/net/virtio_net.c
|
||||
@@ -497,8 +497,17 @@ static void receive_buf(struct receive_q
|
||||
skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
|
||||
break;
|
||||
case VIRTIO_NET_HDR_GSO_UDP:
|
||||
+ {
|
||||
+ static bool warned;
|
||||
+
|
||||
+ if (!warned) {
|
||||
+ warned = true;
|
||||
+ netdev_warn(dev,
|
||||
+ "host using disabled UFO feature; please fix it\n");
|
||||
+ }
|
||||
skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
|
||||
break;
|
||||
+ }
|
||||
case VIRTIO_NET_HDR_GSO_TCPV6:
|
||||
skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
|
||||
break;
|
||||
@@ -885,8 +894,6 @@ static int xmit_skb(struct send_queue *s
|
||||
hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
|
||||
else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
|
||||
hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
|
||||
- else if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP)
|
||||
- hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_UDP;
|
||||
else
|
||||
BUG();
|
||||
if (skb_shinfo(skb)->gso_type & SKB_GSO_TCP_ECN)
|
||||
@@ -1710,7 +1717,7 @@ static int virtnet_probe(struct virtio_d
|
||||
dev->features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST;
|
||||
|
||||
if (virtio_has_feature(vdev, VIRTIO_NET_F_GSO)) {
|
||||
- dev->hw_features |= NETIF_F_TSO | NETIF_F_UFO
|
||||
+ dev->hw_features |= NETIF_F_TSO
|
||||
| NETIF_F_TSO_ECN | NETIF_F_TSO6;
|
||||
}
|
||||
/* Individual feature bits: what can host handle? */
|
||||
@@ -1720,11 +1727,9 @@ static int virtnet_probe(struct virtio_d
|
||||
dev->hw_features |= NETIF_F_TSO6;
|
||||
if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_ECN))
|
||||
dev->hw_features |= NETIF_F_TSO_ECN;
|
||||
- if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_UFO))
|
||||
- dev->hw_features |= NETIF_F_UFO;
|
||||
|
||||
if (gso)
|
||||
- dev->features |= dev->hw_features & (NETIF_F_ALL_TSO|NETIF_F_UFO);
|
||||
+ dev->features |= dev->hw_features & NETIF_F_ALL_TSO;
|
||||
/* (!csum && gso) case will be fixed by register_netdev() */
|
||||
}
|
||||
if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_CSUM))
|
||||
@@ -1764,8 +1769,7 @@ static int virtnet_probe(struct virtio_d
|
||||
/* If we can receive ANY GSO packets, we must allocate large ones. */
|
||||
if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) ||
|
||||
virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO6) ||
|
||||
- virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ECN) ||
|
||||
- virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_UFO))
|
||||
+ virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ECN))
|
||||
vi->big_packets = true;
|
||||
|
||||
if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF))
|
||||
@@ -1965,9 +1969,9 @@ static struct virtio_device_id id_table[
|
||||
static unsigned int features[] = {
|
||||
VIRTIO_NET_F_CSUM, VIRTIO_NET_F_GUEST_CSUM,
|
||||
VIRTIO_NET_F_GSO, VIRTIO_NET_F_MAC,
|
||||
- VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6,
|
||||
+ VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_TSO6,
|
||||
VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6,
|
||||
- VIRTIO_NET_F_GUEST_ECN, VIRTIO_NET_F_GUEST_UFO,
|
||||
+ VIRTIO_NET_F_GUEST_ECN,
|
||||
VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, VIRTIO_NET_F_CTRL_VQ,
|
||||
VIRTIO_NET_F_CTRL_RX, VIRTIO_NET_F_CTRL_VLAN,
|
||||
VIRTIO_NET_F_GUEST_ANNOUNCE, VIRTIO_NET_F_MQ,
|
|
@ -96,7 +96,7 @@ upstream submission.
|
|||
fw_size = firmware->size / sizeof(u32);
|
||||
--- a/drivers/bluetooth/ath3k.c
|
||||
+++ b/drivers/bluetooth/ath3k.c
|
||||
@@ -375,10 +375,8 @@ static int ath3k_load_patch(struct usb_d
|
||||
@@ -377,10 +377,8 @@ static int ath3k_load_patch(struct usb_d
|
||||
le32_to_cpu(fw_version.rom_version));
|
||||
|
||||
ret = request_firmware(&firmware, filename, &udev->dev);
|
||||
|
@ -108,7 +108,7 @@ upstream submission.
|
|||
|
||||
pt_rom_version = get_unaligned_le32(firmware->data +
|
||||
firmware->size - 8);
|
||||
@@ -438,10 +436,8 @@ static int ath3k_load_syscfg(struct usb_
|
||||
@@ -440,10 +438,8 @@ static int ath3k_load_syscfg(struct usb_
|
||||
le32_to_cpu(fw_version.rom_version), clk_value, ".dfu");
|
||||
|
||||
ret = request_firmware(&firmware, filename, &udev->dev);
|
||||
|
@ -154,7 +154,7 @@ upstream submission.
|
|||
|
||||
--- a/drivers/bluetooth/bt3c_cs.c
|
||||
+++ b/drivers/bluetooth/bt3c_cs.c
|
||||
@@ -570,10 +570,8 @@ static int bt3c_open(bt3c_info_t *info)
|
||||
@@ -571,10 +571,8 @@ static int bt3c_open(struct bt3c_info *i
|
||||
|
||||
/* Load firmware */
|
||||
err = request_firmware(&firmware, "BT3CPCC.bin", &info->p_dev->dev);
|
||||
|
@ -168,7 +168,7 @@ upstream submission.
|
|||
|
||||
--- a/drivers/bluetooth/btmrvl_sdio.c
|
||||
+++ b/drivers/bluetooth/btmrvl_sdio.c
|
||||
@@ -297,8 +297,6 @@ static int btmrvl_sdio_download_helper(s
|
||||
@@ -328,8 +328,6 @@ static int btmrvl_sdio_download_helper(s
|
||||
ret = request_firmware(&fw_helper, card->helper,
|
||||
&card->func->dev);
|
||||
if ((ret < 0) || !fw_helper) {
|
||||
|
@ -177,7 +177,7 @@ upstream submission.
|
|||
ret = -ENOENT;
|
||||
goto done;
|
||||
}
|
||||
@@ -397,8 +395,6 @@ static int btmrvl_sdio_download_fw_w_hel
|
||||
@@ -428,8 +426,6 @@ static int btmrvl_sdio_download_fw_w_hel
|
||||
ret = request_firmware(&fw_firmware, card->firmware,
|
||||
&card->func->dev);
|
||||
if ((ret < 0) || !fw_firmware) {
|
||||
|
@ -274,7 +274,7 @@ upstream submission.
|
|||
release_firmware(rdev->me_fw);
|
||||
--- a/drivers/gpu/drm/radeon/r100.c
|
||||
+++ b/drivers/gpu/drm/radeon/r100.c
|
||||
@@ -1012,10 +1012,7 @@ static int r100_cp_init_microcode(struct
|
||||
@@ -1029,10 +1029,7 @@ static int r100_cp_init_microcode(struct
|
||||
}
|
||||
|
||||
err = request_firmware(&rdev->me_fw, fw_name, rdev->dev);
|
||||
|
@ -288,7 +288,7 @@ upstream submission.
|
|||
rdev->me_fw->size, fw_name);
|
||||
--- a/drivers/gpu/drm/radeon/r600.c
|
||||
+++ b/drivers/gpu/drm/radeon/r600.c
|
||||
@@ -2426,10 +2426,6 @@ int r600_init_microcode(struct radeon_de
|
||||
@@ -2518,10 +2518,6 @@ int r600_init_microcode(struct radeon_de
|
||||
|
||||
out:
|
||||
if (err) {
|
||||
|
@ -342,7 +342,7 @@ upstream submission.
|
|||
ret = qib_ibsd_ucode_loaded(dd->pport, fw);
|
||||
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
|
||||
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
|
||||
@@ -1932,10 +1932,8 @@ static int mxt_load_fw(struct device *de
|
||||
@@ -1942,10 +1942,8 @@ static int mxt_load_fw(struct device *de
|
||||
int ret;
|
||||
|
||||
ret = request_firmware(&fw, fn, dev);
|
||||
|
@ -381,7 +381,7 @@ upstream submission.
|
|||
}
|
||||
--- a/drivers/media/usb/dvb-usb/dib0700_devices.c
|
||||
+++ b/drivers/media/usb/dvb-usb/dib0700_devices.c
|
||||
@@ -2372,12 +2372,9 @@ static int stk9090m_frontend_attach(stru
|
||||
@@ -2394,12 +2394,9 @@ static int stk9090m_frontend_attach(stru
|
||||
|
||||
dib9000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, 0x80);
|
||||
|
||||
|
@ -396,7 +396,7 @@ upstream submission.
|
|||
stk9090m_config.microcode_B_fe_size = state->frontend_firmware->size;
|
||||
stk9090m_config.microcode_B_fe_buffer = state->frontend_firmware->data;
|
||||
|
||||
@@ -2438,12 +2435,9 @@ static int nim9090md_frontend_attach(str
|
||||
@@ -2460,12 +2457,9 @@ static int nim9090md_frontend_attach(str
|
||||
msleep(20);
|
||||
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
|
||||
|
||||
|
@ -498,7 +498,7 @@ upstream submission.
|
|||
+ if (ret)
|
||||
return ret;
|
||||
- }
|
||||
deb_info("got firmware: %zd\n",fw->size);
|
||||
deb_info("got firmware: %zu\n", fw->size);
|
||||
|
||||
b = fw->data;
|
||||
--- a/drivers/media/dvb-frontends/cx24116.c
|
||||
|
@ -534,7 +534,7 @@ upstream submission.
|
|||
if (state->microcode == NULL) {
|
||||
--- a/drivers/media/dvb-frontends/drxk_hard.c
|
||||
+++ b/drivers/media/dvb-frontends/drxk_hard.c
|
||||
@@ -6282,10 +6282,6 @@ static void load_firmware_cb(const struc
|
||||
@@ -6283,10 +6283,6 @@ static void load_firmware_cb(const struc
|
||||
|
||||
dprintk(1, ": %s\n", fw ? "firmware loaded" : "firmware not loaded");
|
||||
if (!fw) {
|
||||
|
@ -701,7 +701,7 @@ upstream submission.
|
|||
for (i = 0; i < ARRAY_SIZE(tab2); i++) {
|
||||
--- a/drivers/media/pci/ngene/ngene-core.c
|
||||
+++ b/drivers/media/pci/ngene/ngene-core.c
|
||||
@@ -1262,13 +1262,8 @@ static int ngene_load_firm(struct ngene
|
||||
@@ -1260,13 +1260,8 @@ static int ngene_load_firm(struct ngene
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -716,7 +716,7 @@ upstream submission.
|
|||
if (size == 0)
|
||||
size = fw->size;
|
||||
if (size != fw->size) {
|
||||
@@ -1276,8 +1271,6 @@ static int ngene_load_firm(struct ngene
|
||||
@@ -1274,8 +1269,6 @@ static int ngene_load_firm(struct ngene
|
||||
": Firmware %s has invalid size!", fw_name);
|
||||
err = -1;
|
||||
} else {
|
||||
|
@ -830,7 +830,7 @@ upstream submission.
|
|||
+ if (ret)
|
||||
return ret;
|
||||
- }
|
||||
fmdbg("Firmware(%s) length : %d bytes\n", fw_name, fw_entry->size);
|
||||
fmdbg("Firmware(%s) length : %zu bytes\n", fw_name, fw_entry->size);
|
||||
|
||||
fw_data = (void *)fw_entry->data;
|
||||
--- a/drivers/media/pci/bt8xx/bttv-cards.c
|
||||
|
@ -940,7 +940,7 @@ upstream submission.
|
|||
pr_err("ERROR: Firmware size mismatch (have %zd, expected %d)\n",
|
||||
--- a/drivers/media/pci/cx23885/cx23885-417.c
|
||||
+++ b/drivers/media/pci/cx23885/cx23885-417.c
|
||||
@@ -930,14 +930,8 @@ static int cx23885_load_firmware(struct
|
||||
@@ -931,14 +931,8 @@ static int cx23885_load_firmware(struct
|
||||
retval = request_firmware(&firmware, CX23885_FIRM_IMAGE_NAME,
|
||||
&dev->pci->dev);
|
||||
|
||||
|
@ -958,7 +958,7 @@ upstream submission.
|
|||
printk(KERN_ERR "ERROR: Firmware size mismatch "
|
||||
--- a/drivers/media/pci/cx23885/cx23885-cards.c
|
||||
+++ b/drivers/media/pci/cx23885/cx23885-cards.c
|
||||
@@ -1958,11 +1958,7 @@ void cx23885_card_setup(struct cx23885_d
|
||||
@@ -1980,11 +1980,7 @@ void cx23885_card_setup(struct cx23885_d
|
||||
cinfo.rev, filename);
|
||||
|
||||
ret = request_firmware(&fw, filename, &dev->pci->dev);
|
||||
|
@ -1075,7 +1075,7 @@ upstream submission.
|
|||
pdata = (__le32 *) &dev->fw_data->fw->data[fw_size - 8];
|
||||
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
|
||||
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
|
||||
@@ -94,10 +94,8 @@ int s5p_mfc_load_firmware(struct s5p_mfc
|
||||
@@ -95,10 +95,8 @@ int s5p_mfc_load_firmware(struct s5p_mfc
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1206,7 +1206,7 @@ upstream submission.
|
|||
|
||||
--- a/drivers/net/ethernet/broadcom/bnx2.c
|
||||
+++ b/drivers/net/ethernet/broadcom/bnx2.c
|
||||
@@ -3701,16 +3701,13 @@ static int bnx2_request_uncached_firmwar
|
||||
@@ -3702,16 +3702,13 @@ static int bnx2_request_uncached_firmwar
|
||||
}
|
||||
|
||||
rc = request_firmware(&bp->mips_firmware, mips_fw_file, &bp->pdev->dev);
|
||||
|
@ -1228,7 +1228,7 @@ upstream submission.
|
|||
if (bp->mips_firmware->size < sizeof(*mips_fw) ||
|
||||
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
|
||||
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
|
||||
@@ -12747,11 +12747,8 @@ static int bnx2x_init_firmware(struct bn
|
||||
@@ -12953,11 +12953,8 @@ static int bnx2x_init_firmware(struct bn
|
||||
BNX2X_DEV_INFO("Loading %s\n", fw_file_name);
|
||||
|
||||
rc = request_firmware(&bp->firmware, fw_file_name, &bp->pdev->dev);
|
||||
|
@ -1243,7 +1243,7 @@ upstream submission.
|
|||
if (rc) {
|
||||
--- a/drivers/net/ethernet/broadcom/tg3.c
|
||||
+++ b/drivers/net/ethernet/broadcom/tg3.c
|
||||
@@ -11305,11 +11305,8 @@ static int tg3_request_firmware(struct t
|
||||
@@ -11325,11 +11325,8 @@ static int tg3_request_firmware(struct t
|
||||
{
|
||||
const struct tg3_firmware_hdr *fw_hdr;
|
||||
|
||||
|
@ -1478,7 +1478,7 @@ upstream submission.
|
|||
int success = 0;
|
||||
--- a/drivers/net/wireless/b43/main.c
|
||||
+++ b/drivers/net/wireless/b43/main.c
|
||||
@@ -2185,19 +2185,8 @@ int b43_do_request_fw(struct b43_request
|
||||
@@ -2215,19 +2215,8 @@ int b43_do_request_fw(struct b43_request
|
||||
}
|
||||
err = request_firmware(&ctx->blob, ctx->fwname,
|
||||
ctx->dev->dev->dev);
|
||||
|
@ -1540,7 +1540,7 @@ upstream submission.
|
|||
}
|
||||
--- a/drivers/net/wireless/ipw2x00/ipw2100.c
|
||||
+++ b/drivers/net/wireless/ipw2x00/ipw2100.c
|
||||
@@ -8419,12 +8419,8 @@ static int ipw2100_get_firmware(struct i
|
||||
@@ -8411,12 +8411,8 @@ static int ipw2100_get_firmware(struct i
|
||||
|
||||
rc = request_firmware(&fw->fw_entry, fw_name, &priv->pci_dev->dev);
|
||||
|
||||
|
@ -1580,7 +1580,7 @@ upstream submission.
|
|||
else
|
||||
--- a/drivers/net/wireless/iwlwifi/iwl-drv.c
|
||||
+++ b/drivers/net/wireless/iwlwifi/iwl-drv.c
|
||||
@@ -990,13 +990,8 @@ static void iwl_req_fw_callback(const st
|
||||
@@ -1010,13 +1010,8 @@ static void iwl_req_fw_callback(const st
|
||||
|
||||
memset(&pieces, 0, sizeof(pieces));
|
||||
|
||||
|
@ -1608,7 +1608,7 @@ upstream submission.
|
|||
}
|
||||
--- a/drivers/net/wireless/mwifiex/main.c
|
||||
+++ b/drivers/net/wireless/mwifiex/main.c
|
||||
@@ -427,11 +427,8 @@ static void mwifiex_fw_dpc(const struct
|
||||
@@ -394,11 +394,8 @@ static void mwifiex_fw_dpc(const struct
|
||||
bool init_failed = false;
|
||||
struct wireless_dev *wdev;
|
||||
|
||||
|
@ -1702,7 +1702,7 @@ upstream submission.
|
|||
|
||||
--- a/drivers/net/wireless/orinoco/orinoco_usb.c
|
||||
+++ b/drivers/net/wireless/orinoco/orinoco_usb.c
|
||||
@@ -1675,7 +1675,6 @@ static int ezusb_probe(struct usb_interf
|
||||
@@ -1669,7 +1669,6 @@ static int ezusb_probe(struct usb_interf
|
||||
if (ezusb_firmware_download(upriv, &firmware) < 0)
|
||||
goto error;
|
||||
} else {
|
||||
|
@ -1777,7 +1777,7 @@ upstream submission.
|
|||
rt2x00_err(rt2x00dev, "Failed to read Firmware\n");
|
||||
--- a/drivers/net/wireless/rtlwifi/core.c
|
||||
+++ b/drivers/net/wireless/rtlwifi/core.c
|
||||
@@ -115,7 +115,6 @@ void rtl_fw_cb(const struct firmware *fi
|
||||
@@ -114,7 +114,6 @@ void rtl_fw_cb(const struct firmware *fi
|
||||
if (!err)
|
||||
goto found_alt;
|
||||
}
|
||||
|
@ -1787,7 +1787,7 @@ upstream submission.
|
|||
}
|
||||
--- a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
|
||||
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
|
||||
@@ -97,7 +97,6 @@ static void rtl92se_fw_cb(const struct f
|
||||
@@ -94,7 +94,6 @@ static void rtl92se_fw_cb(const struct f
|
||||
"Firmware callback routine entered!\n");
|
||||
complete(&rtlpriv->firmware_loading_complete);
|
||||
if (!firmware) {
|
||||
|
@ -1942,7 +1942,7 @@ upstream submission.
|
|||
}
|
||||
--- a/drivers/scsi/ipr.c
|
||||
+++ b/drivers/scsi/ipr.c
|
||||
@@ -3983,10 +3983,8 @@ static ssize_t ipr_store_update_fw(struc
|
||||
@@ -3993,10 +3993,8 @@ static ssize_t ipr_store_update_fw(struc
|
||||
len = snprintf(fname, 99, "%s", buf);
|
||||
fname[len-1] = '\0';
|
||||
|
||||
|
@ -1956,7 +1956,7 @@ upstream submission.
|
|||
|
||||
--- a/drivers/scsi/pm8001/pm8001_ctl.c
|
||||
+++ b/drivers/scsi/pm8001/pm8001_ctl.c
|
||||
@@ -687,10 +687,6 @@ static ssize_t pm8001_store_update_fw(st
|
||||
@@ -685,10 +685,6 @@ static ssize_t pm8001_store_update_fw(st
|
||||
pm8001_ha->dev);
|
||||
|
||||
if (ret) {
|
||||
|
@ -1980,7 +1980,7 @@ upstream submission.
|
|||
}
|
||||
--- a/drivers/scsi/qla2xxx/qla_init.c
|
||||
+++ b/drivers/scsi/qla2xxx/qla_init.c
|
||||
@@ -5350,8 +5350,6 @@ qla2x00_load_risc(scsi_qla_host_t *vha,
|
||||
@@ -5365,8 +5365,6 @@ qla2x00_load_risc(scsi_qla_host_t *vha,
|
||||
/* Load firmware blob. */
|
||||
blob = qla2x00_request_firmware(vha);
|
||||
if (!blob) {
|
||||
|
@ -1989,7 +1989,7 @@ upstream submission.
|
|||
ql_log(ql_log_info, vha, 0x0084,
|
||||
"Firmware images can be retrieved from: "QLA_FW_URL ".\n");
|
||||
return QLA_FUNCTION_FAILED;
|
||||
@@ -5453,8 +5451,6 @@ qla24xx_load_risc_blob(scsi_qla_host_t *
|
||||
@@ -5468,8 +5466,6 @@ qla24xx_load_risc_blob(scsi_qla_host_t *
|
||||
/* Load firmware blob. */
|
||||
blob = qla2x00_request_firmware(vha);
|
||||
if (!blob) {
|
||||
|
@ -2015,7 +2015,7 @@ upstream submission.
|
|||
if (qla82xx_validate_firmware_blob(vha,
|
||||
--- a/drivers/scsi/qla2xxx/qla_os.c
|
||||
+++ b/drivers/scsi/qla2xxx/qla_os.c
|
||||
@@ -5413,8 +5413,6 @@ qla2x00_request_firmware(scsi_qla_host_t
|
||||
@@ -5428,8 +5428,6 @@ qla2x00_request_firmware(scsi_qla_host_t
|
||||
goto out;
|
||||
|
||||
if (request_firmware(&blob->fw, blob->name, &ha->pdev->dev)) {
|
||||
|
@ -2041,7 +2041,7 @@ upstream submission.
|
|||
fw->size, fwname);
|
||||
--- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c
|
||||
+++ b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c
|
||||
@@ -2230,16 +2230,12 @@ struct net_device *init_ft1000_card(stru
|
||||
@@ -2231,16 +2231,12 @@ struct net_device *init_ft1000_card(stru
|
||||
info->AsicID = ft1000_read_reg(dev, FT1000_REG_ASIC_ID);
|
||||
if (info->AsicID == ELECTRABUZZ_ID) {
|
||||
DEBUG(0, "ft1000_hw: ELECTRABUZZ ASIC\n");
|
||||
|
@ -2074,34 +2074,6 @@ upstream submission.
|
|||
|
||||
size = max_t(uint, dsp_fw->size, 4096);
|
||||
pFileStart = kmalloc(size, GFP_KERNEL);
|
||||
--- a/drivers/staging/media/as102/as102_fw.c
|
||||
+++ b/drivers/staging/media/as102/as102_fw.c
|
||||
@@ -185,11 +185,8 @@ int as102_fw_upload(struct as10x_bus_ada
|
||||
|
||||
/* request kernel to locate firmware file: part1 */
|
||||
errno = request_firmware(&firmware, fw1, &dev->dev);
|
||||
- if (errno < 0) {
|
||||
- pr_err("%s: unable to locate firmware file: %s\n",
|
||||
- DRIVER_NAME, fw1);
|
||||
+ if (errno)
|
||||
goto error;
|
||||
- }
|
||||
|
||||
/* initiate firmware upload */
|
||||
errno = as102_firmware_upload(bus_adap, cmd_buf, firmware);
|
||||
@@ -208,11 +205,8 @@ int as102_fw_upload(struct as10x_bus_ada
|
||||
|
||||
/* request kernel to locate firmware file: part2 */
|
||||
errno = request_firmware(&firmware, fw2, &dev->dev);
|
||||
- if (errno < 0) {
|
||||
- pr_err("%s: unable to locate firmware file: %s\n",
|
||||
- DRIVER_NAME, fw2);
|
||||
+ if (errno)
|
||||
goto error;
|
||||
- }
|
||||
|
||||
/* initiate firmware upload */
|
||||
errno = as102_firmware_upload(bus_adap, cmd_buf, firmware);
|
||||
--- a/drivers/media/usb/go7007/go7007-driver.c
|
||||
+++ b/drivers/media/usb/go7007/go7007-driver.c
|
||||
@@ -92,10 +92,8 @@ static int go7007_load_encoder(struct go
|
||||
|
@ -2162,7 +2134,7 @@ upstream submission.
|
|||
if (0 != ret) {
|
||||
--- a/drivers/staging/media/lirc/lirc_zilog.c
|
||||
+++ b/drivers/staging/media/lirc/lirc_zilog.c
|
||||
@@ -767,8 +767,6 @@ static int fw_load(struct IR_tx *tx)
|
||||
@@ -768,8 +768,6 @@ static int fw_load(struct IR_tx *tx)
|
||||
/* Request codeset data file */
|
||||
ret = request_firmware(&fw_entry, "haup-ir-blaster.bin", tx->ir->l.dev);
|
||||
if (ret != 0) {
|
||||
|
@ -2173,11 +2145,11 @@ upstream submission.
|
|||
}
|
||||
--- a/drivers/staging/rtl8192u/r819xU_firmware.c
|
||||
+++ b/drivers/staging/rtl8192u/r819xU_firmware.c
|
||||
@@ -242,10 +242,8 @@ bool init_firmware(struct net_device *de
|
||||
@@ -241,10 +241,8 @@ bool init_firmware(struct net_device *de
|
||||
*/
|
||||
if (rst_opt == OPT_SYSTEM_RESET) {
|
||||
rc = request_firmware(&fw_entry, fw_name[init_step],&priv->udev->dev);
|
||||
- if (rc < 0 ) {
|
||||
- if (rc < 0) {
|
||||
- RT_TRACE(COMP_ERR, "request firmware fail!\n");
|
||||
+ if (rc)
|
||||
goto download_firmware_fail;
|
||||
|
@ -2187,14 +2159,15 @@ upstream submission.
|
|||
RT_TRACE(COMP_ERR, "img file size exceed the container buffer fail!\n");
|
||||
--- a/drivers/staging/rtl8712/hal_init.c
|
||||
+++ b/drivers/staging/rtl8712/hal_init.c
|
||||
@@ -49,7 +49,6 @@ static void rtl871x_load_fw_cb(const str
|
||||
if (!firmware) {
|
||||
struct usb_device *udev = padapter->dvobjpriv.pusbdev;
|
||||
struct usb_interface *pusb_intf = padapter->pusb_intf;
|
||||
- dev_err(&udev->dev, "r8712u: Firmware request failed\n");
|
||||
usb_put_dev(udev);
|
||||
usb_set_intfdata(pusb_intf, NULL);
|
||||
return;
|
||||
@@ -71,8 +71,6 @@ int rtl871x_load_fw(struct _adapter *pad
|
||||
dev_info(dev, "r8712u: Loading firmware from \"%s\"\n", firmware_file);
|
||||
rc = request_firmware_nowait(THIS_MODULE, 1, firmware_file, dev,
|
||||
GFP_KERNEL, padapter, rtl871x_load_fw_cb);
|
||||
- if (rc)
|
||||
- dev_err(dev, "r8712u: Firmware request error %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
MODULE_FIRMWARE("rtlwifi/rtl8712u.bin");
|
||||
--- a/drivers/staging/slicoss/slicoss.c
|
||||
+++ b/drivers/staging/slicoss/slicoss.c
|
||||
@@ -393,11 +393,8 @@ static int slic_card_download_gbrcv(stru
|
||||
|
@ -2487,7 +2460,7 @@ upstream submission.
|
|||
}
|
||||
--- a/drivers/usb/serial/ti_usb_3410_5052.c
|
||||
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
|
||||
@@ -1490,10 +1490,8 @@ static int ti_download_firmware(struct t
|
||||
@@ -1485,10 +1485,8 @@ static int ti_download_firmware(struct t
|
||||
}
|
||||
status = request_firmware(&fw_p, buf, &dev->dev);
|
||||
}
|
||||
|
@ -2646,7 +2619,7 @@ upstream submission.
|
|||
filename, emu->firmware->size);
|
||||
--- a/sound/pci/hda/hda_intel.c
|
||||
+++ b/sound/pci/hda/hda_intel.c
|
||||
@@ -1644,10 +1644,8 @@ static void azx_firmware_cb(const struct
|
||||
@@ -1662,10 +1662,8 @@ static void azx_firmware_cb(const struct
|
||||
struct azx *chip = card->private_data;
|
||||
struct pci_dev *pci = chip->pci;
|
||||
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
From a636289fb6037392c3551aeed1033576c3aef426 Mon Sep 17 00:00:00 2001
|
||||
From: Ian Campbell <ian.campbell@citrix.com>
|
||||
Date: Tue, 25 Nov 2014 15:05:13 +0000
|
||||
Subject: [PATCH] of/fdt: memblock_reserve /memreserve/ regions in the case of
|
||||
partial overlap
|
||||
Origin: https://git.kernel.org/cgit/linux/kernel/git/glikely/linux.git/commit/?h=devicetree/merge&id=094cb98179f19b75acf9ff471daabf3948ce98e6
|
||||
|
||||
memblock_is_region_reserved() returns true in the case of a partial
|
||||
overlap, meaning that the current code fails to reserve the
|
||||
non-overlapping portion.
|
||||
|
||||
This call was introduced as part of d1552ce449eb "of/fdt: move
|
||||
memreserve and dtb memory reservations into core" which went into
|
||||
v3.16.
|
||||
|
||||
I observed this causing a Midway system with a buggy fdt (the header
|
||||
declares itself to be larger than it really is) failing to boot
|
||||
because the over-inflated size of the fdt was causing it to seem to
|
||||
run into the swapper_pg_dir region, meaning the DT wasn't reserved.
|
||||
The symptoms were failing to find an disks or network and failing to
|
||||
boot.
|
||||
|
||||
However given the ambiguity of whether things like the initrd are
|
||||
covered by /memreserve/ and similar I think it is best to also
|
||||
register the region rather than just ignoring it.
|
||||
|
||||
Since memblock_reserve() handles overlaps just fine lets just warn and
|
||||
carry on.
|
||||
|
||||
Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Signed-off-by: Grant Likely <grant.likely@linaro.org>
|
||||
Cc: Rob Herring <robh+dt@kernel.org>
|
||||
Cc: stable@vger.kernel.org # v3.16+
|
||||
---
|
||||
drivers/of/fdt.c | 2 --
|
||||
1 file changed, 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
|
||||
index 379ad4f..94a8511 100644
|
||||
--- a/drivers/of/fdt.c
|
||||
+++ b/drivers/of/fdt.c
|
||||
@@ -960,8 +960,6 @@ void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size)
|
||||
int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base,
|
||||
phys_addr_t size, bool nomap)
|
||||
{
|
||||
- if (memblock_is_region_reserved(base, size))
|
||||
- return -EBUSY;
|
||||
if (nomap)
|
||||
return memblock_remove(base, size);
|
||||
return memblock_reserve(base, size);
|
||||
--
|
||||
2.1.3
|
||||
|
|
@ -28,9 +28,9 @@ missing, except for the pre-R600 KMS case.
|
|||
---
|
||||
--- a/drivers/gpu/drm/radeon/radeon_drv.c
|
||||
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
|
||||
@@ -39,6 +39,9 @@
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/vga_switcheroo.h>
|
||||
@@ -41,6 +41,9 @@
|
||||
#include <drm/drm_gem.h>
|
||||
|
||||
#include "drm_crtc_helper.h"
|
||||
+#include <linux/namei.h>
|
||||
+#include <linux/path.h>
|
||||
|
@ -38,7 +38,7 @@ missing, except for the pre-R600 KMS case.
|
|||
/*
|
||||
* KMS wrapper.
|
||||
* - 2.0.0 - initial interface
|
||||
@@ -341,6 +344,42 @@ static struct drm_driver driver_old = {
|
||||
@@ -362,6 +365,42 @@ static struct drm_driver driver_old = {
|
||||
|
||||
static struct drm_driver kms_driver;
|
||||
|
||||
|
@ -81,7 +81,7 @@ missing, except for the pre-R600 KMS case.
|
|||
static int radeon_kick_out_firmware_fb(struct pci_dev *pdev)
|
||||
{
|
||||
struct apertures_struct *ap;
|
||||
@@ -367,6 +406,12 @@ static int radeon_pci_probe(struct pci_d
|
||||
@@ -388,6 +427,12 @@ static int radeon_pci_probe(struct pci_d
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -94,7 +94,7 @@ missing, except for the pre-R600 KMS case.
|
|||
/* Get rid of things like offb */
|
||||
ret = radeon_kick_out_firmware_fb(pdev);
|
||||
if (ret)
|
||||
@@ -586,6 +631,7 @@ static struct pci_driver *pdriver;
|
||||
@@ -610,6 +655,7 @@ static struct pci_driver *pdriver;
|
||||
static struct pci_driver radeon_pci_driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.id_table = pciidlist,
|
||||
|
|
|
@ -1,614 +0,0 @@
|
|||
From 8a73fe2999810038cde046462258a3cd5afe170e Mon Sep 17 00:00:00 2001
|
||||
From: David Vrabel <david.vrabel@citrix.com>
|
||||
Date: Wed, 22 Oct 2014 14:08:54 +0100
|
||||
Subject: [PATCH 13/14] xen-netback: fix unlimited guest Rx internal queue and
|
||||
carrier flapping
|
||||
Origin: https://git.kernel.org/linus/f48da8b14d04ca87ffcffe68829afd45f926ec6a
|
||||
|
||||
Netback needs to discard old to-guest skb's (guest Rx queue drain) and
|
||||
it needs detect guest Rx stalls (to disable the carrier so packets are
|
||||
discarded earlier), but the current implementation is very broken.
|
||||
|
||||
1. The check in hard_start_xmit of the slot availability did not
|
||||
consider the number of packets that were already in the guest Rx
|
||||
queue. This could allow the queue to grow without bound.
|
||||
|
||||
The guest stops consuming packets and the ring was allowed to fill
|
||||
leaving S slot free. Netback queues a packet requiring more than S
|
||||
slots (ensuring that the ring stays with S slots free). Netback
|
||||
queue indefinately packets provided that then require S or fewer
|
||||
slots.
|
||||
|
||||
2. The Rx stall detection is not triggered in this case since the
|
||||
(host) Tx queue is not stopped.
|
||||
|
||||
3. If the Tx queue is stopped and a guest Rx interrupt occurs, netback
|
||||
will consider this an Rx purge event which may result in it taking
|
||||
the carrier down unnecessarily. It also considers a queue with
|
||||
only 1 slot free as unstalled (even though the next packet might
|
||||
not fit in this).
|
||||
|
||||
The internal guest Rx queue is limited by a byte length (to 512 Kib,
|
||||
enough for half the ring). The (host) Tx queue is stopped and started
|
||||
based on this limit. This sets an upper bound on the amount of memory
|
||||
used by packets on the internal queue.
|
||||
|
||||
This allows the estimatation of the number of slots for an skb to be
|
||||
removed (it wasn't a very good estimate anyway). Instead, the guest
|
||||
Rx thread just waits for enough free slots for a maximum sized packet.
|
||||
|
||||
skbs queued on the internal queue have an 'expires' time (set to the
|
||||
current time plus the drain timeout). The guest Rx thread will detect
|
||||
when the skb at the head of the queue has expired and discard expired
|
||||
skbs. This sets a clear upper bound on the length of time an skb can
|
||||
be queued for. For a guest being destroyed the maximum time needed to
|
||||
wait for all the packets it sent to be dropped is still the drain
|
||||
timeout (10 s) since it will not be sending new packets.
|
||||
|
||||
Rx stall detection is reintroduced in a later commit.
|
||||
|
||||
Signed-off-by: David Vrabel <david.vrabel@citrix.com>
|
||||
Reviewed-by: Wei Liu <wei.liu2@citrix.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
(cherry picked from commit f48da8b14d04ca87ffcffe68829afd45f926ec6a)
|
||||
---
|
||||
drivers/net/xen-netback/common.h | 29 +++--
|
||||
drivers/net/xen-netback/interface.c | 59 ++-------
|
||||
drivers/net/xen-netback/netback.c | 243 ++++++++++++++++++-----------------
|
||||
drivers/net/xen-netback/xenbus.c | 8 ++
|
||||
4 files changed, 161 insertions(+), 178 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h
|
||||
index 93ca77c..c264240 100644
|
||||
--- a/drivers/net/xen-netback/common.h
|
||||
+++ b/drivers/net/xen-netback/common.h
|
||||
@@ -176,10 +176,9 @@ struct xenvif_queue { /* Per-queue data for xenvif */
|
||||
char rx_irq_name[IRQ_NAME_SIZE]; /* DEVNAME-qN-rx */
|
||||
struct xen_netif_rx_back_ring rx;
|
||||
struct sk_buff_head rx_queue;
|
||||
- RING_IDX rx_last_skb_slots;
|
||||
- unsigned long status;
|
||||
|
||||
- struct timer_list rx_stalled;
|
||||
+ unsigned int rx_queue_max;
|
||||
+ unsigned int rx_queue_len;
|
||||
|
||||
struct gnttab_copy grant_copy_op[MAX_GRANT_COPY_OPS];
|
||||
|
||||
@@ -199,18 +198,14 @@ struct xenvif_queue { /* Per-queue data for xenvif */
|
||||
struct xenvif_stats stats;
|
||||
};
|
||||
|
||||
+/* Maximum number of Rx slots a to-guest packet may use, including the
|
||||
+ * slot needed for GSO meta-data.
|
||||
+ */
|
||||
+#define XEN_NETBK_RX_SLOTS_MAX (MAX_SKB_FRAGS + 1)
|
||||
+
|
||||
enum state_bit_shift {
|
||||
/* This bit marks that the vif is connected */
|
||||
VIF_STATUS_CONNECTED,
|
||||
- /* This bit signals the RX thread that queuing was stopped (in
|
||||
- * start_xmit), and either the timer fired or an RX interrupt came
|
||||
- */
|
||||
- QUEUE_STATUS_RX_PURGE_EVENT,
|
||||
- /* This bit tells the interrupt handler that this queue was the reason
|
||||
- * for the carrier off, so it should kick the thread. Only queues which
|
||||
- * brought it down can turn on the carrier.
|
||||
- */
|
||||
- QUEUE_STATUS_RX_STALLED
|
||||
};
|
||||
|
||||
struct xenvif {
|
||||
@@ -246,6 +241,14 @@ struct xenvif {
|
||||
struct net_device *dev;
|
||||
};
|
||||
|
||||
+struct xenvif_rx_cb {
|
||||
+ unsigned long expires;
|
||||
+ int meta_slots_used;
|
||||
+ bool full_coalesce;
|
||||
+};
|
||||
+
|
||||
+#define XENVIF_RX_CB(skb) ((struct xenvif_rx_cb *)(skb)->cb)
|
||||
+
|
||||
static inline struct xenbus_device *xenvif_to_xenbus_device(struct xenvif *vif)
|
||||
{
|
||||
return to_xenbus_device(vif->dev->dev.parent);
|
||||
@@ -291,6 +294,8 @@ void xenvif_kick_thread(struct xenvif_queue *queue);
|
||||
|
||||
int xenvif_dealloc_kthread(void *data);
|
||||
|
||||
+void xenvif_rx_queue_tail(struct xenvif_queue *queue, struct sk_buff *skb);
|
||||
+
|
||||
/* Determine whether the needed number of slots (req) are available,
|
||||
* and set req_event if not.
|
||||
*/
|
||||
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c
|
||||
index 6879251..9e8af0b 100644
|
||||
--- a/drivers/net/xen-netback/interface.c
|
||||
+++ b/drivers/net/xen-netback/interface.c
|
||||
@@ -43,6 +43,9 @@
|
||||
#define XENVIF_QUEUE_LENGTH 32
|
||||
#define XENVIF_NAPI_WEIGHT 64
|
||||
|
||||
+/* Number of bytes allowed on the internal guest Rx queue. */
|
||||
+#define XENVIF_RX_QUEUE_BYTES (XEN_NETIF_RX_RING_SIZE/2 * PAGE_SIZE)
|
||||
+
|
||||
/* This function is used to set SKBTX_DEV_ZEROCOPY as well as
|
||||
* increasing the inflight counter. We need to increase the inflight
|
||||
* counter because core driver calls into xenvif_zerocopy_callback
|
||||
@@ -63,7 +66,8 @@ void xenvif_skb_zerocopy_complete(struct xenvif_queue *queue)
|
||||
int xenvif_schedulable(struct xenvif *vif)
|
||||
{
|
||||
return netif_running(vif->dev) &&
|
||||
- test_bit(VIF_STATUS_CONNECTED, &vif->status);
|
||||
+ test_bit(VIF_STATUS_CONNECTED, &vif->status) &&
|
||||
+ !vif->disabled;
|
||||
}
|
||||
|
||||
static irqreturn_t xenvif_tx_interrupt(int irq, void *dev_id)
|
||||
@@ -104,16 +108,7 @@ int xenvif_poll(struct napi_struct *napi, int budget)
|
||||
static irqreturn_t xenvif_rx_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct xenvif_queue *queue = dev_id;
|
||||
- struct netdev_queue *net_queue =
|
||||
- netdev_get_tx_queue(queue->vif->dev, queue->id);
|
||||
|
||||
- /* QUEUE_STATUS_RX_PURGE_EVENT is only set if either QDisc was off OR
|
||||
- * the carrier went down and this queue was previously blocked
|
||||
- */
|
||||
- if (unlikely(netif_tx_queue_stopped(net_queue) ||
|
||||
- (!netif_carrier_ok(queue->vif->dev) &&
|
||||
- test_bit(QUEUE_STATUS_RX_STALLED, &queue->status))))
|
||||
- set_bit(QUEUE_STATUS_RX_PURGE_EVENT, &queue->status);
|
||||
xenvif_kick_thread(queue);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
@@ -141,24 +136,13 @@ void xenvif_wake_queue(struct xenvif_queue *queue)
|
||||
netif_tx_wake_queue(netdev_get_tx_queue(dev, id));
|
||||
}
|
||||
|
||||
-/* Callback to wake the queue's thread and turn the carrier off on timeout */
|
||||
-static void xenvif_rx_stalled(unsigned long data)
|
||||
-{
|
||||
- struct xenvif_queue *queue = (struct xenvif_queue *)data;
|
||||
-
|
||||
- if (xenvif_queue_stopped(queue)) {
|
||||
- set_bit(QUEUE_STATUS_RX_PURGE_EVENT, &queue->status);
|
||||
- xenvif_kick_thread(queue);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
static int xenvif_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct xenvif *vif = netdev_priv(dev);
|
||||
struct xenvif_queue *queue = NULL;
|
||||
unsigned int num_queues = vif->num_queues;
|
||||
u16 index;
|
||||
- int min_slots_needed;
|
||||
+ struct xenvif_rx_cb *cb;
|
||||
|
||||
BUG_ON(skb->dev != dev);
|
||||
|
||||
@@ -181,30 +165,10 @@ static int xenvif_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
!xenvif_schedulable(vif))
|
||||
goto drop;
|
||||
|
||||
- /* At best we'll need one slot for the header and one for each
|
||||
- * frag.
|
||||
- */
|
||||
- min_slots_needed = 1 + skb_shinfo(skb)->nr_frags;
|
||||
+ cb = XENVIF_RX_CB(skb);
|
||||
+ cb->expires = jiffies + rx_drain_timeout_jiffies;
|
||||
|
||||
- /* If the skb is GSO then we'll also need an extra slot for the
|
||||
- * metadata.
|
||||
- */
|
||||
- if (skb_is_gso(skb))
|
||||
- min_slots_needed++;
|
||||
-
|
||||
- /* If the skb can't possibly fit in the remaining slots
|
||||
- * then turn off the queue to give the ring a chance to
|
||||
- * drain.
|
||||
- */
|
||||
- if (!xenvif_rx_ring_slots_available(queue, min_slots_needed)) {
|
||||
- queue->rx_stalled.function = xenvif_rx_stalled;
|
||||
- queue->rx_stalled.data = (unsigned long)queue;
|
||||
- netif_tx_stop_queue(netdev_get_tx_queue(dev, queue->id));
|
||||
- mod_timer(&queue->rx_stalled,
|
||||
- jiffies + rx_drain_timeout_jiffies);
|
||||
- }
|
||||
-
|
||||
- skb_queue_tail(&queue->rx_queue, skb);
|
||||
+ xenvif_rx_queue_tail(queue, skb);
|
||||
xenvif_kick_thread(queue);
|
||||
|
||||
return NETDEV_TX_OK;
|
||||
@@ -498,6 +462,8 @@ int xenvif_init_queue(struct xenvif_queue *queue)
|
||||
init_timer(&queue->credit_timeout);
|
||||
queue->credit_window_start = get_jiffies_64();
|
||||
|
||||
+ queue->rx_queue_max = XENVIF_RX_QUEUE_BYTES;
|
||||
+
|
||||
skb_queue_head_init(&queue->rx_queue);
|
||||
skb_queue_head_init(&queue->tx_queue);
|
||||
|
||||
@@ -529,8 +495,6 @@ int xenvif_init_queue(struct xenvif_queue *queue)
|
||||
queue->grant_tx_handle[i] = NETBACK_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
- init_timer(&queue->rx_stalled);
|
||||
-
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -664,7 +628,6 @@ void xenvif_disconnect(struct xenvif *vif)
|
||||
netif_napi_del(&queue->napi);
|
||||
|
||||
if (queue->task) {
|
||||
- del_timer_sync(&queue->rx_stalled);
|
||||
kthread_stop(queue->task);
|
||||
queue->task = NULL;
|
||||
}
|
||||
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
|
||||
index 08f6599..57aa3b5 100644
|
||||
--- a/drivers/net/xen-netback/netback.c
|
||||
+++ b/drivers/net/xen-netback/netback.c
|
||||
@@ -55,8 +55,8 @@
|
||||
bool separate_tx_rx_irq = 1;
|
||||
module_param(separate_tx_rx_irq, bool, 0644);
|
||||
|
||||
-/* When guest ring is filled up, qdisc queues the packets for us, but we have
|
||||
- * to timeout them, otherwise other guests' packets can get stuck there
|
||||
+/* The time that packets can stay on the guest Rx internal queue
|
||||
+ * before they are dropped.
|
||||
*/
|
||||
unsigned int rx_drain_timeout_msecs = 10000;
|
||||
module_param(rx_drain_timeout_msecs, uint, 0444);
|
||||
@@ -83,7 +83,6 @@ static void make_tx_response(struct xenvif_queue *queue,
|
||||
s8 st);
|
||||
|
||||
static inline int tx_work_todo(struct xenvif_queue *queue);
|
||||
-static inline int rx_work_todo(struct xenvif_queue *queue);
|
||||
|
||||
static struct xen_netif_rx_response *make_rx_response(struct xenvif_queue *queue,
|
||||
u16 id,
|
||||
@@ -163,6 +162,69 @@ bool xenvif_rx_ring_slots_available(struct xenvif_queue *queue, int needed)
|
||||
return false;
|
||||
}
|
||||
|
||||
+void xenvif_rx_queue_tail(struct xenvif_queue *queue, struct sk_buff *skb)
|
||||
+{
|
||||
+ unsigned long flags;
|
||||
+
|
||||
+ spin_lock_irqsave(&queue->rx_queue.lock, flags);
|
||||
+
|
||||
+ __skb_queue_tail(&queue->rx_queue, skb);
|
||||
+
|
||||
+ queue->rx_queue_len += skb->len;
|
||||
+ if (queue->rx_queue_len > queue->rx_queue_max)
|
||||
+ netif_tx_stop_queue(netdev_get_tx_queue(queue->vif->dev, queue->id));
|
||||
+
|
||||
+ spin_unlock_irqrestore(&queue->rx_queue.lock, flags);
|
||||
+}
|
||||
+
|
||||
+static struct sk_buff *xenvif_rx_dequeue(struct xenvif_queue *queue)
|
||||
+{
|
||||
+ struct sk_buff *skb;
|
||||
+
|
||||
+ spin_lock_irq(&queue->rx_queue.lock);
|
||||
+
|
||||
+ skb = __skb_dequeue(&queue->rx_queue);
|
||||
+ if (skb)
|
||||
+ queue->rx_queue_len -= skb->len;
|
||||
+
|
||||
+ spin_unlock_irq(&queue->rx_queue.lock);
|
||||
+
|
||||
+ return skb;
|
||||
+}
|
||||
+
|
||||
+static void xenvif_rx_queue_maybe_wake(struct xenvif_queue *queue)
|
||||
+{
|
||||
+ spin_lock_irq(&queue->rx_queue.lock);
|
||||
+
|
||||
+ if (queue->rx_queue_len < queue->rx_queue_max)
|
||||
+ netif_tx_wake_queue(netdev_get_tx_queue(queue->vif->dev, queue->id));
|
||||
+
|
||||
+ spin_unlock_irq(&queue->rx_queue.lock);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static void xenvif_rx_queue_purge(struct xenvif_queue *queue)
|
||||
+{
|
||||
+ struct sk_buff *skb;
|
||||
+ while ((skb = xenvif_rx_dequeue(queue)) != NULL)
|
||||
+ kfree_skb(skb);
|
||||
+}
|
||||
+
|
||||
+static void xenvif_rx_queue_drop_expired(struct xenvif_queue *queue)
|
||||
+{
|
||||
+ struct sk_buff *skb;
|
||||
+
|
||||
+ for(;;) {
|
||||
+ skb = skb_peek(&queue->rx_queue);
|
||||
+ if (!skb)
|
||||
+ break;
|
||||
+ if (time_before(jiffies, XENVIF_RX_CB(skb)->expires))
|
||||
+ break;
|
||||
+ xenvif_rx_dequeue(queue);
|
||||
+ kfree_skb(skb);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Returns true if we should start a new receive buffer instead of
|
||||
* adding 'size' bytes to a buffer which currently contains 'offset'
|
||||
@@ -237,13 +299,6 @@ static struct xenvif_rx_meta *get_next_rx_buffer(struct xenvif_queue *queue,
|
||||
return meta;
|
||||
}
|
||||
|
||||
-struct xenvif_rx_cb {
|
||||
- int meta_slots_used;
|
||||
- bool full_coalesce;
|
||||
-};
|
||||
-
|
||||
-#define XENVIF_RX_CB(skb) ((struct xenvif_rx_cb *)(skb)->cb)
|
||||
-
|
||||
/*
|
||||
* Set up the grant operations for this fragment. If it's a flipping
|
||||
* interface, we also set up the unmap request from here.
|
||||
@@ -587,7 +642,8 @@ static void xenvif_rx_action(struct xenvif_queue *queue)
|
||||
|
||||
skb_queue_head_init(&rxq);
|
||||
|
||||
- while ((skb = skb_dequeue(&queue->rx_queue)) != NULL) {
|
||||
+ while (xenvif_rx_ring_slots_available(queue, XEN_NETBK_RX_SLOTS_MAX)
|
||||
+ && (skb = xenvif_rx_dequeue(queue)) != NULL) {
|
||||
RING_IDX max_slots_needed;
|
||||
RING_IDX old_req_cons;
|
||||
RING_IDX ring_slots_used;
|
||||
@@ -634,15 +690,6 @@ static void xenvif_rx_action(struct xenvif_queue *queue)
|
||||
skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6))
|
||||
max_slots_needed++;
|
||||
|
||||
- /* If the skb may not fit then bail out now */
|
||||
- if (!xenvif_rx_ring_slots_available(queue, max_slots_needed)) {
|
||||
- skb_queue_head(&queue->rx_queue, skb);
|
||||
- need_to_notify = true;
|
||||
- queue->rx_last_skb_slots = max_slots_needed;
|
||||
- break;
|
||||
- } else
|
||||
- queue->rx_last_skb_slots = 0;
|
||||
-
|
||||
old_req_cons = queue->rx.req_cons;
|
||||
XENVIF_RX_CB(skb)->meta_slots_used = xenvif_gop_skb(skb, &npo, queue);
|
||||
ring_slots_used = queue->rx.req_cons - old_req_cons;
|
||||
@@ -1869,12 +1916,6 @@ void xenvif_idx_unmap(struct xenvif_queue *queue, u16 pending_idx)
|
||||
}
|
||||
}
|
||||
|
||||
-static inline int rx_work_todo(struct xenvif_queue *queue)
|
||||
-{
|
||||
- return (!skb_queue_empty(&queue->rx_queue) &&
|
||||
- xenvif_rx_ring_slots_available(queue, queue->rx_last_skb_slots));
|
||||
-}
|
||||
-
|
||||
static inline int tx_work_todo(struct xenvif_queue *queue)
|
||||
{
|
||||
if (likely(RING_HAS_UNCONSUMED_REQUESTS(&queue->tx)))
|
||||
@@ -1931,92 +1972,64 @@ err:
|
||||
return err;
|
||||
}
|
||||
|
||||
-static void xenvif_start_queue(struct xenvif_queue *queue)
|
||||
+static bool xenvif_have_rx_work(struct xenvif_queue *queue)
|
||||
{
|
||||
- if (xenvif_schedulable(queue->vif))
|
||||
- xenvif_wake_queue(queue);
|
||||
+ return (!skb_queue_empty(&queue->rx_queue)
|
||||
+ && xenvif_rx_ring_slots_available(queue, XEN_NETBK_RX_SLOTS_MAX))
|
||||
+ || kthread_should_stop()
|
||||
+ || queue->vif->disabled;
|
||||
}
|
||||
|
||||
-/* Only called from the queue's thread, it handles the situation when the guest
|
||||
- * doesn't post enough requests on the receiving ring.
|
||||
- * First xenvif_start_xmit disables QDisc and start a timer, and then either the
|
||||
- * timer fires, or the guest send an interrupt after posting new request. If it
|
||||
- * is the timer, the carrier is turned off here.
|
||||
- * */
|
||||
-static void xenvif_rx_purge_event(struct xenvif_queue *queue)
|
||||
+static long xenvif_rx_queue_timeout(struct xenvif_queue *queue)
|
||||
{
|
||||
- /* Either the last unsuccesful skb or at least 1 slot should fit */
|
||||
- int needed = queue->rx_last_skb_slots ?
|
||||
- queue->rx_last_skb_slots : 1;
|
||||
+ struct sk_buff *skb;
|
||||
+ long timeout;
|
||||
|
||||
- /* It is assumed that if the guest post new slots after this, the RX
|
||||
- * interrupt will set the QUEUE_STATUS_RX_PURGE_EVENT bit and wake up
|
||||
- * the thread again
|
||||
- */
|
||||
- set_bit(QUEUE_STATUS_RX_STALLED, &queue->status);
|
||||
- if (!xenvif_rx_ring_slots_available(queue, needed)) {
|
||||
- rtnl_lock();
|
||||
- if (netif_carrier_ok(queue->vif->dev)) {
|
||||
- /* Timer fired and there are still no slots. Turn off
|
||||
- * everything except the interrupts
|
||||
- */
|
||||
- netif_carrier_off(queue->vif->dev);
|
||||
- skb_queue_purge(&queue->rx_queue);
|
||||
- queue->rx_last_skb_slots = 0;
|
||||
- if (net_ratelimit())
|
||||
- netdev_err(queue->vif->dev, "Carrier off due to lack of guest response on queue %d\n", queue->id);
|
||||
- } else {
|
||||
- /* Probably an another queue already turned the carrier
|
||||
- * off, make sure nothing is stucked in the internal
|
||||
- * queue of this queue
|
||||
- */
|
||||
- skb_queue_purge(&queue->rx_queue);
|
||||
- queue->rx_last_skb_slots = 0;
|
||||
- }
|
||||
- rtnl_unlock();
|
||||
- } else if (!netif_carrier_ok(queue->vif->dev)) {
|
||||
- unsigned int num_queues = queue->vif->num_queues;
|
||||
- unsigned int i;
|
||||
- /* The carrier was down, but an interrupt kicked
|
||||
- * the thread again after new requests were
|
||||
- * posted
|
||||
- */
|
||||
- clear_bit(QUEUE_STATUS_RX_STALLED,
|
||||
- &queue->status);
|
||||
- rtnl_lock();
|
||||
- netif_carrier_on(queue->vif->dev);
|
||||
- netif_tx_wake_all_queues(queue->vif->dev);
|
||||
- rtnl_unlock();
|
||||
+ skb = skb_peek(&queue->rx_queue);
|
||||
+ if (!skb)
|
||||
+ return MAX_SCHEDULE_TIMEOUT;
|
||||
|
||||
- for (i = 0; i < num_queues; i++) {
|
||||
- struct xenvif_queue *temp = &queue->vif->queues[i];
|
||||
+ timeout = XENVIF_RX_CB(skb)->expires - jiffies;
|
||||
+ return timeout < 0 ? 0 : timeout;
|
||||
+}
|
||||
|
||||
- xenvif_napi_schedule_or_enable_events(temp);
|
||||
- }
|
||||
- if (net_ratelimit())
|
||||
- netdev_err(queue->vif->dev, "Carrier on again\n");
|
||||
- } else {
|
||||
- /* Queuing were stopped, but the guest posted
|
||||
- * new requests and sent an interrupt
|
||||
- */
|
||||
- clear_bit(QUEUE_STATUS_RX_STALLED,
|
||||
- &queue->status);
|
||||
- del_timer_sync(&queue->rx_stalled);
|
||||
- xenvif_start_queue(queue);
|
||||
+/* Wait until the guest Rx thread has work.
|
||||
+ *
|
||||
+ * The timeout needs to be adjusted based on the current head of the
|
||||
+ * queue (and not just the head at the beginning). In particular, if
|
||||
+ * the queue is initially empty an infinite timeout is used and this
|
||||
+ * needs to be reduced when a skb is queued.
|
||||
+ *
|
||||
+ * This cannot be done with wait_event_timeout() because it only
|
||||
+ * calculates the timeout once.
|
||||
+ */
|
||||
+static void xenvif_wait_for_rx_work(struct xenvif_queue *queue)
|
||||
+{
|
||||
+ DEFINE_WAIT(wait);
|
||||
+
|
||||
+ if (xenvif_have_rx_work(queue))
|
||||
+ return;
|
||||
+
|
||||
+ for (;;) {
|
||||
+ long ret;
|
||||
+
|
||||
+ prepare_to_wait(&queue->wq, &wait, TASK_INTERRUPTIBLE);
|
||||
+ if (xenvif_have_rx_work(queue))
|
||||
+ break;
|
||||
+ ret = schedule_timeout(xenvif_rx_queue_timeout(queue));
|
||||
+ if (!ret)
|
||||
+ break;
|
||||
}
|
||||
+ finish_wait(&queue->wq, &wait);
|
||||
}
|
||||
|
||||
int xenvif_kthread_guest_rx(void *data)
|
||||
{
|
||||
struct xenvif_queue *queue = data;
|
||||
- struct sk_buff *skb;
|
||||
+ struct xenvif *vif = queue->vif;
|
||||
|
||||
- while (!kthread_should_stop()) {
|
||||
- wait_event_interruptible(queue->wq,
|
||||
- rx_work_todo(queue) ||
|
||||
- queue->vif->disabled ||
|
||||
- test_bit(QUEUE_STATUS_RX_PURGE_EVENT, &queue->status) ||
|
||||
- kthread_should_stop());
|
||||
+ for (;;) {
|
||||
+ xenvif_wait_for_rx_work(queue);
|
||||
|
||||
if (kthread_should_stop())
|
||||
break;
|
||||
@@ -2028,35 +2041,29 @@ int xenvif_kthread_guest_rx(void *data)
|
||||
* context so we defer it here, if this thread is
|
||||
* associated with queue 0.
|
||||
*/
|
||||
- if (unlikely(queue->vif->disabled && queue->id == 0)) {
|
||||
- xenvif_carrier_off(queue->vif);
|
||||
- } else if (unlikely(queue->vif->disabled)) {
|
||||
- /* kthread_stop() would be called upon this thread soon,
|
||||
- * be a bit proactive
|
||||
- */
|
||||
- skb_queue_purge(&queue->rx_queue);
|
||||
- queue->rx_last_skb_slots = 0;
|
||||
- } else if (unlikely(test_and_clear_bit(QUEUE_STATUS_RX_PURGE_EVENT,
|
||||
- &queue->status))) {
|
||||
- xenvif_rx_purge_event(queue);
|
||||
- } else if (!netif_carrier_ok(queue->vif->dev)) {
|
||||
- /* Another queue stalled and turned the carrier off, so
|
||||
- * purge the internal queue of queues which were not
|
||||
- * blocked
|
||||
- */
|
||||
- skb_queue_purge(&queue->rx_queue);
|
||||
- queue->rx_last_skb_slots = 0;
|
||||
+ if (unlikely(vif->disabled && queue->id == 0)) {
|
||||
+ xenvif_carrier_off(vif);
|
||||
+ xenvif_rx_queue_purge(queue);
|
||||
+ continue;
|
||||
}
|
||||
|
||||
if (!skb_queue_empty(&queue->rx_queue))
|
||||
xenvif_rx_action(queue);
|
||||
|
||||
+ /* Queued packets may have foreign pages from other
|
||||
+ * domains. These cannot be queued indefinitely as
|
||||
+ * this would starve guests of grant refs and transmit
|
||||
+ * slots.
|
||||
+ */
|
||||
+ xenvif_rx_queue_drop_expired(queue);
|
||||
+
|
||||
+ xenvif_rx_queue_maybe_wake(queue);
|
||||
+
|
||||
cond_resched();
|
||||
}
|
||||
|
||||
/* Bin any remaining skbs */
|
||||
- while ((skb = skb_dequeue(&queue->rx_queue)) != NULL)
|
||||
- dev_kfree_skb(skb);
|
||||
+ xenvif_rx_queue_purge(queue);
|
||||
|
||||
return 0;
|
||||
}
|
||||
diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c
|
||||
index 5e5cca1..54b5f24 100644
|
||||
--- a/drivers/net/xen-netback/xenbus.c
|
||||
+++ b/drivers/net/xen-netback/xenbus.c
|
||||
@@ -52,6 +52,7 @@ static int xenvif_read_io_ring(struct seq_file *m, void *v)
|
||||
struct xenvif_queue *queue = m->private;
|
||||
struct xen_netif_tx_back_ring *tx_ring = &queue->tx;
|
||||
struct xen_netif_rx_back_ring *rx_ring = &queue->rx;
|
||||
+ struct netdev_queue *dev_queue;
|
||||
|
||||
if (tx_ring->sring) {
|
||||
struct xen_netif_tx_sring *sring = tx_ring->sring;
|
||||
@@ -112,6 +113,13 @@ static int xenvif_read_io_ring(struct seq_file *m, void *v)
|
||||
queue->credit_timeout.expires,
|
||||
jiffies);
|
||||
|
||||
+ dev_queue = netdev_get_tx_queue(queue->vif->dev, queue->id);
|
||||
+
|
||||
+ seq_printf(m, "\nRx internal queue: len %u max %u pkts %u %s\n",
|
||||
+ queue->rx_queue_len, queue->rx_queue_max,
|
||||
+ skb_queue_len(&queue->rx_queue),
|
||||
+ netif_tx_queue_stopped(dev_queue) ? "stopped" : "running");
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
From 63350994825046216104c9c4c99db9e7a2715a97 Mon Sep 17 00:00:00 2001
|
||||
From: David Vrabel <david.vrabel@citrix.com>
|
||||
Date: Wed, 22 Oct 2014 14:08:53 +0100
|
||||
Subject: [PATCH 12/14] xen-netback: make feature-rx-notify mandatory
|
||||
Origin: https://git.kernel.org/linus/bc96f648df1bbc2729abbb84513cf4f64273a1f1
|
||||
|
||||
Frontends that do not provide feature-rx-notify may stall because
|
||||
netback depends on the notification from frontend to wake the guest Rx
|
||||
thread (even if can_queue is false).
|
||||
|
||||
This could be fixed but feature-rx-notify was introduced in 2006 and I
|
||||
am not aware of any frontends that do not implement this.
|
||||
|
||||
Signed-off-by: David Vrabel <david.vrabel@citrix.com>
|
||||
Acked-by: Wei Liu <wei.liu2@citrix.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
(cherry picked from commit bc96f648df1bbc2729abbb84513cf4f64273a1f1)
|
||||
---
|
||||
drivers/net/xen-netback/common.h | 5 -----
|
||||
drivers/net/xen-netback/interface.c | 12 +-----------
|
||||
drivers/net/xen-netback/xenbus.c | 13 ++++---------
|
||||
3 files changed, 5 insertions(+), 25 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h
|
||||
index d4eb8d2..93ca77c 100644
|
||||
--- a/drivers/net/xen-netback/common.h
|
||||
+++ b/drivers/net/xen-netback/common.h
|
||||
@@ -228,9 +228,6 @@ struct xenvif {
|
||||
u8 ip_csum:1;
|
||||
u8 ipv6_csum:1;
|
||||
|
||||
- /* Internal feature information. */
|
||||
- u8 can_queue:1; /* can queue packets for receiver? */
|
||||
-
|
||||
/* Is this interface disabled? True when backend discovers
|
||||
* frontend is rogue.
|
||||
*/
|
||||
@@ -272,8 +269,6 @@ void xenvif_xenbus_fini(void);
|
||||
|
||||
int xenvif_schedulable(struct xenvif *vif);
|
||||
|
||||
-int xenvif_must_stop_queue(struct xenvif_queue *queue);
|
||||
-
|
||||
int xenvif_queue_stopped(struct xenvif_queue *queue);
|
||||
void xenvif_wake_queue(struct xenvif_queue *queue);
|
||||
|
||||
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c
|
||||
index 18cdc81..6879251 100644
|
||||
--- a/drivers/net/xen-netback/interface.c
|
||||
+++ b/drivers/net/xen-netback/interface.c
|
||||
@@ -60,16 +60,6 @@ void xenvif_skb_zerocopy_complete(struct xenvif_queue *queue)
|
||||
atomic_dec(&queue->inflight_packets);
|
||||
}
|
||||
|
||||
-static inline void xenvif_stop_queue(struct xenvif_queue *queue)
|
||||
-{
|
||||
- struct net_device *dev = queue->vif->dev;
|
||||
-
|
||||
- if (!queue->vif->can_queue)
|
||||
- return;
|
||||
-
|
||||
- netif_tx_stop_queue(netdev_get_tx_queue(dev, queue->id));
|
||||
-}
|
||||
-
|
||||
int xenvif_schedulable(struct xenvif *vif)
|
||||
{
|
||||
return netif_running(vif->dev) &&
|
||||
@@ -209,7 +199,7 @@ static int xenvif_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
if (!xenvif_rx_ring_slots_available(queue, min_slots_needed)) {
|
||||
queue->rx_stalled.function = xenvif_rx_stalled;
|
||||
queue->rx_stalled.data = (unsigned long)queue;
|
||||
- xenvif_stop_queue(queue);
|
||||
+ netif_tx_stop_queue(netdev_get_tx_queue(dev, queue->id));
|
||||
mod_timer(&queue->rx_stalled,
|
||||
jiffies + rx_drain_timeout_jiffies);
|
||||
}
|
||||
diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c
|
||||
index 9c47b89..5e5cca1 100644
|
||||
--- a/drivers/net/xen-netback/xenbus.c
|
||||
+++ b/drivers/net/xen-netback/xenbus.c
|
||||
@@ -873,15 +873,10 @@ static int read_xenbus_vif_flags(struct backend_info *be)
|
||||
if (!rx_copy)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
- if (vif->dev->tx_queue_len != 0) {
|
||||
- if (xenbus_scanf(XBT_NIL, dev->otherend,
|
||||
- "feature-rx-notify", "%d", &val) < 0)
|
||||
- val = 0;
|
||||
- if (val)
|
||||
- vif->can_queue = 1;
|
||||
- else
|
||||
- /* Must be non-zero for pfifo_fast to work. */
|
||||
- vif->dev->tx_queue_len = 1;
|
||||
+ if (xenbus_scanf(XBT_NIL, dev->otherend,
|
||||
+ "feature-rx-notify", "%d", &val) < 0 || val == 0) {
|
||||
+ xenbus_dev_fatal(dev, -EINVAL, "feature-rx-notify is mandatory");
|
||||
+ return -EINVAL;
|
||||
}
|
||||
|
||||
if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-sg",
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -1,218 +0,0 @@
|
|||
From bd54d3b8d2a15e230f81965041169ba0dc2210c8 Mon Sep 17 00:00:00 2001
|
||||
From: David Vrabel <david.vrabel@citrix.com>
|
||||
Date: Wed, 22 Oct 2014 14:08:55 +0100
|
||||
Subject: [PATCH 14/14] xen-netback: reintroduce guest Rx stall detection
|
||||
Origin: https://git.kernel.org/linus/ecf08d2dbb96d5a4b4bcc53a39e8d29cc8fef02e
|
||||
|
||||
If a frontend not receiving packets it is useful to detect this and
|
||||
turn off the carrier so packets are dropped early instead of being
|
||||
queued and drained when they expire.
|
||||
|
||||
A to-guest queue is stalled if it doesn't have enough free slots for a
|
||||
an extended period of time (default 60 s).
|
||||
|
||||
If at least one queue is stalled, the carrier is turned off (in the
|
||||
expectation that the other queues will soon stall as well). The
|
||||
carrier is only turned on once all queues are ready.
|
||||
|
||||
When the frontend connects, all the queues start in the stalled state
|
||||
and only become ready once the frontend queues enough Rx requests.
|
||||
|
||||
Signed-off-by: David Vrabel <david.vrabel@citrix.com>
|
||||
Reviewed-by: Wei Liu <wei.liu2@citrix.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
(cherry picked from commit ecf08d2dbb96d5a4b4bcc53a39e8d29cc8fef02e)
|
||||
---
|
||||
drivers/net/xen-netback/common.h | 5 +++
|
||||
drivers/net/xen-netback/interface.c | 5 ++-
|
||||
drivers/net/xen-netback/netback.c | 76 +++++++++++++++++++++++++++++++++++
|
||||
drivers/net/xen-netback/xenbus.c | 1 +
|
||||
4 files changed, 86 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h
|
||||
index c264240..083ecc9 100644
|
||||
--- a/drivers/net/xen-netback/common.h
|
||||
+++ b/drivers/net/xen-netback/common.h
|
||||
@@ -179,6 +179,8 @@ struct xenvif_queue { /* Per-queue data for xenvif */
|
||||
|
||||
unsigned int rx_queue_max;
|
||||
unsigned int rx_queue_len;
|
||||
+ unsigned long last_rx_time;
|
||||
+ bool stalled;
|
||||
|
||||
struct gnttab_copy grant_copy_op[MAX_GRANT_COPY_OPS];
|
||||
|
||||
@@ -232,6 +234,9 @@ struct xenvif {
|
||||
/* Queues */
|
||||
struct xenvif_queue *queues;
|
||||
unsigned int num_queues; /* active queues, resource allocated */
|
||||
+ unsigned int stalled_queues;
|
||||
+
|
||||
+ spinlock_t lock;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *xenvif_dbg_root;
|
||||
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c
|
||||
index 9e8af0b..21d8db8 100644
|
||||
--- a/drivers/net/xen-netback/interface.c
|
||||
+++ b/drivers/net/xen-netback/interface.c
|
||||
@@ -419,6 +419,8 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid,
|
||||
vif->queues = NULL;
|
||||
vif->num_queues = 0;
|
||||
|
||||
+ spin_lock_init(&vif->lock);
|
||||
+
|
||||
dev->netdev_ops = &xenvif_netdev_ops;
|
||||
dev->hw_features = NETIF_F_SG |
|
||||
NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
|
||||
@@ -505,7 +507,6 @@ void xenvif_carrier_on(struct xenvif *vif)
|
||||
dev_set_mtu(vif->dev, ETH_DATA_LEN);
|
||||
netdev_update_features(vif->dev);
|
||||
set_bit(VIF_STATUS_CONNECTED, &vif->status);
|
||||
- netif_carrier_on(vif->dev);
|
||||
if (netif_running(vif->dev))
|
||||
xenvif_up(vif);
|
||||
rtnl_unlock();
|
||||
@@ -565,6 +566,8 @@ int xenvif_connect(struct xenvif_queue *queue, unsigned long tx_ring_ref,
|
||||
disable_irq(queue->rx_irq);
|
||||
}
|
||||
|
||||
+ queue->stalled = true;
|
||||
+
|
||||
task = kthread_create(xenvif_kthread_guest_rx,
|
||||
(void *)queue, "%s-guest-rx", queue->name);
|
||||
if (IS_ERR(task)) {
|
||||
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
|
||||
index 57aa3b5..6563f07 100644
|
||||
--- a/drivers/net/xen-netback/netback.c
|
||||
+++ b/drivers/net/xen-netback/netback.c
|
||||
@@ -62,6 +62,13 @@ unsigned int rx_drain_timeout_msecs = 10000;
|
||||
module_param(rx_drain_timeout_msecs, uint, 0444);
|
||||
unsigned int rx_drain_timeout_jiffies;
|
||||
|
||||
+/* The length of time before the frontend is considered unresponsive
|
||||
+ * because it isn't providing Rx slots.
|
||||
+ */
|
||||
+static unsigned int rx_stall_timeout_msecs = 60000;
|
||||
+module_param(rx_stall_timeout_msecs, uint, 0444);
|
||||
+static unsigned int rx_stall_timeout_jiffies;
|
||||
+
|
||||
unsigned int xenvif_max_queues;
|
||||
module_param_named(max_queues, xenvif_max_queues, uint, 0644);
|
||||
MODULE_PARM_DESC(max_queues,
|
||||
@@ -649,6 +656,8 @@ static void xenvif_rx_action(struct xenvif_queue *queue)
|
||||
RING_IDX ring_slots_used;
|
||||
int i;
|
||||
|
||||
+ queue->last_rx_time = jiffies;
|
||||
+
|
||||
/* We need a cheap worse case estimate for the number of
|
||||
* slots we'll use.
|
||||
*/
|
||||
@@ -1972,10 +1981,67 @@ err:
|
||||
return err;
|
||||
}
|
||||
|
||||
+static void xenvif_queue_carrier_off(struct xenvif_queue *queue)
|
||||
+{
|
||||
+ struct xenvif *vif = queue->vif;
|
||||
+
|
||||
+ queue->stalled = true;
|
||||
+
|
||||
+ /* At least one queue has stalled? Disable the carrier. */
|
||||
+ spin_lock(&vif->lock);
|
||||
+ if (vif->stalled_queues++ == 0) {
|
||||
+ netdev_info(vif->dev, "Guest Rx stalled");
|
||||
+ netif_carrier_off(vif->dev);
|
||||
+ }
|
||||
+ spin_unlock(&vif->lock);
|
||||
+}
|
||||
+
|
||||
+static void xenvif_queue_carrier_on(struct xenvif_queue *queue)
|
||||
+{
|
||||
+ struct xenvif *vif = queue->vif;
|
||||
+
|
||||
+ queue->last_rx_time = jiffies; /* Reset Rx stall detection. */
|
||||
+ queue->stalled = false;
|
||||
+
|
||||
+ /* All queues are ready? Enable the carrier. */
|
||||
+ spin_lock(&vif->lock);
|
||||
+ if (--vif->stalled_queues == 0) {
|
||||
+ netdev_info(vif->dev, "Guest Rx ready");
|
||||
+ netif_carrier_on(vif->dev);
|
||||
+ }
|
||||
+ spin_unlock(&vif->lock);
|
||||
+}
|
||||
+
|
||||
+static bool xenvif_rx_queue_stalled(struct xenvif_queue *queue)
|
||||
+{
|
||||
+ RING_IDX prod, cons;
|
||||
+
|
||||
+ prod = queue->rx.sring->req_prod;
|
||||
+ cons = queue->rx.req_cons;
|
||||
+
|
||||
+ return !queue->stalled
|
||||
+ && prod - cons < XEN_NETBK_RX_SLOTS_MAX
|
||||
+ && time_after(jiffies,
|
||||
+ queue->last_rx_time + rx_stall_timeout_jiffies);
|
||||
+}
|
||||
+
|
||||
+static bool xenvif_rx_queue_ready(struct xenvif_queue *queue)
|
||||
+{
|
||||
+ RING_IDX prod, cons;
|
||||
+
|
||||
+ prod = queue->rx.sring->req_prod;
|
||||
+ cons = queue->rx.req_cons;
|
||||
+
|
||||
+ return queue->stalled
|
||||
+ && prod - cons >= XEN_NETBK_RX_SLOTS_MAX;
|
||||
+}
|
||||
+
|
||||
static bool xenvif_have_rx_work(struct xenvif_queue *queue)
|
||||
{
|
||||
return (!skb_queue_empty(&queue->rx_queue)
|
||||
&& xenvif_rx_ring_slots_available(queue, XEN_NETBK_RX_SLOTS_MAX))
|
||||
+ || xenvif_rx_queue_stalled(queue)
|
||||
+ || xenvif_rx_queue_ready(queue)
|
||||
|| kthread_should_stop()
|
||||
|| queue->vif->disabled;
|
||||
}
|
||||
@@ -2050,6 +2116,15 @@ int xenvif_kthread_guest_rx(void *data)
|
||||
if (!skb_queue_empty(&queue->rx_queue))
|
||||
xenvif_rx_action(queue);
|
||||
|
||||
+ /* If the guest hasn't provided any Rx slots for a
|
||||
+ * while it's probably not responsive, drop the
|
||||
+ * carrier so packets are dropped earlier.
|
||||
+ */
|
||||
+ if (xenvif_rx_queue_stalled(queue))
|
||||
+ xenvif_queue_carrier_off(queue);
|
||||
+ else if (xenvif_rx_queue_ready(queue))
|
||||
+ xenvif_queue_carrier_on(queue);
|
||||
+
|
||||
/* Queued packets may have foreign pages from other
|
||||
* domains. These cannot be queued indefinitely as
|
||||
* this would starve guests of grant refs and transmit
|
||||
@@ -2120,6 +2195,7 @@ static int __init netback_init(void)
|
||||
goto failed_init;
|
||||
|
||||
rx_drain_timeout_jiffies = msecs_to_jiffies(rx_drain_timeout_msecs);
|
||||
+ rx_stall_timeout_jiffies = msecs_to_jiffies(rx_stall_timeout_msecs);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
xen_netback_dbg_root = debugfs_create_dir("xen-netback", NULL);
|
||||
diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c
|
||||
index 54b5f24..396b3d9 100644
|
||||
--- a/drivers/net/xen-netback/xenbus.c
|
||||
+++ b/drivers/net/xen-netback/xenbus.c
|
||||
@@ -711,6 +711,7 @@ static void connect(struct backend_info *be)
|
||||
be->vif->queues = vzalloc(requested_num_queues *
|
||||
sizeof(struct xenvif_queue));
|
||||
be->vif->num_queues = requested_num_queues;
|
||||
+ be->vif->stalled_queues = requested_num_queues;
|
||||
|
||||
for (queue_index = 0; queue_index < requested_num_queues; ++queue_index) {
|
||||
queue = &be->vif->queues[queue_index];
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
From: Helge Deller <deller@gmx.de>
|
||||
Date: Fri, 10 Oct 2014 22:20:17 +0200
|
||||
Subject: parisc: Reduce SIGRTMIN from 37 to 32 to behave like other Linux
|
||||
architectures
|
||||
Origin: https://git.kernel.org/linus/1f25df2eff5b25f52c139d3ff31bc883eee9a0ab
|
||||
Bug-Debian: https://bugs.debian.org/766635
|
||||
|
||||
This patch reduces the value of SIGRTMIN on PARISC from 37 to 32, thus
|
||||
increasing the number of available RT signals and bring it in sync with other
|
||||
Linux architectures.
|
||||
|
||||
Historically we wanted to natively support HP-UX 32bit binaries with the
|
||||
PA-RISC Linux port. Because of that we carried the various available signals
|
||||
from HP-UX (e.g. SIGEMT and SIGLOST) and folded them in between the native
|
||||
Linux signals. Although this was the right decision at that time, this
|
||||
required us to increase SIGRTMIN to at least 37 which left us with 27 (64-37)
|
||||
RT signals.
|
||||
|
||||
Those 27 RT signals haven't been a problem in the past, but with the upcoming
|
||||
importance of systemd we now got the problem that systemd alloctes (hardcoded)
|
||||
signals up to SIGRTMIN+29 which is beyond our NSIG of 64. Because of that we
|
||||
have not been able to use systemd on the PARISC Linux port yet.
|
||||
|
||||
Of course we could ask the systemd developers to not use those hardcoded
|
||||
values, but this change is very unlikely, esp. with PA-RISC being a niche
|
||||
architecture.
|
||||
|
||||
The other possibility would be to increase NSIG to e.g. 128, but this would
|
||||
mean to duplicate most of the existing Linux signal handling code into the
|
||||
parisc specific Linux kernel tree which would most likely introduce lots of new
|
||||
bugs beside the code duplication.
|
||||
|
||||
The third option is to drop some HP-UX signals and shuffle some other signals
|
||||
around to bring SIGRTMIN to 32. This is of course an ABI change, but testing
|
||||
has shown that existing Linux installations are not visibly affected by this
|
||||
change - most likely because we move those signals around which are rarely used
|
||||
and move them to slots which haven't been used in Linux yet. In an existing
|
||||
installation I was able to exchange either the Linux kernel or glibc (or both)
|
||||
without affecting the boot process and installed applications.
|
||||
|
||||
Dropping the HP-UX signals isn't an issue either, since support for HP-UX was
|
||||
basically dropped a few months back with Kernel 3.14 in commit
|
||||
f5a408d53edef3af07ac7697b8bc54a755628450 already, when we changed EWOULDBLOCK
|
||||
to be equal to EAGAIN.
|
||||
|
||||
So, even if this is an ABI change, it's better to change it now and thus bring
|
||||
PARISC Linux in sync with other architectures to avoid other issues in the
|
||||
future.
|
||||
|
||||
Signed-off-by: Helge Deller <deller@gmx.de>
|
||||
Cc: Carlos O'Donell <carlos@systemhalted.org>
|
||||
Cc: John David Anglin <dave.anglin@bell.net>
|
||||
Cc: James Bottomley <James.Bottomley@HansenPartnership.com>
|
||||
Cc: Aaro Koskinen <aaro.koskinen@iki.fi>
|
||||
Cc: PARISC Linux Kernel Mailinglist <linux-parisc@vger.kernel.org>
|
||||
Tested-by: Aaro Koskinen <aaro.koskinen@iki.fi>
|
||||
---
|
||||
arch/parisc/include/uapi/asm/signal.h | 16 ++++++----------
|
||||
1 file changed, 6 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/arch/parisc/include/uapi/asm/signal.h b/arch/parisc/include/uapi/asm/signal.h
|
||||
index f5645d6..10df707 100644
|
||||
--- a/arch/parisc/include/uapi/asm/signal.h
|
||||
+++ b/arch/parisc/include/uapi/asm/signal.h
|
||||
@@ -8,12 +8,12 @@
|
||||
#define SIGTRAP 5
|
||||
#define SIGABRT 6
|
||||
#define SIGIOT 6
|
||||
-#define SIGEMT 7
|
||||
+#define SIGSTKFLT 7
|
||||
#define SIGFPE 8
|
||||
#define SIGKILL 9
|
||||
#define SIGBUS 10
|
||||
#define SIGSEGV 11
|
||||
-#define SIGSYS 12 /* Linux doesn't use this */
|
||||
+#define SIGXCPU 12
|
||||
#define SIGPIPE 13
|
||||
#define SIGALRM 14
|
||||
#define SIGTERM 15
|
||||
@@ -32,16 +32,12 @@
|
||||
#define SIGTTIN 27
|
||||
#define SIGTTOU 28
|
||||
#define SIGURG 29
|
||||
-#define SIGLOST 30 /* Linux doesn't use this either */
|
||||
-#define SIGUNUSED 31
|
||||
-#define SIGRESERVE SIGUNUSED
|
||||
-
|
||||
-#define SIGXCPU 33
|
||||
-#define SIGXFSZ 34
|
||||
-#define SIGSTKFLT 36
|
||||
+#define SIGXFSZ 30
|
||||
+#define SIGUNUSED 31
|
||||
+#define SIGSYS 31 /* Linux doesn't use this */
|
||||
|
||||
/* These should not be considered constants from userland. */
|
||||
-#define SIGRTMIN 37
|
||||
+#define SIGRTMIN 32
|
||||
#define SIGRTMAX _NSIG /* it's 44 under HP/UX */
|
||||
|
||||
/*
|
|
@ -1,111 +0,0 @@
|
|||
From: Andy Lutomirski <luto@amacapital.net>
|
||||
Date: Sat, 22 Nov 2014 18:00:31 -0800
|
||||
Subject: x86_64, traps: Fix the espfix64 #DF fixup and rewrite it in C
|
||||
Origin: https://git.kernel.org/linus/af726f21ed8af2cdaa4e93098dc211521218ae65
|
||||
|
||||
There's nothing special enough about the espfix64 double fault fixup to
|
||||
justify writing it in assembly. Move it to C.
|
||||
|
||||
This also fixes a bug: if the double fault came from an IST stack, the
|
||||
old asm code would return to a partially uninitialized stack frame.
|
||||
|
||||
Fixes: 3891a04aafd668686239349ea58f3314ea2af86b
|
||||
Signed-off-by: Andy Lutomirski <luto@amacapital.net>
|
||||
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
---
|
||||
arch/x86/kernel/entry_64.S | 34 ++--------------------------------
|
||||
arch/x86/kernel/traps.c | 24 ++++++++++++++++++++++++
|
||||
2 files changed, 26 insertions(+), 32 deletions(-)
|
||||
|
||||
--- a/arch/x86/kernel/entry_64.S
|
||||
+++ b/arch/x86/kernel/entry_64.S
|
||||
@@ -860,6 +860,7 @@ ENTRY(native_iret)
|
||||
jnz native_irq_return_ldt
|
||||
#endif
|
||||
|
||||
+.global native_irq_return_iret
|
||||
native_irq_return_iret:
|
||||
iretq
|
||||
_ASM_EXTABLE(native_irq_return_iret, bad_iret)
|
||||
@@ -954,37 +955,6 @@ ENTRY(retint_kernel)
|
||||
CFI_ENDPROC
|
||||
END(common_interrupt)
|
||||
|
||||
- /*
|
||||
- * If IRET takes a fault on the espfix stack, then we
|
||||
- * end up promoting it to a doublefault. In that case,
|
||||
- * modify the stack to make it look like we just entered
|
||||
- * the #GP handler from user space, similar to bad_iret.
|
||||
- */
|
||||
-#ifdef CONFIG_X86_ESPFIX64
|
||||
- ALIGN
|
||||
-__do_double_fault:
|
||||
- XCPT_FRAME 1 RDI+8
|
||||
- movq RSP(%rdi),%rax /* Trap on the espfix stack? */
|
||||
- sarq $PGDIR_SHIFT,%rax
|
||||
- cmpl $ESPFIX_PGD_ENTRY,%eax
|
||||
- jne do_double_fault /* No, just deliver the fault */
|
||||
- cmpl $__KERNEL_CS,CS(%rdi)
|
||||
- jne do_double_fault
|
||||
- movq RIP(%rdi),%rax
|
||||
- cmpq $native_irq_return_iret,%rax
|
||||
- jne do_double_fault /* This shouldn't happen... */
|
||||
- movq PER_CPU_VAR(kernel_stack),%rax
|
||||
- subq $(6*8-KERNEL_STACK_OFFSET),%rax /* Reset to original stack */
|
||||
- movq %rax,RSP(%rdi)
|
||||
- movq $0,(%rax) /* Missing (lost) #GP error code */
|
||||
- movq $general_protection,RIP(%rdi)
|
||||
- retq
|
||||
- CFI_ENDPROC
|
||||
-END(__do_double_fault)
|
||||
-#else
|
||||
-# define __do_double_fault do_double_fault
|
||||
-#endif
|
||||
-
|
||||
/*
|
||||
* APIC interrupts.
|
||||
*/
|
||||
@@ -1156,7 +1126,7 @@ idtentry overflow do_overflow has_error_
|
||||
idtentry bounds do_bounds has_error_code=0
|
||||
idtentry invalid_op do_invalid_op has_error_code=0
|
||||
idtentry device_not_available do_device_not_available has_error_code=0
|
||||
-idtentry double_fault __do_double_fault has_error_code=1 paranoid=1
|
||||
+idtentry double_fault do_double_fault has_error_code=1 paranoid=1
|
||||
idtentry coprocessor_segment_overrun do_coprocessor_segment_overrun has_error_code=0
|
||||
idtentry invalid_TSS do_invalid_TSS has_error_code=1
|
||||
idtentry segment_not_present do_segment_not_present has_error_code=1
|
||||
--- a/arch/x86/kernel/traps.c
|
||||
+++ b/arch/x86/kernel/traps.c
|
||||
@@ -243,6 +243,30 @@ dotraplinkage void do_double_fault(struc
|
||||
static const char str[] = "double fault";
|
||||
struct task_struct *tsk = current;
|
||||
|
||||
+#ifdef CONFIG_X86_ESPFIX64
|
||||
+ extern unsigned char native_irq_return_iret[];
|
||||
+
|
||||
+ /*
|
||||
+ * If IRET takes a non-IST fault on the espfix64 stack, then we
|
||||
+ * end up promoting it to a doublefault. In that case, modify
|
||||
+ * the stack to make it look like we just entered the #GP
|
||||
+ * handler from user space, similar to bad_iret.
|
||||
+ */
|
||||
+ if (((long)regs->sp >> PGDIR_SHIFT) == ESPFIX_PGD_ENTRY &&
|
||||
+ regs->cs == __KERNEL_CS &&
|
||||
+ regs->ip == (unsigned long)native_irq_return_iret)
|
||||
+ {
|
||||
+ struct pt_regs *normal_regs = task_pt_regs(current);
|
||||
+
|
||||
+ /* Fake a #GP(0) from userspace. */
|
||||
+ memmove(&normal_regs->ip, (void *)regs->sp, 5*8);
|
||||
+ normal_regs->orig_ax = 0; /* Missing (lost) #GP error code */
|
||||
+ regs->ip = (unsigned long)general_protection;
|
||||
+ regs->sp = (unsigned long)&normal_regs->orig_ax;
|
||||
+ return;
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
exception_enter();
|
||||
/* Return not checked because double check cannot be ignored */
|
||||
notify_die(DIE_TRAP, str, regs, error_code, X86_TRAP_DF, SIGSEGV);
|
|
@ -1,154 +0,0 @@
|
|||
From: Andy Lutomirski <luto@amacapital.net>
|
||||
Date: Sat, 22 Nov 2014 18:00:33 -0800
|
||||
Subject: x86_64, traps: Rework bad_iret
|
||||
Origin: https://git.kernel.org/linus/b645af2d5905c4e32399005b867987919cbfc3ae
|
||||
|
||||
It's possible for iretq to userspace to fail. This can happen because
|
||||
of a bad CS, SS, or RIP.
|
||||
|
||||
Historically, we've handled it by fixing up an exception from iretq to
|
||||
land at bad_iret, which pretends that the failed iret frame was really
|
||||
the hardware part of #GP(0) from userspace. To make this work, there's
|
||||
an extra fixup to fudge the gs base into a usable state.
|
||||
|
||||
This is suboptimal because it loses the original exception. It's also
|
||||
buggy because there's no guarantee that we were on the kernel stack to
|
||||
begin with. For example, if the failing iret happened on return from an
|
||||
NMI, then we'll end up executing general_protection on the NMI stack.
|
||||
This is bad for several reasons, the most immediate of which is that
|
||||
general_protection, as a non-paranoid idtentry, will try to deliver
|
||||
signals and/or schedule from the wrong stack.
|
||||
|
||||
This patch throws out bad_iret entirely. As a replacement, it augments
|
||||
the existing swapgs fudge into a full-blown iret fixup, mostly written
|
||||
in C. It's should be clearer and more correct.
|
||||
|
||||
Signed-off-by: Andy Lutomirski <luto@amacapital.net>
|
||||
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
---
|
||||
arch/x86/kernel/entry_64.S | 45 +++++++++++++++++++--------------------------
|
||||
arch/x86/kernel/traps.c | 29 +++++++++++++++++++++++++++++
|
||||
2 files changed, 48 insertions(+), 26 deletions(-)
|
||||
|
||||
--- a/arch/x86/kernel/entry_64.S
|
||||
+++ b/arch/x86/kernel/entry_64.S
|
||||
@@ -843,8 +843,13 @@ ENTRY(native_iret)
|
||||
|
||||
.global native_irq_return_iret
|
||||
native_irq_return_iret:
|
||||
+ /*
|
||||
+ * This may fault. Non-paranoid faults on return to userspace are
|
||||
+ * handled by fixup_bad_iret. These include #SS, #GP, and #NP.
|
||||
+ * Double-faults due to espfix64 are handled in do_double_fault.
|
||||
+ * Other faults here are fatal.
|
||||
+ */
|
||||
iretq
|
||||
- _ASM_EXTABLE(native_irq_return_iret, bad_iret)
|
||||
|
||||
#ifdef CONFIG_X86_ESPFIX64
|
||||
native_irq_return_ldt:
|
||||
@@ -872,25 +877,6 @@ native_irq_return_ldt:
|
||||
jmp native_irq_return_iret
|
||||
#endif
|
||||
|
||||
- .section .fixup,"ax"
|
||||
-bad_iret:
|
||||
- /*
|
||||
- * The iret traps when the %cs or %ss being restored is bogus.
|
||||
- * We've lost the original trap vector and error code.
|
||||
- * #GPF is the most likely one to get for an invalid selector.
|
||||
- * So pretend we completed the iret and took the #GPF in user mode.
|
||||
- *
|
||||
- * We are now running with the kernel GS after exception recovery.
|
||||
- * But error_entry expects us to have user GS to match the user %cs,
|
||||
- * so swap back.
|
||||
- */
|
||||
- pushq $0
|
||||
-
|
||||
- SWAPGS
|
||||
- jmp general_protection
|
||||
-
|
||||
- .previous
|
||||
-
|
||||
/* edi: workmask, edx: work */
|
||||
retint_careful:
|
||||
CFI_RESTORE_STATE
|
||||
@@ -1382,17 +1368,16 @@ error_sti:
|
||||
|
||||
/*
|
||||
* There are two places in the kernel that can potentially fault with
|
||||
- * usergs. Handle them here. The exception handlers after iret run with
|
||||
- * kernel gs again, so don't set the user space flag. B stepping K8s
|
||||
- * sometimes report an truncated RIP for IRET exceptions returning to
|
||||
- * compat mode. Check for these here too.
|
||||
+ * usergs. Handle them here. B stepping K8s sometimes report a
|
||||
+ * truncated RIP for IRET exceptions returning to compat mode. Check
|
||||
+ * for these here too.
|
||||
*/
|
||||
error_kernelspace:
|
||||
CFI_REL_OFFSET rcx, RCX+8
|
||||
incl %ebx
|
||||
leaq native_irq_return_iret(%rip),%rcx
|
||||
cmpq %rcx,RIP+8(%rsp)
|
||||
- je error_swapgs
|
||||
+ je error_bad_iret
|
||||
movl %ecx,%eax /* zero extend */
|
||||
cmpq %rax,RIP+8(%rsp)
|
||||
je bstep_iret
|
||||
@@ -1403,7 +1388,15 @@ error_kernelspace:
|
||||
bstep_iret:
|
||||
/* Fix truncated RIP */
|
||||
movq %rcx,RIP+8(%rsp)
|
||||
- jmp error_swapgs
|
||||
+ /* fall through */
|
||||
+
|
||||
+error_bad_iret:
|
||||
+ SWAPGS
|
||||
+ mov %rsp,%rdi
|
||||
+ call fixup_bad_iret
|
||||
+ mov %rax,%rsp
|
||||
+ decl %ebx /* Return to usergs */
|
||||
+ jmp error_sti
|
||||
CFI_ENDPROC
|
||||
END(error_entry)
|
||||
|
||||
--- a/arch/x86/kernel/traps.c
|
||||
+++ b/arch/x86/kernel/traps.c
|
||||
@@ -407,6 +407,35 @@ asmlinkage __visible struct pt_regs *syn
|
||||
return regs;
|
||||
}
|
||||
NOKPROBE_SYMBOL(sync_regs);
|
||||
+
|
||||
+struct bad_iret_stack {
|
||||
+ void *error_entry_ret;
|
||||
+ struct pt_regs regs;
|
||||
+};
|
||||
+
|
||||
+asmlinkage __visible
|
||||
+struct bad_iret_stack *fixup_bad_iret(struct bad_iret_stack *s)
|
||||
+{
|
||||
+ /*
|
||||
+ * This is called from entry_64.S early in handling a fault
|
||||
+ * caused by a bad iret to user mode. To handle the fault
|
||||
+ * correctly, we want move our stack frame to task_pt_regs
|
||||
+ * and we want to pretend that the exception came from the
|
||||
+ * iret target.
|
||||
+ */
|
||||
+ struct bad_iret_stack *new_stack =
|
||||
+ container_of(task_pt_regs(current),
|
||||
+ struct bad_iret_stack, regs);
|
||||
+
|
||||
+ /* Copy the IRET target to the new stack. */
|
||||
+ memmove(&new_stack->regs.ip, (void *)s->regs.sp, 5*8);
|
||||
+
|
||||
+ /* Copy the remainder of the stack from the current stack. */
|
||||
+ memmove(new_stack, s, offsetof(struct bad_iret_stack, regs.ip));
|
||||
+
|
||||
+ BUG_ON(!user_mode_vm(&new_stack->regs));
|
||||
+ return new_stack;
|
||||
+}
|
||||
#endif
|
||||
|
||||
/*
|
|
@ -1,131 +0,0 @@
|
|||
From: Andy Lutomirski <luto@amacapital.net>
|
||||
Date: Sat, 22 Nov 2014 18:00:32 -0800
|
||||
Subject: x86_64, traps: Stop using IST for #SS
|
||||
Origin: https://git.kernel.org/linus/6f442be2fb22be02cafa606f1769fa1e6f894441
|
||||
|
||||
On a 32-bit kernel, this has no effect, since there are no IST stacks.
|
||||
|
||||
On a 64-bit kernel, #SS can only happen in user code, on a failed iret
|
||||
to user space, a canonical violation on access via RSP or RBP, or a
|
||||
genuine stack segment violation in 32-bit kernel code. The first two
|
||||
cases don't need IST, and the latter two cases are unlikely fatal bugs,
|
||||
and promoting them to double faults would be fine.
|
||||
|
||||
This fixes a bug in which the espfix64 code mishandles a stack segment
|
||||
violation.
|
||||
|
||||
This saves 4k of memory per CPU and a tiny bit of code.
|
||||
|
||||
Signed-off-by: Andy Lutomirski <luto@amacapital.net>
|
||||
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
---
|
||||
arch/x86/include/asm/page_32_types.h | 1 -
|
||||
arch/x86/include/asm/page_64_types.h | 11 +++++------
|
||||
arch/x86/include/asm/traps.h | 1 +
|
||||
arch/x86/kernel/dumpstack_64.c | 1 -
|
||||
arch/x86/kernel/entry_64.S | 2 +-
|
||||
arch/x86/kernel/traps.c | 18 +-----------------
|
||||
6 files changed, 8 insertions(+), 26 deletions(-)
|
||||
|
||||
--- a/arch/x86/include/asm/page_32_types.h
|
||||
+++ b/arch/x86/include/asm/page_32_types.h
|
||||
@@ -20,7 +20,6 @@
|
||||
#define THREAD_SIZE_ORDER 1
|
||||
#define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER)
|
||||
|
||||
-#define STACKFAULT_STACK 0
|
||||
#define DOUBLEFAULT_STACK 1
|
||||
#define NMI_STACK 0
|
||||
#define DEBUG_STACK 0
|
||||
--- a/arch/x86/include/asm/page_64_types.h
|
||||
+++ b/arch/x86/include/asm/page_64_types.h
|
||||
@@ -14,12 +14,11 @@
|
||||
#define IRQ_STACK_ORDER 2
|
||||
#define IRQ_STACK_SIZE (PAGE_SIZE << IRQ_STACK_ORDER)
|
||||
|
||||
-#define STACKFAULT_STACK 1
|
||||
-#define DOUBLEFAULT_STACK 2
|
||||
-#define NMI_STACK 3
|
||||
-#define DEBUG_STACK 4
|
||||
-#define MCE_STACK 5
|
||||
-#define N_EXCEPTION_STACKS 5 /* hw limit: 7 */
|
||||
+#define DOUBLEFAULT_STACK 1
|
||||
+#define NMI_STACK 2
|
||||
+#define DEBUG_STACK 3
|
||||
+#define MCE_STACK 4
|
||||
+#define N_EXCEPTION_STACKS 4 /* hw limit: 7 */
|
||||
|
||||
#define PUD_PAGE_SIZE (_AC(1, UL) << PUD_SHIFT)
|
||||
#define PUD_PAGE_MASK (~(PUD_PAGE_SIZE-1))
|
||||
--- a/arch/x86/include/asm/traps.h
|
||||
+++ b/arch/x86/include/asm/traps.h
|
||||
@@ -39,6 +39,7 @@ asmlinkage void simd_coprocessor_error(v
|
||||
|
||||
#ifdef CONFIG_TRACING
|
||||
asmlinkage void trace_page_fault(void);
|
||||
+#define trace_stack_segment stack_segment
|
||||
#define trace_divide_error divide_error
|
||||
#define trace_bounds bounds
|
||||
#define trace_invalid_op invalid_op
|
||||
--- a/arch/x86/kernel/dumpstack_64.c
|
||||
+++ b/arch/x86/kernel/dumpstack_64.c
|
||||
@@ -24,7 +24,6 @@ static char x86_stack_ids[][8] = {
|
||||
[ DEBUG_STACK-1 ] = "#DB",
|
||||
[ NMI_STACK-1 ] = "NMI",
|
||||
[ DOUBLEFAULT_STACK-1 ] = "#DF",
|
||||
- [ STACKFAULT_STACK-1 ] = "#SS",
|
||||
[ MCE_STACK-1 ] = "#MC",
|
||||
#if DEBUG_STKSZ > EXCEPTION_STKSZ
|
||||
[ N_EXCEPTION_STACKS ...
|
||||
--- a/arch/x86/kernel/entry_64.S
|
||||
+++ b/arch/x86/kernel/entry_64.S
|
||||
@@ -1321,7 +1321,7 @@ apicinterrupt3 HYPERVISOR_CALLBACK_VECTO
|
||||
|
||||
idtentry debug do_debug has_error_code=0 paranoid=1 shift_ist=DEBUG_STACK
|
||||
idtentry int3 do_int3 has_error_code=0 paranoid=1 shift_ist=DEBUG_STACK
|
||||
-idtentry stack_segment do_stack_segment has_error_code=1 paranoid=1
|
||||
+idtentry stack_segment do_stack_segment has_error_code=1
|
||||
#ifdef CONFIG_XEN
|
||||
idtentry xen_debug do_debug has_error_code=0
|
||||
idtentry xen_int3 do_int3 has_error_code=0
|
||||
--- a/arch/x86/kernel/traps.c
|
||||
+++ b/arch/x86/kernel/traps.c
|
||||
@@ -233,27 +233,11 @@ DO_ERROR(X86_TRAP_UD, SIGILL, "inva
|
||||
DO_ERROR(X86_TRAP_OLD_MF, SIGFPE, "coprocessor segment overrun",coprocessor_segment_overrun)
|
||||
DO_ERROR(X86_TRAP_TS, SIGSEGV, "invalid TSS", invalid_TSS)
|
||||
DO_ERROR(X86_TRAP_NP, SIGBUS, "segment not present", segment_not_present)
|
||||
-#ifdef CONFIG_X86_32
|
||||
DO_ERROR(X86_TRAP_SS, SIGBUS, "stack segment", stack_segment)
|
||||
-#endif
|
||||
DO_ERROR(X86_TRAP_AC, SIGBUS, "alignment check", alignment_check)
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
/* Runs on IST stack */
|
||||
-dotraplinkage void do_stack_segment(struct pt_regs *regs, long error_code)
|
||||
-{
|
||||
- enum ctx_state prev_state;
|
||||
-
|
||||
- prev_state = exception_enter();
|
||||
- if (notify_die(DIE_TRAP, "stack segment", regs, error_code,
|
||||
- X86_TRAP_SS, SIGBUS) != NOTIFY_STOP) {
|
||||
- preempt_conditional_sti(regs);
|
||||
- do_trap(X86_TRAP_SS, SIGBUS, "stack segment", regs, error_code, NULL);
|
||||
- preempt_conditional_cli(regs);
|
||||
- }
|
||||
- exception_exit(prev_state);
|
||||
-}
|
||||
-
|
||||
dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code)
|
||||
{
|
||||
static const char str[] = "double fault";
|
||||
@@ -778,7 +762,7 @@ void __init trap_init(void)
|
||||
set_intr_gate(X86_TRAP_OLD_MF, coprocessor_segment_overrun);
|
||||
set_intr_gate(X86_TRAP_TS, invalid_TSS);
|
||||
set_intr_gate(X86_TRAP_NP, segment_not_present);
|
||||
- set_intr_gate_ist(X86_TRAP_SS, &stack_segment, STACKFAULT_STACK);
|
||||
+ set_intr_gate(X86_TRAP_SS, stack_segment);
|
||||
set_intr_gate(X86_TRAP_GP, general_protection);
|
||||
set_intr_gate(X86_TRAP_SPURIOUS, spurious_interrupt_bug);
|
||||
set_intr_gate(X86_TRAP_MF, coprocessor_error);
|
|
@ -32,7 +32,7 @@ Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
|
|||
a single hierarchy
|
||||
--- a/init/Kconfig
|
||||
+++ b/init/Kconfig
|
||||
@@ -1003,6 +1003,14 @@ config MEMCG
|
||||
@@ -1005,6 +1005,14 @@ config MEMCG
|
||||
disable memory resource controller and you can avoid overheads.
|
||||
(and lose benefits of memory resource controller)
|
||||
|
||||
|
@ -49,8 +49,8 @@ Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
|
|||
depends on MEMCG && SWAP
|
||||
--- a/kernel/cgroup.c
|
||||
+++ b/kernel/cgroup.c
|
||||
@@ -5359,7 +5359,7 @@ static void cgroup_release_agent(struct
|
||||
mutex_unlock(&cgroup_mutex);
|
||||
@@ -5299,7 +5299,7 @@ out_free:
|
||||
kfree(pathbuf);
|
||||
}
|
||||
|
||||
-static int __init cgroup_disable(char *str)
|
||||
|
@ -58,7 +58,7 @@ Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
|
|||
{
|
||||
struct cgroup_subsys *ss;
|
||||
char *token;
|
||||
@@ -5371,17 +5371,29 @@ static int __init cgroup_disable(char *s
|
||||
@@ -5311,17 +5311,29 @@ static int __init cgroup_disable(char *s
|
||||
|
||||
for_each_subsys(ss, i) {
|
||||
if (!strcmp(token, ss->name)) {
|
||||
|
@ -93,7 +93,7 @@ Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
|
|||
printk("cgroup: using legacy files on the default hierarchy\n");
|
||||
--- a/mm/memcontrol.c
|
||||
+++ b/mm/memcontrol.c
|
||||
@@ -6297,6 +6297,9 @@ static void mem_cgroup_bind(struct cgrou
|
||||
@@ -6196,6 +6196,9 @@ static void mem_cgroup_bind(struct cgrou
|
||||
}
|
||||
|
||||
struct cgroup_subsys memory_cgrp_subsys = {
|
||||
|
|
|
@ -19,14 +19,14 @@ Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
|
|||
|
||||
--- a/arch/arm/boot/dts/Makefile
|
||||
+++ b/arch/arm/boot/dts/Makefile
|
||||
@@ -414,6 +414,7 @@ dtb-$(CONFIG_MACH_SUN6I) += \
|
||||
@@ -435,6 +435,7 @@ dtb-$(CONFIG_MACH_SUN6I) += \
|
||||
sun6i-a31-hummingbird.dtb \
|
||||
sun6i-a31-m9.dtb
|
||||
dtb-$(CONFIG_MACH_SUN7I) += \
|
||||
+ sun7i-a20-bananapi.dtb \
|
||||
sun7i-a20-cubieboard2.dtb \
|
||||
sun7i-a20-cubietruck.dtb \
|
||||
sun7i-a20-i12-tvbox.dtb \
|
||||
sun7i-a20-hummingbird.dtb \
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/boot/dts/sun7i-a20-bananapi.dts
|
||||
@@ -0,0 +1,214 @@
|
||||
|
|
|
@ -1,165 +0,0 @@
|
|||
From: FUKAUMI Naoki <naobsd@gmail.com>
|
||||
Date: Wed, 20 Aug 2014 14:25:03 +0900
|
||||
Subject: [PATCH] ARM: sun7i: Add support for Olimex A20-OLinuXino-LIME
|
||||
Origin: https://git.kernel.org/linus/a71b4438af8242f383906071205db95a8b8e7b6d
|
||||
|
||||
This patch adds support for Olimex A20-OLinuXino-LIME board.
|
||||
|
||||
Signed-off-by: FUKAUMI Naoki <naobsd@gmail.com>
|
||||
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
|
||||
---
|
||||
arch/arm/boot/dts/Makefile | 1 +
|
||||
arch/arm/boot/dts/sun7i-a20-olinuxino-lime.dts | 137 +++++++++++++++++++++++++
|
||||
2 files changed, 138 insertions(+)
|
||||
create mode 100644 arch/arm/boot/dts/sun7i-a20-olinuxino-lime.dts
|
||||
|
||||
--- a/arch/arm/boot/dts/Makefile
|
||||
+++ b/arch/arm/boot/dts/Makefile
|
||||
@@ -418,6 +418,7 @@ dtb-$(CONFIG_MACH_SUN7I) += \
|
||||
sun7i-a20-cubieboard2.dtb \
|
||||
sun7i-a20-cubietruck.dtb \
|
||||
sun7i-a20-i12-tvbox.dtb \
|
||||
+ sun7i-a20-olinuxino-lime.dtb \
|
||||
sun7i-a20-olinuxino-micro.dtb \
|
||||
sun7i-a20-pcduino3.dtb
|
||||
dtb-$(CONFIG_MACH_SUN8I) += \
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime.dts
|
||||
@@ -0,0 +1,137 @@
|
||||
+/*
|
||||
+ * This is based on sun4i-a10-olinuxino-lime.dts
|
||||
+ *
|
||||
+ * Copyright 2014 - Hans de Goede <hdegoede@redhat.com>
|
||||
+ * Copyright (c) 2014 FUKAUMI Naoki <naobsd@gmail.com>
|
||||
+ *
|
||||
+ * The code contained herein is licensed under the GNU General Public
|
||||
+ * License. You may obtain a copy of the GNU General Public License
|
||||
+ * Version 2 or later at the following locations:
|
||||
+ *
|
||||
+ * http://www.opensource.org/licenses/gpl-license.html
|
||||
+ * http://www.gnu.org/copyleft/gpl.html
|
||||
+ */
|
||||
+
|
||||
+/dts-v1/;
|
||||
+/include/ "sun7i-a20.dtsi"
|
||||
+/include/ "sunxi-common-regulators.dtsi"
|
||||
+
|
||||
+/ {
|
||||
+ model = "Olimex A20-OLinuXino-LIME";
|
||||
+ compatible = "olimex,a20-olinuxino-lime", "allwinner,sun7i-a20";
|
||||
+
|
||||
+ soc@01c00000 {
|
||||
+ mmc0: mmc@01c0f000 {
|
||||
+ pinctrl-names = "default";
|
||||
+ pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>;
|
||||
+ vmmc-supply = <®_vcc3v3>;
|
||||
+ bus-width = <4>;
|
||||
+ cd-gpios = <&pio 7 1 0>; /* PH1 */
|
||||
+ cd-inverted;
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ usbphy: phy@01c13400 {
|
||||
+ usb1_vbus-supply = <®_usb1_vbus>;
|
||||
+ usb2_vbus-supply = <®_usb2_vbus>;
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ ehci0: usb@01c14000 {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ ohci0: usb@01c14400 {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ ahci: sata@01c18000 {
|
||||
+ target-supply = <®_ahci_5v>;
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ ehci1: usb@01c1c000 {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ ohci1: usb@01c1c400 {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ pinctrl@01c20800 {
|
||||
+ ahci_pwr_pin_olinuxinolime: ahci_pwr_pin@1 {
|
||||
+ allwinner,pins = "PC3";
|
||||
+ allwinner,function = "gpio_out";
|
||||
+ allwinner,drive = <0>;
|
||||
+ allwinner,pull = <0>;
|
||||
+ };
|
||||
+
|
||||
+ led_pins_olinuxinolime: led_pins@0 {
|
||||
+ allwinner,pins = "PH2";
|
||||
+ allwinner,function = "gpio_out";
|
||||
+ allwinner,drive = <1>;
|
||||
+ allwinner,pull = <0>;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ uart0: serial@01c28000 {
|
||||
+ pinctrl-names = "default";
|
||||
+ pinctrl-0 = <&uart0_pins_a>;
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ i2c0: i2c@01c2ac00 {
|
||||
+ pinctrl-names = "default";
|
||||
+ pinctrl-0 = <&i2c0_pins_a>;
|
||||
+ status = "okay";
|
||||
+
|
||||
+ axp209: pmic@34 {
|
||||
+ compatible = "x-powers,axp209";
|
||||
+ reg = <0x34>;
|
||||
+ interrupt-parent = <&nmi_intc>;
|
||||
+ interrupts = <0 8>;
|
||||
+
|
||||
+ interrupt-controller;
|
||||
+ #interrupt-cells = <1>;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ gmac: ethernet@01c50000 {
|
||||
+ pinctrl-names = "default";
|
||||
+ pinctrl-0 = <&gmac_pins_mii_a>;
|
||||
+ phy = <&phy1>;
|
||||
+ phy-mode = "mii";
|
||||
+ status = "okay";
|
||||
+
|
||||
+ phy1: ethernet-phy@1 {
|
||||
+ reg = <1>;
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ leds {
|
||||
+ compatible = "gpio-leds";
|
||||
+ pinctrl-names = "default";
|
||||
+ pinctrl-0 = <&led_pins_olinuxinolime>;
|
||||
+
|
||||
+ green {
|
||||
+ label = "a20-olinuxino-lime:green:usr";
|
||||
+ gpios = <&pio 7 2 0>;
|
||||
+ default-state = "on";
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ reg_ahci_5v: ahci-5v {
|
||||
+ pinctrl-0 = <&ahci_pwr_pin_olinuxinolime>;
|
||||
+ gpio = <&pio 2 3 0>;
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ reg_usb1_vbus: usb1-vbus {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ reg_usb2_vbus: usb2-vbus {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+};
|
|
@ -1,64 +0,0 @@
|
|||
From 23a92cd33a89eaf4c76c0a848ec878035c08cc85 Mon Sep 17 00:00:00 2001
|
||||
From: Iyappan Subramanian <isubramanian@apm.com>
|
||||
Date: Thu, 9 Oct 2014 18:32:07 -0700
|
||||
Subject: [PATCH 03/11] drivers: net: xgene: Add 10GbE ethtool support
|
||||
Origin: https://git.kernel.org/linus/41aace6e088d198f2441f3d0e579657d6815234c
|
||||
|
||||
Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
|
||||
Signed-off-by: Keyur Chudgar <kchudgar@apm.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
.../net/ethernet/apm/xgene/xgene_enet_ethtool.c | 28 +++++++++++++++++-----
|
||||
1 file changed, 22 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
|
||||
index 63f2aa5..c1c997b 100644
|
||||
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
|
||||
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
|
||||
@@ -59,10 +59,22 @@ static int xgene_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
|
||||
struct xgene_enet_pdata *pdata = netdev_priv(ndev);
|
||||
struct phy_device *phydev = pdata->phy_dev;
|
||||
|
||||
- if (phydev == NULL)
|
||||
- return -ENODEV;
|
||||
+ if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) {
|
||||
+ if (phydev == NULL)
|
||||
+ return -ENODEV;
|
||||
|
||||
- return phy_ethtool_gset(phydev, cmd);
|
||||
+ return phy_ethtool_gset(phydev, cmd);
|
||||
+ }
|
||||
+
|
||||
+ cmd->supported = SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE;
|
||||
+ cmd->advertising = cmd->supported;
|
||||
+ ethtool_cmd_speed_set(cmd, SPEED_10000);
|
||||
+ cmd->duplex = DUPLEX_FULL;
|
||||
+ cmd->port = PORT_FIBRE;
|
||||
+ cmd->transceiver = XCVR_EXTERNAL;
|
||||
+ cmd->autoneg = AUTONEG_DISABLE;
|
||||
+
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static int xgene_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
|
||||
@@ -70,10 +82,14 @@ static int xgene_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
|
||||
struct xgene_enet_pdata *pdata = netdev_priv(ndev);
|
||||
struct phy_device *phydev = pdata->phy_dev;
|
||||
|
||||
- if (phydev == NULL)
|
||||
- return -ENODEV;
|
||||
+ if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) {
|
||||
+ if (phydev == NULL)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ return phy_ethtool_sset(phydev, cmd);
|
||||
+ }
|
||||
|
||||
- return phy_ethtool_sset(phydev, cmd);
|
||||
+ return -EINVAL;
|
||||
}
|
||||
|
||||
static void xgene_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
|
||||
--
|
||||
2.1.0
|
||||
|
|
@ -1,662 +0,0 @@
|
|||
From 226068a83722c5cf3da300cce9bab7201088a061 Mon Sep 17 00:00:00 2001
|
||||
From: Iyappan Subramanian <isubramanian@apm.com>
|
||||
Date: Thu, 9 Oct 2014 18:32:06 -0700
|
||||
Subject: [PATCH 02/11] drivers: net: xgene: Add 10GbE support
|
||||
Origin: https://git.kernel.org/linus/0148d38d36b76b190ddddff68f02d2617ada3bcb
|
||||
|
||||
- Added 10GbE support
|
||||
- Removed unused macros/variables
|
||||
- Moved mac_init call to the end of hardware init
|
||||
|
||||
Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
|
||||
Signed-off-by: Keyur Chudgar <kchudgar@apm.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/apm/xgene/Makefile | 3 +-
|
||||
drivers/net/ethernet/apm/xgene/xgene_enet_hw.h | 14 +-
|
||||
drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 58 ++--
|
||||
drivers/net/ethernet/apm/xgene/xgene_enet_main.h | 5 +-
|
||||
drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c | 331 ++++++++++++++++++++++
|
||||
drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h | 57 ++++
|
||||
6 files changed, 438 insertions(+), 30 deletions(-)
|
||||
create mode 100644 drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
|
||||
create mode 100644 drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h
|
||||
|
||||
diff --git a/drivers/net/ethernet/apm/xgene/Makefile b/drivers/net/ethernet/apm/xgene/Makefile
|
||||
index c643e8a..589b352 100644
|
||||
--- a/drivers/net/ethernet/apm/xgene/Makefile
|
||||
+++ b/drivers/net/ethernet/apm/xgene/Makefile
|
||||
@@ -2,5 +2,6 @@
|
||||
# Makefile for APM X-Gene Ethernet Driver.
|
||||
#
|
||||
|
||||
-xgene-enet-objs := xgene_enet_hw.o xgene_enet_main.o xgene_enet_ethtool.o
|
||||
+xgene-enet-objs := xgene_enet_hw.o xgene_enet_xgmac.o \
|
||||
+ xgene_enet_main.o xgene_enet_ethtool.o
|
||||
obj-$(CONFIG_NET_XGENE) += xgene-enet.o
|
||||
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
|
||||
index 084ac68..15ec426 100644
|
||||
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
|
||||
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
|
||||
@@ -42,6 +42,11 @@ static inline u32 xgene_get_bits(u32 val, u32 start, u32 end)
|
||||
return (val & GENMASK(end, start)) >> start;
|
||||
}
|
||||
|
||||
+enum xgene_enet_rm {
|
||||
+ RM0,
|
||||
+ RM3 = 3
|
||||
+};
|
||||
+
|
||||
#define CSR_RING_ID 0x0008
|
||||
#define OVERWRITE BIT(31)
|
||||
#define IS_BUFFER_POOL BIT(20)
|
||||
@@ -52,7 +57,6 @@ static inline u32 xgene_get_bits(u32 val, u32 start, u32 end)
|
||||
#define CSR_RING_WR_BASE 0x0070
|
||||
#define NUM_RING_CONFIG 5
|
||||
#define BUFPOOL_MODE 3
|
||||
-#define RM3 3
|
||||
#define INC_DEC_CMD_ADDR 0x002c
|
||||
#define UDP_HDR_SIZE 2
|
||||
#define BUF_LEN_CODE_2K 0x5000
|
||||
@@ -94,11 +98,9 @@ static inline u32 xgene_get_bits(u32 val, u32 start, u32 end)
|
||||
|
||||
#define BLOCK_ETH_CSR_OFFSET 0x2000
|
||||
#define BLOCK_ETH_RING_IF_OFFSET 0x9000
|
||||
-#define BLOCK_ETH_CLKRST_CSR_OFFSET 0xC000
|
||||
#define BLOCK_ETH_DIAG_CSR_OFFSET 0xD000
|
||||
|
||||
#define BLOCK_ETH_MAC_OFFSET 0x0000
|
||||
-#define BLOCK_ETH_STATS_OFFSET 0x0014
|
||||
#define BLOCK_ETH_MAC_CSR_OFFSET 0x2800
|
||||
|
||||
#define MAC_ADDR_REG_OFFSET 0x00
|
||||
@@ -107,12 +109,6 @@ static inline u32 xgene_get_bits(u32 val, u32 start, u32 end)
|
||||
#define MAC_READ_REG_OFFSET 0x0c
|
||||
#define MAC_COMMAND_DONE_REG_OFFSET 0x10
|
||||
|
||||
-#define STAT_ADDR_REG_OFFSET 0x00
|
||||
-#define STAT_COMMAND_REG_OFFSET 0x04
|
||||
-#define STAT_WRITE_REG_OFFSET 0x08
|
||||
-#define STAT_READ_REG_OFFSET 0x0c
|
||||
-#define STAT_COMMAND_DONE_REG_OFFSET 0x10
|
||||
-
|
||||
#define MII_MGMT_CONFIG_ADDR 0x20
|
||||
#define MII_MGMT_COMMAND_ADDR 0x24
|
||||
#define MII_MGMT_ADDRESS_ADDR 0x28
|
||||
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
|
||||
index c432644..9b85239 100644
|
||||
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
|
||||
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include "xgene_enet_main.h"
|
||||
#include "xgene_enet_hw.h"
|
||||
+#include "xgene_enet_xgmac.h"
|
||||
|
||||
static void xgene_enet_init_bufpool(struct xgene_enet_desc_ring *buf_pool)
|
||||
{
|
||||
@@ -390,7 +391,7 @@ static int xgene_enet_process_ring(struct xgene_enet_desc_ring *ring,
|
||||
}
|
||||
}
|
||||
|
||||
- return budget;
|
||||
+ return count;
|
||||
}
|
||||
|
||||
static int xgene_enet_napi(struct napi_struct *napi, const int budget)
|
||||
@@ -456,8 +457,10 @@ static int xgene_enet_open(struct net_device *ndev)
|
||||
return ret;
|
||||
napi_enable(&pdata->rx_ring->napi);
|
||||
|
||||
- if (pdata->phy_dev)
|
||||
+ if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII)
|
||||
phy_start(pdata->phy_dev);
|
||||
+ else
|
||||
+ schedule_delayed_work(&pdata->link_work, PHY_POLL_LINK_OFF);
|
||||
|
||||
netif_start_queue(ndev);
|
||||
|
||||
@@ -471,8 +474,10 @@ static int xgene_enet_close(struct net_device *ndev)
|
||||
|
||||
netif_stop_queue(ndev);
|
||||
|
||||
- if (pdata->phy_dev)
|
||||
+ if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII)
|
||||
phy_stop(pdata->phy_dev);
|
||||
+ else
|
||||
+ cancel_delayed_work_sync(&pdata->link_work);
|
||||
|
||||
napi_disable(&pdata->rx_ring->napi);
|
||||
xgene_enet_free_irq(ndev);
|
||||
@@ -615,7 +620,6 @@ static struct xgene_enet_desc_ring *xgene_enet_create_desc_ring(
|
||||
|
||||
ring->cmd_base = pdata->ring_cmd_addr + (ring->num << 6);
|
||||
ring->cmd = ring->cmd_base + INC_DEC_CMD_ADDR;
|
||||
- pdata->rm = RM3;
|
||||
ring = xgene_enet_setup_ring(ring);
|
||||
netdev_dbg(ndev, "ring info: num=%d size=%d id=%d slots=%d\n",
|
||||
ring->num, ring->size, ring->id, ring->slots);
|
||||
@@ -805,8 +809,13 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
|
||||
|
||||
pdata->phy_mode = of_get_phy_mode(pdev->dev.of_node);
|
||||
if (pdata->phy_mode < 0) {
|
||||
- dev_err(dev, "Incorrect phy-connection-type in DTS\n");
|
||||
- return -EINVAL;
|
||||
+ dev_err(dev, "Unable to get phy-connection-type\n");
|
||||
+ return pdata->phy_mode;
|
||||
+ }
|
||||
+ if (pdata->phy_mode != PHY_INTERFACE_MODE_RGMII &&
|
||||
+ pdata->phy_mode != PHY_INTERFACE_MODE_XGMII) {
|
||||
+ dev_err(dev, "Incorrect phy-connection-type specified\n");
|
||||
+ return -ENODEV;
|
||||
}
|
||||
|
||||
pdata->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
@@ -821,12 +830,18 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
|
||||
pdata->eth_csr_addr = base_addr + BLOCK_ETH_CSR_OFFSET;
|
||||
pdata->eth_ring_if_addr = base_addr + BLOCK_ETH_RING_IF_OFFSET;
|
||||
pdata->eth_diag_csr_addr = base_addr + BLOCK_ETH_DIAG_CSR_OFFSET;
|
||||
- pdata->mcx_mac_addr = base_addr + BLOCK_ETH_MAC_OFFSET;
|
||||
- pdata->mcx_stats_addr = base_addr + BLOCK_ETH_STATS_OFFSET;
|
||||
- pdata->mcx_mac_csr_addr = base_addr + BLOCK_ETH_MAC_CSR_OFFSET;
|
||||
+ if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) {
|
||||
+ pdata->mcx_mac_addr = base_addr + BLOCK_ETH_MAC_OFFSET;
|
||||
+ pdata->mcx_mac_csr_addr = base_addr + BLOCK_ETH_MAC_CSR_OFFSET;
|
||||
+ pdata->rm = RM3;
|
||||
+ } else {
|
||||
+ pdata->mcx_mac_addr = base_addr + BLOCK_AXG_MAC_OFFSET;
|
||||
+ pdata->mcx_mac_csr_addr = base_addr + BLOCK_AXG_MAC_CSR_OFFSET;
|
||||
+ pdata->rm = RM0;
|
||||
+ }
|
||||
pdata->rx_buff_cnt = NUM_PKT_BUF;
|
||||
|
||||
- return ret;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
|
||||
@@ -836,8 +851,7 @@ static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
|
||||
u16 dst_ring_num;
|
||||
int ret;
|
||||
|
||||
- pdata->mac_ops->tx_disable(pdata);
|
||||
- pdata->mac_ops->rx_disable(pdata);
|
||||
+ pdata->port_ops->reset(pdata);
|
||||
|
||||
ret = xgene_enet_create_desc_rings(ndev);
|
||||
if (ret) {
|
||||
@@ -856,14 +870,23 @@ static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
|
||||
|
||||
dst_ring_num = xgene_enet_dst_ring_num(pdata->rx_ring);
|
||||
pdata->port_ops->cle_bypass(pdata, dst_ring_num, buf_pool->id);
|
||||
+ pdata->mac_ops->init(pdata);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void xgene_enet_setup_ops(struct xgene_enet_pdata *pdata)
|
||||
{
|
||||
- pdata->mac_ops = &xgene_gmac_ops;
|
||||
- pdata->port_ops = &xgene_gport_ops;
|
||||
+ switch (pdata->phy_mode) {
|
||||
+ case PHY_INTERFACE_MODE_RGMII:
|
||||
+ pdata->mac_ops = &xgene_gmac_ops;
|
||||
+ pdata->port_ops = &xgene_gport_ops;
|
||||
+ break;
|
||||
+ default:
|
||||
+ pdata->mac_ops = &xgene_xgmac_ops;
|
||||
+ pdata->port_ops = &xgene_xgport_ops;
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
|
||||
static int xgene_enet_probe(struct platform_device *pdev)
|
||||
@@ -895,8 +918,6 @@ static int xgene_enet_probe(struct platform_device *pdev)
|
||||
goto err;
|
||||
|
||||
xgene_enet_setup_ops(pdata);
|
||||
- pdata->port_ops->reset(pdata);
|
||||
- pdata->mac_ops->init(pdata);
|
||||
|
||||
ret = register_netdev(ndev);
|
||||
if (ret) {
|
||||
@@ -916,7 +937,10 @@ static int xgene_enet_probe(struct platform_device *pdev)
|
||||
|
||||
napi = &pdata->rx_ring->napi;
|
||||
netif_napi_add(ndev, napi, xgene_enet_napi, NAPI_POLL_WEIGHT);
|
||||
- ret = xgene_enet_mdio_config(pdata);
|
||||
+ if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII)
|
||||
+ ret = xgene_enet_mdio_config(pdata);
|
||||
+ else
|
||||
+ INIT_DELAYED_WORK(&pdata->link_work, xgene_enet_link_state);
|
||||
|
||||
return ret;
|
||||
err:
|
||||
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
|
||||
index ac180f9..86cf68b 100644
|
||||
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
|
||||
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
|
||||
@@ -105,18 +105,17 @@ struct xgene_enet_pdata {
|
||||
void __iomem *eth_ring_if_addr;
|
||||
void __iomem *eth_diag_csr_addr;
|
||||
void __iomem *mcx_mac_addr;
|
||||
- void __iomem *mcx_stats_addr;
|
||||
void __iomem *mcx_mac_csr_addr;
|
||||
void __iomem *base_addr;
|
||||
void __iomem *ring_csr_addr;
|
||||
void __iomem *ring_cmd_addr;
|
||||
u32 phy_addr;
|
||||
int phy_mode;
|
||||
- u32 speed;
|
||||
- u16 rm;
|
||||
+ enum xgene_enet_rm rm;
|
||||
struct rtnl_link_stats64 stats;
|
||||
struct xgene_mac_ops *mac_ops;
|
||||
struct xgene_port_ops *port_ops;
|
||||
+ struct delayed_work link_work;
|
||||
};
|
||||
|
||||
/* Set the specified value into a bit-field defined by its starting position
|
||||
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
|
||||
new file mode 100644
|
||||
index 0000000..cd64b9f
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
|
||||
@@ -0,0 +1,331 @@
|
||||
+/* Applied Micro X-Gene SoC Ethernet Driver
|
||||
+ *
|
||||
+ * Copyright (c) 2014, Applied Micro Circuits Corporation
|
||||
+ * Authors: Iyappan Subramanian <isubramanian@apm.com>
|
||||
+ * Keyur Chudgar <kchudgar@apm.com>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify it
|
||||
+ * under the terms of the GNU General Public License as published by the
|
||||
+ * Free Software Foundation; either version 2 of the License, or (at your
|
||||
+ * option) any later version.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License
|
||||
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
+ */
|
||||
+
|
||||
+#include "xgene_enet_main.h"
|
||||
+#include "xgene_enet_hw.h"
|
||||
+#include "xgene_enet_xgmac.h"
|
||||
+
|
||||
+static void xgene_enet_wr_csr(struct xgene_enet_pdata *pdata,
|
||||
+ u32 offset, u32 val)
|
||||
+{
|
||||
+ void __iomem *addr = pdata->eth_csr_addr + offset;
|
||||
+
|
||||
+ iowrite32(val, addr);
|
||||
+}
|
||||
+
|
||||
+static void xgene_enet_wr_ring_if(struct xgene_enet_pdata *pdata,
|
||||
+ u32 offset, u32 val)
|
||||
+{
|
||||
+ void __iomem *addr = pdata->eth_ring_if_addr + offset;
|
||||
+
|
||||
+ iowrite32(val, addr);
|
||||
+}
|
||||
+
|
||||
+static void xgene_enet_wr_diag_csr(struct xgene_enet_pdata *pdata,
|
||||
+ u32 offset, u32 val)
|
||||
+{
|
||||
+ void __iomem *addr = pdata->eth_diag_csr_addr + offset;
|
||||
+
|
||||
+ iowrite32(val, addr);
|
||||
+}
|
||||
+
|
||||
+static bool xgene_enet_wr_indirect(void __iomem *addr, void __iomem *wr,
|
||||
+ void __iomem *cmd, void __iomem *cmd_done,
|
||||
+ u32 wr_addr, u32 wr_data)
|
||||
+{
|
||||
+ u32 done;
|
||||
+ u8 wait = 10;
|
||||
+
|
||||
+ iowrite32(wr_addr, addr);
|
||||
+ iowrite32(wr_data, wr);
|
||||
+ iowrite32(XGENE_ENET_WR_CMD, cmd);
|
||||
+
|
||||
+ /* wait for write command to complete */
|
||||
+ while (!(done = ioread32(cmd_done)) && wait--)
|
||||
+ udelay(1);
|
||||
+
|
||||
+ if (!done)
|
||||
+ return false;
|
||||
+
|
||||
+ iowrite32(0, cmd);
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+static void xgene_enet_wr_mac(struct xgene_enet_pdata *pdata,
|
||||
+ u32 wr_addr, u32 wr_data)
|
||||
+{
|
||||
+ void __iomem *addr, *wr, *cmd, *cmd_done;
|
||||
+
|
||||
+ addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET;
|
||||
+ wr = pdata->mcx_mac_addr + MAC_WRITE_REG_OFFSET;
|
||||
+ cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET;
|
||||
+ cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET;
|
||||
+
|
||||
+ if (!xgene_enet_wr_indirect(addr, wr, cmd, cmd_done, wr_addr, wr_data))
|
||||
+ netdev_err(pdata->ndev, "MCX mac write failed, addr: %04x\n",
|
||||
+ wr_addr);
|
||||
+}
|
||||
+
|
||||
+static void xgene_enet_rd_csr(struct xgene_enet_pdata *pdata,
|
||||
+ u32 offset, u32 *val)
|
||||
+{
|
||||
+ void __iomem *addr = pdata->eth_csr_addr + offset;
|
||||
+
|
||||
+ *val = ioread32(addr);
|
||||
+}
|
||||
+
|
||||
+static void xgene_enet_rd_diag_csr(struct xgene_enet_pdata *pdata,
|
||||
+ u32 offset, u32 *val)
|
||||
+{
|
||||
+ void __iomem *addr = pdata->eth_diag_csr_addr + offset;
|
||||
+
|
||||
+ *val = ioread32(addr);
|
||||
+}
|
||||
+
|
||||
+static bool xgene_enet_rd_indirect(void __iomem *addr, void __iomem *rd,
|
||||
+ void __iomem *cmd, void __iomem *cmd_done,
|
||||
+ u32 rd_addr, u32 *rd_data)
|
||||
+{
|
||||
+ u32 done;
|
||||
+ u8 wait = 10;
|
||||
+
|
||||
+ iowrite32(rd_addr, addr);
|
||||
+ iowrite32(XGENE_ENET_RD_CMD, cmd);
|
||||
+
|
||||
+ /* wait for read command to complete */
|
||||
+ while (!(done = ioread32(cmd_done)) && wait--)
|
||||
+ udelay(1);
|
||||
+
|
||||
+ if (!done)
|
||||
+ return false;
|
||||
+
|
||||
+ *rd_data = ioread32(rd);
|
||||
+ iowrite32(0, cmd);
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+static void xgene_enet_rd_mac(struct xgene_enet_pdata *pdata,
|
||||
+ u32 rd_addr, u32 *rd_data)
|
||||
+{
|
||||
+ void __iomem *addr, *rd, *cmd, *cmd_done;
|
||||
+
|
||||
+ addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET;
|
||||
+ rd = pdata->mcx_mac_addr + MAC_READ_REG_OFFSET;
|
||||
+ cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET;
|
||||
+ cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET;
|
||||
+
|
||||
+ if (!xgene_enet_rd_indirect(addr, rd, cmd, cmd_done, rd_addr, rd_data))
|
||||
+ netdev_err(pdata->ndev, "MCX mac read failed, addr: %04x\n",
|
||||
+ rd_addr);
|
||||
+}
|
||||
+
|
||||
+static int xgene_enet_ecc_init(struct xgene_enet_pdata *pdata)
|
||||
+{
|
||||
+ struct net_device *ndev = pdata->ndev;
|
||||
+ u32 data;
|
||||
+ u8 wait = 10;
|
||||
+
|
||||
+ xgene_enet_wr_diag_csr(pdata, ENET_CFG_MEM_RAM_SHUTDOWN_ADDR, 0x0);
|
||||
+ do {
|
||||
+ usleep_range(100, 110);
|
||||
+ xgene_enet_rd_diag_csr(pdata, ENET_BLOCK_MEM_RDY_ADDR, &data);
|
||||
+ } while ((data != 0xffffffff) && wait--);
|
||||
+
|
||||
+ if (data != 0xffffffff) {
|
||||
+ netdev_err(ndev, "Failed to release memory from shutdown\n");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *pdata)
|
||||
+{
|
||||
+ xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIWQASSOC_ADDR, 0);
|
||||
+ xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIFPQASSOC_ADDR, 0);
|
||||
+ xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIQMLITEWQASSOC_ADDR, 0);
|
||||
+ xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIQMLITEFPQASSOC_ADDR, 0);
|
||||
+}
|
||||
+
|
||||
+static void xgene_xgmac_reset(struct xgene_enet_pdata *pdata)
|
||||
+{
|
||||
+ xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_0, HSTMACRST);
|
||||
+ xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_0, 0);
|
||||
+}
|
||||
+
|
||||
+static void xgene_xgmac_set_mac_addr(struct xgene_enet_pdata *pdata)
|
||||
+{
|
||||
+ u32 addr0, addr1;
|
||||
+ u8 *dev_addr = pdata->ndev->dev_addr;
|
||||
+
|
||||
+ addr0 = (dev_addr[3] << 24) | (dev_addr[2] << 16) |
|
||||
+ (dev_addr[1] << 8) | dev_addr[0];
|
||||
+ addr1 = (dev_addr[5] << 24) | (dev_addr[4] << 16);
|
||||
+
|
||||
+ xgene_enet_wr_mac(pdata, HSTMACADR_LSW_ADDR, addr0);
|
||||
+ xgene_enet_wr_mac(pdata, HSTMACADR_MSW_ADDR, addr1);
|
||||
+}
|
||||
+
|
||||
+static u32 xgene_enet_link_status(struct xgene_enet_pdata *pdata)
|
||||
+{
|
||||
+ u32 data;
|
||||
+
|
||||
+ xgene_enet_rd_csr(pdata, XG_LINK_STATUS_ADDR, &data);
|
||||
+
|
||||
+ return data;
|
||||
+}
|
||||
+
|
||||
+static void xgene_xgmac_init(struct xgene_enet_pdata *pdata)
|
||||
+{
|
||||
+ u32 data;
|
||||
+
|
||||
+ xgene_xgmac_reset(pdata);
|
||||
+
|
||||
+ xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data);
|
||||
+ data |= HSTPPEN;
|
||||
+ data &= ~HSTLENCHK;
|
||||
+ xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data);
|
||||
+
|
||||
+ xgene_enet_wr_mac(pdata, HSTMAXFRAME_LENGTH_ADDR, 0x06000600);
|
||||
+ xgene_xgmac_set_mac_addr(pdata);
|
||||
+
|
||||
+ xgene_enet_rd_csr(pdata, XG_RSIF_CONFIG_REG_ADDR, &data);
|
||||
+ data |= CFG_RSIF_FPBUFF_TIMEOUT_EN;
|
||||
+ xgene_enet_wr_csr(pdata, XG_RSIF_CONFIG_REG_ADDR, data);
|
||||
+
|
||||
+ xgene_enet_wr_csr(pdata, XG_CFG_BYPASS_ADDR, RESUME_TX);
|
||||
+ xgene_enet_wr_csr(pdata, XGENET_RX_DV_GATE_REG_0_ADDR, 0);
|
||||
+ xgene_enet_rd_csr(pdata, XG_ENET_SPARE_CFG_REG_ADDR, &data);
|
||||
+ data |= BIT(12);
|
||||
+ xgene_enet_wr_csr(pdata, XG_ENET_SPARE_CFG_REG_ADDR, data);
|
||||
+ xgene_enet_wr_csr(pdata, XG_ENET_SPARE_CFG_REG_1_ADDR, 0x82);
|
||||
+}
|
||||
+
|
||||
+static void xgene_xgmac_rx_enable(struct xgene_enet_pdata *pdata)
|
||||
+{
|
||||
+ u32 data;
|
||||
+
|
||||
+ xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data);
|
||||
+ xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data | HSTRFEN);
|
||||
+}
|
||||
+
|
||||
+static void xgene_xgmac_tx_enable(struct xgene_enet_pdata *pdata)
|
||||
+{
|
||||
+ u32 data;
|
||||
+
|
||||
+ xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data);
|
||||
+ xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data | HSTTFEN);
|
||||
+}
|
||||
+
|
||||
+static void xgene_xgmac_rx_disable(struct xgene_enet_pdata *pdata)
|
||||
+{
|
||||
+ u32 data;
|
||||
+
|
||||
+ xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data);
|
||||
+ xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data & ~HSTRFEN);
|
||||
+}
|
||||
+
|
||||
+static void xgene_xgmac_tx_disable(struct xgene_enet_pdata *pdata)
|
||||
+{
|
||||
+ u32 data;
|
||||
+
|
||||
+ xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data);
|
||||
+ xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data & ~HSTTFEN);
|
||||
+}
|
||||
+
|
||||
+static void xgene_enet_reset(struct xgene_enet_pdata *pdata)
|
||||
+{
|
||||
+ clk_prepare_enable(pdata->clk);
|
||||
+ clk_disable_unprepare(pdata->clk);
|
||||
+ clk_prepare_enable(pdata->clk);
|
||||
+
|
||||
+ xgene_enet_ecc_init(pdata);
|
||||
+ xgene_enet_config_ring_if_assoc(pdata);
|
||||
+}
|
||||
+
|
||||
+static void xgene_enet_xgcle_bypass(struct xgene_enet_pdata *pdata,
|
||||
+ u32 dst_ring_num, u16 bufpool_id)
|
||||
+{
|
||||
+ u32 cb, fpsel;
|
||||
+
|
||||
+ xgene_enet_rd_csr(pdata, XCLE_BYPASS_REG0_ADDR, &cb);
|
||||
+ cb |= CFG_CLE_BYPASS_EN0;
|
||||
+ CFG_CLE_IP_PROTOCOL0_SET(&cb, 3);
|
||||
+ xgene_enet_wr_csr(pdata, XCLE_BYPASS_REG0_ADDR, cb);
|
||||
+
|
||||
+ fpsel = xgene_enet_ring_bufnum(bufpool_id) - 0x20;
|
||||
+ xgene_enet_rd_csr(pdata, XCLE_BYPASS_REG1_ADDR, &cb);
|
||||
+ CFG_CLE_DSTQID0_SET(&cb, dst_ring_num);
|
||||
+ CFG_CLE_FPSEL0_SET(&cb, fpsel);
|
||||
+ xgene_enet_wr_csr(pdata, XCLE_BYPASS_REG1_ADDR, cb);
|
||||
+}
|
||||
+
|
||||
+static void xgene_enet_shutdown(struct xgene_enet_pdata *pdata)
|
||||
+{
|
||||
+ clk_disable_unprepare(pdata->clk);
|
||||
+}
|
||||
+
|
||||
+void xgene_enet_link_state(struct work_struct *work)
|
||||
+{
|
||||
+ struct xgene_enet_pdata *pdata = container_of(to_delayed_work(work),
|
||||
+ struct xgene_enet_pdata, link_work);
|
||||
+ struct net_device *ndev = pdata->ndev;
|
||||
+ u32 link_status, poll_interval;
|
||||
+
|
||||
+ link_status = xgene_enet_link_status(pdata);
|
||||
+ if (link_status) {
|
||||
+ if (!netif_carrier_ok(ndev)) {
|
||||
+ netif_carrier_on(ndev);
|
||||
+ xgene_xgmac_init(pdata);
|
||||
+ xgene_xgmac_rx_enable(pdata);
|
||||
+ xgene_xgmac_tx_enable(pdata);
|
||||
+ netdev_info(ndev, "Link is Up - 10Gbps\n");
|
||||
+ }
|
||||
+ poll_interval = PHY_POLL_LINK_ON;
|
||||
+ } else {
|
||||
+ if (netif_carrier_ok(ndev)) {
|
||||
+ xgene_xgmac_rx_disable(pdata);
|
||||
+ xgene_xgmac_tx_disable(pdata);
|
||||
+ netif_carrier_off(ndev);
|
||||
+ netdev_info(ndev, "Link is Down\n");
|
||||
+ }
|
||||
+ poll_interval = PHY_POLL_LINK_OFF;
|
||||
+ }
|
||||
+
|
||||
+ schedule_delayed_work(&pdata->link_work, poll_interval);
|
||||
+}
|
||||
+
|
||||
+struct xgene_mac_ops xgene_xgmac_ops = {
|
||||
+ .init = xgene_xgmac_init,
|
||||
+ .reset = xgene_xgmac_reset,
|
||||
+ .rx_enable = xgene_xgmac_rx_enable,
|
||||
+ .tx_enable = xgene_xgmac_tx_enable,
|
||||
+ .rx_disable = xgene_xgmac_rx_disable,
|
||||
+ .tx_disable = xgene_xgmac_tx_disable,
|
||||
+ .set_mac_addr = xgene_xgmac_set_mac_addr,
|
||||
+};
|
||||
+
|
||||
+struct xgene_port_ops xgene_xgport_ops = {
|
||||
+ .reset = xgene_enet_reset,
|
||||
+ .cle_bypass = xgene_enet_xgcle_bypass,
|
||||
+ .shutdown = xgene_enet_shutdown,
|
||||
+};
|
||||
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h
|
||||
new file mode 100644
|
||||
index 0000000..d2d59e7
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h
|
||||
@@ -0,0 +1,57 @@
|
||||
+/* Applied Micro X-Gene SoC Ethernet Driver
|
||||
+ *
|
||||
+ * Copyright (c) 2014, Applied Micro Circuits Corporation
|
||||
+ * Authors: Iyappan Subramanian <isubramanian@apm.com>
|
||||
+ * Keyur Chudgar <kchudgar@apm.com>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify it
|
||||
+ * under the terms of the GNU General Public License as published by the
|
||||
+ * Free Software Foundation; either version 2 of the License, or (at your
|
||||
+ * option) any later version.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License
|
||||
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
+ */
|
||||
+
|
||||
+#ifndef __XGENE_ENET_XGMAC_H__
|
||||
+#define __XGENE_ENET_XGMAC_H__
|
||||
+
|
||||
+#define BLOCK_AXG_MAC_OFFSET 0x0800
|
||||
+#define BLOCK_AXG_MAC_CSR_OFFSET 0x2000
|
||||
+
|
||||
+#define AXGMAC_CONFIG_0 0x0000
|
||||
+#define AXGMAC_CONFIG_1 0x0004
|
||||
+#define HSTMACRST BIT(31)
|
||||
+#define HSTTCTLEN BIT(31)
|
||||
+#define HSTTFEN BIT(30)
|
||||
+#define HSTRCTLEN BIT(29)
|
||||
+#define HSTRFEN BIT(28)
|
||||
+#define HSTPPEN BIT(7)
|
||||
+#define HSTDRPLT64 BIT(5)
|
||||
+#define HSTLENCHK BIT(3)
|
||||
+#define HSTMACADR_LSW_ADDR 0x0010
|
||||
+#define HSTMACADR_MSW_ADDR 0x0014
|
||||
+#define HSTMAXFRAME_LENGTH_ADDR 0x0020
|
||||
+
|
||||
+#define XG_RSIF_CONFIG_REG_ADDR 0x00a0
|
||||
+#define XCLE_BYPASS_REG0_ADDR 0x0160
|
||||
+#define XCLE_BYPASS_REG1_ADDR 0x0164
|
||||
+#define XG_CFG_BYPASS_ADDR 0x0204
|
||||
+#define XG_LINK_STATUS_ADDR 0x0228
|
||||
+#define XG_ENET_SPARE_CFG_REG_ADDR 0x040c
|
||||
+#define XG_ENET_SPARE_CFG_REG_1_ADDR 0x0410
|
||||
+#define XGENET_RX_DV_GATE_REG_0_ADDR 0x0804
|
||||
+
|
||||
+#define PHY_POLL_LINK_ON (10 * HZ)
|
||||
+#define PHY_POLL_LINK_OFF (PHY_POLL_LINK_ON / 5)
|
||||
+
|
||||
+void xgene_enet_link_state(struct work_struct *work);
|
||||
+extern struct xgene_mac_ops xgene_xgmac_ops;
|
||||
+extern struct xgene_port_ops xgene_xgport_ops;
|
||||
+
|
||||
+#endif /* __XGENE_ENET_XGMAC_H__ */
|
||||
--
|
||||
2.1.0
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
From c566829d7ea3c25a85a372901b0fce080017034b Mon Sep 17 00:00:00 2001
|
||||
From: Iyappan Subramanian <isubramanian@apm.com>
|
||||
Date: Mon, 13 Oct 2014 17:05:35 -0700
|
||||
Subject: [PATCH 06/11] drivers: net: xgene: Add SGMII based 1GbE ethtool
|
||||
support
|
||||
Origin: https://git.kernel.org/linus/5e6a024bebea5bad6b787cf2c0ee28116b4147f0
|
||||
|
||||
Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
|
||||
Signed-off-by: Keyur Chudgar <kchudgar@apm.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
.../net/ethernet/apm/xgene/xgene_enet_ethtool.c | 25 +++++++++++++++-------
|
||||
1 file changed, 17 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
|
||||
index c1c997b..416d6eb 100644
|
||||
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
|
||||
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
|
||||
@@ -64,16 +64,25 @@ static int xgene_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
|
||||
return -ENODEV;
|
||||
|
||||
return phy_ethtool_gset(phydev, cmd);
|
||||
+ } else if (pdata->phy_mode == PHY_INTERFACE_MODE_SGMII) {
|
||||
+ cmd->supported = SUPPORTED_1000baseT_Full |
|
||||
+ SUPPORTED_Autoneg | SUPPORTED_MII;
|
||||
+ cmd->advertising = cmd->supported;
|
||||
+ ethtool_cmd_speed_set(cmd, SPEED_1000);
|
||||
+ cmd->duplex = DUPLEX_FULL;
|
||||
+ cmd->port = PORT_MII;
|
||||
+ cmd->transceiver = XCVR_INTERNAL;
|
||||
+ cmd->autoneg = AUTONEG_ENABLE;
|
||||
+ } else {
|
||||
+ cmd->supported = SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE;
|
||||
+ cmd->advertising = cmd->supported;
|
||||
+ ethtool_cmd_speed_set(cmd, SPEED_10000);
|
||||
+ cmd->duplex = DUPLEX_FULL;
|
||||
+ cmd->port = PORT_FIBRE;
|
||||
+ cmd->transceiver = XCVR_INTERNAL;
|
||||
+ cmd->autoneg = AUTONEG_DISABLE;
|
||||
}
|
||||
|
||||
- cmd->supported = SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE;
|
||||
- cmd->advertising = cmd->supported;
|
||||
- ethtool_cmd_speed_set(cmd, SPEED_10000);
|
||||
- cmd->duplex = DUPLEX_FULL;
|
||||
- cmd->port = PORT_FIBRE;
|
||||
- cmd->transceiver = XCVR_EXTERNAL;
|
||||
- cmd->autoneg = AUTONEG_DISABLE;
|
||||
-
|
||||
return 0;
|
||||
}
|
||||
|
||||
--
|
||||
2.1.0
|
||||
|
|
@ -1,583 +0,0 @@
|
|||
From 30bf224d12eb84225e3c0dcdd520cf9a23276f11 Mon Sep 17 00:00:00 2001
|
||||
From: Iyappan Subramanian <isubramanian@apm.com>
|
||||
Date: Mon, 13 Oct 2014 17:05:34 -0700
|
||||
Subject: [PATCH 05/11] drivers: net: xgene: Add SGMII based 1GbE support
|
||||
Origin: https://git.kernel.org/linus/32f784b50e14c653ad0f010fbd5921a5f8caf846
|
||||
|
||||
Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
|
||||
Signed-off-by: Keyur Chudgar <kchudgar@apm.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/apm/xgene/Makefile | 2 +-
|
||||
drivers/net/ethernet/apm/xgene/xgene_enet_hw.h | 3 +
|
||||
drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 10 +-
|
||||
drivers/net/ethernet/apm/xgene/xgene_enet_main.h | 10 +
|
||||
drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c | 389 ++++++++++++++++++++++
|
||||
drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h | 41 +++
|
||||
drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h | 3 -
|
||||
7 files changed, 453 insertions(+), 5 deletions(-)
|
||||
create mode 100644 drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
|
||||
create mode 100644 drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h
|
||||
|
||||
diff --git a/drivers/net/ethernet/apm/xgene/Makefile b/drivers/net/ethernet/apm/xgene/Makefile
|
||||
index 589b352..68be5655 100644
|
||||
--- a/drivers/net/ethernet/apm/xgene/Makefile
|
||||
+++ b/drivers/net/ethernet/apm/xgene/Makefile
|
||||
@@ -2,6 +2,6 @@
|
||||
# Makefile for APM X-Gene Ethernet Driver.
|
||||
#
|
||||
|
||||
-xgene-enet-objs := xgene_enet_hw.o xgene_enet_xgmac.o \
|
||||
+xgene-enet-objs := xgene_enet_hw.o xgene_enet_sgmac.o xgene_enet_xgmac.o \
|
||||
xgene_enet_main.o xgene_enet_ethtool.o
|
||||
obj-$(CONFIG_NET_XGENE) += xgene-enet.o
|
||||
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
|
||||
index 2efc4d9..3855858 100644
|
||||
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
|
||||
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
|
||||
@@ -44,6 +44,7 @@ static inline u32 xgene_get_bits(u32 val, u32 start, u32 end)
|
||||
|
||||
enum xgene_enet_rm {
|
||||
RM0,
|
||||
+ RM1,
|
||||
RM3 = 3
|
||||
};
|
||||
|
||||
@@ -143,6 +144,8 @@ enum xgene_enet_rm {
|
||||
#define CFG_CLE_FPSEL0_SET(dst, val) xgene_set_bits(dst, val, 16, 4)
|
||||
#define CFG_MACMODE_SET(dst, val) xgene_set_bits(dst, val, 18, 2)
|
||||
#define CFG_WAITASYNCRD_SET(dst, val) xgene_set_bits(dst, val, 0, 16)
|
||||
+#define CFG_CLE_DSTQID0(val) (val & GENMASK(11, 0))
|
||||
+#define CFG_CLE_FPSEL0(val) ((val << 16) & GENMASK(19, 16))
|
||||
#define ICM_CONFIG0_REG_0_ADDR 0x0400
|
||||
#define ICM_CONFIG2_REG_0_ADDR 0x0410
|
||||
#define RX_DV_GATE_REG_0_ADDR 0x05fc
|
||||
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
|
||||
index 9e251ec..3c208cc 100644
|
||||
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
|
||||
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include "xgene_enet_main.h"
|
||||
#include "xgene_enet_hw.h"
|
||||
+#include "xgene_enet_sgmac.h"
|
||||
#include "xgene_enet_xgmac.h"
|
||||
|
||||
static void xgene_enet_init_bufpool(struct xgene_enet_desc_ring *buf_pool)
|
||||
@@ -813,6 +814,7 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
|
||||
return pdata->phy_mode;
|
||||
}
|
||||
if (pdata->phy_mode != PHY_INTERFACE_MODE_RGMII &&
|
||||
+ pdata->phy_mode != PHY_INTERFACE_MODE_SGMII &&
|
||||
pdata->phy_mode != PHY_INTERFACE_MODE_XGMII) {
|
||||
dev_err(dev, "Incorrect phy-connection-type specified\n");
|
||||
return -ENODEV;
|
||||
@@ -830,7 +832,8 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
|
||||
pdata->eth_csr_addr = base_addr + BLOCK_ETH_CSR_OFFSET;
|
||||
pdata->eth_ring_if_addr = base_addr + BLOCK_ETH_RING_IF_OFFSET;
|
||||
pdata->eth_diag_csr_addr = base_addr + BLOCK_ETH_DIAG_CSR_OFFSET;
|
||||
- if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) {
|
||||
+ if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII ||
|
||||
+ pdata->phy_mode == PHY_INTERFACE_MODE_SGMII) {
|
||||
pdata->mcx_mac_addr = base_addr + BLOCK_ETH_MAC_OFFSET;
|
||||
pdata->mcx_mac_csr_addr = base_addr + BLOCK_ETH_MAC_CSR_OFFSET;
|
||||
} else {
|
||||
@@ -881,6 +884,11 @@ static void xgene_enet_setup_ops(struct xgene_enet_pdata *pdata)
|
||||
pdata->port_ops = &xgene_gport_ops;
|
||||
pdata->rm = RM3;
|
||||
break;
|
||||
+ case PHY_INTERFACE_MODE_SGMII:
|
||||
+ pdata->mac_ops = &xgene_sgmac_ops;
|
||||
+ pdata->port_ops = &xgene_sgport_ops;
|
||||
+ pdata->rm = RM1;
|
||||
+ break;
|
||||
default:
|
||||
pdata->mac_ops = &xgene_xgmac_ops;
|
||||
pdata->port_ops = &xgene_xgport_ops;
|
||||
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
|
||||
index 10b03a1..874e5a0 100644
|
||||
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
|
||||
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
|
||||
@@ -39,6 +39,9 @@
|
||||
#define NUM_PKT_BUF 64
|
||||
#define NUM_BUFPOOL 32
|
||||
|
||||
+#define PHY_POLL_LINK_ON (10 * HZ)
|
||||
+#define PHY_POLL_LINK_OFF (PHY_POLL_LINK_ON / 5)
|
||||
+
|
||||
/* software context of a descriptor ring */
|
||||
struct xgene_enet_desc_ring {
|
||||
struct net_device *ndev;
|
||||
@@ -118,6 +121,13 @@ struct xgene_enet_pdata {
|
||||
struct delayed_work link_work;
|
||||
};
|
||||
|
||||
+struct xgene_indirect_ctl {
|
||||
+ void __iomem *addr;
|
||||
+ void __iomem *ctl;
|
||||
+ void __iomem *cmd;
|
||||
+ void __iomem *cmd_done;
|
||||
+};
|
||||
+
|
||||
/* Set the specified value into a bit-field defined by its starting position
|
||||
* and length within a single u64.
|
||||
*/
|
||||
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
|
||||
new file mode 100644
|
||||
index 0000000..e6d24c2
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
|
||||
@@ -0,0 +1,389 @@
|
||||
+/* Applied Micro X-Gene SoC Ethernet Driver
|
||||
+ *
|
||||
+ * Copyright (c) 2014, Applied Micro Circuits Corporation
|
||||
+ * Authors: Iyappan Subramanian <isubramanian@apm.com>
|
||||
+ * Keyur Chudgar <kchudgar@apm.com>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify it
|
||||
+ * under the terms of the GNU General Public License as published by the
|
||||
+ * Free Software Foundation; either version 2 of the License, or (at your
|
||||
+ * option) any later version.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License
|
||||
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
+ */
|
||||
+
|
||||
+#include "xgene_enet_main.h"
|
||||
+#include "xgene_enet_hw.h"
|
||||
+#include "xgene_enet_sgmac.h"
|
||||
+
|
||||
+static void xgene_enet_wr_csr(struct xgene_enet_pdata *p, u32 offset, u32 val)
|
||||
+{
|
||||
+ iowrite32(val, p->eth_csr_addr + offset);
|
||||
+}
|
||||
+
|
||||
+static void xgene_enet_wr_ring_if(struct xgene_enet_pdata *p,
|
||||
+ u32 offset, u32 val)
|
||||
+{
|
||||
+ iowrite32(val, p->eth_ring_if_addr + offset);
|
||||
+}
|
||||
+
|
||||
+static void xgene_enet_wr_diag_csr(struct xgene_enet_pdata *p,
|
||||
+ u32 offset, u32 val)
|
||||
+{
|
||||
+ iowrite32(val, p->eth_diag_csr_addr + offset);
|
||||
+}
|
||||
+
|
||||
+static bool xgene_enet_wr_indirect(struct xgene_indirect_ctl *ctl,
|
||||
+ u32 wr_addr, u32 wr_data)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ iowrite32(wr_addr, ctl->addr);
|
||||
+ iowrite32(wr_data, ctl->ctl);
|
||||
+ iowrite32(XGENE_ENET_WR_CMD, ctl->cmd);
|
||||
+
|
||||
+ /* wait for write command to complete */
|
||||
+ for (i = 0; i < 10; i++) {
|
||||
+ if (ioread32(ctl->cmd_done)) {
|
||||
+ iowrite32(0, ctl->cmd);
|
||||
+ return true;
|
||||
+ }
|
||||
+ udelay(1);
|
||||
+ }
|
||||
+
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+static void xgene_enet_wr_mac(struct xgene_enet_pdata *p,
|
||||
+ u32 wr_addr, u32 wr_data)
|
||||
+{
|
||||
+ struct xgene_indirect_ctl ctl = {
|
||||
+ .addr = p->mcx_mac_addr + MAC_ADDR_REG_OFFSET,
|
||||
+ .ctl = p->mcx_mac_addr + MAC_WRITE_REG_OFFSET,
|
||||
+ .cmd = p->mcx_mac_addr + MAC_COMMAND_REG_OFFSET,
|
||||
+ .cmd_done = p->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET
|
||||
+ };
|
||||
+
|
||||
+ if (!xgene_enet_wr_indirect(&ctl, wr_addr, wr_data))
|
||||
+ netdev_err(p->ndev, "mac write failed, addr: %04x\n", wr_addr);
|
||||
+}
|
||||
+
|
||||
+static u32 xgene_enet_rd_csr(struct xgene_enet_pdata *p, u32 offset)
|
||||
+{
|
||||
+ return ioread32(p->eth_csr_addr + offset);
|
||||
+}
|
||||
+
|
||||
+static u32 xgene_enet_rd_diag_csr(struct xgene_enet_pdata *p, u32 offset)
|
||||
+{
|
||||
+ return ioread32(p->eth_diag_csr_addr + offset);
|
||||
+}
|
||||
+
|
||||
+static u32 xgene_enet_rd_indirect(struct xgene_indirect_ctl *ctl, u32 rd_addr)
|
||||
+{
|
||||
+ u32 rd_data;
|
||||
+ int i;
|
||||
+
|
||||
+ iowrite32(rd_addr, ctl->addr);
|
||||
+ iowrite32(XGENE_ENET_RD_CMD, ctl->cmd);
|
||||
+
|
||||
+ /* wait for read command to complete */
|
||||
+ for (i = 0; i < 10; i++) {
|
||||
+ if (ioread32(ctl->cmd_done)) {
|
||||
+ rd_data = ioread32(ctl->ctl);
|
||||
+ iowrite32(0, ctl->cmd);
|
||||
+
|
||||
+ return rd_data;
|
||||
+ }
|
||||
+ udelay(1);
|
||||
+ }
|
||||
+
|
||||
+ pr_err("%s: mac read failed, addr: %04x\n", __func__, rd_addr);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static u32 xgene_enet_rd_mac(struct xgene_enet_pdata *p, u32 rd_addr)
|
||||
+{
|
||||
+ struct xgene_indirect_ctl ctl = {
|
||||
+ .addr = p->mcx_mac_addr + MAC_ADDR_REG_OFFSET,
|
||||
+ .ctl = p->mcx_mac_addr + MAC_READ_REG_OFFSET,
|
||||
+ .cmd = p->mcx_mac_addr + MAC_COMMAND_REG_OFFSET,
|
||||
+ .cmd_done = p->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET
|
||||
+ };
|
||||
+
|
||||
+ return xgene_enet_rd_indirect(&ctl, rd_addr);
|
||||
+}
|
||||
+
|
||||
+static int xgene_enet_ecc_init(struct xgene_enet_pdata *p)
|
||||
+{
|
||||
+ struct net_device *ndev = p->ndev;
|
||||
+ u32 data;
|
||||
+ int i;
|
||||
+
|
||||
+ xgene_enet_wr_diag_csr(p, ENET_CFG_MEM_RAM_SHUTDOWN_ADDR, 0);
|
||||
+ for (i = 0; i < 10 && data != ~0U ; i++) {
|
||||
+ usleep_range(100, 110);
|
||||
+ data = xgene_enet_rd_diag_csr(p, ENET_BLOCK_MEM_RDY_ADDR);
|
||||
+ }
|
||||
+
|
||||
+ if (data != ~0U) {
|
||||
+ netdev_err(ndev, "Failed to release memory from shutdown\n");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *p)
|
||||
+{
|
||||
+ u32 val = 0xffffffff;
|
||||
+
|
||||
+ xgene_enet_wr_ring_if(p, ENET_CFGSSQMIWQASSOC_ADDR, val);
|
||||
+ xgene_enet_wr_ring_if(p, ENET_CFGSSQMIFPQASSOC_ADDR, val);
|
||||
+}
|
||||
+
|
||||
+static void xgene_mii_phy_write(struct xgene_enet_pdata *p, u8 phy_id,
|
||||
+ u32 reg, u16 data)
|
||||
+{
|
||||
+ u32 addr, wr_data, done;
|
||||
+ int i;
|
||||
+
|
||||
+ addr = PHY_ADDR(phy_id) | REG_ADDR(reg);
|
||||
+ xgene_enet_wr_mac(p, MII_MGMT_ADDRESS_ADDR, addr);
|
||||
+
|
||||
+ wr_data = PHY_CONTROL(data);
|
||||
+ xgene_enet_wr_mac(p, MII_MGMT_CONTROL_ADDR, wr_data);
|
||||
+
|
||||
+ for (i = 0; i < 10; i++) {
|
||||
+ done = xgene_enet_rd_mac(p, MII_MGMT_INDICATORS_ADDR);
|
||||
+ if (!(done & BUSY_MASK))
|
||||
+ return;
|
||||
+ usleep_range(10, 20);
|
||||
+ }
|
||||
+
|
||||
+ netdev_err(p->ndev, "MII_MGMT write failed\n");
|
||||
+}
|
||||
+
|
||||
+static u32 xgene_mii_phy_read(struct xgene_enet_pdata *p, u8 phy_id, u32 reg)
|
||||
+{
|
||||
+ u32 addr, data, done;
|
||||
+ int i;
|
||||
+
|
||||
+ addr = PHY_ADDR(phy_id) | REG_ADDR(reg);
|
||||
+ xgene_enet_wr_mac(p, MII_MGMT_ADDRESS_ADDR, addr);
|
||||
+ xgene_enet_wr_mac(p, MII_MGMT_COMMAND_ADDR, READ_CYCLE_MASK);
|
||||
+
|
||||
+ for (i = 0; i < 10; i++) {
|
||||
+ done = xgene_enet_rd_mac(p, MII_MGMT_INDICATORS_ADDR);
|
||||
+ if (!(done & BUSY_MASK)) {
|
||||
+ data = xgene_enet_rd_mac(p, MII_MGMT_STATUS_ADDR);
|
||||
+ xgene_enet_wr_mac(p, MII_MGMT_COMMAND_ADDR, 0);
|
||||
+
|
||||
+ return data;
|
||||
+ }
|
||||
+ usleep_range(10, 20);
|
||||
+ }
|
||||
+
|
||||
+ netdev_err(p->ndev, "MII_MGMT read failed\n");
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void xgene_sgmac_reset(struct xgene_enet_pdata *p)
|
||||
+{
|
||||
+ xgene_enet_wr_mac(p, MAC_CONFIG_1_ADDR, SOFT_RESET1);
|
||||
+ xgene_enet_wr_mac(p, MAC_CONFIG_1_ADDR, 0);
|
||||
+}
|
||||
+
|
||||
+static void xgene_sgmac_set_mac_addr(struct xgene_enet_pdata *p)
|
||||
+{
|
||||
+ u32 addr0, addr1;
|
||||
+ u8 *dev_addr = p->ndev->dev_addr;
|
||||
+
|
||||
+ addr0 = (dev_addr[3] << 24) | (dev_addr[2] << 16) |
|
||||
+ (dev_addr[1] << 8) | dev_addr[0];
|
||||
+ xgene_enet_wr_mac(p, STATION_ADDR0_ADDR, addr0);
|
||||
+
|
||||
+ addr1 = xgene_enet_rd_mac(p, STATION_ADDR1_ADDR);
|
||||
+ addr1 |= (dev_addr[5] << 24) | (dev_addr[4] << 16);
|
||||
+ xgene_enet_wr_mac(p, STATION_ADDR1_ADDR, addr1);
|
||||
+}
|
||||
+
|
||||
+static u32 xgene_enet_link_status(struct xgene_enet_pdata *p)
|
||||
+{
|
||||
+ u32 data;
|
||||
+
|
||||
+ data = xgene_mii_phy_read(p, INT_PHY_ADDR,
|
||||
+ SGMII_BASE_PAGE_ABILITY_ADDR >> 2);
|
||||
+
|
||||
+ return data & LINK_UP;
|
||||
+}
|
||||
+
|
||||
+static void xgene_sgmac_init(struct xgene_enet_pdata *p)
|
||||
+{
|
||||
+ u32 data, loop = 10;
|
||||
+
|
||||
+ xgene_sgmac_reset(p);
|
||||
+
|
||||
+ /* Enable auto-negotiation */
|
||||
+ xgene_mii_phy_write(p, INT_PHY_ADDR, SGMII_CONTROL_ADDR >> 2, 0x1000);
|
||||
+ xgene_mii_phy_write(p, INT_PHY_ADDR, SGMII_TBI_CONTROL_ADDR >> 2, 0);
|
||||
+
|
||||
+ while (loop--) {
|
||||
+ data = xgene_mii_phy_read(p, INT_PHY_ADDR,
|
||||
+ SGMII_STATUS_ADDR >> 2);
|
||||
+ if ((data & AUTO_NEG_COMPLETE) && (data & LINK_STATUS))
|
||||
+ break;
|
||||
+ usleep_range(10, 20);
|
||||
+ }
|
||||
+ if (!(data & AUTO_NEG_COMPLETE) || !(data & LINK_STATUS))
|
||||
+ netdev_err(p->ndev, "Auto-negotiation failed\n");
|
||||
+
|
||||
+ data = xgene_enet_rd_mac(p, MAC_CONFIG_2_ADDR);
|
||||
+ ENET_INTERFACE_MODE2_SET(&data, 2);
|
||||
+ xgene_enet_wr_mac(p, MAC_CONFIG_2_ADDR, data | FULL_DUPLEX2);
|
||||
+ xgene_enet_wr_mac(p, INTERFACE_CONTROL_ADDR, ENET_GHD_MODE);
|
||||
+
|
||||
+ data = xgene_enet_rd_csr(p, ENET_SPARE_CFG_REG_ADDR);
|
||||
+ data |= MPA_IDLE_WITH_QMI_EMPTY;
|
||||
+ xgene_enet_wr_csr(p, ENET_SPARE_CFG_REG_ADDR, data);
|
||||
+
|
||||
+ xgene_sgmac_set_mac_addr(p);
|
||||
+
|
||||
+ data = xgene_enet_rd_csr(p, DEBUG_REG_ADDR);
|
||||
+ data |= CFG_BYPASS_UNISEC_TX | CFG_BYPASS_UNISEC_RX;
|
||||
+ xgene_enet_wr_csr(p, DEBUG_REG_ADDR, data);
|
||||
+
|
||||
+ /* Adjust MDC clock frequency */
|
||||
+ data = xgene_enet_rd_mac(p, MII_MGMT_CONFIG_ADDR);
|
||||
+ MGMT_CLOCK_SEL_SET(&data, 7);
|
||||
+ xgene_enet_wr_mac(p, MII_MGMT_CONFIG_ADDR, data);
|
||||
+
|
||||
+ /* Enable drop if bufpool not available */
|
||||
+ data = xgene_enet_rd_csr(p, RSIF_CONFIG_REG_ADDR);
|
||||
+ data |= CFG_RSIF_FPBUFF_TIMEOUT_EN;
|
||||
+ xgene_enet_wr_csr(p, RSIF_CONFIG_REG_ADDR, data);
|
||||
+
|
||||
+ /* Rtype should be copied from FP */
|
||||
+ xgene_enet_wr_csr(p, RSIF_RAM_DBG_REG0_ADDR, 0);
|
||||
+
|
||||
+ /* Bypass traffic gating */
|
||||
+ xgene_enet_wr_csr(p, CFG_LINK_AGGR_RESUME_0_ADDR, TX_PORT0);
|
||||
+ xgene_enet_wr_csr(p, CFG_BYPASS_ADDR, RESUME_TX);
|
||||
+ xgene_enet_wr_csr(p, SG_RX_DV_GATE_REG_0_ADDR, RESUME_RX0);
|
||||
+}
|
||||
+
|
||||
+static void xgene_sgmac_rxtx(struct xgene_enet_pdata *p, u32 bits, bool set)
|
||||
+{
|
||||
+ u32 data;
|
||||
+
|
||||
+ data = xgene_enet_rd_mac(p, MAC_CONFIG_1_ADDR);
|
||||
+
|
||||
+ if (set)
|
||||
+ data |= bits;
|
||||
+ else
|
||||
+ data &= ~bits;
|
||||
+
|
||||
+ xgene_enet_wr_mac(p, MAC_CONFIG_1_ADDR, data);
|
||||
+}
|
||||
+
|
||||
+static void xgene_sgmac_rx_enable(struct xgene_enet_pdata *p)
|
||||
+{
|
||||
+ xgene_sgmac_rxtx(p, RX_EN, true);
|
||||
+}
|
||||
+
|
||||
+static void xgene_sgmac_tx_enable(struct xgene_enet_pdata *p)
|
||||
+{
|
||||
+ xgene_sgmac_rxtx(p, TX_EN, true);
|
||||
+}
|
||||
+
|
||||
+static void xgene_sgmac_rx_disable(struct xgene_enet_pdata *p)
|
||||
+{
|
||||
+ xgene_sgmac_rxtx(p, RX_EN, false);
|
||||
+}
|
||||
+
|
||||
+static void xgene_sgmac_tx_disable(struct xgene_enet_pdata *p)
|
||||
+{
|
||||
+ xgene_sgmac_rxtx(p, TX_EN, false);
|
||||
+}
|
||||
+
|
||||
+static void xgene_enet_reset(struct xgene_enet_pdata *p)
|
||||
+{
|
||||
+ clk_prepare_enable(p->clk);
|
||||
+ clk_disable_unprepare(p->clk);
|
||||
+ clk_prepare_enable(p->clk);
|
||||
+
|
||||
+ xgene_enet_ecc_init(p);
|
||||
+ xgene_enet_config_ring_if_assoc(p);
|
||||
+}
|
||||
+
|
||||
+static void xgene_enet_cle_bypass(struct xgene_enet_pdata *p,
|
||||
+ u32 dst_ring_num, u16 bufpool_id)
|
||||
+{
|
||||
+ u32 data, fpsel;
|
||||
+
|
||||
+ data = CFG_CLE_BYPASS_EN0;
|
||||
+ xgene_enet_wr_csr(p, CLE_BYPASS_REG0_0_ADDR, data);
|
||||
+
|
||||
+ fpsel = xgene_enet_ring_bufnum(bufpool_id) - 0x20;
|
||||
+ data = CFG_CLE_DSTQID0(dst_ring_num) | CFG_CLE_FPSEL0(fpsel);
|
||||
+ xgene_enet_wr_csr(p, CLE_BYPASS_REG1_0_ADDR, data);
|
||||
+}
|
||||
+
|
||||
+static void xgene_enet_shutdown(struct xgene_enet_pdata *p)
|
||||
+{
|
||||
+ clk_disable_unprepare(p->clk);
|
||||
+}
|
||||
+
|
||||
+static void xgene_enet_link_state(struct work_struct *work)
|
||||
+{
|
||||
+ struct xgene_enet_pdata *p = container_of(to_delayed_work(work),
|
||||
+ struct xgene_enet_pdata, link_work);
|
||||
+ struct net_device *ndev = p->ndev;
|
||||
+ u32 link, poll_interval;
|
||||
+
|
||||
+ link = xgene_enet_link_status(p);
|
||||
+ if (link) {
|
||||
+ if (!netif_carrier_ok(ndev)) {
|
||||
+ netif_carrier_on(ndev);
|
||||
+ xgene_sgmac_init(p);
|
||||
+ xgene_sgmac_rx_enable(p);
|
||||
+ xgene_sgmac_tx_enable(p);
|
||||
+ netdev_info(ndev, "Link is Up - 1Gbps\n");
|
||||
+ }
|
||||
+ poll_interval = PHY_POLL_LINK_ON;
|
||||
+ } else {
|
||||
+ if (netif_carrier_ok(ndev)) {
|
||||
+ xgene_sgmac_rx_disable(p);
|
||||
+ xgene_sgmac_tx_disable(p);
|
||||
+ netif_carrier_off(ndev);
|
||||
+ netdev_info(ndev, "Link is Down\n");
|
||||
+ }
|
||||
+ poll_interval = PHY_POLL_LINK_OFF;
|
||||
+ }
|
||||
+
|
||||
+ schedule_delayed_work(&p->link_work, poll_interval);
|
||||
+}
|
||||
+
|
||||
+struct xgene_mac_ops xgene_sgmac_ops = {
|
||||
+ .init = xgene_sgmac_init,
|
||||
+ .reset = xgene_sgmac_reset,
|
||||
+ .rx_enable = xgene_sgmac_rx_enable,
|
||||
+ .tx_enable = xgene_sgmac_tx_enable,
|
||||
+ .rx_disable = xgene_sgmac_rx_disable,
|
||||
+ .tx_disable = xgene_sgmac_tx_disable,
|
||||
+ .set_mac_addr = xgene_sgmac_set_mac_addr,
|
||||
+ .link_state = xgene_enet_link_state
|
||||
+};
|
||||
+
|
||||
+struct xgene_port_ops xgene_sgport_ops = {
|
||||
+ .reset = xgene_enet_reset,
|
||||
+ .cle_bypass = xgene_enet_cle_bypass,
|
||||
+ .shutdown = xgene_enet_shutdown
|
||||
+};
|
||||
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h
|
||||
new file mode 100644
|
||||
index 0000000..de43246
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h
|
||||
@@ -0,0 +1,41 @@
|
||||
+/* Applied Micro X-Gene SoC Ethernet Driver
|
||||
+ *
|
||||
+ * Copyright (c) 2014, Applied Micro Circuits Corporation
|
||||
+ * Authors: Iyappan Subramanian <isubramanian@apm.com>
|
||||
+ * Keyur Chudgar <kchudgar@apm.com>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify it
|
||||
+ * under the terms of the GNU General Public License as published by the
|
||||
+ * Free Software Foundation; either version 2 of the License, or (at your
|
||||
+ * option) any later version.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License
|
||||
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
+ */
|
||||
+
|
||||
+#ifndef __XGENE_ENET_SGMAC_H__
|
||||
+#define __XGENE_ENET_SGMAC_H__
|
||||
+
|
||||
+#define PHY_ADDR(src) (((src)<<8) & GENMASK(12, 8))
|
||||
+#define REG_ADDR(src) ((src) & GENMASK(4, 0))
|
||||
+#define PHY_CONTROL(src) ((src) & GENMASK(15, 0))
|
||||
+#define INT_PHY_ADDR 0x1e
|
||||
+#define SGMII_TBI_CONTROL_ADDR 0x44
|
||||
+#define SGMII_CONTROL_ADDR 0x00
|
||||
+#define SGMII_STATUS_ADDR 0x04
|
||||
+#define SGMII_BASE_PAGE_ABILITY_ADDR 0x14
|
||||
+#define AUTO_NEG_COMPLETE BIT(5)
|
||||
+#define LINK_STATUS BIT(2)
|
||||
+#define LINK_UP BIT(15)
|
||||
+#define MPA_IDLE_WITH_QMI_EMPTY BIT(12)
|
||||
+#define SG_RX_DV_GATE_REG_0_ADDR 0x0dfc
|
||||
+
|
||||
+extern struct xgene_mac_ops xgene_sgmac_ops;
|
||||
+extern struct xgene_port_ops xgene_sgport_ops;
|
||||
+
|
||||
+#endif /* __XGENE_ENET_SGMAC_H__ */
|
||||
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h
|
||||
index dcb2087..5a5296a 100644
|
||||
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h
|
||||
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h
|
||||
@@ -47,9 +47,6 @@
|
||||
#define XG_ENET_SPARE_CFG_REG_1_ADDR 0x0410
|
||||
#define XGENET_RX_DV_GATE_REG_0_ADDR 0x0804
|
||||
|
||||
-#define PHY_POLL_LINK_ON (10 * HZ)
|
||||
-#define PHY_POLL_LINK_OFF (PHY_POLL_LINK_ON / 5)
|
||||
-
|
||||
extern struct xgene_mac_ops xgene_xgmac_ops;
|
||||
extern struct xgene_port_ops xgene_xgport_ops;
|
||||
|
||||
--
|
||||
2.1.0
|
||||
|
|
@ -1,175 +0,0 @@
|
|||
From 092e35e5b10fdea2d814aa96ab2c2f2aad477640 Mon Sep 17 00:00:00 2001
|
||||
From: Iyappan Subramanian <isubramanian@apm.com>
|
||||
Date: Mon, 3 Nov 2014 11:59:55 -0800
|
||||
Subject: [PATCH 08/11] drivers: net: xgene: Backward compatibility with older
|
||||
firmware
|
||||
Origin: https://git.kernel.org/cgit/linux/kernel/git/davem/net-next.git/commit/?id=c3f4465d272fa94d5a077c502e83d3e712ec8d62
|
||||
|
||||
This patch adds support when used with older firmware (<= 1.13.28).
|
||||
|
||||
- Added xgene_ring_mgr_init() to check whether ring manager is initialized
|
||||
- Calling xgene_ring_mgr_init() from xgene_port_ops.reset()
|
||||
- To handle errors, changed the return type of xgene_port_ops.reset()
|
||||
|
||||
Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
|
||||
Signed-off-by: Keyur Chudgar <kchudgar@apm.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/apm/xgene/xgene_enet_hw.c | 18 +++++++++++++++++-
|
||||
drivers/net/ethernet/apm/xgene/xgene_enet_hw.h | 4 ++++
|
||||
drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 5 ++++-
|
||||
drivers/net/ethernet/apm/xgene/xgene_enet_main.h | 2 +-
|
||||
drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c | 7 ++++++-
|
||||
drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c | 7 ++++++-
|
||||
6 files changed, 38 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
|
||||
index 63ea194..7ba83ff 100644
|
||||
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
|
||||
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
|
||||
@@ -575,10 +575,24 @@ static void xgene_gmac_tx_disable(struct xgene_enet_pdata *pdata)
|
||||
xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data & ~TX_EN);
|
||||
}
|
||||
|
||||
-static void xgene_enet_reset(struct xgene_enet_pdata *pdata)
|
||||
+bool xgene_ring_mgr_init(struct xgene_enet_pdata *p)
|
||||
+{
|
||||
+ if (!ioread32(p->ring_csr_addr + CLKEN_ADDR))
|
||||
+ return false;
|
||||
+
|
||||
+ if (ioread32(p->ring_csr_addr + SRST_ADDR))
|
||||
+ return false;
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+static int xgene_enet_reset(struct xgene_enet_pdata *pdata)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
+ if (!xgene_ring_mgr_init(pdata))
|
||||
+ return -ENODEV;
|
||||
+
|
||||
clk_prepare_enable(pdata->clk);
|
||||
clk_disable_unprepare(pdata->clk);
|
||||
clk_prepare_enable(pdata->clk);
|
||||
@@ -590,6 +604,8 @@ static void xgene_enet_reset(struct xgene_enet_pdata *pdata)
|
||||
val |= SCAN_AUTO_INCR;
|
||||
MGMT_CLOCK_SEL_SET(&val, 1);
|
||||
xgene_enet_wr_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, val);
|
||||
+
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static void xgene_gport_shutdown(struct xgene_enet_pdata *pdata)
|
||||
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
|
||||
index 3855858..ec45f32 100644
|
||||
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
|
||||
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
|
||||
@@ -104,6 +104,9 @@ enum xgene_enet_rm {
|
||||
#define BLOCK_ETH_MAC_OFFSET 0x0000
|
||||
#define BLOCK_ETH_MAC_CSR_OFFSET 0x2800
|
||||
|
||||
+#define CLKEN_ADDR 0xc208
|
||||
+#define SRST_ADDR 0xc200
|
||||
+
|
||||
#define MAC_ADDR_REG_OFFSET 0x00
|
||||
#define MAC_COMMAND_REG_OFFSET 0x04
|
||||
#define MAC_WRITE_REG_OFFSET 0x08
|
||||
@@ -318,6 +321,7 @@ void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring,
|
||||
|
||||
int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata);
|
||||
void xgene_enet_mdio_remove(struct xgene_enet_pdata *pdata);
|
||||
+bool xgene_ring_mgr_init(struct xgene_enet_pdata *p);
|
||||
|
||||
extern struct xgene_mac_ops xgene_gmac_ops;
|
||||
extern struct xgene_port_ops xgene_gport_ops;
|
||||
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
|
||||
index 3c208cc..cc3f955 100644
|
||||
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
|
||||
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
|
||||
@@ -852,7 +852,9 @@ static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
|
||||
u16 dst_ring_num;
|
||||
int ret;
|
||||
|
||||
- pdata->port_ops->reset(pdata);
|
||||
+ ret = pdata->port_ops->reset(pdata);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
|
||||
ret = xgene_enet_create_desc_rings(ndev);
|
||||
if (ret) {
|
||||
@@ -954,6 +956,7 @@ static int xgene_enet_probe(struct platform_device *pdev)
|
||||
|
||||
return ret;
|
||||
err:
|
||||
+ unregister_netdev(ndev);
|
||||
free_netdev(ndev);
|
||||
return ret;
|
||||
}
|
||||
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
|
||||
index 874e5a0..dba647d 100644
|
||||
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
|
||||
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
|
||||
@@ -83,7 +83,7 @@ struct xgene_mac_ops {
|
||||
};
|
||||
|
||||
struct xgene_port_ops {
|
||||
- void (*reset)(struct xgene_enet_pdata *pdata);
|
||||
+ int (*reset)(struct xgene_enet_pdata *pdata);
|
||||
void (*cle_bypass)(struct xgene_enet_pdata *pdata,
|
||||
u32 dst_ring_num, u16 bufpool_id);
|
||||
void (*shutdown)(struct xgene_enet_pdata *pdata);
|
||||
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
|
||||
index c22f326..f5d4f68 100644
|
||||
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
|
||||
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
|
||||
@@ -311,14 +311,19 @@ static void xgene_sgmac_tx_disable(struct xgene_enet_pdata *p)
|
||||
xgene_sgmac_rxtx(p, TX_EN, false);
|
||||
}
|
||||
|
||||
-static void xgene_enet_reset(struct xgene_enet_pdata *p)
|
||||
+static int xgene_enet_reset(struct xgene_enet_pdata *p)
|
||||
{
|
||||
+ if (!xgene_ring_mgr_init(p))
|
||||
+ return -ENODEV;
|
||||
+
|
||||
clk_prepare_enable(p->clk);
|
||||
clk_disable_unprepare(p->clk);
|
||||
clk_prepare_enable(p->clk);
|
||||
|
||||
xgene_enet_ecc_init(p);
|
||||
xgene_enet_config_ring_if_assoc(p);
|
||||
+
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static void xgene_enet_cle_bypass(struct xgene_enet_pdata *p,
|
||||
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
|
||||
index 67d0720..a18a9d1 100644
|
||||
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
|
||||
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
|
||||
@@ -252,14 +252,19 @@ static void xgene_xgmac_tx_disable(struct xgene_enet_pdata *pdata)
|
||||
xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data & ~HSTTFEN);
|
||||
}
|
||||
|
||||
-static void xgene_enet_reset(struct xgene_enet_pdata *pdata)
|
||||
+static int xgene_enet_reset(struct xgene_enet_pdata *pdata)
|
||||
{
|
||||
+ if (!xgene_ring_mgr_init(pdata))
|
||||
+ return -ENODEV;
|
||||
+
|
||||
clk_prepare_enable(pdata->clk);
|
||||
clk_disable_unprepare(pdata->clk);
|
||||
clk_prepare_enable(pdata->clk);
|
||||
|
||||
xgene_enet_ecc_init(pdata);
|
||||
xgene_enet_config_ring_if_assoc(pdata);
|
||||
+
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static void xgene_enet_xgcle_bypass(struct xgene_enet_pdata *pdata,
|
||||
--
|
||||
2.1.0
|
||||
|
|
@ -1,353 +0,0 @@
|
|||
From 33f8dba6cb5493b2fff26c43a6cc0321e0814732 Mon Sep 17 00:00:00 2001
|
||||
From: Iyappan Subramanian <isubramanian@apm.com>
|
||||
Date: Thu, 9 Oct 2014 18:32:05 -0700
|
||||
Subject: [PATCH 01/11] drivers: net: xgene: Preparing for adding 10GbE support
|
||||
Origin: https://git.kernel.org/linus/d0eb74582fa7b5c15710d293a3c4d8d3409ae165
|
||||
|
||||
- Rearranged code to pave the way for adding 10GbE support
|
||||
- Added mac_ops structure containing function pointers for mac specific functions
|
||||
- Added port_ops structure containing function pointers for port specific functions
|
||||
|
||||
Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
|
||||
Signed-off-by: Keyur Chudgar <kchudgar@apm.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/apm/xgene/xgene_enet_hw.c | 44 ++++++++++++++++--------
|
||||
drivers/net/ethernet/apm/xgene/xgene_enet_hw.h | 16 ++-------
|
||||
drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 40 +++++++++++++--------
|
||||
drivers/net/ethernet/apm/xgene/xgene_enet_main.h | 19 ++++++++++
|
||||
4 files changed, 78 insertions(+), 41 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
|
||||
index 812d8d6..c8f3824 100644
|
||||
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
|
||||
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
|
||||
@@ -402,7 +402,7 @@ static int xgene_mii_phy_read(struct xgene_enet_pdata *pdata,
|
||||
return data;
|
||||
}
|
||||
|
||||
-void xgene_gmac_set_mac_addr(struct xgene_enet_pdata *pdata)
|
||||
+static void xgene_gmac_set_mac_addr(struct xgene_enet_pdata *pdata)
|
||||
{
|
||||
u32 addr0, addr1;
|
||||
u8 *dev_addr = pdata->ndev->dev_addr;
|
||||
@@ -436,13 +436,13 @@ static int xgene_enet_ecc_init(struct xgene_enet_pdata *pdata)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-void xgene_gmac_reset(struct xgene_enet_pdata *pdata)
|
||||
+static void xgene_gmac_reset(struct xgene_enet_pdata *pdata)
|
||||
{
|
||||
xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, SOFT_RESET1);
|
||||
xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, 0);
|
||||
}
|
||||
|
||||
-void xgene_gmac_init(struct xgene_enet_pdata *pdata, int speed)
|
||||
+static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
|
||||
{
|
||||
u32 value, mc2;
|
||||
u32 intf_ctl, rgmii;
|
||||
@@ -456,7 +456,7 @@ void xgene_gmac_init(struct xgene_enet_pdata *pdata, int speed)
|
||||
xgene_enet_rd_mcx_mac(pdata, INTERFACE_CONTROL_ADDR, &intf_ctl);
|
||||
xgene_enet_rd_csr(pdata, RGMII_REG_0_ADDR, &rgmii);
|
||||
|
||||
- switch (speed) {
|
||||
+ switch (pdata->phy_speed) {
|
||||
case SPEED_10:
|
||||
ENET_INTERFACE_MODE2_SET(&mc2, 1);
|
||||
CFG_MACMODE_SET(&icm0, 0);
|
||||
@@ -525,8 +525,8 @@ static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *pdata)
|
||||
xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIQMLITEFPQASSOC_ADDR, val);
|
||||
}
|
||||
|
||||
-void xgene_enet_cle_bypass(struct xgene_enet_pdata *pdata,
|
||||
- u32 dst_ring_num, u16 bufpool_id)
|
||||
+static void xgene_enet_cle_bypass(struct xgene_enet_pdata *pdata,
|
||||
+ u32 dst_ring_num, u16 bufpool_id)
|
||||
{
|
||||
u32 cb;
|
||||
u32 fpsel;
|
||||
@@ -544,7 +544,7 @@ void xgene_enet_cle_bypass(struct xgene_enet_pdata *pdata,
|
||||
xgene_enet_wr_csr(pdata, CLE_BYPASS_REG1_0_ADDR, cb);
|
||||
}
|
||||
|
||||
-void xgene_gmac_rx_enable(struct xgene_enet_pdata *pdata)
|
||||
+static void xgene_gmac_rx_enable(struct xgene_enet_pdata *pdata)
|
||||
{
|
||||
u32 data;
|
||||
|
||||
@@ -552,7 +552,7 @@ void xgene_gmac_rx_enable(struct xgene_enet_pdata *pdata)
|
||||
xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data | RX_EN);
|
||||
}
|
||||
|
||||
-void xgene_gmac_tx_enable(struct xgene_enet_pdata *pdata)
|
||||
+static void xgene_gmac_tx_enable(struct xgene_enet_pdata *pdata)
|
||||
{
|
||||
u32 data;
|
||||
|
||||
@@ -560,7 +560,7 @@ void xgene_gmac_tx_enable(struct xgene_enet_pdata *pdata)
|
||||
xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data | TX_EN);
|
||||
}
|
||||
|
||||
-void xgene_gmac_rx_disable(struct xgene_enet_pdata *pdata)
|
||||
+static void xgene_gmac_rx_disable(struct xgene_enet_pdata *pdata)
|
||||
{
|
||||
u32 data;
|
||||
|
||||
@@ -568,7 +568,7 @@ void xgene_gmac_rx_disable(struct xgene_enet_pdata *pdata)
|
||||
xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data & ~RX_EN);
|
||||
}
|
||||
|
||||
-void xgene_gmac_tx_disable(struct xgene_enet_pdata *pdata)
|
||||
+static void xgene_gmac_tx_disable(struct xgene_enet_pdata *pdata)
|
||||
{
|
||||
u32 data;
|
||||
|
||||
@@ -576,7 +576,7 @@ void xgene_gmac_tx_disable(struct xgene_enet_pdata *pdata)
|
||||
xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data & ~TX_EN);
|
||||
}
|
||||
|
||||
-void xgene_enet_reset(struct xgene_enet_pdata *pdata)
|
||||
+static void xgene_enet_reset(struct xgene_enet_pdata *pdata)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
@@ -593,7 +593,7 @@ void xgene_enet_reset(struct xgene_enet_pdata *pdata)
|
||||
xgene_enet_wr_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, val);
|
||||
}
|
||||
|
||||
-void xgene_gport_shutdown(struct xgene_enet_pdata *pdata)
|
||||
+static void xgene_gport_shutdown(struct xgene_enet_pdata *pdata)
|
||||
{
|
||||
clk_disable_unprepare(pdata->clk);
|
||||
}
|
||||
@@ -627,10 +627,10 @@ static void xgene_enet_adjust_link(struct net_device *ndev)
|
||||
|
||||
if (phydev->link) {
|
||||
if (pdata->phy_speed != phydev->speed) {
|
||||
- xgene_gmac_init(pdata, phydev->speed);
|
||||
+ pdata->phy_speed = phydev->speed;
|
||||
+ xgene_gmac_init(pdata);
|
||||
xgene_gmac_rx_enable(pdata);
|
||||
xgene_gmac_tx_enable(pdata);
|
||||
- pdata->phy_speed = phydev->speed;
|
||||
phy_print_status(phydev);
|
||||
}
|
||||
} else {
|
||||
@@ -726,3 +726,19 @@ void xgene_enet_mdio_remove(struct xgene_enet_pdata *pdata)
|
||||
mdiobus_free(pdata->mdio_bus);
|
||||
pdata->mdio_bus = NULL;
|
||||
}
|
||||
+
|
||||
+struct xgene_mac_ops xgene_gmac_ops = {
|
||||
+ .init = xgene_gmac_init,
|
||||
+ .reset = xgene_gmac_reset,
|
||||
+ .rx_enable = xgene_gmac_rx_enable,
|
||||
+ .tx_enable = xgene_gmac_tx_enable,
|
||||
+ .rx_disable = xgene_gmac_rx_disable,
|
||||
+ .tx_disable = xgene_gmac_tx_disable,
|
||||
+ .set_mac_addr = xgene_gmac_set_mac_addr,
|
||||
+};
|
||||
+
|
||||
+struct xgene_port_ops xgene_gport_ops = {
|
||||
+ .reset = xgene_enet_reset,
|
||||
+ .cle_bypass = xgene_enet_cle_bypass,
|
||||
+ .shutdown = xgene_gport_shutdown,
|
||||
+};
|
||||
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
|
||||
index 371e7a5..084ac68 100644
|
||||
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
|
||||
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
|
||||
@@ -318,20 +318,10 @@ void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring,
|
||||
struct xgene_enet_pdata *pdata,
|
||||
enum xgene_enet_err_code status);
|
||||
|
||||
-void xgene_enet_reset(struct xgene_enet_pdata *priv);
|
||||
-void xgene_gmac_reset(struct xgene_enet_pdata *priv);
|
||||
-void xgene_gmac_init(struct xgene_enet_pdata *priv, int speed);
|
||||
-void xgene_gmac_tx_enable(struct xgene_enet_pdata *priv);
|
||||
-void xgene_gmac_rx_enable(struct xgene_enet_pdata *priv);
|
||||
-void xgene_gmac_tx_disable(struct xgene_enet_pdata *priv);
|
||||
-void xgene_gmac_rx_disable(struct xgene_enet_pdata *priv);
|
||||
-void xgene_gmac_set_mac_addr(struct xgene_enet_pdata *pdata);
|
||||
-void xgene_enet_cle_bypass(struct xgene_enet_pdata *pdata,
|
||||
- u32 dst_ring_num, u16 bufpool_id);
|
||||
-void xgene_gport_shutdown(struct xgene_enet_pdata *priv);
|
||||
-void xgene_gmac_get_tx_stats(struct xgene_enet_pdata *pdata);
|
||||
-
|
||||
int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata);
|
||||
void xgene_enet_mdio_remove(struct xgene_enet_pdata *pdata);
|
||||
|
||||
+extern struct xgene_mac_ops xgene_gmac_ops;
|
||||
+extern struct xgene_port_ops xgene_gport_ops;
|
||||
+
|
||||
#endif /* __XGENE_ENET_HW_H__ */
|
||||
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
|
||||
index e4222af..c432644 100644
|
||||
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
|
||||
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
|
||||
@@ -413,7 +413,7 @@ static void xgene_enet_timeout(struct net_device *ndev)
|
||||
{
|
||||
struct xgene_enet_pdata *pdata = netdev_priv(ndev);
|
||||
|
||||
- xgene_gmac_reset(pdata);
|
||||
+ pdata->mac_ops->reset(pdata);
|
||||
}
|
||||
|
||||
static int xgene_enet_register_irq(struct net_device *ndev)
|
||||
@@ -445,10 +445,11 @@ static void xgene_enet_free_irq(struct net_device *ndev)
|
||||
static int xgene_enet_open(struct net_device *ndev)
|
||||
{
|
||||
struct xgene_enet_pdata *pdata = netdev_priv(ndev);
|
||||
+ struct xgene_mac_ops *mac_ops = pdata->mac_ops;
|
||||
int ret;
|
||||
|
||||
- xgene_gmac_tx_enable(pdata);
|
||||
- xgene_gmac_rx_enable(pdata);
|
||||
+ mac_ops->tx_enable(pdata);
|
||||
+ mac_ops->rx_enable(pdata);
|
||||
|
||||
ret = xgene_enet_register_irq(ndev);
|
||||
if (ret)
|
||||
@@ -466,6 +467,7 @@ static int xgene_enet_open(struct net_device *ndev)
|
||||
static int xgene_enet_close(struct net_device *ndev)
|
||||
{
|
||||
struct xgene_enet_pdata *pdata = netdev_priv(ndev);
|
||||
+ struct xgene_mac_ops *mac_ops = pdata->mac_ops;
|
||||
|
||||
netif_stop_queue(ndev);
|
||||
|
||||
@@ -476,8 +478,8 @@ static int xgene_enet_close(struct net_device *ndev)
|
||||
xgene_enet_free_irq(ndev);
|
||||
xgene_enet_process_ring(pdata->rx_ring, -1);
|
||||
|
||||
- xgene_gmac_tx_disable(pdata);
|
||||
- xgene_gmac_rx_disable(pdata);
|
||||
+ mac_ops->tx_disable(pdata);
|
||||
+ mac_ops->rx_disable(pdata);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -724,7 +726,7 @@ static int xgene_enet_set_mac_address(struct net_device *ndev, void *addr)
|
||||
ret = eth_mac_addr(ndev, addr);
|
||||
if (ret)
|
||||
return ret;
|
||||
- xgene_gmac_set_mac_addr(pdata);
|
||||
+ pdata->mac_ops->set_mac_addr(pdata);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -834,8 +836,8 @@ static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
|
||||
u16 dst_ring_num;
|
||||
int ret;
|
||||
|
||||
- xgene_gmac_tx_disable(pdata);
|
||||
- xgene_gmac_rx_disable(pdata);
|
||||
+ pdata->mac_ops->tx_disable(pdata);
|
||||
+ pdata->mac_ops->rx_disable(pdata);
|
||||
|
||||
ret = xgene_enet_create_desc_rings(ndev);
|
||||
if (ret) {
|
||||
@@ -853,11 +855,17 @@ static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
|
||||
}
|
||||
|
||||
dst_ring_num = xgene_enet_dst_ring_num(pdata->rx_ring);
|
||||
- xgene_enet_cle_bypass(pdata, dst_ring_num, buf_pool->id);
|
||||
+ pdata->port_ops->cle_bypass(pdata, dst_ring_num, buf_pool->id);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static void xgene_enet_setup_ops(struct xgene_enet_pdata *pdata)
|
||||
+{
|
||||
+ pdata->mac_ops = &xgene_gmac_ops;
|
||||
+ pdata->port_ops = &xgene_gport_ops;
|
||||
+}
|
||||
+
|
||||
static int xgene_enet_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct net_device *ndev;
|
||||
@@ -886,8 +894,9 @@ static int xgene_enet_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
- xgene_enet_reset(pdata);
|
||||
- xgene_gmac_init(pdata, SPEED_1000);
|
||||
+ xgene_enet_setup_ops(pdata);
|
||||
+ pdata->port_ops->reset(pdata);
|
||||
+ pdata->mac_ops->init(pdata);
|
||||
|
||||
ret = register_netdev(ndev);
|
||||
if (ret) {
|
||||
@@ -918,19 +927,21 @@ err:
|
||||
static int xgene_enet_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct xgene_enet_pdata *pdata;
|
||||
+ struct xgene_mac_ops *mac_ops;
|
||||
struct net_device *ndev;
|
||||
|
||||
pdata = platform_get_drvdata(pdev);
|
||||
+ mac_ops = pdata->mac_ops;
|
||||
ndev = pdata->ndev;
|
||||
|
||||
- xgene_gmac_rx_disable(pdata);
|
||||
- xgene_gmac_tx_disable(pdata);
|
||||
+ mac_ops->rx_disable(pdata);
|
||||
+ mac_ops->tx_disable(pdata);
|
||||
|
||||
netif_napi_del(&pdata->rx_ring->napi);
|
||||
xgene_enet_mdio_remove(pdata);
|
||||
xgene_enet_delete_desc_rings(pdata);
|
||||
unregister_netdev(ndev);
|
||||
- xgene_gport_shutdown(pdata);
|
||||
+ pdata->port_ops->shutdown(pdata);
|
||||
free_netdev(ndev);
|
||||
|
||||
return 0;
|
||||
@@ -956,5 +967,6 @@ module_platform_driver(xgene_enet_driver);
|
||||
|
||||
MODULE_DESCRIPTION("APM X-Gene SoC Ethernet driver");
|
||||
MODULE_VERSION(XGENE_DRV_VERSION);
|
||||
+MODULE_AUTHOR("Iyappan Subramanian <isubramanian@apm.com>");
|
||||
MODULE_AUTHOR("Keyur Chudgar <kchudgar@apm.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
|
||||
index 0815866..ac180f9 100644
|
||||
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
|
||||
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
|
||||
@@ -68,6 +68,23 @@ struct xgene_enet_desc_ring {
|
||||
};
|
||||
};
|
||||
|
||||
+struct xgene_mac_ops {
|
||||
+ void (*init)(struct xgene_enet_pdata *pdata);
|
||||
+ void (*reset)(struct xgene_enet_pdata *pdata);
|
||||
+ void (*tx_enable)(struct xgene_enet_pdata *pdata);
|
||||
+ void (*rx_enable)(struct xgene_enet_pdata *pdata);
|
||||
+ void (*tx_disable)(struct xgene_enet_pdata *pdata);
|
||||
+ void (*rx_disable)(struct xgene_enet_pdata *pdata);
|
||||
+ void (*set_mac_addr)(struct xgene_enet_pdata *pdata);
|
||||
+};
|
||||
+
|
||||
+struct xgene_port_ops {
|
||||
+ void (*reset)(struct xgene_enet_pdata *pdata);
|
||||
+ void (*cle_bypass)(struct xgene_enet_pdata *pdata,
|
||||
+ u32 dst_ring_num, u16 bufpool_id);
|
||||
+ void (*shutdown)(struct xgene_enet_pdata *pdata);
|
||||
+};
|
||||
+
|
||||
/* ethernet private data */
|
||||
struct xgene_enet_pdata {
|
||||
struct net_device *ndev;
|
||||
@@ -98,6 +115,8 @@ struct xgene_enet_pdata {
|
||||
u32 speed;
|
||||
u16 rm;
|
||||
struct rtnl_link_stats64 stats;
|
||||
+ struct xgene_mac_ops *mac_ops;
|
||||
+ struct xgene_port_ops *port_ops;
|
||||
};
|
||||
|
||||
/* Set the specified value into a bit-field defined by its starting position
|
||||
--
|
||||
2.1.0
|
||||
|
|
@ -1,153 +0,0 @@
|
|||
From 0d0393191a19911ef523a4cba10bedb10bbf07dd Mon Sep 17 00:00:00 2001
|
||||
From: Iyappan Subramanian <isubramanian@apm.com>
|
||||
Date: Mon, 13 Oct 2014 17:05:33 -0700
|
||||
Subject: [PATCH 04/11] drivers: net: xgene: Preparing for adding SGMII based
|
||||
1GbE
|
||||
Origin: https://git.kernel.org/linus/dc8385f0c0f46ca18c1c8ab59c9f565dc7cfa6bf
|
||||
|
||||
- Added link_state function pointer to the xgene__mac_ops structure
|
||||
- Moved ring manager (pdata->rm) assignment to xgene_enet_setup_ops
|
||||
- Removed unused variable (pdata->phy_addr) and macro (FULL_DUPLEX)
|
||||
|
||||
Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
|
||||
Signed-off-by: Keyur Chudgar <kchudgar@apm.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/apm/xgene/xgene_enet_hw.c | 1 -
|
||||
drivers/net/ethernet/apm/xgene/xgene_enet_hw.h | 1 -
|
||||
drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 8 +++++---
|
||||
drivers/net/ethernet/apm/xgene/xgene_enet_main.h | 2 +-
|
||||
drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c | 3 ++-
|
||||
drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h | 1 -
|
||||
6 files changed, 8 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
|
||||
index c8f3824..63ea194 100644
|
||||
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
|
||||
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
|
||||
@@ -410,7 +410,6 @@ static void xgene_gmac_set_mac_addr(struct xgene_enet_pdata *pdata)
|
||||
addr0 = (dev_addr[3] << 24) | (dev_addr[2] << 16) |
|
||||
(dev_addr[1] << 8) | dev_addr[0];
|
||||
addr1 = (dev_addr[5] << 24) | (dev_addr[4] << 16);
|
||||
- addr1 |= pdata->phy_addr & 0xFFFF;
|
||||
|
||||
xgene_enet_wr_mcx_mac(pdata, STATION_ADDR0_ADDR, addr0);
|
||||
xgene_enet_wr_mcx_mac(pdata, STATION_ADDR1_ADDR, addr1);
|
||||
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
|
||||
index 15ec426..2efc4d9 100644
|
||||
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
|
||||
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
|
||||
@@ -179,7 +179,6 @@ enum xgene_enet_rm {
|
||||
#define TUND_ADDR 0x4a
|
||||
|
||||
#define TSO_IPPROTO_TCP 1
|
||||
-#define FULL_DUPLEX 2
|
||||
|
||||
#define USERINFO_POS 0
|
||||
#define USERINFO_LEN 32
|
||||
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
|
||||
index 9b85239..9e251ec 100644
|
||||
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
|
||||
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
|
||||
@@ -833,11 +833,9 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
|
||||
if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) {
|
||||
pdata->mcx_mac_addr = base_addr + BLOCK_ETH_MAC_OFFSET;
|
||||
pdata->mcx_mac_csr_addr = base_addr + BLOCK_ETH_MAC_CSR_OFFSET;
|
||||
- pdata->rm = RM3;
|
||||
} else {
|
||||
pdata->mcx_mac_addr = base_addr + BLOCK_AXG_MAC_OFFSET;
|
||||
pdata->mcx_mac_csr_addr = base_addr + BLOCK_AXG_MAC_CSR_OFFSET;
|
||||
- pdata->rm = RM0;
|
||||
}
|
||||
pdata->rx_buff_cnt = NUM_PKT_BUF;
|
||||
|
||||
@@ -881,10 +879,12 @@ static void xgene_enet_setup_ops(struct xgene_enet_pdata *pdata)
|
||||
case PHY_INTERFACE_MODE_RGMII:
|
||||
pdata->mac_ops = &xgene_gmac_ops;
|
||||
pdata->port_ops = &xgene_gport_ops;
|
||||
+ pdata->rm = RM3;
|
||||
break;
|
||||
default:
|
||||
pdata->mac_ops = &xgene_xgmac_ops;
|
||||
pdata->port_ops = &xgene_xgport_ops;
|
||||
+ pdata->rm = RM0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -895,6 +895,7 @@ static int xgene_enet_probe(struct platform_device *pdev)
|
||||
struct xgene_enet_pdata *pdata;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct napi_struct *napi;
|
||||
+ struct xgene_mac_ops *mac_ops;
|
||||
int ret;
|
||||
|
||||
ndev = alloc_etherdev(sizeof(struct xgene_enet_pdata));
|
||||
@@ -937,10 +938,11 @@ static int xgene_enet_probe(struct platform_device *pdev)
|
||||
|
||||
napi = &pdata->rx_ring->napi;
|
||||
netif_napi_add(ndev, napi, xgene_enet_napi, NAPI_POLL_WEIGHT);
|
||||
+ mac_ops = pdata->mac_ops;
|
||||
if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII)
|
||||
ret = xgene_enet_mdio_config(pdata);
|
||||
else
|
||||
- INIT_DELAYED_WORK(&pdata->link_work, xgene_enet_link_state);
|
||||
+ INIT_DELAYED_WORK(&pdata->link_work, mac_ops->link_state);
|
||||
|
||||
return ret;
|
||||
err:
|
||||
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
|
||||
index 86cf68b..10b03a1 100644
|
||||
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
|
||||
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
|
||||
@@ -76,6 +76,7 @@ struct xgene_mac_ops {
|
||||
void (*tx_disable)(struct xgene_enet_pdata *pdata);
|
||||
void (*rx_disable)(struct xgene_enet_pdata *pdata);
|
||||
void (*set_mac_addr)(struct xgene_enet_pdata *pdata);
|
||||
+ void (*link_state)(struct work_struct *work);
|
||||
};
|
||||
|
||||
struct xgene_port_ops {
|
||||
@@ -109,7 +110,6 @@ struct xgene_enet_pdata {
|
||||
void __iomem *base_addr;
|
||||
void __iomem *ring_csr_addr;
|
||||
void __iomem *ring_cmd_addr;
|
||||
- u32 phy_addr;
|
||||
int phy_mode;
|
||||
enum xgene_enet_rm rm;
|
||||
struct rtnl_link_stats64 stats;
|
||||
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
|
||||
index cd64b9f..67d0720 100644
|
||||
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
|
||||
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
|
||||
@@ -284,7 +284,7 @@ static void xgene_enet_shutdown(struct xgene_enet_pdata *pdata)
|
||||
clk_disable_unprepare(pdata->clk);
|
||||
}
|
||||
|
||||
-void xgene_enet_link_state(struct work_struct *work)
|
||||
+static void xgene_enet_link_state(struct work_struct *work)
|
||||
{
|
||||
struct xgene_enet_pdata *pdata = container_of(to_delayed_work(work),
|
||||
struct xgene_enet_pdata, link_work);
|
||||
@@ -322,6 +322,7 @@ struct xgene_mac_ops xgene_xgmac_ops = {
|
||||
.rx_disable = xgene_xgmac_rx_disable,
|
||||
.tx_disable = xgene_xgmac_tx_disable,
|
||||
.set_mac_addr = xgene_xgmac_set_mac_addr,
|
||||
+ .link_state = xgene_enet_link_state
|
||||
};
|
||||
|
||||
struct xgene_port_ops xgene_xgport_ops = {
|
||||
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h
|
||||
index d2d59e7..dcb2087 100644
|
||||
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h
|
||||
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h
|
||||
@@ -50,7 +50,6 @@
|
||||
#define PHY_POLL_LINK_ON (10 * HZ)
|
||||
#define PHY_POLL_LINK_OFF (PHY_POLL_LINK_ON / 5)
|
||||
|
||||
-void xgene_enet_link_state(struct work_struct *work);
|
||||
extern struct xgene_mac_ops xgene_xgmac_ops;
|
||||
extern struct xgene_port_ops xgene_xgport_ops;
|
||||
|
||||
--
|
||||
2.1.0
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
From 9f2bc2c30d24987cff5edc43a3d8f89bef6ce12a Mon Sep 17 00:00:00 2001
|
||||
From: Geert Uytterhoeven <geert@linux-m68k.org>
|
||||
Date: Thu, 23 Oct 2014 10:25:53 +0200
|
||||
Subject: [PATCH 07/11] drivers: net: xgene: Rewrite buggy loop in
|
||||
xgene_enet_ecc_init()
|
||||
Origin: https://git.kernel.org/linus/b71e821de50f0ff92f10f33064ee1713e9014158
|
||||
|
||||
drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c: In function ‘xgene_enet_ecc_init’:
|
||||
drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c:126: warning: ‘data’ may be used uninitialized in this function
|
||||
|
||||
Depending on the arbitrary value on the stack, the loop may terminate
|
||||
too early, and cause a bogus -ENODEV failure.
|
||||
|
||||
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c | 16 +++++++---------
|
||||
1 file changed, 7 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
|
||||
index e6d24c2..c22f326 100644
|
||||
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
|
||||
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
|
||||
@@ -124,20 +124,18 @@ static int xgene_enet_ecc_init(struct xgene_enet_pdata *p)
|
||||
{
|
||||
struct net_device *ndev = p->ndev;
|
||||
u32 data;
|
||||
- int i;
|
||||
+ int i = 0;
|
||||
|
||||
xgene_enet_wr_diag_csr(p, ENET_CFG_MEM_RAM_SHUTDOWN_ADDR, 0);
|
||||
- for (i = 0; i < 10 && data != ~0U ; i++) {
|
||||
+ do {
|
||||
usleep_range(100, 110);
|
||||
data = xgene_enet_rd_diag_csr(p, ENET_BLOCK_MEM_RDY_ADDR);
|
||||
- }
|
||||
+ if (data == ~0U)
|
||||
+ return 0;
|
||||
+ } while (++i < 10);
|
||||
|
||||
- if (data != ~0U) {
|
||||
- netdev_err(ndev, "Failed to release memory from shutdown\n");
|
||||
- return -ENODEV;
|
||||
- }
|
||||
-
|
||||
- return 0;
|
||||
+ netdev_err(ndev, "Failed to release memory from shutdown\n");
|
||||
+ return -ENODEV;
|
||||
}
|
||||
|
||||
static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *p)
|
||||
--
|
||||
2.1.0
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
From 33b54088743086cd6fdce269486e0bf27ed24155 Mon Sep 17 00:00:00 2001
|
||||
From: Iyappan Subramanian <isubramanian@apm.com>
|
||||
Date: Mon, 3 Nov 2014 11:59:56 -0800
|
||||
Subject: [PATCH 09/11] drivers: net: xgene: fix: Use separate resources
|
||||
Origin: https://git.kernel.org/cgit/linux/kernel/git/davem/net-next.git/commit/?id=bdd330f0506b2c4d02d5453fa32e785f0c348388
|
||||
|
||||
This patch fixes the following kernel crash during SGMII based 1GbE probe.
|
||||
|
||||
BUG: Bad page state in process swapper/0 pfn:40fe6ad
|
||||
page:ffffffbee37a75d8 count:-1 mapcount:0 mapping: (null) index:0x0
|
||||
flags: 0x0()
|
||||
page dumped because: nonzero _count
|
||||
Modules linked in:
|
||||
CPU: 0 PID: 0 Comm: swapper/0 Not tainted 3.17.0+ #7
|
||||
Call trace:
|
||||
[<ffffffc000087fa0>] dump_backtrace+0x0/0x12c
|
||||
[<ffffffc0000880dc>] show_stack+0x10/0x1c
|
||||
[<ffffffc0004d981c>] dump_stack+0x74/0xc4
|
||||
[<ffffffc00012fe70>] bad_page+0xd8/0x128
|
||||
[<ffffffc000133000>] get_page_from_freelist+0x4b8/0x640
|
||||
[<ffffffc000133260>] __alloc_pages_nodemask+0xd8/0x834
|
||||
[<ffffffc0004194f8>] __netdev_alloc_frag+0x124/0x1b8
|
||||
[<ffffffc00041bfdc>] __netdev_alloc_skb+0x90/0x10c
|
||||
[<ffffffc00039ff30>] xgene_enet_refill_bufpool+0x11c/0x280
|
||||
[<ffffffc0003a11a4>] xgene_enet_process_ring+0x168/0x340
|
||||
[<ffffffc0003a1498>] xgene_enet_napi+0x1c/0x50
|
||||
[<ffffffc00042b454>] net_rx_action+0xc8/0x18c
|
||||
[<ffffffc0000b0880>] __do_softirq+0x114/0x24c
|
||||
[<ffffffc0000b0c34>] irq_exit+0x94/0xc8
|
||||
[<ffffffc0000e68a0>] __handle_domain_irq+0x8c/0xf4
|
||||
[<ffffffc000081288>] gic_handle_irq+0x30/0x7c
|
||||
|
||||
This was due to hardware resource sharing conflict with the firmware. This
|
||||
patch fixes this crash by using resources (descriptor ring, prefetch buffer)
|
||||
that are not shared.
|
||||
|
||||
Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
|
||||
Signed-off-by: Keyur Chudgar <kchudgar@apm.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 6 +++---
|
||||
drivers/net/ethernet/apm/xgene/xgene_enet_main.h | 3 +++
|
||||
2 files changed, 6 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
|
||||
index cc3f955..1236696 100644
|
||||
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
|
||||
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
|
||||
@@ -639,9 +639,9 @@ static int xgene_enet_create_desc_rings(struct net_device *ndev)
|
||||
struct device *dev = ndev_to_dev(ndev);
|
||||
struct xgene_enet_desc_ring *rx_ring, *tx_ring, *cp_ring;
|
||||
struct xgene_enet_desc_ring *buf_pool = NULL;
|
||||
- u8 cpu_bufnum = 0, eth_bufnum = 0;
|
||||
- u8 bp_bufnum = 0x20;
|
||||
- u16 ring_id, ring_num = 0;
|
||||
+ u8 cpu_bufnum = 0, eth_bufnum = START_ETH_BUFNUM;
|
||||
+ u8 bp_bufnum = START_BP_BUFNUM;
|
||||
+ u16 ring_id, ring_num = START_RING_NUM;
|
||||
int ret;
|
||||
|
||||
/* allocate rx descriptor ring */
|
||||
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
|
||||
index dba647d..f9958fa 100644
|
||||
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
|
||||
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
|
||||
@@ -38,6 +38,9 @@
|
||||
#define SKB_BUFFER_SIZE (XGENE_ENET_MAX_MTU - NET_IP_ALIGN)
|
||||
#define NUM_PKT_BUF 64
|
||||
#define NUM_BUFPOOL 32
|
||||
+#define START_ETH_BUFNUM 2
|
||||
+#define START_BP_BUFNUM 0x22
|
||||
+#define START_RING_NUM 8
|
||||
|
||||
#define PHY_POLL_LINK_ON (10 * HZ)
|
||||
#define PHY_POLL_LINK_OFF (PHY_POLL_LINK_ON / 5)
|
||||
--
|
||||
2.1.0
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
From fe64571ba6b03ee505c4b384da1b335729b36db3 Mon Sep 17 00:00:00 2001
|
||||
From: Iyappan Subramanian <isubramanian@apm.com>
|
||||
Date: Thu, 9 Oct 2014 18:32:04 -0700
|
||||
Subject: [PATCH 10/11] dtb: Add 10GbE node to APM X-Gene SoC device tree
|
||||
Origin: https://git.kernel.org/linus/5fb32417b7e52d2e6d5f5c64d277a03e5c998a02
|
||||
|
||||
Added 10GbE interface and clock nodes.
|
||||
|
||||
Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
|
||||
Signed-off-by: Keyur Chudgar <kchudgar@apm.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
arch/arm64/boot/dts/apm-mustang.dts | 4 ++++
|
||||
arch/arm64/boot/dts/apm-storm.dtsi | 29 ++++++++++++++++++++++++++++-
|
||||
2 files changed, 32 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/apm-mustang.dts b/arch/arm64/boot/dts/apm-mustang.dts
|
||||
index b2f5622..2ae782b 100644
|
||||
--- a/arch/arm64/boot/dts/apm-mustang.dts
|
||||
+++ b/arch/arm64/boot/dts/apm-mustang.dts
|
||||
@@ -32,3 +32,7 @@
|
||||
&menet {
|
||||
status = "ok";
|
||||
};
|
||||
+
|
||||
+&xgenet {
|
||||
+ status = "ok";
|
||||
+};
|
||||
diff --git a/arch/arm64/boot/dts/apm-storm.dtsi b/arch/arm64/boot/dts/apm-storm.dtsi
|
||||
index c0aceef..4d762a3 100644
|
||||
--- a/arch/arm64/boot/dts/apm-storm.dtsi
|
||||
+++ b/arch/arm64/boot/dts/apm-storm.dtsi
|
||||
@@ -176,6 +176,16 @@
|
||||
clock-output-names = "menetclk";
|
||||
};
|
||||
|
||||
+ xge0clk: xge0clk@1f61c000 {
|
||||
+ compatible = "apm,xgene-device-clock";
|
||||
+ #clock-cells = <1>;
|
||||
+ clocks = <&socplldiv2 0>;
|
||||
+ reg = <0x0 0x1f61c000 0x0 0x1000>;
|
||||
+ reg-names = "csr-reg";
|
||||
+ csr-mask = <0x3>;
|
||||
+ clock-output-names = "xge0clk";
|
||||
+ };
|
||||
+
|
||||
sataphy1clk: sataphy1clk@1f21c000 {
|
||||
compatible = "apm,xgene-device-clock";
|
||||
#clock-cells = <1>;
|
||||
@@ -407,7 +417,8 @@
|
||||
interrupts = <0x0 0x3c 0x4>;
|
||||
dma-coherent;
|
||||
clocks = <&menetclk 0>;
|
||||
- local-mac-address = [00 01 73 00 00 01];
|
||||
+ /* mac address will be overwritten by the bootloader */
|
||||
+ local-mac-address = [00 00 00 00 00 00];
|
||||
phy-connection-type = "rgmii";
|
||||
phy-handle = <&menetphy>;
|
||||
mdio {
|
||||
@@ -421,5 +432,21 @@
|
||||
|
||||
};
|
||||
};
|
||||
+
|
||||
+ xgenet: ethernet@1f610000 {
|
||||
+ compatible = "apm,xgene-enet";
|
||||
+ status = "disabled";
|
||||
+ reg = <0x0 0x1f610000 0x0 0xd100>,
|
||||
+ <0x0 0x1f600000 0x0 0X400>,
|
||||
+ <0x0 0x18000000 0x0 0X200>;
|
||||
+ reg-names = "enet_csr", "ring_csr", "ring_cmd";
|
||||
+ interrupts = <0x0 0x60 0x4>;
|
||||
+ dma-coherent;
|
||||
+ clocks = <&xge0clk 0>;
|
||||
+ /* mac address will be overwritten by the bootloader */
|
||||
+ local-mac-address = [00 00 00 00 00 00];
|
||||
+ phy-connection-type = "xgmii";
|
||||
+ };
|
||||
+
|
||||
};
|
||||
};
|
||||
--
|
||||
2.1.0
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
From 8e17e86dde4b417cdbe8ee9073b8ffc10a1f5afb Mon Sep 17 00:00:00 2001
|
||||
From: Iyappan Subramanian <isubramanian@apm.com>
|
||||
Date: Mon, 13 Oct 2014 17:05:32 -0700
|
||||
Subject: [PATCH 11/11] dtb: Add SGMII based 1GbE node to APM X-Gene SoC device
|
||||
tree
|
||||
Origin: https://git.kernel.org/linus/4c2e7f0954dcd9fbb47d065c654d44608dad38e0
|
||||
|
||||
Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
|
||||
Signed-off-by: Keyur Chudgar <kchudgar@apm.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
arch/arm64/boot/dts/apm-mustang.dts | 4 ++++
|
||||
arch/arm64/boot/dts/apm-storm.dtsi | 24 ++++++++++++++++++++++++
|
||||
2 files changed, 28 insertions(+)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/apm-mustang.dts b/arch/arm64/boot/dts/apm-mustang.dts
|
||||
index 2ae782b..71a1489 100644
|
||||
--- a/arch/arm64/boot/dts/apm-mustang.dts
|
||||
+++ b/arch/arm64/boot/dts/apm-mustang.dts
|
||||
@@ -33,6 +33,10 @@
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
+&sgenet0 {
|
||||
+ status = "ok";
|
||||
+};
|
||||
+
|
||||
&xgenet {
|
||||
status = "ok";
|
||||
};
|
||||
diff --git a/arch/arm64/boot/dts/apm-storm.dtsi b/arch/arm64/boot/dts/apm-storm.dtsi
|
||||
index d16cc03..f45bbfe 100644
|
||||
--- a/arch/arm64/boot/dts/apm-storm.dtsi
|
||||
+++ b/arch/arm64/boot/dts/apm-storm.dtsi
|
||||
@@ -176,6 +176,16 @@
|
||||
clock-output-names = "menetclk";
|
||||
};
|
||||
|
||||
+ sge0clk: sge0clk@1f21c000 {
|
||||
+ compatible = "apm,xgene-device-clock";
|
||||
+ #clock-cells = <1>;
|
||||
+ clocks = <&socplldiv2 0>;
|
||||
+ reg = <0x0 0x1f21c000 0x0 0x1000>;
|
||||
+ reg-names = "csr-reg";
|
||||
+ csr-mask = <0x3>;
|
||||
+ clock-output-names = "sge0clk";
|
||||
+ };
|
||||
+
|
||||
xge0clk: xge0clk@1f61c000 {
|
||||
compatible = "apm,xgene-device-clock";
|
||||
#clock-cells = <1>;
|
||||
@@ -446,6 +456,20 @@
|
||||
};
|
||||
};
|
||||
|
||||
+ sgenet0: ethernet@1f210000 {
|
||||
+ compatible = "apm,xgene-enet";
|
||||
+ status = "disabled";
|
||||
+ reg = <0x0 0x1f210000 0x0 0x10000>,
|
||||
+ <0x0 0x1f200000 0x0 0X10000>,
|
||||
+ <0x0 0x1B000000 0x0 0X20000>;
|
||||
+ reg-names = "enet_csr", "ring_csr", "ring_cmd";
|
||||
+ interrupts = <0x0 0xA0 0x4>;
|
||||
+ dma-coherent;
|
||||
+ clocks = <&sge0clk 0>;
|
||||
+ local-mac-address = [00 00 00 00 00 00];
|
||||
+ phy-connection-type = "sgmii";
|
||||
+ };
|
||||
+
|
||||
xgenet: ethernet@1f610000 {
|
||||
compatible = "apm,xgene-enet";
|
||||
status = "disabled";
|
||||
--
|
||||
2.1.0
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
From 09c9e0593d7215c809a4a47659b0e760112d656e Mon Sep 17 00:00:00 2001
|
||||
From: Iyappan Subramanian <isubramanian@apm.com>
|
||||
Date: Mon, 3 Nov 2014 11:59:54 -0800
|
||||
Subject: [PATCH] dtb: xgene: fix: Backward compatibility with older firmware
|
||||
Origin: https://git.kernel.org/linus/09c9e0593d7215c809a4a47659b0e760112d656e
|
||||
|
||||
The following kernel crash was reported when using older firmware (<= 1.13.28).
|
||||
|
||||
[ 0.980000] libphy: APM X-Gene MDIO bus: probed
|
||||
[ 1.130000] Unhandled fault: synchronous external abort (0x96000010) at 0xffffff800009a17c
|
||||
[ 1.140000] Internal error: : 96000010 [#1] SMP
|
||||
[ 1.140000] Modules linked in:
|
||||
[ 1.140000] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.17.0+ #21
|
||||
[ 1.140000] task: ffffffc3f0110000 ti: ffffffc3f0064000 task.ti: ffffffc3f0064000
|
||||
[ 1.140000] PC is at ioread32+0x58/0x68
|
||||
[ 1.140000] LR is at xgene_enet_setup_ring+0x18c/0x1cc
|
||||
[ 1.140000] pc : [<ffffffc0003cec68>] lr : [<ffffffc00053dad8>] pstate: a0000045
|
||||
[ 1.140000] sp : ffffffc3f0067b20
|
||||
[ 1.140000] x29: ffffffc3f0067b20 x28: ffffffc000aa8ea0
|
||||
[ 1.140000] x27: ffffffc000bb2000 x26: ffffffc000a64270
|
||||
[ 1.140000] x25: ffffffc000b05ad8 x24: ffffffc0ff99ba58
|
||||
[ 1.140000] x23: 0000000000004000 x22: 0000000000004000
|
||||
[ 1.140000] x21: 0000000000000200 x20: 0000000000200000
|
||||
[ 1.140000] x19: ffffffc0ff99ba18 x18: ffffffc0007a6000
|
||||
[ 1.140000] x17: 0000000000000007 x16: 000000000000000e
|
||||
[ 1.140000] x15: 0000000000000001 x14: 0000000000000000
|
||||
[ 1.140000] x13: ffffffbeedb71320 x12: 00000000ffffff80
|
||||
[ 1.140000] x11: 0000000000000002 x10: 0000000000000000
|
||||
[ 1.140000] x9 : 0000000000000000 x8 : ffffffc3eb2a4000
|
||||
[ 1.140000] x7 : 0000000000000000 x6 : 0000000000000000
|
||||
[ 1.140000] x5 : 0000000001080000 x4 : 000000007d654010
|
||||
[ 1.140000] x3 : ffffffffffffffff x2 : 000000000003ffff
|
||||
[ 1.140000] x1 : ffffff800009a17c x0 : ffffff800009a17c
|
||||
|
||||
The issue was that the older firmware does not support 10GbE and
|
||||
SGMII based 1GBE interfaces.
|
||||
|
||||
This patch changes the address length of the reg property of sgmii0 and xgmii
|
||||
nodes and serves as preparatory patch for the fix.
|
||||
|
||||
Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
|
||||
Signed-off-by: Keyur Chudgar <kchudgar@apm.com>
|
||||
Reported-by: Dann Frazier <dann.frazier@canonical.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
arch/arm64/boot/dts/apm-storm.dtsi | 10 +++++-----
|
||||
1 file changed, 5 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/apm-storm.dtsi b/arch/arm64/boot/dts/apm-storm.dtsi
|
||||
index 295c72d..f1ad9c2 100644
|
||||
--- a/arch/arm64/boot/dts/apm-storm.dtsi
|
||||
+++ b/arch/arm64/boot/dts/apm-storm.dtsi
|
||||
@@ -599,7 +599,7 @@
|
||||
compatible = "apm,xgene-enet";
|
||||
status = "disabled";
|
||||
reg = <0x0 0x17020000 0x0 0xd100>,
|
||||
- <0x0 0X17030000 0x0 0X400>,
|
||||
+ <0x0 0X17030000 0x0 0Xc300>,
|
||||
<0x0 0X10000000 0x0 0X200>;
|
||||
reg-names = "enet_csr", "ring_csr", "ring_cmd";
|
||||
interrupts = <0x0 0x3c 0x4>;
|
||||
@@ -624,9 +624,9 @@
|
||||
sgenet0: ethernet@1f210000 {
|
||||
compatible = "apm,xgene-enet";
|
||||
status = "disabled";
|
||||
- reg = <0x0 0x1f210000 0x0 0x10000>,
|
||||
- <0x0 0x1f200000 0x0 0X10000>,
|
||||
- <0x0 0x1B000000 0x0 0X20000>;
|
||||
+ reg = <0x0 0x1f210000 0x0 0xd100>,
|
||||
+ <0x0 0x1f200000 0x0 0Xc300>,
|
||||
+ <0x0 0x1B000000 0x0 0X200>;
|
||||
reg-names = "enet_csr", "ring_csr", "ring_cmd";
|
||||
interrupts = <0x0 0xA0 0x4>;
|
||||
dma-coherent;
|
||||
@@ -639,7 +639,7 @@
|
||||
compatible = "apm,xgene-enet";
|
||||
status = "disabled";
|
||||
reg = <0x0 0x1f610000 0x0 0xd100>,
|
||||
- <0x0 0x1f600000 0x0 0X400>,
|
||||
+ <0x0 0x1f600000 0x0 0Xc300>,
|
||||
<0x0 0x18000000 0x0 0X200>;
|
||||
reg-names = "enet_csr", "ring_csr", "ring_cmd";
|
||||
interrupts = <0x0 0x60 0x4>;
|
||||
--
|
||||
2.1.0
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
From: Michael Neuling <mikey@neuling.org>
|
||||
Subject: deb-pkg: Add support for powerpc little endian
|
||||
Origin: http://marc.info/?l=linux-kernel&m=140989493729069&w=2
|
||||
|
||||
The Debian powerpc little endian architecture is called ppc64le. This
|
||||
is the default architecture used by Ubuntu for powerpc.
|
||||
|
||||
The below checks the kernel config to see if we are compiling little
|
||||
endian and sets the Debian arch appropriately.
|
||||
|
||||
Signed-off-by: Michael Neuling <mikey@neuling.org>
|
||||
|
||||
diff --git a/scripts/package/builddeb b/scripts/package/builddeb
|
||||
index 35d5a58..6f4a1af 100644
|
||||
--- a/scripts/package/builddeb
|
||||
+++ b/scripts/package/builddeb
|
||||
@@ -37,7 +37,7 @@ create_package() {
|
||||
s390*)
|
||||
debarch=s390$(grep -q CONFIG_64BIT=y $KCONFIG_CONFIG && echo x || true) ;;
|
||||
ppc*)
|
||||
- debarch=powerpc ;;
|
||||
+ debarch=$(grep -q CPU_LITTLE_ENDIAN=y $KCONFIG_CONFIG && echo ppc64el || echo powerpc) ;;
|
||||
parisc*)
|
||||
debarch=hppa ;;
|
||||
mips*)
|
|
@ -28,7 +28,7 @@ Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
|
|||
|
||||
--- a/Documentation/kernel-parameters.txt
|
||||
+++ b/Documentation/kernel-parameters.txt
|
||||
@@ -3132,6 +3132,10 @@ bytes respectively. Such letter suffixes
|
||||
@@ -3397,6 +3397,10 @@ bytes respectively. Such letter suffixes
|
||||
|
||||
switches= [HW,M68k]
|
||||
|
||||
|
@ -41,7 +41,7 @@ Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
|
|||
on older distributions. When this option is enabled
|
||||
--- a/arch/x86/Kconfig
|
||||
+++ b/arch/x86/Kconfig
|
||||
@@ -2384,6 +2384,14 @@ config X86_X32
|
||||
@@ -2455,6 +2455,14 @@ config X86_X32
|
||||
elf32_x86_64 support enabled to compile a kernel with this
|
||||
option set.
|
||||
|
||||
|
@ -58,7 +58,7 @@ Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
|
|||
depends on IA32_EMULATION || X86_X32
|
||||
--- a/arch/x86/include/asm/elf.h
|
||||
+++ b/arch/x86/include/asm/elf.h
|
||||
@@ -149,6 +149,12 @@ do { \
|
||||
@@ -154,6 +154,12 @@ do { \
|
||||
|
||||
#else /* CONFIG_X86_32 */
|
||||
|
||||
|
@ -71,7 +71,7 @@ Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
|
|||
/*
|
||||
* This is used to ensure we don't load something for the wrong architecture.
|
||||
*/
|
||||
@@ -157,7 +163,7 @@ do { \
|
||||
@@ -162,7 +168,7 @@ do { \
|
||||
|
||||
#define compat_elf_check_arch(x) \
|
||||
(elf_check_arch_ia32(x) || \
|
||||
|
@ -82,7 +82,7 @@ Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
|
|||
# error "The following code assumes __USER32_DS == __USER_DS"
|
||||
--- a/arch/x86/kernel/entry_64.S
|
||||
+++ b/arch/x86/kernel/entry_64.S
|
||||
@@ -621,8 +621,12 @@ system_call_fastpath:
|
||||
@@ -414,8 +414,12 @@ system_call_fastpath:
|
||||
#if __SYSCALL_MASK == ~0
|
||||
cmpq $__NR_syscall_max,%rax
|
||||
#else
|
||||
|
@ -95,9 +95,9 @@ Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
|
|||
+ .byte P6_NOP4
|
||||
+system_call_fast_compare_end:
|
||||
#endif
|
||||
ja badsys
|
||||
ja ret_from_sys_call /* and return regs->ax */
|
||||
movq %r10,%rcx
|
||||
@@ -740,8 +744,12 @@ tracesys:
|
||||
@@ -520,8 +524,12 @@ tracesys_phase2:
|
||||
#if __SYSCALL_MASK == ~0
|
||||
cmpq $__NR_syscall_max,%rax
|
||||
#else
|
||||
|
@ -110,9 +110,9 @@ Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
|
|||
+ .byte P6_NOP4
|
||||
+system_call_trace_compare_end:
|
||||
#endif
|
||||
ja int_ret_from_sys_call /* RAX(%rsp) set to -ENOSYS above */
|
||||
ja int_ret_from_sys_call /* RAX(%rsp) is already set */
|
||||
movq %r10,%rcx /* fixup for C */
|
||||
@@ -813,6 +821,16 @@ int_restore_rest:
|
||||
@@ -593,6 +601,16 @@ int_restore_rest:
|
||||
CFI_ENDPROC
|
||||
END(system_call)
|
||||
|
||||
|
|
|
@ -18,13 +18,13 @@ bugfix/all/radeon-firmware-is-required-for-drm-and-kms-on-r600-onward.patch
|
|||
|
||||
# Patches and source files from aufs3 repository, imported with
|
||||
# debian/patches/features/all/aufs3/gen-patch.
|
||||
features/all/aufs3/aufs3-kbuild.patch
|
||||
features/all/aufs3/aufs3-base.patch
|
||||
features/all/aufs3/aufs3-mmap.patch
|
||||
features/all/aufs3/aufs3-standalone.patch
|
||||
features/all/aufs3/aufs3-add.patch
|
||||
#features/all/aufs3/aufs3-kbuild.patch
|
||||
#features/all/aufs3/aufs3-base.patch
|
||||
#features/all/aufs3/aufs3-mmap.patch
|
||||
#features/all/aufs3/aufs3-standalone.patch
|
||||
#features/all/aufs3/aufs3-add.patch
|
||||
# Debian-specific changes
|
||||
debian/aufs3-mark-as-staging.patch
|
||||
#debian/aufs3-mark-as-staging.patch
|
||||
|
||||
# Change some defaults for security reasons
|
||||
debian/af_802154-Disable-auto-loading-as-mitigation-against.patch
|
||||
|
@ -50,19 +50,14 @@ bugfix/x86/viafb-autoload-on-olpc-xo1.5-only.patch
|
|||
bugfix/arm/omap-musb-choice.patch
|
||||
bugfix/mips/disable-advansys.patch
|
||||
bugfix/m68k/ethernat-kconfig.patch
|
||||
bugfix/parisc/parisc-reduce-sigrtmin-from-37-to-32-to-behave-like-.patch
|
||||
bugfix/arm64/arm64-add-missing-dts-entry-for-X-Gene-platform.patch
|
||||
bugfix/arm64/arm64-removed-using-of-the-mask-attribute-in-the-dts.patch
|
||||
bugfix/x86/x86_64-traps-Stop-using-IST-for-SS.patch
|
||||
bugfix/x86/x86_64-traps-Fix-the-espfix64-DF-fixup-and-rewrite-i.patch
|
||||
bugfix/x86/x86_64-traps-Rework-bad_iret.patch
|
||||
bugfix/x86/x86-asm-traps-Disable-tracing-and-kprobes-in-fixup_b.patch
|
||||
|
||||
# Arch features
|
||||
features/mips/MIPS-increase-MAX-PHYSMEM-BITS-on-Loongson-3-only.patch
|
||||
features/mips/MIPS-Loongson-3-Add-Loongson-LS3A-RS780E-1-way-machi.patch
|
||||
features/mips/MIPS-octeon-Add-support-for-the-UBNT-E200-board.patch
|
||||
features/powerpc/deb-pkg-add-support-for-powerpc-little-endian.patch
|
||||
features/x86/x86-memtest-WARN-if-bad-RAM-found.patch
|
||||
features/x86/x86-make-x32-syscall-support-conditional.patch
|
||||
features/arm/deb-pkg-add-automatic-support-for-armhf-architecture.patch
|
||||
|
@ -70,19 +65,6 @@ features/arm/dts-sun7i-Add-spi0_pins_a-pinctrl-setting.patch
|
|||
features/arm/dts-sun7i-Add-uart3_pins_b-pinctrl-setting.patch
|
||||
features/arm/dts-sun7i-Add-Banana-Pi-board.patch
|
||||
features/arm/dts-sunxi-Banana-Pi-increase-startup-delay-for-the-GMAC-PHY-regulator.patch
|
||||
features/arm/dts-sun7i-Add-support-for-Olimex-A20-OLinuXino-LIME.patch
|
||||
features/arm64/drivers-net-xgene-Preparing-for-adding-10GbE-support.patch
|
||||
features/arm64/drivers-net-xgene-Add-10GbE-support.patch
|
||||
features/arm64/drivers-net-xgene-Add-10GbE-ethtool-support.patch
|
||||
features/arm64/drivers-net-xgene-Preparing-for-adding-SGMII-based-1.patch
|
||||
features/arm64/drivers-net-xgene-Add-SGMII-based-1GbE-support.patch
|
||||
features/arm64/drivers-net-xgene-Add-SGMII-based-1GbE-ethtool-suppo.patch
|
||||
features/arm64/drivers-net-xgene-Rewrite-buggy-loop-in-xgene_enet_e.patch
|
||||
features/arm64/drivers-net-xgene-Backward-compatibility-with-older-.patch
|
||||
features/arm64/drivers-net-xgene-fix-Use-separate-resources.patch
|
||||
features/arm64/dtb-Add-10GbE-node-to-APM-X-Gene-SoC-device-tree.patch
|
||||
features/arm64/dtb-Add-SGMII-based-1GbE-node-to-APM-X-Gene-SoC-devi.patch
|
||||
features/arm64/dtb-xgene-fix-Backward-compatibility-with-older-firm.patch
|
||||
|
||||
# Miscellaneous bug fixes
|
||||
bugfix/all/misc-bmp085-Enable-building-as-a-module.patch
|
||||
|
@ -91,12 +73,7 @@ bugfix/all/disable-some-marvell-phys.patch
|
|||
debian/i2o-disable-i2o_ext_adaptec-on-64bit.patch
|
||||
bugfix/all/aic94xx-remove-broken-fallback-for-missing-ctrl-a.patch
|
||||
bugfix/all/rtsx_usb_ms-use-msleep_interruptible-in-polling-loop.patch
|
||||
bugfix/all/drivers-net-Disable-UFO-through-virtio.patch
|
||||
bugfix/all/revert-drivers-net-disable-ufo-through-virtio-in-macvtap-and-tun.patch
|
||||
bugfix/all/xen-netback-make-feature-rx-notify-mandatory.patch
|
||||
bugfix/all/xen-netback-fix-unlimited-guest-Rx-internal-queue-an.patch
|
||||
bugfix/all/xen-netback-reintroduce-guest-Rx-stall-detection.patch
|
||||
bugfix/all/of-fdt-memblock_reserve-memreserve-regions-in-the-ca.patch
|
||||
|
||||
# Miscellaneous features
|
||||
features/all/efi-autoload-efivars.patch
|
||||
|
|
Loading…
Reference in New Issue