* [PATCH 05/12] atl1c: remove SMB/CMB DMA related code
From: xiong @ 2012-04-18 5:32 UTC (permalink / raw)
To: davem, netdev, linux-kernel; +Cc: qca-linux-team, nic-devel, xiong
In-Reply-To: <1334727156-6830-1-git-send-email-xiong@qca.qualcomm.com>
l1c & later chips don't support DMA for SMB.
CMB is removed from hardware.
reg(15C8) is used to trig interrupt by tpd threshold.
Signed-off-by: xiong <xiong@qca.qualcomm.com>
Tested-by: Liu David <dwliu@qca.qualcomm.com>
---
drivers/net/ethernet/atheros/atl1c/atl1c.h | 19 +------------
drivers/net/ethernet/atheros/atl1c/atl1c_hw.h | 10 +-----
drivers/net/ethernet/atheros/atl1c/atl1c_main.c | 34 ++---------------------
3 files changed, 6 insertions(+), 57 deletions(-)
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c.h b/drivers/net/ethernet/atheros/atl1c/atl1c.h
index cf82b74..93b5991 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c.h
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c.h
@@ -426,10 +426,6 @@ struct atl1c_hw {
#define ATL1C_FPGA_VERSION 0x8000
u16 link_cap_flags;
#define ATL1C_LINK_CAP_1000M 0x0001
- u16 cmb_tpd;
- u16 cmb_rrd;
- u16 cmb_rx_timer; /* 2us resolution */
- u16 cmb_tx_timer;
u32 smb_timer;
u16 rrd_thresh; /* Threshold of number of RRD produced to trigger
@@ -449,8 +445,7 @@ struct atl1c_hw {
/*
* atl1c_ring_header represents a single, contiguous block of DMA space
- * mapped for the three descriptor rings (tpd, rfd, rrd) and the two
- * message blocks (cmb, smb) described below
+ * mapped for the three descriptor rings (tpd, rfd, rrd) described below
*/
struct atl1c_ring_header {
void *desc; /* virtual address */
@@ -524,16 +519,6 @@ struct atl1c_rrd_ring {
u16 next_to_clean;
};
-struct atl1c_cmb {
- void *cmb;
- dma_addr_t dma;
-};
-
-struct atl1c_smb {
- void *smb;
- dma_addr_t dma;
-};
-
/* board specific private data structure */
struct atl1c_adapter {
struct net_device *netdev;
@@ -571,8 +556,6 @@ struct atl1c_adapter {
struct atl1c_tpd_ring tpd_ring[AT_MAX_TRANSMIT_QUEUE];
struct atl1c_rfd_ring rfd_ring;
struct atl1c_rrd_ring rrd_ring;
- struct atl1c_cmb cmb;
- struct atl1c_smb smb;
u32 bd_number; /* board number;*/
};
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
index f5c7473..caff2ae 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
@@ -447,8 +447,6 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw);
*/
#define REG_RX_BASE_ADDR_HI 0x1540
#define REG_TX_BASE_ADDR_HI 0x1544
-#define REG_SMB_BASE_ADDR_HI 0x1548
-#define REG_SMB_BASE_ADDR_LO 0x154C
#define REG_RFD0_HEAD_ADDR_LO 0x1550
#define REG_RFD_RING_SIZE 0x1560
#define RFD_RING_SIZE_MASK 0x0FFF
@@ -461,7 +459,6 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw);
#define REG_NTPD_HEAD_ADDR_LO 0x1580
#define REG_TPD_RING_SIZE 0x1584
#define TPD_RING_SIZE_MASK 0xFFFF
-#define REG_CMB_BASE_ADDR_LO 0x1588
/* TXQ Control Register */
#define REG_TXQ_CTRL 0x1590
@@ -556,13 +553,10 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw);
#define MAC_CTRL_SMB_DIS 0x1000000
#define DMA_CTRL_SMB_NOW 0x80000000
-/* CMB/SMB Control Register */
+/* INT-triggle/SMB Control Register */
#define REG_SMB_STAT_TIMER 0x15C4 /* 2us resolution */
#define SMB_STAT_TIMER_MASK 0xFFFFFF
-#define REG_CMB_TPD_THRESH 0x15C8
-#define CMB_TPD_THRESH_MASK 0xFFFF
-#define REG_CMB_TX_TIMER 0x15CC /* 2us resolution */
-#define CMB_TX_TIMER_MASK 0xFFFF
+#define REG_TINT_TPD_THRESH 0x15C8 /* tpd th to trig intrrupt */
/* Mail box */
#define MB_RFDX_PROD_IDX_MASK 0xFFFF
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index 885e892..ceb9df5 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -733,8 +733,6 @@ static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter)
hw->ict = 50000; /* 100ms */
hw->smb_timer = 200000; /* 400ms */
- hw->cmb_tpd = 4;
- hw->cmb_tx_timer = 1; /* 2 us */
hw->rx_imt = 200;
hw->tx_imt = 1000;
@@ -943,8 +941,7 @@ static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter)
sizeof(struct atl1c_tpd_desc) * tpd_ring->count * 2 +
sizeof(struct atl1c_rx_free_desc) * rx_desc_count +
sizeof(struct atl1c_recv_ret_status) * rx_desc_count +
- sizeof(struct atl1c_hw_stats) +
- 8 * 4 + 8 * 2;
+ 8 * 4;
ring_header->desc = pci_alloc_consistent(pdev, ring_header->size,
&ring_header->dma);
@@ -977,8 +974,6 @@ static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter)
rrd_ring->count;
offset += roundup(rrd_ring->size, 8);
- adapter->smb.dma = ring_header->dma + offset;
- adapter->smb.smb = (u8 *)ring_header->desc + offset;
return 0;
err_nomem:
@@ -993,8 +988,6 @@ static void atl1c_configure_des_ring(struct atl1c_adapter *adapter)
struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring;
struct atl1c_tpd_ring *tpd_ring = (struct atl1c_tpd_ring *)
adapter->tpd_ring;
- struct atl1c_cmb *cmb = (struct atl1c_cmb *) &adapter->cmb;
- struct atl1c_smb *smb = (struct atl1c_smb *) &adapter->smb;
u32 data;
/* TPD */
@@ -1029,14 +1022,6 @@ static void atl1c_configure_des_ring(struct atl1c_adapter *adapter)
AT_WRITE_REG(hw, REG_RRD_RING_SIZE,
(rrd_ring->count & RRD_RING_SIZE_MASK));
- /* CMB */
- AT_WRITE_REG(hw, REG_CMB_BASE_ADDR_LO, cmb->dma & AT_DMA_LO_ADDR_MASK);
-
- /* SMB */
- AT_WRITE_REG(hw, REG_SMB_BASE_ADDR_HI,
- (u32)((smb->dma & AT_DMA_HI_ADDR_MASK) >> 32));
- AT_WRITE_REG(hw, REG_SMB_BASE_ADDR_LO,
- (u32)(smb->dma & AT_DMA_LO_ADDR_MASK));
if (hw->nic_type == athr_l2c_b) {
AT_WRITE_REG(hw, REG_SRAM_RXF_LEN, 0x02a0L);
AT_WRITE_REG(hw, REG_SRAM_TXF_LEN, 0x0100L);
@@ -1115,12 +1100,6 @@ static void atl1c_configure_dma(struct atl1c_adapter *adapter)
u32 dma_ctrl_data;
dma_ctrl_data = DMA_CTRL_DMAR_REQ_PRI;
- if (hw->ctrl_flags & ATL1C_CMB_ENABLE)
- dma_ctrl_data |= DMA_CTRL_CMB_EN;
- if (hw->ctrl_flags & ATL1C_SMB_ENABLE)
- dma_ctrl_data |= DMA_CTRL_SMB_EN;
- else
- dma_ctrl_data |= MAC_CTRL_SMB_DIS;
switch (hw->dma_order) {
case atl1c_dma_ord_in:
@@ -1440,16 +1419,9 @@ static int atl1c_configure(struct atl1c_adapter *adapter)
master_ctrl_data |= MASTER_CTRL_SA_TIMER_EN;
AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data);
- if (hw->ctrl_flags & ATL1C_CMB_ENABLE) {
- AT_WRITE_REG(hw, REG_CMB_TPD_THRESH,
- hw->cmb_tpd & CMB_TPD_THRESH_MASK);
- AT_WRITE_REG(hw, REG_CMB_TX_TIMER,
- hw->cmb_tx_timer & CMB_TX_TIMER_MASK);
- }
+ AT_WRITE_REG(hw, REG_SMB_STAT_TIMER,
+ hw->smb_timer & SMB_STAT_TIMER_MASK);
- if (hw->ctrl_flags & ATL1C_SMB_ENABLE)
- AT_WRITE_REG(hw, REG_SMB_STAT_TIMER,
- hw->smb_timer & SMB_STAT_TIMER_MASK);
/* set MTU */
AT_WRITE_REG(hw, REG_MTU, hw->max_frame_size + ETH_HLEN +
VLAN_HLEN + ETH_FCS_LEN);
--
1.7.7
^ permalink raw reply related
* [PATCH 04/12] atl1c: remove VPD register
From: xiong @ 2012-04-18 5:32 UTC (permalink / raw)
To: davem, netdev, linux-kernel; +Cc: qca-linux-team, nic-devel, xiong
In-Reply-To: <1334727156-6830-1-git-send-email-xiong@qca.qualcomm.com>
VPD register is only used for L1(devid=PCI_DEVICE_ID_ATTANSIC_L1) to
access external NV-memory.
l1c & later chip doesn't use it any more.
PHY 0/1 registers occupy the last 2 slots of the dump table.
Signed-off-by: xiong <xiong@qca.qualcomm.com>
Tested-by: Liu David <dwliu@qca.qualcomm.com>
---
drivers/net/ethernet/atheros/atl1c/atl1c.h | 2 +-
drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c | 7 +++----
drivers/net/ethernet/atheros/atl1c/atl1c_hw.h | 11 -----------
3 files changed, 4 insertions(+), 16 deletions(-)
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c.h b/drivers/net/ethernet/atheros/atl1c/atl1c.h
index c725ee5..cf82b74 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c.h
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c.h
@@ -100,7 +100,7 @@
#define ATL1C_ASPM_L0s_ENABLE 0x0001
#define ATL1C_ASPM_L1_ENABLE 0x0002
-#define AT_REGS_LEN (75 * sizeof(u32))
+#define AT_REGS_LEN (74 * sizeof(u32))
#define AT_EEPROM_LEN 512
#define ATL1C_GET_DESC(R, i, type) (&(((type *)((R)->desc))[i]))
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c b/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c
index 0a9326a..3feb846 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c
@@ -141,8 +141,7 @@ static void atl1c_get_regs(struct net_device *netdev,
memset(p, 0, AT_REGS_LEN);
- regs->version = 0;
- AT_READ_REG(hw, REG_VPD_CAP, p++);
+ regs->version = 1;
AT_READ_REG(hw, REG_PM_CTRL, p++);
AT_READ_REG(hw, REG_MAC_HALF_DUPLX_CTRL, p++);
AT_READ_REG(hw, REG_TWSI_CTRL, p++);
@@ -167,9 +166,9 @@ static void atl1c_get_regs(struct net_device *netdev,
AT_READ_REG(hw, REG_WOL_CTRL, p++);
atl1c_read_phy_reg(hw, MII_BMCR, &phy_data);
- regs_buff[73] = (u32) phy_data;
+ regs_buff[AT_REGS_LEN/sizeof(u32) - 2] = (u32) phy_data;
atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
- regs_buff[74] = (u32) phy_data;
+ regs_buff[AT_REGS_LEN/sizeof(u32) - 1] = (u32) phy_data;
}
static int atl1c_get_eeprom_len(struct net_device *netdev)
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
index c22d698..f5c7473 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
@@ -59,17 +59,6 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw);
#define LINK_CTRL_L1_EN 0x02
#define LINK_CTRL_EXT_SYNC 0x80
-#define REG_VPD_CAP 0x6C
-#define VPD_CAP_ID_MASK 0xff
-#define VPD_CAP_ID_SHIFT 0
-#define VPD_CAP_NEXT_PTR_MASK 0xFF
-#define VPD_CAP_NEXT_PTR_SHIFT 8
-#define VPD_CAP_VPD_ADDR_MASK 0x7FFF
-#define VPD_CAP_VPD_ADDR_SHIFT 16
-#define VPD_CAP_VPD_FLAG 0x80000000
-
-#define REG_VPD_DATA 0x70
-
#define REG_PCIE_UC_SEVERITY 0x10C
#define PCIE_UC_SERVRITY_TRN 0x00000001
#define PCIE_UC_SERVRITY_DLP 0x00000010
--
1.7.7
^ permalink raw reply related
* [PATCH 03/12] atl1c: remove HDS register
From: xiong @ 2012-04-18 5:32 UTC (permalink / raw)
To: davem, netdev, linux-kernel; +Cc: qca-linux-team, nic-devel, xiong
In-Reply-To: <1334727156-6830-1-git-send-email-xiong@qca.qualcomm.com>
remove HDS register as it doesn't exist in hardware.
Signed-off-by: xiong <xiong@qca.qualcomm.com>
Tested-by: Liu David <dwliu@qca.qualcomm.com>
---
drivers/net/ethernet/atheros/atl1c/atl1c_hw.h | 7 -------
drivers/net/ethernet/atheros/atl1c/atl1c_main.c | 2 --
2 files changed, 0 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
index 855aca0..c22d698 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
@@ -669,13 +669,6 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw);
#define REG_INT_RETRIG_TIMER 0x1608
#define INT_RETRIG_TIMER_MASK 0xFFFF
-#define REG_HDS_CTRL 0x160C
-#define HDS_CTRL_EN 0x0001
-#define HDS_CTRL_BACKFILLSIZE_SHIFT 8
-#define HDS_CTRL_BACKFILLSIZE_MASK 0x0FFF
-#define HDS_CTRL_MAX_HDRSIZE_SHIFT 20
-#define HDS_CTRL_MAC_HDRSIZE_MASK 0x0FFF
-
#define REG_MAC_RX_STATUS_BIN 0x1700
#define REG_MAC_RX_STATUS_END 0x175c
#define REG_MAC_TX_STATUS_BIN 0x1760
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index 226be99..885e892 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -1453,8 +1453,6 @@ static int atl1c_configure(struct atl1c_adapter *adapter)
/* set MTU */
AT_WRITE_REG(hw, REG_MTU, hw->max_frame_size + ETH_HLEN +
VLAN_HLEN + ETH_FCS_LEN);
- /* HDS, disable */
- AT_WRITE_REG(hw, REG_HDS_CTRL, 0);
atl1c_configure_tx(adapter);
atl1c_configure_rx(adapter);
--
1.7.7
^ permalink raw reply related
* [PATCH 02/12] atl1c: remove multiple-RX-Q code
From: xiong @ 2012-04-18 5:32 UTC (permalink / raw)
To: davem, netdev, linux-kernel; +Cc: qca-linux-team, nic-devel, xiong
In-Reply-To: <1334727156-6830-1-git-send-email-xiong@qca.qualcomm.com>
the multiple-RX-Q in hardware doesn't work,
all related register definition & code are removed.
Signed-off-by: xiong <xiong@qca.qualcomm.com>
Tested-by: Liu David <dwliu@qca.qualcomm.com>
---
drivers/net/ethernet/atheros/atl1c/atl1c.h | 22 +--
drivers/net/ethernet/atheros/atl1c/atl1c_hw.h | 36 ----
drivers/net/ethernet/atheros/atl1c/atl1c_main.c | 216 +++++++----------------
3 files changed, 65 insertions(+), 209 deletions(-)
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c.h b/drivers/net/ethernet/atheros/atl1c/atl1c.h
index ca70e16..c725ee5 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c.h
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c.h
@@ -297,20 +297,6 @@ enum atl1c_dma_req_block {
atl1c_dma_req_4096 = 5
};
-enum atl1c_rss_mode {
- atl1c_rss_mode_disable = 0,
- atl1c_rss_sig_que = 1,
- atl1c_rss_mul_que_sig_int = 2,
- atl1c_rss_mul_que_mul_int = 4,
-};
-
-enum atl1c_rss_type {
- atl1c_rss_disable = 0,
- atl1c_rss_ipv4 = 1,
- atl1c_rss_ipv4_tcp = 2,
- atl1c_rss_ipv6 = 4,
- atl1c_rss_ipv6_tcp = 8
-};
enum atl1c_nic_type {
athr_l1c = 0,
@@ -451,9 +437,6 @@ struct atl1c_hw {
u16 tpd_thresh;
u8 tpd_burst; /* Number of TPD to prefetch in cache-aligned burst. */
u8 rfd_burst;
- enum atl1c_rss_type rss_type;
- enum atl1c_rss_mode rss_mode;
- u8 rss_hash_bits;
u32 base_cpu;
u32 indirect_tab;
u8 mac_addr[ETH_ALEN];
@@ -586,11 +569,10 @@ struct atl1c_adapter {
/* All Descriptor memory */
struct atl1c_ring_header ring_header;
struct atl1c_tpd_ring tpd_ring[AT_MAX_TRANSMIT_QUEUE];
- struct atl1c_rfd_ring rfd_ring[AT_MAX_RECEIVE_QUEUE];
- struct atl1c_rrd_ring rrd_ring[AT_MAX_RECEIVE_QUEUE];
+ struct atl1c_rfd_ring rfd_ring;
+ struct atl1c_rrd_ring rrd_ring;
struct atl1c_cmb cmb;
struct atl1c_smb smb;
- int num_rx_queues;
u32 bd_number; /* board number;*/
};
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
index 655fc6c..855aca0 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
@@ -461,17 +461,11 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw);
#define REG_SMB_BASE_ADDR_HI 0x1548
#define REG_SMB_BASE_ADDR_LO 0x154C
#define REG_RFD0_HEAD_ADDR_LO 0x1550
-#define REG_RFD1_HEAD_ADDR_LO 0x1554
-#define REG_RFD2_HEAD_ADDR_LO 0x1558
-#define REG_RFD3_HEAD_ADDR_LO 0x155C
#define REG_RFD_RING_SIZE 0x1560
#define RFD_RING_SIZE_MASK 0x0FFF
#define REG_RX_BUF_SIZE 0x1564
#define RX_BUF_SIZE_MASK 0xFFFF
#define REG_RRD0_HEAD_ADDR_LO 0x1568
-#define REG_RRD1_HEAD_ADDR_LO 0x156C
-#define REG_RRD2_HEAD_ADDR_LO 0x1570
-#define REG_RRD3_HEAD_ADDR_LO 0x1574
#define REG_RRD_RING_SIZE 0x1578
#define RRD_RING_SIZE_MASK 0x0FFF
#define REG_HTPD_HEAD_ADDR_LO 0x157C
@@ -480,30 +474,6 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw);
#define TPD_RING_SIZE_MASK 0xFFFF
#define REG_CMB_BASE_ADDR_LO 0x1588
-/* RSS about */
-#define REG_RSS_KEY0 0x14B0
-#define REG_RSS_KEY1 0x14B4
-#define REG_RSS_KEY2 0x14B8
-#define REG_RSS_KEY3 0x14BC
-#define REG_RSS_KEY4 0x14C0
-#define REG_RSS_KEY5 0x14C4
-#define REG_RSS_KEY6 0x14C8
-#define REG_RSS_KEY7 0x14CC
-#define REG_RSS_KEY8 0x14D0
-#define REG_RSS_KEY9 0x14D4
-#define REG_IDT_TABLE0 0x14E0
-#define REG_IDT_TABLE1 0x14E4
-#define REG_IDT_TABLE2 0x14E8
-#define REG_IDT_TABLE3 0x14EC
-#define REG_IDT_TABLE4 0x14F0
-#define REG_IDT_TABLE5 0x14F4
-#define REG_IDT_TABLE6 0x14F8
-#define REG_IDT_TABLE7 0x14FC
-#define REG_IDT_TABLE REG_IDT_TABLE0
-#define REG_RSS_HASH_VALUE 0x15B0
-#define REG_RSS_HASH_FLAG 0x15B4
-#define REG_BASE_CPU_NUMBER 0x15B8
-
/* TXQ Control Register */
#define REG_TXQ_CTRL 0x1590
#define TXQ_NUM_TPD_BURST_MASK 0xF
@@ -608,9 +578,6 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw);
/* Mail box */
#define MB_RFDX_PROD_IDX_MASK 0xFFFF
#define REG_MB_RFD0_PROD_IDX 0x15E0
-#define REG_MB_RFD1_PROD_IDX 0x15E4
-#define REG_MB_RFD2_PROD_IDX 0x15E8
-#define REG_MB_RFD3_PROD_IDX 0x15EC
#define MB_PRIO_PROD_IDX_MASK 0xFFFF
#define REG_MB_PRIO_PROD_IDX 0x15F0
@@ -625,9 +592,6 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw);
#define REG_MB_RFD01_CONS_IDX 0x15F8
#define MB_RFD0_CONS_IDX_MASK 0x0000FFFF
#define MB_RFD1_CONS_IDX_MASK 0xFFFF0000
-#define REG_MB_RFD23_CONS_IDX 0x15FC
-#define MB_RFD2_CONS_IDX_MASK 0x0000FFFF
-#define MB_RFD3_CONS_IDX_MASK 0xFFFF0000
/* Interrupt Status Register */
#define REG_ISR 0x1600
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index 1f1f9eb..226be99 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -66,7 +66,7 @@ static void atl1c_enable_tx_ctrl(struct atl1c_hw *hw);
static void atl1c_disable_l0s_l1(struct atl1c_hw *hw);
static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup);
static void atl1c_setup_mac_ctrl(struct atl1c_adapter *adapter);
-static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, u8 que,
+static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter,
int *work_done, int work_to_do);
static int atl1c_up(struct atl1c_adapter *adapter);
static void atl1c_down(struct atl1c_adapter *adapter);
@@ -75,29 +75,6 @@ static const u16 atl1c_pay_load_size[] = {
128, 256, 512, 1024, 2048, 4096,
};
-static const u16 atl1c_rfd_prod_idx_regs[AT_MAX_RECEIVE_QUEUE] =
-{
- REG_MB_RFD0_PROD_IDX,
- REG_MB_RFD1_PROD_IDX,
- REG_MB_RFD2_PROD_IDX,
- REG_MB_RFD3_PROD_IDX
-};
-
-static const u16 atl1c_rfd_addr_lo_regs[AT_MAX_RECEIVE_QUEUE] =
-{
- REG_RFD0_HEAD_ADDR_LO,
- REG_RFD1_HEAD_ADDR_LO,
- REG_RFD2_HEAD_ADDR_LO,
- REG_RFD3_HEAD_ADDR_LO
-};
-
-static const u16 atl1c_rrd_addr_lo_regs[AT_MAX_RECEIVE_QUEUE] =
-{
- REG_RRD0_HEAD_ADDR_LO,
- REG_RRD1_HEAD_ADDR_LO,
- REG_RRD2_HEAD_ADDR_LO,
- REG_RRD3_HEAD_ADDR_LO
-};
static const u32 atl1c_default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE |
NETIF_MSG_LINK | NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP;
@@ -730,9 +707,8 @@ static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter)
device_set_wakeup_enable(&pdev->dev, false);
adapter->link_speed = SPEED_0;
adapter->link_duplex = FULL_DUPLEX;
- adapter->num_rx_queues = AT_DEF_RECEIVE_QUEUE;
adapter->tpd_ring[0].count = 1024;
- adapter->rfd_ring[0].count = 512;
+ adapter->rfd_ring.count = 512;
hw->vendor_id = pdev->vendor;
hw->device_id = pdev->device;
@@ -751,14 +727,6 @@ static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter)
hw->phy_configured = false;
hw->preamble_len = 7;
hw->max_frame_size = adapter->netdev->mtu;
- if (adapter->num_rx_queues < 2) {
- hw->rss_type = atl1c_rss_disable;
- hw->rss_mode = atl1c_rss_mode_disable;
- } else {
- hw->rss_type = atl1c_rss_ipv4;
- hw->rss_mode = atl1c_rss_mul_que_mul_int;
- hw->rss_hash_bits = 16;
- }
hw->autoneg_advertised = ADVERTISED_Autoneg;
hw->indirect_tab = 0xE4E4E4E4;
hw->base_cpu = 0;
@@ -852,24 +820,22 @@ static void atl1c_clean_tx_ring(struct atl1c_adapter *adapter,
*/
static void atl1c_clean_rx_ring(struct atl1c_adapter *adapter)
{
- struct atl1c_rfd_ring *rfd_ring = adapter->rfd_ring;
- struct atl1c_rrd_ring *rrd_ring = adapter->rrd_ring;
+ struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring;
+ struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring;
struct atl1c_buffer *buffer_info;
struct pci_dev *pdev = adapter->pdev;
- int i, j;
+ int j;
- for (i = 0; i < adapter->num_rx_queues; i++) {
- for (j = 0; j < rfd_ring[i].count; j++) {
- buffer_info = &rfd_ring[i].buffer_info[j];
- atl1c_clean_buffer(pdev, buffer_info, 0);
- }
- /* zero out the descriptor ring */
- memset(rfd_ring[i].desc, 0, rfd_ring[i].size);
- rfd_ring[i].next_to_clean = 0;
- rfd_ring[i].next_to_use = 0;
- rrd_ring[i].next_to_use = 0;
- rrd_ring[i].next_to_clean = 0;
+ for (j = 0; j < rfd_ring->count; j++) {
+ buffer_info = &rfd_ring->buffer_info[j];
+ atl1c_clean_buffer(pdev, buffer_info, 0);
}
+ /* zero out the descriptor ring */
+ memset(rfd_ring->desc, 0, rfd_ring->size);
+ rfd_ring->next_to_clean = 0;
+ rfd_ring->next_to_use = 0;
+ rrd_ring->next_to_use = 0;
+ rrd_ring->next_to_clean = 0;
}
/*
@@ -878,8 +844,8 @@ static void atl1c_clean_rx_ring(struct atl1c_adapter *adapter)
static void atl1c_init_ring_ptrs(struct atl1c_adapter *adapter)
{
struct atl1c_tpd_ring *tpd_ring = adapter->tpd_ring;
- struct atl1c_rfd_ring *rfd_ring = adapter->rfd_ring;
- struct atl1c_rrd_ring *rrd_ring = adapter->rrd_ring;
+ struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring;
+ struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring;
struct atl1c_buffer *buffer_info;
int i, j;
@@ -891,15 +857,13 @@ static void atl1c_init_ring_ptrs(struct atl1c_adapter *adapter)
ATL1C_SET_BUFFER_STATE(&buffer_info[i],
ATL1C_BUFFER_FREE);
}
- for (i = 0; i < adapter->num_rx_queues; i++) {
- rfd_ring[i].next_to_use = 0;
- rfd_ring[i].next_to_clean = 0;
- rrd_ring[i].next_to_use = 0;
- rrd_ring[i].next_to_clean = 0;
- for (j = 0; j < rfd_ring[i].count; j++) {
- buffer_info = &rfd_ring[i].buffer_info[j];
- ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_FREE);
- }
+ rfd_ring->next_to_use = 0;
+ rfd_ring->next_to_clean = 0;
+ rrd_ring->next_to_use = 0;
+ rrd_ring->next_to_clean = 0;
+ for (j = 0; j < rfd_ring->count; j++) {
+ buffer_info = &rfd_ring->buffer_info[j];
+ ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_FREE);
}
}
@@ -936,27 +900,23 @@ static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter)
{
struct pci_dev *pdev = adapter->pdev;
struct atl1c_tpd_ring *tpd_ring = adapter->tpd_ring;
- struct atl1c_rfd_ring *rfd_ring = adapter->rfd_ring;
- struct atl1c_rrd_ring *rrd_ring = adapter->rrd_ring;
+ struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring;
+ struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring;
struct atl1c_ring_header *ring_header = &adapter->ring_header;
- int num_rx_queues = adapter->num_rx_queues;
int size;
int i;
int count = 0;
int rx_desc_count = 0;
u32 offset = 0;
- rrd_ring[0].count = rfd_ring[0].count;
+ rrd_ring->count = rfd_ring->count;
for (i = 1; i < AT_MAX_TRANSMIT_QUEUE; i++)
tpd_ring[i].count = tpd_ring[0].count;
- for (i = 1; i < adapter->num_rx_queues; i++)
- rfd_ring[i].count = rrd_ring[i].count = rfd_ring[0].count;
-
/* 2 tpd queue, one high priority queue,
* another normal priority queue */
size = sizeof(struct atl1c_buffer) * (tpd_ring->count * 2 +
- rfd_ring->count * num_rx_queues);
+ rfd_ring->count);
tpd_ring->buffer_info = kzalloc(size, GFP_KERNEL);
if (unlikely(!tpd_ring->buffer_info)) {
dev_err(&pdev->dev, "kzalloc failed, size = %d\n",
@@ -969,12 +929,11 @@ static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter)
count += tpd_ring[i].count;
}
- for (i = 0; i < num_rx_queues; i++) {
- rfd_ring[i].buffer_info =
- (struct atl1c_buffer *) (tpd_ring->buffer_info + count);
- count += rfd_ring[i].count;
- rx_desc_count += rfd_ring[i].count;
- }
+ rfd_ring->buffer_info =
+ (struct atl1c_buffer *) (tpd_ring->buffer_info + count);
+ count += rfd_ring->count;
+ rx_desc_count += rfd_ring->count;
+
/*
* real ring DMA buffer
* each ring/block may need up to 8 bytes for alignment, hence the
@@ -985,7 +944,7 @@ static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter)
sizeof(struct atl1c_rx_free_desc) * rx_desc_count +
sizeof(struct atl1c_recv_ret_status) * rx_desc_count +
sizeof(struct atl1c_hw_stats) +
- 8 * 4 + 8 * 2 * num_rx_queues;
+ 8 * 4 + 8 * 2;
ring_header->desc = pci_alloc_consistent(pdev, ring_header->size,
&ring_header->dma);
@@ -1006,22 +965,17 @@ static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter)
offset += roundup(tpd_ring[i].size, 8);
}
/* init RFD ring */
- for (i = 0; i < num_rx_queues; i++) {
- rfd_ring[i].dma = ring_header->dma + offset;
- rfd_ring[i].desc = (u8 *) ring_header->desc + offset;
- rfd_ring[i].size = sizeof(struct atl1c_rx_free_desc) *
- rfd_ring[i].count;
- offset += roundup(rfd_ring[i].size, 8);
- }
+ rfd_ring->dma = ring_header->dma + offset;
+ rfd_ring->desc = (u8 *) ring_header->desc + offset;
+ rfd_ring->size = sizeof(struct atl1c_rx_free_desc) * rfd_ring->count;
+ offset += roundup(rfd_ring->size, 8);
/* init RRD ring */
- for (i = 0; i < num_rx_queues; i++) {
- rrd_ring[i].dma = ring_header->dma + offset;
- rrd_ring[i].desc = (u8 *) ring_header->desc + offset;
- rrd_ring[i].size = sizeof(struct atl1c_recv_ret_status) *
- rrd_ring[i].count;
- offset += roundup(rrd_ring[i].size, 8);
- }
+ rrd_ring->dma = ring_header->dma + offset;
+ rrd_ring->desc = (u8 *) ring_header->desc + offset;
+ rrd_ring->size = sizeof(struct atl1c_recv_ret_status) *
+ rrd_ring->count;
+ offset += roundup(rrd_ring->size, 8);
adapter->smb.dma = ring_header->dma + offset;
adapter->smb.smb = (u8 *)ring_header->desc + offset;
@@ -1035,15 +989,12 @@ err_nomem:
static void atl1c_configure_des_ring(struct atl1c_adapter *adapter)
{
struct atl1c_hw *hw = &adapter->hw;
- struct atl1c_rfd_ring *rfd_ring = (struct atl1c_rfd_ring *)
- adapter->rfd_ring;
- struct atl1c_rrd_ring *rrd_ring = (struct atl1c_rrd_ring *)
- adapter->rrd_ring;
+ struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring;
+ struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring;
struct atl1c_tpd_ring *tpd_ring = (struct atl1c_tpd_ring *)
adapter->tpd_ring;
struct atl1c_cmb *cmb = (struct atl1c_cmb *) &adapter->cmb;
struct atl1c_smb *smb = (struct atl1c_smb *) &adapter->smb;
- int i;
u32 data;
/* TPD */
@@ -1063,22 +1014,20 @@ static void atl1c_configure_des_ring(struct atl1c_adapter *adapter)
/* RFD */
AT_WRITE_REG(hw, REG_RX_BASE_ADDR_HI,
- (u32)((rfd_ring[0].dma & AT_DMA_HI_ADDR_MASK) >> 32));
- for (i = 0; i < adapter->num_rx_queues; i++)
- AT_WRITE_REG(hw, atl1c_rfd_addr_lo_regs[i],
- (u32)(rfd_ring[i].dma & AT_DMA_LO_ADDR_MASK));
+ (u32)((rfd_ring->dma & AT_DMA_HI_ADDR_MASK) >> 32));
+ AT_WRITE_REG(hw, REG_RFD0_HEAD_ADDR_LO,
+ (u32)(rfd_ring->dma & AT_DMA_LO_ADDR_MASK));
AT_WRITE_REG(hw, REG_RFD_RING_SIZE,
- rfd_ring[0].count & RFD_RING_SIZE_MASK);
+ rfd_ring->count & RFD_RING_SIZE_MASK);
AT_WRITE_REG(hw, REG_RX_BUF_SIZE,
adapter->rx_buffer_len & RX_BUF_SIZE_MASK);
/* RRD */
- for (i = 0; i < adapter->num_rx_queues; i++)
- AT_WRITE_REG(hw, atl1c_rrd_addr_lo_regs[i],
- (u32)(rrd_ring[i].dma & AT_DMA_LO_ADDR_MASK));
+ AT_WRITE_REG(hw, REG_RRD0_HEAD_ADDR_LO,
+ (u32)(rrd_ring->dma & AT_DMA_LO_ADDR_MASK));
AT_WRITE_REG(hw, REG_RRD_RING_SIZE,
- (rrd_ring[0].count & RRD_RING_SIZE_MASK));
+ (rrd_ring->count & RRD_RING_SIZE_MASK));
/* CMB */
AT_WRITE_REG(hw, REG_CMB_BASE_ADDR_LO, cmb->dma & AT_DMA_LO_ADDR_MASK);
@@ -1152,21 +1101,7 @@ static void atl1c_configure_rx(struct atl1c_adapter *adapter)
if (hw->ctrl_flags & ATL1C_RX_IPV6_CHKSUM)
rxq_ctrl_data |= IPV6_CHKSUM_CTRL_EN;
- if (hw->rss_type == atl1c_rss_ipv4)
- rxq_ctrl_data |= RSS_HASH_IPV4;
- if (hw->rss_type == atl1c_rss_ipv4_tcp)
- rxq_ctrl_data |= RSS_HASH_IPV4_TCP;
- if (hw->rss_type == atl1c_rss_ipv6)
- rxq_ctrl_data |= RSS_HASH_IPV6;
- if (hw->rss_type == atl1c_rss_ipv6_tcp)
- rxq_ctrl_data |= RSS_HASH_IPV6_TCP;
- if (hw->rss_type != atl1c_rss_disable)
- rxq_ctrl_data |= RRS_HASH_CTRL_EN;
- rxq_ctrl_data |= (hw->rss_mode & RSS_MODE_MASK) <<
- RSS_MODE_SHIFT;
- rxq_ctrl_data |= (hw->rss_hash_bits & RSS_HASH_BITS_MASK) <<
- RSS_HASH_BITS_SHIFT;
if (hw->ctrl_flags & ATL1C_ASPM_CTRL_MON)
rxq_ctrl_data |= (ASPM_THRUPUT_LIMIT_1M &
ASPM_THRUPUT_LIMIT_MASK) << ASPM_THRUPUT_LIMIT_SHIFT;
@@ -1174,14 +1109,6 @@ static void atl1c_configure_rx(struct atl1c_adapter *adapter)
AT_WRITE_REG(hw, REG_RXQ_CTRL, rxq_ctrl_data);
}
-static void atl1c_configure_rss(struct atl1c_adapter *adapter)
-{
- struct atl1c_hw *hw = &adapter->hw;
-
- AT_WRITE_REG(hw, REG_IDT_TABLE, hw->indirect_tab);
- AT_WRITE_REG(hw, REG_BASE_CPU_NUMBER, hw->base_cpu);
-}
-
static void atl1c_configure_dma(struct atl1c_adapter *adapter)
{
struct atl1c_hw *hw = &adapter->hw;
@@ -1253,19 +1180,6 @@ static void atl1c_enable_rx_ctrl(struct atl1c_hw *hw)
u32 data;
AT_READ_REG(hw, REG_RXQ_CTRL, &data);
- switch (hw->adapter->num_rx_queues) {
- case 4:
- data |= (RXQ3_CTRL_EN | RXQ2_CTRL_EN | RXQ1_CTRL_EN);
- break;
- case 3:
- data |= (RXQ2_CTRL_EN | RXQ1_CTRL_EN);
- break;
- case 2:
- data |= RXQ1_CTRL_EN;
- break;
- default:
- break;
- }
data |= RXQ_CTRL_EN;
AT_WRITE_REG(hw, REG_RXQ_CTRL, data);
}
@@ -1544,7 +1458,6 @@ static int atl1c_configure(struct atl1c_adapter *adapter)
atl1c_configure_tx(adapter);
atl1c_configure_rx(adapter);
- atl1c_configure_rss(adapter);
atl1c_configure_dma(adapter);
return 0;
@@ -1747,9 +1660,9 @@ static inline void atl1c_rx_checksum(struct atl1c_adapter *adapter,
skb_checksum_none_assert(skb);
}
-static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter, const int ringid)
+static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter)
{
- struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring[ringid];
+ struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring;
struct pci_dev *pdev = adapter->pdev;
struct atl1c_buffer *buffer_info, *next_info;
struct sk_buff *skb;
@@ -1801,7 +1714,7 @@ static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter, const int ringid
/* TODO: update mailbox here */
wmb();
rfd_ring->next_to_use = rfd_next_to_use;
- AT_WRITE_REG(&adapter->hw, atl1c_rfd_prod_idx_regs[ringid],
+ AT_WRITE_REG(&adapter->hw, REG_MB_RFD0_PROD_IDX,
rfd_ring->next_to_use & MB_RFDX_PROD_IDX_MASK);
}
@@ -1840,7 +1753,7 @@ static void atl1c_clean_rfd(struct atl1c_rfd_ring *rfd_ring,
rfd_ring->next_to_clean = rfd_index;
}
-static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, u8 que,
+static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter,
int *work_done, int work_to_do)
{
u16 rfd_num, rfd_index;
@@ -1848,8 +1761,8 @@ static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, u8 que,
u16 length;
struct pci_dev *pdev = adapter->pdev;
struct net_device *netdev = adapter->netdev;
- struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring[que];
- struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring[que];
+ struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring;
+ struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring;
struct sk_buff *skb;
struct atl1c_recv_ret_status *rrs;
struct atl1c_buffer *buffer_info;
@@ -1915,7 +1828,7 @@ rrs_checked:
count++;
}
if (count)
- atl1c_alloc_rx_buffer(adapter, que);
+ atl1c_alloc_rx_buffer(adapter);
}
/*
@@ -1932,7 +1845,7 @@ static int atl1c_clean(struct napi_struct *napi, int budget)
if (!netif_carrier_ok(adapter->netdev))
goto quit_polling;
/* just enable one RXQ */
- atl1c_clean_rx_irq(adapter, 0, &work_done, budget);
+ atl1c_clean_rx_irq(adapter, &work_done, budget);
if (work_done < budget) {
quit_polling:
@@ -2334,19 +2247,16 @@ static int atl1c_up(struct atl1c_adapter *adapter)
struct net_device *netdev = adapter->netdev;
int num;
int err;
- int i;
netif_carrier_off(netdev);
atl1c_init_ring_ptrs(adapter);
atl1c_set_multi(netdev);
atl1c_restore_vlan(adapter);
- for (i = 0; i < adapter->num_rx_queues; i++) {
- num = atl1c_alloc_rx_buffer(adapter, i);
- if (unlikely(num == 0)) {
- err = -ENOMEM;
- goto err_alloc_rx;
- }
+ num = atl1c_alloc_rx_buffer(adapter);
+ if (unlikely(num == 0)) {
+ err = -ENOMEM;
+ goto err_alloc_rx;
}
if (atl1c_configure(adapter)) {
--
1.7.7
^ permalink raw reply related
* [PATCH 01/12] atl1c: update author contact info & company/driver desciption
From: xiong @ 2012-04-18 5:32 UTC (permalink / raw)
To: davem, netdev, linux-kernel; +Cc: qca-linux-team, nic-devel, xiong
In-Reply-To: <1334727156-6830-1-git-send-email-xiong@qca.qualcomm.com>
replace unavailable email of the author since he left with a mail-list.
update company info as well, Atheros was acquired by Qualcomm.
insert "100" to driver description since it support 100M controller.
Signed-off-by: xiong <xiong@qca.qualcomm.com>
Tested-by: Liu David <dwliu@qca.qualcomm.com>
---
drivers/net/ethernet/atheros/atl1c/atl1c_main.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index 1ef0c92..1f1f9eb 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -54,8 +54,9 @@ static DEFINE_PCI_DEVICE_TABLE(atl1c_pci_tbl) = {
};
MODULE_DEVICE_TABLE(pci, atl1c_pci_tbl);
-MODULE_AUTHOR("Jie Yang <jie.yang@atheros.com>");
-MODULE_DESCRIPTION("Atheros 1000M Ethernet Network Driver");
+MODULE_AUTHOR("Jie Yang");
+MODULE_AUTHOR("Qualcomm Atheros Inc., <nic-devel@qualcomm.com>");
+MODULE_DESCRIPTION("Qualcom Atheros 100/1000M Ethernet Network Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(ATL1C_DRV_VERSION);
--
1.7.7
^ permalink raw reply related
* Re: [PATCH] stmmac: fix kernel crash when device probed for SPEAr with DT
From: Viresh Kumar @ 2012-04-18 5:14 UTC (permalink / raw)
To: Giuseppe CAVALLARO
Cc: spear-devel, viresh.linux@gmail.com, netdev@vger.kernel.org,
davem@davemloft.net, Deepak SIKRI
In-Reply-To: <4F8E4CEC.9050002@st.com>
On 4/18/2012 10:41 AM, Giuseppe CAVALLARO wrote:
> I hoped it was fully tested on SPEAr platforms. at any rate
I am only working for SPEAr3xx with DT support and this patch is must as
without it we have build failures. Haven't tested on any other SPEAr SoCs, they
may require extra pdata fields to be initialized, but that will follow with
their DT support.
--
viresh
^ permalink raw reply
* Re: [PATCH] stmmac: fix kernel crash when device probed for SPEAr with DT
From: Giuseppe CAVALLARO @ 2012-04-18 5:11 UTC (permalink / raw)
To: Viresh KUMAR; +Cc: spear-devel, viresh.linux, netdev, davem, Deepak SIKRI
In-Reply-To: <91ea900ce78bb2054d83e0575c16ac70f3f11511.1334654597.git.viresh.kumar@st.com>
Hi Viresh
On 4/17/2012 11:24 AM, Viresh KUMAR wrote:
> plat->dma_cfg is never allocated memory and is tried to be filled when we boot
> it for SPEAr SoCs with DT. And so get a kernel crash.
>
> Fix it by allocating memory for dma_cfg.
The fix seems to be legal but I'd like to do a review of the code again.
I was reluctant to add the dma_cfg because it had a big impact on
several platforms etc (as discussed with SPEAr guys). I accepted it
because logically correct and tidied-up the code, indeed.
I hoped it was fully tested on SPEAr platforms. at any rate, I'll look
at you patch and perform some tests on my boards and then come-back to you.
Kind Regards
Peppe
>
> Signed-off-by: Viresh Kumar <viresh.kumar@st.com>
> ---
> .../net/ethernet/stmicro/stmmac/stmmac_platform.c | 8 ++++++++
> 1 files changed, 8 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
> index 12bd221..f124f60 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
> @@ -110,6 +110,14 @@ static int stmmac_pltfr_probe(struct platform_device *pdev)
> goto out_unmap;
> }
>
> + plat_dat->dma_cfg = devm_kzalloc(&pdev->dev,
> + sizeof(*plat_dat->dma_cfg), GFP_KERNEL);
> + if (!plat_dat->dma_cfg) {
> + pr_err("%s: ERROR: no memory for dma_cfg", __func__);
> + ret = -ENOMEM;
> + goto out_unmap;
> + }
> +
> ret = stmmac_probe_config_dt(pdev, plat_dat, &mac);
> if (ret) {
> pr_err("%s: main dt probe failed", __func__);
^ permalink raw reply
* [PATCH net-next] netfilter: nf_conntrack.h: use this_cpu_inc()
From: Eric Dumazet @ 2012-04-18 4:36 UTC (permalink / raw)
To: Pablo Neira Ayuso
Cc: linux-kernel, netdev, Christoph Lameter, Tejun Heo,
Patrick McHardy
From: Eric Dumazet <edumazet@google.com>
this_cpu_inc() is IRQ safe and faster than
local_bh_disable()/__this_cpu_inc()/local_bh_enable(), at least on x86.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Patrick McHardy <kaber@trash.net>
Cc: Christoph Lameter <cl@linux.com>
Cc: Tejun Heo <tj@kernel.org>
---
include/net/netfilter/nf_conntrack.h | 10 ++--------
1 file changed, 2 insertions(+), 8 deletions(-)
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index ab86036..cce7f6a 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -321,14 +321,8 @@ extern unsigned int nf_conntrack_max;
extern unsigned int nf_conntrack_hash_rnd;
void init_nf_conntrack_hash_rnd(void);
-#define NF_CT_STAT_INC(net, count) \
- __this_cpu_inc((net)->ct.stat->count)
-#define NF_CT_STAT_INC_ATOMIC(net, count) \
-do { \
- local_bh_disable(); \
- __this_cpu_inc((net)->ct.stat->count); \
- local_bh_enable(); \
-} while (0)
+#define NF_CT_STAT_INC(net, count) __this_cpu_inc((net)->ct.stat->count)
+#define NF_CT_STAT_INC_ATOMIC(net, count) this_cpu_inc((net)->ct.stat->count)
#define MODULE_ALIAS_NFCT_HELPER(helper) \
MODULE_ALIAS("nfct-helper-" helper)
^ permalink raw reply related
* Re: [RFC PATCH 2/2] l2tp: Introduce L2TPv3 IP encapsulation support for IPv6
From: David Miller @ 2012-04-18 4:28 UTC (permalink / raw)
To: jchapman; +Cc: netdev, bcrl
In-Reply-To: <1334665766-11461-3-git-send-email-jchapman@katalix.com>
From: James Chapman <jchapman@katalix.com>
Date: Tue, 17 Apr 2012 13:29:26 +0100
> L2TPv3 defines an IP encapsulation packet format where data is carried
> directly over IP (no UDP). The kernel already has support for L2TP IP
> encapsulation over IPv4 (l2tp_ip). This patch introduces support for L2TP
> IP encapsulation over IPv6.
Either the ipv4 side should be changed to use ip4_datagram_connect()
or the ipv6 side should duplicate just the parts of
ip6_datagram_connect() it needs.
Which is it? :-)
^ permalink raw reply
* Re: [PATCH] net/ipv4:Remove two memleak reports by kmemeleak_not_leak.
From: David Miller @ 2012-04-18 4:22 UTC (permalink / raw)
To: majianpeng; +Cc: eric.dumazet, netdev
In-Reply-To: <201204171333149372727@gmail.com>
From: "majianpeng" <majianpeng@gmail.com>
Date: Tue, 17 Apr 2012 13:33:31 +0800
>>From fe9ae7e12cc7bdc56705eb504facb71aa86dfe65 Mon Sep 17 00:00:00 2001
> From: majianpeng <majianpeng@gmail.com>
> Date: Tue, 17 Apr 2012 13:29:55 +0800
> Subject: [PATCH] net/ipv4:Remove two memleak reports by kmemeleak_not_leak.
>
>
> Signed-off-by: majianpeng <majianpeng@gmail.com>
I've applied both of your patches, but you are EXTREMELY careless
with your commit log messages and subject lines.
In this patch, and the net/core one, you misspell "kmemleak_not_leak"
In the net/core patch, you failed to separate "by" and "kmemleak_not_leak"
with a space in the Subject line.
Furthermore, it is extraneous to include the same From:, Date:, and
Subject: fields in the body of your email. They are just fine in
your normal email headers.
Thanks.
^ permalink raw reply
* Re: [patch] Fix handling of overlength pathname in AF_UNIX sun_path
From: David Miller @ 2012-04-18 4:16 UTC (permalink / raw)
To: carlos-v2tUB8YBRSi3e3T8WW9gsA
Cc: mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w,
netdev-u79uwXL29TY76Z2rM5mHXA,
penguin-kernel-1yMVhJb1mP/7nzcFbJAaVXf5DAMn2ifp,
linux-api-u79uwXL29TY76Z2rM5mHXA, yoshfuji-VfPWfsRibaP+Ru+s062T9g,
jengelh-nopoi9nDyk+ELgA04lAiVw, w,
alan-qBU/x9rampVanCEyBjwyrvXRex20P6io
In-Reply-To: <CADZpyix6DZ93f8MQf3Aa1NVV7HCFMAXVAdzRMFBY7xWHHQMPog-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
From: "Carlos O'Donell" <carlos-v2tUB8YBRSi3e3T8WW9gsA@public.gmane.org>
Date: Wed, 18 Apr 2012 00:08:47 -0400
> I don't clearly understand your position here, and perhaps that's my
> own ignorance, but could you please clarify, with examples, exactly
> why the change is not acceptable?
My position is that since millions upon millions of Linux systems, in
fact every single Linux system, exists right now with the current
behavior we are not helping application writers at all by changing
behavior now after it's been this way for nearly 20 years.
Because if an application writer wants his code to work on systems
that actually exist he has to accomodate the non-NULL termination
situation if he wants to inspect or print out an AF_UNIX path.
Because every system in existence right now allows the non-NULL
terminated AF_UNIX paths, therefore it's possible on every system
in existence right now.
Catch my drift?
The very thing the patch claims to help, it doesn't. We install this
kernel patch now and then tell application writers that they can just
assume all AF_UNIX paths are NULL terminated when they want to print
it out, because such code will not actually be guarenteed to work on
all deployed Linux machines out there.
You cannot just ignore 20 years of precedence and say "oh let's change
this in the kernel now, and that way application writers don't have to
worry about that lack of NULL termination any more." It simply
doesn't work like that.
All of this talk about whether applications actually create non-NULL
terminated AF_UNIX paths don't even factor into the conversation.
So the value proposition for this patch simply does not exist.
^ permalink raw reply
* Re: [patch] Fix handling of overlength pathname in AF_UNIX sun_path
From: Carlos O'Donell @ 2012-04-18 4:08 UTC (permalink / raw)
To: David Miller
Cc: mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w,
netdev-u79uwXL29TY76Z2rM5mHXA,
penguin-kernel-1yMVhJb1mP/7nzcFbJAaVXf5DAMn2ifp,
linux-api-u79uwXL29TY76Z2rM5mHXA, yoshfuji-VfPWfsRibaP+Ru+s062T9g,
jengelh-nopoi9nDyk+ELgA04lAiVw, w,
alan-qBU/x9rampVanCEyBjwyrvXRex20P6io
In-Reply-To: <20120417.223614.629911246108750471.davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
On Tue, Apr 17, 2012 at 10:36 PM, David Miller <davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org> wrote:
> From: Michael Kerrisk <mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Date: Tue, 17 Apr 2012 22:44:15 +1200
>
>> 1. Changing the kernel behavior prevents userspace having
>> to go through the sort of contortions described above
>> in order to handle the 108-non-NUL-bytes-in-sun_path case.
>
> The problem with this logic is that it ignores every single Linux
> system that exists right now.
>
> You need to code this logic into your application unless you don't
> want it to run properly on every Linux system that actually exists.
>
> Sorry, we're not making this change.
Dave,
I don't clearly understand your position here, and perhaps that's my
own ignorance, but could you please clarify, with examples, exactly
why the change is not acceptable? I can see several valid arguments
against the change, but I don't know which argument your position
asserts.
One might assert that careless userspace applications exist that pass
`sizeof(struct sockaddr_un)' (or worse) as the 3rd argument to bind
instead of SUN_LEN(my_sock). The logic in the patch doesn't account
for this, and can't really, and would therefore unacceptably break
existing applications by trying to assert the location of a \0 where
one doesn't exist. The kernel must therefore continue to
null-terminate at the specified length, possibly the 109th character,
and use strlen to capture the true length of the path. The kernel
knows that in the worst case a non-null terminated path might contain
some garbage, but that's the users fault, and the logic to prevent
this must exist in the application not the kernel.
The counter argument to all of this is that it's a QoI issue, and that
the kernel shouldn't accept accidentally non-null terminated paths,
and should instead return EINVAL for them. Not to mention that it's
difficult for userspace to easily catch this error in glibc which
would need to inspect the sockaddr, duplicating kernel code.
Why is it valid for the user path to have no null terminator?
Why not have:
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index d510353..f9f77a7 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -216,6 +216,9 @@ static int unix_mkname(struct sockaddr_un
*sunaddr, int len, unsigned *hashp)
*/
((char *)sunaddr)[len] = 0;
len = strlen(sunaddr->sun_path)+1+sizeof(short);
+ /* No null terminator was found in the path. */
+ if (len > sizeof(*sunaddr))
+ return -EINVAL;
return len;
}
---
Does that make sense?
Cheers,
Carlos.
^ permalink raw reply related
* Re: [PATCH] netns: do not leak net_generic data on failed init
From: David Miller @ 2012-04-18 4:05 UTC (permalink / raw)
To: ebiederm; +Cc: ja, netdev
In-Reply-To: <m1wr5d3cyv.fsf@fess.ebiederm.org>
From: ebiederm@xmission.com (Eric W. Biederman)
Date: Tue, 17 Apr 2012 21:01:28 -0700
> Julian Anastasov <ja@ssi.bg> writes:
>
>> ops_init should free the net_generic data on
>> init failure and __register_pernet_operations should not
>> call ops_free when NET_NS is not enabled.
>
> The subject is good.
>
> There is most definitely a leak with us not freeing the net_generic data
> on ops_init failure. Having ops_init just take care of it seems like
> the logical place as it makes for simple analysis.
>
> The bit about __register_pernet_operations should not call ops_free when
> NET_NS is not enabled is a bad comment. We just need to move the
> ops_free into ops_init on failure, which is what your patch does.
>
> Without your patch the only caller of ops_init that doesn't leak today
> is __register_pernet_operations in !CONFIG_NET_NS, precisely because
> it does that ops_free.
>
> Now all of that said I have just read through everything and
> patch cleanly fixes a rare but real memory leak, and leaves
> the code in better state then it is today.
>
> David please apply this patch.
>
> Reviewed-by: "Eric W. Biederman" <ebiederm@xmission.com>
Done, thanks Eric.
^ permalink raw reply
* Re: [PATCH] netns: do not leak net_generic data on failed init
From: Eric W. Biederman @ 2012-04-18 4:01 UTC (permalink / raw)
To: Julian Anastasov; +Cc: netdev
In-Reply-To: <1334587395-6033-1-git-send-email-ja@ssi.bg>
Julian Anastasov <ja@ssi.bg> writes:
> ops_init should free the net_generic data on
> init failure and __register_pernet_operations should not
> call ops_free when NET_NS is not enabled.
The subject is good.
There is most definitely a leak with us not freeing the net_generic data
on ops_init failure. Having ops_init just take care of it seems like
the logical place as it makes for simple analysis.
The bit about __register_pernet_operations should not call ops_free when
NET_NS is not enabled is a bad comment. We just need to move the
ops_free into ops_init on failure, which is what your patch does.
Without your patch the only caller of ops_init that doesn't leak today
is __register_pernet_operations in !CONFIG_NET_NS, precisely because
it does that ops_free.
Now all of that said I have just read through everything and
patch cleanly fixes a rare but real memory leak, and leaves
the code in better state then it is today.
David please apply this patch.
Reviewed-by: "Eric W. Biederman" <ebiederm@xmission.com>
> Signed-off-by: Julian Anastasov <ja@ssi.bg>
> ---
> net/core/net_namespace.c | 33 ++++++++++++++++++---------------
> 1 files changed, 18 insertions(+), 15 deletions(-)
>
> diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
> index 0e950fd..31a5ae5 100644
> --- a/net/core/net_namespace.c
> +++ b/net/core/net_namespace.c
> @@ -83,21 +83,29 @@ assign:
>
> static int ops_init(const struct pernet_operations *ops, struct net *net)
> {
> - int err;
> + int err = -ENOMEM;
> + void *data = NULL;
> +
> if (ops->id && ops->size) {
> - void *data = kzalloc(ops->size, GFP_KERNEL);
> + data = kzalloc(ops->size, GFP_KERNEL);
> if (!data)
> - return -ENOMEM;
> + goto out;
>
> err = net_assign_generic(net, *ops->id, data);
> - if (err) {
> - kfree(data);
> - return err;
> - }
> + if (err)
> + goto cleanup;
> }
> + err = 0;
> if (ops->init)
> - return ops->init(net);
> - return 0;
> + err = ops->init(net);
> + if (!err)
> + return 0;
> +
> +cleanup:
> + kfree(data);
> +
> +out:
> + return err;
> }
>
> static void ops_free(const struct pernet_operations *ops, struct net *net)
> @@ -448,12 +456,7 @@ static void __unregister_pernet_operations(struct pernet_operations *ops)
> static int __register_pernet_operations(struct list_head *list,
> struct pernet_operations *ops)
> {
> - int err = 0;
> - err = ops_init(ops, &init_net);
> - if (err)
> - ops_free(ops, &init_net);
> - return err;
> -
> + return ops_init(ops, &init_net);
> }
>
> static void __unregister_pernet_operations(struct pernet_operations *ops)
^ permalink raw reply
* Re: [PATCH] net: filter: remove unused cpu_off
From: Eric Dumazet @ 2012-04-18 3:48 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20120417.232106.186221097843548596.davem@davemloft.net>
On Tue, 2012-04-17 at 23:21 -0400, David Miller wrote:
> They all had sparc in them :-)
>
> David S. Miller (3):
> net: filter: Just In Time compiler for sparc
> net: filter: Fix some minor issues in sparc JIT.
> net: filter: Fix some more small issues in sparc JIT.
>
Oh forget this, it was 5am here and I misread your reply ;)
^ permalink raw reply
* Re: [PATCH] net: filter: remove unused cpu_off
From: David Miller @ 2012-04-18 3:21 UTC (permalink / raw)
To: eric.dumazet; +Cc: netdev
In-Reply-To: <1334717992.2472.75.camel@edumazet-glaptop>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Wed, 18 Apr 2012 04:59:52 +0200
> On Tue, 2012-04-17 at 22:57 -0400, David Miller wrote:
>> From: Eric Dumazet <eric.dumazet@gmail.com>
>> Date: Wed, 18 Apr 2012 04:51:19 +0200
>>
>> > Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
>>
>> Applied, but I added "in sparc JIT" to the subject line.
>>
>> Thanks.
>
> No problem, I just copy/pasted your own subjects for this file
They all had sparc in them :-)
David S. Miller (3):
net: filter: Just In Time compiler for sparc
net: filter: Fix some minor issues in sparc JIT.
net: filter: Fix some more small issues in sparc JIT.
^ permalink raw reply
* Re: TSO not 10G friendly if peer is close enough
From: Eric Dumazet @ 2012-04-18 3:00 UTC (permalink / raw)
To: David Miller
Cc: alexander.h.duyck, jeffrey.t.kirsher, donald.c.skidmore,
gregory.v.rose, john.r.fastabend, jesse.brandeburg, netdev
In-Reply-To: <20120417.174759.327568768780440362.davem@davemloft.net>
On Tue, 2012-04-17 at 17:47 -0400, David Miller wrote:
> From: Eric Dumazet <eric.dumazet@gmail.com>
> Date: Tue, 17 Apr 2012 23:38:42 +0200
>
> > Hmm... maybe tcp_trim_head should not trim but only update an offset in
> > skb... With some luck, offset can reach skb->len when all data is
> > ACKnowledged...
>
> This is definitely the way to fix this. Just essentially defer all
> the page operations until later when the entire SKB is consumed.
Yes, I'll implement this today.
Thanks
^ permalink raw reply
* Re: [PATCH net-next] dmfe: enforce consistent timing delay.
From: David Miller @ 2012-04-18 2:59 UTC (permalink / raw)
To: grantgrundler; +Cc: romieu, netdev
In-Reply-To: <CANEJEGsb6_6btnu4OdriK=V2MbHcmxmvGy8UgsjNG1VPS_B0oQ@mail.gmail.com>
From: Grant Grundler <grantgrundler@gmail.com>
Date: Tue, 17 Apr 2012 14:45:38 -0700
> On Tue, Apr 17, 2012 at 2:11 PM, Francois Romieu <romieu@fr.zoreil.com> wrote:
>> The driver does not always use the same timing for what looks like
>> the same operations.
>>
>> - DCR0
>> Use the same udelay everywhere for reset. Upper bound is 100 us.
>> - DCR9
>> Use 5us delay for srom clock. 1us delay for phy_write_1bit (writes
>> PHY_DATA_[01]) are not changed as they stay withing a 2,5MHz MDIO
>> clock range.
>>
>> Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
>
>
> Reviewed-by: Grant Grundler <grundler@parisc-linux.org>
Applied, thanks.
^ permalink raw reply
* Re: [PATCH] net: filter: remove unused cpu_off
From: Eric Dumazet @ 2012-04-18 2:59 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20120417.225733.605856895750092515.davem@davemloft.net>
On Tue, 2012-04-17 at 22:57 -0400, David Miller wrote:
> From: Eric Dumazet <eric.dumazet@gmail.com>
> Date: Wed, 18 Apr 2012 04:51:19 +0200
>
> > Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
>
> Applied, but I added "in sparc JIT" to the subject line.
>
> Thanks.
No problem, I just copy/pasted your own subjects for this file
Thanks
^ permalink raw reply
* Re: [net 0/2][pull request] Intel Wired LAN Driver Updates
From: David Miller @ 2012-04-18 2:59 UTC (permalink / raw)
To: jeffrey.t.kirsher; +Cc: netdev, gospo, sassmann
In-Reply-To: <1334702885-4411-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Date: Tue, 17 Apr 2012 15:48:03 -0700
> This series of patches contains fixes for ixgbe only.
>
> The following are changes since commit a99ff7d0123b19ecad3b589480b6542716ab6b52:
> net: usb: smsc75xx: fix mtu
> and are available in the git repository at:
> git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net master
Pulled, thanks Jeff.
^ permalink raw reply
* Re: [PATCH] net: filter: remove unused cpu_off
From: David Miller @ 2012-04-18 2:57 UTC (permalink / raw)
To: eric.dumazet; +Cc: netdev
In-Reply-To: <1334717479.2472.73.camel@edumazet-glaptop>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Wed, 18 Apr 2012 04:51:19 +0200
> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Applied, but I added "in sparc JIT" to the subject line.
Thanks.
^ permalink raw reply
* Re: [PATCH v18 15/15] Documentation: prctl/seccomp_filter
From: Will Drewry @ 2012-04-18 2:53 UTC (permalink / raw)
To: Paul Gortmaker
Cc: linux-kernel, linux-man, linux-security-module, linux-arch,
linux-doc, kernel-hardening, netdev, x86, arnd, davem, hpa, mingo,
oleg, peterz, rdunlap, mcgrathr, tglx, luto, eparis, serge.hallyn,
djm, scarybeasts, indan, pmoore, akpm, corbet, eric.dumazet,
markus, coreyb, keescook, jmorris
In-Reply-To: <CAP=VYLqKOOV41yXuD7jqEUfkxC4ROzZmhA-UP5pkNAKPFiddRw@mail.gmail.com>
On Tue, Apr 17, 2012 at 9:28 PM, Paul Gortmaker
<paul.gortmaker@windriver.com> wrote:
> On Thu, Apr 12, 2012 at 5:48 PM, Will Drewry <wad@chromium.org> wrote:
>> Documents how system call filtering using Berkeley Packet
>> Filter programs works and how it may be used.
>> Includes an example for x86 and a semi-generic
>> example using a macro-based code generator.
>
> Hi guys, that is quite the To/CC list. I didn't have the heart to add
> yet another address (linux-next) to it...
>
> Can you have a look at this link? It appears to be breaking
> the i386 allmodconfig builds in linux-next.
>
> http://kisskb.ellerman.id.au/kisskb/buildresult/6123842/
>
> "samples/seccomp/bpf-direct.c:47:2: error: #error Unsupported platform"
Ouch. It's checking the __i386__ and __x86_64__ macros. I'll reproduce
it and see what needs to change. I suspect it'll be something dumb,
but the worst case is that I drop that bit of fanciness.
Thanks and sorry!
will
>>
>> Acked-by: Eric Paris <eparis@redhat.com>
>> Signed-off-by: Will Drewry <wad@chromium.org>
>>
>> v18: - added acked by
>> - update no new privs numbers
>> v17: - remove @compat note and add Pitfalls section for arch checking
>> (keescook@chromium.org)
>> v16: -
>> v15: -
>> v14: - rebase/nochanges
>> v13: - rebase on to 88ebdda6159ffc15699f204c33feb3e431bf9bdc
>> v12: - comment on the ptrace_event use
>> - update arch support comment
>> - note the behavior of SECCOMP_RET_DATA when there are multiple filters
>> (keescook@chromium.org)
>> - lots of samples/ clean up incl 64-bit bpf-direct support
>> (markus@chromium.org)
>> - rebase to linux-next
>> v11: - overhaul return value language, updates (keescook@chromium.org)
>> - comment on do_exit(SIGSYS)
>> v10: - update for SIGSYS
>> - update for new seccomp_data layout
>> - update for ptrace option use
>> v9: - updated bpf-direct.c for SIGILL
>> v8: - add PR_SET_NO_NEW_PRIVS to the samples.
>> v7: - updated for all the new stuff in v7: TRAP, TRACE
>> - only talk about PR_SET_SECCOMP now
>> - fixed bad JLE32 check (coreyb@linux.vnet.ibm.com)
>> - adds dropper.c: a simple system call disabler
>> v6: - tweak the language to note the requirement of
>> PR_SET_NO_NEW_PRIVS being called prior to use. (luto@mit.edu)
>> v5: - update sample to use system call arguments
>> - adds a "fancy" example using a macro-based generator
>> - cleaned up bpf in the sample
>> - update docs to mention arguments
>> - fix prctl value (eparis@redhat.com)
>> - language cleanup (rdunlap@xenotime.net)
>> v4: - update for no_new_privs use
>> - minor tweaks
>> v3: - call out BPF <-> Berkeley Packet Filter (rdunlap@xenotime.net)
>> - document use of tentative always-unprivileged
>> - guard sample compilation for i386 and x86_64
>> v2: - move code to samples (corbet@lwn.net)
>> ---
>> Documentation/prctl/seccomp_filter.txt | 163 ++++++++++++++++++++++
>> samples/Makefile | 2 +-
>> samples/seccomp/Makefile | 38 +++++
>> samples/seccomp/bpf-direct.c | 176 +++++++++++++++++++++++
>> samples/seccomp/bpf-fancy.c | 102 ++++++++++++++
>> samples/seccomp/bpf-helper.c | 89 ++++++++++++
>> samples/seccomp/bpf-helper.h | 238 ++++++++++++++++++++++++++++++++
>> samples/seccomp/dropper.c | 68 +++++++++
>> 8 files changed, 875 insertions(+), 1 deletions(-)
>> create mode 100644 Documentation/prctl/seccomp_filter.txt
>> create mode 100644 samples/seccomp/Makefile
>> create mode 100644 samples/seccomp/bpf-direct.c
>> create mode 100644 samples/seccomp/bpf-fancy.c
>> create mode 100644 samples/seccomp/bpf-helper.c
>> create mode 100644 samples/seccomp/bpf-helper.h
>> create mode 100644 samples/seccomp/dropper.c
>>
>> diff --git a/Documentation/prctl/seccomp_filter.txt b/Documentation/prctl/seccomp_filter.txt
>> new file mode 100644
>> index 0000000..597c3c5
>> --- /dev/null
>> +++ b/Documentation/prctl/seccomp_filter.txt
>> @@ -0,0 +1,163 @@
>> + SECure COMPuting with filters
>> + =============================
>> +
>> +Introduction
>> +------------
>> +
>> +A large number of system calls are exposed to every userland process
>> +with many of them going unused for the entire lifetime of the process.
>> +As system calls change and mature, bugs are found and eradicated. A
>> +certain subset of userland applications benefit by having a reduced set
>> +of available system calls. The resulting set reduces the total kernel
>> +surface exposed to the application. System call filtering is meant for
>> +use with those applications.
>> +
>> +Seccomp filtering provides a means for a process to specify a filter for
>> +incoming system calls. The filter is expressed as a Berkeley Packet
>> +Filter (BPF) program, as with socket filters, except that the data
>> +operated on is related to the system call being made: system call
>> +number and the system call arguments. This allows for expressive
>> +filtering of system calls using a filter program language with a long
>> +history of being exposed to userland and a straightforward data set.
>> +
>> +Additionally, BPF makes it impossible for users of seccomp to fall prey
>> +to time-of-check-time-of-use (TOCTOU) attacks that are common in system
>> +call interposition frameworks. BPF programs may not dereference
>> +pointers which constrains all filters to solely evaluating the system
>> +call arguments directly.
>> +
>> +What it isn't
>> +-------------
>> +
>> +System call filtering isn't a sandbox. It provides a clearly defined
>> +mechanism for minimizing the exposed kernel surface. It is meant to be
>> +a tool for sandbox developers to use. Beyond that, policy for logical
>> +behavior and information flow should be managed with a combination of
>> +other system hardening techniques and, potentially, an LSM of your
>> +choosing. Expressive, dynamic filters provide further options down this
>> +path (avoiding pathological sizes or selecting which of the multiplexed
>> +system calls in socketcall() is allowed, for instance) which could be
>> +construed, incorrectly, as a more complete sandboxing solution.
>> +
>> +Usage
>> +-----
>> +
>> +An additional seccomp mode is added and is enabled using the same
>> +prctl(2) call as the strict seccomp. If the architecture has
>> +CONFIG_HAVE_ARCH_SECCOMP_FILTER, then filters may be added as below:
>> +
>> +PR_SET_SECCOMP:
>> + Now takes an additional argument which specifies a new filter
>> + using a BPF program.
>> + The BPF program will be executed over struct seccomp_data
>> + reflecting the system call number, arguments, and other
>> + metadata. The BPF program must then return one of the
>> + acceptable values to inform the kernel which action should be
>> + taken.
>> +
>> + Usage:
>> + prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, prog);
>> +
>> + The 'prog' argument is a pointer to a struct sock_fprog which
>> + will contain the filter program. If the program is invalid, the
>> + call will return -1 and set errno to EINVAL.
>> +
>> + If fork/clone and execve are allowed by @prog, any child
>> + processes will be constrained to the same filters and system
>> + call ABI as the parent.
>> +
>> + Prior to use, the task must call prctl(PR_SET_NO_NEW_PRIVS, 1) or
>> + run with CAP_SYS_ADMIN privileges in its namespace. If these are not
>> + true, -EACCES will be returned. This requirement ensures that filter
>> + programs cannot be applied to child processes with greater privileges
>> + than the task that installed them.
>> +
>> + Additionally, if prctl(2) is allowed by the attached filter,
>> + additional filters may be layered on which will increase evaluation
>> + time, but allow for further decreasing the attack surface during
>> + execution of a process.
>> +
>> +The above call returns 0 on success and non-zero on error.
>> +
>> +Return values
>> +-------------
>> +A seccomp filter may return any of the following values. If multiple
>> +filters exist, the return value for the evaluation of a given system
>> +call will always use the highest precedent value. (For example,
>> +SECCOMP_RET_KILL will always take precedence.)
>> +
>> +In precedence order, they are:
>> +
>> +SECCOMP_RET_KILL:
>> + Results in the task exiting immediately without executing the
>> + system call. The exit status of the task (status & 0x7f) will
>> + be SIGSYS, not SIGKILL.
>> +
>> +SECCOMP_RET_TRAP:
>> + Results in the kernel sending a SIGSYS signal to the triggering
>> + task without executing the system call. The kernel will
>> + rollback the register state to just before the system call
>> + entry such that a signal handler in the task will be able to
>> + inspect the ucontext_t->uc_mcontext registers and emulate
>> + system call success or failure upon return from the signal
>> + handler.
>> +
>> + The SECCOMP_RET_DATA portion of the return value will be passed
>> + as si_errno.
>> +
>> + SIGSYS triggered by seccomp will have a si_code of SYS_SECCOMP.
>> +
>> +SECCOMP_RET_ERRNO:
>> + Results in the lower 16-bits of the return value being passed
>> + to userland as the errno without executing the system call.
>> +
>> +SECCOMP_RET_TRACE:
>> + When returned, this value will cause the kernel to attempt to
>> + notify a ptrace()-based tracer prior to executing the system
>> + call. If there is no tracer present, -ENOSYS is returned to
>> + userland and the system call is not executed.
>> +
>> + A tracer will be notified if it requests PTRACE_O_TRACESECCOMP
>> + using ptrace(PTRACE_SETOPTIONS). The tracer will be notified
>> + of a PTRACE_EVENT_SECCOMP and the SECCOMP_RET_DATA portion of
>> + the BPF program return value will be available to the tracer
>> + via PTRACE_GETEVENTMSG.
>> +
>> +SECCOMP_RET_ALLOW:
>> + Results in the system call being executed.
>> +
>> +If multiple filters exist, the return value for the evaluation of a
>> +given system call will always use the highest precedent value.
>> +
>> +Precedence is only determined using the SECCOMP_RET_ACTION mask. When
>> +multiple filters return values of the same precedence, only the
>> +SECCOMP_RET_DATA from the most recently installed filter will be
>> +returned.
>> +
>> +Pitfalls
>> +--------
>> +
>> +The biggest pitfall to avoid during use is filtering on system call
>> +number without checking the architecture value. Why? On any
>> +architecture that supports multiple system call invocation conventions,
>> +the system call numbers may vary based on the specific invocation. If
>> +the numbers in the different calling conventions overlap, then checks in
>> +the filters may be abused. Always check the arch value!
>> +
>> +Example
>> +-------
>> +
>> +The samples/seccomp/ directory contains both an x86-specific example
>> +and a more generic example of a higher level macro interface for BPF
>> +program generation.
>> +
>> +
>> +
>> +Adding architecture support
>> +-----------------------
>> +
>> +See arch/Kconfig for the authoritative requirements. In general, if an
>> +architecture supports both ptrace_event and seccomp, it will be able to
>> +support seccomp filter with minor fixup: SIGSYS support and seccomp return
>> +value checking. Then it must just add CONFIG_HAVE_ARCH_SECCOMP_FILTER
>> +to its arch-specific Kconfig.
>> diff --git a/samples/Makefile b/samples/Makefile
>> index 2f75851..5ef08bb 100644
>> --- a/samples/Makefile
>> +++ b/samples/Makefile
>> @@ -1,4 +1,4 @@
>> # Makefile for Linux samples code
>>
>> obj-$(CONFIG_SAMPLES) += kobject/ kprobes/ tracepoints/ trace_events/ \
>> - hw_breakpoint/ kfifo/ kdb/ hidraw/ rpmsg/
>> + hw_breakpoint/ kfifo/ kdb/ hidraw/ rpmsg/ seccomp/
>> diff --git a/samples/seccomp/Makefile b/samples/seccomp/Makefile
>> new file mode 100644
>> index 0000000..e8fe0f5
>> --- /dev/null
>> +++ b/samples/seccomp/Makefile
>> @@ -0,0 +1,38 @@
>> +# kbuild trick to avoid linker error. Can be omitted if a module is built.
>> +obj- := dummy.o
>> +
>> +hostprogs-$(CONFIG_SECCOMP) := bpf-fancy dropper
>> +bpf-fancy-objs := bpf-fancy.o bpf-helper.o
>> +
>> +HOSTCFLAGS_bpf-fancy.o += -I$(objtree)/usr/include
>> +HOSTCFLAGS_bpf-fancy.o += -idirafter $(objtree)/include
>> +HOSTCFLAGS_bpf-helper.o += -I$(objtree)/usr/include
>> +HOSTCFLAGS_bpf-helper.o += -idirafter $(objtree)/include
>> +
>> +HOSTCFLAGS_dropper.o += -I$(objtree)/usr/include
>> +HOSTCFLAGS_dropper.o += -idirafter $(objtree)/include
>> +dropper-objs := dropper.o
>> +
>> +# bpf-direct.c is x86-only.
>> +ifeq ($(SRCARCH),x86)
>> +# List of programs to build
>> +hostprogs-$(CONFIG_SECCOMP) += bpf-direct
>> +bpf-direct-objs := bpf-direct.o
>> +endif
>> +
>> +HOSTCFLAGS_bpf-direct.o += -I$(objtree)/usr/include
>> +HOSTCFLAGS_bpf-direct.o += -idirafter $(objtree)/include
>> +
>> +# Try to match the kernel target.
>> +ifeq ($(CONFIG_64BIT),)
>> +HOSTCFLAGS_bpf-direct.o += -m32
>> +HOSTCFLAGS_dropper.o += -m32
>> +HOSTCFLAGS_bpf-helper.o += -m32
>> +HOSTCFLAGS_bpf-fancy.o += -m32
>> +HOSTLOADLIBES_bpf-direct += -m32
>> +HOSTLOADLIBES_bpf-fancy += -m32
>> +HOSTLOADLIBES_dropper += -m32
>> +endif
>> +
>> +# Tell kbuild to always build the programs
>> +always := $(hostprogs-y)
>> diff --git a/samples/seccomp/bpf-direct.c b/samples/seccomp/bpf-direct.c
>> new file mode 100644
>> index 0000000..26f523e
>> --- /dev/null
>> +++ b/samples/seccomp/bpf-direct.c
>> @@ -0,0 +1,176 @@
>> +/*
>> + * Seccomp filter example for x86 (32-bit and 64-bit) with BPF macros
>> + *
>> + * Copyright (c) 2012 The Chromium OS Authors <chromium-os-dev@chromium.org>
>> + * Author: Will Drewry <wad@chromium.org>
>> + *
>> + * The code may be used by anyone for any purpose,
>> + * and can serve as a starting point for developing
>> + * applications using prctl(PR_SET_SECCOMP, 2, ...).
>> + */
>> +#define __USE_GNU 1
>> +#define _GNU_SOURCE 1
>> +
>> +#include <linux/types.h>
>> +#include <linux/filter.h>
>> +#include <linux/seccomp.h>
>> +#include <linux/unistd.h>
>> +#include <signal.h>
>> +#include <stdio.h>
>> +#include <stddef.h>
>> +#include <string.h>
>> +#include <sys/prctl.h>
>> +#include <unistd.h>
>> +
>> +#define syscall_arg(_n) (offsetof(struct seccomp_data, args[_n]))
>> +#define syscall_nr (offsetof(struct seccomp_data, nr))
>> +
>> +#if defined(__i386__)
>> +#define REG_RESULT REG_EAX
>> +#define REG_SYSCALL REG_EAX
>> +#define REG_ARG0 REG_EBX
>> +#define REG_ARG1 REG_ECX
>> +#define REG_ARG2 REG_EDX
>> +#define REG_ARG3 REG_ESI
>> +#define REG_ARG4 REG_EDI
>> +#define REG_ARG5 REG_EBP
>> +#elif defined(__x86_64__)
>> +#define REG_RESULT REG_RAX
>> +#define REG_SYSCALL REG_RAX
>> +#define REG_ARG0 REG_RDI
>> +#define REG_ARG1 REG_RSI
>> +#define REG_ARG2 REG_RDX
>> +#define REG_ARG3 REG_R10
>> +#define REG_ARG4 REG_R8
>> +#define REG_ARG5 REG_R9
>> +#else
>> +#error Unsupported platform
>> +#endif
>> +
>> +#ifndef PR_SET_NO_NEW_PRIVS
>> +#define PR_SET_NO_NEW_PRIVS 38
>> +#endif
>> +
>> +#ifndef SYS_SECCOMP
>> +#define SYS_SECCOMP 1
>> +#endif
>> +
>> +static void emulator(int nr, siginfo_t *info, void *void_context)
>> +{
>> + ucontext_t *ctx = (ucontext_t *)(void_context);
>> + int syscall;
>> + char *buf;
>> + ssize_t bytes;
>> + size_t len;
>> + if (info->si_code != SYS_SECCOMP)
>> + return;
>> + if (!ctx)
>> + return;
>> + syscall = ctx->uc_mcontext.gregs[REG_SYSCALL];
>> + buf = (char *) ctx->uc_mcontext.gregs[REG_ARG1];
>> + len = (size_t) ctx->uc_mcontext.gregs[REG_ARG2];
>> +
>> + if (syscall != __NR_write)
>> + return;
>> + if (ctx->uc_mcontext.gregs[REG_ARG0] != STDERR_FILENO)
>> + return;
>> + /* Redirect stderr messages to stdout. Doesn't handle EINTR, etc */
>> + ctx->uc_mcontext.gregs[REG_RESULT] = -1;
>> + if (write(STDOUT_FILENO, "[ERR] ", 6) > 0) {
>> + bytes = write(STDOUT_FILENO, buf, len);
>> + ctx->uc_mcontext.gregs[REG_RESULT] = bytes;
>> + }
>> + return;
>> +}
>> +
>> +static int install_emulator(void)
>> +{
>> + struct sigaction act;
>> + sigset_t mask;
>> + memset(&act, 0, sizeof(act));
>> + sigemptyset(&mask);
>> + sigaddset(&mask, SIGSYS);
>> +
>> + act.sa_sigaction = &emulator;
>> + act.sa_flags = SA_SIGINFO;
>> + if (sigaction(SIGSYS, &act, NULL) < 0) {
>> + perror("sigaction");
>> + return -1;
>> + }
>> + if (sigprocmask(SIG_UNBLOCK, &mask, NULL)) {
>> + perror("sigprocmask");
>> + return -1;
>> + }
>> + return 0;
>> +}
>> +
>> +static int install_filter(void)
>> +{
>> + struct sock_filter filter[] = {
>> + /* Grab the system call number */
>> + BPF_STMT(BPF_LD+BPF_W+BPF_ABS, syscall_nr),
>> + /* Jump table for the allowed syscalls */
>> + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_rt_sigreturn, 0, 1),
>> + BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
>> +#ifdef __NR_sigreturn
>> + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_sigreturn, 0, 1),
>> + BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
>> +#endif
>> + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_exit_group, 0, 1),
>> + BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
>> + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_exit, 0, 1),
>> + BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
>> + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_read, 1, 0),
>> + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_write, 3, 2),
>> +
>> + /* Check that read is only using stdin. */
>> + BPF_STMT(BPF_LD+BPF_W+BPF_ABS, syscall_arg(0)),
>> + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, STDIN_FILENO, 4, 0),
>> + BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL),
>> +
>> + /* Check that write is only using stdout */
>> + BPF_STMT(BPF_LD+BPF_W+BPF_ABS, syscall_arg(0)),
>> + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, STDOUT_FILENO, 1, 0),
>> + /* Trap attempts to write to stderr */
>> + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, STDERR_FILENO, 1, 2),
>> +
>> + BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
>> + BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_TRAP),
>> + BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL),
>> + };
>> + struct sock_fprog prog = {
>> + .len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
>> + .filter = filter,
>> + };
>> +
>> + if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
>> + perror("prctl(NO_NEW_PRIVS)");
>> + return 1;
>> + }
>> +
>> +
>> + if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
>> + perror("prctl");
>> + return 1;
>> + }
>> + return 0;
>> +}
>> +
>> +#define payload(_c) (_c), sizeof((_c))
>> +int main(int argc, char **argv)
>> +{
>> + char buf[4096];
>> + ssize_t bytes = 0;
>> + if (install_emulator())
>> + return 1;
>> + if (install_filter())
>> + return 1;
>> + syscall(__NR_write, STDOUT_FILENO,
>> + payload("OHAI! WHAT IS YOUR NAME? "));
>> + bytes = syscall(__NR_read, STDIN_FILENO, buf, sizeof(buf));
>> + syscall(__NR_write, STDOUT_FILENO, payload("HELLO, "));
>> + syscall(__NR_write, STDOUT_FILENO, buf, bytes);
>> + syscall(__NR_write, STDERR_FILENO,
>> + payload("Error message going to STDERR\n"));
>> + return 0;
>> +}
>> diff --git a/samples/seccomp/bpf-fancy.c b/samples/seccomp/bpf-fancy.c
>> new file mode 100644
>> index 0000000..8eb483a
>> --- /dev/null
>> +++ b/samples/seccomp/bpf-fancy.c
>> @@ -0,0 +1,102 @@
>> +/*
>> + * Seccomp BPF example using a macro-based generator.
>> + *
>> + * Copyright (c) 2012 The Chromium OS Authors <chromium-os-dev@chromium.org>
>> + * Author: Will Drewry <wad@chromium.org>
>> + *
>> + * The code may be used by anyone for any purpose,
>> + * and can serve as a starting point for developing
>> + * applications using prctl(PR_ATTACH_SECCOMP_FILTER).
>> + */
>> +
>> +#include <linux/filter.h>
>> +#include <linux/seccomp.h>
>> +#include <linux/unistd.h>
>> +#include <stdio.h>
>> +#include <string.h>
>> +#include <sys/prctl.h>
>> +#include <unistd.h>
>> +
>> +#include "bpf-helper.h"
>> +
>> +#ifndef PR_SET_NO_NEW_PRIVS
>> +#define PR_SET_NO_NEW_PRIVS 38
>> +#endif
>> +
>> +int main(int argc, char **argv)
>> +{
>> + struct bpf_labels l;
>> + static const char msg1[] = "Please type something: ";
>> + static const char msg2[] = "You typed: ";
>> + char buf[256];
>> + struct sock_filter filter[] = {
>> + /* TODO: LOAD_SYSCALL_NR(arch) and enforce an arch */
>> + LOAD_SYSCALL_NR,
>> + SYSCALL(__NR_exit, ALLOW),
>> + SYSCALL(__NR_exit_group, ALLOW),
>> + SYSCALL(__NR_write, JUMP(&l, write_fd)),
>> + SYSCALL(__NR_read, JUMP(&l, read)),
>> + DENY, /* Don't passthrough into a label */
>> +
>> + LABEL(&l, read),
>> + ARG(0),
>> + JNE(STDIN_FILENO, DENY),
>> + ARG(1),
>> + JNE((unsigned long)buf, DENY),
>> + ARG(2),
>> + JGE(sizeof(buf), DENY),
>> + ALLOW,
>> +
>> + LABEL(&l, write_fd),
>> + ARG(0),
>> + JEQ(STDOUT_FILENO, JUMP(&l, write_buf)),
>> + JEQ(STDERR_FILENO, JUMP(&l, write_buf)),
>> + DENY,
>> +
>> + LABEL(&l, write_buf),
>> + ARG(1),
>> + JEQ((unsigned long)msg1, JUMP(&l, msg1_len)),
>> + JEQ((unsigned long)msg2, JUMP(&l, msg2_len)),
>> + JEQ((unsigned long)buf, JUMP(&l, buf_len)),
>> + DENY,
>> +
>> + LABEL(&l, msg1_len),
>> + ARG(2),
>> + JLT(sizeof(msg1), ALLOW),
>> + DENY,
>> +
>> + LABEL(&l, msg2_len),
>> + ARG(2),
>> + JLT(sizeof(msg2), ALLOW),
>> + DENY,
>> +
>> + LABEL(&l, buf_len),
>> + ARG(2),
>> + JLT(sizeof(buf), ALLOW),
>> + DENY,
>> + };
>> + struct sock_fprog prog = {
>> + .filter = filter,
>> + .len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
>> + };
>> + ssize_t bytes;
>> + bpf_resolve_jumps(&l, filter, sizeof(filter)/sizeof(*filter));
>> +
>> + if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
>> + perror("prctl(NO_NEW_PRIVS)");
>> + return 1;
>> + }
>> +
>> + if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
>> + perror("prctl(SECCOMP)");
>> + return 1;
>> + }
>> + syscall(__NR_write, STDOUT_FILENO, msg1, strlen(msg1));
>> + bytes = syscall(__NR_read, STDIN_FILENO, buf, sizeof(buf)-1);
>> + bytes = (bytes > 0 ? bytes : 0);
>> + syscall(__NR_write, STDERR_FILENO, msg2, strlen(msg2));
>> + syscall(__NR_write, STDERR_FILENO, buf, bytes);
>> + /* Now get killed */
>> + syscall(__NR_write, STDERR_FILENO, msg2, strlen(msg2)+2);
>> + return 0;
>> +}
>> diff --git a/samples/seccomp/bpf-helper.c b/samples/seccomp/bpf-helper.c
>> new file mode 100644
>> index 0000000..579cfe3
>> --- /dev/null
>> +++ b/samples/seccomp/bpf-helper.c
>> @@ -0,0 +1,89 @@
>> +/*
>> + * Seccomp BPF helper functions
>> + *
>> + * Copyright (c) 2012 The Chromium OS Authors <chromium-os-dev@chromium.org>
>> + * Author: Will Drewry <wad@chromium.org>
>> + *
>> + * The code may be used by anyone for any purpose,
>> + * and can serve as a starting point for developing
>> + * applications using prctl(PR_ATTACH_SECCOMP_FILTER).
>> + */
>> +
>> +#include <stdio.h>
>> +#include <string.h>
>> +
>> +#include "bpf-helper.h"
>> +
>> +int bpf_resolve_jumps(struct bpf_labels *labels,
>> + struct sock_filter *filter, size_t count)
>> +{
>> + struct sock_filter *begin = filter;
>> + __u8 insn = count - 1;
>> +
>> + if (count < 1)
>> + return -1;
>> + /*
>> + * Walk it once, backwards, to build the label table and do fixups.
>> + * Since backward jumps are disallowed by BPF, this is easy.
>> + */
>> + filter += insn;
>> + for (; filter >= begin; --insn, --filter) {
>> + if (filter->code != (BPF_JMP+BPF_JA))
>> + continue;
>> + switch ((filter->jt<<8)|filter->jf) {
>> + case (JUMP_JT<<8)|JUMP_JF:
>> + if (labels->labels[filter->k].location == 0xffffffff) {
>> + fprintf(stderr, "Unresolved label: '%s'\n",
>> + labels->labels[filter->k].label);
>> + return 1;
>> + }
>> + filter->k = labels->labels[filter->k].location -
>> + (insn + 1);
>> + filter->jt = 0;
>> + filter->jf = 0;
>> + continue;
>> + case (LABEL_JT<<8)|LABEL_JF:
>> + if (labels->labels[filter->k].location != 0xffffffff) {
>> + fprintf(stderr, "Duplicate label use: '%s'\n",
>> + labels->labels[filter->k].label);
>> + return 1;
>> + }
>> + labels->labels[filter->k].location = insn;
>> + filter->k = 0; /* fall through */
>> + filter->jt = 0;
>> + filter->jf = 0;
>> + continue;
>> + }
>> + }
>> + return 0;
>> +}
>> +
>> +/* Simple lookup table for labels. */
>> +__u32 seccomp_bpf_label(struct bpf_labels *labels, const char *label)
>> +{
>> + struct __bpf_label *begin = labels->labels, *end;
>> + int id;
>> + if (labels->count == 0) {
>> + begin->label = label;
>> + begin->location = 0xffffffff;
>> + labels->count++;
>> + return 0;
>> + }
>> + end = begin + labels->count;
>> + for (id = 0; begin < end; ++begin, ++id) {
>> + if (!strcmp(label, begin->label))
>> + return id;
>> + }
>> + begin->label = label;
>> + begin->location = 0xffffffff;
>> + labels->count++;
>> + return id;
>> +}
>> +
>> +void seccomp_bpf_print(struct sock_filter *filter, size_t count)
>> +{
>> + struct sock_filter *end = filter + count;
>> + for ( ; filter < end; ++filter)
>> + printf("{ code=%u,jt=%u,jf=%u,k=%u },\n",
>> + filter->code, filter->jt, filter->jf, filter->k);
>> +}
>> diff --git a/samples/seccomp/bpf-helper.h b/samples/seccomp/bpf-helper.h
>> new file mode 100644
>> index 0000000..643279d
>> --- /dev/null
>> +++ b/samples/seccomp/bpf-helper.h
>> @@ -0,0 +1,238 @@
>> +/*
>> + * Example wrapper around BPF macros.
>> + *
>> + * Copyright (c) 2012 The Chromium OS Authors <chromium-os-dev@chromium.org>
>> + * Author: Will Drewry <wad@chromium.org>
>> + *
>> + * The code may be used by anyone for any purpose,
>> + * and can serve as a starting point for developing
>> + * applications using prctl(PR_SET_SECCOMP, 2, ...).
>> + *
>> + * No guarantees are provided with respect to the correctness
>> + * or functionality of this code.
>> + */
>> +#ifndef __BPF_HELPER_H__
>> +#define __BPF_HELPER_H__
>> +
>> +#include <asm/bitsperlong.h> /* for __BITS_PER_LONG */
>> +#include <endian.h>
>> +#include <linux/filter.h>
>> +#include <linux/seccomp.h> /* for seccomp_data */
>> +#include <linux/types.h>
>> +#include <linux/unistd.h>
>> +#include <stddef.h>
>> +
>> +#define BPF_LABELS_MAX 256
>> +struct bpf_labels {
>> + int count;
>> + struct __bpf_label {
>> + const char *label;
>> + __u32 location;
>> + } labels[BPF_LABELS_MAX];
>> +};
>> +
>> +int bpf_resolve_jumps(struct bpf_labels *labels,
>> + struct sock_filter *filter, size_t count);
>> +__u32 seccomp_bpf_label(struct bpf_labels *labels, const char *label);
>> +void seccomp_bpf_print(struct sock_filter *filter, size_t count);
>> +
>> +#define JUMP_JT 0xff
>> +#define JUMP_JF 0xff
>> +#define LABEL_JT 0xfe
>> +#define LABEL_JF 0xfe
>> +
>> +#define ALLOW \
>> + BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
>> +#define DENY \
>> + BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)
>> +#define JUMP(labels, label) \
>> + BPF_JUMP(BPF_JMP+BPF_JA, FIND_LABEL((labels), (label)), \
>> + JUMP_JT, JUMP_JF)
>> +#define LABEL(labels, label) \
>> + BPF_JUMP(BPF_JMP+BPF_JA, FIND_LABEL((labels), (label)), \
>> + LABEL_JT, LABEL_JF)
>> +#define SYSCALL(nr, jt) \
>> + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (nr), 0, 1), \
>> + jt
>> +
>> +/* Lame, but just an example */
>> +#define FIND_LABEL(labels, label) seccomp_bpf_label((labels), #label)
>> +
>> +#define EXPAND(...) __VA_ARGS__
>> +/* Map all width-sensitive operations */
>> +#if __BITS_PER_LONG == 32
>> +
>> +#define JEQ(x, jt) JEQ32(x, EXPAND(jt))
>> +#define JNE(x, jt) JNE32(x, EXPAND(jt))
>> +#define JGT(x, jt) JGT32(x, EXPAND(jt))
>> +#define JLT(x, jt) JLT32(x, EXPAND(jt))
>> +#define JGE(x, jt) JGE32(x, EXPAND(jt))
>> +#define JLE(x, jt) JLE32(x, EXPAND(jt))
>> +#define JA(x, jt) JA32(x, EXPAND(jt))
>> +#define ARG(i) ARG_32(i)
>> +#define LO_ARG(idx) offsetof(struct seccomp_data, args[(idx)])
>> +
>> +#elif __BITS_PER_LONG == 64
>> +
>> +/* Ensure that we load the logically correct offset. */
>> +#if __BYTE_ORDER == __LITTLE_ENDIAN
>> +#define ENDIAN(_lo, _hi) _lo, _hi
>> +#define LO_ARG(idx) offsetof(struct seccomp_data, args[(idx)])
>> +#define HI_ARG(idx) offsetof(struct seccomp_data, args[(idx)]) + sizeof(__u32)
>> +#elif __BYTE_ORDER == __BIG_ENDIAN
>> +#define ENDIAN(_lo, _hi) _hi, _lo
>> +#define LO_ARG(idx) offsetof(struct seccomp_data, args[(idx)]) + sizeof(__u32)
>> +#define HI_ARG(idx) offsetof(struct seccomp_data, args[(idx)])
>> +#else
>> +#error "Unknown endianness"
>> +#endif
>> +
>> +union arg64 {
>> + struct {
>> + __u32 ENDIAN(lo32, hi32);
>> + };
>> + __u64 u64;
>> +};
>> +
>> +#define JEQ(x, jt) \
>> + JEQ64(((union arg64){.u64 = (x)}).lo32, \
>> + ((union arg64){.u64 = (x)}).hi32, \
>> + EXPAND(jt))
>> +#define JGT(x, jt) \
>> + JGT64(((union arg64){.u64 = (x)}).lo32, \
>> + ((union arg64){.u64 = (x)}).hi32, \
>> + EXPAND(jt))
>> +#define JGE(x, jt) \
>> + JGE64(((union arg64){.u64 = (x)}).lo32, \
>> + ((union arg64){.u64 = (x)}).hi32, \
>> + EXPAND(jt))
>> +#define JNE(x, jt) \
>> + JNE64(((union arg64){.u64 = (x)}).lo32, \
>> + ((union arg64){.u64 = (x)}).hi32, \
>> + EXPAND(jt))
>> +#define JLT(x, jt) \
>> + JLT64(((union arg64){.u64 = (x)}).lo32, \
>> + ((union arg64){.u64 = (x)}).hi32, \
>> + EXPAND(jt))
>> +#define JLE(x, jt) \
>> + JLE64(((union arg64){.u64 = (x)}).lo32, \
>> + ((union arg64){.u64 = (x)}).hi32, \
>> + EXPAND(jt))
>> +
>> +#define JA(x, jt) \
>> + JA64(((union arg64){.u64 = (x)}).lo32, \
>> + ((union arg64){.u64 = (x)}).hi32, \
>> + EXPAND(jt))
>> +#define ARG(i) ARG_64(i)
>> +
>> +#else
>> +#error __BITS_PER_LONG value unusable.
>> +#endif
>> +
>> +/* Loads the arg into A */
>> +#define ARG_32(idx) \
>> + BPF_STMT(BPF_LD+BPF_W+BPF_ABS, LO_ARG(idx))
>> +
>> +/* Loads hi into A and lo in X */
>> +#define ARG_64(idx) \
>> + BPF_STMT(BPF_LD+BPF_W+BPF_ABS, LO_ARG(idx)), \
>> + BPF_STMT(BPF_ST, 0), /* lo -> M[0] */ \
>> + BPF_STMT(BPF_LD+BPF_W+BPF_ABS, HI_ARG(idx)), \
>> + BPF_STMT(BPF_ST, 1) /* hi -> M[1] */
>> +
>> +#define JEQ32(value, jt) \
>> + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (value), 0, 1), \
>> + jt
>> +
>> +#define JNE32(value, jt) \
>> + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (value), 1, 0), \
>> + jt
>> +
>> +/* Checks the lo, then swaps to check the hi. A=lo,X=hi */
>> +#define JEQ64(lo, hi, jt) \
>> + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
>> + BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
>> + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (lo), 0, 2), \
>> + BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
>> + jt, \
>> + BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
>> +
>> +#define JNE64(lo, hi, jt) \
>> + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 5, 0), \
>> + BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
>> + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (lo), 2, 0), \
>> + BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
>> + jt, \
>> + BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
>> +
>> +#define JA32(value, jt) \
>> + BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (value), 0, 1), \
>> + jt
>> +
>> +#define JA64(lo, hi, jt) \
>> + BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (hi), 3, 0), \
>> + BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
>> + BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (lo), 0, 2), \
>> + BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
>> + jt, \
>> + BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
>> +
>> +#define JGE32(value, jt) \
>> + BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (value), 0, 1), \
>> + jt
>> +
>> +#define JLT32(value, jt) \
>> + BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (value), 1, 0), \
>> + jt
>> +
>> +/* Shortcut checking if hi > arg.hi. */
>> +#define JGE64(lo, hi, jt) \
>> + BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (hi), 4, 0), \
>> + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
>> + BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
>> + BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (lo), 0, 2), \
>> + BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
>> + jt, \
>> + BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
>> +
>> +#define JLT64(lo, hi, jt) \
>> + BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (hi), 0, 4), \
>> + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
>> + BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
>> + BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (lo), 2, 0), \
>> + BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
>> + jt, \
>> + BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
>> +
>> +#define JGT32(value, jt) \
>> + BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (value), 0, 1), \
>> + jt
>> +
>> +#define JLE32(value, jt) \
>> + BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (value), 1, 0), \
>> + jt
>> +
>> +/* Check hi > args.hi first, then do the GE checking */
>> +#define JGT64(lo, hi, jt) \
>> + BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (hi), 4, 0), \
>> + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
>> + BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
>> + BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (lo), 0, 2), \
>> + BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
>> + jt, \
>> + BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
>> +
>> +#define JLE64(lo, hi, jt) \
>> + BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (hi), 6, 0), \
>> + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 3), \
>> + BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
>> + BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (lo), 2, 0), \
>> + BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
>> + jt, \
>> + BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
>> +
>> +#define LOAD_SYSCALL_NR \
>> + BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \
>> + offsetof(struct seccomp_data, nr))
>> +
>> +#endif /* __BPF_HELPER_H__ */
>> diff --git a/samples/seccomp/dropper.c b/samples/seccomp/dropper.c
>> new file mode 100644
>> index 0000000..c69c347
>> --- /dev/null
>> +++ b/samples/seccomp/dropper.c
>> @@ -0,0 +1,68 @@
>> +/*
>> + * Naive system call dropper built on seccomp_filter.
>> + *
>> + * Copyright (c) 2012 The Chromium OS Authors <chromium-os-dev@chromium.org>
>> + * Author: Will Drewry <wad@chromium.org>
>> + *
>> + * The code may be used by anyone for any purpose,
>> + * and can serve as a starting point for developing
>> + * applications using prctl(PR_SET_SECCOMP, 2, ...).
>> + *
>> + * When run, returns the specified errno for the specified
>> + * system call number against the given architecture.
>> + *
>> + * Run this one as root as PR_SET_NO_NEW_PRIVS is not called.
>> + */
>> +
>> +#include <errno.h>
>> +#include <linux/audit.h>
>> +#include <linux/filter.h>
>> +#include <linux/seccomp.h>
>> +#include <linux/unistd.h>
>> +#include <stdio.h>
>> +#include <stddef.h>
>> +#include <stdlib.h>
>> +#include <sys/prctl.h>
>> +#include <unistd.h>
>> +
>> +static int install_filter(int nr, int arch, int error)
>> +{
>> + struct sock_filter filter[] = {
>> + BPF_STMT(BPF_LD+BPF_W+BPF_ABS,
>> + (offsetof(struct seccomp_data, arch))),
>> + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, arch, 0, 3),
>> + BPF_STMT(BPF_LD+BPF_W+BPF_ABS,
>> + (offsetof(struct seccomp_data, nr))),
>> + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, nr, 0, 1),
>> + BPF_STMT(BPF_RET+BPF_K,
>> + SECCOMP_RET_ERRNO|(error & SECCOMP_RET_DATA)),
>> + BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
>> + };
>> + struct sock_fprog prog = {
>> + .len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
>> + .filter = filter,
>> + };
>> + if (prctl(PR_SET_SECCOMP, 2, &prog)) {
>> + perror("prctl");
>> + return 1;
>> + }
>> + return 0;
>> +}
>> +
>> +int main(int argc, char **argv)
>> +{
>> + if (argc < 5) {
>> + fprintf(stderr, "Usage:\n"
>> + "dropper <syscall_nr> <arch> <errno> <prog> [<args>]\n"
>> + "Hint: AUDIT_ARCH_I386: 0x%X\n"
>> + " AUDIT_ARCH_X86_64: 0x%X\n"
>> + "\n", AUDIT_ARCH_I386, AUDIT_ARCH_X86_64);
>> + return 1;
>> + }
>> + if (install_filter(strtol(argv[1], NULL, 0), strtol(argv[2], NULL, 0),
>> + strtol(argv[3], NULL, 0)))
>> + return 1;
>> + execv(argv[4], &argv[4]);
>> + printf("Failed to execv\n");
>> + return 255;
>> +}
>> --
>> 1.7.5.4
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe netdev" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v4 3/3] netdev/of/phy: Add MDIO bus multiplexer driven by GPIO lines.
From: David Miller @ 2012-04-18 2:53 UTC (permalink / raw)
To: ddaney.cavm
Cc: grant.likely, rob.herring, devicetree-discuss, netdev,
linux-kernel, linux-mips, afleming, galak, david.daney
In-Reply-To: <1334683966-12112-4-git-send-email-ddaney.cavm@gmail.com>
From: David Daney <ddaney.cavm@gmail.com>
Date: Tue, 17 Apr 2012 10:32:46 -0700
> From: David Daney <david.daney@cavium.com>
>
> The GPIO pins select which sub bus is connected to the master.
>
> Initially tested with an sn74cbtlv3253 switch device wired into the
> MDIO bus.
>
> Signed-off-by: David Daney <david.daney@cavium.com>
Are you sure the Kconfig dependencies are sufficient? This code seems
to depend upon OF, and in particular the OF_MDIO stuff.
^ permalink raw reply
* Re: [PATCH] ethernet: fix checkpatch errors
From: David Miller @ 2012-04-18 2:50 UTC (permalink / raw)
To: laura; +Cc: linux-kernel, netdev, eric.dumazet, nhorman
In-Reply-To: <1334672844-10129-1-git-send-email-laura@rosedu.org>
From: Laura Vasilescu <laura@rosedu.org>
Date: Tue, 17 Apr 2012 17:27:24 +0300
> Signed-off-by: Laura Vasilescu <laura@rosedu.org>
I'd rather have the checkpath errors than what we end up with
your changes:
> - else if (1 /*dev->flags&IFF_PROMISC */ ) {
> - if (unlikely(compare_ether_addr_64bits(eth->h_dest, dev->dev_addr)))
> + else if (1 /*dev->flags&IFF_PROMISC */) {
> + if (unlikely(compare_ether_addr_64bits(eth->h_dest,
> + dev->dev_addr)))
This indentation is wrong, the "dev->dev_addr" argument must line up
with the first column after the openning parenthesis on the previous
line.
> -int eth_header_cache(const struct neighbour *neigh, struct hh_cache *hh, __be16 type)
> +int eth_header_cache(const struct neighbour *neigh,
> + struct hh_cache *hh,
> + __be16 type)
Same problem here for hh and type args.
^ permalink raw reply
* [PATCH] net: filter: remove unused cpu_off
From: Eric Dumazet @ 2012-04-18 2:51 UTC (permalink / raw)
To: David Miller; +Cc: netdev
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
diff --git a/arch/sparc/net/bpf_jit_comp.c b/arch/sparc/net/bpf_jit_comp.c
index 4ce0296..1a69244 100644
--- a/arch/sparc/net/bpf_jit_comp.c
+++ b/arch/sparc/net/bpf_jit_comp.c
@@ -240,8 +240,6 @@ do { *prog++ = LD32I | RS1(FP) | S13(-(OFF)) | RD(DEST); \
do { *prog++ = LD32I | RS1(FP) | S13(-(OFF)) | RD(SRC); \
} while (0)
-#define cpu_off offsetof(struct thread_info, cpu)
-
#ifdef CONFIG_SMP
#ifdef CONFIG_SPARC64
#define emit_load_cpu(REG) \
^ permalink raw reply related
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