All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: NAT'ing multiple IPsec clients to the same destination IPSec server
From: Martijn Lievaart @ 2007-11-09 23:01 UTC (permalink / raw)
  To: pawong; +Cc: netfilter
In-Reply-To: <1194648215.26369.17.camel@fe7pawong.versa.versasys.com>

Patrick Wong wrote:
> Way back in 2.0.18 kernel, there was an IPsec connection tracking module
> that would allow me to masquerade multiple IPsec clients (eg Cisco VPN
> client) all going to the same remote IPsec server onto one external IP
> address. This was done with IPsec connection module + ipmasqadm +
> ipchains.
>
> I have never been able to get the above to work on iptables. In the
> early days of iptables, I also noticed there was no IPsec conntrack
> module. 
>
> If I have only 1 external IP address on my firewall/gateway to SNAT to,
> is there a way to support multiple IPSec clients on my internal LAN all
> establishing IPSec connections to the same destination IPSec server?
>   

Cisco VPN client supports UDP encapsulation. You have to allow it on the 
concentrator too, but if that is possible, it should work without 
specific iptables rules.

M4


^ permalink raw reply

* Re: [PATCH 1/24] mm/sparse-vmemmap.c: make sure init_mm is included
From: Jeremy Fitzhardinge @ 2007-11-09 23:00 UTC (permalink / raw)
  To: Glauber de Oliveira Costa
  Cc: lguest-mnsaURCQ41sdnm+yROfE0A,
	kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	virtualization-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
	Linus Torvalds, akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	ak-l3A5Bk7waGM
In-Reply-To: <11946337933104-git-send-email-gcosta-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>

Glauber de Oliveira Costa wrote:
> mm/sparse-vmemmap.c uses init_mm in some places.  However, it is not
> present in any of the headers currently included in the file.
>
> init_mm is defined as extern in sched.h, so we add it to the headers list
>
> Up to now, this problem was masked by the fact that functions like
> set_pte_at() and pmd_populate_kernel() are usually macros that expand to
> simpler variants that does not use the first parameter at all.
>
> Signed-off-by: Glauber de Oliveira Costa <gcosta-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> Signed-off-by: Andrew Morton <akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
> Signed-off-by: Linus Torvalds <torvalds-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
> ---
>  mm/sparse-vmemmap.c |    1 +
>  1 files changed, 1 insertions(+), 0 deletions(-)
>
> diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c
> index d3b718b..22620f6 100644
> --- a/mm/sparse-vmemmap.c
> +++ b/mm/sparse-vmemmap.c
> @@ -24,6 +24,7 @@
>  #include <linux/module.h>
>  #include <linux/spinlock.h>
>  #include <linux/vmalloc.h>
> +#include <linux/sched.h>
>   

This is already in git.

    J

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/

^ permalink raw reply

* Re: [PATCH 1/24] mm/sparse-vmemmap.c: make sure init_mm is included
From: Jeremy Fitzhardinge @ 2007-11-09 23:00 UTC (permalink / raw)
  To: Glauber de Oliveira Costa
  Cc: lguest, kvm-devel, mingo, linux-kernel, virtualization, chrisw,
	anthony, tglx, Linus Torvalds, akpm, ak
In-Reply-To: <11946337933104-git-send-email-gcosta@redhat.com>

Glauber de Oliveira Costa wrote:
> mm/sparse-vmemmap.c uses init_mm in some places.  However, it is not
> present in any of the headers currently included in the file.
>
> init_mm is defined as extern in sched.h, so we add it to the headers list
>
> Up to now, this problem was masked by the fact that functions like
> set_pte_at() and pmd_populate_kernel() are usually macros that expand to
> simpler variants that does not use the first parameter at all.
>
> Signed-off-by: Glauber de Oliveira Costa <gcosta@redhat.com>
> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
> ---
>  mm/sparse-vmemmap.c |    1 +
>  1 files changed, 1 insertions(+), 0 deletions(-)
>
> diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c
> index d3b718b..22620f6 100644
> --- a/mm/sparse-vmemmap.c
> +++ b/mm/sparse-vmemmap.c
> @@ -24,6 +24,7 @@
>  #include <linux/module.h>
>  #include <linux/spinlock.h>
>  #include <linux/vmalloc.h>
> +#include <linux/sched.h>
>   

This is already in git.

    J

^ permalink raw reply

* [PATCH 6/6] ssb: Remove the old, now unused, data structures
From: Larry Finger @ 2007-11-09 22:58 UTC (permalink / raw)
  To: John Linville; +Cc: Michael Buesch, Bcm43xx-dev, linux-wireless

Patch 6 of 6.

The old, now unused, data structures and SPROM extraction routines
are removed.

Signed-off-by: Larry Finger<Larry.Finger@lwfinger.net>
---

Index: wireless-2.6/include/linux/ssb/ssb.h
===================================================================
--- wireless-2.6.orig/include/linux/ssb/ssb.h
+++ wireless-2.6/include/linux/ssb/ssb.h
@@ -15,72 +15,7 @@ struct pcmcia_device;
 struct ssb_bus;
 struct ssb_driver;
 
-
-struct ssb_sprom_r1 {
-	u16 pci_spid;		/* Subsystem Product ID for PCI */
-	u16 pci_svid;		/* Subsystem Vendor ID for PCI */
-	u16 pci_pid;		/* Product ID for PCI */
-	u8 il0mac[6];		/* MAC address for 802.11b/g */
-	u8 et0mac[6];		/* MAC address for Ethernet */
-	u8 et1mac[6];		/* MAC address for 802.11a */
-	u8 et0phyaddr:5;	/* MII address for enet0 */
-	u8 et1phyaddr:5;	/* MII address for enet1 */
-	u8 et0mdcport:1;	/* MDIO for enet0 */
-	u8 et1mdcport:1;	/* MDIO for enet1 */
-	u8 board_rev;		/* Board revision */
-	u8 country_code:4;	/* Country Code */
-	u8 antenna_a:2;		/* Antenna 0/1 available for A-PHY */
-	u8 antenna_bg:2;	/* Antenna 0/1 available for B-PHY and G-PHY */
-	u16 pa0b0;
-	u16 pa0b1;
-	u16 pa0b2;
-	u16 pa1b0;
-	u16 pa1b1;
-	u16 pa1b2;
-	u8 gpio0;		/* GPIO pin 0 */
-	u8 gpio1;		/* GPIO pin 1 */
-	u8 gpio2;		/* GPIO pin 2 */
-	u8 gpio3;		/* GPIO pin 3 */
-	u16 maxpwr_a;		/* A-PHY Power Amplifier Max Power (in dBm Q5.2) */
-	u16 maxpwr_bg;		/* B/G-PHY Power Amplifier Max Power (in dBm Q5.2) */
-	u8 itssi_a;		/* Idle TSSI Target for A-PHY */
-	u8 itssi_bg;		/* Idle TSSI Target for B/G-PHY */
-	u16 boardflags_lo;	/* Boardflags (low 16 bits) */
-	u8 antenna_gain_a;	/* A-PHY Antenna gain (in dBm Q5.2) */
-	u8 antenna_gain_bg;	/* B/G-PHY Antenna gain (in dBm Q5.2) */
-	u8 oem[8];		/* OEM string (rev 1 only) */
-};
-
-struct ssb_sprom_r2 {
-	u16 boardflags_hi;	/* Boardflags (high 16 bits) */
-	u8 maxpwr_a_lo;		/* A-PHY Max Power Low */
-	u8 maxpwr_a_hi;		/* A-PHY Max Power High */
-	u16 pa1lob0;		/* A-PHY PA Low Settings */
-	u16 pa1lob1;		/* A-PHY PA Low Settings */
-	u16 pa1lob2;		/* A-PHY PA Low Settings */
-	u16 pa1hib0;		/* A-PHY PA High Settings */
-	u16 pa1hib1;		/* A-PHY PA High Settings */
-	u16 pa1hib2;		/* A-PHY PA High Settings */
-	u8 ofdm_pwr_off;	/* OFDM Power Offset from CCK Level */
-	u8 country_str[2];	/* Two char Country Code */
-};
-
-struct ssb_sprom_r3 {
-	u32 ofdmapo;		/* A-PHY OFDM Mid Power Offset */
-	u32 ofdmalpo;		/* A-PHY OFDM Low Power Offset */
-	u32 ofdmahpo;		/* A-PHY OFDM High Power Offset */
-	u8 gpioldc_on_cnt;	/* GPIO LED Powersave Duty Cycle ON count */
-	u8 gpioldc_off_cnt;	/* GPIO LED Powersave Duty Cycle OFF count */
-	u8 cckpo_1M:4;		/* CCK Power Offset for Rate 1M */
-	u8 cckpo_2M:4;		/* CCK Power Offset for Rate 2M */
-	u8 cckpo_55M:4;		/* CCK Power Offset for Rate 5.5M */
-	u8 cckpo_11M:4;		/* CCK Power Offset for Rate 11M */
-	u32 ofdmgpo;		/* G-PHY OFDM Power Offset */
-};
-
 struct ssb_sprom {
-	u8 revision;
-	u8 temp_fill[2 * sizeof(struct ssb_sprom_r1)];
 	u8 il0mac[6];		/* MAC address for 802.11b/g */
 	u8 et0mac[6];		/* MAC address for Ethernet */
 	u8 et1mac[6];		/* MAC address for 802.11a */
@@ -106,16 +41,6 @@ struct ssb_sprom {
 	u8 antenna_gain_bg;	/* B/G-PHY Antenna gain (in dBm Q5.2) */
 
 	/* TODO - add any parameters needed from rev 2, 3, or 4 SPROMs */
-	/* The valid r# fields are selected by the "revision".
-	 * Revision 3 and lower inherit from lower revisions.
-	 */
-	union {
-		struct {
-			struct ssb_sprom_r1 r1;
-			struct ssb_sprom_r2 r2;
-			struct ssb_sprom_r3 r3;
-		};
-	};
 };
 
 /* Information about the PCB the circuitry is soldered on. */
Index: wireless-2.6/drivers/ssb/pci.c
===================================================================
--- wireless-2.6.orig/drivers/ssb/pci.c
+++ wireless-2.6/drivers/ssb/pci.c
@@ -297,62 +297,6 @@ err_ctlreg:
 	return err;
 }
 
-static void sprom_extract_r1(struct ssb_sprom_r1 *out, const u16 *in)
-{
-	int i;
-	u16 v;
-
-	SPEX(pci_spid, SSB_SPROM1_SPID, 0xFFFF, 0);
-	SPEX(pci_svid, SSB_SPROM1_SVID, 0xFFFF, 0);
-	SPEX(pci_pid, SSB_SPROM1_PID, 0xFFFF, 0);
-	for (i = 0; i < 3; i++) {
-		v = in[SPOFF(SSB_SPROM1_IL0MAC) + i];
-		*(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
-	}
-	for (i = 0; i < 3; i++) {
-		v = in[SPOFF(SSB_SPROM1_ET0MAC) + i];
-		*(((__be16 *)out->et0mac) + i) = cpu_to_be16(v);
-	}
-	for (i = 0; i < 3; i++) {
-		v = in[SPOFF(SSB_SPROM1_ET1MAC) + i];
-		*(((__be16 *)out->et1mac) + i) = cpu_to_be16(v);
-	}
-	SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0);
-	SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A,
-	     SSB_SPROM1_ETHPHY_ET1A_SHIFT);
-	SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14);
-	SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15);
-	SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0);
-	SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
-	     SSB_SPROM1_BINF_CCODE_SHIFT);
-	SPEX(antenna_a, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTA,
-	     SSB_SPROM1_BINF_ANTA_SHIFT);
-	SPEX(antenna_bg, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTBG,
-	     SSB_SPROM1_BINF_ANTBG_SHIFT);
-	SPEX(pa0b0, SSB_SPROM1_PA0B0, 0xFFFF, 0);
-	SPEX(pa0b1, SSB_SPROM1_PA0B1, 0xFFFF, 0);
-	SPEX(pa0b2, SSB_SPROM1_PA0B2, 0xFFFF, 0);
-	SPEX(pa1b0, SSB_SPROM1_PA1B0, 0xFFFF, 0);
-	SPEX(pa1b1, SSB_SPROM1_PA1B1, 0xFFFF, 0);
-	SPEX(pa1b2, SSB_SPROM1_PA1B2, 0xFFFF, 0);
-	SPEX(gpio0, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P0, 0);
-	SPEX(gpio1, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P1,
-	     SSB_SPROM1_GPIOA_P1_SHIFT);
-	SPEX(gpio2, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P2, 0);
-	SPEX(gpio3, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P3,
-	     SSB_SPROM1_GPIOB_P3_SHIFT);
-	SPEX(maxpwr_a, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_A,
-	     SSB_SPROM1_MAXPWR_A_SHIFT);
-	SPEX(maxpwr_bg, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_BG, 0);
-	SPEX(itssi_a, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_A,
-	     SSB_SPROM1_ITSSI_A_SHIFT);
-	SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0);
-	SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0);
-	SPEX(antenna_gain_a, SSB_SPROM1_AGAIN, SSB_SPROM1_AGAIN_A, 0);
-	SPEX(antenna_gain_bg, SSB_SPROM1_AGAIN, SSB_SPROM1_AGAIN_BG,
-	     SSB_SPROM1_AGAIN_BG_SHIFT);
-}
-
 static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
 {
 	int i;
@@ -414,7 +358,7 @@ static void sprom_extract_r4(struct ssb_
 	int i;
 	u16 v;
 
-	/* extract the r1 variables */
+	/* extract the equivalent of the r1 variables */
 	for (i = 0; i < 3; i++) {
 		v = in[SPOFF(SSB_SPROM4_IL0MAC) + i];
 		*(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
@@ -435,6 +379,18 @@ static void sprom_extract_r4(struct ssb_
 	SPEX(antenna_gain_a, SSB_SPROM4_AGAIN, SSB_SPROM4_AGAIN_0, 0);
 	SPEX(antenna_gain_bg, SSB_SPROM4_AGAIN, SSB_SPROM4_AGAIN_1,
 	     SSB_SPROM4_AGAIN_1_SHIFT);
+	SPEX(maxpwr_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_MAXP_BG_MASK, 0);
+	SPEX(itssi_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_ITSSI_BG,
+	     SSB_SPROM4_ITSSI_BG_SHIFT);
+	SPEX(maxpwr_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_MAXP_A_MASK, 0);
+	SPEX(itssi_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_ITSSI_A,
+	     SSB_SPROM4_ITSSI_A_SHIFT);
+	SPEX(gpio0, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P0, 0);
+	SPEX(gpio1, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P1,
+	     SSB_SPROM4_GPIOA_P1_SHIFT);
+	SPEX(gpio2, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P2, 0);
+	SPEX(gpio3, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P3,
+	     SSB_SPROM4_GPIOB_P3_SHIFT);
 	/* TODO - get remaining rev 4 stuff needed */
 }
 
@@ -444,13 +400,13 @@ static int sprom_extract(struct ssb_bus 
 	memset(out, 0, sizeof(*out));
 
 	out->revision = in[size - 1] & 0x00FF;
+	ssb_printk(KERN_INFO PFX "SPROM revision %d detected.\n", out->revision);
 	if ((bus->chip_id & 0xFF00) == 0x4400) {
 		/* Workaround: The BCM44XX chip has a stupid revision
 		 * number stored in the SPROM.
 		 * Always extract r1. */
 		out->revision = 1;
 		sprom_extract_r123(out, in);
-		sprom_extract_r1(&out->r1, in);
 	} else if (bus->chip_id == 0x4321) {
 		/* the BCM4328 has a chipid == 0x4321 and a rev 4 SPROM */
 		out->revision = 4;
@@ -460,7 +416,6 @@ static int sprom_extract(struct ssb_bus 
 			goto unsupported;
 		if (out->revision >= 1 && out->revision <= 3) {
 			sprom_extract_r123(out, in);
-			sprom_extract_r1(&out->r1, in);
 		}
 		if (out->revision == 4)
 			sprom_extract_r4(out, in);
@@ -472,7 +427,7 @@ static int sprom_extract(struct ssb_bus 
 unsupported:
 	ssb_printk(KERN_WARNING PFX "Unsupported SPROM revision %d "
 		   "detected. Will extract v1\n", out->revision);
-	sprom_extract_r1(&out->r1, in);
+	sprom_extract_r123(out, in);
 	return 0;
 }
 
Index: wireless-2.6/include/linux/ssb/ssb_regs.h
===================================================================
--- wireless-2.6.orig/include/linux/ssb/ssb_regs.h
+++ wireless-2.6/include/linux/ssb/ssb_regs.h
@@ -175,6 +175,7 @@
 #define  SSB_SPROM_REVISION_REV		0x00FF	/* SPROM Revision number */
 #define  SSB_SPROM_REVISION_CRC		0xFF00	/* SPROM CRC8 value */
 #define  SSB_SPROM_REVISION_CRC_SHIFT	8
+
 /* SPROM Revision 1 */
 #define SSB_SPROM1_SPID			0x1004	/* Subsystem Product ID for PCI */
 #define SSB_SPROM1_SVID			0x1006	/* Subsystem Vendor ID for PCI */
@@ -223,7 +224,7 @@
 #define  SSB_SPROM1_AGAIN_A		0x00FF	/* A-PHY */
 #define  SSB_SPROM1_AGAIN_BG		0xFF00	/* B-PHY and G-PHY */
 #define  SSB_SPROM1_AGAIN_BG_SHIFT	8
-#define SSB_SPROM1_OEM			0x1076	/* 8 bytes OEM string (rev 1 only) */
+
 /* SPROM Revision 2 (inherits from rev 1) */
 #define SSB_SPROM2_BFLHI		0x1038	/* Boardflags (high 16 bits) */
 #define SSB_SPROM2_MAXP_A		0x103A	/* A-PHY Max Power */
@@ -240,6 +241,7 @@
 #define  SSB_SPROM2_OPO_VALUE		0x00FF
 #define  SSB_SPROM2_OPO_UNUSED		0xFF00
 #define SSB_SPROM2_CCODE		0x107C	/* Two char Country Code */
+
 /* SPROM Revision 3 (inherits most data from rev 2) */
 #define SSB_SPROM3_IL0MAC		0x104A	/* 6 bytes MAC address for 802.11b/g */
 #define SSB_SPROM3_ET0MAC		0x1050	/* 6 bytes MAC address for Ethernet ?? */
@@ -261,11 +263,12 @@
 #define  SSB_SPROM3_CCKPO_11M		0xF000	/* 11M Rate PO */
 #define  SSB_SPROM3_CCKPO_11M_SHIFT	12
 #define  SSB_SPROM3_OFDMGPO		0x107A	/* G-PHY OFDM Power Offset (4 bytes, BigEndian) */
+
 /* SPROM Revision 4 		entries with ?? in comment are unknown */
-#define SSB_SPROM4_IL0MAC		0x104C	/* 6 byte MAC address for b/g */
+#define SSB_SPROM4_IL0MAC		0x104C	/* 6 byte MAC address for a/b/g/n */
 #define SSB_SPROM4_ET0MAC		0x1018	/* 6 bytes MAC address for Ethernet ?? */
 #define SSB_SPROM4_ET1MAC		0x1018	/* 6 bytes MAC address for 802.11a ?? */
-#define SSB_SPROM4_ETHPHY		0x105A	/* Ethernet PHY settings */
+#define SSB_SPROM4_ETHPHY		0x105A	/* Ethernet PHY settings ?? */
 #define  SSB_SPROM4_ETHPHY_ET0A		0x001F	/* MII Address for enet0 */
 #define  SSB_SPROM4_ETHPHY_ET1A		0x03E0	/* MII Address for enet1 */
 #define  SSB_SPROM4_ETHPHY_ET1A_SHIFT	5
@@ -280,24 +283,28 @@
 #define  SSB_SPROM4_AGAIN_1		0xFF00	/* Antenna 1 */
 #define  SSB_SPROM4_AGAIN_1_SHIFT	8
 #define SSB_SPROM4_BFLHI		0x1046  /* Board Flags Hi */
-#define SSB_SPROM4_MAXP_A		0x1000  /* Max Power A ?? */
-#define SSB_SPROM4_MAXP_A_HI		0x00FF  /* Mask for Hi */
-#define SSB_SPROM4_MAXP_A_LO		0xFF00  /* Mask for Lo */
-#define SSB_SPROM4_MAXP_A_LO_SHIFT	16	/* Shift for Lo */
-#define SSB_SPROM4_PA1LOB0		0x1000  /* ?? */
-#define SSB_SPROM4_PA1LOB1		0x1000  /* ?? */
-#define SSB_SPROM4_PA1LOB2		0x1000  /* ?? */
-#define SSB_SPROM4_PA1HIB0		0x1000	/* ?? */
-#define SSB_SPROM4_PA1HIB1		0x1000	/* ?? */
-#define SSB_SPROM4_PA1HIB2		0x1000	/* ?? */
-#define SSB_SPROM4_OPO			0x1000	/* ?? */
-#define SSB_SPROM4_OPO_VALUE		0x0000	/* ?? */
-#define SSB_SPROM4_GPIOLDC		0x105A	/* LED Powersave Duty Cycle */
-#define  SSB_SPROM4_GPIOLDC_OFF		0x0000FF00	/* Off Count */
-#define  SSB_SPROM4_GPIOLDC_OFF_SHIFT	8
-#define  SSB_SPROM4_GPIOLDC_ON		0x00FF0000	/* On Count */
-#define  SSB_SPROM4_GPIOLDC_ON_SHIFT	16
-
+#define SSB_SPROM4_MAXP_BG		0x1080  /* Max Power BG in path 1 */
+#define  SSB_SPROM4_MAXP_BG_MASK	0x00FF  /* Mask for Max Power BG */
+#define  SSB_SPROM4_ITSSI_BG		0xFF00	/* Mask for path 1 itssi_bg */
+#define  SSB_SPROM4_ITSSI_BG_SHIFT	8
+#define SSB_SPROM4_MAXP_A		0x108A  /* Max Power A in path 1 */
+#define  SSB_SPROM4_MAXP_A_MASK		0x00FF  /* Mask for Max Power A */
+#define  SSB_SPROM4_ITSSI_A		0xFF00	/* Mask for path 1 itssi_a */
+#define  SSB_SPROM4_ITSSI_A_SHIFT	8
+#define SSB_SPROM4_GPIOA		0x1056	/* Gen. Purpose IO # 0 and 1 */
+#define  SSB_SPROM4_GPIOA_P0		0x00FF	/* Pin 0 */
+#define  SSB_SPROM4_GPIOA_P1		0xFF00	/* Pin 1 */
+#define  SSB_SPROM4_GPIOA_P1_SHIFT	8
+#define SSB_SPROM4_GPIOB		0x1058	/* Gen. Purpose IO # 2 and 3 */
+#define  SSB_SPROM4_GPIOB_P2		0x00FF	/* Pin 2 */
+#define  SSB_SPROM4_GPIOB_P3		0xFF00	/* Pin 3 */
+#define  SSB_SPROM4_GPIOB_P3_SHIFT	8
+#define SSB_SPROM4_PA0B0		0x1082	/* The paXbY locations are */
+#define SSB_SPROM4_PA0B1		0x1084	/*   only guesses */
+#define SSB_SPROM4_PA0B2		0x1086
+#define SSB_SPROM4_PA1B0		0x108E
+#define SSB_SPROM4_PA1B1		0x1090
+#define SSB_SPROM4_PA1B2		0x1092
 
 /* Values for SSB_SPROM1_BINF_CCODE */
 enum {

^ permalink raw reply

* Re: git submodules and diffing
From: Jakub Narebski @ 2007-11-09 22:57 UTC (permalink / raw)
  To: Sven Herzberg, git; +Cc: Jakub Narebski
In-Reply-To: <4D079E0B-D6FB-4FBA-B449-2EFBFD5A5DE4@imendio.com>

Sven Herzberg wrote:

> When I started working with git submodules, I realized that git-diff  
> only lists the revision ids of a submodule if it has changed. I have  
> created a repository which includes a diff command for git-submodule,  
> so you can use it like "gut submodule diff <modules...>"
> 
> I pushed my git tree at git://git.imendio.com/sven/git.git

I have checked it int the gitweb at
  http://git.imendio.com/?p=sven/git.git

> Feel free to look into the changes and request improvements or merge  
> it into your tree.

As far as I can see that is single patch (single commit) on top of
git.git repository, so you could have send this patch to the list,
to be commented upon.

Although having "git submodule diff" is quite nice, I'd rather have
"git diff --recurse-submodules" (or something like that) if I want to
get diff of submodules.

>From browsing commitdiff
  http://git.imendio.com/?p=sven/git.git;a=commitdiff;h=7fa1d4911d1ac2590ab1eccd84a7f235aca7878e
I'd like to mention that instead of

  (unset GIT_DIR && cd "$path" && git diff $flag "$sha1..HEAD")

you can simply use

  git --git-dir="$path" diff $flag "$sha1..HEAD"

Note that you can write "$sha1.." (but it is a bit cryptic)

> PS: Please CC me, I'm not on this list

You can always read list using NNTP / news / Usenet interface at
  nntp://news.gmane.org/gmane.comp.version-control.git
or one of the mailing list archives, see
  http://git.or.cz/gitwiki/GitCommunity

-- 
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git

^ permalink raw reply

* Re: TSO doesn't work for domU (because of routing?)
From: Milan Holzäpfel @ 2007-11-09 22:58 UTC (permalink / raw)
  To: xen-devel
In-Reply-To: <20071029083219.32e70394.listen@mjh.name>

On Mon, 29 Oct 2007 08:32:19 +0100
Milan Holzäpfel <listen@mjh.name> wrote:

> [...]
> All my xen virtual networks are routed.  Is domU TSO supposed to work
> in a routed environment?  If not, should it be disabled automatically?
> 
> Xen version is Xen-3.1.1.  Kernel version is 2.6.22.9-0.4 from
> OpenSUSE-10.3.  

Is there actually any information on this?  Am I asking on the wrong ML
or did I miss sth else important? 

Regards,
Milan


-- 
Milan Holzaepfel <mail(a)mjh(d)name>             <URL:http://mjh.name/>
pub  4096R/C790FC23  EB8E 5E81 81E3 53A9 9B74  B895 5179 54C0 C790 FC23

^ permalink raw reply

* Re: underruns and strange code in pcm_rate.c
From: Timur Tabi @ 2007-11-09 22:53 UTC (permalink / raw)
  To: Stas Sergeev; +Cc: alsa-devel, Lee Revell
In-Reply-To: <4734E4AF.3020809@aknet.ru>

Stas Sergeev wrote:
> Hello.
> 
> Lee Revell wrote:
>>> Ok, now I'm confused.  Isn't this whole thread is about underrun problems with
>>> OSS?
>> Yes.
> Any evidence of this?

I can only get an underrun if using OSS.

-- 
Timur Tabi
Linux kernel developer at Freescale

^ permalink raw reply

* [PATCH 5/6] b43legacy: Convert to use of the new SPROM structure
From: Larry Finger @ 2007-11-09 22:57 UTC (permalink / raw)
  To: John Linville; +Cc: Michael Buesch, Bcm43xx-dev, linux-wireless

Patch 5 of 6.

The b43legacy driver is modified to use the new SPROM structure.

Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
---

Index: wireless-2.6/drivers/net/wireless/b43legacy/leds.c
===================================================================
--- wireless-2.6.orig/drivers/net/wireless/b43legacy/leds.c
+++ wireless-2.6/drivers/net/wireless/b43legacy/leds.c
@@ -189,10 +189,10 @@ void b43legacy_leds_init(struct b43legac
 	enum b43legacy_led_behaviour behaviour;
 	bool activelow;
 
-	sprom[0] = bus->sprom.r1.gpio0;
-	sprom[1] = bus->sprom.r1.gpio1;
-	sprom[2] = bus->sprom.r1.gpio2;
-	sprom[3] = bus->sprom.r1.gpio3;
+	sprom[0] = bus->sprom.gpio0;
+	sprom[1] = bus->sprom.gpio1;
+	sprom[2] = bus->sprom.gpio2;
+	sprom[3] = bus->sprom.gpio3;
 
 	for (i = 0; i < 4; i++) {
 		if (sprom[i] == 0xFF) {
Index: wireless-2.6/drivers/net/wireless/b43legacy/main.c
===================================================================
--- wireless-2.6.orig/drivers/net/wireless/b43legacy/main.c
+++ wireless-2.6/drivers/net/wireless/b43legacy/main.c
@@ -1753,7 +1753,7 @@ static int b43legacy_gpio_init(struct b4
 		mask |= 0x0060;
 		set |= 0x0060;
 	}
-	if (dev->dev->bus->sprom.r1.boardflags_lo & B43legacy_BFL_PACTRL) {
+	if (dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_PACTRL) {
 		b43legacy_write16(dev, B43legacy_MMIO_GPIO_MASK,
 				  b43legacy_read16(dev,
 				  B43legacy_MMIO_GPIO_MASK)
@@ -2130,7 +2130,7 @@ static void b43legacy_periodic_every120s
 static void b43legacy_periodic_every60sec(struct b43legacy_wldev *dev)
 {
 	b43legacy_phy_lo_mark_all_unused(dev);
-	if (dev->dev->bus->sprom.r1.boardflags_lo & B43legacy_BFL_RSSI) {
+	if (dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_RSSI) {
 		b43legacy_mac_suspend(dev);
 		b43legacy_calc_nrssi_slope(dev);
 		b43legacy_mac_enable(dev);
@@ -3058,7 +3058,7 @@ static int b43legacy_wireless_core_init(
 		hf |= B43legacy_HF_SYMW;
 		if (phy->rev == 1)
 			hf |= B43legacy_HF_GDCW;
-		if (sprom->r1.boardflags_lo & B43legacy_BFL_PACTRL)
+		if (sprom->boardflags_lo & B43legacy_BFL_PACTRL)
 			hf |= B43legacy_HF_OFDMPABOOST;
 	} else if (phy->type == B43legacy_PHYTYPE_B) {
 		hf |= B43legacy_HF_SYMW;
@@ -3537,12 +3537,12 @@ static void b43legacy_sprom_fixup(struct
 	if (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE &&
 	    bus->boardinfo.type == 0x4E &&
 	    bus->boardinfo.rev > 0x40)
-		bus->sprom.r1.boardflags_lo |= B43legacy_BFL_PACTRL;
+		bus->sprom.boardflags_lo |= B43legacy_BFL_PACTRL;
 
 	/* Convert Antennagain values to Q5.2 */
-	if (bus->sprom.r1.antenna_gain_bg == 0xFF)
-		bus->sprom.r1.antenna_gain_bg = 2; /* if unset, use 2 dBm */
-	bus->sprom.r1.antenna_gain_bg <<= 2;
+	if (bus->sprom.antenna_gain_bg == 0xFF)
+		bus->sprom.antenna_gain_bg = 2; /* if unset, use 2 dBm */
+	bus->sprom.antenna_gain_bg <<= 2;
 }
 
 static void b43legacy_wireless_exit(struct ssb_device *dev,
@@ -3577,10 +3577,10 @@ static int b43legacy_wireless_init(struc
 	hw->max_noise = -110;
 	hw->queues = 1; /* FIXME: hardware has more queues */
 	SET_IEEE80211_DEV(hw, dev->dev);
-	if (is_valid_ether_addr(sprom->r1.et1mac))
-		SET_IEEE80211_PERM_ADDR(hw, sprom->r1.et1mac);
+	if (is_valid_ether_addr(sprom->et1mac))
+		SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac);
 	else
-		SET_IEEE80211_PERM_ADDR(hw, sprom->r1.il0mac);
+		SET_IEEE80211_PERM_ADDR(hw, sprom->il0mac);
 
 	/* Get and initialize struct b43legacy_wl */
 	wl = hw_to_b43legacy_wl(hw);
Index: wireless-2.6/drivers/net/wireless/b43legacy/phy.c
===================================================================
--- wireless-2.6.orig/drivers/net/wireless/b43legacy/phy.c
+++ wireless-2.6/drivers/net/wireless/b43legacy/phy.c
@@ -441,7 +441,7 @@ static void b43legacy_phy_inita(struct b
 	might_sleep();
 
 	b43legacy_phy_setupg(dev);
-	if (dev->dev->bus->sprom.r1.boardflags_lo & B43legacy_BFL_PACTRL)
+	if (dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_PACTRL)
 		b43legacy_phy_write(dev, 0x046E, 0x03CF);
 }
 
@@ -543,7 +543,7 @@ static void b43legacy_phy_initb4(struct 
 	if (phy->radio_ver == 0x2050)
 		b43legacy_phy_write(dev, 0x002A, 0x88C2);
 	b43legacy_radio_set_txpower_bg(dev, 0xFFFF, 0xFFFF, 0xFFFF);
-	if (dev->dev->bus->sprom.r1.boardflags_lo & B43legacy_BFL_RSSI) {
+	if (dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_RSSI) {
 		b43legacy_calc_nrssi_slope(dev);
 		b43legacy_calc_nrssi_threshold(dev);
 	}
@@ -699,7 +699,7 @@ static void b43legacy_phy_initb6(struct 
 		b43legacy_radio_write16(dev, 0x005A, 0x0088);
 		b43legacy_radio_write16(dev, 0x005B, 0x006B);
 		b43legacy_radio_write16(dev, 0x005C, 0x000F);
-		if (dev->dev->bus->sprom.r1.boardflags_lo & 0x8000) {
+		if (dev->dev->bus->sprom.boardflags_lo & 0x8000) {
 			b43legacy_radio_write16(dev, 0x005D, 0x00FA);
 			b43legacy_radio_write16(dev, 0x005E, 0x00D8);
 		} else {
@@ -797,7 +797,7 @@ static void b43legacy_phy_initb6(struct 
 		b43legacy_phy_write(dev, 0x0062, 0x0007);
 		b43legacy_radio_init2050(dev);
 		b43legacy_phy_lo_g_measure(dev);
-		if (dev->dev->bus->sprom.r1.boardflags_lo &
+		if (dev->dev->bus->sprom.boardflags_lo &
 		    B43legacy_BFL_RSSI) {
 			b43legacy_calc_nrssi_slope(dev);
 			b43legacy_calc_nrssi_threshold(dev);
@@ -921,7 +921,7 @@ static void b43legacy_calc_loopback_gain
 			    b43legacy_phy_read(dev, 0x0811) | 0x0100);
 	b43legacy_phy_write(dev, 0x0812,
 			    b43legacy_phy_read(dev, 0x0812) & 0xCFFF);
-	if (dev->dev->bus->sprom.r1.boardflags_lo & B43legacy_BFL_EXTLNA) {
+	if (dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_EXTLNA) {
 		if (phy->rev >= 7) {
 			b43legacy_phy_write(dev, 0x0811,
 					    b43legacy_phy_read(dev, 0x0811)
@@ -1072,7 +1072,7 @@ static void b43legacy_phy_initg(struct b
 			b43legacy_phy_write(dev, 0x0036,
 					    (b43legacy_phy_read(dev, 0x0036)
 					     & 0x0FFF) | (phy->txctl2 << 12));
-		if (dev->dev->bus->sprom.r1.boardflags_lo &
+		if (dev->dev->bus->sprom.boardflags_lo &
 		    B43legacy_BFL_PACTRL)
 			b43legacy_phy_write(dev, 0x002E, 0x8075);
 		else
@@ -1087,7 +1087,7 @@ static void b43legacy_phy_initg(struct b
 		b43legacy_phy_write(dev, 0x080F, 0x8078);
 	}
 
-	if (!(dev->dev->bus->sprom.r1.boardflags_lo & B43legacy_BFL_RSSI)) {
+	if (!(dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_RSSI)) {
 		/* The specs state to update the NRSSI LT with
 		 * the value 0x7FFFFFFF here. I think that is some weird
 		 * compiler optimization in the original driver.
@@ -1838,9 +1838,9 @@ void b43legacy_phy_xmitpower(struct b43l
 
 	estimated_pwr = b43legacy_phy_estimate_power_out(dev, average);
 
-	max_pwr = dev->dev->bus->sprom.r1.maxpwr_bg;
+	max_pwr = dev->dev->bus->sprom.maxpwr_bg;
 
-	if ((dev->dev->bus->sprom.r1.boardflags_lo
+	if ((dev->dev->bus->sprom.boardflags_lo
 	     & B43legacy_BFL_PACTRL) &&
 	    (phy->type == B43legacy_PHYTYPE_G))
 		max_pwr -= 0x3;
@@ -1848,7 +1848,7 @@ void b43legacy_phy_xmitpower(struct b43l
 		b43legacywarn(dev->wl, "Invalid max-TX-power value in SPROM."
 			"\n");
 		max_pwr = 74; /* fake it */
-		dev->dev->bus->sprom.r1.maxpwr_bg = max_pwr;
+		dev->dev->bus->sprom.maxpwr_bg = max_pwr;
 	}
 
 	/* Use regulatory information to get the maximum power.
@@ -1858,7 +1858,8 @@ void b43legacy_phy_xmitpower(struct b43l
 	 * and 1.5 dBm (a safety factor??). The result is in Q5.2 format
 	 * which accounts for the factor of 4 */
 #define REG_MAX_PWR 20
-	max_pwr = min(REG_MAX_PWR * 4 - dev->dev->bus->sprom.r1.antenna_gain_bg
+	max_pwr = min(REG_MAX_PWR * 4
+		      - dev->dev->bus->sprom.antenna_gain_bg
 		      - 0x6, max_pwr);
 
 	/* find the desired power in Q5.2 - power_level is in dBm
@@ -1918,7 +1919,7 @@ void b43legacy_phy_xmitpower(struct b43l
 				txpower = 3;
 				radio_attenuation += 2;
 				baseband_attenuation += 2;
-			} else if (dev->dev->bus->sprom.r1.boardflags_lo
+			} else if (dev->dev->bus->sprom.boardflags_lo
 				   & B43legacy_BFL_PACTRL) {
 				baseband_attenuation += 4 *
 						     (radio_attenuation - 2);
@@ -2000,9 +2001,9 @@ int b43legacy_phy_init_tssi2dbm_table(st
 
 	B43legacy_WARN_ON(!(phy->type == B43legacy_PHYTYPE_B ||
 			  phy->type == B43legacy_PHYTYPE_G));
-	pab0 = (s16)(dev->dev->bus->sprom.r1.pa0b0);
-	pab1 = (s16)(dev->dev->bus->sprom.r1.pa0b1);
-	pab2 = (s16)(dev->dev->bus->sprom.r1.pa0b2);
+	pab0 = (s16)(dev->dev->bus->sprom.pa0b0);
+	pab1 = (s16)(dev->dev->bus->sprom.pa0b1);
+	pab2 = (s16)(dev->dev->bus->sprom.pa0b2);
 
 	if ((dev->dev->bus->chip_id == 0x4301) && (phy->radio_ver != 0x2050)) {
 		phy->idle_tssi = 0x34;
@@ -2013,9 +2014,10 @@ int b43legacy_phy_init_tssi2dbm_table(st
 	if (pab0 != 0 && pab1 != 0 && pab2 != 0 &&
 	    pab0 != -1 && pab1 != -1 && pab2 != -1) {
 		/* The pabX values are set in SPROM. Use them. */
-		if ((s8)dev->dev->bus->sprom.r1.itssi_bg != 0 &&
-		    (s8)dev->dev->bus->sprom.r1.itssi_bg != -1)
-			phy->idle_tssi = (s8)(dev->dev->bus->sprom.r1.itssi_bg);
+		if ((s8)dev->dev->bus->sprom.itssi_bg != 0 &&
+		    (s8)dev->dev->bus->sprom.itssi_bg != -1)
+			phy->idle_tssi = (s8)(dev->dev->bus->sprom.
+					  itssi_bg);
 		else
 			phy->idle_tssi = 62;
 		dyn_tssi2dbm = kmalloc(64, GFP_KERNEL);
Index: wireless-2.6/drivers/net/wireless/b43legacy/radio.c
===================================================================
--- wireless-2.6.orig/drivers/net/wireless/b43legacy/radio.c
+++ wireless-2.6/drivers/net/wireless/b43legacy/radio.c
@@ -827,7 +827,7 @@ void b43legacy_calc_nrssi_threshold(stru
 	case B43legacy_PHYTYPE_B: {
 		if (phy->radio_ver != 0x2050)
 			return;
-		if (!(dev->dev->bus->sprom.r1.boardflags_lo &
+		if (!(dev->dev->bus->sprom.boardflags_lo &
 		    B43legacy_BFL_RSSI))
 			return;
 
@@ -857,7 +857,7 @@ void b43legacy_calc_nrssi_threshold(stru
 	}
 	case B43legacy_PHYTYPE_G:
 		if (!phy->gmode ||
-		    !(dev->dev->bus->sprom.r1.boardflags_lo &
+		    !(dev->dev->bus->sprom.boardflags_lo &
 		    B43legacy_BFL_RSSI)) {
 			tmp16 = b43legacy_nrssi_hw_read(dev, 0x20);
 			if (tmp16 >= 0x20)
@@ -1406,7 +1406,7 @@ static u16 b43legacy_get_812_value(struc
 	if (!phy->gmode)
 		return 0;
 	if (!has_loopback_gain(phy)) {
-		if (phy->rev < 7 || !(dev->dev->bus->sprom.r1.boardflags_lo
+		if (phy->rev < 7 || !(dev->dev->bus->sprom.boardflags_lo
 		    & B43legacy_BFL_EXTLNA)) {
 			switch (lpd) {
 			case LPD(0, 1, 1):
@@ -1459,7 +1459,7 @@ static u16 b43legacy_get_812_value(struc
 		}
 
 		loop_or = (loop << 8) | extern_lna_control;
-		if (phy->rev >= 7 && dev->dev->bus->sprom.r1.boardflags_lo
+		if (phy->rev >= 7 && dev->dev->bus->sprom.boardflags_lo
 		    & B43legacy_BFL_EXTLNA) {
 			if (extern_lna_control)
 				loop_or |= 0x8000;
@@ -1550,7 +1550,7 @@ u16 b43legacy_radio_init2050(struct b43l
 					    b43legacy_get_812_value(dev,
 					    LPD(0, 1, 1)));
 			if (phy->rev < 7 ||
-			    !(dev->dev->bus->sprom.r1.boardflags_lo
+			    !(dev->dev->bus->sprom.boardflags_lo
 			    & B43legacy_BFL_EXTLNA))
 				b43legacy_phy_write(dev, 0x0811, 0x01B3);
 			else
@@ -1786,7 +1786,7 @@ int b43legacy_radio_selectchannel(struct
 			  channel2freq_bg(channel));
 
 	if (channel == 14) {
-		if (dev->dev->bus->sprom.r1.country_code == 5)   /* JAPAN) */
+		if (dev->dev->bus->sprom.country_code == 5)   /* JAPAN) */
 			b43legacy_shm_write32(dev, B43legacy_SHM_SHARED,
 					      B43legacy_UCODEFLAGS_OFFSET,
 					      b43legacy_shm_read32(dev,
Index: wireless-2.6/drivers/net/wireless/b43legacy/xmit.c
===================================================================
--- wireless-2.6.orig/drivers/net/wireless/b43legacy/xmit.c
+++ wireless-2.6/drivers/net/wireless/b43legacy/xmit.c
@@ -378,7 +378,7 @@ static s8 b43legacy_rssi_postprocess(str
 			else
 				tmp -= 3;
 		} else {
-			if (dev->dev->bus->sprom.r1.boardflags_lo
+			if (dev->dev->bus->sprom.boardflags_lo
 			    & B43legacy_BFL_RSSI) {
 				if (in_rssi > 63)
 					in_rssi = 63;

^ permalink raw reply

* [PATCH 4/6] b43: Convert to use of the new SPROM structure
From: Larry Finger @ 2007-11-09 22:57 UTC (permalink / raw)
  To: John Linville; +Cc: Michael Buesch, Bcm43xx-dev, linux-wireless

Patch 4 of 6.

The b43 driver is modified to use the new SPROM structure.

Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
---

Index: wireless-2.6/drivers/net/wireless/b43/leds.c
===================================================================
--- wireless-2.6.orig/drivers/net/wireless/b43/leds.c
+++ wireless-2.6/drivers/net/wireless/b43/leds.c
@@ -187,10 +187,10 @@ void b43_leds_init(struct b43_wldev *dev
 	enum b43_led_behaviour behaviour;
 	bool activelow;
 
-	sprom[0] = bus->sprom.r1.gpio0;
-	sprom[1] = bus->sprom.r1.gpio1;
-	sprom[2] = bus->sprom.r1.gpio2;
-	sprom[3] = bus->sprom.r1.gpio3;
+	sprom[0] = bus->sprom.gpio0;
+	sprom[1] = bus->sprom.gpio1;
+	sprom[2] = bus->sprom.gpio2;
+	sprom[3] = bus->sprom.gpio3;
 
 	for (i = 0; i < 4; i++) {
 		if (sprom[i] == 0xFF) {
Index: wireless-2.6/drivers/net/wireless/b43/lo.c
===================================================================
--- wireless-2.6.orig/drivers/net/wireless/b43/lo.c
+++ wireless-2.6/drivers/net/wireless/b43/lo.c
@@ -264,8 +264,8 @@ static u16 lo_measure_feedthrough(struct
 		rfover |= pga;
 		rfover |= lna;
 		rfover |= trsw_rx;
-		if ((dev->dev->bus->sprom.r1.boardflags_lo & B43_BFL_EXTLNA) &&
-		    phy->rev > 6)
+		if ((dev->dev->bus->sprom.boardflags_lo & B43_BFL_EXTLNA)
+		    && phy->rev > 6)
 			rfover |= B43_PHY_RFOVERVAL_EXTLNA;
 
 		b43_phy_write(dev, B43_PHY_PGACTL, 0xE300);
@@ -634,7 +634,7 @@ static void lo_measure_setup(struct b43_
 			      & 0xFFFC);
 		if (phy->type == B43_PHYTYPE_G) {
 			if ((phy->rev >= 7) &&
-			    (sprom->r1.boardflags_lo & B43_BFL_EXTLNA)) {
+			    (sprom->boardflags_lo & B43_BFL_EXTLNA)) {
 				b43_phy_write(dev, B43_PHY_RFOVER, 0x933);
 			} else {
 				b43_phy_write(dev, B43_PHY_RFOVER, 0x133);
Index: wireless-2.6/drivers/net/wireless/b43/main.c
===================================================================
--- wireless-2.6.orig/drivers/net/wireless/b43/main.c
+++ wireless-2.6/drivers/net/wireless/b43/main.c
@@ -1924,7 +1924,7 @@ static int b43_gpio_init(struct b43_wlde
 		mask |= 0x0180;
 		set |= 0x0180;
 	}
-	if (dev->dev->bus->sprom.r1.boardflags_lo & B43_BFL_PACTRL) {
+	if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL) {
 		b43_write16(dev, B43_MMIO_GPIO_MASK,
 			    b43_read16(dev, B43_MMIO_GPIO_MASK)
 			    | 0x0200);
@@ -2289,7 +2289,7 @@ static void b43_periodic_every60sec(stru
 
 	if (!b43_has_hardware_pctl(phy))
 		b43_lo_g_ctl_mark_all_unused(dev);
-	if (dev->dev->bus->sprom.r1.boardflags_lo & B43_BFL_RSSI) {
+	if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI) {
 		b43_mac_suspend(dev);
 		b43_calc_nrssi_slope(dev);
 		if ((phy->radio_ver == 0x2050) && (phy->radio_rev == 8)) {
@@ -3208,13 +3208,13 @@ static void b43_bluetooth_coext_enable(s
 	struct ssb_sprom *sprom = &dev->dev->bus->sprom;
 	u32 hf;
 
-	if (!(sprom->r1.boardflags_lo & B43_BFL_BTCOEXIST))
+	if (!(sprom->boardflags_lo & B43_BFL_BTCOEXIST))
 		return;
 	if (dev->phy.type != B43_PHYTYPE_B && !dev->phy.gmode)
 		return;
 
 	hf = b43_hf_read(dev);
-	if (sprom->r1.boardflags_lo & B43_BFL_BTCMOD)
+	if (sprom->boardflags_lo & B43_BFL_BTCMOD)
 		hf |= B43_HF_BTCOEXALT;
 	else
 		hf |= B43_HF_BTCOEX;
@@ -3348,7 +3348,7 @@ static int b43_wireless_core_init(struct
 		hf |= B43_HF_SYMW;
 		if (phy->rev == 1)
 			hf |= B43_HF_GDCW;
-		if (sprom->r1.boardflags_lo & B43_BFL_PACTRL)
+		if (sprom->boardflags_lo & B43_BFL_PACTRL)
 			hf |= B43_HF_OFDMPABOOST;
 	} else if (phy->type == B43_PHYTYPE_B) {
 		hf |= B43_HF_SYMW;
@@ -3859,20 +3859,20 @@ static void b43_sprom_fixup(struct ssb_b
 	/* boardflags workarounds */
 	if (bus->boardinfo.vendor == SSB_BOARDVENDOR_DELL &&
 	    bus->chip_id == 0x4301 && bus->boardinfo.rev == 0x74)
-		bus->sprom.r1.boardflags_lo |= B43_BFL_BTCOEXIST;
+		bus->sprom.boardflags_lo |= B43_BFL_BTCOEXIST;
 	if (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE &&
 	    bus->boardinfo.type == 0x4E && bus->boardinfo.rev > 0x40)
-		bus->sprom.r1.boardflags_lo |= B43_BFL_PACTRL;
+		bus->sprom.boardflags_lo |= B43_BFL_PACTRL;
 
 	/* Handle case when gain is not set in sprom */
-	if (bus->sprom.r1.antenna_gain_a == 0xFF)
-		bus->sprom.r1.antenna_gain_a = 2;
-	if (bus->sprom.r1.antenna_gain_bg == 0xFF)
-		bus->sprom.r1.antenna_gain_bg = 2;
+	if (bus->sprom.antenna_gain_a == 0xFF)
+		bus->sprom.antenna_gain_a = 2;
+	if (bus->sprom.antenna_gain_bg == 0xFF)
+		bus->sprom.antenna_gain_bg = 2;
 
 	/* Convert Antennagain values to Q5.2 */
-	bus->sprom.r1.antenna_gain_a <<= 2;
-	bus->sprom.r1.antenna_gain_bg <<= 2;
+	bus->sprom.antenna_gain_a <<= 2;
+	bus->sprom.antenna_gain_bg <<= 2;
 }
 
 static void b43_wireless_exit(struct ssb_device *dev, struct b43_wl *wl)
@@ -3905,10 +3905,10 @@ static int b43_wireless_init(struct ssb_
 	hw->max_noise = -110;
 	hw->queues = 1;		/* FIXME: hardware has more queues */
 	SET_IEEE80211_DEV(hw, dev->dev);
-	if (is_valid_ether_addr(sprom->r1.et1mac))
-		SET_IEEE80211_PERM_ADDR(hw, sprom->r1.et1mac);
+	if (is_valid_ether_addr(sprom->et1mac))
+		SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac);
 	else
-		SET_IEEE80211_PERM_ADDR(hw, sprom->r1.il0mac);
+		SET_IEEE80211_PERM_ADDR(hw, sprom->il0mac);
 
 	/* Get and initialize struct b43_wl */
 	wl = hw_to_b43_wl(hw);
Index: wireless-2.6/drivers/net/wireless/b43/phy.c
===================================================================
--- wireless-2.6.orig/drivers/net/wireless/b43/phy.c
+++ wireless-2.6/drivers/net/wireless/b43/phy.c
@@ -1139,7 +1139,7 @@ static void b43_phy_inita(struct b43_wld
 	} else {
 		b43_phy_setupg(dev);
 		if (phy->gmode &&
-		    (dev->dev->bus->sprom.r1.boardflags_lo & B43_BFL_PACTRL))
+		    (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL))
 			b43_phy_write(dev, 0x046E, 0x03CF);
 		return;
 	}
@@ -1286,7 +1286,7 @@ static void b43_phy_initb4(struct b43_wl
 	if (phy->radio_ver == 0x2050)
 		b43_phy_write(dev, 0x002A, 0x88C2);
 	b43_set_txpower_g(dev, &phy->bbatt, &phy->rfatt, phy->tx_control);
-	if (dev->dev->bus->sprom.r1.boardflags_lo & B43_BFL_RSSI) {
+	if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI) {
 		b43_calc_nrssi_slope(dev);
 		b43_calc_nrssi_threshold(dev);
 	}
@@ -1433,7 +1433,7 @@ static void b43_phy_initb6(struct b43_wl
 		b43_radio_write16(dev, 0x5A, 0x88);
 		b43_radio_write16(dev, 0x5B, 0x6B);
 		b43_radio_write16(dev, 0x5C, 0x0F);
-		if (dev->dev->bus->sprom.r1.boardflags_lo & B43_BFL_ALTIQ) {
+		if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_ALTIQ) {
 			b43_radio_write16(dev, 0x5D, 0xFA);
 			b43_radio_write16(dev, 0x5E, 0xD8);
 		} else {
@@ -1525,7 +1525,7 @@ static void b43_phy_initb6(struct b43_wl
 		b43_phy_write(dev, 0x0062, 0x0007);
 		b43_radio_init2050(dev);
 		b43_lo_g_measure(dev);
-		if (dev->dev->bus->sprom.r1.boardflags_lo & B43_BFL_RSSI) {
+		if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI) {
 			b43_calc_nrssi_slope(dev);
 			b43_calc_nrssi_threshold(dev);
 		}
@@ -1645,7 +1645,7 @@ static void b43_calc_loopback_gain(struc
 	b43_phy_write(dev, B43_PHY_RFOVERVAL,
 		      b43_phy_read(dev, B43_PHY_RFOVERVAL) & 0xCFFF);
 
-	if (dev->dev->bus->sprom.r1.boardflags_lo & B43_BFL_EXTLNA) {
+	if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_EXTLNA) {
 		if (phy->rev >= 7) {
 			b43_phy_write(dev, B43_PHY_RFOVER,
 				      b43_phy_read(dev, B43_PHY_RFOVER)
@@ -1812,7 +1812,7 @@ static void b43_phy_initg(struct b43_wld
 				       & 0x0FFF) | (phy->lo_control->
 						    tx_bias << 12));
 		}
-		if (dev->dev->bus->sprom.r1.boardflags_lo & B43_BFL_PACTRL)
+		if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)
 			b43_phy_write(dev, B43_PHY_BASE(0x2E), 0x8075);
 		else
 			b43_phy_write(dev, B43_PHY_BASE(0x2E), 0x807F);
@@ -1826,7 +1826,7 @@ static void b43_phy_initg(struct b43_wld
 		b43_phy_write(dev, B43_PHY_LO_MASK, 0x8078);
 	}
 
-	if (!(dev->dev->bus->sprom.r1.boardflags_lo & B43_BFL_RSSI)) {
+	if (!(dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) {
 		/* The specs state to update the NRSSI LT with
 		 * the value 0x7FFFFFFF here. I think that is some weird
 		 * compiler optimization in the original driver.
@@ -2036,16 +2036,15 @@ void b43_phy_xmitpower(struct b43_wldev 
 			estimated_pwr =
 			    b43_phy_estimate_power_out(dev, average);
 
-			max_pwr = dev->dev->bus->sprom.r1.maxpwr_bg;
-			if ((dev->dev->bus->sprom.r1.
-			     boardflags_lo & B43_BFL_PACTRL)
-			    && (phy->type == B43_PHYTYPE_G))
+			max_pwr = dev->dev->bus->sprom.maxpwr_bg;
+			if ((dev->dev->bus->sprom.boardflags_lo
+			    & B43_BFL_PACTRL) && (phy->type == B43_PHYTYPE_G))
 				max_pwr -= 0x3;
 			if (unlikely(max_pwr <= 0)) {
 				b43warn(dev->wl,
 					"Invalid max-TX-power value in SPROM.\n");
 				max_pwr = 60;	/* fake it */
-				dev->dev->bus->sprom.r1.maxpwr_bg = max_pwr;
+				dev->dev->bus->sprom.maxpwr_bg = max_pwr;
 			}
 
 			/*TODO:
@@ -2103,7 +2102,7 @@ void b43_phy_xmitpower(struct b43_wldev 
 						    B43_TXCTL_TXMIX;
 						rfatt += 2;
 						bbatt += 2;
-					} else if (dev->dev->bus->sprom.r1.
+					} else if (dev->dev->bus->sprom.
 						   boardflags_lo &
 						   B43_BFL_PACTRL) {
 						bbatt += 4 * (rfatt - 2);
@@ -2179,13 +2178,13 @@ int b43_phy_init_tssi2dbm_table(struct b
 	s8 *dyn_tssi2dbm;
 
 	if (phy->type == B43_PHYTYPE_A) {
-		pab0 = (s16) (dev->dev->bus->sprom.r1.pa1b0);
-		pab1 = (s16) (dev->dev->bus->sprom.r1.pa1b1);
-		pab2 = (s16) (dev->dev->bus->sprom.r1.pa1b2);
+		pab0 = (s16) (dev->dev->bus->sprom.pa1b0);
+		pab1 = (s16) (dev->dev->bus->sprom.pa1b1);
+		pab2 = (s16) (dev->dev->bus->sprom.pa1b2);
 	} else {
-		pab0 = (s16) (dev->dev->bus->sprom.r1.pa0b0);
-		pab1 = (s16) (dev->dev->bus->sprom.r1.pa0b1);
-		pab2 = (s16) (dev->dev->bus->sprom.r1.pa0b2);
+		pab0 = (s16) (dev->dev->bus->sprom.pa0b0);
+		pab1 = (s16) (dev->dev->bus->sprom.pa0b1);
+		pab2 = (s16) (dev->dev->bus->sprom.pa0b2);
 	}
 
 	if ((dev->dev->bus->chip_id == 0x4301) && (phy->radio_ver != 0x2050)) {
@@ -2198,17 +2197,17 @@ int b43_phy_init_tssi2dbm_table(struct b
 	    pab0 != -1 && pab1 != -1 && pab2 != -1) {
 		/* The pabX values are set in SPROM. Use them. */
 		if (phy->type == B43_PHYTYPE_A) {
-			if ((s8) dev->dev->bus->sprom.r1.itssi_a != 0 &&
-			    (s8) dev->dev->bus->sprom.r1.itssi_a != -1)
+			if ((s8) dev->dev->bus->sprom.itssi_a != 0 &&
+			    (s8) dev->dev->bus->sprom.itssi_a != -1)
 				phy->tgt_idle_tssi =
-				    (s8) (dev->dev->bus->sprom.r1.itssi_a);
+				    (s8) (dev->dev->bus->sprom.itssi_a);
 			else
 				phy->tgt_idle_tssi = 62;
 		} else {
-			if ((s8) dev->dev->bus->sprom.r1.itssi_bg != 0 &&
-			    (s8) dev->dev->bus->sprom.r1.itssi_bg != -1)
+			if ((s8) dev->dev->bus->sprom.itssi_bg != 0 &&
+			    (s8) dev->dev->bus->sprom.itssi_bg != -1)
 				phy->tgt_idle_tssi =
-				    (s8) (dev->dev->bus->sprom.r1.itssi_bg);
+				    (s8) (dev->dev->bus->sprom.itssi_bg);
 			else
 				phy->tgt_idle_tssi = 62;
 		}
@@ -3114,7 +3113,7 @@ void b43_calc_nrssi_threshold(struct b43
 			if (phy->radio_ver != 0x2050)
 				return;
 			if (!
-			    (dev->dev->bus->sprom.r1.
+			    (dev->dev->bus->sprom.
 			     boardflags_lo & B43_BFL_RSSI))
 				return;
 
@@ -3145,7 +3144,7 @@ void b43_calc_nrssi_threshold(struct b43
 		}
 	case B43_PHYTYPE_G:
 		if (!phy->gmode ||
-		    !(dev->dev->bus->sprom.r1.boardflags_lo & B43_BFL_RSSI)) {
+		    !(dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) {
 			tmp16 = b43_nrssi_hw_read(dev, 0x20);
 			if (tmp16 >= 0x20)
 				tmp16 -= 0x40;
@@ -3667,7 +3666,7 @@ static u16 radio2050_rfover_val(struct b
 		}
 
 		if ((phy->rev < 7) ||
-		    !(sprom->r1.boardflags_lo & B43_BFL_EXTLNA)) {
+		    !(sprom->boardflags_lo & B43_BFL_EXTLNA)) {
 			if (phy_register == B43_PHY_RFOVER) {
 				return 0x1B3;
 			} else if (phy_register == B43_PHY_RFOVERVAL) {
@@ -3707,7 +3706,7 @@ static u16 radio2050_rfover_val(struct b
 		}
 	} else {
 		if ((phy->rev < 7) ||
-		    !(sprom->r1.boardflags_lo & B43_BFL_EXTLNA)) {
+		    !(sprom->boardflags_lo & B43_BFL_EXTLNA)) {
 			if (phy_register == B43_PHY_RFOVER) {
 				return 0x1B3;
 			} else if (phy_register == B43_PHY_RFOVERVAL) {
@@ -4186,7 +4185,7 @@ int b43_radio_selectchannel(struct b43_w
 		b43_write16(dev, B43_MMIO_CHANNEL, channel2freq_bg(channel));
 
 		if (channel == 14) {
-			if (dev->dev->bus->sprom.r1.country_code ==
+			if (dev->dev->bus->sprom.country_code ==
 			    SSB_SPROM1CCODE_JAPAN)
 				b43_hf_write(dev,
 					     b43_hf_read(dev) & ~B43_HF_ACPR);
Index: wireless-2.6/drivers/net/wireless/b43/xmit.c
===================================================================
--- wireless-2.6.orig/drivers/net/wireless/b43/xmit.c
+++ wireless-2.6/drivers/net/wireless/b43/xmit.c
@@ -385,7 +385,7 @@ static s8 b43_rssi_postprocess(struct b4
 			else
 				tmp -= 3;
 		} else {
-			if (dev->dev->bus->sprom.r1.
+			if (dev->dev->bus->sprom.
 			    boardflags_lo & B43_BFL_RSSI) {
 				if (in_rssi > 63)
 					in_rssi = 63;

^ permalink raw reply

* Re: [PATCH] grub-probe -t prefix, -t all
From: Robert Millan @ 2007-11-09 22:56 UTC (permalink / raw)
  To: The development of GRUB 2
In-Reply-To: <4734D447.9030202@t-online.de>

On Fri, Nov 09, 2007 at 10:42:31PM +0100, Christian Franke wrote:
> Robert Millan wrote:
> >On Mon, Oct 29, 2007 at 09:20:00PM +0100, Christian Franke wrote:
> >  
> >>This patch adds '-t prefix', '-t all', and allows multiple -t options to 
> >>be specified.
> >>
> >>'-t prefix' was initially added to test grub_get_prefix() on Cygwin, but 
> >>may be useful in scripts.
> >>    
> >
> >What does -t prefix do?  Is it the same as
> >make_system_path_relative_to_its_root () ?  Sounds like I screwed up then 
> >:-/
> >
> >  
> 
> print_result_of_grub_get_grefix ()
> 
> or
> 
> make_path_relative_to_its_mount_point_and_then_absolute ()
> 
> or
> 
> please_tell_me_which_prefix_grub_setup_will_patch_into_kernel (:-)

Note that make_system_path_relative_to_its_root() actually exists :-/

If you provide an (obviously better) way to do the same thing, maybe you
could also get rid of the other one in your patch?

-- 
Robert Millan

<GPLv2> I know my rights; I want my phone call!
<DRM> What use is a phone call, if you are unable to speak?
(as seen on /.)



^ permalink raw reply

* [PATCH 2/ 6 V2] ssb: Convert to use of the new SPROM structure
From: Larry Finger @ 2007-11-09 22:56 UTC (permalink / raw)
  To: John Linville; +Cc: Michael Buesch, Bcm43xx-dev, linux-wireless

Patch 2 of 6:

In disagreement with the SPROM specs, revision 3 devices appear to have
moved the MAC address.

Change ssb to handle the revision 4 SPROM, which is a different size.
This change in size is handled by adding a new variable to the ssb_sprom
struct and using it whenever possible. For those routines that do not
have access to this structure, a 'u16 size' argument is added.

The new PCI_ID for the BCM4328 is also added.

Testing of the Revision 4 SPROM, which is used on the BCM4328, was done
by Michael Gerdau <mgerdau@tiscali.de>.

Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
---

Index: wireless-2.6/drivers/ssb/pci.c
===================================================================
--- wireless-2.6.orig/drivers/ssb/pci.c
+++ wireless-2.6/drivers/ssb/pci.c
@@ -212,29 +212,29 @@ static inline u8 ssb_crc8(u8 crc, u8 dat
 	return t[crc ^ data];
 }
 
-static u8 ssb_sprom_crc(const u16 *sprom)
+static u8 ssb_sprom_crc(const u16 *sprom, u16 size)
 {
 	int word;
 	u8 crc = 0xFF;
 
-	for (word = 0; word < SSB_SPROMSIZE_WORDS - 1; word++) {
+	for (word = 0; word < size - 1; word++) {
 		crc = ssb_crc8(crc, sprom[word] & 0x00FF);
 		crc = ssb_crc8(crc, (sprom[word] & 0xFF00) >> 8);
 	}
-	crc = ssb_crc8(crc, sprom[SPOFF(SSB_SPROM_REVISION)] & 0x00FF);
+	crc = ssb_crc8(crc, sprom[size - 1] & 0x00FF);
 	crc ^= 0xFF;
 
 	return crc;
 }
 
-static int sprom_check_crc(const u16 *sprom)
+static int sprom_check_crc(const u16 *sprom, u16 size)
 {
 	u8 crc;
 	u8 expected_crc;
 	u16 tmp;
 
-	crc = ssb_sprom_crc(sprom);
-	tmp = sprom[SPOFF(SSB_SPROM_REVISION)] & SSB_SPROM_REVISION_CRC;
+	crc = ssb_sprom_crc(sprom, size);
+	tmp = sprom[size - 1] & SSB_SPROM_REVISION_CRC;
 	expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT;
 	if (crc != expected_crc)
 		return -EPROTO;
@@ -246,7 +246,7 @@ static void sprom_do_read(struct ssb_bus
 {
 	int i;
 
-	for (i = 0; i < SSB_SPROMSIZE_WORDS; i++)
+	for (i = 0; i < bus->sprom_size; i++)
 		sprom[i] = readw(bus->mmio + SSB_SPROM_BASE + (i * 2));
 }
 
@@ -255,6 +255,7 @@ static int sprom_do_write(struct ssb_bus
 	struct pci_dev *pdev = bus->host_pci;
 	int i, err;
 	u32 spromctl;
+	u16 size = bus->sprom_size;
 
 	ssb_printk(KERN_NOTICE PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n");
 	err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
@@ -266,12 +267,12 @@ static int sprom_do_write(struct ssb_bus
 		goto err_ctlreg;
 	ssb_printk(KERN_NOTICE PFX "[ 0%%");
 	msleep(500);
-	for (i = 0; i < SSB_SPROMSIZE_WORDS; i++) {
-		if (i == SSB_SPROMSIZE_WORDS / 4)
+	for (i = 0; i < size; i++) {
+		if (i == size / 4)
 			ssb_printk("25%%");
-		else if (i == SSB_SPROMSIZE_WORDS / 2)
+		else if (i == size / 2)
 			ssb_printk("50%%");
-		else if (i == (SSB_SPROMSIZE_WORDS / 4) * 3)
+		else if (i == (size * 3) / 4)
 			ssb_printk("75%%");
 		else if (i % 2)
 			ssb_printk(".");
@@ -350,95 +351,120 @@ static void sprom_extract_r1(struct ssb_
 	SPEX(antenna_gain_a, SSB_SPROM1_AGAIN, SSB_SPROM1_AGAIN_A, 0);
 	SPEX(antenna_gain_bg, SSB_SPROM1_AGAIN, SSB_SPROM1_AGAIN_BG,
 	     SSB_SPROM1_AGAIN_BG_SHIFT);
-	for (i = 0; i < 4; i++) {
-		v = in[SPOFF(SSB_SPROM1_OEM) + i];
-		*(((__le16 *)out->oem) + i) = cpu_to_le16(v);
-	}
 }
 
-static void sprom_extract_r2(struct ssb_sprom_r2 *out, const u16 *in)
+static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
 {
 	int i;
 	u16 v;
+	u16 loc[3];
 
-	SPEX(boardflags_hi, SSB_SPROM2_BFLHI,  0xFFFF, 0);
-	SPEX(maxpwr_a_hi, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_HI, 0);
-	SPEX(maxpwr_a_lo, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_LO,
-	     SSB_SPROM2_MAXP_A_LO_SHIFT);
-	SPEX(pa1lob0, SSB_SPROM2_PA1LOB0, 0xFFFF, 0);
-	SPEX(pa1lob1, SSB_SPROM2_PA1LOB1, 0xFFFF, 0);
-	SPEX(pa1lob2, SSB_SPROM2_PA1LOB2, 0xFFFF, 0);
-	SPEX(pa1hib0, SSB_SPROM2_PA1HIB0, 0xFFFF, 0);
-	SPEX(pa1hib1, SSB_SPROM2_PA1HIB1, 0xFFFF, 0);
-	SPEX(pa1hib2, SSB_SPROM2_PA1HIB2, 0xFFFF, 0);
-	SPEX(ofdm_pwr_off, SSB_SPROM2_OPO, SSB_SPROM2_OPO_VALUE, 0);
-	for (i = 0; i < 4; i++) {
-		v = in[SPOFF(SSB_SPROM2_CCODE) + i];
-		*(((__le16 *)out->country_str) + i) = cpu_to_le16(v);
+	if (out->revision == 3) {			/* rev 3 moved MAC */
+		loc[0] = SSB_SPROM3_IL0MAC;
+		loc[1] = SSB_SPROM3_ET0MAC;
+		loc[2] = SSB_SPROM3_ET1MAC;
+	} else {
+		loc[0] = SSB_SPROM1_IL0MAC;
+		loc[1] = SSB_SPROM1_ET0MAC;
+		loc[2] = SSB_SPROM1_ET1MAC;
+	}
+	for (i = 0; i < 3; i++) {
+		v = in[SPOFF(loc[0]) + i];
+		*(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
+	}
+	for (i = 0; i < 3; i++) {
+		v = in[SPOFF(loc[1]) + i];
+		*(((__be16 *)out->et0mac) + i) = cpu_to_be16(v);
+	}
+	for (i = 0; i < 3; i++) {
+		v = in[SPOFF(loc[2]) + i];
+		*(((__be16 *)out->et1mac) + i) = cpu_to_be16(v);
 	}
+	SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0);
+	SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A,
+	     SSB_SPROM1_ETHPHY_ET1A_SHIFT);
+	SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
+	     SSB_SPROM1_BINF_CCODE_SHIFT);
+	SPEX(pa0b0, SSB_SPROM1_PA0B0, 0xFFFF, 0);
+	SPEX(pa0b1, SSB_SPROM1_PA0B1, 0xFFFF, 0);
+	SPEX(pa0b2, SSB_SPROM1_PA0B2, 0xFFFF, 0);
+	SPEX(pa1b0, SSB_SPROM1_PA1B0, 0xFFFF, 0);
+	SPEX(pa1b1, SSB_SPROM1_PA1B1, 0xFFFF, 0);
+	SPEX(pa1b2, SSB_SPROM1_PA1B2, 0xFFFF, 0);
+	SPEX(gpio0, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P0, 0);
+	SPEX(gpio1, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P1,
+	     SSB_SPROM1_GPIOA_P1_SHIFT);
+	SPEX(gpio2, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P2, 0);
+	SPEX(gpio3, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P3,
+	     SSB_SPROM1_GPIOB_P3_SHIFT);
+	SPEX(maxpwr_a, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_A,
+	     SSB_SPROM1_MAXPWR_A_SHIFT);
+	SPEX(maxpwr_bg, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_BG, 0);
+	SPEX(itssi_a, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_A,
+	     SSB_SPROM1_ITSSI_A_SHIFT);
+	SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0);
+	SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0);
+	SPEX(antenna_gain_a, SSB_SPROM1_AGAIN, SSB_SPROM1_AGAIN_A, 0);
+	SPEX(antenna_gain_bg, SSB_SPROM1_AGAIN, SSB_SPROM1_AGAIN_BG,
+	     SSB_SPROM1_AGAIN_BG_SHIFT);
 }
 
-static void sprom_extract_r3(struct ssb_sprom_r3 *out, const u16 *in)
-{
-	out->ofdmapo  = (in[SPOFF(SSB_SPROM3_OFDMAPO) + 0] & 0xFF00) >> 8;
-	out->ofdmapo |= (in[SPOFF(SSB_SPROM3_OFDMAPO) + 0] & 0x00FF) << 8;
-	out->ofdmapo <<= 16;
-	out->ofdmapo |= (in[SPOFF(SSB_SPROM3_OFDMAPO) + 1] & 0xFF00) >> 8;
-	out->ofdmapo |= (in[SPOFF(SSB_SPROM3_OFDMAPO) + 1] & 0x00FF) << 8;
-
-	out->ofdmalpo  = (in[SPOFF(SSB_SPROM3_OFDMALPO) + 0] & 0xFF00) >> 8;
-	out->ofdmalpo |= (in[SPOFF(SSB_SPROM3_OFDMALPO) + 0] & 0x00FF) << 8;
-	out->ofdmalpo <<= 16;
-	out->ofdmalpo |= (in[SPOFF(SSB_SPROM3_OFDMALPO) + 1] & 0xFF00) >> 8;
-	out->ofdmalpo |= (in[SPOFF(SSB_SPROM3_OFDMALPO) + 1] & 0x00FF) << 8;
-
-	out->ofdmahpo  = (in[SPOFF(SSB_SPROM3_OFDMAHPO) + 0] & 0xFF00) >> 8;
-	out->ofdmahpo |= (in[SPOFF(SSB_SPROM3_OFDMAHPO) + 0] & 0x00FF) << 8;
-	out->ofdmahpo <<= 16;
-	out->ofdmahpo |= (in[SPOFF(SSB_SPROM3_OFDMAHPO) + 1] & 0xFF00) >> 8;
-	out->ofdmahpo |= (in[SPOFF(SSB_SPROM3_OFDMAHPO) + 1] & 0x00FF) << 8;
-
-	SPEX(gpioldc_on_cnt, SSB_SPROM3_GPIOLDC, SSB_SPROM3_GPIOLDC_ON,
-	     SSB_SPROM3_GPIOLDC_ON_SHIFT);
-	SPEX(gpioldc_off_cnt, SSB_SPROM3_GPIOLDC, SSB_SPROM3_GPIOLDC_OFF,
-	     SSB_SPROM3_GPIOLDC_OFF_SHIFT);
-	SPEX(cckpo_1M, SSB_SPROM3_CCKPO, SSB_SPROM3_CCKPO_1M, 0);
-	SPEX(cckpo_2M, SSB_SPROM3_CCKPO, SSB_SPROM3_CCKPO_2M,
-	     SSB_SPROM3_CCKPO_2M_SHIFT);
-	SPEX(cckpo_55M, SSB_SPROM3_CCKPO, SSB_SPROM3_CCKPO_55M,
-	     SSB_SPROM3_CCKPO_55M_SHIFT);
-	SPEX(cckpo_11M, SSB_SPROM3_CCKPO, SSB_SPROM3_CCKPO_11M,
-	     SSB_SPROM3_CCKPO_11M_SHIFT);
-
-	out->ofdmgpo  = (in[SPOFF(SSB_SPROM3_OFDMGPO) + 0] & 0xFF00) >> 8;
-	out->ofdmgpo |= (in[SPOFF(SSB_SPROM3_OFDMGPO) + 0] & 0x00FF) << 8;
-	out->ofdmgpo <<= 16;
-	out->ofdmgpo |= (in[SPOFF(SSB_SPROM3_OFDMGPO) + 1] & 0xFF00) >> 8;
-	out->ofdmgpo |= (in[SPOFF(SSB_SPROM3_OFDMGPO) + 1] & 0x00FF) << 8;
+static void sprom_extract_r4(struct ssb_sprom *out, const u16 *in)
+{
+	int i;
+	u16 v;
+
+	/* extract the r1 variables */
+	for (i = 0; i < 3; i++) {
+		v = in[SPOFF(SSB_SPROM4_IL0MAC) + i];
+		*(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
+	}
+	for (i = 0; i < 3; i++) {
+		v = in[SPOFF(SSB_SPROM4_ET0MAC) + i];
+		*(((__be16 *)out->et0mac) + i) = cpu_to_be16(v);
+	}
+	for (i = 0; i < 3; i++) {
+		v = in[SPOFF(SSB_SPROM4_ET1MAC) + i];
+		*(((__be16 *)out->et1mac) + i) = cpu_to_be16(v);
+	}
+	SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0);
+	SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A,
+	     SSB_SPROM4_ETHPHY_ET1A_SHIFT);
+	SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0);
+	SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0);
+	SPEX(antenna_gain_a, SSB_SPROM4_AGAIN, SSB_SPROM4_AGAIN_0, 0);
+	SPEX(antenna_gain_bg, SSB_SPROM4_AGAIN, SSB_SPROM4_AGAIN_1,
+	     SSB_SPROM4_AGAIN_1_SHIFT);
+	/* TODO - get remaining rev 4 stuff needed */
 }
 
-static int sprom_extract(struct ssb_bus *bus,
-			 struct ssb_sprom *out, const u16 *in)
+static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
+			 const u16 *in, u16 size)
 {
 	memset(out, 0, sizeof(*out));
 
-	SPEX(revision, SSB_SPROM_REVISION, SSB_SPROM_REVISION_REV, 0);
-
+	out->revision = in[size - 1] & 0x00FF;
 	if ((bus->chip_id & 0xFF00) == 0x4400) {
 		/* Workaround: The BCM44XX chip has a stupid revision
 		 * number stored in the SPROM.
 		 * Always extract r1. */
+		out->revision = 1;
+		sprom_extract_r123(out, in);
 		sprom_extract_r1(&out->r1, in);
+	} else if (bus->chip_id == 0x4321) {
+		/* the BCM4328 has a chipid == 0x4321 and a rev 4 SPROM */
+		out->revision = 4;
+		sprom_extract_r4(out, in);
 	} else {
 		if (out->revision == 0)
 			goto unsupported;
-		if (out->revision >= 1 && out->revision <= 3)
+		if (out->revision >= 1 && out->revision <= 3) {
+			sprom_extract_r123(out, in, out->revision);
 			sprom_extract_r1(&out->r1, in);
-		if (out->revision >= 2 && out->revision <= 3)
-			sprom_extract_r2(&out->r2, in);
-		if (out->revision == 3)
-			sprom_extract_r3(&out->r3, in);
-		if (out->revision >= 4)
+		}
+		if (out->revision == 4)
+			sprom_extract_r4(out, in);
+		if (out->revision >= 5)
 			goto unsupported;
 	}
 
@@ -456,16 +482,31 @@ static int ssb_pci_sprom_get(struct ssb_
 	int err = -ENOMEM;
 	u16 *buf;
 
-	buf = kcalloc(SSB_SPROMSIZE_WORDS, sizeof(u16), GFP_KERNEL);
+	buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
 	if (!buf)
 		goto out;
+	bus->sprom_size = SSB_SPROMSIZE_WORDS_R123;
 	sprom_do_read(bus, buf);
-	err = sprom_check_crc(buf);
+	err = sprom_check_crc(buf, bus->sprom_size);
 	if (err) {
-		ssb_printk(KERN_WARNING PFX
-			   "WARNING: Invalid SPROM CRC (corrupt SPROM)\n");
+		/* check for rev 4 sprom - has special signature */
+		if (buf [32] == 0x5372) {
+			ssb_printk(KERN_WARNING PFX "Extracting a rev 4"
+				   " SPROM\n");
+			kfree(buf);
+			buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
+				      GFP_KERNEL);
+			if (!buf)
+				goto out;
+			bus->sprom_size = SSB_SPROMSIZE_WORDS_R4;
+			sprom_do_read(bus, buf);
+			err = sprom_check_crc(buf, bus->sprom_size);
+		}
+		if (err)
+			ssb_printk(KERN_WARNING PFX "WARNING: Invalid"
+				   " SPROM CRC (corrupt SPROM)\n");
 	}
-	err = sprom_extract(bus, sprom, buf);
+	err = sprom_extract(bus, sprom, buf, bus->sprom_size);
 
 	kfree(buf);
 out:
@@ -579,29 +620,28 @@ const struct ssb_bus_ops ssb_pci_ops = {
 	.write32	= ssb_pci_write32,
 };
 
-static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len)
+static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len, u16 size)
 {
 	int i, pos = 0;
 
-	for (i = 0; i < SSB_SPROMSIZE_WORDS; i++) {
+	for (i = 0; i < size; i++)
 		pos += snprintf(buf + pos, buf_len - pos - 1,
 				"%04X", swab16(sprom[i]) & 0xFFFF);
-	}
 	pos += snprintf(buf + pos, buf_len - pos - 1, "\n");
 
 	return pos + 1;
 }
 
-static int hex2sprom(u16 *sprom, const char *dump, size_t len)
+static int hex2sprom(u16 *sprom, const char *dump, size_t len, u16 size)
 {
 	char tmp[5] = { 0 };
 	int cnt = 0;
 	unsigned long parsed;
 
-	if (len < SSB_SPROMSIZE_BYTES * 2)
+	if (len < size * 2)
 		return -EINVAL;
 
-	while (cnt < SSB_SPROMSIZE_WORDS) {
+	while (cnt < size) {
 		memcpy(tmp, dump, 4);
 		dump += 4;
 		parsed = simple_strtoul(tmp, NULL, 16);
@@ -625,7 +665,7 @@ static ssize_t ssb_pci_attr_sprom_show(s
 	if (!bus)
 		goto out;
 	err = -ENOMEM;
-	sprom = kcalloc(SSB_SPROMSIZE_WORDS, sizeof(u16), GFP_KERNEL);
+	sprom = kcalloc(bus->sprom_size, sizeof(u16), GFP_KERNEL);
 	if (!sprom)
 		goto out;
 
@@ -638,7 +678,7 @@ static ssize_t ssb_pci_attr_sprom_show(s
 	sprom_do_read(bus, sprom);
 	mutex_unlock(&bus->pci_sprom_mutex);
 
-	count = sprom2hex(sprom, buf, PAGE_SIZE);
+	count = sprom2hex(sprom, buf, PAGE_SIZE, bus->sprom_size);
 	err = 0;
 
 out_kfree:
@@ -660,15 +700,15 @@ static ssize_t ssb_pci_attr_sprom_store(
 	if (!bus)
 		goto out;
 	err = -ENOMEM;
-	sprom = kcalloc(SSB_SPROMSIZE_WORDS, sizeof(u16), GFP_KERNEL);
+	sprom = kcalloc(bus->sprom_size, sizeof(u16), GFP_KERNEL);
 	if (!sprom)
 		goto out;
-	err = hex2sprom(sprom, buf, count);
+	err = hex2sprom(sprom, buf, count, bus->sprom_size);
 	if (err) {
 		err = -EINVAL;
 		goto out_kfree;
 	}
-	err = sprom_check_crc(sprom);
+	err = sprom_check_crc(sprom, bus->sprom_size);
 	if (err) {
 		err = -EINVAL;
 		goto out_kfree;
Index: wireless-2.6/drivers/ssb/main.c
===================================================================
--- wireless-2.6.orig/drivers/ssb/main.c
+++ wireless-2.6/drivers/ssb/main.c
@@ -872,14 +872,22 @@ EXPORT_SYMBOL(ssb_clockspeed);
 
 static u32 ssb_tmslow_reject_bitmask(struct ssb_device *dev)
 {
+	u32 rev = ssb_read32(dev, SSB_IDLOW) & SSB_IDLOW_SSBREV;
+
 	/* The REJECT bit changed position in TMSLOW between
 	 * Backplane revisions. */
-	switch (ssb_read32(dev, SSB_IDLOW) & SSB_IDLOW_SSBREV) {
+	switch (rev) {
 	case SSB_IDLOW_SSBREV_22:
 		return SSB_TMSLOW_REJECT_22;
 	case SSB_IDLOW_SSBREV_23:
 		return SSB_TMSLOW_REJECT_23;
+	case SSB_IDLOW_SSBREV_24:     /* TODO - find the proper REJECT bits */
+	case SSB_IDLOW_SSBREV_25:     /* same here */
+	case SSB_IDLOW_SSBREV_26:     /* same here */
+	case SSB_IDLOW_SSBREV_27:     /* same here */
+		return SSB_TMSLOW_REJECT_23;	/* this is a guess */
 	default:
+		printk(KERN_INFO "ssb: Backplane Revision 0x%.8X\n", rev);
 		WARN_ON(1);
 	}
 	return (SSB_TMSLOW_REJECT_22 | SSB_TMSLOW_REJECT_23);
Index: wireless-2.6/include/linux/ssb/ssb.h
===================================================================
--- wireless-2.6.orig/include/linux/ssb/ssb.h
+++ wireless-2.6/include/linux/ssb/ssb.h
@@ -308,6 +308,7 @@ struct ssb_bus {
 	/* ID information about the Chip. */
 	u16 chip_id;
 	u16 chip_rev;
+	u16 sprom_size;		/* number of words in sprom */
 	u8 chip_package;
 
 	/* List of devices (cores) on the backplane. */
Index: wireless-2.6/include/linux/ssb/ssb_regs.h
===================================================================
--- wireless-2.6.orig/include/linux/ssb/ssb_regs.h
+++ wireless-2.6/include/linux/ssb/ssb_regs.h
@@ -147,6 +147,10 @@
 #define  SSB_IDLOW_SSBREV	0xF0000000 /* Sonics Backplane Revision code */
 #define  SSB_IDLOW_SSBREV_22	0x00000000 /* <= 2.2 */
 #define  SSB_IDLOW_SSBREV_23	0x10000000 /* 2.3 */
+#define  SSB_IDLOW_SSBREV_24	0x40000000 /* ?? Found in BCM4328 */
+#define  SSB_IDLOW_SSBREV_25	0x50000000 /* ?? Not Found yet */
+#define  SSB_IDLOW_SSBREV_26	0x60000000 /* ?? Found in some BCM4311/2 */
+#define  SSB_IDLOW_SSBREV_27	0x70000000 /* ?? Found in some BCM4311/2 */
 #define SSB_IDHIGH		0x0FFC     /* SB Identification High */
 #define  SSB_IDHIGH_RCLO	0x0000000F /* Revision Code (low part) */
 #define  SSB_IDHIGH_CC		0x00008FF0 /* Core Code */
@@ -162,6 +166,10 @@
  */
 #define SSB_SPROMSIZE_WORDS		64
 #define SSB_SPROMSIZE_BYTES		(SSB_SPROMSIZE_WORDS * sizeof(u16))
+#define SSB_SPROMSIZE_WORDS_R123	64
+#define SSB_SPROMSIZE_WORDS_R4		220
+#define SSB_SPROMSIZE_BYTES_R123	(SSB_SPROMSIZE_WORDS_R123 * sizeof(u16))
+#define SSB_SPROMSIZE_BYTES_R4		(SSB_SPROMSIZE_WORDS_R4 * sizeof(u16))
 #define SSB_SPROM_BASE			0x1000
 #define SSB_SPROM_REVISION		0x107E
 #define  SSB_SPROM_REVISION_REV		0x00FF	/* SPROM Revision number */
@@ -232,7 +240,10 @@
 #define  SSB_SPROM2_OPO_VALUE		0x00FF
 #define  SSB_SPROM2_OPO_UNUSED		0xFF00
 #define SSB_SPROM2_CCODE		0x107C	/* Two char Country Code */
-/* SPROM Revision 3 (inherits from rev 2) */
+/* SPROM Revision 3 (inherits most data from rev 2) */
+#define SSB_SPROM3_IL0MAC		0x104A	/* 6 bytes MAC address for 802.11b/g */
+#define SSB_SPROM3_ET0MAC		0x1050	/* 6 bytes MAC address for Ethernet ?? */
+#define SSB_SPROM3_ET1MAC		0x1050	/* 6 bytes MAC address for 802.11a ?? */
 #define SSB_SPROM3_OFDMAPO		0x102C	/* A-PHY OFDM Mid Power Offset (4 bytes, BigEndian) */
 #define SSB_SPROM3_OFDMALPO		0x1030	/* A-PHY OFDM Low Power Offset (4 bytes, BigEndian) */
 #define SSB_SPROM3_OFDMAHPO		0x1034	/* A-PHY OFDM High Power Offset (4 bytes, BigEndian) */
@@ -250,8 +261,10 @@
 #define  SSB_SPROM3_CCKPO_11M		0xF000	/* 11M Rate PO */
 #define  SSB_SPROM3_CCKPO_11M_SHIFT	12
 #define  SSB_SPROM3_OFDMGPO		0x107A	/* G-PHY OFDM Power Offset (4 bytes, BigEndian) */
-/* SPROM Revision 4 */
+/* SPROM Revision 4 		entries with ?? in comment are unknown */
 #define SSB_SPROM4_IL0MAC		0x104C	/* 6 byte MAC address for b/g */
+#define SSB_SPROM4_ET0MAC		0x1018	/* 6 bytes MAC address for Ethernet ?? */
+#define SSB_SPROM4_ET1MAC		0x1018	/* 6 bytes MAC address for 802.11a ?? */
 #define SSB_SPROM4_ETHPHY		0x105A	/* Ethernet PHY settings */
 #define  SSB_SPROM4_ETHPHY_ET0A		0x001F	/* MII Address for enet0 */
 #define  SSB_SPROM4_ETHPHY_ET1A		0x03E0	/* MII Address for enet1 */
@@ -263,19 +276,22 @@
 #define SSB_SPROM4_ANT_BG		0x105C  /* B/G Antennas */
 #define SSB_SPROM4_BFLLO		0x1044	/* Boardflags (low 16 bits) */
 #define SSB_SPROM4_AGAIN		0x105E	/* Antenna Gain (in dBm Q5.2) */
+#define  SSB_SPROM4_AGAIN_0		0x00FF	/* Antenna 0 */
+#define  SSB_SPROM4_AGAIN_1		0xFF00	/* Antenna 1 */
+#define  SSB_SPROM4_AGAIN_1_SHIFT	8
 #define SSB_SPROM4_BFLHI		0x1046  /* Board Flags Hi */
-#define SSB_SPROM4_MAXP_A		0x1000  /* Max Power A */
+#define SSB_SPROM4_MAXP_A		0x1000  /* Max Power A ?? */
 #define SSB_SPROM4_MAXP_A_HI		0x00FF  /* Mask for Hi */
 #define SSB_SPROM4_MAXP_A_LO		0xFF00  /* Mask for Lo */
 #define SSB_SPROM4_MAXP_A_LO_SHIFT	16	/* Shift for Lo */
-#define SSB_SPROM4_PA1LOB0		0x1000
-#define SSB_SPROM4_PA1LOB1		0x1000
-#define SSB_SPROM4_PA1LOB2		0x1000
-#define SSB_SPROM4_PA1HIB0		0x1000
-#define SSB_SPROM4_PA1HIB1		0x1000
-#define SSB_SPROM4_PA1HIB2		0x1000
-#define SSB_SPROM4_OPO			0x1000
-#define SSB_SPROM4_OPO_VALUE		0x0000
+#define SSB_SPROM4_PA1LOB0		0x1000  /* ?? */
+#define SSB_SPROM4_PA1LOB1		0x1000  /* ?? */
+#define SSB_SPROM4_PA1LOB2		0x1000  /* ?? */
+#define SSB_SPROM4_PA1HIB0		0x1000	/* ?? */
+#define SSB_SPROM4_PA1HIB1		0x1000	/* ?? */
+#define SSB_SPROM4_PA1HIB2		0x1000	/* ?? */
+#define SSB_SPROM4_OPO			0x1000	/* ?? */
+#define SSB_SPROM4_OPO_VALUE		0x0000	/* ?? */
 #define SSB_SPROM4_GPIOLDC		0x105A	/* LED Powersave Duty Cycle */
 #define  SSB_SPROM4_GPIOLDC_OFF		0x0000FF00	/* Off Count */
 #define  SSB_SPROM4_GPIOLDC_OFF_SHIFT	8
Index: wireless-2.6/drivers/ssb/b43_pci_bridge.c
===================================================================
--- wireless-2.6.orig/drivers/ssb/b43_pci_bridge.c
+++ wireless-2.6/drivers/ssb/b43_pci_bridge.c
@@ -27,6 +27,7 @@ static const struct pci_device_id b43_pc
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4321) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4324) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4325) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4328) },
 	{ 0, },
 };
 MODULE_DEVICE_TABLE(pci, b43_pci_bridge_tbl);

^ permalink raw reply

* [PATCH 3/6] b44: Convert to use of the new SPROM structure
From: Larry Finger @ 2007-11-09 22:56 UTC (permalink / raw)
  To: John Linville; +Cc: Michael Buesch, Bcm43xx-dev, linux-wireless

Patch 3 of 6.

The b44 driver is changed to use the new SPROM data structure.

Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
---

Index: wireless-2.6/drivers/net/b44.c
===================================================================
--- wireless-2.6.orig/drivers/net/b44.c
+++ wireless-2.6/drivers/net/b44.c
@@ -2060,11 +2060,11 @@ static int __devinit b44_get_invariants(
 
 	if (sdev->bus->bustype == SSB_BUSTYPE_SSB &&
 	    instance > 1) {
-		addr = sdev->bus->sprom.r1.et1mac;
-		bp->phy_addr = sdev->bus->sprom.r1.et1phyaddr;
+		addr = sdev->bus->sprom.et1mac;
+		bp->phy_addr = sdev->bus->sprom.et1phyaddr;
 	} else {
-		addr = sdev->bus->sprom.r1.et0mac;
-		bp->phy_addr = sdev->bus->sprom.r1.et0phyaddr;
+		addr = sdev->bus->sprom.et0mac;
+		bp->phy_addr = sdev->bus->sprom.et0phyaddr;
 	}
 	memcpy(bp->dev->dev_addr, addr, 6);
 

^ permalink raw reply

* Re: oops in oprofile/dump_trace/X86 with 2.6.24-rcX
From: Robert Fitzsimons @ 2007-11-09 22:55 UTC (permalink / raw)
  To: Jan Blunck
  Cc: Robert Fitzsimons, linux-kernel, Andi Kleen, Ingo Molnar,
	Thomas Gleixner, akpm
In-Reply-To: <20071109213010.GJ18693@hasse.suse.de>

> this only happens 32bit. Somehow I broke this when I introduced
> stack_pointer(). Here is a patch that fixes the problem.
> 
> Subject: oprofile: Fix oops on x86 32-bit

I've tested this and it fixes the oops.

Thank you.

Robert


^ permalink raw reply

* [PATCH 1/ 6] ssb: Convert to use of the new SPROM structure
From: Larry Finger @ 2007-11-09 22:55 UTC (permalink / raw)
  To: John Linville; +Cc: Michael Buesch, Bcm43xx-dev, linux-wireless

Patch 2 of 6:

In disagreement with the SPROM specs, revision 3 devices appear to have
moved the MAC address.

Change ssb to handle the revision 4 SPROM, which is a different size.
This change in size is handled by adding a new variable to the ssb_sprom
struct and using it whenever possible. For those routines that do not
have access to this structure, a 'u16 size' argument is added.

The new PCI_ID for the BCM4328 is also added.

Testing of the Revision 4 SPROM, which is used on the BCM4328, was done
by Michael Gerdau <mgerdau@tiscali.de>.

Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
---

Index: wireless-2.6/drivers/ssb/pci.c
===================================================================
--- wireless-2.6.orig/drivers/ssb/pci.c
+++ wireless-2.6/drivers/ssb/pci.c
@@ -212,29 +212,29 @@ static inline u8 ssb_crc8(u8 crc, u8 dat
 	return t[crc ^ data];
 }
 
-static u8 ssb_sprom_crc(const u16 *sprom)
+static u8 ssb_sprom_crc(const u16 *sprom, u16 size)
 {
 	int word;
 	u8 crc = 0xFF;
 
-	for (word = 0; word < SSB_SPROMSIZE_WORDS - 1; word++) {
+	for (word = 0; word < size - 1; word++) {
 		crc = ssb_crc8(crc, sprom[word] & 0x00FF);
 		crc = ssb_crc8(crc, (sprom[word] & 0xFF00) >> 8);
 	}
-	crc = ssb_crc8(crc, sprom[SPOFF(SSB_SPROM_REVISION)] & 0x00FF);
+	crc = ssb_crc8(crc, sprom[size - 1] & 0x00FF);
 	crc ^= 0xFF;
 
 	return crc;
 }
 
-static int sprom_check_crc(const u16 *sprom)
+static int sprom_check_crc(const u16 *sprom, u16 size)
 {
 	u8 crc;
 	u8 expected_crc;
 	u16 tmp;
 
-	crc = ssb_sprom_crc(sprom);
-	tmp = sprom[SPOFF(SSB_SPROM_REVISION)] & SSB_SPROM_REVISION_CRC;
+	crc = ssb_sprom_crc(sprom, size);
+	tmp = sprom[size - 1] & SSB_SPROM_REVISION_CRC;
 	expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT;
 	if (crc != expected_crc)
 		return -EPROTO;
@@ -246,7 +246,7 @@ static void sprom_do_read(struct ssb_bus
 {
 	int i;
 
-	for (i = 0; i < SSB_SPROMSIZE_WORDS; i++)
+	for (i = 0; i < bus->sprom_size; i++)
 		sprom[i] = readw(bus->mmio + SSB_SPROM_BASE + (i * 2));
 }
 
@@ -255,6 +255,7 @@ static int sprom_do_write(struct ssb_bus
 	struct pci_dev *pdev = bus->host_pci;
 	int i, err;
 	u32 spromctl;
+	u16 size = bus->sprom_size;
 
 	ssb_printk(KERN_NOTICE PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n");
 	err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
@@ -266,12 +267,12 @@ static int sprom_do_write(struct ssb_bus
 		goto err_ctlreg;
 	ssb_printk(KERN_NOTICE PFX "[ 0%%");
 	msleep(500);
-	for (i = 0; i < SSB_SPROMSIZE_WORDS; i++) {
-		if (i == SSB_SPROMSIZE_WORDS / 4)
+	for (i = 0; i < size; i++) {
+		if (i == size / 4)
 			ssb_printk("25%%");
-		else if (i == SSB_SPROMSIZE_WORDS / 2)
+		else if (i == size / 2)
 			ssb_printk("50%%");
-		else if (i == (SSB_SPROMSIZE_WORDS / 4) * 3)
+		else if (i == (size * 3) / 4)
 			ssb_printk("75%%");
 		else if (i % 2)
 			ssb_printk(".");
@@ -350,95 +351,120 @@ static void sprom_extract_r1(struct ssb_
 	SPEX(antenna_gain_a, SSB_SPROM1_AGAIN, SSB_SPROM1_AGAIN_A, 0);
 	SPEX(antenna_gain_bg, SSB_SPROM1_AGAIN, SSB_SPROM1_AGAIN_BG,
 	     SSB_SPROM1_AGAIN_BG_SHIFT);
-	for (i = 0; i < 4; i++) {
-		v = in[SPOFF(SSB_SPROM1_OEM) + i];
-		*(((__le16 *)out->oem) + i) = cpu_to_le16(v);
-	}
 }
 
-static void sprom_extract_r2(struct ssb_sprom_r2 *out, const u16 *in)
+static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
 {
 	int i;
 	u16 v;
+	u16 loc[3];
 
-	SPEX(boardflags_hi, SSB_SPROM2_BFLHI,  0xFFFF, 0);
-	SPEX(maxpwr_a_hi, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_HI, 0);
-	SPEX(maxpwr_a_lo, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_LO,
-	     SSB_SPROM2_MAXP_A_LO_SHIFT);
-	SPEX(pa1lob0, SSB_SPROM2_PA1LOB0, 0xFFFF, 0);
-	SPEX(pa1lob1, SSB_SPROM2_PA1LOB1, 0xFFFF, 0);
-	SPEX(pa1lob2, SSB_SPROM2_PA1LOB2, 0xFFFF, 0);
-	SPEX(pa1hib0, SSB_SPROM2_PA1HIB0, 0xFFFF, 0);
-	SPEX(pa1hib1, SSB_SPROM2_PA1HIB1, 0xFFFF, 0);
-	SPEX(pa1hib2, SSB_SPROM2_PA1HIB2, 0xFFFF, 0);
-	SPEX(ofdm_pwr_off, SSB_SPROM2_OPO, SSB_SPROM2_OPO_VALUE, 0);
-	for (i = 0; i < 4; i++) {
-		v = in[SPOFF(SSB_SPROM2_CCODE) + i];
-		*(((__le16 *)out->country_str) + i) = cpu_to_le16(v);
+	if (out->revision == 3) {			/* rev 3 moved MAC */
+		loc[0] = SSB_SPROM3_IL0MAC;
+		loc[1] = SSB_SPROM3_ET0MAC;
+		loc[2] = SSB_SPROM3_ET1MAC;
+	} else {
+		loc[0] = SSB_SPROM1_IL0MAC;
+		loc[1] = SSB_SPROM1_ET0MAC;
+		loc[2] = SSB_SPROM1_ET1MAC;
+	}
+	for (i = 0; i < 3; i++) {
+		v = in[SPOFF(loc[0]) + i];
+		*(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
+	}
+	for (i = 0; i < 3; i++) {
+		v = in[SPOFF(loc[1]) + i];
+		*(((__be16 *)out->et0mac) + i) = cpu_to_be16(v);
+	}
+	for (i = 0; i < 3; i++) {
+		v = in[SPOFF(loc[2]) + i];
+		*(((__be16 *)out->et1mac) + i) = cpu_to_be16(v);
 	}
+	SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0);
+	SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A,
+	     SSB_SPROM1_ETHPHY_ET1A_SHIFT);
+	SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
+	     SSB_SPROM1_BINF_CCODE_SHIFT);
+	SPEX(pa0b0, SSB_SPROM1_PA0B0, 0xFFFF, 0);
+	SPEX(pa0b1, SSB_SPROM1_PA0B1, 0xFFFF, 0);
+	SPEX(pa0b2, SSB_SPROM1_PA0B2, 0xFFFF, 0);
+	SPEX(pa1b0, SSB_SPROM1_PA1B0, 0xFFFF, 0);
+	SPEX(pa1b1, SSB_SPROM1_PA1B1, 0xFFFF, 0);
+	SPEX(pa1b2, SSB_SPROM1_PA1B2, 0xFFFF, 0);
+	SPEX(gpio0, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P0, 0);
+	SPEX(gpio1, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P1,
+	     SSB_SPROM1_GPIOA_P1_SHIFT);
+	SPEX(gpio2, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P2, 0);
+	SPEX(gpio3, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P3,
+	     SSB_SPROM1_GPIOB_P3_SHIFT);
+	SPEX(maxpwr_a, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_A,
+	     SSB_SPROM1_MAXPWR_A_SHIFT);
+	SPEX(maxpwr_bg, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_BG, 0);
+	SPEX(itssi_a, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_A,
+	     SSB_SPROM1_ITSSI_A_SHIFT);
+	SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0);
+	SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0);
+	SPEX(antenna_gain_a, SSB_SPROM1_AGAIN, SSB_SPROM1_AGAIN_A, 0);
+	SPEX(antenna_gain_bg, SSB_SPROM1_AGAIN, SSB_SPROM1_AGAIN_BG,
+	     SSB_SPROM1_AGAIN_BG_SHIFT);
 }
 
-static void sprom_extract_r3(struct ssb_sprom_r3 *out, const u16 *in)
-{
-	out->ofdmapo  = (in[SPOFF(SSB_SPROM3_OFDMAPO) + 0] & 0xFF00) >> 8;
-	out->ofdmapo |= (in[SPOFF(SSB_SPROM3_OFDMAPO) + 0] & 0x00FF) << 8;
-	out->ofdmapo <<= 16;
-	out->ofdmapo |= (in[SPOFF(SSB_SPROM3_OFDMAPO) + 1] & 0xFF00) >> 8;
-	out->ofdmapo |= (in[SPOFF(SSB_SPROM3_OFDMAPO) + 1] & 0x00FF) << 8;
-
-	out->ofdmalpo  = (in[SPOFF(SSB_SPROM3_OFDMALPO) + 0] & 0xFF00) >> 8;
-	out->ofdmalpo |= (in[SPOFF(SSB_SPROM3_OFDMALPO) + 0] & 0x00FF) << 8;
-	out->ofdmalpo <<= 16;
-	out->ofdmalpo |= (in[SPOFF(SSB_SPROM3_OFDMALPO) + 1] & 0xFF00) >> 8;
-	out->ofdmalpo |= (in[SPOFF(SSB_SPROM3_OFDMALPO) + 1] & 0x00FF) << 8;
-
-	out->ofdmahpo  = (in[SPOFF(SSB_SPROM3_OFDMAHPO) + 0] & 0xFF00) >> 8;
-	out->ofdmahpo |= (in[SPOFF(SSB_SPROM3_OFDMAHPO) + 0] & 0x00FF) << 8;
-	out->ofdmahpo <<= 16;
-	out->ofdmahpo |= (in[SPOFF(SSB_SPROM3_OFDMAHPO) + 1] & 0xFF00) >> 8;
-	out->ofdmahpo |= (in[SPOFF(SSB_SPROM3_OFDMAHPO) + 1] & 0x00FF) << 8;
-
-	SPEX(gpioldc_on_cnt, SSB_SPROM3_GPIOLDC, SSB_SPROM3_GPIOLDC_ON,
-	     SSB_SPROM3_GPIOLDC_ON_SHIFT);
-	SPEX(gpioldc_off_cnt, SSB_SPROM3_GPIOLDC, SSB_SPROM3_GPIOLDC_OFF,
-	     SSB_SPROM3_GPIOLDC_OFF_SHIFT);
-	SPEX(cckpo_1M, SSB_SPROM3_CCKPO, SSB_SPROM3_CCKPO_1M, 0);
-	SPEX(cckpo_2M, SSB_SPROM3_CCKPO, SSB_SPROM3_CCKPO_2M,
-	     SSB_SPROM3_CCKPO_2M_SHIFT);
-	SPEX(cckpo_55M, SSB_SPROM3_CCKPO, SSB_SPROM3_CCKPO_55M,
-	     SSB_SPROM3_CCKPO_55M_SHIFT);
-	SPEX(cckpo_11M, SSB_SPROM3_CCKPO, SSB_SPROM3_CCKPO_11M,
-	     SSB_SPROM3_CCKPO_11M_SHIFT);
-
-	out->ofdmgpo  = (in[SPOFF(SSB_SPROM3_OFDMGPO) + 0] & 0xFF00) >> 8;
-	out->ofdmgpo |= (in[SPOFF(SSB_SPROM3_OFDMGPO) + 0] & 0x00FF) << 8;
-	out->ofdmgpo <<= 16;
-	out->ofdmgpo |= (in[SPOFF(SSB_SPROM3_OFDMGPO) + 1] & 0xFF00) >> 8;
-	out->ofdmgpo |= (in[SPOFF(SSB_SPROM3_OFDMGPO) + 1] & 0x00FF) << 8;
+static void sprom_extract_r4(struct ssb_sprom *out, const u16 *in)
+{
+	int i;
+	u16 v;
+
+	/* extract the r1 variables */
+	for (i = 0; i < 3; i++) {
+		v = in[SPOFF(SSB_SPROM4_IL0MAC) + i];
+		*(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
+	}
+	for (i = 0; i < 3; i++) {
+		v = in[SPOFF(SSB_SPROM4_ET0MAC) + i];
+		*(((__be16 *)out->et0mac) + i) = cpu_to_be16(v);
+	}
+	for (i = 0; i < 3; i++) {
+		v = in[SPOFF(SSB_SPROM4_ET1MAC) + i];
+		*(((__be16 *)out->et1mac) + i) = cpu_to_be16(v);
+	}
+	SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0);
+	SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A,
+	     SSB_SPROM4_ETHPHY_ET1A_SHIFT);
+	SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0);
+	SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0);
+	SPEX(antenna_gain_a, SSB_SPROM4_AGAIN, SSB_SPROM4_AGAIN_0, 0);
+	SPEX(antenna_gain_bg, SSB_SPROM4_AGAIN, SSB_SPROM4_AGAIN_1,
+	     SSB_SPROM4_AGAIN_1_SHIFT);
+	/* TODO - get remaining rev 4 stuff needed */
 }
 
-static int sprom_extract(struct ssb_bus *bus,
-			 struct ssb_sprom *out, const u16 *in)
+static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
+			 const u16 *in, u16 size)
 {
 	memset(out, 0, sizeof(*out));
 
-	SPEX(revision, SSB_SPROM_REVISION, SSB_SPROM_REVISION_REV, 0);
-
+	out->revision = in[size - 1] & 0x00FF;
 	if ((bus->chip_id & 0xFF00) == 0x4400) {
 		/* Workaround: The BCM44XX chip has a stupid revision
 		 * number stored in the SPROM.
 		 * Always extract r1. */
+		out->revision = 1;
+		sprom_extract_r123(out, in);
 		sprom_extract_r1(&out->r1, in);
+	} else if (bus->chip_id == 0x4321) {
+		/* the BCM4328 has a chipid == 0x4321 and a rev 4 SPROM */
+		out->revision = 4;
+		sprom_extract_r4(out, in);
 	} else {
 		if (out->revision == 0)
 			goto unsupported;
-		if (out->revision >= 1 && out->revision <= 3)
+		if (out->revision >= 1 && out->revision <= 3) {
+			sprom_extract_r123(out, in, out->revision);
 			sprom_extract_r1(&out->r1, in);
-		if (out->revision >= 2 && out->revision <= 3)
-			sprom_extract_r2(&out->r2, in);
-		if (out->revision == 3)
-			sprom_extract_r3(&out->r3, in);
-		if (out->revision >= 4)
+		}
+		if (out->revision == 4)
+			sprom_extract_r4(out, in);
+		if (out->revision >= 5)
 			goto unsupported;
 	}
 
@@ -456,16 +482,31 @@ static int ssb_pci_sprom_get(struct ssb_
 	int err = -ENOMEM;
 	u16 *buf;
 
-	buf = kcalloc(SSB_SPROMSIZE_WORDS, sizeof(u16), GFP_KERNEL);
+	buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
 	if (!buf)
 		goto out;
+	bus->sprom_size = SSB_SPROMSIZE_WORDS_R123;
 	sprom_do_read(bus, buf);
-	err = sprom_check_crc(buf);
+	err = sprom_check_crc(buf, bus->sprom_size);
 	if (err) {
-		ssb_printk(KERN_WARNING PFX
-			   "WARNING: Invalid SPROM CRC (corrupt SPROM)\n");
+		/* check for rev 4 sprom - has special signature */
+		if (buf [32] == 0x5372) {
+			ssb_printk(KERN_WARNING PFX "Extracting a rev 4"
+				   " SPROM\n");
+			kfree(buf);
+			buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
+				      GFP_KERNEL);
+			if (!buf)
+				goto out;
+			bus->sprom_size = SSB_SPROMSIZE_WORDS_R4;
+			sprom_do_read(bus, buf);
+			err = sprom_check_crc(buf, bus->sprom_size);
+		}
+		if (err)
+			ssb_printk(KERN_WARNING PFX "WARNING: Invalid"
+				   " SPROM CRC (corrupt SPROM)\n");
 	}
-	err = sprom_extract(bus, sprom, buf);
+	err = sprom_extract(bus, sprom, buf, bus->sprom_size);
 
 	kfree(buf);
 out:
@@ -579,29 +620,28 @@ const struct ssb_bus_ops ssb_pci_ops = {
 	.write32	= ssb_pci_write32,
 };
 
-static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len)
+static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len, u16 size)
 {
 	int i, pos = 0;
 
-	for (i = 0; i < SSB_SPROMSIZE_WORDS; i++) {
+	for (i = 0; i < size; i++)
 		pos += snprintf(buf + pos, buf_len - pos - 1,
 				"%04X", swab16(sprom[i]) & 0xFFFF);
-	}
 	pos += snprintf(buf + pos, buf_len - pos - 1, "\n");
 
 	return pos + 1;
 }
 
-static int hex2sprom(u16 *sprom, const char *dump, size_t len)
+static int hex2sprom(u16 *sprom, const char *dump, size_t len, u16 size)
 {
 	char tmp[5] = { 0 };
 	int cnt = 0;
 	unsigned long parsed;
 
-	if (len < SSB_SPROMSIZE_BYTES * 2)
+	if (len < size * 2)
 		return -EINVAL;
 
-	while (cnt < SSB_SPROMSIZE_WORDS) {
+	while (cnt < size) {
 		memcpy(tmp, dump, 4);
 		dump += 4;
 		parsed = simple_strtoul(tmp, NULL, 16);
@@ -625,7 +665,7 @@ static ssize_t ssb_pci_attr_sprom_show(s
 	if (!bus)
 		goto out;
 	err = -ENOMEM;
-	sprom = kcalloc(SSB_SPROMSIZE_WORDS, sizeof(u16), GFP_KERNEL);
+	sprom = kcalloc(bus->sprom_size, sizeof(u16), GFP_KERNEL);
 	if (!sprom)
 		goto out;
 
@@ -638,7 +678,7 @@ static ssize_t ssb_pci_attr_sprom_show(s
 	sprom_do_read(bus, sprom);
 	mutex_unlock(&bus->pci_sprom_mutex);
 
-	count = sprom2hex(sprom, buf, PAGE_SIZE);
+	count = sprom2hex(sprom, buf, PAGE_SIZE, bus->sprom_size);
 	err = 0;
 
 out_kfree:
@@ -660,15 +700,15 @@ static ssize_t ssb_pci_attr_sprom_store(
 	if (!bus)
 		goto out;
 	err = -ENOMEM;
-	sprom = kcalloc(SSB_SPROMSIZE_WORDS, sizeof(u16), GFP_KERNEL);
+	sprom = kcalloc(bus->sprom_size, sizeof(u16), GFP_KERNEL);
 	if (!sprom)
 		goto out;
-	err = hex2sprom(sprom, buf, count);
+	err = hex2sprom(sprom, buf, count, bus->sprom_size);
 	if (err) {
 		err = -EINVAL;
 		goto out_kfree;
 	}
-	err = sprom_check_crc(sprom);
+	err = sprom_check_crc(sprom, bus->sprom_size);
 	if (err) {
 		err = -EINVAL;
 		goto out_kfree;
Index: wireless-2.6/drivers/ssb/main.c
===================================================================
--- wireless-2.6.orig/drivers/ssb/main.c
+++ wireless-2.6/drivers/ssb/main.c
@@ -872,14 +872,22 @@ EXPORT_SYMBOL(ssb_clockspeed);
 
 static u32 ssb_tmslow_reject_bitmask(struct ssb_device *dev)
 {
+	u32 rev = ssb_read32(dev, SSB_IDLOW) & SSB_IDLOW_SSBREV;
+
 	/* The REJECT bit changed position in TMSLOW between
 	 * Backplane revisions. */
-	switch (ssb_read32(dev, SSB_IDLOW) & SSB_IDLOW_SSBREV) {
+	switch (rev) {
 	case SSB_IDLOW_SSBREV_22:
 		return SSB_TMSLOW_REJECT_22;
 	case SSB_IDLOW_SSBREV_23:
 		return SSB_TMSLOW_REJECT_23;
+	case SSB_IDLOW_SSBREV_24:     /* TODO - find the proper REJECT bits */
+	case SSB_IDLOW_SSBREV_25:     /* same here */
+	case SSB_IDLOW_SSBREV_26:     /* same here */
+	case SSB_IDLOW_SSBREV_27:     /* same here */
+		return SSB_TMSLOW_REJECT_23;	/* this is a guess */
 	default:
+		printk(KERN_INFO "ssb: Backplane Revision 0x%.8X\n", rev);
 		WARN_ON(1);
 	}
 	return (SSB_TMSLOW_REJECT_22 | SSB_TMSLOW_REJECT_23);
Index: wireless-2.6/include/linux/ssb/ssb.h
===================================================================
--- wireless-2.6.orig/include/linux/ssb/ssb.h
+++ wireless-2.6/include/linux/ssb/ssb.h
@@ -308,6 +308,7 @@ struct ssb_bus {
 	/* ID information about the Chip. */
 	u16 chip_id;
 	u16 chip_rev;
+	u16 sprom_size;		/* number of words in sprom */
 	u8 chip_package;
 
 	/* List of devices (cores) on the backplane. */
Index: wireless-2.6/include/linux/ssb/ssb_regs.h
===================================================================
--- wireless-2.6.orig/include/linux/ssb/ssb_regs.h
+++ wireless-2.6/include/linux/ssb/ssb_regs.h
@@ -147,6 +147,10 @@
 #define  SSB_IDLOW_SSBREV	0xF0000000 /* Sonics Backplane Revision code */
 #define  SSB_IDLOW_SSBREV_22	0x00000000 /* <= 2.2 */
 #define  SSB_IDLOW_SSBREV_23	0x10000000 /* 2.3 */
+#define  SSB_IDLOW_SSBREV_24	0x40000000 /* ?? Found in BCM4328 */
+#define  SSB_IDLOW_SSBREV_25	0x50000000 /* ?? Not Found yet */
+#define  SSB_IDLOW_SSBREV_26	0x60000000 /* ?? Found in some BCM4311/2 */
+#define  SSB_IDLOW_SSBREV_27	0x70000000 /* ?? Found in some BCM4311/2 */
 #define SSB_IDHIGH		0x0FFC     /* SB Identification High */
 #define  SSB_IDHIGH_RCLO	0x0000000F /* Revision Code (low part) */
 #define  SSB_IDHIGH_CC		0x00008FF0 /* Core Code */
@@ -162,6 +166,10 @@
  */
 #define SSB_SPROMSIZE_WORDS		64
 #define SSB_SPROMSIZE_BYTES		(SSB_SPROMSIZE_WORDS * sizeof(u16))
+#define SSB_SPROMSIZE_WORDS_R123	64
+#define SSB_SPROMSIZE_WORDS_R4		220
+#define SSB_SPROMSIZE_BYTES_R123	(SSB_SPROMSIZE_WORDS_R123 * sizeof(u16))
+#define SSB_SPROMSIZE_BYTES_R4		(SSB_SPROMSIZE_WORDS_R4 * sizeof(u16))
 #define SSB_SPROM_BASE			0x1000
 #define SSB_SPROM_REVISION		0x107E
 #define  SSB_SPROM_REVISION_REV		0x00FF	/* SPROM Revision number */
@@ -232,7 +240,10 @@
 #define  SSB_SPROM2_OPO_VALUE		0x00FF
 #define  SSB_SPROM2_OPO_UNUSED		0xFF00
 #define SSB_SPROM2_CCODE		0x107C	/* Two char Country Code */
-/* SPROM Revision 3 (inherits from rev 2) */
+/* SPROM Revision 3 (inherits most data from rev 2) */
+#define SSB_SPROM3_IL0MAC		0x104A	/* 6 bytes MAC address for 802.11b/g */
+#define SSB_SPROM3_ET0MAC		0x1050	/* 6 bytes MAC address for Ethernet ?? */
+#define SSB_SPROM3_ET1MAC		0x1050	/* 6 bytes MAC address for 802.11a ?? */
 #define SSB_SPROM3_OFDMAPO		0x102C	/* A-PHY OFDM Mid Power Offset (4 bytes, BigEndian) */
 #define SSB_SPROM3_OFDMALPO		0x1030	/* A-PHY OFDM Low Power Offset (4 bytes, BigEndian) */
 #define SSB_SPROM3_OFDMAHPO		0x1034	/* A-PHY OFDM High Power Offset (4 bytes, BigEndian) */
@@ -250,8 +261,10 @@
 #define  SSB_SPROM3_CCKPO_11M		0xF000	/* 11M Rate PO */
 #define  SSB_SPROM3_CCKPO_11M_SHIFT	12
 #define  SSB_SPROM3_OFDMGPO		0x107A	/* G-PHY OFDM Power Offset (4 bytes, BigEndian) */
-/* SPROM Revision 4 */
+/* SPROM Revision 4 		entries with ?? in comment are unknown */
 #define SSB_SPROM4_IL0MAC		0x104C	/* 6 byte MAC address for b/g */
+#define SSB_SPROM4_ET0MAC		0x1018	/* 6 bytes MAC address for Ethernet ?? */
+#define SSB_SPROM4_ET1MAC		0x1018	/* 6 bytes MAC address for 802.11a ?? */
 #define SSB_SPROM4_ETHPHY		0x105A	/* Ethernet PHY settings */
 #define  SSB_SPROM4_ETHPHY_ET0A		0x001F	/* MII Address for enet0 */
 #define  SSB_SPROM4_ETHPHY_ET1A		0x03E0	/* MII Address for enet1 */
@@ -263,19 +276,22 @@
 #define SSB_SPROM4_ANT_BG		0x105C  /* B/G Antennas */
 #define SSB_SPROM4_BFLLO		0x1044	/* Boardflags (low 16 bits) */
 #define SSB_SPROM4_AGAIN		0x105E	/* Antenna Gain (in dBm Q5.2) */
+#define  SSB_SPROM4_AGAIN_0		0x00FF	/* Antenna 0 */
+#define  SSB_SPROM4_AGAIN_1		0xFF00	/* Antenna 1 */
+#define  SSB_SPROM4_AGAIN_1_SHIFT	8
 #define SSB_SPROM4_BFLHI		0x1046  /* Board Flags Hi */
-#define SSB_SPROM4_MAXP_A		0x1000  /* Max Power A */
+#define SSB_SPROM4_MAXP_A		0x1000  /* Max Power A ?? */
 #define SSB_SPROM4_MAXP_A_HI		0x00FF  /* Mask for Hi */
 #define SSB_SPROM4_MAXP_A_LO		0xFF00  /* Mask for Lo */
 #define SSB_SPROM4_MAXP_A_LO_SHIFT	16	/* Shift for Lo */
-#define SSB_SPROM4_PA1LOB0		0x1000
-#define SSB_SPROM4_PA1LOB1		0x1000
-#define SSB_SPROM4_PA1LOB2		0x1000
-#define SSB_SPROM4_PA1HIB0		0x1000
-#define SSB_SPROM4_PA1HIB1		0x1000
-#define SSB_SPROM4_PA1HIB2		0x1000
-#define SSB_SPROM4_OPO			0x1000
-#define SSB_SPROM4_OPO_VALUE		0x0000
+#define SSB_SPROM4_PA1LOB0		0x1000  /* ?? */
+#define SSB_SPROM4_PA1LOB1		0x1000  /* ?? */
+#define SSB_SPROM4_PA1LOB2		0x1000  /* ?? */
+#define SSB_SPROM4_PA1HIB0		0x1000	/* ?? */
+#define SSB_SPROM4_PA1HIB1		0x1000	/* ?? */
+#define SSB_SPROM4_PA1HIB2		0x1000	/* ?? */
+#define SSB_SPROM4_OPO			0x1000	/* ?? */
+#define SSB_SPROM4_OPO_VALUE		0x0000	/* ?? */
 #define SSB_SPROM4_GPIOLDC		0x105A	/* LED Powersave Duty Cycle */
 #define  SSB_SPROM4_GPIOLDC_OFF		0x0000FF00	/* Off Count */
 #define  SSB_SPROM4_GPIOLDC_OFF_SHIFT	8
Index: wireless-2.6/drivers/ssb/b43_pci_bridge.c
===================================================================
--- wireless-2.6.orig/drivers/ssb/b43_pci_bridge.c
+++ wireless-2.6/drivers/ssb/b43_pci_bridge.c
@@ -27,6 +27,7 @@ static const struct pci_device_id b43_pc
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4321) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4324) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4325) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4328) },
 	{ 0, },
 };
 MODULE_DEVICE_TABLE(pci, b43_pci_bridge_tbl);

^ permalink raw reply

* [PATCH 1/ 6] ssb: Add new SPROM structure while keeping the old
From: Larry Finger @ 2007-11-09 22:54 UTC (permalink / raw)
  To: John Linville; +Cc: Michael Buesch, Bcm43xx-dev, linux-wireless

This is patch 1 of 6.

The SPROM's for various devices utilizing the Sonics Silicon Backplane come
with various revisions. The Revision 2 SPROM inherited the data layout of 1, and
Revision 3 inherited the layout of 2. The first instance of Revision 4 has
now been found in a BCM4328 wireless LAN card. This device does not inherit any
layout from previous versions. Although it was possible to create a data
structure that kept all the old layouts, we decided to start fresh, keep only
those SPROM variables that are used by the drivers that utilize ssb, and to
do the conversion in such a manner that neither compilation or execution will
be affected if a bisection lands in the middle of these changes, while keeping
the patches as small as possible.

In this patch, the sprom structures are changed while maintaining the old ones.

Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
---

Index: wireless-2.6/include/linux/ssb/ssb.h
===================================================================
--- wireless-2.6.orig/include/linux/ssb/ssb.h
+++ wireless-2.6/include/linux/ssb/ssb.h
@@ -78,13 +78,34 @@ struct ssb_sprom_r3 {
 	u32 ofdmgpo;		/* G-PHY OFDM Power Offset */
 };
 
-struct ssb_sprom_r4 {
-	/* TODO */
-};
-
 struct ssb_sprom {
 	u8 revision;
-	u8 crc;
+	u8 temp_fill[2 * sizeof(struct ssb_sprom_r1)];
+	u8 il0mac[6];		/* MAC address for 802.11b/g */
+	u8 et0mac[6];		/* MAC address for Ethernet */
+	u8 et1mac[6];		/* MAC address for 802.11a */
+	u8 et0phyaddr;		/* MII address for enet0 */
+	u8 et1phyaddr;		/* MII address for enet1 */
+	u8 country_code;	/* Country Code */
+	u16 pa0b0;
+	u16 pa0b1;
+	u16 pa0b2;
+	u16 pa1b0;
+	u16 pa1b1;
+	u16 pa1b2;
+	u8 gpio0;		/* GPIO pin 0 */
+	u8 gpio1;		/* GPIO pin 1 */
+	u8 gpio2;		/* GPIO pin 2 */
+	u8 gpio3;		/* GPIO pin 3 */
+	u16 maxpwr_a;		/* A-PHY Amplifier Max Power (in dBm Q5.2) */
+	u16 maxpwr_bg;		/* B/G-PHY Amplifier Max Power (in dBm Q5.2) */
+	u8 itssi_a;		/* Idle TSSI Target for A-PHY */
+	u8 itssi_bg;		/* Idle TSSI Target for B/G-PHY */
+	u16 boardflags_lo;	/* Boardflags (low 16 bits) */
+	u8 antenna_gain_a;	/* A-PHY Antenna gain (in dBm Q5.2) */
+	u8 antenna_gain_bg;	/* B/G-PHY Antenna gain (in dBm Q5.2) */
+
+	/* TODO - add any parameters needed from rev 2, 3, or 4 SPROMs */
 	/* The valid r# fields are selected by the "revision".
 	 * Revision 3 and lower inherit from lower revisions.
 	 */
@@ -94,7 +115,6 @@ struct ssb_sprom {
 			struct ssb_sprom_r2 r2;
 			struct ssb_sprom_r3 r3;
 		};
-		struct ssb_sprom_r4 r4;
 	};
 };
 
Index: wireless-2.6/include/linux/ssb/ssb_regs.h
===================================================================
--- wireless-2.6.orig/include/linux/ssb/ssb_regs.h
+++ wireless-2.6/include/linux/ssb/ssb_regs.h
@@ -250,6 +250,38 @@
 #define  SSB_SPROM3_CCKPO_11M		0xF000	/* 11M Rate PO */
 #define  SSB_SPROM3_CCKPO_11M_SHIFT	12
 #define  SSB_SPROM3_OFDMGPO		0x107A	/* G-PHY OFDM Power Offset (4 bytes, BigEndian) */
+/* SPROM Revision 4 */
+#define SSB_SPROM4_IL0MAC		0x104C	/* 6 byte MAC address for b/g */
+#define SSB_SPROM4_ETHPHY		0x105A	/* Ethernet PHY settings */
+#define  SSB_SPROM4_ETHPHY_ET0A		0x001F	/* MII Address for enet0 */
+#define  SSB_SPROM4_ETHPHY_ET1A		0x03E0	/* MII Address for enet1 */
+#define  SSB_SPROM4_ETHPHY_ET1A_SHIFT	5
+#define  SSB_SPROM4_ETHPHY_ET0M		(1<<14)	/* MDIO for enet0 */
+#define  SSB_SPROM4_ETHPHY_ET1M		(1<<15)	/* MDIO for enet1 */
+#define SSB_SPROM4_CCODE		0x1052	/* Country Code (2 bytes) */
+#define SSB_SPROM4_ANT_A		0x105D  /* A Antennas */
+#define SSB_SPROM4_ANT_BG		0x105C  /* B/G Antennas */
+#define SSB_SPROM4_BFLLO		0x1044	/* Boardflags (low 16 bits) */
+#define SSB_SPROM4_AGAIN		0x105E	/* Antenna Gain (in dBm Q5.2) */
+#define SSB_SPROM4_BFLHI		0x1046  /* Board Flags Hi */
+#define SSB_SPROM4_MAXP_A		0x1000  /* Max Power A */
+#define SSB_SPROM4_MAXP_A_HI		0x00FF  /* Mask for Hi */
+#define SSB_SPROM4_MAXP_A_LO		0xFF00  /* Mask for Lo */
+#define SSB_SPROM4_MAXP_A_LO_SHIFT	16	/* Shift for Lo */
+#define SSB_SPROM4_PA1LOB0		0x1000
+#define SSB_SPROM4_PA1LOB1		0x1000
+#define SSB_SPROM4_PA1LOB2		0x1000
+#define SSB_SPROM4_PA1HIB0		0x1000
+#define SSB_SPROM4_PA1HIB1		0x1000
+#define SSB_SPROM4_PA1HIB2		0x1000
+#define SSB_SPROM4_OPO			0x1000
+#define SSB_SPROM4_OPO_VALUE		0x0000
+#define SSB_SPROM4_GPIOLDC		0x105A	/* LED Powersave Duty Cycle */
+#define  SSB_SPROM4_GPIOLDC_OFF		0x0000FF00	/* Off Count */
+#define  SSB_SPROM4_GPIOLDC_OFF_SHIFT	8
+#define  SSB_SPROM4_GPIOLDC_ON		0x00FF0000	/* On Count */
+#define  SSB_SPROM4_GPIOLDC_ON_SHIFT	16
+
 
 /* Values for SSB_SPROM1_BINF_CCODE */
 enum {
Index: wireless-2.6/drivers/ssb/pci.c
===================================================================
--- wireless-2.6.orig/drivers/ssb/pci.c
+++ wireless-2.6/drivers/ssb/pci.c
@@ -423,8 +423,6 @@ static int sprom_extract(struct ssb_bus 
 	memset(out, 0, sizeof(*out));
 
 	SPEX(revision, SSB_SPROM_REVISION, SSB_SPROM_REVISION_REV, 0);
-	SPEX(crc, SSB_SPROM_REVISION, SSB_SPROM_REVISION_CRC,
-	     SSB_SPROM_REVISION_CRC_SHIFT);
 
 	if ((bus->chip_id & 0xFF00) == 0x4400) {
 		/* Workaround: The BCM44XX chip has a stupid revision

^ permalink raw reply

* [PATCH 0/6] ssb and friends: Change layout and naming of SPROM data
From: Larry Finger @ 2007-11-09 22:53 UTC (permalink / raw)
  To: John Linville; +Cc: wireless, Broadcom Linux, Michael Buesch

In the various Broadcom devices that are supported, several revisions of the SPROM have been
encountered. Current code takes advantage of the fact that Revision 2 inherits all the data of
1, and that Revision 3 inherits most data from 2. This scheme breaks down with revision 4, which
does not inherit from the earlier models. In addition, the current code has an error for Rev. 3
SPROMS. In deciding how best to implement the new design, a fresh approach is warranted.
Furthermore, we decided not to include any SPROM variables not used in the supported drivers (b44,
b43 and b43legacy). To keep the patches small while preserving compilation and correct execution
during bisection, the change has been split into the following pieces:

1. Introduce new structure while maintaining the old.
2. Convert the ssb module to the new structure.
3. Convert the b44 driver.
4. Convert b43.
5. convert b43legacy.
6. Remove the old structures from ssb.

Larry



^ permalink raw reply

* Re: underruns and strange code in pcm_rate.c
From: Stas Sergeev @ 2007-11-09 22:52 UTC (permalink / raw)
  To: Lee Revell; +Cc: alsa-devel, Timur Tabi
In-Reply-To: <75b66ecd0711091337m374f8b13ne4fae13818841502@mail.gmail.com>

Hello.

Lee Revell wrote:
>> Ok, now I'm confused.  Isn't this whole thread is about underrun problems with
>> OSS?
> Yes.
Any evidence of this?

^ permalink raw reply

* Re: [PATCH] Fix eisa_mmap evaluation, add memory existence check
From: Robert Millan @ 2007-11-09 22:51 UTC (permalink / raw)
  To: The development of GRUB 2
In-Reply-To: <4734D6D3.9020307@t-online.de>

On Fri, Nov 09, 2007 at 10:53:23PM +0100, Christian Franke wrote:
> >Ah, and why 0xcf instead of 0xff ?
> >
> >  
> 
> ... or 0xaa or 0x55.

0xaa and 0x55 are typicaly used directly in memory because every bit is
negated, which is precisely what `^ 0xff' would do.

-- 
Robert Millan

<GPLv2> I know my rights; I want my phone call!
<DRM> What use is a phone call, if you are unable to speak?
(as seen on /.)



^ permalink raw reply

* Re: kernel BUG message while using jffs2
From: David Woodhouse @ 2007-11-09 22:39 UTC (permalink / raw)
  To: Alexandru Damian; +Cc: linux-kernel
In-Reply-To: <f881070f0711090708u1b77a78dlcdb504a724b22fcf@mail.gmail.com>


On Fri, 2007-11-09 at 17:08 +0200, Alexandru Damian wrote:
> Hello,
> 
> Sorry for posting here, it seems the best spot; if I need to redirect
> this to mtd-utils team, please tell me.
> 
> I'm playing around with some jffs2 files. While trying to mount (via
> block2mtd, loop) a jffs2 system, a "kernel BUG message" appeared in
> dmesg, with these lines:
> 
> kernel BUG at mm/slub.c:2204!

I don't see a BUG() or BUG_ON() anywhere near that line. What version of
the kernel? Precisely what is at that line?

-- 
dwmw2


^ permalink raw reply

* Re: [PATCH 2/6] MTD: Add support for the SST 39VF1601 flash chip [try #5]
From: David Woodhouse @ 2007-11-09 22:34 UTC (permalink / raw)
  To: David Howells; +Cc: torvalds, akpm, linux-kernel, linux-am33-list
In-Reply-To: <20071109153442.20803.51684.stgit@warthog.procyon.org.uk>


On Fri, 2007-11-09 at 15:34 +0000, David Howells wrote:
> Add support for the SST 39VF1601 flash chip.
> 
> Signed-off-by: David Howells <dhowells@redhat.com>

Applied.

-- 
dwmw2


^ permalink raw reply

* [PATCH] b43: Output message at startup if hardware switch for radio is off
From: Larry Finger @ 2007-11-09 22:47 UTC (permalink / raw)
  To: John Linville, Michael Buesch; +Cc: Bcm43xx-dev, linux-wireless

Now that the radio is controlled by rfkill, there is a potential
difficulty in helping a new user get started, as it is unlikely
that they will have setup rfkill. This patch prints a message if
the interface is started with the hardware switch off.

Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
---

John,

This patch is intended for the everything branch of wireless-2.6.

Larry

 main.c   |   10 +++++++---
 main.h   |    2 ++
 rfkill.c |    2 +-
 3 files changed, 10 insertions(+), 4 deletions(-)

Index: wireless-2.6/drivers/net/wireless/b43/main.c
===================================================================
--- wireless-2.6.orig/drivers/net/wireless/b43/main.c
+++ wireless-2.6/drivers/net/wireless/b43/main.c
@@ -3181,11 +3181,15 @@ static void setup_struct_phy_for_init(st
 
 static void setup_struct_wldev_for_init(struct b43_wldev *dev)
 {
+	struct b43_wl *wl = dev->wl;
+
 	/* Flags */
 	dev->reg124_set_0x4 = 0;
-	/* Assume the radio is enabled. If it's not enabled, the state will
-	 * immediately get fixed on the first periodic work run. */
-	dev->radio_hw_enable = 1;
+	dev->radio_hw_enable = b43_is_hw_radio_enabled(dev);
+	if (!dev->radio_hw_enable)
+		b43info(wl, "***** The hardware switch for your radio switch"
+			" is off.\n          ***** Until it is switched on,"
+			" your device will not work.\n");
 
 	/* Stats */
 	memset(&dev->stats, 0, sizeof(dev->stats));
Index: wireless-2.6/drivers/net/wireless/b43/main.h
===================================================================
--- wireless-2.6.orig/drivers/net/wireless/b43/main.h
+++ wireless-2.6/drivers/net/wireless/b43/main.h
@@ -116,6 +116,8 @@ void b43_mac_enable(struct b43_wldev *de
 
 void b43_controller_restart(struct b43_wldev *dev, const char *reason);
 
+bool b43_is_hw_radio_enabled(struct b43_wldev *dev);
+
 #define B43_PS_ENABLED	(1 << 0)	/* Force enable hardware power saving */
 #define B43_PS_DISABLED	(1 << 1)	/* Force disable hardware power saving */
 #define B43_PS_AWAKE	(1 << 2)	/* Force device awake */
Index: wireless-2.6/drivers/net/wireless/b43/rfkill.c
===================================================================
--- wireless-2.6.orig/drivers/net/wireless/b43/rfkill.c
+++ wireless-2.6/drivers/net/wireless/b43/rfkill.c
@@ -27,7 +27,7 @@
 
 
 /* Returns TRUE, if the radio is enabled in hardware. */
-static bool b43_is_hw_radio_enabled(struct b43_wldev *dev)
+bool b43_is_hw_radio_enabled(struct b43_wldev *dev)
 {
 	if (dev->phy.rev >= 3) {
 		if (!(b43_read32(dev, B43_MMIO_RADIO_HWENABLED_HI)

^ permalink raw reply

* + add-64-bit-capability-support-to-the-kernel.patch added to -mm tree
From: akpm @ 2007-11-09 22:45 UTC (permalink / raw)
  To: mm-commits; +Cc: morgan, casey, chrisw, jmorris, sds, serue


The patch titled
     Add 64-bit capability support to the kernel
has been added to the -mm tree.  Its filename is
     add-64-bit-capability-support-to-the-kernel.patch

*** Remember to use Documentation/SubmitChecklist when testing your code ***

See http://www.zip.com.au/~akpm/linux/patches/stuff/added-to-mm.txt to find
out what to do about this

------------------------------------------------------
Subject: Add 64-bit capability support to the kernel
From: Andrew Morgan <morgan@kernel.org>

The patch supports legacy (32-bit) capability userspace, and where possible
translates 32-bit capabilities to/from userspace and the VFS to 64-bit
kernel space capabilities.  If a capability set cannot be compressed into
32-bits for consumption by user space, the system call fails, with -ERANGE.

FWIW libcap-2.00 supports this change (and earlier capability formats)

 http://www.kernel.org/pub/linux/libs/security/linux-privs/kernel-2.6/

Signed-off-by: Andrew G. Morgan <morgan@kernel.org>
Cc: Stephen Smalley <sds@tycho.nsa.gov>
Cc: Serge Hallyn <serue@us.ibm.com>
Cc: Chris Wright <chrisw@sous-sol.org>
Cc: James Morris <jmorris@namei.org>
Cc: Casey Schaufler <casey@schaufler-ca.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---

 fs/nfsd/auth.c             |   10 -
 fs/proc/array.c            |   21 ++-
 include/linux/capability.h |  220 ++++++++++++++++++++++++-----------
 kernel/capability.c        |   89 ++++++++++++--
 mm/oom_kill.c              |    5 
 security/commoncap.c       |   93 ++++++++++----
 security/dummy.c           |   17 +-
 7 files changed, 331 insertions(+), 124 deletions(-)

diff -puN fs/nfsd/auth.c~add-64-bit-capability-support-to-the-kernel fs/nfsd/auth.c
--- a/fs/nfsd/auth.c~add-64-bit-capability-support-to-the-kernel
+++ a/fs/nfsd/auth.c
@@ -11,8 +11,6 @@
 #include <linux/nfsd/nfsd.h>
 #include <linux/nfsd/export.h>
 
-#define	CAP_NFSD_MASK (CAP_FS_MASK|CAP_TO_MASK(CAP_SYS_RESOURCE))
-
 int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp)
 {
 	struct exp_flavor_info *f;
@@ -69,10 +67,12 @@ int nfsd_setuser(struct svc_rqst *rqstp,
 	ret = set_current_groups(cred.cr_group_info);
 	put_group_info(cred.cr_group_info);
 	if ((cred.cr_uid)) {
-		cap_t(current->cap_effective) &= ~CAP_NFSD_MASK;
+		current->cap_effective =
+			cap_drop_nfsd_set(current->cap_effective);
 	} else {
-		cap_t(current->cap_effective) |= (CAP_NFSD_MASK &
-						  current->cap_permitted);
+		current->cap_effective =
+			cap_raise_nfsd_set(current->cap_effective,
+					   current->cap_permitted);
 	}
 	return ret;
 }
diff -puN fs/proc/array.c~add-64-bit-capability-support-to-the-kernel fs/proc/array.c
--- a/fs/proc/array.c~add-64-bit-capability-support-to-the-kernel
+++ a/fs/proc/array.c
@@ -286,14 +286,23 @@ static inline char *task_sig(struct task
 	return buffer;
 }
 
+static char *render_cap_t(const char *header, kernel_cap_t *a, char *buffer)
+{
+	unsigned __capi;
+
+	buffer += sprintf(buffer, "%s", header);
+	CAP_FOR_EACH_U32(__capi) {
+		buffer += sprintf(buffer, "%08x",
+				  a->cap[(_LINUX_CAPABILITY_U32S-1) -__capi]);
+	}
+	return buffer + sprintf(buffer, "\n");
+}
+
 static inline char *task_cap(struct task_struct *p, char *buffer)
 {
-    return buffer + sprintf(buffer, "CapInh:\t%016x\n"
-			    "CapPrm:\t%016x\n"
-			    "CapEff:\t%016x\n",
-			    cap_t(p->cap_inheritable),
-			    cap_t(p->cap_permitted),
-			    cap_t(p->cap_effective));
+	buffer = render_cap_t("CapInh:\t", &p->cap_inheritable, buffer);
+	buffer = render_cap_t("CapPrm:\t", &p->cap_permitted, buffer);
+	return render_cap_t("CapEff:\t", &p->cap_effective, buffer);
 }
 
 static inline char *task_context_switch_counts(struct task_struct *p,
diff -puN include/linux/capability.h~add-64-bit-capability-support-to-the-kernel include/linux/capability.h
--- a/include/linux/capability.h~add-64-bit-capability-support-to-the-kernel
+++ a/include/linux/capability.h
@@ -23,13 +23,20 @@ struct task_struct;
    kernel might be somewhat backwards compatible, but don't bet on
    it. */
 
-/* XXX - Note, cap_t, is defined by POSIX to be an "opaque" pointer to
+/* Note, cap_t, is defined by POSIX (draft) to be an "opaque" pointer to
    a set of three capability sets.  The transposition of 3*the
    following structure to such a composite is better handled in a user
    library since the draft standard requires the use of malloc/free
    etc.. */
 
-#define _LINUX_CAPABILITY_VERSION  0x19980330
+#define _LINUX_CAPABILITY_VERSION_1  0x19980330
+#define _LINUX_CAPABILITY_U32S_1     1
+
+#define _LINUX_CAPABILITY_VERSION_2  0x20071026
+#define _LINUX_CAPABILITY_U32S_2     2
+
+#define _LINUX_CAPABILITY_VERSION    _LINUX_CAPABILITY_VERSION_2
+#define _LINUX_CAPABILITY_U32S       _LINUX_CAPABILITY_U32S_2
 
 typedef struct __user_cap_header_struct {
 	__u32 version;
@@ -42,43 +49,42 @@ typedef struct __user_cap_data_struct {
         __u32 inheritable;
 } __user *cap_user_data_t;
 
+
 #define XATTR_CAPS_SUFFIX "capability"
 #define XATTR_NAME_CAPS XATTR_SECURITY_PREFIX XATTR_CAPS_SUFFIX
 
-#define XATTR_CAPS_SZ (3*sizeof(__le32))
 #define VFS_CAP_REVISION_MASK	0xFF000000
+#define VFS_CAP_FLAGS_MASK	~VFS_CAP_REVISION_MASK
+#define VFS_CAP_FLAGS_EFFECTIVE	0x000001
+
 #define VFS_CAP_REVISION_1	0x01000000
+#define VFS_CAP_U32_1           1
+#define XATTR_CAPS_SZ_1         (sizeof(__le32)*(1 + 2*VFS_CAP_U32_1))
 
-#define VFS_CAP_REVISION	VFS_CAP_REVISION_1
+#define VFS_CAP_REVISION_2	0x02000000
+#define VFS_CAP_U32_2           2
+#define XATTR_CAPS_SZ_2         (sizeof(__le32)*(1 + 2*VFS_CAP_U32_2))
+
+#define XATTR_CAPS_SZ           XATTR_CAPS_SZ_2
+#define VFS_CAP_U32             VFS_CAP_U32_2
+#define VFS_CAP_REVISION	VFS_CAP_REVISION_2
 
-#define VFS_CAP_FLAGS_MASK	~VFS_CAP_REVISION_MASK
-#define VFS_CAP_FLAGS_EFFECTIVE	0x000001
 
 struct vfs_cap_data {
-	__u32 magic_etc;  /* Little endian */
+	__le32 magic_etc;            /* Little endian */
 	struct {
-		__u32 permitted;    /* Little endian */
-		__u32 inheritable;  /* Little endian */
-	} data[1];
+		__le32 permitted;    /* Little endian */
+		__le32 inheritable;  /* Little endian */
+	} data[VFS_CAP_U32];
 };
 
 #ifdef __KERNEL__
 
-/* #define STRICT_CAP_T_TYPECHECKS */
-
-#ifdef STRICT_CAP_T_TYPECHECKS
-
 typedef struct kernel_cap_struct {
-	__u32 cap;
+	__u32 cap[_LINUX_CAPABILITY_U32S];
 } kernel_cap_t;
 
-#else
-
-typedef __u32 kernel_cap_t;
-
-#endif
-
-#define _USER_CAP_HEADER_SIZE  (2*sizeof(__u32))
+#define _USER_CAP_HEADER_SIZE  (sizeof(struct __user_cap_header_struct))
 #define _KERNEL_CAP_T_SIZE     (sizeof(kernel_cap_t))
 
 #endif
@@ -121,10 +127,6 @@ typedef __u32 kernel_cap_t;
 
 #define CAP_FSETID           4
 
-/* Used to decide between falling back on the old suser() or fsuser(). */
-
-#define CAP_FS_MASK          0x1f
-
 /* Overrides the restriction that the real or effective user ID of a
    process sending a signal must match the real or effective user ID
    of the process receiving the signal. */
@@ -147,8 +149,12 @@ typedef __u32 kernel_cap_t;
  ** Linux-specific capabilities
  **/
 
-/* Transfer any capability in your permitted set to any pid,
-   remove any capability in your permitted set from any pid */
+/* Without VFS support for capabilities:
+ *   Transfer any capability in your permitted set to any pid,
+ *   remove any capability in your permitted set from any pid
+ * With VFS support for capabilities (neither of above, but)
+ *   Add any capability to the current process' inheritable set
+ */
 
 #define CAP_SETPCAP          8
 
@@ -309,70 +315,154 @@ typedef __u32 kernel_cap_t;
 
 #define CAP_SETFCAP	     31
 
+/*
+ * Bit location of each capability (used by user-space library and kernel)
+ */
+
+#define CAP_TO_INDEX(x)     ((x) >> 5)        /* 1 << 5 == bits in __u32 */
+#define CAP_TO_MASK(x)      (1 << ((x) & 31)) /* mask for indexed __u32 */
+
 #ifdef __KERNEL__
 
 /*
  * Internal kernel functions only
  */
 
-#ifdef STRICT_CAP_T_TYPECHECKS
+#define CAP_FOR_EACH_U32(__capi)  \
+	for (__capi=0; __capi<_LINUX_CAPABILITY_U32S; ++__capi)
 
-#define to_cap_t(x) { x }
-#define cap_t(x) (x).cap
+# define CAP_FS_MASK_B0     (CAP_TO_MASK(CAP_CHOWN)             \
+			    |CAP_TO_MASK(CAP_DAC_OVERRIDE)      \
+			    |CAP_TO_MASK(CAP_DAC_READ_SEARCH)   \
+			    |CAP_TO_MASK(CAP_FOWNER)            \
+			    |CAP_TO_MASK(CAP_FSETID))
+
+#if _LINUX_CAPABILITY_U32S != 2
+# error Fix up hand-coded capability macro initializers
+#else /* HAND-CODED capability initializers */
+
+# define CAP_EMPTY_SET    {{ 0, 0 }}
+# define CAP_FULL_SET     {{ ~0, ~0 }}
+# define CAP_INIT_EFF_SET {{ ~CAP_TO_MASK(CAP_SETPCAP), ~0 }}
+# define CAP_FS_SET       {{ CAP_FS_MASK_B0, 0 }}
+# define CAP_NFSD_SET     {{ CAP_FS_MASK_B0|CAP_TO_MASK(CAP_SYS_RESOURCE), 0 }}
+
+#endif /* _LINUX_CAPABILITY_U32S != 2 */
+
+#define CAP_INIT_INH_SET    CAP_EMPTY_SET
+
+# define cap_clear(c)         do { (c) = __cap_empty_set; } while (0)
+# define cap_set_full(c)      do { (c) = __cap_full_set; } while (0)
+# define cap_set_init_eff(c)  do { (c) = __cap_init_eff_set; } while (0)
+
+#define cap_raise(c,flag)  ((c).cap[CAP_TO_INDEX(flag)] |= CAP_TO_MASK(flag))
+#define cap_lower(c,flag)  ((c).cap[CAP_TO_INDEX(flag)] &= ~CAP_TO_MASK(flag))
+#define cap_raised(c,flag) ((c).cap[CAP_TO_INDEX(flag)] & CAP_TO_MASK(flag))
+
+#define CAP_BOP_ALL(c, a, b, OP)                                    \
+do {                                                                \
+	unsigned __capi;                                            \
+	CAP_FOR_EACH_U32(__capi) {                                  \
+		c.cap[__capi] = a.cap[__capi] OP b.cap[__capi];     \
+	}                                                           \
+} while (0)
+
+#define CAP_UOP_ALL(c, a, OP)                                       \
+do {                                                                \
+	unsigned __capi;                                            \
+	CAP_FOR_EACH_U32(__capi) {                                  \
+		c.cap[__capi] = OP a.cap[__capi];                   \
+	}                                                           \
+} while (0)
 
-#else
+static inline kernel_cap_t cap_combine(const kernel_cap_t a,
+				       const kernel_cap_t b)
+{
+	kernel_cap_t dest;
+	CAP_BOP_ALL(dest, a, b, |);
+	return dest;
+}
 
-#define to_cap_t(x) (x)
-#define cap_t(x) (x)
+static inline kernel_cap_t cap_intersect(const kernel_cap_t a,
+					 const kernel_cap_t b)
+{
+	kernel_cap_t dest;
+	CAP_BOP_ALL(dest, a, b, &);
+	return dest;
+}
 
-#endif
+static inline kernel_cap_t cap_drop(const kernel_cap_t a,
+				    const kernel_cap_t drop)
+{
+	kernel_cap_t dest;
+	CAP_BOP_ALL(dest, a, drop, &~);
+	return dest;
+}
 
-#define CAP_EMPTY_SET       to_cap_t(0)
-#define CAP_FULL_SET        to_cap_t(~0)
-#define CAP_INIT_EFF_SET    to_cap_t(~0 & ~CAP_TO_MASK(CAP_SETPCAP))
-#define CAP_INIT_INH_SET    to_cap_t(0)
+static inline kernel_cap_t cap_invert(const kernel_cap_t c)
+{
+	kernel_cap_t dest;
+	CAP_UOP_ALL(dest, c, ~);
+	return dest;
+}
 
-#define CAP_TO_MASK(x) (1 << (x))
-#define cap_raise(c, flag)   (cap_t(c) |=  CAP_TO_MASK(flag))
-#define cap_lower(c, flag)   (cap_t(c) &= ~CAP_TO_MASK(flag))
-#define cap_raised(c, flag)  (cap_t(c) & CAP_TO_MASK(flag))
+static inline int cap_isclear(const kernel_cap_t a)
+{
+	unsigned __capi;
+	CAP_FOR_EACH_U32(__capi) {
+		if (a.cap[__capi] != 0) {
+			return 0;
+		}
+	}
+	return 1;
+}
 
-static inline kernel_cap_t cap_combine(kernel_cap_t a, kernel_cap_t b)
+static inline int cap_issubset(const kernel_cap_t a, const kernel_cap_t set)
 {
-     kernel_cap_t dest;
-     cap_t(dest) = cap_t(a) | cap_t(b);
-     return dest;
+	kernel_cap_t dest;
+	dest = cap_drop(a, set);
+	return cap_isclear(dest);
 }
 
-static inline kernel_cap_t cap_intersect(kernel_cap_t a, kernel_cap_t b)
+/* Used to decide between falling back on the old suser() or fsuser(). */
+
+static inline int cap_is_fs_cap(int cap)
 {
-     kernel_cap_t dest;
-     cap_t(dest) = cap_t(a) & cap_t(b);
-     return dest;
+	const kernel_cap_t __cap_fs_set = CAP_FS_SET;
+	return !!(CAP_TO_MASK(cap) & __cap_fs_set.cap[CAP_TO_INDEX(cap)]);
 }
 
-static inline kernel_cap_t cap_drop(kernel_cap_t a, kernel_cap_t drop)
+static inline kernel_cap_t cap_drop_fs_set(const kernel_cap_t a)
 {
-     kernel_cap_t dest;
-     cap_t(dest) = cap_t(a) & ~cap_t(drop);
-     return dest;
+	const kernel_cap_t __cap_fs_set = CAP_FS_SET;
+	return cap_drop(a, __cap_fs_set);
 }
 
-static inline kernel_cap_t cap_invert(kernel_cap_t c)
+static inline kernel_cap_t cap_raise_fs_set(const kernel_cap_t a,
+					    const kernel_cap_t permitted)
 {
-     kernel_cap_t dest;
-     cap_t(dest) = ~cap_t(c);
-     return dest;
+	const kernel_cap_t __cap_fs_set = CAP_FS_SET;
+	return cap_combine(a,
+			   cap_intersect(permitted, __cap_fs_set));
 }
 
-#define cap_isclear(c)       (!cap_t(c))
-#define cap_issubset(a,set)  (!(cap_t(a) & ~cap_t(set)))
+static inline kernel_cap_t cap_drop_nfsd_set(const kernel_cap_t a)
+{
+	const kernel_cap_t __cap_fs_set = CAP_NFSD_SET;
+	return cap_drop(a, __cap_fs_set);
+}
 
-#define cap_clear(c)         do { cap_t(c) =  0; } while(0)
-#define cap_set_full(c)      do { cap_t(c) = ~0; } while(0)
-#define cap_mask(c,mask)     do { cap_t(c) &= cap_t(mask); } while(0)
+static inline kernel_cap_t cap_raise_nfsd_set(const kernel_cap_t a,
+					      const kernel_cap_t permitted)
+{
+	const kernel_cap_t __cap_nfsd_set = CAP_NFSD_SET;
+	return cap_combine(a,
+			   cap_intersect(permitted, __cap_nfsd_set));
+}
 
-#define cap_is_fs_cap(c)     (CAP_TO_MASK(c) & CAP_FS_MASK)
+extern const kernel_cap_t __cap_empty_set;
+extern const kernel_cap_t __cap_full_set;
+extern const kernel_cap_t __cap_init_eff_set;
 
 int capable(int cap);
 int __capable(struct task_struct *t, int cap);
diff -puN kernel/capability.c~add-64-bit-capability-support-to-the-kernel kernel/capability.c
--- a/kernel/capability.c~add-64-bit-capability-support-to-the-kernel
+++ a/kernel/capability.c
@@ -22,6 +22,14 @@
 static DEFINE_SPINLOCK(task_capability_lock);
 
 /*
+ * Leveraged for setting/resetting capabilities
+ */
+
+const kernel_cap_t __cap_empty_set = CAP_EMPTY_SET;
+const kernel_cap_t __cap_full_set = CAP_FULL_SET;
+const kernel_cap_t __cap_init_eff_set = CAP_INIT_EFF_SET;
+
+/*
  * For sys_getproccap() and sys_setproccap(), any of the three
  * capability set pointers may be NULL -- indicating that that set is
  * uninteresting and/or not to be changed.
@@ -38,16 +46,31 @@ static DEFINE_SPINLOCK(task_capability_l
  */
 asmlinkage long sys_capget(cap_user_header_t header, cap_user_data_t dataptr)
 {
+	static int warned = 0;
 	int ret = 0;
 	pid_t pid;
 	__u32 version;
 	struct task_struct *target;
-	struct __user_cap_data_struct data;
+	unsigned tocopy;
+	kernel_cap_t pE, pI, pP;
 
 	if (get_user(version, &header->version))
 		return -EFAULT;
 
-	if (version != _LINUX_CAPABILITY_VERSION) {
+	switch (version) {
+	case _LINUX_CAPABILITY_VERSION_1:
+		if (warned < 5) {
+			warned++;
+			printk(KERN_INFO
+			       "warning: process `%s' gets w/ old libcap\n",
+			       current->comm);
+		}
+		tocopy = _LINUX_CAPABILITY_U32S_1;
+		break;
+	case _LINUX_CAPABILITY_VERSION_2:
+		tocopy = _LINUX_CAPABILITY_U32S_2;
+		break;
+	default:
 		if (put_user(_LINUX_CAPABILITY_VERSION, &header->version))
 			return -EFAULT;
 		return -EINVAL;
@@ -71,14 +94,34 @@ asmlinkage long sys_capget(cap_user_head
 	} else
 		target = current;
 
-	ret = security_capget(target, &data.effective, &data.inheritable, &data.permitted);
+	ret = security_capget(target, &pE, &pI, &pP);
 
 out:
 	read_unlock(&tasklist_lock);
 	spin_unlock(&task_capability_lock);
 
-	if (!ret && copy_to_user(dataptr, &data, sizeof data))
-		return -EFAULT;
+	if (!ret) {
+		struct __user_cap_data_struct kdata[_LINUX_CAPABILITY_U32S];
+		unsigned i;
+
+		for (i=0; i < tocopy; i++) {
+			kdata[i].effective = pE.cap[i];
+			kdata[i].permitted = pP.cap[i];
+			kdata[i].inheritable = pI.cap[i];
+		}
+		while (i < _LINUX_CAPABILITY_U32S) {
+			if (pE.cap[i] || pP.cap[i] || pP.cap[i]) {
+				/* Cannot represent w/ legacy structure */
+				return -ERANGE;
+			}
+			i++;
+		}
+
+		if (copy_to_user(dataptr, kdata, tocopy
+				 * sizeof(struct __user_cap_data_struct))) {
+			return -EFAULT;
+		}
+	}
 
 	return ret;
 }
@@ -167,6 +210,9 @@ static inline int cap_set_all(kernel_cap
  */
 asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data)
 {
+	static int warned = 0;
+	struct __user_cap_data_struct kdata[_LINUX_CAPABILITY_U32S];
+	unsigned i, tocopy;
 	kernel_cap_t inheritable, permitted, effective;
 	__u32 version;
 	struct task_struct *target;
@@ -176,7 +222,20 @@ asmlinkage long sys_capset(cap_user_head
 	if (get_user(version, &header->version))
 		return -EFAULT;
 
-	if (version != _LINUX_CAPABILITY_VERSION) {
+	switch (version) {
+	case _LINUX_CAPABILITY_VERSION_1:
+		if (warned < 5) {
+			warned++;
+			printk(KERN_INFO
+			       "warning: process `%s' sets w/ old libcap\n",
+			       current->comm);
+		}
+		tocopy = _LINUX_CAPABILITY_U32S_1;
+		break;
+	case _LINUX_CAPABILITY_VERSION_2:
+		tocopy = _LINUX_CAPABILITY_U32S_2;
+		break;
+	default:
 		if (put_user(_LINUX_CAPABILITY_VERSION, &header->version))
 			return -EFAULT;
 		return -EINVAL;
@@ -188,10 +247,22 @@ asmlinkage long sys_capset(cap_user_head
 	if (pid && pid != task_pid_vnr(current) && !capable(CAP_SETPCAP))
 		return -EPERM;
 
-	if (copy_from_user(&effective, &data->effective, sizeof(effective)) ||
-	    copy_from_user(&inheritable, &data->inheritable, sizeof(inheritable)) ||
-	    copy_from_user(&permitted, &data->permitted, sizeof(permitted)))
+	if (copy_from_user(&kdata, data, tocopy
+			   * sizeof(struct __user_cap_data_struct))) {
 		return -EFAULT;
+	}
+
+	for (i=0; i < tocopy; i++) {
+		effective.cap[i] = kdata[i].effective;
+		permitted.cap[i] = kdata[i].permitted;
+		inheritable.cap[i] = kdata[i].inheritable;
+	}
+	while (i < _LINUX_CAPABILITY_U32S) {
+		effective.cap[i] = 0;
+		permitted.cap[i] = 0;
+		inheritable.cap[i] = 0;
+		i++;
+	}
 
 	spin_lock(&task_capability_lock);
 	read_lock(&tasklist_lock);
diff -puN mm/oom_kill.c~add-64-bit-capability-support-to-the-kernel mm/oom_kill.c
--- a/mm/oom_kill.c~add-64-bit-capability-support-to-the-kernel
+++ a/mm/oom_kill.c
@@ -125,8 +125,7 @@ unsigned long badness(struct task_struct
 	 * Superuser processes are usually more important, so we make it
 	 * less likely that we kill those.
 	 */
-	if (cap_t(p->cap_effective) & CAP_TO_MASK(CAP_SYS_ADMIN) ||
-				p->uid == 0 || p->euid == 0)
+	if (__capable(p, CAP_SYS_ADMIN) || p->uid == 0 || p->euid == 0)
 		points /= 4;
 
 	/*
@@ -135,7 +134,7 @@ unsigned long badness(struct task_struct
 	 * tend to only have this flag set on applications they think
 	 * of as important.
 	 */
-	if (cap_t(p->cap_effective) & CAP_TO_MASK(CAP_SYS_RAWIO))
+	if (__capable(p, CAP_SYS_RAWIO))
 		points /= 4;
 
 	/*
diff -puN security/commoncap.c~add-64-bit-capability-support-to-the-kernel security/commoncap.c
--- a/security/commoncap.c~add-64-bit-capability-support-to-the-kernel
+++ a/security/commoncap.c
@@ -1,4 +1,4 @@
-/* Common capabilities, needed by capability.o and root_plug.o 
+/* Common capabilities, needed by capability.o and root_plug.o
  *
  *	This program is free software; you can redistribute it and/or modify
  *	it under the terms of the GNU General Public License as published by
@@ -87,9 +87,9 @@ int cap_capget (struct task_struct *targ
 		kernel_cap_t *inheritable, kernel_cap_t *permitted)
 {
 	/* Derived from kernel/capability.c:sys_capget. */
-	*effective = cap_t (target->cap_effective);
-	*inheritable = cap_t (target->cap_inheritable);
-	*permitted = cap_t (target->cap_permitted);
+	*effective = target->cap_effective;
+	*inheritable = target->cap_inheritable;
+	*permitted = target->cap_permitted;
 	return 0;
 }
 
@@ -190,28 +190,54 @@ int cap_inode_killpriv(struct dentry *de
 	return inode->i_op->removexattr(dentry, XATTR_NAME_CAPS);
 }
 
-static inline int cap_from_disk(__le32 *caps, struct linux_binprm *bprm,
-				int size)
+static inline int cap_from_disk(struct vfs_cap_data *caps,
+				struct linux_binprm *bprm, unsigned size)
 {
 	__u32 magic_etc;
+	unsigned tocopy, i;
 
-	if (size != XATTR_CAPS_SZ)
+	if (size < sizeof(magic_etc)) {
 		return -EINVAL;
+	}
 
-	magic_etc = le32_to_cpu(caps[0]);
+	magic_etc = le32_to_cpu(caps->magic_etc);
 
 	switch ((magic_etc & VFS_CAP_REVISION_MASK)) {
-	case VFS_CAP_REVISION:
-		if (magic_etc & VFS_CAP_FLAGS_EFFECTIVE)
-			bprm->cap_effective = true;
-		else
-			bprm->cap_effective = false;
-		bprm->cap_permitted = to_cap_t(le32_to_cpu(caps[1]));
-		bprm->cap_inheritable = to_cap_t(le32_to_cpu(caps[2]));
-		return 0;
+	case VFS_CAP_REVISION_1:
+		if (size != XATTR_CAPS_SZ_1) {
+			return -EINVAL;
+		}
+		tocopy = VFS_CAP_U32_1;
+		break;
+	case VFS_CAP_REVISION_2:
+		if (size != XATTR_CAPS_SZ_2) {
+			return -EINVAL;
+		}
+		tocopy = VFS_CAP_U32_2;
+		break;
 	default:
 		return -EINVAL;
 	}
+
+	if (magic_etc & VFS_CAP_FLAGS_EFFECTIVE) {
+		bprm->cap_effective = true;
+	} else {
+		bprm->cap_effective = false;
+	}
+
+	for (i=0; i < tocopy; ++i) {
+		bprm->cap_permitted.cap[i] =
+			le32_to_cpu(caps->data[i].permitted);
+		bprm->cap_inheritable.cap[i] =
+			le32_to_cpu(caps->data[i].inheritable);
+	}
+	while (i < VFS_CAP_U32) {
+		bprm->cap_permitted.cap[i] = 0;
+		bprm->cap_inheritable.cap[i] = 0;
+		i++;
+	}
+
+	return 0;
 }
 
 /* Locate any VFS capabilities: */
@@ -219,7 +245,7 @@ static int get_file_caps(struct linux_bi
 {
 	struct dentry *dentry;
 	int rc = 0;
-	__le32 v1caps[XATTR_CAPS_SZ];
+	struct vfs_cap_data vcaps;
 	struct inode *inode;
 
 	if (bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID) {
@@ -232,8 +258,8 @@ static int get_file_caps(struct linux_bi
 	if (!inode->i_op || !inode->i_op->getxattr)
 		goto out;
 
-	rc = inode->i_op->getxattr(dentry, XATTR_NAME_CAPS, &v1caps,
-							XATTR_CAPS_SZ);
+	rc = inode->i_op->getxattr(dentry, XATTR_NAME_CAPS, &vcaps,
+				   XATTR_CAPS_SZ);
 	if (rc == -ENODATA || rc == -EOPNOTSUPP) {
 		/* no data, that's ok */
 		rc = 0;
@@ -242,7 +268,7 @@ static int get_file_caps(struct linux_bi
 	if (rc < 0)
 		goto out;
 
-	rc = cap_from_disk(v1caps, bprm, rc);
+	rc = cap_from_disk(&vcaps, bprm, rc);
 	if (rc)
 		printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n",
 			__FUNCTION__, rc, bprm->filename);
@@ -337,8 +363,11 @@ void cap_bprm_apply_creds (struct linux_
 	 * capability rules */
 	if (!is_global_init(current)) {
 		current->cap_permitted = new_permitted;
-		current->cap_effective = bprm->cap_effective ?
-				new_permitted : 0;
+		if (bprm->cap_effective) {
+			current->cap_effective = new_permitted;
+		} else {
+			cap_clear(current->cap_effective);
+		}
 	}
 
 	/* AUD: Audit candidate if current->cap_effective is set */
@@ -460,13 +489,17 @@ int cap_task_post_setuid (uid_t old_ruid
 
 			if (!issecure (SECURE_NO_SETUID_FIXUP)) {
 				if (old_fsuid == 0 && current->fsuid != 0) {
-					cap_t (current->cap_effective) &=
-					    ~CAP_FS_MASK;
+					current->cap_effective =
+						cap_drop_fs_set(
+						    current->cap_effective
+						    );
 				}
 				if (old_fsuid != 0 && current->fsuid == 0) {
-					cap_t (current->cap_effective) |=
-					    (cap_t (current->cap_permitted) &
-					     CAP_FS_MASK);
+					current->cap_effective =
+						cap_raise_fs_set(
+						    current->cap_effective,
+						    current->cap_permitted
+						    );
 				}
 			}
 			break;
@@ -561,9 +594,9 @@ int cap_task_kill(struct task_struct *p,
 
 void cap_task_reparent_to_init (struct task_struct *p)
 {
-	p->cap_effective = CAP_INIT_EFF_SET;
-	p->cap_inheritable = CAP_INIT_INH_SET;
-	p->cap_permitted = CAP_FULL_SET;
+	cap_set_init_eff(p->cap_effective);
+	cap_clear(p->cap_inheritable);
+	cap_set_full(p->cap_permitted);
 	p->keep_capabilities = 0;
 	return;
 }
diff -puN security/dummy.c~add-64-bit-capability-support-to-the-kernel security/dummy.c
--- a/security/dummy.c~add-64-bit-capability-support-to-the-kernel
+++ a/security/dummy.c
@@ -36,14 +36,19 @@ static int dummy_ptrace (struct task_str
 static int dummy_capget (struct task_struct *target, kernel_cap_t * effective,
 			 kernel_cap_t * inheritable, kernel_cap_t * permitted)
 {
-	*effective = *inheritable = *permitted = 0;
 	if (target->euid == 0) {
-		*permitted |= (~0 & ~CAP_FS_MASK);
-		*effective |= (~0 & ~CAP_TO_MASK(CAP_SETPCAP) & ~CAP_FS_MASK);
+		cap_set_full(*permitted);
+		cap_set_init_eff(*effective);
+	} else {
+		cap_clear(*permitted);
+		cap_clear(*effective);
 	}
-	if (target->fsuid == 0) {
-		*permitted |= CAP_FS_MASK;
-		*effective |= CAP_FS_MASK;
+
+	cap_clear(*inheritable);
+
+	if (target->fsuid != 0) {
+		*permitted = cap_drop_fs_set(*permitted);
+		*effective = cap_drop_fs_set(*effective);
 	}
 	return 0;
 }
_

Patches currently in -mm which might be from morgan@kernel.org are

file-capabilities-allow-sigcont-within-session-v2.patch
file-capabilities-allow-sigcont-within-session-v2-file-capabilities-remove-the-non-matching-uid-special-case-for-kill.patch
revert-capabilities-clean-up-file-capability-reading.patch
revert-capabilities-clean-up-file-capability-reading-checkpatch-fixes.patch
add-64-bit-capability-support-to-the-kernel.patch

^ permalink raw reply

* Re: [PATCH -v3] SELinux: Add get, set, and cloning of superblock security information
From: Casey Schaufler @ 2007-11-09 22:46 UTC (permalink / raw)
  To: Eric Paris, selinux, LSM List, linux-fsdevel
  Cc: sds, jmorris, Casey Schaufler
In-Reply-To: <1194646937.4627.30.camel@localhost.localdomain>


--- Eric Paris <eparis@redhat.com> wrote:

> Adds security_get_sb_mnt_opts, security_set_sb_mnt_opts, and
> security_clont_sb_mnt_opts to the LSM and to SELinux.  This will allow
> filesystems to directly own and control all of their mount options if
> they so choose.

I understand why you would want get_sb_mnt_opts(), but what
is the value for set_sb_mnt_opts() and what is the purpose of
clone_sb_mnt_opts()?

> This interface deals only with option identifiers and
> strings so it should generic enough for any LSM which may come in the
> future.  Filesystems which pass text mount data around in the kernel
> (almost all of them) need not currently make use of this interface for
> SELinux sake since it will still parse those strings as it always has.

If SELinux is still dealing with strings on it's own what is
the point of these hooks?

> An LSM would need to implement these functions only if they had mount
> time options, such as selinux has context= or fscontext=.  If the LSM
> has no mount time options they could simply not implement and let the
> dummy ops take care of things.  

Smack and SELinux currently deal with options in sb_kern_mount(), with
help from sb_copy_data(). Why change the implementation?

> A LSM other than SELinux would need to define new option numbers in
> security.h

I don't think it is a good idea to require that LSM specific
information be stored outside the scope of the LSM.

> (or could reuse if they have the same basic meaning I guess)
> and any FS which decides to own there own security options would need to
> be patched to use this new interface for every possible LSM.  This is
> because it was stated to me very clearly that LSM's should not attempt
> to understand FS mount data and the burdon to understand security should
> be in the FS which owns the options.

Perhaps a mount option prefix then. "Smack.root", "SELinux.context",
that sort of thing. An LSM writer shouldn't have to patch security.h
every time she wants to add a mount option.

> Signed-off-by: Eric Paris <eparis@redhat.com>
> 
> ---
> 
> For now the only forseen user of this interface is NFS.  NFS uses a
> binary blob in kernel for mount data (it uses this blob irrespective of
> the binary vs. text mount options it can get from userspace.)  NFS must
> then set its own mount options explicitly so we need some interface for
> it to do so.
> 
> 
>  include/linux/security.h          |   36 ++
>  security/dummy.c                  |   26 ++
>  security/security.c               |   20 +
>  security/selinux/hooks.c          |  749
> ++++++++++++++++++++++++-------------
>  security/selinux/include/objsec.h |    1 +
>  5 files changed, 578 insertions(+), 254 deletions(-)
> 
> diff --git a/include/linux/security.h b/include/linux/security.h
> index ac05083..dcbb792 100644
> --- a/include/linux/security.h
> +++ b/include/linux/security.h
> @@ -34,6 +34,12 @@
>  #include <linux/xfrm.h>
>  #include <net/flow.h>
>  
> +/* only a char in selinux superblock security struct flags */
> +#define FSCONTEXT_MNT		0x01
> +#define CONTEXT_MNT		0x02
> +#define ROOTCONTEXT_MNT		0x04
> +#define DEFCONTEXT_MNT		0x08
> +
>  /*
>   * Bounding set
>   */
> @@ -261,6 +267,22 @@ struct request_sock;
>   *	Update module state after a successful pivot.
>   *	@old_nd contains the nameidata structure for the old root.
>   *      @new_nd contains the nameidata structure for the new root.
> + * @sb_get_mnt_opts:
> + *      Get the security relevant mount options used for a superblock
> + *      @sb the superblock to get security mount options from
> + *      @mount_options array for pointers to mount options
> + *      @mount_flags array of ints specifying what each mount options is
> + *      @num_opts number of options in the arrays
> + * @sb_set_mnt_opts:
> + *      Set the security relevant mount options used for a superblock
> + *      @sb the superblock to set security mount options for
> + *      @mount_options array for pointers to mount options
> + *      @mount_flags array of ints specifying what each mount options is
> + *      @num_opts number of options in the arrays
> + * @sb_clone_mnt_opts:
> + *	Copy all security options from a given superblock to another
> + *	@oldsb old superblock which contain information to clone
> + *	@newsb new superblock which needs filled in
>   *
>   * Security hooks for inode operations.
>   *
> @@ -1242,6 +1264,13 @@ struct security_operations {
>  			     struct nameidata * new_nd);
>  	void (*sb_post_pivotroot) (struct nameidata * old_nd,
>  				   struct nameidata * new_nd);
> +	int (*sb_get_mnt_opts) (const struct super_block *sb,
> +				char ***mount_options, int **flags,
> +				int *num_opts);
> +	int (*sb_set_mnt_opts) (struct super_block *sb, char **mount_options,
> +				int *flags, int num_opts);
> +	void (*sb_clone_mnt_opts) (const struct super_block *oldsb,
> +				   struct super_block *newsb);
>  
>  	int (*inode_alloc_security) (struct inode *inode);	
>  	void (*inode_free_security) (struct inode *inode);
> @@ -1499,6 +1528,13 @@ void security_sb_post_mountroot(void);
>  void security_sb_post_addmount(struct vfsmount *mnt, struct nameidata
> *mountpoint_nd);
>  int security_sb_pivotroot(struct nameidata *old_nd, struct nameidata
> *new_nd);
>  void security_sb_post_pivotroot(struct nameidata *old_nd, struct nameidata
> *new_nd);
> +int security_sb_get_mnt_opts(const struct super_block *sb, char
> ***mount_options,
> +			     int **flags, int *num_opts);
> +int security_sb_set_mnt_opts(struct super_block *sb, char **mount_options,
> +			     int *flags, int num_opts);
> +void security_sb_clone_mnt_opts(const struct super_block *oldsb,
> +				struct super_block *newsb);
> +
>  int security_inode_alloc(struct inode *inode);
>  void security_inode_free(struct inode *inode);
>  int security_inode_init_security(struct inode *inode, struct inode *dir,
> diff --git a/security/dummy.c b/security/dummy.c
> index 6d895ad..22d9663 100644
> --- a/security/dummy.c
> +++ b/security/dummy.c
> @@ -245,6 +245,29 @@ static void dummy_sb_post_pivotroot (struct nameidata
> *old_nd, struct nameidata
>  	return;
>  }
>  
> +static int dummy_sb_get_mnt_opts(const struct super_block *sb, char
> ***mount_options,
> +				 int **flags, int *num_opts)
> +{
> +	*mount_options = NULL;
> +	*flags = NULL;
> +	*num_opts = 0;
> +	return 0;
> +}
> +
> +static int dummy_sb_set_mnt_opts(struct super_block *sb, char
> **mount_options,
> +				 int *flags, int num_opts)
> +{
> +	if (unlikely(num_opts))
> +		return -EOPNOTSUPP;
> +	return 0;
> +}
> +
> +static void dummy_sb_clone_mnt_opts(const struct super_block *oldsb,
> +				    struct super_block *newsb)
> +{
> +	return;
> +}
> +
>  static int dummy_inode_alloc_security (struct inode *inode)
>  {
>  	return 0;
> @@ -998,6 +1021,9 @@ void security_fixup_ops (struct security_operations
> *ops)
>  	set_to_dummy_if_null(ops, sb_post_addmount);
>  	set_to_dummy_if_null(ops, sb_pivotroot);
>  	set_to_dummy_if_null(ops, sb_post_pivotroot);
> +	set_to_dummy_if_null(ops, sb_get_mnt_opts);
> +	set_to_dummy_if_null(ops, sb_set_mnt_opts);
> +	set_to_dummy_if_null(ops, sb_clone_mnt_opts);
>  	set_to_dummy_if_null(ops, inode_alloc_security);
>  	set_to_dummy_if_null(ops, inode_free_security);
>  	set_to_dummy_if_null(ops, inode_init_security);
> diff --git a/security/security.c b/security/security.c
> index 0e1f1f1..f48fb30 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -308,6 +308,26 @@ void security_sb_post_pivotroot(struct nameidata
> *old_nd, struct nameidata *new_
>  	security_ops->sb_post_pivotroot(old_nd, new_nd);
>  }
>  
> +int security_sb_get_mnt_opts (const struct super_block *sb,
> +			      char ***mount_options,
> +			      int **flags, int *num_opts)
> +{
> +	return security_ops->sb_get_mnt_opts(sb, mount_options, flags, num_opts);
> +}
> +
> +int security_sb_set_mnt_opts (struct super_block *sb,
> +			      char **mount_options,
> +			      int *flags, int num_opts)
> +{
> +	return security_ops->sb_set_mnt_opts(sb, mount_options, flags, num_opts);
> +}
> +
> +void security_sb_clone_mnt_opts(const struct super_block *oldsb,
> +				struct super_block *newsb)
> +{
> +	security_ops->sb_clone_mnt_opts(oldsb, newsb);
> +}
> +
>  int security_inode_alloc(struct inode *inode)
>  {
>  	inode->i_security = NULL;
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 9f3124b..e710764 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -82,6 +82,8 @@
>  #define XATTR_SELINUX_SUFFIX "selinux"
>  #define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX
>  
> +#define NUM_SEL_MNT_OPTS 4
> +
>  extern unsigned int policydb_loaded_version;
>  extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);
>  extern int selinux_compat_net;
> @@ -321,8 +323,8 @@ enum {
>  	Opt_error = -1,
>  	Opt_context = 1,
>  	Opt_fscontext = 2,
> -	Opt_defcontext = 4,
> -	Opt_rootcontext = 8,
> +	Opt_defcontext = 3,
> +	Opt_rootcontext = 4,
>  };
>  
>  static match_table_t tokens = {
> @@ -366,150 +368,318 @@ static int may_context_mount_inode_relabel(u32 sid,
>  	return rc;
>  }
>  
> -static int try_context_mount(struct super_block *sb, void *data)
> +static int sb_finish_set_opts(struct super_block *sb)
>  {
> -	char *context = NULL, *defcontext = NULL;
> -	char *fscontext = NULL, *rootcontext = NULL;
> -	const char *name;
> -	u32 sid;
> -	int alloc = 0, rc = 0, seen = 0;
> -	struct task_security_struct *tsec = current->security;
>  	struct superblock_security_struct *sbsec = sb->s_security;
> +	struct dentry *root = sb->s_root;
> +	struct inode *root_inode = root->d_inode;
> +	int rc = 0;
>  
> -	if (!data)
> -		goto out;
> +	if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
> +		/* Make sure that the xattr handler exists and that no
> +		   error other than -ENODATA is returned by getxattr on
> +		   the root directory.  -ENODATA is ok, as this may be
> +		   the first boot of the SELinux kernel before we have
> +		   assigned xattr values to the filesystem. */
> +		if (!root_inode->i_op->getxattr) {
> +			printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
> +			       "xattr support\n", sb->s_id, sb->s_type->name);
> +			rc = -EOPNOTSUPP;
> +			goto out;
> +		}
> +		rc = root_inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0);
> +		if (rc < 0 && rc != -ENODATA) {
> +			if (rc == -EOPNOTSUPP)
> +				printk(KERN_WARNING "SELinux: (dev %s, type "
> +				       "%s) has no security xattr handler\n",
> +				       sb->s_id, sb->s_type->name);
> +			else
> +				printk(KERN_WARNING "SELinux: (dev %s, type "
> +				       "%s) getxattr errno %d\n", sb->s_id,
> +				       sb->s_type->name, -rc);
> +			goto out;
> +		}
> +	}
>  
> -	name = sb->s_type->name;
> +	sbsec->initialized = 1;
>  
> -	if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA) {
> +	if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) {
> +		printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown
> behavior\n",
> +		       sb->s_id, sb->s_type->name);
> +	}
> +	else {
> +		printk(KERN_DEBUG "SELinux: initialized (dev %s, type %s), %s\n",
> +		       sb->s_id, sb->s_type->name,
> +		       labeling_behaviors[sbsec->behavior-1]);
> +	}
>  
> -		/* NFS we understand. */
> -		if (!strcmp(name, "nfs")) {
> -			struct nfs_mount_data *d = data;
> +	/* Initialize the root inode. */
> +	rc = inode_doinit_with_dentry(root_inode, root);
>  
> -			if (d->version <  NFS_MOUNT_VERSION)
> -				goto out;
> +	/* Initialize any other inodes associated with the superblock, e.g.
> +	   inodes created prior to initial policy load or inodes created
> +	   during get_sb by a pseudo filesystem that directly
> +	   populates itself. */
> +	spin_lock(&sbsec->isec_lock);
> +next_inode:
> +	if (!list_empty(&sbsec->isec_head)) {
> +		struct inode_security_struct *isec =
> +				list_entry(sbsec->isec_head.next,
> +					   struct inode_security_struct, list);
> +		struct inode *inode = isec->inode;
> +		spin_unlock(&sbsec->isec_lock);
> +		inode = igrab(inode);
> +		if (inode) {
> +			if (!IS_PRIVATE (inode))
> +				inode_doinit(inode);
> +			iput(inode);
> +		}
> +		spin_lock(&sbsec->isec_lock);
> +		list_del_init(&isec->list);
> +		goto next_inode;
> +	}
> +	spin_unlock(&sbsec->isec_lock);
> +out:
> +	return rc;
> +}
>  
> -			if (d->context[0]) {
> -				context = d->context;
> -				seen |= Opt_context;
> -			}
> -		} else
> -			goto out;
> +/*
> + * This function should allow an FS to ask what it's mount security
> + * options were so it can use those later for submounts, displaying
> + * mount options, or whatever.
> + */
> +static int selinux_get_mnt_opts(const struct super_block *sb,
> +				char ***mount_options, int **mnt_opts_flags,
> +				int *num_opts)
> +{
> +	int rc = 0, i;
> +	struct superblock_security_struct *sbsec = sb->s_security;
> +	char *context = NULL;
> +	u32 len;
> +	char tmp; 
>  
> -	} else {
> -		/* Standard string-based options. */
> -		char *p, *options = data;
> +	*num_opts = 0;
> +	*mount_options = NULL;
> +	*mnt_opts_flags = NULL;
>  
> -		while ((p = strsep(&options, "|")) != NULL) {
> -			int token;
> -			substring_t args[MAX_OPT_ARGS];
> +	if (!sbsec->initialized)
> +		return -EINVAL;
>  
> -			if (!*p)
> -				continue;
> +	if (!ss_initialized)
> +		return -EINVAL;
>  
> -			token = match_token(p, tokens, args);
> +	/* 
> +	 * if we ever use sbsec flags for anything other than tracking mount
> +	 * settings this is going to need a mask
> +	 */
> +	tmp = sbsec->flags;
> +	/* count the number of mount options for this sb */
> +	for(i = 0; i < 8; i++) {
> +		if (tmp & 0x01)
> +			(*num_opts)++;
> +		tmp >>= 1;
> +	}
>  
> -			switch (token) {
> -			case Opt_context:
> -				if (seen & (Opt_context|Opt_defcontext)) {
> -					rc = -EINVAL;
> -					printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
> -					goto out_free;
> -				}
> -				context = match_strdup(&args[0]);
> -				if (!context) {
> -					rc = -ENOMEM;
> -					goto out_free;
> -				}
> -				if (!alloc)
> -					alloc = 1;
> -				seen |= Opt_context;
> -				break;
> +	*mount_options = kcalloc(*num_opts, sizeof(char *), GFP_ATOMIC);
> +	if (!*mount_options) {
> +		rc = -ENOMEM;
> +		goto out_free;
> +	}
>  
> -			case Opt_fscontext:
> -				if (seen & Opt_fscontext) {
> -					rc = -EINVAL;
> -					printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
> -					goto out_free;
> -				}
> -				fscontext = match_strdup(&args[0]);
> -				if (!fscontext) {
> -					rc = -ENOMEM;
> -					goto out_free;
> -				}
> -				if (!alloc)
> -					alloc = 1;
> -				seen |= Opt_fscontext;
> -				break;
> +	*mnt_opts_flags = kcalloc(*num_opts, sizeof(int), GFP_ATOMIC);
> +	if (!*mnt_opts_flags) {
> +		rc = -ENOMEM;
> +		goto out_free;
> +	}
>  
> -			case Opt_rootcontext:
> -				if (seen & Opt_rootcontext) {
> -					rc = -EINVAL;
> -					printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
> -					goto out_free;
> -				}
> -				rootcontext = match_strdup(&args[0]);
> -				if (!rootcontext) {
> -					rc = -ENOMEM;
> -					goto out_free;
> -				}
> -				if (!alloc)
> -					alloc = 1;
> -				seen |= Opt_rootcontext;
> -				break;
> +	i = 0;
> +	if (sbsec->flags & FSCONTEXT_MNT) {
> +		rc = security_sid_to_context(sbsec->sid, &context, &len);
> +		if (rc)
> +			goto out_free;
> +		(*mount_options)[i] = context;
> +		(*mnt_opts_flags)[i++] = FSCONTEXT_MNT;
> +	}
> +	if (sbsec->flags & CONTEXT_MNT) {
> +		rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len);
> +		if (rc)
> +			goto out_free;
> +		(*mount_options)[i] = context;
> +		(*mnt_opts_flags)[i++] = CONTEXT_MNT;
> +	}
> +	if (sbsec->flags & DEFCONTEXT_MNT) {
> +		rc = security_sid_to_context(sbsec->def_sid, &context, &len);
> +		if (rc)
> +			goto out_free;
> +		(*mount_options)[i] = context;
> +		(*mnt_opts_flags)[i++] = DEFCONTEXT_MNT;
> +	}
> +	if (sbsec->flags & ROOTCONTEXT_MNT) {
> +		struct inode *root = sbsec->sb->s_root->d_inode;
> +		struct inode_security_struct *isec = root->i_security;
>  
> -			case Opt_defcontext:
> -				if (sbsec->behavior != SECURITY_FS_USE_XATTR) {
> -					rc = -EINVAL;
> -					printk(KERN_WARNING "SELinux:  "
> -					       "defcontext option is invalid "
> -					       "for this filesystem type\n");
> -					goto out_free;
> -				}
> -				if (seen & (Opt_context|Opt_defcontext)) {
> -					rc = -EINVAL;
> -					printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
> -					goto out_free;
> -				}
> -				defcontext = match_strdup(&args[0]);
> -				if (!defcontext) {
> -					rc = -ENOMEM;
> -					goto out_free;
> -				}
> -				if (!alloc)
> -					alloc = 1;
> -				seen |= Opt_defcontext;
> -				break;
> +		rc = security_sid_to_context(isec->sid, &context, &len);
> +		if (rc)
> +			goto out_free;
> +		(*mount_options)[i] = context;
> +		(*mnt_opts_flags)[i++] = ROOTCONTEXT_MNT;
> +	}
>  
> -			default:
> -				rc = -EINVAL;
> -				printk(KERN_WARNING "SELinux:  unknown mount "
> -				       "option\n");
> -				goto out_free;
> +	BUG_ON(i != *num_opts);
>  
> -			}
> -		}
> -	}
> +	return 0;
> +
> +out_free:
> +	/* don't leak context string if security_sid_to_context had an error */
> +	if(*mount_options && i)
> +		for (; i > 0; i--)
> +			kfree((*mount_options)[i-1]);
> +	kfree(*mount_options);
> +	*mount_options = NULL;
> +	kfree(*mnt_opts_flags);
> +	*mnt_opts_flags = NULL;
> +	*num_opts = 0;
> +	return rc;
> +}
> +
> +static int bad_option(struct superblock_security_struct *sbsec, char flag,
> +		      u32 old_sid, u32 new_sid)
> +{
> +	/* check if the old mount command had the same options */
> +	if (sbsec->initialized)
> +		if (!(sbsec->flags & flag) ||
> +		    (old_sid != new_sid))
> +			return 1;
> +
> +	/* check if we were passed the same options twice,
> +	 * aka someone passed context=a,context=b
> +	 */
> +	if (!sbsec->initialized)
> +		if (sbsec->flags & flag)
> +			return 1;
> +	return 0;
> +}
> +/*
> + * Allow filesystems with binary mount data to explicitly set mount point
> labeling.
> + */
> +int selinux_set_mnt_opts(struct super_block *sb, char **mount_options,
> +				 int *flags, int num_opts)
> +{
> +	int rc = 0, i;
> +	struct task_security_struct *tsec = current->security;
> +	struct superblock_security_struct *sbsec = sb->s_security;
> +	const char *name = sb->s_type->name;
> +	struct inode *inode = sbsec->sb->s_root->d_inode;
> +	struct inode_security_struct *root_isec = inode->i_security;
> +	u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
> +	u32 defcontext_sid = 0;
> +
> +	mutex_lock(&sbsec->lock);
>  
> -	if (!seen)
> +	if (!ss_initialized) {
> +		if (!num_opts) {
> +			/* Defer initialization until selinux_complete_init,
> +		   	after the initial policy is loaded and the security
> +		   	server is ready to handle calls. */
> +			spin_lock(&sb_security_lock);
> +			if (list_empty(&sbsec->list))
> +				list_add(&sbsec->list, &superblock_security_head);
> +			spin_unlock(&sb_security_lock);
> +			goto out;
> +		}
> +		rc = -EINVAL;
> +		printk(KERN_WARNING "Unable to set superblock options before "
> +		       "the security server is initialized\n");
>  		goto out;
> +	}
>  
> -	/* sets the context of the superblock for the fs being mounted. */
> -	if (fscontext) {
> -		rc = security_context_to_sid(fscontext, strlen(fscontext), &sid);
> +	/* 
> +	 * parse the mount options, check if they are valid sids.
> +	 * also check if someone is trying to mount the same sb more
> +	 * than once with different security options.
> +	 */
> +	for(i = 0; i < num_opts; i++) {
> +		u32 sid;
> +		rc = security_context_to_sid(mount_options[i],
> +					     strlen(mount_options[i]), &sid);
>  		if (rc) {
>  			printk(KERN_WARNING "SELinux: security_context_to_sid"
>  			       "(%s) failed for (dev %s, type %s) errno=%d\n",
> -			       fscontext, sb->s_id, name, rc);
> -			goto out_free;
> +			       mount_options[i], sb->s_id, name, rc);
> +			goto out;
>  		}
> +		switch(flags[i]) {
> +		case FSCONTEXT_MNT:
> +			fscontext_sid = sid;
> +
> +			if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
> +					fscontext_sid))
> +				goto out_double_mount;
> +
> +			sbsec->flags |= FSCONTEXT_MNT;
> +			break;
> +		case CONTEXT_MNT:
> +			context_sid = sid;
> +
> +			if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
> +					context_sid))
> +				goto out_double_mount;
> +
> +			sbsec->flags |= CONTEXT_MNT;
> +			break;
> +		case ROOTCONTEXT_MNT:
> +			rootcontext_sid = sid;
> +
> +			if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
> +					rootcontext_sid))
> +				goto out_double_mount;
> +
> +			sbsec->flags |= ROOTCONTEXT_MNT;
> +
> +			break;
> +		case DEFCONTEXT_MNT:
> +			defcontext_sid = sid;
> +
> +			if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
> +					defcontext_sid))
> +				goto out_double_mount;
>  
> -		rc = may_context_mount_sb_relabel(sid, sbsec, tsec);
> +			sbsec->flags |= DEFCONTEXT_MNT;
> +
> +			break;
> +		default:
> +			rc = -EINVAL;
> +			goto out;
> +		}
> +	}
> +
> +	if (sbsec->initialized) {
> +		/* previously mounted with options, but not on this attempt? */
> +		if (sbsec->flags && !num_opts)
> +			goto out_double_mount;
> +		rc = 0;
> +		goto out;
> +	}
> +
> +	if (strcmp(sb->s_type->name, "proc") == 0)
> +		sbsec->proc = 1;
> +
> +	/* Determine the labeling behavior to use for this filesystem type. */
> +	rc = security_fs_use(sb->s_type->name, &sbsec->behavior, &sbsec->sid);
> +	if (rc) {
> +		printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n",
> +		       __FUNCTION__, sb->s_type->name, rc);
> +		goto out;
> +	}
> +
> +	/* sets the context of the superblock for the fs being mounted. */
> +	if (fscontext_sid) {
> +
> +		rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, tsec);
>  		if (rc)
> -			goto out_free;
> +			goto out;
>  
> -		sbsec->sid = sid;
> +		sbsec->sid = fscontext_sid;
>  	}
>  
>  	/*
> @@ -517,182 +687,250 @@ static int try_context_mount(struct super_block *sb,
> void *data)
>  	 * sets the label used on all file below the mountpoint, and will set
>  	 * the superblock context if not already set.
>  	 */
> -	if (context) {
> -		rc = security_context_to_sid(context, strlen(context), &sid);
> -		if (rc) {
> -			printk(KERN_WARNING "SELinux: security_context_to_sid"
> -			       "(%s) failed for (dev %s, type %s) errno=%d\n",
> -			       context, sb->s_id, name, rc);
> -			goto out_free;
> -		}
> -
> -		if (!fscontext) {
> -			rc = may_context_mount_sb_relabel(sid, sbsec, tsec);
> +	if (context_sid) {
> +		if (!fscontext_sid) {
> +			rc = may_context_mount_sb_relabel(context_sid, sbsec, tsec);
>  			if (rc)
> -				goto out_free;
> -			sbsec->sid = sid;
> +				goto out;
> +			sbsec->sid = context_sid;
>  		} else {
> -			rc = may_context_mount_inode_relabel(sid, sbsec, tsec);
> +			rc = may_context_mount_inode_relabel(context_sid, sbsec, tsec);
>  			if (rc)
> -				goto out_free;
> +				goto out;
>  		}
> -		sbsec->mntpoint_sid = sid;
> +		if (!rootcontext_sid)
> +			rootcontext_sid = context_sid;
>  
> +		sbsec->mntpoint_sid = context_sid;
>  		sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
>  	}
>  
> -	if (rootcontext) {
> -		struct inode *inode = sb->s_root->d_inode;
> -		struct inode_security_struct *isec = inode->i_security;
> -		rc = security_context_to_sid(rootcontext, strlen(rootcontext), &sid);
> -		if (rc) {
> -			printk(KERN_WARNING "SELinux: security_context_to_sid"
> -			       "(%s) failed for (dev %s, type %s) errno=%d\n",
> -			       rootcontext, sb->s_id, name, rc);
> -			goto out_free;
> -		}
> -
> -		rc = may_context_mount_inode_relabel(sid, sbsec, tsec);
> +	if (rootcontext_sid) {
> +		rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec, tsec);
>  		if (rc)
> -			goto out_free;
> +			goto out;
>  
> -		isec->sid = sid;
> -		isec->initialized = 1;
> +		root_isec->sid = rootcontext_sid;
> +		root_isec->initialized = 1;
>  	}
>  
> -	if (defcontext) {
> -		rc = security_context_to_sid(defcontext, strlen(defcontext), &sid);
> -		if (rc) {
> -			printk(KERN_WARNING "SELinux: security_context_to_sid"
> -			       "(%s) failed for (dev %s, type %s) errno=%d\n",
> -			       defcontext, sb->s_id, name, rc);
> -			goto out_free;
> +	if (defcontext_sid) {
> +		if (sbsec->behavior != SECURITY_FS_USE_XATTR) {
> +			rc = -EINVAL;
> +			printk(KERN_WARNING "SELinux: defcontext option is "
> +			       "invalid for this filesystem type\n");
> +			goto out;
>  		}
>  
> -		if (sid == sbsec->def_sid)
> -			goto out_free;
> -
> -		rc = may_context_mount_inode_relabel(sid, sbsec, tsec);
> -		if (rc)
> -			goto out_free;
> +		if (defcontext_sid != sbsec->def_sid) {
> +			rc = may_context_mount_inode_relabel(defcontext_sid,
> +							     sbsec, tsec);
> +			if (rc)
> +				goto out;
> +		}
>  
> -		sbsec->def_sid = sid;
> +		sbsec->def_sid = defcontext_sid;
>  	}
>  
> -out_free:
> -	if (alloc) {
> -		kfree(context);
> -		kfree(defcontext);
> -		kfree(fscontext);
> -		kfree(rootcontext);
> -	}
> +	rc = sb_finish_set_opts(sb);
>  out:
> +	mutex_unlock(&sbsec->lock);
>  	return rc;
> +out_double_mount:
> +	rc = -EINVAL;
> +	printk(KERN_WARNING "SELinux: mount invalid.  Same superblock, different "
> +	       "security settings for (dev %s, type %s)\n", sb->s_id, name);
> +	goto out;
>  }
>  
> -static int superblock_doinit(struct super_block *sb, void *data)
> +static void selinux_sb_clone_mnt_opts (const struct super_block *oldsb,
> +					struct super_block *newsb)
>  {
> -	struct superblock_security_struct *sbsec = sb->s_security;
> -	struct dentry *root = sb->s_root;
> -	struct inode *inode = root->d_inode;
> -	int rc = 0;
> +	const struct superblock_security_struct *oldsbsec = oldsb->s_security;
> +	struct superblock_security_struct *newsbsec = newsb->s_security;
>  
> -	mutex_lock(&sbsec->lock);
> -	if (sbsec->initialized)
> -		goto out;
> +	int set_fscontext =	(oldsbsec->flags & FSCONTEXT_MNT);
> +	int set_context =	(oldsbsec->flags & CONTEXT_MNT);
> +	int set_rootcontext =	(oldsbsec->flags & ROOTCONTEXT_MNT);
>  
> -	if (!ss_initialized) {
> -		/* Defer initialization until selinux_complete_init,
> -		   after the initial policy is loaded and the security
> -		   server is ready to handle calls. */
> -		spin_lock(&sb_security_lock);
> -		if (list_empty(&sbsec->list))
> -			list_add(&sbsec->list, &superblock_security_head);
> -		spin_unlock(&sb_security_lock);
> -		goto out;
> +	/* we can't error, we can't save the info, this shouldn't get called
> +	 * this early in the boot process. */
> +	BUG_ON(!ss_initialized);
> +
> +	/* this might go away sometime down the line if there is a new user
> +	 * of clone, but for now, nfs better not get here... */
> +	BUG_ON(newsbsec->initialized);
> +
> +	/* how can we clone if the old one wasn't set up?? */
> +	BUG_ON(!oldsbsec->initialized);
> +
> +	mutex_lock(&newsbsec->lock);
> +
> +	newsbsec->flags = oldsbsec->flags;
> +
> +	newsbsec->sid = oldsbsec->sid;
> +	newsbsec->def_sid = oldsbsec->def_sid;
> +	newsbsec->behavior = oldsbsec->behavior;
> +
> +	if (set_context) {
> +		u32 sid = oldsbsec->mntpoint_sid;
> +
> +		if (!set_fscontext)
> +			newsbsec->sid = sid;
> +		if (!set_rootcontext) {
> +			struct inode *newinode = newsb->s_root->d_inode;
> +			struct inode_security_struct *newisec = newinode->i_security;
> +			newisec->sid = sid;
> +		}
> +		newsbsec->mntpoint_sid = sid;
>  	}
> +	if (set_rootcontext) {
> +		const struct inode *oldinode = oldsb->s_root->d_inode;
> +		const struct inode_security_struct *oldisec = oldinode->i_security;
> +		struct inode *newinode = newsb->s_root->d_inode;
> +		struct inode_security_struct *newisec = newinode->i_security;
>  
> -	/* Determine the labeling behavior to use for this filesystem type. */
> -	rc = security_fs_use(sb->s_type->name, &sbsec->behavior, &sbsec->sid);
> -	if (rc) {
> -		printk(KERN_WARNING "%s:  security_fs_use(%s) returned %d\n",
> -		       __FUNCTION__, sb->s_type->name, rc);
> -		goto out;
> +		newisec->sid = oldisec->sid;
>  	}
>  
> -	rc = try_context_mount(sb, data);
> -	if (rc)
> +	sb_finish_set_opts(newsb);
> +	mutex_unlock(&newsbsec->lock);
> +}
> +
> +/*
> + * string mount options parsing and call set the sbsec
> + */
> +static int superblock_doinit(struct super_block *sb, void *data)
> +{
> +	char *context = NULL, *defcontext = NULL;
> +	char *fscontext = NULL, *rootcontext = NULL;
> +	int rc = 0;
> +	char *p, *options = data;
> +	/* selinux only know about a fixed number of mount options */
> +	char *mnt_opts[NUM_SEL_MNT_OPTS];
> +	int mnt_opts_flags[NUM_SEL_MNT_OPTS], num_mnt_opts = 0;
> +
> +	if (!data)
>  		goto out;
>  
> -	if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
> -		/* Make sure that the xattr handler exists and that no
> -		   error other than -ENODATA is returned by getxattr on
> -		   the root directory.  -ENODATA is ok, as this may be
> -		   the first boot of the SELinux kernel before we have
> -		   assigned xattr values to the filesystem. */
> -		if (!inode->i_op->getxattr) {
> -			printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
> -			       "xattr support\n", sb->s_id, sb->s_type->name);
> -			rc = -EOPNOTSUPP;
> -			goto out;
> -		}
> -		rc = inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0);
> -		if (rc < 0 && rc != -ENODATA) {
> -			if (rc == -EOPNOTSUPP)
> -				printk(KERN_WARNING "SELinux: (dev %s, type "
> -				       "%s) has no security xattr handler\n",
> -				       sb->s_id, sb->s_type->name);
> -			else
> -				printk(KERN_WARNING "SELinux: (dev %s, type "
> -				       "%s) getxattr errno %d\n", sb->s_id,
> -				       sb->s_type->name, -rc);
> +	/* with the nfs patch this will become a goto out; */
> +	if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA) {
> +		const char *name = sb->s_type->name;
> +		/* NFS we understand. */
> +		if (!strcmp(name, "nfs")) {
> +			struct nfs_mount_data *d = data;
> +
> +			if (d->version !=  NFS_MOUNT_VERSION)
> +				goto out;
> +
> +			if (d->context[0]) {
> +				context = kstrdup(d->context, GFP_KERNEL);
> +				if (!context) {
> +					rc = -ENOMEM;
> +					goto out;
> +				}
> +			}
> +			goto build_flags;
> +		} else
>  			goto out;
> -		}
>  	}
>  
> -	if (strcmp(sb->s_type->name, "proc") == 0)
> -		sbsec->proc = 1;
> +	/* Standard string-based options. */
> +	while ((p = strsep(&options, "|")) != NULL) {
> +		int token;
> +		substring_t args[MAX_OPT_ARGS];
>  
> -	sbsec->initialized = 1;
> +		if (!*p)
> +			continue;
>  
> -	if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) {
> -		printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown
> behavior\n",
> -		       sb->s_id, sb->s_type->name);
> -	}
> -	else {
> -		printk(KERN_DEBUG "SELinux: initialized (dev %s, type %s), %s\n",
> -		       sb->s_id, sb->s_type->name,
> -		       labeling_behaviors[sbsec->behavior-1]);
> -	}
> +		token = match_token(p, tokens, args);
>  
> -	/* Initialize the root inode. */
> -	rc = inode_doinit_with_dentry(sb->s_root->d_inode, sb->s_root);
> +		switch (token) {
> +		case Opt_context:
> +			if (context || defcontext) {
> +				rc = -EINVAL;
> +				printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
> +				goto out_err;
> +			}
> +			context = match_strdup(&args[0]);
> +			if (!context) {
> +				rc = -ENOMEM;
> +				goto out_err;
> +			}
> +			break;
> +
> +		case Opt_fscontext:
> +			if (fscontext) {
> +				rc = -EINVAL;
> +				printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
> +				goto out_err;
> +			}
> +			fscontext = match_strdup(&args[0]);
> +			if (!fscontext) {
> +				rc = -ENOMEM;
> +				goto out_err;
> +			}
> +			break;
> +
> +		case Opt_rootcontext:
> +			if (rootcontext) {
> +				rc = -EINVAL;
> +				printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
> +				goto out_err;
> +			}
> +			rootcontext = match_strdup(&args[0]);
> +			if (!rootcontext) {
> +				rc = -ENOMEM;
> +				goto out_err;
> +			}
> +			break;
> +
> +		case Opt_defcontext:
> +			if (context || defcontext) {
> +				rc = -EINVAL;
> +				printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
> +				goto out_err;
> +			}
> +			defcontext = match_strdup(&args[0]);
> +			if (!defcontext) {
> +				rc = -ENOMEM;
> +				goto out_err;
> +			}
> +			break;
> +
> +		default:
> +			rc = -EINVAL;
> +			printk(KERN_WARNING "SELinux:  unknown mount option\n");
> +			goto out_err;
>  
> -	/* Initialize any other inodes associated with the superblock, e.g.
> -	   inodes created prior to initial policy load or inodes created
> -	   during get_sb by a pseudo filesystem that directly
> -	   populates itself. */
> -	spin_lock(&sbsec->isec_lock);
> -next_inode:
> -	if (!list_empty(&sbsec->isec_head)) {
> -		struct inode_security_struct *isec =
> -				list_entry(sbsec->isec_head.next,
> -				           struct inode_security_struct, list);
> -		struct inode *inode = isec->inode;
> -		spin_unlock(&sbsec->isec_lock);
> -		inode = igrab(inode);
> -		if (inode) {
> -			if (!IS_PRIVATE (inode))
> -				inode_doinit(inode);
> -			iput(inode);
>  		}
> -		spin_lock(&sbsec->isec_lock);
> -		list_del_init(&isec->list);
> -		goto next_inode;
>  	}
> -	spin_unlock(&sbsec->isec_lock);
> +
> +build_flags:
> +	if (fscontext) {
> +		mnt_opts[num_mnt_opts] = fscontext;
> +		mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT;
> +	}
> +	if (context) {
> +		mnt_opts[num_mnt_opts] = context;
> +		mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT;
> +	}
> +	if (rootcontext) {
> +		mnt_opts[num_mnt_opts] = rootcontext;
> +		mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT;
> +	}
> +	if (defcontext) {
> +		mnt_opts[num_mnt_opts] = defcontext;
> +		mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT;
> +	}
> +
>  out:
> -	mutex_unlock(&sbsec->lock);
> +	rc = selinux_set_mnt_opts(sb, mnt_opts, mnt_opts_flags, num_mnt_opts);
> +out_err:
> +	kfree(context);
> +	kfree(defcontext);
> +	kfree(fscontext);
> +	kfree(rootcontext);
>  	return rc;
>  }
>  
> @@ -4800,6 +5038,9 @@ static struct security_operations selinux_ops = {
>  	.sb_statfs =			selinux_sb_statfs,
>  	.sb_mount =			selinux_mount,
>  	.sb_umount =			selinux_umount,
> +	.sb_get_mnt_opts =		selinux_get_mnt_opts,
> +	.sb_set_mnt_opts =		selinux_set_mnt_opts,
> +	.sb_clone_mnt_opts = 		selinux_sb_clone_mnt_opts,
>  
>  	.inode_alloc_security =		selinux_inode_alloc_security,
>  	.inode_free_security =		selinux_inode_free_security,
> diff --git a/security/selinux/include/objsec.h
> b/security/selinux/include/objsec.h
> index 642a9fd..4138a80 100644
> --- a/security/selinux/include/objsec.h
> +++ b/security/selinux/include/objsec.h
> @@ -65,6 +65,7 @@ struct superblock_security_struct {
>  	u32 mntpoint_sid;		/* SECURITY_FS_USE_MNTPOINT context for files */
>  	unsigned int behavior;          /* labeling behavior */
>  	unsigned char initialized;      /* initialization flag */
> +	unsigned char flags;		/* which mount options were specified */
>  	unsigned char proc;             /* proc fs */
>  	struct mutex lock;
>  	struct list_head isec_head;
> 
> 
> 
> 


Casey Schaufler
casey@schaufler-ca.com

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply

* Re: [PATCH -v3] SELinux: Add get, set, and cloning of superblock security information
From: Casey Schaufler @ 2007-11-09 22:46 UTC (permalink / raw)
  To: Eric Paris, selinux, LSM List, linux-fsdevel
  Cc: sds, jmorris, Casey Schaufler
In-Reply-To: <1194646937.4627.30.camel@localhost.localdomain>


--- Eric Paris <eparis@redhat.com> wrote:

> Adds security_get_sb_mnt_opts, security_set_sb_mnt_opts, and
> security_clont_sb_mnt_opts to the LSM and to SELinux.  This will allow
> filesystems to directly own and control all of their mount options if
> they so choose.

I understand why you would want get_sb_mnt_opts(), but what
is the value for set_sb_mnt_opts() and what is the purpose of
clone_sb_mnt_opts()?

> This interface deals only with option identifiers and
> strings so it should generic enough for any LSM which may come in the
> future.  Filesystems which pass text mount data around in the kernel
> (almost all of them) need not currently make use of this interface for
> SELinux sake since it will still parse those strings as it always has.

If SELinux is still dealing with strings on it's own what is
the point of these hooks?

> An LSM would need to implement these functions only if they had mount
> time options, such as selinux has context= or fscontext=.  If the LSM
> has no mount time options they could simply not implement and let the
> dummy ops take care of things.  

Smack and SELinux currently deal with options in sb_kern_mount(), with
help from sb_copy_data(). Why change the implementation?

> A LSM other than SELinux would need to define new option numbers in
> security.h

I don't think it is a good idea to require that LSM specific
information be stored outside the scope of the LSM.

> (or could reuse if they have the same basic meaning I guess)
> and any FS which decides to own there own security options would need to
> be patched to use this new interface for every possible LSM.  This is
> because it was stated to me very clearly that LSM's should not attempt
> to understand FS mount data and the burdon to understand security should
> be in the FS which owns the options.

Perhaps a mount option prefix then. "Smack.root", "SELinux.context",
that sort of thing. An LSM writer shouldn't have to patch security.h
every time she wants to add a mount option.

> Signed-off-by: Eric Paris <eparis@redhat.com>
> 
> ---
> 
> For now the only forseen user of this interface is NFS.  NFS uses a
> binary blob in kernel for mount data (it uses this blob irrespective of
> the binary vs. text mount options it can get from userspace.)  NFS must
> then set its own mount options explicitly so we need some interface for
> it to do so.
> 
> 
>  include/linux/security.h          |   36 ++
>  security/dummy.c                  |   26 ++
>  security/security.c               |   20 +
>  security/selinux/hooks.c          |  749
> ++++++++++++++++++++++++-------------
>  security/selinux/include/objsec.h |    1 +
>  5 files changed, 578 insertions(+), 254 deletions(-)
> 
> diff --git a/include/linux/security.h b/include/linux/security.h
> index ac05083..dcbb792 100644
> --- a/include/linux/security.h
> +++ b/include/linux/security.h
> @@ -34,6 +34,12 @@
>  #include <linux/xfrm.h>
>  #include <net/flow.h>
>  
> +/* only a char in selinux superblock security struct flags */
> +#define FSCONTEXT_MNT		0x01
> +#define CONTEXT_MNT		0x02
> +#define ROOTCONTEXT_MNT		0x04
> +#define DEFCONTEXT_MNT		0x08
> +
>  /*
>   * Bounding set
>   */
> @@ -261,6 +267,22 @@ struct request_sock;
>   *	Update module state after a successful pivot.
>   *	@old_nd contains the nameidata structure for the old root.
>   *      @new_nd contains the nameidata structure for the new root.
> + * @sb_get_mnt_opts:
> + *      Get the security relevant mount options used for a superblock
> + *      @sb the superblock to get security mount options from
> + *      @mount_options array for pointers to mount options
> + *      @mount_flags array of ints specifying what each mount options is
> + *      @num_opts number of options in the arrays
> + * @sb_set_mnt_opts:
> + *      Set the security relevant mount options used for a superblock
> + *      @sb the superblock to set security mount options for
> + *      @mount_options array for pointers to mount options
> + *      @mount_flags array of ints specifying what each mount options is
> + *      @num_opts number of options in the arrays
> + * @sb_clone_mnt_opts:
> + *	Copy all security options from a given superblock to another
> + *	@oldsb old superblock which contain information to clone
> + *	@newsb new superblock which needs filled in
>   *
>   * Security hooks for inode operations.
>   *
> @@ -1242,6 +1264,13 @@ struct security_operations {
>  			     struct nameidata * new_nd);
>  	void (*sb_post_pivotroot) (struct nameidata * old_nd,
>  				   struct nameidata * new_nd);
> +	int (*sb_get_mnt_opts) (const struct super_block *sb,
> +				char ***mount_options, int **flags,
> +				int *num_opts);
> +	int (*sb_set_mnt_opts) (struct super_block *sb, char **mount_options,
> +				int *flags, int num_opts);
> +	void (*sb_clone_mnt_opts) (const struct super_block *oldsb,
> +				   struct super_block *newsb);
>  
>  	int (*inode_alloc_security) (struct inode *inode);	
>  	void (*inode_free_security) (struct inode *inode);
> @@ -1499,6 +1528,13 @@ void security_sb_post_mountroot(void);
>  void security_sb_post_addmount(struct vfsmount *mnt, struct nameidata
> *mountpoint_nd);
>  int security_sb_pivotroot(struct nameidata *old_nd, struct nameidata
> *new_nd);
>  void security_sb_post_pivotroot(struct nameidata *old_nd, struct nameidata
> *new_nd);
> +int security_sb_get_mnt_opts(const struct super_block *sb, char
> ***mount_options,
> +			     int **flags, int *num_opts);
> +int security_sb_set_mnt_opts(struct super_block *sb, char **mount_options,
> +			     int *flags, int num_opts);
> +void security_sb_clone_mnt_opts(const struct super_block *oldsb,
> +				struct super_block *newsb);
> +
>  int security_inode_alloc(struct inode *inode);
>  void security_inode_free(struct inode *inode);
>  int security_inode_init_security(struct inode *inode, struct inode *dir,
> diff --git a/security/dummy.c b/security/dummy.c
> index 6d895ad..22d9663 100644
> --- a/security/dummy.c
> +++ b/security/dummy.c
> @@ -245,6 +245,29 @@ static void dummy_sb_post_pivotroot (struct nameidata
> *old_nd, struct nameidata
>  	return;
>  }
>  
> +static int dummy_sb_get_mnt_opts(const struct super_block *sb, char
> ***mount_options,
> +				 int **flags, int *num_opts)
> +{
> +	*mount_options = NULL;
> +	*flags = NULL;
> +	*num_opts = 0;
> +	return 0;
> +}
> +
> +static int dummy_sb_set_mnt_opts(struct super_block *sb, char
> **mount_options,
> +				 int *flags, int num_opts)
> +{
> +	if (unlikely(num_opts))
> +		return -EOPNOTSUPP;
> +	return 0;
> +}
> +
> +static void dummy_sb_clone_mnt_opts(const struct super_block *oldsb,
> +				    struct super_block *newsb)
> +{
> +	return;
> +}
> +
>  static int dummy_inode_alloc_security (struct inode *inode)
>  {
>  	return 0;
> @@ -998,6 +1021,9 @@ void security_fixup_ops (struct security_operations
> *ops)
>  	set_to_dummy_if_null(ops, sb_post_addmount);
>  	set_to_dummy_if_null(ops, sb_pivotroot);
>  	set_to_dummy_if_null(ops, sb_post_pivotroot);
> +	set_to_dummy_if_null(ops, sb_get_mnt_opts);
> +	set_to_dummy_if_null(ops, sb_set_mnt_opts);
> +	set_to_dummy_if_null(ops, sb_clone_mnt_opts);
>  	set_to_dummy_if_null(ops, inode_alloc_security);
>  	set_to_dummy_if_null(ops, inode_free_security);
>  	set_to_dummy_if_null(ops, inode_init_security);
> diff --git a/security/security.c b/security/security.c
> index 0e1f1f1..f48fb30 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -308,6 +308,26 @@ void security_sb_post_pivotroot(struct nameidata
> *old_nd, struct nameidata *new_
>  	security_ops->sb_post_pivotroot(old_nd, new_nd);
>  }
>  
> +int security_sb_get_mnt_opts (const struct super_block *sb,
> +			      char ***mount_options,
> +			      int **flags, int *num_opts)
> +{
> +	return security_ops->sb_get_mnt_opts(sb, mount_options, flags, num_opts);
> +}
> +
> +int security_sb_set_mnt_opts (struct super_block *sb,
> +			      char **mount_options,
> +			      int *flags, int num_opts)
> +{
> +	return security_ops->sb_set_mnt_opts(sb, mount_options, flags, num_opts);
> +}
> +
> +void security_sb_clone_mnt_opts(const struct super_block *oldsb,
> +				struct super_block *newsb)
> +{
> +	security_ops->sb_clone_mnt_opts(oldsb, newsb);
> +}
> +
>  int security_inode_alloc(struct inode *inode)
>  {
>  	inode->i_security = NULL;
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 9f3124b..e710764 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -82,6 +82,8 @@
>  #define XATTR_SELINUX_SUFFIX "selinux"
>  #define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX
>  
> +#define NUM_SEL_MNT_OPTS 4
> +
>  extern unsigned int policydb_loaded_version;
>  extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);
>  extern int selinux_compat_net;
> @@ -321,8 +323,8 @@ enum {
>  	Opt_error = -1,
>  	Opt_context = 1,
>  	Opt_fscontext = 2,
> -	Opt_defcontext = 4,
> -	Opt_rootcontext = 8,
> +	Opt_defcontext = 3,
> +	Opt_rootcontext = 4,
>  };
>  
>  static match_table_t tokens = {
> @@ -366,150 +368,318 @@ static int may_context_mount_inode_relabel(u32 sid,
>  	return rc;
>  }
>  
> -static int try_context_mount(struct super_block *sb, void *data)
> +static int sb_finish_set_opts(struct super_block *sb)
>  {
> -	char *context = NULL, *defcontext = NULL;
> -	char *fscontext = NULL, *rootcontext = NULL;
> -	const char *name;
> -	u32 sid;
> -	int alloc = 0, rc = 0, seen = 0;
> -	struct task_security_struct *tsec = current->security;
>  	struct superblock_security_struct *sbsec = sb->s_security;
> +	struct dentry *root = sb->s_root;
> +	struct inode *root_inode = root->d_inode;
> +	int rc = 0;
>  
> -	if (!data)
> -		goto out;
> +	if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
> +		/* Make sure that the xattr handler exists and that no
> +		   error other than -ENODATA is returned by getxattr on
> +		   the root directory.  -ENODATA is ok, as this may be
> +		   the first boot of the SELinux kernel before we have
> +		   assigned xattr values to the filesystem. */
> +		if (!root_inode->i_op->getxattr) {
> +			printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
> +			       "xattr support\n", sb->s_id, sb->s_type->name);
> +			rc = -EOPNOTSUPP;
> +			goto out;
> +		}
> +		rc = root_inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0);
> +		if (rc < 0 && rc != -ENODATA) {
> +			if (rc == -EOPNOTSUPP)
> +				printk(KERN_WARNING "SELinux: (dev %s, type "
> +				       "%s) has no security xattr handler\n",
> +				       sb->s_id, sb->s_type->name);
> +			else
> +				printk(KERN_WARNING "SELinux: (dev %s, type "
> +				       "%s) getxattr errno %d\n", sb->s_id,
> +				       sb->s_type->name, -rc);
> +			goto out;
> +		}
> +	}
>  
> -	name = sb->s_type->name;
> +	sbsec->initialized = 1;
>  
> -	if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA) {
> +	if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) {
> +		printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown
> behavior\n",
> +		       sb->s_id, sb->s_type->name);
> +	}
> +	else {
> +		printk(KERN_DEBUG "SELinux: initialized (dev %s, type %s), %s\n",
> +		       sb->s_id, sb->s_type->name,
> +		       labeling_behaviors[sbsec->behavior-1]);
> +	}
>  
> -		/* NFS we understand. */
> -		if (!strcmp(name, "nfs")) {
> -			struct nfs_mount_data *d = data;
> +	/* Initialize the root inode. */
> +	rc = inode_doinit_with_dentry(root_inode, root);
>  
> -			if (d->version <  NFS_MOUNT_VERSION)
> -				goto out;
> +	/* Initialize any other inodes associated with the superblock, e.g.
> +	   inodes created prior to initial policy load or inodes created
> +	   during get_sb by a pseudo filesystem that directly
> +	   populates itself. */
> +	spin_lock(&sbsec->isec_lock);
> +next_inode:
> +	if (!list_empty(&sbsec->isec_head)) {
> +		struct inode_security_struct *isec =
> +				list_entry(sbsec->isec_head.next,
> +					   struct inode_security_struct, list);
> +		struct inode *inode = isec->inode;
> +		spin_unlock(&sbsec->isec_lock);
> +		inode = igrab(inode);
> +		if (inode) {
> +			if (!IS_PRIVATE (inode))
> +				inode_doinit(inode);
> +			iput(inode);
> +		}
> +		spin_lock(&sbsec->isec_lock);
> +		list_del_init(&isec->list);
> +		goto next_inode;
> +	}
> +	spin_unlock(&sbsec->isec_lock);
> +out:
> +	return rc;
> +}
>  
> -			if (d->context[0]) {
> -				context = d->context;
> -				seen |= Opt_context;
> -			}
> -		} else
> -			goto out;
> +/*
> + * This function should allow an FS to ask what it's mount security
> + * options were so it can use those later for submounts, displaying
> + * mount options, or whatever.
> + */
> +static int selinux_get_mnt_opts(const struct super_block *sb,
> +				char ***mount_options, int **mnt_opts_flags,
> +				int *num_opts)
> +{
> +	int rc = 0, i;
> +	struct superblock_security_struct *sbsec = sb->s_security;
> +	char *context = NULL;
> +	u32 len;
> +	char tmp; 
>  
> -	} else {
> -		/* Standard string-based options. */
> -		char *p, *options = data;
> +	*num_opts = 0;
> +	*mount_options = NULL;
> +	*mnt_opts_flags = NULL;
>  
> -		while ((p = strsep(&options, "|")) != NULL) {
> -			int token;
> -			substring_t args[MAX_OPT_ARGS];
> +	if (!sbsec->initialized)
> +		return -EINVAL;
>  
> -			if (!*p)
> -				continue;
> +	if (!ss_initialized)
> +		return -EINVAL;
>  
> -			token = match_token(p, tokens, args);
> +	/* 
> +	 * if we ever use sbsec flags for anything other than tracking mount
> +	 * settings this is going to need a mask
> +	 */
> +	tmp = sbsec->flags;
> +	/* count the number of mount options for this sb */
> +	for(i = 0; i < 8; i++) {
> +		if (tmp & 0x01)
> +			(*num_opts)++;
> +		tmp >>= 1;
> +	}
>  
> -			switch (token) {
> -			case Opt_context:
> -				if (seen & (Opt_context|Opt_defcontext)) {
> -					rc = -EINVAL;
> -					printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
> -					goto out_free;
> -				}
> -				context = match_strdup(&args[0]);
> -				if (!context) {
> -					rc = -ENOMEM;
> -					goto out_free;
> -				}
> -				if (!alloc)
> -					alloc = 1;
> -				seen |= Opt_context;
> -				break;
> +	*mount_options = kcalloc(*num_opts, sizeof(char *), GFP_ATOMIC);
> +	if (!*mount_options) {
> +		rc = -ENOMEM;
> +		goto out_free;
> +	}
>  
> -			case Opt_fscontext:
> -				if (seen & Opt_fscontext) {
> -					rc = -EINVAL;
> -					printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
> -					goto out_free;
> -				}
> -				fscontext = match_strdup(&args[0]);
> -				if (!fscontext) {
> -					rc = -ENOMEM;
> -					goto out_free;
> -				}
> -				if (!alloc)
> -					alloc = 1;
> -				seen |= Opt_fscontext;
> -				break;
> +	*mnt_opts_flags = kcalloc(*num_opts, sizeof(int), GFP_ATOMIC);
> +	if (!*mnt_opts_flags) {
> +		rc = -ENOMEM;
> +		goto out_free;
> +	}
>  
> -			case Opt_rootcontext:
> -				if (seen & Opt_rootcontext) {
> -					rc = -EINVAL;
> -					printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
> -					goto out_free;
> -				}
> -				rootcontext = match_strdup(&args[0]);
> -				if (!rootcontext) {
> -					rc = -ENOMEM;
> -					goto out_free;
> -				}
> -				if (!alloc)
> -					alloc = 1;
> -				seen |= Opt_rootcontext;
> -				break;
> +	i = 0;
> +	if (sbsec->flags & FSCONTEXT_MNT) {
> +		rc = security_sid_to_context(sbsec->sid, &context, &len);
> +		if (rc)
> +			goto out_free;
> +		(*mount_options)[i] = context;
> +		(*mnt_opts_flags)[i++] = FSCONTEXT_MNT;
> +	}
> +	if (sbsec->flags & CONTEXT_MNT) {
> +		rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len);
> +		if (rc)
> +			goto out_free;
> +		(*mount_options)[i] = context;
> +		(*mnt_opts_flags)[i++] = CONTEXT_MNT;
> +	}
> +	if (sbsec->flags & DEFCONTEXT_MNT) {
> +		rc = security_sid_to_context(sbsec->def_sid, &context, &len);
> +		if (rc)
> +			goto out_free;
> +		(*mount_options)[i] = context;
> +		(*mnt_opts_flags)[i++] = DEFCONTEXT_MNT;
> +	}
> +	if (sbsec->flags & ROOTCONTEXT_MNT) {
> +		struct inode *root = sbsec->sb->s_root->d_inode;
> +		struct inode_security_struct *isec = root->i_security;
>  
> -			case Opt_defcontext:
> -				if (sbsec->behavior != SECURITY_FS_USE_XATTR) {
> -					rc = -EINVAL;
> -					printk(KERN_WARNING "SELinux:  "
> -					       "defcontext option is invalid "
> -					       "for this filesystem type\n");
> -					goto out_free;
> -				}
> -				if (seen & (Opt_context|Opt_defcontext)) {
> -					rc = -EINVAL;
> -					printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
> -					goto out_free;
> -				}
> -				defcontext = match_strdup(&args[0]);
> -				if (!defcontext) {
> -					rc = -ENOMEM;
> -					goto out_free;
> -				}
> -				if (!alloc)
> -					alloc = 1;
> -				seen |= Opt_defcontext;
> -				break;
> +		rc = security_sid_to_context(isec->sid, &context, &len);
> +		if (rc)
> +			goto out_free;
> +		(*mount_options)[i] = context;
> +		(*mnt_opts_flags)[i++] = ROOTCONTEXT_MNT;
> +	}
>  
> -			default:
> -				rc = -EINVAL;
> -				printk(KERN_WARNING "SELinux:  unknown mount "
> -				       "option\n");
> -				goto out_free;
> +	BUG_ON(i != *num_opts);
>  
> -			}
> -		}
> -	}
> +	return 0;
> +
> +out_free:
> +	/* don't leak context string if security_sid_to_context had an error */
> +	if(*mount_options && i)
> +		for (; i > 0; i--)
> +			kfree((*mount_options)[i-1]);
> +	kfree(*mount_options);
> +	*mount_options = NULL;
> +	kfree(*mnt_opts_flags);
> +	*mnt_opts_flags = NULL;
> +	*num_opts = 0;
> +	return rc;
> +}
> +
> +static int bad_option(struct superblock_security_struct *sbsec, char flag,
> +		      u32 old_sid, u32 new_sid)
> +{
> +	/* check if the old mount command had the same options */
> +	if (sbsec->initialized)
> +		if (!(sbsec->flags & flag) ||
> +		    (old_sid != new_sid))
> +			return 1;
> +
> +	/* check if we were passed the same options twice,
> +	 * aka someone passed context=a,context=b
> +	 */
> +	if (!sbsec->initialized)
> +		if (sbsec->flags & flag)
> +			return 1;
> +	return 0;
> +}
> +/*
> + * Allow filesystems with binary mount data to explicitly set mount point
> labeling.
> + */
> +int selinux_set_mnt_opts(struct super_block *sb, char **mount_options,
> +				 int *flags, int num_opts)
> +{
> +	int rc = 0, i;
> +	struct task_security_struct *tsec = current->security;
> +	struct superblock_security_struct *sbsec = sb->s_security;
> +	const char *name = sb->s_type->name;
> +	struct inode *inode = sbsec->sb->s_root->d_inode;
> +	struct inode_security_struct *root_isec = inode->i_security;
> +	u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
> +	u32 defcontext_sid = 0;
> +
> +	mutex_lock(&sbsec->lock);
>  
> -	if (!seen)
> +	if (!ss_initialized) {
> +		if (!num_opts) {
> +			/* Defer initialization until selinux_complete_init,
> +		   	after the initial policy is loaded and the security
> +		   	server is ready to handle calls. */
> +			spin_lock(&sb_security_lock);
> +			if (list_empty(&sbsec->list))
> +				list_add(&sbsec->list, &superblock_security_head);
> +			spin_unlock(&sb_security_lock);
> +			goto out;
> +		}
> +		rc = -EINVAL;
> +		printk(KERN_WARNING "Unable to set superblock options before "
> +		       "the security server is initialized\n");
>  		goto out;
> +	}
>  
> -	/* sets the context of the superblock for the fs being mounted. */
> -	if (fscontext) {
> -		rc = security_context_to_sid(fscontext, strlen(fscontext), &sid);
> +	/* 
> +	 * parse the mount options, check if they are valid sids.
> +	 * also check if someone is trying to mount the same sb more
> +	 * than once with different security options.
> +	 */
> +	for(i = 0; i < num_opts; i++) {
> +		u32 sid;
> +		rc = security_context_to_sid(mount_options[i],
> +					     strlen(mount_options[i]), &sid);
>  		if (rc) {
>  			printk(KERN_WARNING "SELinux: security_context_to_sid"
>  			       "(%s) failed for (dev %s, type %s) errno=%d\n",
> -			       fscontext, sb->s_id, name, rc);
> -			goto out_free;
> +			       mount_options[i], sb->s_id, name, rc);
> +			goto out;
>  		}
> +		switch(flags[i]) {
> +		case FSCONTEXT_MNT:
> +			fscontext_sid = sid;
> +
> +			if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
> +					fscontext_sid))
> +				goto out_double_mount;
> +
> +			sbsec->flags |= FSCONTEXT_MNT;
> +			break;
> +		case CONTEXT_MNT:
> +			context_sid = sid;
> +
> +			if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
> +					context_sid))
> +				goto out_double_mount;
> +
> +			sbsec->flags |= CONTEXT_MNT;
> +			break;
> +		case ROOTCONTEXT_MNT:
> +			rootcontext_sid = sid;
> +
> +			if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
> +					rootcontext_sid))
> +				goto out_double_mount;
> +
> +			sbsec->flags |= ROOTCONTEXT_MNT;
> +
> +			break;
> +		case DEFCONTEXT_MNT:
> +			defcontext_sid = sid;
> +
> +			if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
> +					defcontext_sid))
> +				goto out_double_mount;
>  
> -		rc = may_context_mount_sb_relabel(sid, sbsec, tsec);
> +			sbsec->flags |= DEFCONTEXT_MNT;
> +
> +			break;
> +		default:
> +			rc = -EINVAL;
> +			goto out;
> +		}
> +	}
> +
> +	if (sbsec->initialized) {
> +		/* previously mounted with options, but not on this attempt? */
> +		if (sbsec->flags && !num_opts)
> +			goto out_double_mount;
> +		rc = 0;
> +		goto out;
> +	}
> +
> +	if (strcmp(sb->s_type->name, "proc") == 0)
> +		sbsec->proc = 1;
> +
> +	/* Determine the labeling behavior to use for this filesystem type. */
> +	rc = security_fs_use(sb->s_type->name, &sbsec->behavior, &sbsec->sid);
> +	if (rc) {
> +		printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n",
> +		       __FUNCTION__, sb->s_type->name, rc);
> +		goto out;
> +	}
> +
> +	/* sets the context of the superblock for the fs being mounted. */
> +	if (fscontext_sid) {
> +
> +		rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, tsec);
>  		if (rc)
> -			goto out_free;
> +			goto out;
>  
> -		sbsec->sid = sid;
> +		sbsec->sid = fscontext_sid;
>  	}
>  
>  	/*
> @@ -517,182 +687,250 @@ static int try_context_mount(struct super_block *sb,
> void *data)
>  	 * sets the label used on all file below the mountpoint, and will set
>  	 * the superblock context if not already set.
>  	 */
> -	if (context) {
> -		rc = security_context_to_sid(context, strlen(context), &sid);
> -		if (rc) {
> -			printk(KERN_WARNING "SELinux: security_context_to_sid"
> -			       "(%s) failed for (dev %s, type %s) errno=%d\n",
> -			       context, sb->s_id, name, rc);
> -			goto out_free;
> -		}
> -
> -		if (!fscontext) {
> -			rc = may_context_mount_sb_relabel(sid, sbsec, tsec);
> +	if (context_sid) {
> +		if (!fscontext_sid) {
> +			rc = may_context_mount_sb_relabel(context_sid, sbsec, tsec);
>  			if (rc)
> -				goto out_free;
> -			sbsec->sid = sid;
> +				goto out;
> +			sbsec->sid = context_sid;
>  		} else {
> -			rc = may_context_mount_inode_relabel(sid, sbsec, tsec);
> +			rc = may_context_mount_inode_relabel(context_sid, sbsec, tsec);
>  			if (rc)
> -				goto out_free;
> +				goto out;
>  		}
> -		sbsec->mntpoint_sid = sid;
> +		if (!rootcontext_sid)
> +			rootcontext_sid = context_sid;
>  
> +		sbsec->mntpoint_sid = context_sid;
>  		sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
>  	}
>  
> -	if (rootcontext) {
> -		struct inode *inode = sb->s_root->d_inode;
> -		struct inode_security_struct *isec = inode->i_security;
> -		rc = security_context_to_sid(rootcontext, strlen(rootcontext), &sid);
> -		if (rc) {
> -			printk(KERN_WARNING "SELinux: security_context_to_sid"
> -			       "(%s) failed for (dev %s, type %s) errno=%d\n",
> -			       rootcontext, sb->s_id, name, rc);
> -			goto out_free;
> -		}
> -
> -		rc = may_context_mount_inode_relabel(sid, sbsec, tsec);
> +	if (rootcontext_sid) {
> +		rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec, tsec);
>  		if (rc)
> -			goto out_free;
> +			goto out;
>  
> -		isec->sid = sid;
> -		isec->initialized = 1;
> +		root_isec->sid = rootcontext_sid;
> +		root_isec->initialized = 1;
>  	}
>  
> -	if (defcontext) {
> -		rc = security_context_to_sid(defcontext, strlen(defcontext), &sid);
> -		if (rc) {
> -			printk(KERN_WARNING "SELinux: security_context_to_sid"
> -			       "(%s) failed for (dev %s, type %s) errno=%d\n",
> -			       defcontext, sb->s_id, name, rc);
> -			goto out_free;
> +	if (defcontext_sid) {
> +		if (sbsec->behavior != SECURITY_FS_USE_XATTR) {
> +			rc = -EINVAL;
> +			printk(KERN_WARNING "SELinux: defcontext option is "
> +			       "invalid for this filesystem type\n");
> +			goto out;
>  		}
>  
> -		if (sid == sbsec->def_sid)
> -			goto out_free;
> -
> -		rc = may_context_mount_inode_relabel(sid, sbsec, tsec);
> -		if (rc)
> -			goto out_free;
> +		if (defcontext_sid != sbsec->def_sid) {
> +			rc = may_context_mount_inode_relabel(defcontext_sid,
> +							     sbsec, tsec);
> +			if (rc)
> +				goto out;
> +		}
>  
> -		sbsec->def_sid = sid;
> +		sbsec->def_sid = defcontext_sid;
>  	}
>  
> -out_free:
> -	if (alloc) {
> -		kfree(context);
> -		kfree(defcontext);
> -		kfree(fscontext);
> -		kfree(rootcontext);
> -	}
> +	rc = sb_finish_set_opts(sb);
>  out:
> +	mutex_unlock(&sbsec->lock);
>  	return rc;
> +out_double_mount:
> +	rc = -EINVAL;
> +	printk(KERN_WARNING "SELinux: mount invalid.  Same superblock, different "
> +	       "security settings for (dev %s, type %s)\n", sb->s_id, name);
> +	goto out;
>  }
>  
> -static int superblock_doinit(struct super_block *sb, void *data)
> +static void selinux_sb_clone_mnt_opts (const struct super_block *oldsb,
> +					struct super_block *newsb)
>  {
> -	struct superblock_security_struct *sbsec = sb->s_security;
> -	struct dentry *root = sb->s_root;
> -	struct inode *inode = root->d_inode;
> -	int rc = 0;
> +	const struct superblock_security_struct *oldsbsec = oldsb->s_security;
> +	struct superblock_security_struct *newsbsec = newsb->s_security;
>  
> -	mutex_lock(&sbsec->lock);
> -	if (sbsec->initialized)
> -		goto out;
> +	int set_fscontext =	(oldsbsec->flags & FSCONTEXT_MNT);
> +	int set_context =	(oldsbsec->flags & CONTEXT_MNT);
> +	int set_rootcontext =	(oldsbsec->flags & ROOTCONTEXT_MNT);
>  
> -	if (!ss_initialized) {
> -		/* Defer initialization until selinux_complete_init,
> -		   after the initial policy is loaded and the security
> -		   server is ready to handle calls. */
> -		spin_lock(&sb_security_lock);
> -		if (list_empty(&sbsec->list))
> -			list_add(&sbsec->list, &superblock_security_head);
> -		spin_unlock(&sb_security_lock);
> -		goto out;
> +	/* we can't error, we can't save the info, this shouldn't get called
> +	 * this early in the boot process. */
> +	BUG_ON(!ss_initialized);
> +
> +	/* this might go away sometime down the line if there is a new user
> +	 * of clone, but for now, nfs better not get here... */
> +	BUG_ON(newsbsec->initialized);
> +
> +	/* how can we clone if the old one wasn't set up?? */
> +	BUG_ON(!oldsbsec->initialized);
> +
> +	mutex_lock(&newsbsec->lock);
> +
> +	newsbsec->flags = oldsbsec->flags;
> +
> +	newsbsec->sid = oldsbsec->sid;
> +	newsbsec->def_sid = oldsbsec->def_sid;
> +	newsbsec->behavior = oldsbsec->behavior;
> +
> +	if (set_context) {
> +		u32 sid = oldsbsec->mntpoint_sid;
> +
> +		if (!set_fscontext)
> +			newsbsec->sid = sid;
> +		if (!set_rootcontext) {
> +			struct inode *newinode = newsb->s_root->d_inode;
> +			struct inode_security_struct *newisec = newinode->i_security;
> +			newisec->sid = sid;
> +		}
> +		newsbsec->mntpoint_sid = sid;
>  	}
> +	if (set_rootcontext) {
> +		const struct inode *oldinode = oldsb->s_root->d_inode;
> +		const struct inode_security_struct *oldisec = oldinode->i_security;
> +		struct inode *newinode = newsb->s_root->d_inode;
> +		struct inode_security_struct *newisec = newinode->i_security;
>  
> -	/* Determine the labeling behavior to use for this filesystem type. */
> -	rc = security_fs_use(sb->s_type->name, &sbsec->behavior, &sbsec->sid);
> -	if (rc) {
> -		printk(KERN_WARNING "%s:  security_fs_use(%s) returned %d\n",
> -		       __FUNCTION__, sb->s_type->name, rc);
> -		goto out;
> +		newisec->sid = oldisec->sid;
>  	}
>  
> -	rc = try_context_mount(sb, data);
> -	if (rc)
> +	sb_finish_set_opts(newsb);
> +	mutex_unlock(&newsbsec->lock);
> +}
> +
> +/*
> + * string mount options parsing and call set the sbsec
> + */
> +static int superblock_doinit(struct super_block *sb, void *data)
> +{
> +	char *context = NULL, *defcontext = NULL;
> +	char *fscontext = NULL, *rootcontext = NULL;
> +	int rc = 0;
> +	char *p, *options = data;
> +	/* selinux only know about a fixed number of mount options */
> +	char *mnt_opts[NUM_SEL_MNT_OPTS];
> +	int mnt_opts_flags[NUM_SEL_MNT_OPTS], num_mnt_opts = 0;
> +
> +	if (!data)
>  		goto out;
>  
> -	if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
> -		/* Make sure that the xattr handler exists and that no
> -		   error other than -ENODATA is returned by getxattr on
> -		   the root directory.  -ENODATA is ok, as this may be
> -		   the first boot of the SELinux kernel before we have
> -		   assigned xattr values to the filesystem. */
> -		if (!inode->i_op->getxattr) {
> -			printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
> -			       "xattr support\n", sb->s_id, sb->s_type->name);
> -			rc = -EOPNOTSUPP;
> -			goto out;
> -		}
> -		rc = inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0);
> -		if (rc < 0 && rc != -ENODATA) {
> -			if (rc == -EOPNOTSUPP)
> -				printk(KERN_WARNING "SELinux: (dev %s, type "
> -				       "%s) has no security xattr handler\n",
> -				       sb->s_id, sb->s_type->name);
> -			else
> -				printk(KERN_WARNING "SELinux: (dev %s, type "
> -				       "%s) getxattr errno %d\n", sb->s_id,
> -				       sb->s_type->name, -rc);
> +	/* with the nfs patch this will become a goto out; */
> +	if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA) {
> +		const char *name = sb->s_type->name;
> +		/* NFS we understand. */
> +		if (!strcmp(name, "nfs")) {
> +			struct nfs_mount_data *d = data;
> +
> +			if (d->version !=  NFS_MOUNT_VERSION)
> +				goto out;
> +
> +			if (d->context[0]) {
> +				context = kstrdup(d->context, GFP_KERNEL);
> +				if (!context) {
> +					rc = -ENOMEM;
> +					goto out;
> +				}
> +			}
> +			goto build_flags;
> +		} else
>  			goto out;
> -		}
>  	}
>  
> -	if (strcmp(sb->s_type->name, "proc") == 0)
> -		sbsec->proc = 1;
> +	/* Standard string-based options. */
> +	while ((p = strsep(&options, "|")) != NULL) {
> +		int token;
> +		substring_t args[MAX_OPT_ARGS];
>  
> -	sbsec->initialized = 1;
> +		if (!*p)
> +			continue;
>  
> -	if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) {
> -		printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown
> behavior\n",
> -		       sb->s_id, sb->s_type->name);
> -	}
> -	else {
> -		printk(KERN_DEBUG "SELinux: initialized (dev %s, type %s), %s\n",
> -		       sb->s_id, sb->s_type->name,
> -		       labeling_behaviors[sbsec->behavior-1]);
> -	}
> +		token = match_token(p, tokens, args);
>  
> -	/* Initialize the root inode. */
> -	rc = inode_doinit_with_dentry(sb->s_root->d_inode, sb->s_root);
> +		switch (token) {
> +		case Opt_context:
> +			if (context || defcontext) {
> +				rc = -EINVAL;
> +				printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
> +				goto out_err;
> +			}
> +			context = match_strdup(&args[0]);
> +			if (!context) {
> +				rc = -ENOMEM;
> +				goto out_err;
> +			}
> +			break;
> +
> +		case Opt_fscontext:
> +			if (fscontext) {
> +				rc = -EINVAL;
> +				printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
> +				goto out_err;
> +			}
> +			fscontext = match_strdup(&args[0]);
> +			if (!fscontext) {
> +				rc = -ENOMEM;
> +				goto out_err;
> +			}
> +			break;
> +
> +		case Opt_rootcontext:
> +			if (rootcontext) {
> +				rc = -EINVAL;
> +				printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
> +				goto out_err;
> +			}
> +			rootcontext = match_strdup(&args[0]);
> +			if (!rootcontext) {
> +				rc = -ENOMEM;
> +				goto out_err;
> +			}
> +			break;
> +
> +		case Opt_defcontext:
> +			if (context || defcontext) {
> +				rc = -EINVAL;
> +				printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
> +				goto out_err;
> +			}
> +			defcontext = match_strdup(&args[0]);
> +			if (!defcontext) {
> +				rc = -ENOMEM;
> +				goto out_err;
> +			}
> +			break;
> +
> +		default:
> +			rc = -EINVAL;
> +			printk(KERN_WARNING "SELinux:  unknown mount option\n");
> +			goto out_err;
>  
> -	/* Initialize any other inodes associated with the superblock, e.g.
> -	   inodes created prior to initial policy load or inodes created
> -	   during get_sb by a pseudo filesystem that directly
> -	   populates itself. */
> -	spin_lock(&sbsec->isec_lock);
> -next_inode:
> -	if (!list_empty(&sbsec->isec_head)) {
> -		struct inode_security_struct *isec =
> -				list_entry(sbsec->isec_head.next,
> -				           struct inode_security_struct, list);
> -		struct inode *inode = isec->inode;
> -		spin_unlock(&sbsec->isec_lock);
> -		inode = igrab(inode);
> -		if (inode) {
> -			if (!IS_PRIVATE (inode))
> -				inode_doinit(inode);
> -			iput(inode);
>  		}
> -		spin_lock(&sbsec->isec_lock);
> -		list_del_init(&isec->list);
> -		goto next_inode;
>  	}
> -	spin_unlock(&sbsec->isec_lock);
> +
> +build_flags:
> +	if (fscontext) {
> +		mnt_opts[num_mnt_opts] = fscontext;
> +		mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT;
> +	}
> +	if (context) {
> +		mnt_opts[num_mnt_opts] = context;
> +		mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT;
> +	}
> +	if (rootcontext) {
> +		mnt_opts[num_mnt_opts] = rootcontext;
> +		mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT;
> +	}
> +	if (defcontext) {
> +		mnt_opts[num_mnt_opts] = defcontext;
> +		mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT;
> +	}
> +
>  out:
> -	mutex_unlock(&sbsec->lock);
> +	rc = selinux_set_mnt_opts(sb, mnt_opts, mnt_opts_flags, num_mnt_opts);
> +out_err:
> +	kfree(context);
> +	kfree(defcontext);
> +	kfree(fscontext);
> +	kfree(rootcontext);
>  	return rc;
>  }
>  
> @@ -4800,6 +5038,9 @@ static struct security_operations selinux_ops = {
>  	.sb_statfs =			selinux_sb_statfs,
>  	.sb_mount =			selinux_mount,
>  	.sb_umount =			selinux_umount,
> +	.sb_get_mnt_opts =		selinux_get_mnt_opts,
> +	.sb_set_mnt_opts =		selinux_set_mnt_opts,
> +	.sb_clone_mnt_opts = 		selinux_sb_clone_mnt_opts,
>  
>  	.inode_alloc_security =		selinux_inode_alloc_security,
>  	.inode_free_security =		selinux_inode_free_security,
> diff --git a/security/selinux/include/objsec.h
> b/security/selinux/include/objsec.h
> index 642a9fd..4138a80 100644
> --- a/security/selinux/include/objsec.h
> +++ b/security/selinux/include/objsec.h
> @@ -65,6 +65,7 @@ struct superblock_security_struct {
>  	u32 mntpoint_sid;		/* SECURITY_FS_USE_MNTPOINT context for files */
>  	unsigned int behavior;          /* labeling behavior */
>  	unsigned char initialized;      /* initialization flag */
> +	unsigned char flags;		/* which mount options were specified */
>  	unsigned char proc;             /* proc fs */
>  	struct mutex lock;
>  	struct list_head isec_head;
> 
> 
> 
> 


Casey Schaufler
casey@schaufler-ca.com

^ permalink raw reply

* + revert-capabilities-clean-up-file-capability-reading-checkpatch-fixes.patch added to -mm tree
From: akpm @ 2007-11-09 22:44 UTC (permalink / raw)
  To: mm-commits; +Cc: akpm, casey, chrisw, jmorris, morgan, sds, serue


The patch titled
     revert-capabilities-clean-up-file-capability-reading-checkpatch-fixes
has been added to the -mm tree.  Its filename is
     revert-capabilities-clean-up-file-capability-reading-checkpatch-fixes.patch

*** Remember to use Documentation/SubmitChecklist when testing your code ***

See http://www.zip.com.au/~akpm/linux/patches/stuff/added-to-mm.txt to find
out what to do about this

------------------------------------------------------
Subject: revert-capabilities-clean-up-file-capability-reading-checkpatch-fixes
From: Andrew Morton <akpm@linux-foundation.org>

ERROR: no space after that open parenthesis '('
#63: FILE: security/commoncap.c:209:
+		bprm->cap_permitted = to_cap_t( le32_to_cpu(caps[1]) );

ERROR: no space before that close parenthesis ')'
#63: FILE: security/commoncap.c:209:
+		bprm->cap_permitted = to_cap_t( le32_to_cpu(caps[1]) );

ERROR: no space after that open parenthesis '('
#64: FILE: security/commoncap.c:210:
+		bprm->cap_inheritable = to_cap_t( le32_to_cpu(caps[2]) );

ERROR: no space before that close parenthesis ')'
#64: FILE: security/commoncap.c:210:
+		bprm->cap_inheritable = to_cap_t( le32_to_cpu(caps[2]) );

total: 4 errors, 0 warnings, 71 lines checked
Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

Please run checkpatch prior to sending patches

Cc: Andrew Morgan <morgan@kernel.org>
Cc: Casey Schaufler <casey@schaufler-ca.com>
Cc: Chris Wright <chrisw@sous-sol.org>
Cc: James Morris <jmorris@namei.org>
Cc: Serge Hallyn <serue@us.ibm.com>
Cc: Stephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---

 security/commoncap.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff -puN security/commoncap.c~revert-capabilities-clean-up-file-capability-reading-checkpatch-fixes security/commoncap.c
--- a/security/commoncap.c~revert-capabilities-clean-up-file-capability-reading-checkpatch-fixes
+++ a/security/commoncap.c
@@ -206,8 +206,8 @@ static inline int cap_from_disk(__le32 *
 			bprm->cap_effective = true;
 		else
 			bprm->cap_effective = false;
-		bprm->cap_permitted = to_cap_t( le32_to_cpu(caps[1]) );
-		bprm->cap_inheritable = to_cap_t( le32_to_cpu(caps[2]) );
+		bprm->cap_permitted = to_cap_t(le32_to_cpu(caps[1]));
+		bprm->cap_inheritable = to_cap_t( le32_to_cpu(caps[2]));
 		return 0;
 	default:
 		return -EINVAL;
_

Patches currently in -mm which might be from akpm@linux-foundation.org are

proc-fix-proc_kill_inodes-to-kill-dentries-on-all-proc-superblocks-checkpatch-fixes.patch
acpi-make-acpi_procfs-default-to-y.patch
get_task_comm-return-the-result.patch
clone-prepare-to-recycle-clone_detached-and-clone_stopped.patch
acpi-enable-c3-power-state-on-dell-inspiron-8200-fix.patch
acpi-add-reboot-mechanism.patch
small-acpica-extension-to-be-able-to-store-the-name-of.patch
git-alsa.patch
working-3d-dri-intel-agpko-resume-for-i815-chip.patch
git-arm.patch
git-arm-fixup.patch
agk-dm-dm-ioctl-move-compat-code-fix.patch
unbork-gregkh-driver-kset-convert-sys-devices-to-use-kset_create-vioc.patch
unbork-gregkh-driver-kset-convert-sys-devices-to-use-kset_create-vioc-fix.patch
git-dvb.patch
git-hwmon.patch
ia64-slim-down-__clear_bit_unlock-checkpatch-fixes.patch
elantech-touchpad-driver-fix.patch
git-kvm.patch
git-libata-all.patch
drivers-ata-libata-ehc-fix-printk-warning.patch
pata_hpt37x-fix-outstanding-bug-reports-on-the-hpt374-and-37x-cable-detect-checkpatch-fixes.patch
ide-arm-hack.patch
git-mtd.patch
lmc_ioctl-dont-return-with-locks-held-fix.patch
git-netdev-all.patch
ucc_geth-fix-build-break-introduced-by-commit-09f75cd7bf13720738e6a196cc0107ce9a5bd5a0-checkpatch-fixes.patch
update-smc91x-driver-with-arm-versatile-board-info.patch
bluetooth-uninlining.patch
git-nfsd-fixup.patch
quirk_vialatency-omit-reading-pci-revision-id-checkpatch-fixes.patch
fix-build-breakage-if-sysfs-fix.patch
ips-trim-trailing-whitespace-checkpatch-fixes.patch
scsi-gdth-kill-unneeded-irq-argument-checkpatch-fixes.patch
scsi-fix-bugs-and-canonicalize-ncr5380_intr-drivers-checkpatch-fixes.patch
git-unionfs.patch
vfs-swap-do_ioctl-and-vfs_ioctl-names-fix.patch
git-wireless.patch
jiffies_round-jiffies_round_relative-conversion-rt2x00-checkpatch-fixes.patch
git-ipwireless_cs.patch
git-x86.patch
git-x86-fix-up.patch
git-x86-inlining-borkage.patch
oprofile-op_model_athalonc-support-for-amd-family10h-barcelona-performance-counters-checkpatch-fixes.patch
i386-and-x86_64-randomize-brk-fix.patch
x86-arch_register_cpu-section-fix.patch
mips-undo-locking-on-error-path-returns-checkpatch-fixes.patch
pidns-place-under-config_experimental-checkpatch-fixes.patch
fix-64kb-blocksize-in-ext3-directories-checkpatch-fixes.patch
file-capabilities-allow-sigcont-within-session-v2-checkpatch-fixes.patch
x86-disable-preemption-in-delay_tsc.patch
tty-fix-network-driver-interactions-with-tcget-set-checkpatch-fixes.patch
pagecache-zeroing-zero_user_segment-zero_user_segments-and-zero_user-fix.patch
pagecache-zeroing-zero_user_segment-zero_user_segments-and-zero_user-fix-2.patch
i386-resolve-dependency-of-asm-i386-pgtableh-on-highmemh-checkpatch-fixes.patch
slub-fix-coding-style-violations-checkpatch-fixes.patch
slub-provide-unique-end-marker-for-each-slab-fix.patch
slub-do-our-own-locking-via-slab_lock-and-slab_unlock-checkpatch-fixes.patch
bufferhead-revert-constructor-removal-checkpatch-fixes.patch
maps4-make-page-monitoring-proc-file-optional-fix.patch
hugetlb-split-alloc_huge_page-into-private-and-shared-components-checkpatch-fixes.patch
vmscan-give-referenced-active-and-unmapped-pages-a-second-trip-around-the-lru.patch
vm-dont-run-touch_buffer-during-buffercache-lookups.patch
revert-capabilities-clean-up-file-capability-reading.patch
revert-capabilities-clean-up-file-capability-reading-checkpatch-fixes.patch
pm-qos-infrastructure-and-interface.patch
pm-qos-infrastructure-and-interface-static-initialization-with-blocking-notifiers.patch
cris-build-fixes-atomich-needs-compilerh-fix.patch
cris-build-fixes-update-eth_v10c-ethernet-driver-fix.patch
cris-build-fixes-fixes-in-arch-cris-kernel-timec-checkpatch-fixes.patch
cris-remove-mtd_amstd-and-mtd_obsolete_chips-take-two-checkpatch-fixes.patch
uml-get-rid-of-asmlinkage-checkpatch-fixes.patch
uml-improve-detection-of-host-cmov-checkpatch-fixes.patch
uml-further-bugsc-tidying-checkpatch-fixes.patch
deprecate-smbfs-in-favour-of-cifs.patch
procfs-detect-duplicate-names.patch
kernel-printkc-concerns-about-the-console-handover.patch
fix-versus-precedence-in-various-places-checkpatch-fixes.patch
pie-executable-randomization.patch
pie-executable-randomization-uninlining.patch
pie-executable-randomization-checkpatch-fixes.patch
riscom8-fix-smp-brokenness-fix.patch
use-macros-instead-of-task_-flags-checkpatch-fixes.patch
sound-oss-pss-set_io_base-always-returns-success-mark-it-void-checkpatch-fixes.patch
remove-warnings-for-longstanding-conditions-fix.patch
parallel-port-convert-port_mutex-to-the-mutex-api-checkpatch-fixes.patch
remove-support-for-un-needed-_extratext-section-checkpatch-fixes.patch
allow-auto-destruction-of-loop-devices-checkpatch-fixes.patch
remove-__attribute_used__-checkpatch-fixes.patch
read_current_time-cleanups.patch
sync_sb_inodes-propagate-errors.patch
64-bit-i_version-afs-fixes.patch
kill-filp_open-checkpatch-fixes.patch
rename-open_namei-to-open_pathname-fix.patch
r-o-bind-mounts-elevate-write-count-during-entire-ncp_ioctl-fix.patch
r-o-bind-mounts-elevate-write-count-for-do_utimes.patch
r-o-bind-mounts-elevate-write-count-for-some-ioctls-checkpatch-fixes.patch
r-o-bind-mounts-elevate-write-count-for-some-ioctls-vs-forbid-user-to-change-file-flags-on-quota-files.patch
r-o-bind-mounts-nfs-check-mnt-instead-of-superblock-directly-checkpatch-fixes.patch
r-o-bind-mounts-track-number-of-mount-writer-fix-buggy-loop-checkpatch-fixes.patch
slab-api-remove-useless-ctor-parameter-and-reorder-parameters-vs-revoke.patch
revoke-wire-up-i386-system-calls.patch
revoke-vs-git-block.patch
cgroup-simplify-space-stripping-fix.patch
memory-controller-memory-accounting-v7.patch
memory-controller-add-per-container-lru-and-reclaim-v7.patch
memory-controller-oom-handling-v7.patch
memory-controller-add-switch-to-control-what-type-of-pages-to-limit-v7.patch
memcontrol-move-oom-task-exclusion-to-tasklist.patch
memory-cgroup-enhancements-add-status-accounting-function-for-memory-cgroup-checkpatch-fixes.patch
memory-cgroup-enhancements-add-status-accounting-function-for-memory-cgroup-fix-1.patch
memory-cgroup-enhancements-add-status-accounting-function-for-memory-cgroup-uninlining.patch
memory-cgroup-enhancements-add-status-accounting-function-for-memory-cgroup-fix-2.patch
memory-cgroup-enhancements-add-memorystat-file-checkpatch-fixes.patch
drivers-edac-add-marvell-mv64x60-driver-fix.patch
introduce-flags-for-reserve_bootmem-checkpatch-fixes.patch
iget-stop-affs-from-using-iget-and-read_inode-try-checkpatch-fixes.patch
iget-stop-efs-from-using-iget-and-read_inode-try-checkpatch-fixes.patch
iget-stop-ext2-from-using-iget-and-read_inode-try-checkpatch-fixes.patch
iget-stop-ext3-from-using-iget-and-read_inode-try-checkpatch-fixes.patch
iget-stop-freevxfs-from-using-iget-and-read_inode-checkpatch-fixes.patch
iget-stop-the-minix-filesystem-from-using-iget-and-checkpatch-fixes.patch
iget-stop-procfs-from-using-iget-and-read_inode-checkpatch-fixes.patch
iget-stop-qnx4-from-using-iget-and-read_inode-try-checkpatch-fixes.patch
iget-stop-romfs-from-using-iget-and-read_inode-checkpatch-fixes.patch
iget-stop-the-sysv-filesystem-from-using-iget-and-checkpatch-fixes.patch
iget-stop-ufs-from-using-iget-and-read_inode-try-checkpatch-fixes.patch
iget-stop-hostfs-from-using-iget-and-read_inode-checkpatch-fixes.patch
embed-a-struct-path-into-struct-nameidata-instead-of-nd-dentrymnt-checkpatch-fixes.patch
one-less-parameter-to-__d_path-checkpatch-fixes.patch
d_path-use-struct-path-in-struct-avc_audit_data-checkpatch-fixes.patch
d_path-make-get_dcookie-use-a-struct-path-argument-checkpatch-fixes.patch
use-struct-path-in-struct-svc_export-checkpatch-fixes.patch
make-copy_from_user_inatomic-not-zero-the-tail-on-i386-vs-reiser4.patch
reiser4.patch
jens-broke-reiser4patch-added-to-mm-tree.patch
page-owner-tracking-leak-detector.patch
nr_blockdev_pages-in_interrupt-warning.patch
slab-leaks3-default-y.patch
profile-likely-unlikely-macros-fix.patch
put_bh-debug.patch
kmap_atomic-debugging.patch
shrink_slab-handle-bad-shrinkers.patch
getblk-handle-2tb-devices.patch
getblk-handle-2tb-devices-fix.patch
w1-build-fix.patch

^ permalink raw reply


This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.