* [PATCH net-next 4/8] drivers: net: xgene: Add change_mtu function
From: Iyappan Subramanian @ 2016-12-02 0:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480639304-18757-1-git-send-email-isubramanian@apm.com>
This patch implements ndo_change_mtu() callback function that
enables mtu change.
Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
Signed-off-by: Quan Nguyen <qnguyen@apm.com>
---
drivers/net/ethernet/apm/xgene/xgene_enet_hw.c | 6 ++++++
drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 20 ++++++++++++++++++++
drivers/net/ethernet/apm/xgene/xgene_enet_main.h | 1 +
drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c | 6 ++++++
drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c | 7 +++++++
5 files changed, 40 insertions(+)
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
index fc9010f..92cc7e5 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
@@ -504,6 +504,11 @@ static void xgene_gmac_set_speed(struct xgene_enet_pdata *pdata)
xgene_enet_wr_mcx_csr(pdata, ICM_CONFIG2_REG_0_ADDR, icm2);
}
+static void xgene_enet_set_frame_size(struct xgene_enet_pdata *pdata, int size)
+{
+ xgene_enet_wr_mcx_mac(pdata, MAX_FRAME_LEN_ADDR, size);
+}
+
static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
{
u32 value;
@@ -903,6 +908,7 @@ void xgene_enet_mdio_remove(struct xgene_enet_pdata *pdata)
.tx_disable = xgene_gmac_tx_disable,
.set_speed = xgene_gmac_set_speed,
.set_mac_addr = xgene_gmac_set_mac_addr,
+ .set_framesize = xgene_enet_set_frame_size,
};
const 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 698df27..6c7eea8 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -1500,12 +1500,31 @@ static int xgene_enet_set_mac_address(struct net_device *ndev, void *addr)
return ret;
}
+static int xgene_change_mtu(struct net_device *ndev, int new_mtu)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+ int frame_size;
+
+ if (!netif_running(ndev))
+ return 0;
+
+ frame_size = (new_mtu > ETH_DATA_LEN) ? (new_mtu + 18) : 0x600;
+
+ xgene_enet_close(ndev);
+ ndev->mtu = new_mtu;
+ pdata->mac_ops->set_framesize(pdata, frame_size);
+ xgene_enet_open(ndev);
+
+ return 0;
+}
+
static const struct net_device_ops xgene_ndev_ops = {
.ndo_open = xgene_enet_open,
.ndo_stop = xgene_enet_close,
.ndo_start_xmit = xgene_enet_start_xmit,
.ndo_tx_timeout = xgene_enet_timeout,
.ndo_get_stats64 = xgene_enet_get_stats64,
+ .ndo_change_mtu = xgene_change_mtu,
.ndo_set_mac_address = xgene_enet_set_mac_address,
};
@@ -1832,6 +1851,7 @@ static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
buf_pool->id, ring_id);
}
+ ndev->max_mtu = XGENE_ENET_MAX_MTU;
pdata->phy_speed = SPEED_UNKNOWN;
pdata->mac_ops->init(pdata);
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
index 023ed76..61aa987 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
@@ -156,6 +156,7 @@ struct xgene_mac_ops {
void (*rx_disable)(struct xgene_enet_pdata *pdata);
void (*set_speed)(struct xgene_enet_pdata *pdata);
void (*set_mac_addr)(struct xgene_enet_pdata *pdata);
+ void (*set_framesize)(struct xgene_enet_pdata *pdata, int framesize);
void (*set_mss)(struct xgene_enet_pdata *pdata, u16 mss, u8 index);
void (*link_state)(struct work_struct *work);
};
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
index a10ab64..6283f2b 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
@@ -343,6 +343,11 @@ static void xgene_sgmac_set_speed(struct xgene_enet_pdata *p)
xgene_enet_wr_mcx_csr(p, icm2_addr, icm2);
}
+static void xgene_sgmac_set_frame_size(struct xgene_enet_pdata *pdata, int size)
+{
+ xgene_enet_wr_mac(pdata, MAX_FRAME_LEN_ADDR, size);
+}
+
static void xgene_sgmii_enable_autoneg(struct xgene_enet_pdata *p)
{
u32 data, loop = 10;
@@ -595,6 +600,7 @@ static void xgene_enet_link_state(struct work_struct *work)
.tx_disable = xgene_sgmac_tx_disable,
.set_speed = xgene_sgmac_set_speed,
.set_mac_addr = xgene_sgmac_set_mac_addr,
+ .set_framesize = xgene_sgmac_set_frame_size,
.link_state = xgene_enet_link_state
};
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
index 4109776..2a9761b 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
@@ -250,6 +250,12 @@ static void xgene_xgmac_set_mss(struct xgene_enet_pdata *pdata,
xgene_enet_wr_csr(pdata, XG_TSIF_MSS_REG0_ADDR + offset, data);
}
+static void xgene_xgmac_set_frame_size(struct xgene_enet_pdata *pdata, int size)
+{
+ xgene_enet_wr_mac(pdata, HSTMAXFRAME_LENGTH_ADDR,
+ ((((size + 2) >> 2) << 16) | size));
+}
+
static u32 xgene_enet_link_status(struct xgene_enet_pdata *pdata)
{
u32 data;
@@ -474,6 +480,7 @@ static void xgene_enet_link_state(struct work_struct *work)
.rx_disable = xgene_xgmac_rx_disable,
.tx_disable = xgene_xgmac_tx_disable,
.set_mac_addr = xgene_xgmac_set_mac_addr,
+ .set_framesize = xgene_xgmac_set_frame_size,
.set_mss = xgene_xgmac_set_mss,
.link_state = xgene_enet_link_state
};
--
1.9.1
^ permalink raw reply related
* [PATCH net-next 3/8] drivers: net: xgene: Add support for Jumbo frame
From: Iyappan Subramanian @ 2016-12-02 0:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480639304-18757-1-git-send-email-isubramanian@apm.com>
This patch adds support for jumbo frame, by allocating
additional buffer (page) pool and configuring the hardware.
Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
Signed-off-by: Quan Nguyen <qnguyen@apm.com>
---
drivers/net/ethernet/apm/xgene/xgene_enet_hw.c | 3 +
drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 305 ++++++++++++++++++++--
drivers/net/ethernet/apm/xgene/xgene_enet_main.h | 20 +-
drivers/net/ethernet/apm/xgene/xgene_enet_ring2.c | 1 +
drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c | 3 +
drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c | 4 +
6 files changed, 311 insertions(+), 25 deletions(-)
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
index c395df3..fc9010f 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
@@ -679,6 +679,9 @@ static void xgene_gport_shutdown(struct xgene_enet_pdata *pdata)
for (i = 0; i < pdata->rxq_cnt; i++) {
ring = pdata->rx_ring[i]->buf_pool;
pb |= BIT(xgene_enet_get_fpsel(ring->id));
+ ring = pdata->rx_ring[i]->page_pool;
+ if (ring)
+ pb |= BIT(xgene_enet_get_fpsel(ring->id));
}
xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIFPRESET_ADDR, pb);
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index c89acf5..698df27 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -37,6 +37,9 @@ static void xgene_enet_init_bufpool(struct xgene_enet_desc_ring *buf_pool)
struct xgene_enet_raw_desc16 *raw_desc;
int i;
+ if (!buf_pool)
+ return;
+
for (i = 0; i < buf_pool->slots; i++) {
raw_desc = &buf_pool->raw_desc16[i];
@@ -47,6 +50,86 @@ static void xgene_enet_init_bufpool(struct xgene_enet_desc_ring *buf_pool)
}
}
+static u16 xgene_enet_get_data_len(u64 bufdatalen)
+{
+ u16 hw_len, mask;
+
+ hw_len = GET_VAL(BUFDATALEN, bufdatalen);
+
+ if (unlikely(hw_len == 0x7800)) {
+ return 0;
+ } else if (!(hw_len & BIT(14))) {
+ mask = GENMASK(13, 0);
+ return (hw_len & mask) ? (hw_len & mask) : SIZE_16K;
+ } else if (!(hw_len & GENMASK(13, 12))) {
+ mask = GENMASK(11, 0);
+ return (hw_len & mask) ? (hw_len & mask) : SIZE_4K;
+ } else {
+ mask = GENMASK(11, 0);
+ return (hw_len & mask) ? (hw_len & mask) : SIZE_2K;
+ }
+}
+
+static u16 xgene_enet_set_data_len(u32 size)
+{
+ u16 hw_len;
+
+ hw_len = (size == SIZE_4K) ? BIT(14) : 0;
+
+ return hw_len;
+}
+
+static int xgene_enet_refill_pagepool(struct xgene_enet_desc_ring *buf_pool,
+ u32 nbuf)
+{
+ struct xgene_enet_raw_desc16 *raw_desc;
+ struct xgene_enet_pdata *pdata;
+ struct net_device *ndev;
+ dma_addr_t dma_addr;
+ struct device *dev;
+ struct page *page;
+ u32 slots, tail;
+ u16 hw_len;
+ int i;
+
+ if (unlikely(!buf_pool))
+ return 0;
+
+ ndev = buf_pool->ndev;
+ pdata = netdev_priv(ndev);
+ dev = ndev_to_dev(ndev);
+ slots = buf_pool->slots - 1;
+ tail = buf_pool->tail;
+
+ for (i = 0; i < nbuf; i++) {
+ raw_desc = &buf_pool->raw_desc16[tail];
+
+ page = dev_alloc_page();
+ if (unlikely(!page))
+ return -ENOMEM;
+
+ dma_addr = dma_map_page(dev, page, 0,
+ PAGE_SIZE, DMA_FROM_DEVICE);
+ if (unlikely(dma_mapping_error(dev, dma_addr))) {
+ put_page(page);
+ return -ENOMEM;
+ }
+
+ hw_len = xgene_enet_set_data_len(PAGE_SIZE);
+ raw_desc->m1 = cpu_to_le64(SET_VAL(DATAADDR, dma_addr) |
+ SET_VAL(BUFDATALEN, hw_len) |
+ SET_BIT(COHERENT));
+
+ buf_pool->frag_page[tail] = page;
+ tail = (tail + 1) & slots;
+ }
+
+ pdata->ring_ops->wr_cmd(buf_pool, nbuf);
+ buf_pool->tail = tail;
+
+ return 0;
+}
+
static int xgene_enet_refill_bufpool(struct xgene_enet_desc_ring *buf_pool,
u32 nbuf)
{
@@ -64,8 +147,9 @@ static int xgene_enet_refill_bufpool(struct xgene_enet_desc_ring *buf_pool,
ndev = buf_pool->ndev;
dev = ndev_to_dev(buf_pool->ndev);
pdata = netdev_priv(ndev);
+
bufdatalen = BUF_LEN_CODE_2K | (SKB_BUFFER_SIZE & GENMASK(11, 0));
- len = XGENE_ENET_MAX_MTU;
+ len = XGENE_ENET_STD_MTU;
for (i = 0; i < nbuf; i++) {
raw_desc = &buf_pool->raw_desc16[tail];
@@ -122,6 +206,25 @@ static void xgene_enet_delete_bufpool(struct xgene_enet_desc_ring *buf_pool)
}
}
+static void xgene_enet_delete_pagepool(struct xgene_enet_desc_ring *buf_pool)
+{
+ struct device *dev = ndev_to_dev(buf_pool->ndev);
+ dma_addr_t dma_addr;
+ struct page *page;
+ int i;
+
+ /* Free up the buffers held by hardware */
+ for (i = 0; i < buf_pool->slots; i++) {
+ page = buf_pool->frag_page[i];
+ if (page) {
+ dma_addr = buf_pool->frag_dma_addr[i];
+ dma_unmap_page(dev, dma_addr, PAGE_SIZE,
+ DMA_FROM_DEVICE);
+ put_page(page);
+ }
+ }
+}
+
static irqreturn_t xgene_enet_rx_irq(const int irq, void *data)
{
struct xgene_enet_desc_ring *rx_ring = data;
@@ -515,23 +618,66 @@ static void xgene_enet_skip_csum(struct sk_buff *skb)
}
}
+static void xgene_enet_free_pagepool(struct xgene_enet_desc_ring *buf_pool,
+ struct xgene_enet_raw_desc *raw_desc,
+ struct xgene_enet_raw_desc *exp_desc)
+{
+ __le64 *desc = (void *)exp_desc;
+ dma_addr_t dma_addr;
+ struct device *dev;
+ struct page *page;
+ u16 slots, head;
+ u32 frag_size;
+ int i;
+
+ if (!buf_pool || !raw_desc || !exp_desc ||
+ (!GET_VAL(NV, le64_to_cpu(raw_desc->m0))))
+ return;
+
+ dev = ndev_to_dev(buf_pool->ndev);
+ head = buf_pool->head;
+
+ for (i = 0; i < 4; i++) {
+ frag_size = xgene_enet_get_data_len(le64_to_cpu(desc[i ^ 1]));
+ if (!frag_size)
+ break;
+
+ dma_addr = GET_VAL(DATAADDR, le64_to_cpu(desc[i ^ 1]));
+ dma_unmap_page(dev, dma_addr, PAGE_SIZE, DMA_FROM_DEVICE);
+
+ page = buf_pool->frag_page[head];
+ put_page(page);
+
+ buf_pool->frag_page[head] = NULL;
+ head = (head + 1) & slots;
+ }
+ buf_pool->head = head;
+}
+
static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring,
- struct xgene_enet_raw_desc *raw_desc)
+ struct xgene_enet_raw_desc *raw_desc,
+ struct xgene_enet_raw_desc *exp_desc)
{
+ struct xgene_enet_desc_ring *buf_pool, *page_pool;
+ u32 datalen, frag_size, skb_index;
struct net_device *ndev;
- struct device *dev;
- struct xgene_enet_desc_ring *buf_pool;
- u32 datalen, skb_index;
+ dma_addr_t dma_addr;
struct sk_buff *skb;
+ struct device *dev;
+ struct page *page;
+ u16 slots, head;
+ int i, ret = 0;
+ __le64 *desc;
u8 status;
- int ret = 0;
+ bool nv;
ndev = rx_ring->ndev;
dev = ndev_to_dev(rx_ring->ndev);
buf_pool = rx_ring->buf_pool;
+ page_pool = rx_ring->page_pool;
dma_unmap_single(dev, GET_VAL(DATAADDR, le64_to_cpu(raw_desc->m1)),
- XGENE_ENET_MAX_MTU, DMA_FROM_DEVICE);
+ XGENE_ENET_STD_MTU, DMA_FROM_DEVICE);
skb_index = GET_VAL(USERINFO, le64_to_cpu(raw_desc->m0));
skb = buf_pool->rx_skb[skb_index];
buf_pool->rx_skb[skb_index] = NULL;
@@ -541,6 +687,7 @@ static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring,
GET_VAL(LERR, le64_to_cpu(raw_desc->m0));
if (unlikely(status > 2)) {
dev_kfree_skb_any(skb);
+ xgene_enet_free_pagepool(page_pool, raw_desc, exp_desc);
xgene_enet_parse_error(rx_ring, netdev_priv(rx_ring->ndev),
status);
ret = -EIO;
@@ -548,11 +695,44 @@ static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring,
}
/* strip off CRC as HW isn't doing this */
- datalen = GET_VAL(BUFDATALEN, le64_to_cpu(raw_desc->m1));
- datalen = (datalen & DATALEN_MASK) - 4;
- prefetch(skb->data - NET_IP_ALIGN);
+ datalen = xgene_enet_get_data_len(le64_to_cpu(raw_desc->m1));
+
+ nv = GET_VAL(NV, le64_to_cpu(raw_desc->m0));
+ if (!nv)
+ datalen -= 4;
+
skb_put(skb, datalen);
+ prefetch(skb->data - NET_IP_ALIGN);
+
+ if (!nv)
+ goto skip_jumbo;
+
+ slots = page_pool->slots - 1;
+ head = page_pool->head;
+ desc = (void *)exp_desc;
+
+ for (i = 0; i < 4; i++) {
+ frag_size = xgene_enet_get_data_len(le64_to_cpu(desc[i ^ 1]));
+ if (!frag_size)
+ break;
+
+ dma_addr = GET_VAL(DATAADDR, le64_to_cpu(desc[i ^ 1]));
+ dma_unmap_page(dev, dma_addr, PAGE_SIZE, DMA_FROM_DEVICE);
+
+ page = page_pool->frag_page[head];
+ skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, 0,
+ frag_size, PAGE_SIZE);
+
+ datalen += frag_size;
+
+ page_pool->frag_page[head] = NULL;
+ head = (head + 1) & slots;
+ }
+
+ page_pool->head = head;
+ rx_ring->npagepool -= skb_shinfo(skb)->nr_frags;
+skip_jumbo:
skb_checksum_none_assert(skb);
skb->protocol = eth_type_trans(skb, ndev);
if (likely((ndev->features & NETIF_F_IP_CSUM) &&
@@ -563,7 +743,15 @@ static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring,
rx_ring->rx_packets++;
rx_ring->rx_bytes += datalen;
napi_gro_receive(&rx_ring->napi, skb);
+
out:
+ if (rx_ring->npagepool <= 0) {
+ ret = xgene_enet_refill_pagepool(page_pool, NUM_NXTBUFPOOL);
+ rx_ring->npagepool = NUM_NXTBUFPOOL;
+ if (ret)
+ return ret;
+ }
+
if (--rx_ring->nbufpool == 0) {
ret = xgene_enet_refill_bufpool(buf_pool, NUM_BUFPOOL);
rx_ring->nbufpool = NUM_BUFPOOL;
@@ -611,7 +799,7 @@ static int xgene_enet_process_ring(struct xgene_enet_desc_ring *ring,
desc_count++;
}
if (is_rx_desc(raw_desc)) {
- ret = xgene_enet_rx_frame(ring, raw_desc);
+ ret = xgene_enet_rx_frame(ring, raw_desc, exp_desc);
} else {
ret = xgene_enet_tx_completion(ring, raw_desc);
is_completion = true;
@@ -854,7 +1042,7 @@ static void xgene_enet_delete_ring(struct xgene_enet_desc_ring *ring)
static void xgene_enet_delete_desc_rings(struct xgene_enet_pdata *pdata)
{
- struct xgene_enet_desc_ring *buf_pool;
+ struct xgene_enet_desc_ring *buf_pool, *page_pool;
struct xgene_enet_desc_ring *ring;
int i;
@@ -867,18 +1055,28 @@ static void xgene_enet_delete_desc_rings(struct xgene_enet_pdata *pdata)
xgene_enet_delete_ring(ring->cp_ring);
pdata->tx_ring[i] = NULL;
}
+
}
for (i = 0; i < pdata->rxq_cnt; i++) {
ring = pdata->rx_ring[i];
if (ring) {
+ page_pool = ring->page_pool;
+ if (page_pool) {
+ xgene_enet_delete_pagepool(page_pool);
+ xgene_enet_delete_ring(page_pool);
+ pdata->port_ops->clear(pdata, page_pool);
+ }
+
buf_pool = ring->buf_pool;
xgene_enet_delete_bufpool(buf_pool);
xgene_enet_delete_ring(buf_pool);
pdata->port_ops->clear(pdata, buf_pool);
+
xgene_enet_delete_ring(ring);
pdata->rx_ring[i] = NULL;
}
+
}
}
@@ -931,8 +1129,10 @@ static void xgene_enet_free_desc_ring(struct xgene_enet_desc_ring *ring)
static void xgene_enet_free_desc_rings(struct xgene_enet_pdata *pdata)
{
+ struct xgene_enet_desc_ring *page_pool;
struct device *dev = &pdata->pdev->dev;
struct xgene_enet_desc_ring *ring;
+ void *p;
int i;
for (i = 0; i < pdata->txq_cnt; i++) {
@@ -940,10 +1140,13 @@ static void xgene_enet_free_desc_rings(struct xgene_enet_pdata *pdata)
if (ring) {
if (ring->cp_ring && ring->cp_ring->cp_skb)
devm_kfree(dev, ring->cp_ring->cp_skb);
+
if (ring->cp_ring && pdata->cq_cnt)
xgene_enet_free_desc_ring(ring->cp_ring);
+
xgene_enet_free_desc_ring(ring);
}
+
}
for (i = 0; i < pdata->rxq_cnt; i++) {
@@ -952,8 +1155,21 @@ static void xgene_enet_free_desc_rings(struct xgene_enet_pdata *pdata)
if (ring->buf_pool) {
if (ring->buf_pool->rx_skb)
devm_kfree(dev, ring->buf_pool->rx_skb);
+
xgene_enet_free_desc_ring(ring->buf_pool);
}
+
+ page_pool = ring->page_pool;
+ if (page_pool) {
+ p = page_pool->frag_page;
+ if (p)
+ devm_kfree(dev, p);
+
+ p = page_pool->frag_dma_addr;
+ if (p)
+ devm_kfree(dev, p);
+ }
+
xgene_enet_free_desc_ring(ring);
}
}
@@ -1071,19 +1287,20 @@ static u8 xgene_start_cpu_bufnum(struct xgene_enet_pdata *pdata)
static int xgene_enet_create_desc_rings(struct net_device *ndev)
{
- struct xgene_enet_pdata *pdata = netdev_priv(ndev);
- struct device *dev = ndev_to_dev(ndev);
struct xgene_enet_desc_ring *rx_ring, *tx_ring, *cp_ring;
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+ struct xgene_enet_desc_ring *page_pool = NULL;
struct xgene_enet_desc_ring *buf_pool = NULL;
- enum xgene_ring_owner owner;
- dma_addr_t dma_exp_bufs;
- u8 cpu_bufnum;
+ struct device *dev = ndev_to_dev(ndev);
u8 eth_bufnum = pdata->eth_bufnum;
u8 bp_bufnum = pdata->bp_bufnum;
u16 ring_num = pdata->ring_num;
+ enum xgene_ring_owner owner;
+ dma_addr_t dma_exp_bufs;
+ u16 ring_id, slots;
__le64 *exp_bufs;
- u16 ring_id;
int i, ret, size;
+ u8 cpu_bufnum;
cpu_bufnum = xgene_start_cpu_bufnum(pdata);
@@ -1103,7 +1320,7 @@ static int xgene_enet_create_desc_rings(struct net_device *ndev)
owner = xgene_derive_ring_owner(pdata);
ring_id = xgene_enet_get_ring_id(owner, bp_bufnum++);
buf_pool = xgene_enet_create_desc_ring(ndev, ring_num++,
- RING_CFGSIZE_2KB,
+ RING_CFGSIZE_16KB,
ring_id);
if (!buf_pool) {
ret = -ENOMEM;
@@ -1111,7 +1328,7 @@ static int xgene_enet_create_desc_rings(struct net_device *ndev)
}
rx_ring->nbufpool = NUM_BUFPOOL;
- rx_ring->buf_pool = buf_pool;
+ rx_ring->npagepool = NUM_NXTBUFPOOL;
rx_ring->irq = pdata->irqs[i];
buf_pool->rx_skb = devm_kcalloc(dev, buf_pool->slots,
sizeof(struct sk_buff *),
@@ -1124,6 +1341,42 @@ static int xgene_enet_create_desc_rings(struct net_device *ndev)
buf_pool->dst_ring_num = xgene_enet_dst_ring_num(buf_pool);
rx_ring->buf_pool = buf_pool;
pdata->rx_ring[i] = rx_ring;
+
+ if ((pdata->enet_id == XGENE_ENET1 && pdata->rxq_cnt > 4) ||
+ (pdata->enet_id == XGENE_ENET2 && pdata->rxq_cnt > 16)) {
+ break;
+ }
+
+ /* allocate next buffer pool for jumbo packets */
+ owner = xgene_derive_ring_owner(pdata);
+ ring_id = xgene_enet_get_ring_id(owner, bp_bufnum++);
+ page_pool = xgene_enet_create_desc_ring(ndev, ring_num++,
+ RING_CFGSIZE_16KB,
+ ring_id);
+ if (!page_pool) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ slots = page_pool->slots;
+ page_pool->frag_page = devm_kcalloc(dev, slots,
+ sizeof(struct page *),
+ GFP_KERNEL);
+ if (!page_pool->frag_page) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ page_pool->frag_dma_addr = devm_kcalloc(dev, slots,
+ sizeof(dma_addr_t),
+ GFP_KERNEL);
+ if (!page_pool->frag_dma_addr) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ page_pool->dst_ring_num = xgene_enet_dst_ring_num(page_pool);
+ rx_ring->page_pool = page_pool;
}
for (i = 0; i < pdata->txq_cnt; i++) {
@@ -1523,6 +1776,7 @@ static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
struct xgene_enet_desc_ring *buf_pool;
u16 dst_ring_num, ring_id;
int i, ret;
+ u32 count;
ret = pdata->port_ops->reset(pdata);
if (ret)
@@ -1538,9 +1792,18 @@ static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
for (i = 0; i < pdata->rxq_cnt; i++) {
buf_pool = pdata->rx_ring[i]->buf_pool;
xgene_enet_init_bufpool(buf_pool);
- ret = xgene_enet_refill_bufpool(buf_pool, pdata->rx_buff_cnt);
+ page_pool = pdata->rx_ring[i]->page_pool;
+ xgene_enet_init_bufpool(page_pool);
+
+ count = pdata->rx_buff_cnt;
+ ret = xgene_enet_refill_bufpool(buf_pool, count);
if (ret)
goto err;
+
+ ret = xgene_enet_refill_pagepool(page_pool, count);
+ if (ret)
+ goto err;
+
}
dst_ring_num = xgene_enet_dst_ring_num(pdata->rx_ring[0]);
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
index 1fe3942..023ed76 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
@@ -41,11 +41,14 @@
#include "../../../phy/mdio-xgene.h"
#define XGENE_DRV_VERSION "v1.0"
-#define XGENE_ENET_MAX_MTU 1536
-#define SKB_BUFFER_SIZE (XGENE_ENET_MAX_MTU - NET_IP_ALIGN)
+#define XGENE_ENET_STD_MTU 1536
+#define XGENE_ENET_MAX_MTU 9600
+#define SKB_BUFFER_SIZE (XGENE_ENET_STD_MTU - NET_IP_ALIGN)
+
#define BUFLEN_16K (16 * 1024)
-#define NUM_PKT_BUF 64
+#define NUM_PKT_BUF 1024
#define NUM_BUFPOOL 32
+#define NUM_NXTBUFPOOL 8
#define MAX_EXP_BUFFS 256
#define NUM_MSS_REG 4
#define XGENE_MIN_ENET_FRAME_SIZE 60
@@ -88,6 +91,12 @@ enum xgene_enet_id {
XGENE_ENET2
};
+enum xgene_enet_buf_len {
+ SIZE_2K = 2048,
+ SIZE_4K = 4096,
+ SIZE_16K = 16384
+};
+
/* software context of a descriptor ring */
struct xgene_enet_desc_ring {
struct net_device *ndev;
@@ -107,11 +116,14 @@ struct xgene_enet_desc_ring {
dma_addr_t irq_mbox_dma;
void *irq_mbox_addr;
u16 dst_ring_num;
- u8 nbufpool;
+ u16 nbufpool;
+ int npagepool;
u8 index;
+ u32 flags;
struct sk_buff *(*rx_skb);
struct sk_buff *(*cp_skb);
dma_addr_t *frag_dma_addr;
+ struct page *(*frag_page);
enum xgene_enet_ring_cfgsize cfgsize;
struct xgene_enet_desc_ring *cp_ring;
struct xgene_enet_desc_ring *buf_pool;
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_ring2.c b/drivers/net/ethernet/apm/xgene/xgene_enet_ring2.c
index af51dd5..4ff40559 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_ring2.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_ring2.c
@@ -119,6 +119,7 @@ static void xgene_enet_set_ring_id(struct xgene_enet_desc_ring *ring)
ring_id_buf = (ring->num << 9) & GENMASK(18, 9);
ring_id_buf |= PREFETCH_BUF_EN;
+
if (is_bufpool)
ring_id_buf |= IS_BUFFER_POOL;
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
index 82b7a5e..a10ab64 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
@@ -536,6 +536,9 @@ static void xgene_enet_shutdown(struct xgene_enet_pdata *p)
for (i = 0; i < p->rxq_cnt; i++) {
ring = p->rx_ring[i]->buf_pool;
pb |= BIT(xgene_enet_get_fpsel(ring->id));
+ ring = p->rx_ring[i]->page_pool;
+ if (ring)
+ pb |= BIT(xgene_enet_get_fpsel(ring->id));
}
xgene_enet_wr_ring_if(p, ENET_CFGSSQMIFPRESET_ADDR, pb);
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
index e4adba6..4109776 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
@@ -367,6 +367,7 @@ static void xgene_enet_xgcle_bypass(struct xgene_enet_pdata *pdata,
CFG_CLE_FPSEL0_SET(&cb, fpsel);
CFG_CLE_NXTFPSEL0_SET(&cb, nxtfpsel);
xgene_enet_wr_csr(pdata, XCLE_BYPASS_REG1_ADDR, cb);
+ pr_info("+ cle_bypass: fpsel: %d nxtfpsel: %d\n", fpsel, nxtfpsel);
}
static void xgene_enet_shutdown(struct xgene_enet_pdata *pdata)
@@ -380,6 +381,9 @@ static void xgene_enet_shutdown(struct xgene_enet_pdata *pdata)
for (i = 0; i < pdata->rxq_cnt; i++) {
ring = pdata->rx_ring[i]->buf_pool;
pb |= BIT(xgene_enet_get_fpsel(ring->id));
+ ring = pdata->rx_ring[i]->page_pool;
+ if (ring)
+ pb |= BIT(xgene_enet_get_fpsel(ring->id));
}
xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIFPRESET_ADDR, pb);
--
1.9.1
^ permalink raw reply related
* [PATCH net-next 2/8] drivers: net: xgene: Configure classifier with pagepool
From: Iyappan Subramanian @ 2016-12-02 0:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480639304-18757-1-git-send-email-isubramanian@apm.com>
This patch configures classifier with the pagepool information.
Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
Signed-off-by: Quan Nguyen <qnguyen@apm.com>
---
drivers/net/ethernet/apm/xgene/xgene_enet_cle.c | 16 ++++++++++++++--
drivers/net/ethernet/apm/xgene/xgene_enet_cle.h | 2 ++
drivers/net/ethernet/apm/xgene/xgene_enet_hw.c | 7 +++++--
drivers/net/ethernet/apm/xgene/xgene_enet_hw.h | 6 ++++--
drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 11 +++++++++--
drivers/net/ethernet/apm/xgene/xgene_enet_main.h | 3 ++-
drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c | 9 ++++++---
drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c | 7 +++++--
8 files changed, 47 insertions(+), 14 deletions(-)
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c b/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c
index 7aac0fb..caa55bd 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c
@@ -52,6 +52,7 @@ static void xgene_cle_dbptr_to_hw(struct xgene_enet_pdata *pdata,
{
buf[0] = SET_VAL(CLE_DROP, dbptr->drop);
buf[4] = SET_VAL(CLE_FPSEL, dbptr->fpsel) |
+ SET_VAL(CLE_NFPSEL, dbptr->nxtfpsel) |
SET_VAL(CLE_DSTQIDL, dbptr->dstqid);
buf[5] = SET_VAL(CLE_DSTQIDH, (u32)dbptr->dstqid >> CLE_DSTQIDL_LEN) |
@@ -349,8 +350,12 @@ static int xgene_cle_set_rss_idt(struct xgene_enet_pdata *pdata)
fpsel = xgene_enet_get_fpsel(pool_id);
dstqid = xgene_enet_dst_ring_num(pdata->rx_ring[idx]);
nfpsel = 0;
- idt_reg = 0;
+ if (pdata->rx_ring[idx]->page_pool) {
+ pool_id = pdata->rx_ring[idx]->page_pool->id;
+ nfpsel = xgene_enet_get_fpsel(pool_id);
+ }
+ idt_reg = 0;
xgene_cle_idt_to_hw(pdata, dstqid, fpsel, nfpsel, &idt_reg);
ret = xgene_cle_dram_wr(&pdata->cle, &idt_reg, 1, i,
RSS_IDT, CLE_CMD_WR);
@@ -400,9 +405,9 @@ static int xgene_cle_setup_rss(struct xgene_enet_pdata *pdata)
static int xgene_enet_cle_init(struct xgene_enet_pdata *pdata)
{
struct xgene_enet_cle *enet_cle = &pdata->cle;
+ u32 def_qid, def_fpsel, def_nxtfpsel, pool_id;
struct xgene_cle_dbptr dbptr[DB_MAX_PTRS];
struct xgene_cle_ptree_branch *br;
- u32 def_qid, def_fpsel, pool_id;
struct xgene_cle_ptree *ptree;
struct xgene_cle_ptree_kn kn;
int ret;
@@ -707,13 +712,20 @@ static int xgene_enet_cle_init(struct xgene_enet_pdata *pdata)
def_qid = xgene_enet_dst_ring_num(pdata->rx_ring[0]);
pool_id = pdata->rx_ring[0]->buf_pool->id;
def_fpsel = xgene_enet_get_fpsel(pool_id);
+ def_nxtfpsel = 0;
+ if (pdata->rx_ring[0]->page_pool) {
+ pool_id = pdata->rx_ring[0]->page_pool->id;
+ def_nxtfpsel = xgene_enet_get_fpsel(pool_id);
+ }
memset(dbptr, 0, sizeof(struct xgene_cle_dbptr) * DB_MAX_PTRS);
dbptr[DB_RES_ACCEPT].fpsel = def_fpsel;
+ dbptr[DB_RES_ACCEPT].nxtfpsel = def_nxtfpsel;
dbptr[DB_RES_ACCEPT].dstqid = def_qid;
dbptr[DB_RES_ACCEPT].cle_priority = 1;
dbptr[DB_RES_DEF].fpsel = def_fpsel;
+ dbptr[DB_RES_DEF].nxtfpsel = def_nxtfpsel;
dbptr[DB_RES_DEF].dstqid = def_qid;
dbptr[DB_RES_DEF].cle_priority = 7;
xgene_cle_setup_def_dbptr(pdata, enet_cle, &dbptr[DB_RES_DEF],
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_cle.h b/drivers/net/ethernet/apm/xgene/xgene_enet_cle.h
index 9ac9f8e..903be0c 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_cle.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_cle.h
@@ -91,6 +91,8 @@
#define CLE_DSTQIDH_LEN 5
#define CLE_FPSEL_POS 21
#define CLE_FPSEL_LEN 4
+#define CLE_NFPSEL_POS 17
+#define CLE_NFPSEL_LEN 4
#define CLE_PRIORITY_POS 5
#define CLE_PRIORITY_LEN 3
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
index 1007074..c395df3 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
@@ -550,12 +550,14 @@ static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *pdata)
}
static void xgene_enet_cle_bypass(struct xgene_enet_pdata *pdata,
- u32 dst_ring_num, u16 bufpool_id)
+ u32 dst_ring_num, u16 bufpool_id,
+ u16 nxtbufpool_id)
{
u32 cb;
- u32 fpsel;
+ u32 fpsel, nxtfpsel;
fpsel = xgene_enet_get_fpsel(bufpool_id);
+ nxtfpsel = xgene_enet_get_fpsel(nxtbufpool_id);
xgene_enet_rd_csr(pdata, CLE_BYPASS_REG0_0_ADDR, &cb);
cb |= CFG_CLE_BYPASS_EN0;
@@ -565,6 +567,7 @@ static void xgene_enet_cle_bypass(struct xgene_enet_pdata *pdata,
xgene_enet_rd_csr(pdata, CLE_BYPASS_REG1_0_ADDR, &cb);
CFG_CLE_DSTQID0_SET(&cb, dst_ring_num);
CFG_CLE_FPSEL0_SET(&cb, fpsel);
+ CFG_CLE_NXTFPSEL0_SET(&cb, nxtfpsel);
xgene_enet_wr_csr(pdata, CLE_BYPASS_REG1_0_ADDR, cb);
}
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
index e73cbb1..bd6cb6c 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
@@ -165,10 +165,12 @@ enum xgene_enet_rm {
#define CFG_CLE_IP_PROTOCOL0_SET(dst, val) xgene_set_bits(dst, val, 16, 2)
#define CFG_CLE_DSTQID0_SET(dst, val) xgene_set_bits(dst, val, 0, 12)
#define CFG_CLE_FPSEL0_SET(dst, val) xgene_set_bits(dst, val, 16, 4)
+#define CFG_CLE_NXTFPSEL0_SET(dst, val) xgene_set_bits(dst, val, 20, 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 CFG_CLE_DSTQID0(val) ((val) & GENMASK(11, 0))
+#define CFG_CLE_FPSEL0(val) (((val) << 16) & GENMASK(19, 16))
+#define CFG_CLE_NXTFPSEL0(val) (((val) << 20) & GENMASK(23, 20))
#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 1352b52..c89acf5 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -1518,9 +1518,10 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
{
struct xgene_enet_cle *enet_cle = &pdata->cle;
+ struct xgene_enet_desc_ring *page_pool;
struct net_device *ndev = pdata->ndev;
struct xgene_enet_desc_ring *buf_pool;
- u16 dst_ring_num;
+ u16 dst_ring_num, ring_id;
int i, ret;
ret = pdata->port_ops->reset(pdata);
@@ -1558,8 +1559,14 @@ static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
netdev_err(ndev, "Preclass Tree init error\n");
goto err;
}
+
} else {
- pdata->port_ops->cle_bypass(pdata, dst_ring_num, buf_pool->id);
+ dst_ring_num = xgene_enet_dst_ring_num(pdata->rx_ring[0]);
+ buf_pool = pdata->rx_ring[0]->buf_pool;
+ page_pool = pdata->rx_ring[0]->page_pool;
+ ring_id = (page_pool) ? page_pool->id : 0;
+ pdata->port_ops->cle_bypass(pdata, dst_ring_num,
+ buf_pool->id, ring_id);
}
pdata->phy_speed = SPEED_UNKNOWN;
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
index 011965b..1fe3942 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
@@ -115,6 +115,7 @@ struct xgene_enet_desc_ring {
enum xgene_enet_ring_cfgsize cfgsize;
struct xgene_enet_desc_ring *cp_ring;
struct xgene_enet_desc_ring *buf_pool;
+ struct xgene_enet_desc_ring *page_pool;
struct napi_struct napi;
union {
void *desc_addr;
@@ -152,7 +153,7 @@ struct xgene_port_ops {
void (*clear)(struct xgene_enet_pdata *pdata,
struct xgene_enet_desc_ring *ring);
void (*cle_bypass)(struct xgene_enet_pdata *pdata,
- u32 dst_ring_num, u16 bufpool_id);
+ u32 dst_ring_num, u16 bufpool_id, u16 nxtbufpool_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 8e4209c..82b7a5e 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
@@ -484,11 +484,12 @@ static int xgene_enet_reset(struct xgene_enet_pdata *p)
}
static void xgene_enet_cle_bypass(struct xgene_enet_pdata *p,
- u32 dst_ring_num, u16 bufpool_id)
+ u32 dst_ring_num, u16 bufpool_id,
+ u16 nxtbufpool_id)
{
- u32 data, fpsel;
u32 cle_bypass_reg0, cle_bypass_reg1;
u32 offset = p->port_id * MAC_OFFSET;
+ u32 data, fpsel, nxtfpsel;
if (p->enet_id == XGENE_ENET1) {
cle_bypass_reg0 = CLE_BYPASS_REG0_0_ADDR;
@@ -502,7 +503,9 @@ static void xgene_enet_cle_bypass(struct xgene_enet_pdata *p,
xgene_enet_wr_csr(p, cle_bypass_reg0 + offset, data);
fpsel = xgene_enet_get_fpsel(bufpool_id);
- data = CFG_CLE_DSTQID0(dst_ring_num) | CFG_CLE_FPSEL0(fpsel);
+ nxtfpsel = xgene_enet_get_fpsel(nxtbufpool_id);
+ data = CFG_CLE_DSTQID0(dst_ring_num) | CFG_CLE_FPSEL0(fpsel) |
+ CFG_CLE_NXTFPSEL0(nxtfpsel);
xgene_enet_wr_csr(p, cle_bypass_reg1 + offset, data);
}
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
index f97e599..e4adba6 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
@@ -350,9 +350,10 @@ static int xgene_enet_reset(struct xgene_enet_pdata *pdata)
}
static void xgene_enet_xgcle_bypass(struct xgene_enet_pdata *pdata,
- u32 dst_ring_num, u16 bufpool_id)
+ u32 dst_ring_num, u16 bufpool_id,
+ u16 nxtbufpool_id)
{
- u32 cb, fpsel;
+ u32 cb, fpsel, nxtfpsel;
xgene_enet_rd_csr(pdata, XCLE_BYPASS_REG0_ADDR, &cb);
cb |= CFG_CLE_BYPASS_EN0;
@@ -360,9 +361,11 @@ static void xgene_enet_xgcle_bypass(struct xgene_enet_pdata *pdata,
xgene_enet_wr_csr(pdata, XCLE_BYPASS_REG0_ADDR, cb);
fpsel = xgene_enet_get_fpsel(bufpool_id);
+ nxtfpsel = xgene_enet_get_fpsel(nxtbufpool_id);
xgene_enet_rd_csr(pdata, XCLE_BYPASS_REG1_ADDR, &cb);
CFG_CLE_DSTQID0_SET(&cb, dst_ring_num);
CFG_CLE_FPSEL0_SET(&cb, fpsel);
+ CFG_CLE_NXTFPSEL0_SET(&cb, nxtfpsel);
xgene_enet_wr_csr(pdata, XCLE_BYPASS_REG1_ADDR, cb);
}
--
1.9.1
^ permalink raw reply related
* [PATCH net-next 1/8] drivers: net: xgene: Add helper function
From: Iyappan Subramanian @ 2016-12-02 0:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480639304-18757-1-git-send-email-isubramanian@apm.com>
This is a prepartion patch and adds xgene_enet_get_fpsel() helper
function to get buffer pool number.
Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
Signed-off-by: Quan Nguyen <qnguyen@apm.com>
---
drivers/net/ethernet/apm/xgene/xgene_enet_cle.c | 4 ++--
drivers/net/ethernet/apm/xgene/xgene_enet_hw.c | 19 +++++++------------
drivers/net/ethernet/apm/xgene/xgene_enet_hw.h | 8 ++++++++
drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c | 20 +++++++-------------
drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c | 20 +++++++-------------
5 files changed, 31 insertions(+), 40 deletions(-)
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c b/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c
index 23d72af..7aac0fb 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c
@@ -346,7 +346,7 @@ static int xgene_cle_set_rss_idt(struct xgene_enet_pdata *pdata)
for (i = 0; i < XGENE_CLE_IDT_ENTRIES; i++) {
idx = i % pdata->rxq_cnt;
pool_id = pdata->rx_ring[idx]->buf_pool->id;
- fpsel = xgene_enet_ring_bufnum(pool_id) - 0x20;
+ fpsel = xgene_enet_get_fpsel(pool_id);
dstqid = xgene_enet_dst_ring_num(pdata->rx_ring[idx]);
nfpsel = 0;
idt_reg = 0;
@@ -706,7 +706,7 @@ static int xgene_enet_cle_init(struct xgene_enet_pdata *pdata)
def_qid = xgene_enet_dst_ring_num(pdata->rx_ring[0]);
pool_id = pdata->rx_ring[0]->buf_pool->id;
- def_fpsel = xgene_enet_ring_bufnum(pool_id) - 0x20;
+ def_fpsel = xgene_enet_get_fpsel(pool_id);
memset(dbptr, 0, sizeof(struct xgene_cle_dbptr) * DB_MAX_PTRS);
dbptr[DB_RES_ACCEPT].fpsel = def_fpsel;
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
index 5390ae8..1007074 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
@@ -555,7 +555,7 @@ static void xgene_enet_cle_bypass(struct xgene_enet_pdata *pdata,
u32 cb;
u32 fpsel;
- fpsel = xgene_enet_ring_bufnum(bufpool_id) - 0x20;
+ fpsel = xgene_enet_get_fpsel(bufpool_id);
xgene_enet_rd_csr(pdata, CLE_BYPASS_REG0_0_ADDR, &cb);
cb |= CFG_CLE_BYPASS_EN0;
@@ -652,16 +652,14 @@ static int xgene_enet_reset(struct xgene_enet_pdata *pdata)
static void xgene_enet_clear(struct xgene_enet_pdata *pdata,
struct xgene_enet_desc_ring *ring)
{
- u32 addr, val, data;
-
- val = xgene_enet_ring_bufnum(ring->id);
+ u32 addr, data;
if (xgene_enet_is_bufpool(ring->id)) {
addr = ENET_CFGSSQMIFPRESET_ADDR;
- data = BIT(val - 0x20);
+ data = BIT(xgene_enet_get_fpsel(ring->id));
} else {
addr = ENET_CFGSSQMIWQRESET_ADDR;
- data = BIT(val);
+ data = BIT(xgene_enet_ring_bufnum(ring->id));
}
xgene_enet_wr_ring_if(pdata, addr, data);
@@ -671,24 +669,21 @@ static void xgene_gport_shutdown(struct xgene_enet_pdata *pdata)
{
struct device *dev = &pdata->pdev->dev;
struct xgene_enet_desc_ring *ring;
- u32 pb, val;
+ u32 pb;
int i;
pb = 0;
for (i = 0; i < pdata->rxq_cnt; i++) {
ring = pdata->rx_ring[i]->buf_pool;
+ pb |= BIT(xgene_enet_get_fpsel(ring->id));
- val = xgene_enet_ring_bufnum(ring->id);
- pb |= BIT(val - 0x20);
}
xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIFPRESET_ADDR, pb);
pb = 0;
for (i = 0; i < pdata->txq_cnt; i++) {
ring = pdata->tx_ring[i];
-
- val = xgene_enet_ring_bufnum(ring->id);
- pb |= BIT(val);
+ pb |= BIT(xgene_enet_ring_bufnum(ring->id));
}
xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIWQRESET_ADDR, pb);
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
index 06e598c..e73cbb1 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
@@ -346,6 +346,14 @@ static inline bool xgene_enet_is_bufpool(u16 id)
return ((id & RING_BUFNUM_MASK) >= 0x20) ? true : false;
}
+static inline u8 xgene_enet_get_fpsel(u16 id)
+{
+ if (xgene_enet_is_bufpool(id))
+ return xgene_enet_ring_bufnum(id) - RING_BUFNUM_BUFPOOL;
+
+ return 0;
+}
+
static inline u16 xgene_enet_get_numslots(u16 id, u32 size)
{
bool is_bufpool = xgene_enet_is_bufpool(id);
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
index d12e9cb..8e4209c 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
@@ -501,7 +501,7 @@ static void xgene_enet_cle_bypass(struct xgene_enet_pdata *p,
data = CFG_CLE_BYPASS_EN0;
xgene_enet_wr_csr(p, cle_bypass_reg0 + offset, data);
- fpsel = xgene_enet_ring_bufnum(bufpool_id) - 0x20;
+ fpsel = xgene_enet_get_fpsel(bufpool_id);
data = CFG_CLE_DSTQID0(dst_ring_num) | CFG_CLE_FPSEL0(fpsel);
xgene_enet_wr_csr(p, cle_bypass_reg1 + offset, data);
}
@@ -509,16 +509,14 @@ static void xgene_enet_cle_bypass(struct xgene_enet_pdata *p,
static void xgene_enet_clear(struct xgene_enet_pdata *pdata,
struct xgene_enet_desc_ring *ring)
{
- u32 addr, val, data;
-
- val = xgene_enet_ring_bufnum(ring->id);
+ u32 addr, data;
if (xgene_enet_is_bufpool(ring->id)) {
addr = ENET_CFGSSQMIFPRESET_ADDR;
- data = BIT(val - 0x20);
+ data = BIT(xgene_enet_get_fpsel(ring->id));
} else {
addr = ENET_CFGSSQMIWQRESET_ADDR;
- data = BIT(val);
+ data = BIT(xgene_enet_ring_bufnum(ring->id));
}
xgene_enet_wr_ring_if(pdata, addr, data);
@@ -528,24 +526,20 @@ static void xgene_enet_shutdown(struct xgene_enet_pdata *p)
{
struct device *dev = &p->pdev->dev;
struct xgene_enet_desc_ring *ring;
- u32 pb, val;
+ u32 pb;
int i;
pb = 0;
for (i = 0; i < p->rxq_cnt; i++) {
ring = p->rx_ring[i]->buf_pool;
-
- val = xgene_enet_ring_bufnum(ring->id);
- pb |= BIT(val - 0x20);
+ pb |= BIT(xgene_enet_get_fpsel(ring->id));
}
xgene_enet_wr_ring_if(p, ENET_CFGSSQMIFPRESET_ADDR, pb);
pb = 0;
for (i = 0; i < p->txq_cnt; i++) {
ring = p->tx_ring[i];
-
- val = xgene_enet_ring_bufnum(ring->id);
- pb |= BIT(val);
+ pb |= BIT(xgene_enet_ring_bufnum(ring->id));
}
xgene_enet_wr_ring_if(p, ENET_CFGSSQMIWQRESET_ADDR, pb);
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
index d1758b0..f97e599 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
@@ -359,7 +359,7 @@ static void xgene_enet_xgcle_bypass(struct xgene_enet_pdata *pdata,
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;
+ fpsel = xgene_enet_get_fpsel(bufpool_id);
xgene_enet_rd_csr(pdata, XCLE_BYPASS_REG1_ADDR, &cb);
CFG_CLE_DSTQID0_SET(&cb, dst_ring_num);
CFG_CLE_FPSEL0_SET(&cb, fpsel);
@@ -370,24 +370,20 @@ static void xgene_enet_shutdown(struct xgene_enet_pdata *pdata)
{
struct device *dev = &pdata->pdev->dev;
struct xgene_enet_desc_ring *ring;
- u32 pb, val;
+ u32 pb;
int i;
pb = 0;
for (i = 0; i < pdata->rxq_cnt; i++) {
ring = pdata->rx_ring[i]->buf_pool;
-
- val = xgene_enet_ring_bufnum(ring->id);
- pb |= BIT(val - 0x20);
+ pb |= BIT(xgene_enet_get_fpsel(ring->id));
}
xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIFPRESET_ADDR, pb);
pb = 0;
for (i = 0; i < pdata->txq_cnt; i++) {
ring = pdata->tx_ring[i];
-
- val = xgene_enet_ring_bufnum(ring->id);
- pb |= BIT(val);
+ pb |= BIT(xgene_enet_ring_bufnum(ring->id));
}
xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIWQRESET_ADDR, pb);
@@ -400,16 +396,14 @@ static void xgene_enet_shutdown(struct xgene_enet_pdata *pdata)
static void xgene_enet_clear(struct xgene_enet_pdata *pdata,
struct xgene_enet_desc_ring *ring)
{
- u32 addr, val, data;
-
- val = xgene_enet_ring_bufnum(ring->id);
+ u32 addr, data;
if (xgene_enet_is_bufpool(ring->id)) {
addr = ENET_CFGSSQMIFPRESET_ADDR;
- data = BIT(val - 0x20);
+ data = BIT(xgene_enet_get_fpsel(ring->id));
} else {
addr = ENET_CFGSSQMIWQRESET_ADDR;
- data = BIT(val);
+ data = BIT(xgene_enet_ring_bufnum(ring->id));
}
xgene_enet_wr_ring_if(pdata, addr, data);
--
1.9.1
^ permalink raw reply related
* [PATCH net-next 0/8] drivers: net: xgene: Add Jumbo and Pause frame support
From: Iyappan Subramanian @ 2016-12-02 0:41 UTC (permalink / raw)
To: linux-arm-kernel
This patch set adds,
1. Jumbo frame support
2. Pause frame based flow control
and fixes RSS for non-TCP/UDP packets.
Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
---
Iyappan Subramanian (8):
drivers: net: xgene: Add helper function
drivers: net: xgene: Configure classifier with pagepool
drivers: net: xgene: Add support for Jumbo frame
drivers: net: xgene: Add change_mtu function
drivers: net: xgene: fix: RSS for non-TCP/UDP
drivers: net: xgene: Add flow control configuration
drivers: net: xgene: Add flow control initialization
drivers: net: xgene: ethtool: Add get/set_pauseparam
drivers/net/ethernet/apm/xgene/xgene_enet_cle.c | 110 ++++++-
drivers/net/ethernet/apm/xgene/xgene_enet_cle.h | 3 +
.../net/ethernet/apm/xgene/xgene_enet_ethtool.c | 70 +++++
drivers/net/ethernet/apm/xgene/xgene_enet_hw.c | 140 ++++++++-
drivers/net/ethernet/apm/xgene/xgene_enet_hw.h | 27 +-
drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 336 +++++++++++++++++++--
drivers/net/ethernet/apm/xgene/xgene_enet_main.h | 30 +-
drivers/net/ethernet/apm/xgene/xgene_enet_ring2.c | 1 +
drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c | 146 +++++++--
drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c | 121 +++++++-
drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h | 9 +
11 files changed, 895 insertions(+), 98 deletions(-)
--
1.9.1
^ permalink raw reply
* [PATCH v2] PCI: Add information about describing PCI in ACPI
From: Rafael J. Wysocki @ 2016-12-02 0:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161201232732.GB17948@bhelgaas-glaptop.roam.corp.google.com>
On Fri, Dec 2, 2016 at 12:27 AM, Bjorn Helgaas <helgaas@kernel.org> wrote:
> On Thu, Dec 01, 2016 at 11:37:39PM +0100, Rafael J. Wysocki wrote:
>> On Thursday, December 01, 2016 04:36:04 PM Bjorn Helgaas wrote:
>> > On Tue, Nov 29, 2016 at 03:39:48PM -0600, Bjorn Helgaas wrote:
>> > > Here's another stab at this writeup. I'd appreciate any comments!
>> > >
>> > > Changes from v1 to v2:
>> > > - Consumer/Producer is defined for Extended Address Space descriptors;
>> > > should be ignored for QWord/DWord/Word Address Space descriptors
>> > > - New arches may use Extended Address Space descriptors in PNP0A03 for
>> > > bridge registers, including ECAM (if the arch adds support for this)
>> > > - Add more details about MCFG and _CBA (Lv's suggestion)
>> > > - Incorporate Rafael's suggestions
>> > >
>> > > ---
>> > >
>> > > Bjorn Helgaas (1):
>> > > PCI: Add information about describing PCI in ACPI
>> > >
>> > >
>> > > Documentation/PCI/00-INDEX | 2
>> > > Documentation/PCI/acpi-info.txt | 180 +++++++++++++++++++++++++++++++++++++++
>> > > 2 files changed, 182 insertions(+)
>> > > create mode 100644 Documentation/PCI/acpi-info.txt
>> >
>> > It's very late in the cycle, but I'm considering trying to squeeze
>> > this into v4.9 on the grounds that:
>> >
>> > - It's only a documentation change and can't break anything, and
>> >
>> > - Distributing it more widely may help the arm64 firmware ecosystem
>> >
>> > But I don't want to disseminate misleading or incorrect information,
>> > so if it needs clarification or wordsmithing, or even just maturation,
>> > I'll wait until v4.10.
>> >
>> > The Consumer/Producer stuff, in particular, doesn't seem 100% settled
>> > yet. Your thoughts, and especially your improvements, are welcome!
>>
>> Well, what's the drawback if it doesn't go into 4.9?
>
> Only that it's not as easily accessible. ARM64 ACPI firmware is brand
> new. Neither the firmware nor the kernel developers, nor even the
> hardware designers, have the benefit of all the x86/ia64 history, so I
> wrote this to try to come to a common understanding of what Linux
> expects.
>
> The first generation of ARM64 hardware is already in the field, and it
> has teething problems in hardware, firmware, and kernel. For example,
> the current MCFG quirk situation: the ECAM hardware doesn't work quite
> per spec, the ACPI firmware doesn't describe the address space
> completely, and we don't really have consensus on how the firmware
> should communicate register space to the kernel.
>
> We're hoping the second generation can fix some of these problems, and
> I think this is the time to try to influence that.
Well, I would be super-careful if I were you, then. :-)
I'm not sure if squeezing it into 4.9.0 buys you anything here. If
you get it into 4.10-rc, you can request -stable to pick it up (at
least in principle) and then it will show up in 4.9.y at one point
which should suffice I suppose?
Thanks,
Rafael
^ permalink raw reply
* [resend v2: PATCH 1/2] dt-bindings: Document the hi3660 reset bindings
From: zhangfei @ 2016-12-02 0:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <3900806.3NUubBDb0Q@wuerfel>
Hi, Arnd
On 2016?12?01? 20:05, Arnd Bergmann wrote:
> On Thursday, December 1, 2016 8:48:40 AM CET Zhangfei Gao wrote:
>> + hisi,reset-bits = <0x20 0x8 /* 0: i2c0 */
>> + 0x20 0x10 /* 1: i2c1 */
>> + 0x20 0x20 /* 2: i2c2 */
>> + 0x20 0x8000000>; /* 3: i2c6 */
>> + };
>> +
>> +Specifying reset lines connected to IP modules
>> +==============================================
>> +example:
>> +
>> + i2c0: i2c at ..... {
>> + ...
>> + resets = <&iomcu_rst 0>;
>> + ...
>> + };
> I don't really like this approach, since now the information is
> in two places. Why not put the data into the reset specifier
> directly when it is used?
Any example, still not understand.
They are consumer and provider.
>
> Also the format seems a little too close to the actual register
> layout and could be a little more abstract, using bit numbers instead
> of a bitmask and register numbers instead of offsets.
We use bit numbers first.
But in the developing process, we found several bits may be required for
one driver.
And they may not be continuous as the bits may already be occupied.
Directly using offset, we can set several bits together for simple, to
give more flexibility.
So after discussion, we directly use offset.
Thanks
^ permalink raw reply
* [RFC PATCH 2/2] arm64: defconfig: enable MEMORY_HOTPLUG config options
From: Scott Branden @ 2016-12-02 0:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480637999-4320-1-git-send-email-scott.branden@broadcom.com>
Enable memory hotplug config options to add/remove memory.
Signed-off-by: Scott Branden <scott.branden@broadcom.com>
---
arch/arm64/configs/defconfig | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index dab2cb0..e801b37 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -73,6 +73,9 @@ CONFIG_PCIE_ARMADA_8K=y
CONFIG_ARM64_VA_BITS_48=y
CONFIG_SCHED_MC=y
CONFIG_PREEMPT=y
+CONFIG_MEMORY_HOTPLUG=y
+CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE=y
+CONFIG_MEMORY_HOTREMOVE=y
CONFIG_KSM=y
CONFIG_TRANSPARENT_HUGEPAGE=y
CONFIG_CMA=y
--
2.5.0
^ permalink raw reply related
* [RFC PATCH 1/2] arm64: memory-hotplug: Add MEMORY_HOTPLUG, MEMORY_HOTREMOVE, MEMORY_PROBE
From: Scott Branden @ 2016-12-02 0:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480637999-4320-1-git-send-email-scott.branden@broadcom.com>
Add memory-hotplug support for ARM64 platform.
This requires addition of
ARCH_ENABLE_MEMORY_HOTPLUG and ARCH_ENABLE_MEMORY_HOTREMOVE config options.
MEMORY_PROBE config option is added to support
/sys/devices/system/memory/probe functionality.
In addition architecture specific arch_add_memory and
arch_remove memory management functions are added.
Signed-off-by: Scott Branden <scott.branden@broadcom.com>
---
arch/arm64/Kconfig | 10 ++++++++++
arch/arm64/mm/init.c | 42 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 52 insertions(+)
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 969ef88..2482fdd 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -576,6 +576,12 @@ config HOTPLUG_CPU
Say Y here to experiment with turning CPUs off and on. CPUs
can be controlled through /sys/devices/system/cpu.
+config ARCH_ENABLE_MEMORY_HOTPLUG
+ def_bool y
+
+config ARCH_ENABLE_MEMORY_HOTREMOVE
+ def_bool y
+
# Common NUMA Features
config NUMA
bool "Numa Memory Allocation and Scheduler Support"
@@ -646,6 +652,10 @@ config ARCH_HAS_CACHE_LINE_SIZE
source "mm/Kconfig"
+config ARCH_MEMORY_PROBE
+ def_bool y
+ depends on MEMORY_HOTPLUG
+
config SECCOMP
bool "Enable seccomp to safely compute untrusted bytecode"
---help---
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 212c4d1..687d087 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -536,3 +536,45 @@ static int __init register_mem_limit_dumper(void)
return 0;
}
__initcall(register_mem_limit_dumper);
+
+#ifdef CONFIG_MEMORY_HOTPLUG
+int arch_add_memory(int nid, u64 start, u64 size, bool for_device)
+{
+ pg_data_t *pgdat;
+ struct zone *zone;
+ unsigned long start_pfn = start >> PAGE_SHIFT;
+ unsigned long nr_pages = size >> PAGE_SHIFT;
+ int ret;
+
+ pgdat = NODE_DATA(nid);
+
+ zone = pgdat->node_zones +
+ zone_for_memory(nid, start, size, ZONE_NORMAL, for_device);
+ ret = __add_pages(nid, zone, start_pfn, nr_pages);
+
+ if (ret)
+ pr_warn("%s: Problem encountered in __add_pages() ret=%d\n",
+ __func__, ret);
+
+ return ret;
+}
+
+#ifdef CONFIG_MEMORY_HOTREMOVE
+int arch_remove_memory(u64 start, u64 size)
+{
+ unsigned long start_pfn = start >> PAGE_SHIFT;
+ unsigned long nr_pages = size >> PAGE_SHIFT;
+ struct zone *zone;
+ int ret;
+
+ zone = page_zone(pfn_to_page(start_pfn));
+ ret = __remove_pages(zone, start_pfn, nr_pages);
+ if (ret)
+ pr_warn("%s: Problem encountered in __remove_pages() ret=%d\n",
+ __func__, ret);
+
+ return ret;
+}
+#endif
+#endif
+
--
2.5.0
^ permalink raw reply related
* [RFC PATCH 0/2] arm64: memory-hotplug: Add Memory Hotplug support
From: Scott Branden @ 2016-12-02 0:19 UTC (permalink / raw)
To: linux-arm-kernel
This patchset is sent for comment to add memory hotplug support for ARM64
based platforms. It follows hotplug code added for other architectures
in the linux kernel.
I tried testing the memory hotplug feature following documentation from
Documentation/memory-hotplug.txt. I don't think it is working as expected
- see below:
To add memory to the system I did the following:
echo 0x400000000 > /sys/devices/system/memory/probe
The memory is displayed as system ram:
cat /proc/iomem:
74000000-77ffffff : System RAM
74080000-748dffff : Kernel code
74950000-749d2fff : Kernel data
400000000-43fffffff : System RAM
But does not seem to be added to the kernel memory.
/proc/meminfo did not change.
What else needs to be done so the memory is added to the kernel memory
pool for normal allocation?
Scott Branden (2):
arm64: memory-hotplug: Add MEMORY_HOTPLUG, MEMORY_HOTREMOVE,
MEMORY_PROBE
arm64: defconfig: enable MEMORY_HOTPLUG config options
arch/arm64/Kconfig | 10 ++++++++++
arch/arm64/configs/defconfig | 3 +++
arch/arm64/mm/init.c | 42 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 55 insertions(+)
--
2.5.0
^ permalink raw reply
* [PATCH 2/2] mmc: host: s3cmci: allow probing from device tree
From: Sergio Prado @ 2016-12-02 0:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480637665-6325-1-git-send-email-sergio.prado@e-labworks.com>
Allows configuring Samsung S3C24XX MMC/SD/SDIO controller using a device
tree.
Signed-off-by: Sergio Prado <sergio.prado@e-labworks.com>
---
drivers/mmc/host/s3cmci.c | 155 +++++++++++++++++++++++++++++++++++++++-------
1 file changed, 131 insertions(+), 24 deletions(-)
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
index 932a4b1fed33..bfeb90e8ffee 100644
--- a/drivers/mmc/host/s3cmci.c
+++ b/drivers/mmc/host/s3cmci.c
@@ -23,6 +23,9 @@
#include <linux/gpio.h>
#include <linux/irq.h>
#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
#include <plat/gpio-cfg.h>
#include <mach/dma.h>
@@ -127,6 +130,22 @@ enum dbg_channels {
dbg_conf = (1 << 8),
};
+struct s3cmci_drv_data {
+ int is2440;
+};
+
+static const struct s3cmci_drv_data s3c2410_s3cmci_drv_data = {
+ .is2440 = 0,
+};
+
+static const struct s3cmci_drv_data s3c2412_s3cmci_drv_data = {
+ .is2440 = 1,
+};
+
+static const struct s3cmci_drv_data s3c2440_s3cmci_drv_data = {
+ .is2440 = 1,
+};
+
static const int dbgmap_err = dbg_fail;
static const int dbgmap_info = dbg_info | dbg_conf;
static const int dbgmap_debug = dbg_err | dbg_debug;
@@ -1241,8 +1260,9 @@ static void s3cmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
case MMC_POWER_ON:
case MMC_POWER_UP:
/* Configure GPE5...GPE10 pins in SD mode */
- s3c_gpio_cfgall_range(S3C2410_GPE(5), 6, S3C_GPIO_SFN(2),
- S3C_GPIO_PULL_NONE);
+ if (!host->pdev->dev.of_node)
+ s3c_gpio_cfgall_range(S3C2410_GPE(5), 6, S3C_GPIO_SFN(2),
+ S3C_GPIO_PULL_NONE);
if (host->pdata->set_power)
host->pdata->set_power(ios->power_mode, ios->vdd);
@@ -1254,7 +1274,8 @@ static void s3cmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
case MMC_POWER_OFF:
default:
- gpio_direction_output(S3C2410_GPE(5), 0);
+ if (!host->pdev->dev.of_node)
+ gpio_direction_output(S3C2410_GPE(5), 0);
if (host->is2440)
mci_con |= S3C2440_SDICON_SDRESET;
@@ -1544,21 +1565,12 @@ static inline void s3cmci_debugfs_remove(struct s3cmci_host *host) { }
#endif /* CONFIG_DEBUG_FS */
-static int s3cmci_probe(struct platform_device *pdev)
+static int s3cmci_probe_pdata(struct s3cmci_host *host)
{
- struct s3cmci_host *host;
- struct mmc_host *mmc;
- int ret;
- int is2440;
- int i;
+ struct platform_device *pdev = host->pdev;
+ int i, ret;
- is2440 = platform_get_device_id(pdev)->driver_data;
-
- mmc = mmc_alloc_host(sizeof(struct s3cmci_host), &pdev->dev);
- if (!mmc) {
- ret = -ENOMEM;
- goto probe_out;
- }
+ host->is2440 = platform_get_device_id(pdev)->driver_data;
for (i = S3C2410_GPE(5); i <= S3C2410_GPE(10); i++) {
ret = gpio_request(i, dev_name(&pdev->dev));
@@ -1568,14 +1580,90 @@ static int s3cmci_probe(struct platform_device *pdev)
for (i--; i >= S3C2410_GPE(5); i--)
gpio_free(i);
- goto probe_free_host;
+ return ret;
}
}
+ return 0;
+}
+
+static int s3cmci_probe_dt(struct s3cmci_host *host)
+{
+ struct platform_device *pdev = host->pdev;
+ struct s3c24xx_mci_pdata *pdata;
+ const struct s3cmci_drv_data *drvdata;
+ struct mmc_host *mmc = host->mmc;
+ int gpio, ret;
+
+ drvdata = of_device_get_match_data(&pdev->dev);
+ if (!drvdata)
+ return -ENODEV;
+
+ host->is2440 = drvdata->is2440;
+
+ ret = mmc_of_parse(mmc);
+ if (ret)
+ return ret;
+
+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ pdata->ocr_avail = mmc->ocr_avail;
+
+ if (mmc->caps2 & MMC_CAP2_NO_WRITE_PROTECT)
+ pdata->no_wprotect = 1;
+
+ if (mmc->caps & MMC_CAP_NEEDS_POLL)
+ pdata->no_detect = 1;
+
+ if (mmc->caps2 & MMC_CAP2_RO_ACTIVE_HIGH)
+ pdata->wprotect_invert = 1;
+
+ if (mmc->caps2 & MMC_CAP2_CD_ACTIVE_HIGH)
+ pdata->detect_invert = 1;
+
+ gpio = of_get_named_gpio(pdev->dev.of_node, "cd-gpios", 0);
+ if (gpio_is_valid(gpio)) {
+ pdata->gpio_detect = gpio;
+ gpio_free(gpio);
+ }
+
+ gpio = of_get_named_gpio(pdev->dev.of_node, "wp-gpios", 0);
+ if (gpio_is_valid(gpio)) {
+ pdata->gpio_wprotect = gpio;
+ gpio_free(gpio);
+ }
+
+ pdev->dev.platform_data = pdata;
+
+ return 0;
+}
+
+static int s3cmci_probe(struct platform_device *pdev)
+{
+ struct s3cmci_host *host;
+ struct mmc_host *mmc;
+ int ret;
+ int i;
+
+ mmc = mmc_alloc_host(sizeof(struct s3cmci_host), &pdev->dev);
+ if (!mmc) {
+ ret = -ENOMEM;
+ goto probe_out;
+ }
+
host = mmc_priv(mmc);
host->mmc = mmc;
host->pdev = pdev;
- host->is2440 = is2440;
+
+ if (pdev->dev.of_node)
+ ret = s3cmci_probe_dt(host);
+ else
+ ret = s3cmci_probe_pdata(host);
+
+ if (ret)
+ goto probe_free_host;
host->pdata = pdev->dev.platform_data;
if (!host->pdata) {
@@ -1586,7 +1674,7 @@ static int s3cmci_probe(struct platform_device *pdev)
spin_lock_init(&host->complete_lock);
tasklet_init(&host->pio_tasklet, pio_tasklet, (unsigned long) host);
- if (is2440) {
+ if (host->is2440) {
host->sdiimsk = S3C2440_SDIIMSK;
host->sdidata = S3C2440_SDIDATA;
host->clk_div = 1;
@@ -1789,8 +1877,9 @@ static int s3cmci_probe(struct platform_device *pdev)
release_mem_region(host->mem->start, resource_size(host->mem));
probe_free_gpio:
- for (i = S3C2410_GPE(5); i <= S3C2410_GPE(10); i++)
- gpio_free(i);
+ if (!pdev->dev.of_node)
+ for (i = S3C2410_GPE(5); i <= S3C2410_GPE(10); i++)
+ gpio_free(i);
probe_free_host:
mmc_free_host(mmc);
@@ -1837,9 +1926,9 @@ static int s3cmci_remove(struct platform_device *pdev)
if (!pd->no_detect)
gpio_free(pd->gpio_detect);
- for (i = S3C2410_GPE(5); i <= S3C2410_GPE(10); i++)
- gpio_free(i);
-
+ if (!pdev->dev.of_node)
+ for (i = S3C2410_GPE(5); i <= S3C2410_GPE(10); i++)
+ gpio_free(i);
iounmap(host->base);
release_mem_region(host->mem->start, resource_size(host->mem));
@@ -1848,6 +1937,23 @@ static int s3cmci_remove(struct platform_device *pdev)
return 0;
}
+static const struct of_device_id s3cmci_dt_match[] = {
+ {
+ .compatible = "samsung,s3c2410-sdi",
+ .data = &s3c2410_s3cmci_drv_data,
+ },
+ {
+ .compatible = "samsung,s3c2412-sdi",
+ .data = &s3c2412_s3cmci_drv_data,
+ },
+ {
+ .compatible = "samsung,s3c2440-sdi",
+ .data = &s3c2440_s3cmci_drv_data,
+ },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, sdhci_s3c_dt_match);
+
static const struct platform_device_id s3cmci_driver_ids[] = {
{
.name = "s3c2410-sdi",
@@ -1867,6 +1973,7 @@ static int s3cmci_remove(struct platform_device *pdev)
static struct platform_driver s3cmci_driver = {
.driver = {
.name = "s3c-sdi",
+ .of_match_table = s3cmci_dt_match,
},
.id_table = s3cmci_driver_ids,
.probe = s3cmci_probe,
--
1.9.1
^ permalink raw reply related
* [PATCH 1/2] dt-bindings: mmc: add DT binding for S3C24XX MMC/SD/SDIO controller
From: Sergio Prado @ 2016-12-02 0:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480637665-6325-1-git-send-email-sergio.prado@e-labworks.com>
Adds the device tree bindings description for Samsung S3C24XX
MMC/SD/SDIO controller, used as a connectivity interface with external
MMC, SD and SDIO storage mediums.
Signed-off-by: Sergio Prado <sergio.prado@e-labworks.com>
---
.../devicetree/bindings/mmc/samsung,s3cmci.txt | 38 ++++++++++++++++++++++
1 file changed, 38 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mmc/samsung,s3cmci.txt
diff --git a/Documentation/devicetree/bindings/mmc/samsung,s3cmci.txt b/Documentation/devicetree/bindings/mmc/samsung,s3cmci.txt
new file mode 100644
index 000000000000..3f044076e69a
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/samsung,s3cmci.txt
@@ -0,0 +1,38 @@
+* Samsung's S3C24XX MMC/SD/SDIO controller device tree bindings
+
+Samsung's S3C24XX MMC/SD/SDIO controller is used as a connectivity interface
+with external MMC, SD and SDIO storage mediums.
+
+This file documents differences between the core mmc properties described by
+mmc.txt and the properties used by the Samsung S3C24XX MMC/SD/SDIO controller
+implementation.
+
+Required SoC Specific Properties:
+- compatible: should be one of the following
+ - "samsung,s3c2410-sdi": for controllers compatible with s3c2410
+ - "samsung,s3c2412-sdi": for controllers compatible with s3c2412
+ - "samsung,s3c2440-sdi": for controllers compatible with s3c2440
+- clocks: Should reference the controller clock
+- clock-names: Should contain "sdi"
+
+Required Board Specific Properties:
+- pinctrl-0: Should specify pin control groups used for this controller.
+- pinctrl-names: Should contain only one value - "default".
+
+Example:
+ sdi: sdi at 5a000000 {
+ compatible = "samsung,s3c2440-sdi";
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdi_pins>;
+ reg = <0x5a000000 0x100000>;
+ interrupts = <0 0 21 3>;
+ clocks = <&clocks PCLK_SDI>;
+ clock-names = "sdi";
+ bus-width = <4>;
+ cd-gpios = <&gpg 8 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gph 8 GPIO_ACTIVE_LOW>;
+ };
+
+ Note: This example shows both SoC specific and board specific properties
+ in a single device node. The properties can be actually be separated
+ into SoC specific node and board specific node.
--
1.9.1
^ permalink raw reply related
* [PATCH 0/2] mmc: host: s3cmci: add device tree support
From: Sergio Prado @ 2016-12-02 0:14 UTC (permalink / raw)
To: linux-arm-kernel
This series adds support for configuring Samsung's S3C24XX MMC/SD/SDIO
controller via device tree.
Tested on FriendlyARM mini2440, based on s3c2440 SoC.
Sergio Prado (2):
dt-bindings: mmc: add DT binding for S3C24XX MMC/SD/SDIO controller
mmc: host: s3cmci: allow probing from device tree
.../devicetree/bindings/mmc/samsung,s3cmci.txt | 38 +++++
drivers/mmc/host/s3cmci.c | 155 +++++++++++++++++----
2 files changed, 169 insertions(+), 24 deletions(-)
create mode 100644 Documentation/devicetree/bindings/mmc/samsung,s3cmci.txt
--
1.9.1
^ permalink raw reply
* [PATCH v4 1/3] lib: add bitrev8x4()
From: Joshua Clayton @ 2016-12-02 0:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161201234523.3bed63dc@crub>
Hello Anatolij,
Thanks for the review.
On 12/01/2016 02:45 PM, Anatolij Gustschin wrote:
> On Thu, 1 Dec 2016 09:04:50 -0800
> Joshua Clayton stillcompiling at gmail.com wrote:
> ...
>> diff --git a/arch/arm/include/asm/bitrev.h b/arch/arm/include/asm/bitrev.h
>> index ec291c3..6d2e9ca 100644
>> --- a/arch/arm/include/asm/bitrev.h
>> +++ b/arch/arm/include/asm/bitrev.h
>> @@ -17,4 +17,9 @@ static __always_inline __attribute_const__ u8 __arch_bitrev8(u8 x)
>> return __arch_bitrev32((u32)x) >> 24;
>> }
>>
>> +static __always_inline __attribute_const__ u32 __arch_bitrev8x4(u32 x)
>> +{
>> + __asm__ ("rbit %0, %1; rev %0, %0" : "=r" (x) : "r" (x));
> return x;
Oops thats a little embarrassing;
I'll add a return.
>> +}
> otherwise you get
>
> In function '__arch_bitrev8x4':
> warning: no return statement in function returning non-void [-Wreturn-type]
>
> --
> Anatolij
I wonder why I do not see this warning when compiling. The inlining, maybe?
Joshua
^ permalink raw reply
* [PATCH 2/3] crypto: brcm: Add Broadcom SPU driver
From: kbuild test robot @ 2016-12-01 23:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480536453-24781-3-git-send-email-rob.rice@broadcom.com>
Hi Rob,
[auto build test ERROR on cryptodev/master]
[also build test ERROR on v4.9-rc7 next-20161201]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Rob-Rice/crypto-brcm-DT-documentation-for-Broadcom-SPU-driver/20161202-010038
base: https://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git master
config: arm64-defconfig (attached as .config)
compiler: aarch64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=arm64
All errors (new ones prefixed by >>):
>> ERROR: "des_ekey" [drivers/crypto/bcm/bcm_crypto_spu.ko] undefined!
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 31957 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161202/f5e756e2/attachment-0001.gz>
^ permalink raw reply
* [PATCH v2] PCI: Add information about describing PCI in ACPI
From: Bjorn Helgaas @ 2016-12-01 23:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <47776378.8X3TnsHd3Q@aspire.rjw.lan>
On Thu, Dec 01, 2016 at 11:37:39PM +0100, Rafael J. Wysocki wrote:
> On Thursday, December 01, 2016 04:36:04 PM Bjorn Helgaas wrote:
> > On Tue, Nov 29, 2016 at 03:39:48PM -0600, Bjorn Helgaas wrote:
> > > Here's another stab at this writeup. I'd appreciate any comments!
> > >
> > > Changes from v1 to v2:
> > > - Consumer/Producer is defined for Extended Address Space descriptors;
> > > should be ignored for QWord/DWord/Word Address Space descriptors
> > > - New arches may use Extended Address Space descriptors in PNP0A03 for
> > > bridge registers, including ECAM (if the arch adds support for this)
> > > - Add more details about MCFG and _CBA (Lv's suggestion)
> > > - Incorporate Rafael's suggestions
> > >
> > > ---
> > >
> > > Bjorn Helgaas (1):
> > > PCI: Add information about describing PCI in ACPI
> > >
> > >
> > > Documentation/PCI/00-INDEX | 2
> > > Documentation/PCI/acpi-info.txt | 180 +++++++++++++++++++++++++++++++++++++++
> > > 2 files changed, 182 insertions(+)
> > > create mode 100644 Documentation/PCI/acpi-info.txt
> >
> > It's very late in the cycle, but I'm considering trying to squeeze
> > this into v4.9 on the grounds that:
> >
> > - It's only a documentation change and can't break anything, and
> >
> > - Distributing it more widely may help the arm64 firmware ecosystem
> >
> > But I don't want to disseminate misleading or incorrect information,
> > so if it needs clarification or wordsmithing, or even just maturation,
> > I'll wait until v4.10.
> >
> > The Consumer/Producer stuff, in particular, doesn't seem 100% settled
> > yet. Your thoughts, and especially your improvements, are welcome!
>
> Well, what's the drawback if it doesn't go into 4.9?
Only that it's not as easily accessible. ARM64 ACPI firmware is brand
new. Neither the firmware nor the kernel developers, nor even the
hardware designers, have the benefit of all the x86/ia64 history, so I
wrote this to try to come to a common understanding of what Linux
expects.
The first generation of ARM64 hardware is already in the field, and it
has teething problems in hardware, firmware, and kernel. For example,
the current MCFG quirk situation: the ECAM hardware doesn't work quite
per spec, the ACPI firmware doesn't describe the address space
completely, and we don't really have consensus on how the firmware
should communicate register space to the kernel.
We're hoping the second generation can fix some of these problems, and
I think this is the time to try to influence that.
Bjorn
^ permalink raw reply
* [PATCH v3] PCI/ACPI: xgene: Add ECAM quirk for X-Gene PCIe controller
From: Duc Dang @ 2016-12-01 23:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161201230736.GA17948@bhelgaas-glaptop.roam.corp.google.com>
On Thu, Dec 1, 2016 at 3:07 PM, Bjorn Helgaas <helgaas@kernel.org> wrote:
> On Thu, Dec 01, 2016 at 02:10:10PM -0800, Duc Dang wrote:
>> On Thu, Dec 1, 2016 at 11:41 AM, Bjorn Helgaas <helgaas@kernel.org> wrote:
>> > On Thu, Dec 01, 2016 at 02:20:53PM -0500, Mark Salter wrote:
>> >> On Thu, 2016-12-01 at 12:33 -0600, Bjorn Helgaas wrote:
>> >> > On Wed, Nov 30, 2016 at 03:42:53PM -0800, Duc Dang wrote:
>> >
>> >> > > +static struct resource xgene_v1_csr_res[] = {
>> >> > > + [0] = DEFINE_RES_MEM_NAMED(0x1f2b0000UL, SZ_64K, "PCIe CSR"),
>> >> > > + [1] = DEFINE_RES_MEM_NAMED(0x1f2c0000UL, SZ_64K, "PCIe CSR"),
>> >> > > + [2] = DEFINE_RES_MEM_NAMED(0x1f2d0000UL, SZ_64K, "PCIe CSR"),
>> >> > > + [3] = DEFINE_RES_MEM_NAMED(0x1f500000UL, SZ_64K, "PCIe CSR"),
>> >> > > + [4] = DEFINE_RES_MEM_NAMED(0x1f510000UL, SZ_64K, "PCIe CSR"),
>> >> > I assume these ranges are not the actual ECAM space, right?
>> >> > If they *were* ECAM, I assume you would have included them in the
>> >> > quirk itself in the mcfg_quirks[] table.
>> >>
>> >> These are base addresses for some RC mmio registers.
>> >> >
>> >> > >
>> >> > > +static int xgene_v1_pcie_ecam_init(struct pci_config_window *cfg)
>> >> > > +{
>> >> > > + struct acpi_device *adev = to_acpi_device(cfg->parent);
>> >> > > + struct acpi_pci_root *root = acpi_driver_data(adev);
>> >> > > + struct device *dev = cfg->parent;
>> >> > > + struct xgene_pcie_port *port;
>> >> > > + struct resource *csr;
>> >> > > +
>> >> > > + port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
>> >> > > + if (!port)
>> >> > > + return -ENOMEM;
>> >> > > +
>> >> > > + csr = &xgene_v1_csr_res[root->segment];
>> >> > This makes me nervous because root->segment comes from the ACPI _SEG,
>> >> > and if firmware gives us junk in _SEG, we will reference something in
>> >> > the weeds.
>> >>
>> >> The SoC provide some number of RC bridges, each with a different base
>> >> for some mmio registers. Even if segment is legitimate in MCFG, there
>> >> is still a problem if a platform doesn't use the segment ordering
>> >> implied by the code. But the PNP0A03 _CRS does have this base address
>> >> as the first memory resource, so we could get it from there and not
>> >> have hard-coded addresses and implied ording in the quirk code.
>> >
>> > I'm confused. Doesn't the current code treat every item in PNP0A03
>> > _CRS as a window? Do you mean the first resource is handled
>> > differently somehow? The Consumer/Producer bit could allow us to do
>> > this by marking the RC MMIO space as "Consumer", but I didn't think
>> > that strategy was quite working yet.
>>
>> The first resource is defined like below. It was introduced long time
>> ago to use with older version of X-Gene ECAM quirks.
>> Memory32Fixed(ReadWrite, 0x1F2B0000, 0x10000, )
>
>> [ 0.822990] pci_bus 0000:00: root bus resource [mem 0x1f2b0000-0x1f2bffff]
>
> I think this is wrong. The PCI core thinks [mem 0x1f2b0000-0x1f2bffff]
> is available for use by devices on bus 0000:00, but I think you're
> saying it is consumed by the bridge itself, not forwarded down to PCI.
>
> What's in your /proc/iomem? I see that your quirks do call
> devm_ioremap_resource(), which calls devm_request_mem_region()
> internally, so the driver does at least request that region, which
> should keep us from assigning it to PCI devices.
>
> But it still isn't quite right to tell the PCI core that the region is
> available on the root bus.
This is /proc/iomem output on my Mustang board. The 64K "PCIe CSR"
region is consumed completely.
1f2b0000-1f2bffff : PCI Bus 0000:00
1f2b0000-1f2bffff : PCIe CSR
e040000000-e07fffffff : PCI Bus 0000:00
e040000000-e0401fffff : PCI Bus 0000:01
e040000000-e0400fffff : 0000:01:00.0
e040000000-e0400fffff : mlx4_core
e040100000-e0401fffff : 0000:01:00.0
e0d0000000-e0dfffffff : PCI ECAM
f000000000-ffffffffff : PCI Bus 0000:00
f000000000-f001ffffff : PCI Bus 0000:01
f000000000-f001ffffff : 0000:01:00.0
f000000000-f001ffffff : mlx4_core
Using hard-coded resources for mmio space make the quirk rely on the
segment number passing from the firmware. Using Mark's method or
acpi_get_rc_resource can discover the mmio space and consume all of
the space, but as you mentioned, it leaves the defect that PCI core
considers the mmio space as available resource for secondary devices
although it will never allocate the mmio space to secondary devices as
the RC already reserves and consumes all of the space.
>
> Bjorn
>
Regards,
Duc Dang.
^ permalink raw reply
* [PATCH v3] PCI/ACPI: xgene: Add ECAM quirk for X-Gene PCIe controller
From: Bjorn Helgaas @ 2016-12-01 23:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CADaLNDkVPRPSg0aU-sxHsiJbVvEn=LxcekDt6gfXBBhc+fzhjw@mail.gmail.com>
On Thu, Dec 01, 2016 at 02:10:10PM -0800, Duc Dang wrote:
> On Thu, Dec 1, 2016 at 11:41 AM, Bjorn Helgaas <helgaas@kernel.org> wrote:
> > On Thu, Dec 01, 2016 at 02:20:53PM -0500, Mark Salter wrote:
> >> On Thu, 2016-12-01 at 12:33 -0600, Bjorn Helgaas wrote:
> >> > On Wed, Nov 30, 2016 at 03:42:53PM -0800, Duc Dang wrote:
> >
> >> > > +static struct resource xgene_v1_csr_res[] = {
> >> > > + [0] = DEFINE_RES_MEM_NAMED(0x1f2b0000UL, SZ_64K, "PCIe CSR"),
> >> > > + [1] = DEFINE_RES_MEM_NAMED(0x1f2c0000UL, SZ_64K, "PCIe CSR"),
> >> > > + [2] = DEFINE_RES_MEM_NAMED(0x1f2d0000UL, SZ_64K, "PCIe CSR"),
> >> > > + [3] = DEFINE_RES_MEM_NAMED(0x1f500000UL, SZ_64K, "PCIe CSR"),
> >> > > + [4] = DEFINE_RES_MEM_NAMED(0x1f510000UL, SZ_64K, "PCIe CSR"),
> >> > I assume these ranges are not the actual ECAM space, right?
> >> > If they *were* ECAM, I assume you would have included them in the
> >> > quirk itself in the mcfg_quirks[] table.
> >>
> >> These are base addresses for some RC mmio registers.
> >> >
> >> > >
> >> > > +static int xgene_v1_pcie_ecam_init(struct pci_config_window *cfg)
> >> > > +{
> >> > > + struct acpi_device *adev = to_acpi_device(cfg->parent);
> >> > > + struct acpi_pci_root *root = acpi_driver_data(adev);
> >> > > + struct device *dev = cfg->parent;
> >> > > + struct xgene_pcie_port *port;
> >> > > + struct resource *csr;
> >> > > +
> >> > > + port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
> >> > > + if (!port)
> >> > > + return -ENOMEM;
> >> > > +
> >> > > + csr = &xgene_v1_csr_res[root->segment];
> >> > This makes me nervous because root->segment comes from the ACPI _SEG,
> >> > and if firmware gives us junk in _SEG, we will reference something in
> >> > the weeds.
> >>
> >> The SoC provide some number of RC bridges, each with a different base
> >> for some mmio registers. Even if segment is legitimate in MCFG, there
> >> is still a problem if a platform doesn't use the segment ordering
> >> implied by the code. But the PNP0A03 _CRS does have this base address
> >> as the first memory resource, so we could get it from there and not
> >> have hard-coded addresses and implied ording in the quirk code.
> >
> > I'm confused. Doesn't the current code treat every item in PNP0A03
> > _CRS as a window? Do you mean the first resource is handled
> > differently somehow? The Consumer/Producer bit could allow us to do
> > this by marking the RC MMIO space as "Consumer", but I didn't think
> > that strategy was quite working yet.
>
> The first resource is defined like below. It was introduced long time
> ago to use with older version of X-Gene ECAM quirks.
> Memory32Fixed(ReadWrite, 0x1F2B0000, 0x10000, )
> [ 0.822990] pci_bus 0000:00: root bus resource [mem 0x1f2b0000-0x1f2bffff]
I think this is wrong. The PCI core thinks [mem 0x1f2b0000-0x1f2bffff]
is available for use by devices on bus 0000:00, but I think you're
saying it is consumed by the bridge itself, not forwarded down to PCI.
What's in your /proc/iomem? I see that your quirks do call
devm_ioremap_resource(), which calls devm_request_mem_region()
internally, so the driver does at least request that region, which
should keep us from assigning it to PCI devices.
But it still isn't quite right to tell the PCI core that the region is
available on the root bus.
Bjorn
^ permalink raw reply
* [PATCH v4 1/3] lib: add bitrev8x4()
From: Anatolij Gustschin @ 2016-12-01 22:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <bc92eb1507448731163ae67fc888668d327f9168.1480551148.git.stillcompiling@gmail.com>
On Thu, 1 Dec 2016 09:04:50 -0800
Joshua Clayton stillcompiling at gmail.com wrote:
...
>diff --git a/arch/arm/include/asm/bitrev.h b/arch/arm/include/asm/bitrev.h
>index ec291c3..6d2e9ca 100644
>--- a/arch/arm/include/asm/bitrev.h
>+++ b/arch/arm/include/asm/bitrev.h
>@@ -17,4 +17,9 @@ static __always_inline __attribute_const__ u8 __arch_bitrev8(u8 x)
> return __arch_bitrev32((u32)x) >> 24;
> }
>
>+static __always_inline __attribute_const__ u32 __arch_bitrev8x4(u32 x)
>+{
>+ __asm__ ("rbit %0, %1; rev %0, %0" : "=r" (x) : "r" (x));
return x;
>+}
otherwise you get
In function '__arch_bitrev8x4':
warning: no return statement in function returning non-void [-Wreturn-type]
--
Anatolij
^ permalink raw reply
* [PATCH v2] PCI: Add information about describing PCI in ACPI
From: Rafael J. Wysocki @ 2016-12-01 22:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161201223604.GC15867@bhelgaas-glaptop.roam.corp.google.com>
On Thursday, December 01, 2016 04:36:04 PM Bjorn Helgaas wrote:
> On Tue, Nov 29, 2016 at 03:39:48PM -0600, Bjorn Helgaas wrote:
> > Here's another stab at this writeup. I'd appreciate any comments!
> >
> > Changes from v1 to v2:
> > - Consumer/Producer is defined for Extended Address Space descriptors;
> > should be ignored for QWord/DWord/Word Address Space descriptors
> > - New arches may use Extended Address Space descriptors in PNP0A03 for
> > bridge registers, including ECAM (if the arch adds support for this)
> > - Add more details about MCFG and _CBA (Lv's suggestion)
> > - Incorporate Rafael's suggestions
> >
> > ---
> >
> > Bjorn Helgaas (1):
> > PCI: Add information about describing PCI in ACPI
> >
> >
> > Documentation/PCI/00-INDEX | 2
> > Documentation/PCI/acpi-info.txt | 180 +++++++++++++++++++++++++++++++++++++++
> > 2 files changed, 182 insertions(+)
> > create mode 100644 Documentation/PCI/acpi-info.txt
>
> It's very late in the cycle, but I'm considering trying to squeeze
> this into v4.9 on the grounds that:
>
> - It's only a documentation change and can't break anything, and
>
> - Distributing it more widely may help the arm64 firmware ecosystem
>
> But I don't want to disseminate misleading or incorrect information,
> so if it needs clarification or wordsmithing, or even just maturation,
> I'll wait until v4.10.
>
> The Consumer/Producer stuff, in particular, doesn't seem 100% settled
> yet. Your thoughts, and especially your improvements, are welcome!
Well, what's the drawback if it doesn't go into 4.9?
Thanks,
Rafael
^ permalink raw reply
* [PATCH v7 3/4] arm64: dts: marvell: Add I2C definitions for the Armada 3700
From: Wolfram Sang @ 2016-12-01 22:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161201110440.27530-4-romain.perier@free-electrons.com>
On Thu, Dec 01, 2016 at 12:04:39PM +0100, Romain Perier wrote:
> The Armada 3700 has two i2c bus interface units, this commit adds the
> definitions of the corresponding device nodes. It also enables the node
> on the development board for this SoC.
>
> Signed-off-by: Romain Perier <romain.perier@free-electrons.com>
> Acked-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
This needs to go via arm-soc.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161201/1638dc2e/attachment.sig>
^ permalink raw reply
* [PATCH v7 2/4] i2c: pxa: Add support for the I2C units found in Armada 3700
From: Wolfram Sang @ 2016-12-01 22:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161201110440.27530-3-romain.perier@free-electrons.com>
On Thu, Dec 01, 2016 at 12:04:38PM +0100, Romain Perier wrote:
> The Armada 3700 has two I2C controllers that is compliant with the I2C
> Bus Specificiation 2.1, supports multi-master and different bus speed:
> Standard mode (up to 100 KHz), Fast mode (up to 400 KHz),
> High speed mode (up to 3.4 Mhz).
>
> This IP block has a lot of similarity with the PXA, except some register
> offsets and bitfield. This commits adds a basic support for this I2C
> unit.
>
> Signed-off-by: Romain Perier <romain.perier@free-electrons.com>
> Tested-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
Applied to for-next, thanks!
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161201/3672fc3c/attachment.sig>
^ permalink raw reply
* [PATCH v7 1/4] i2c: pxa: Add definition of fast and high speed modes via the regs layout
From: Wolfram Sang @ 2016-12-01 22:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161201110440.27530-2-romain.perier@free-electrons.com>
On Thu, Dec 01, 2016 at 12:04:37PM +0100, Romain Perier wrote:
> So far, the bit masks for the fast and high speed mode were statically
> defined. Some IP blocks might use different bits for these modes.
>
> This commit introduces new fields in order to enable the definition of
> different bit masks for these features. If these fields are undefined,
> ICR_FM and ICR_HS are selected to preserve backward compatibility with
> other IPs.
>
> Signed-off-by: Romain Perier <romain.perier@free-electrons.com>
Applied to for-next, thanks!
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161201/a419650d/attachment.sig>
^ permalink raw reply
* [PATCH v2] PCI: Add information about describing PCI in ACPI
From: Bjorn Helgaas @ 2016-12-01 22:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161129212816.15663.28100.stgit@bhelgaas-glaptop.roam.corp.google.com>
On Tue, Nov 29, 2016 at 03:39:48PM -0600, Bjorn Helgaas wrote:
> Here's another stab at this writeup. I'd appreciate any comments!
>
> Changes from v1 to v2:
> - Consumer/Producer is defined for Extended Address Space descriptors;
> should be ignored for QWord/DWord/Word Address Space descriptors
> - New arches may use Extended Address Space descriptors in PNP0A03 for
> bridge registers, including ECAM (if the arch adds support for this)
> - Add more details about MCFG and _CBA (Lv's suggestion)
> - Incorporate Rafael's suggestions
>
> ---
>
> Bjorn Helgaas (1):
> PCI: Add information about describing PCI in ACPI
>
>
> Documentation/PCI/00-INDEX | 2
> Documentation/PCI/acpi-info.txt | 180 +++++++++++++++++++++++++++++++++++++++
> 2 files changed, 182 insertions(+)
> create mode 100644 Documentation/PCI/acpi-info.txt
It's very late in the cycle, but I'm considering trying to squeeze
this into v4.9 on the grounds that:
- It's only a documentation change and can't break anything, and
- Distributing it more widely may help the arm64 firmware ecosystem
But I don't want to disseminate misleading or incorrect information,
so if it needs clarification or wordsmithing, or even just maturation,
I'll wait until v4.10.
The Consumer/Producer stuff, in particular, doesn't seem 100% settled
yet. Your thoughts, and especially your improvements, are welcome!
Bjorn
^ permalink raw reply
* [PATCH v7 4/4] dt-bindings: i2c: pxa: Update the documentation for the Armada 3700
From: Wolfram Sang @ 2016-12-01 22:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161201110440.27530-5-romain.perier@free-electrons.com>
On Thu, Dec 01, 2016 at 12:04:40PM +0100, Romain Perier wrote:
> This commit documents the compatible string to have the compatibility for
> the I2C unit found in the Armada 3700.
>
> Signed-off-by: Romain Perier <romain.perier@free-electrons.com>
> Acked-by: Rob Herring <robh@kernel.org>
Applied to for-next, thanks!
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161201/d20b196d/attachment.sig>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox