Merge branch 'core/signal' into perfcounters/core
This is necessary to avoid the conflict of syscall numbers. Conflicts: arch/x86/ia32/ia32entry.S arch/x86/include/asm/unistd_32.h arch/x86/include/asm/unistd_64.h Fixes up the borked syscall numbers of perfcounters versus preadv/pwritev as well. Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
		
						commit
						3c56999eec
					
				| @ -2,8 +2,14 @@ | ||||
| 	- this file (info on ISDN implementation for Linux) | ||||
| CREDITS | ||||
| 	- list of the kind folks that brought you this stuff. | ||||
| HiSax.cert | ||||
| 	- information about the ITU approval certification of the HiSax driver. | ||||
| INTERFACE | ||||
| 	- description of Linklevel and Hardwarelevel ISDN interface. | ||||
| 	- description of isdn4linux Link Level and Hardware Level interfaces. | ||||
| INTERFACE.fax | ||||
| 	- description of the fax subinterface of isdn4linux. | ||||
| INTERFACE.CAPI | ||||
| 	- description of kernel CAPI Link Level to Hardware Level interface. | ||||
| README | ||||
| 	- general info on what you need and what to do for Linux ISDN. | ||||
| README.FAQ | ||||
| @ -12,6 +18,8 @@ README.audio | ||||
| 	- info for running audio over ISDN. | ||||
| README.fax | ||||
| 	- info for using Fax over ISDN. | ||||
| README.gigaset | ||||
| 	- info on the drivers for Siemens Gigaset ISDN adapters. | ||||
| README.icn | ||||
| 	- info on the ICN-ISDN-card and its driver. | ||||
| README.HiSax | ||||
| @ -37,7 +45,8 @@ README.diversion | ||||
| README.sc | ||||
| 	- info on driver for Spellcaster cards. | ||||
| README.x25 | ||||
|     _ info for running X.25 over ISDN. | ||||
| 	- info for running X.25 over ISDN. | ||||
| README.hysdn | ||||
|         - info on driver for Hypercope active HYSDN cards | ||||
|   | ||||
| 	- info on driver for Hypercope active HYSDN cards | ||||
| README.mISDN | ||||
| 	- info on the Modular ISDN subsystem (mISDN). | ||||
|  | ||||
							
								
								
									
										213
									
								
								Documentation/isdn/INTERFACE.CAPI
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										213
									
								
								Documentation/isdn/INTERFACE.CAPI
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,213 @@ | ||||
| Kernel CAPI Interface to Hardware Drivers | ||||
| ----------------------------------------- | ||||
| 
 | ||||
| 1. Overview | ||||
| 
 | ||||
| From the CAPI 2.0 specification: | ||||
| COMMON-ISDN-API (CAPI) is an application programming interface standard used | ||||
| to access ISDN equipment connected to basic rate interfaces (BRI) and primary | ||||
| rate interfaces (PRI). | ||||
| 
 | ||||
| Kernel CAPI operates as a dispatching layer between CAPI applications and CAPI | ||||
| hardware drivers. Hardware drivers register ISDN devices (controllers, in CAPI | ||||
| lingo) with Kernel CAPI to indicate their readiness to provide their service | ||||
| to CAPI applications. CAPI applications also register with Kernel CAPI, | ||||
| requesting association with a CAPI device. Kernel CAPI then dispatches the | ||||
| application registration to an available device, forwarding it to the | ||||
| corresponding hardware driver. Kernel CAPI then forwards CAPI messages in both | ||||
| directions between the application and the hardware driver. | ||||
| 
 | ||||
| Format and semantics of CAPI messages are specified in the CAPI 2.0 standard. | ||||
| This standard is freely available from http://www.capi.org. | ||||
| 
 | ||||
| 
 | ||||
| 2. Driver and Device Registration | ||||
| 
 | ||||
| CAPI drivers optionally register themselves with Kernel CAPI by calling the | ||||
| Kernel CAPI function register_capi_driver() with a pointer to a struct | ||||
| capi_driver. This structure must be filled with the name and revision of the | ||||
| driver, and optionally a pointer to a callback function, add_card(). The | ||||
| registration can be revoked by calling the function unregister_capi_driver() | ||||
| with a pointer to the same struct capi_driver. | ||||
| 
 | ||||
| CAPI drivers must register each of the ISDN devices they control with Kernel | ||||
| CAPI by calling the Kernel CAPI function attach_capi_ctr() with a pointer to a | ||||
| struct capi_ctr before they can be used. This structure must be filled with | ||||
| the names of the driver and controller, and a number of callback function | ||||
| pointers which are subsequently used by Kernel CAPI for communicating with the | ||||
| driver. The registration can be revoked by calling the function | ||||
| detach_capi_ctr() with a pointer to the same struct capi_ctr. | ||||
| 
 | ||||
| Before the device can be actually used, the driver must fill in the device | ||||
| information fields 'manu', 'version', 'profile' and 'serial' in the capi_ctr | ||||
| structure of the device, and signal its readiness by calling capi_ctr_ready(). | ||||
| From then on, Kernel CAPI may call the registered callback functions for the | ||||
| device. | ||||
| 
 | ||||
| If the device becomes unusable for any reason (shutdown, disconnect ...), the | ||||
| driver has to call capi_ctr_reseted(). This will prevent further calls to the | ||||
| callback functions by Kernel CAPI. | ||||
| 
 | ||||
| 
 | ||||
| 3. Application Registration and Communication | ||||
| 
 | ||||
| Kernel CAPI forwards registration requests from applications (calls to CAPI | ||||
| operation CAPI_REGISTER) to an appropriate hardware driver by calling its | ||||
| register_appl() callback function. A unique Application ID (ApplID, u16) is | ||||
| allocated by Kernel CAPI and passed to register_appl() along with the | ||||
| parameter structure provided by the application. This is analogous to the | ||||
| open() operation on regular files or character devices. | ||||
| 
 | ||||
| After a successful return from register_appl(), CAPI messages from the | ||||
| application may be passed to the driver for the device via calls to the | ||||
| send_message() callback function. The CAPI message to send is stored in the | ||||
| data portion of an skb. Conversely, the driver may call Kernel CAPI's | ||||
| capi_ctr_handle_message() function to pass a received CAPI message to Kernel | ||||
| CAPI for forwarding to an application, specifying its ApplID. | ||||
| 
 | ||||
| Deregistration requests (CAPI operation CAPI_RELEASE) from applications are | ||||
| forwarded as calls to the release_appl() callback function, passing the same | ||||
| ApplID as with register_appl(). After return from release_appl(), no CAPI | ||||
| messages for that application may be passed to or from the device anymore. | ||||
| 
 | ||||
| 
 | ||||
| 4. Data Structures | ||||
| 
 | ||||
| 4.1 struct capi_driver | ||||
| 
 | ||||
| This structure describes a Kernel CAPI driver itself. It is used in the | ||||
| register_capi_driver() and unregister_capi_driver() functions, and contains | ||||
| the following non-private fields, all to be set by the driver before calling | ||||
| register_capi_driver(): | ||||
| 
 | ||||
| char name[32] | ||||
| 	the name of the driver, as a zero-terminated ASCII string | ||||
| char revision[32] | ||||
| 	the revision number of the driver, as a zero-terminated ASCII string | ||||
| int (*add_card)(struct capi_driver *driver, capicardparams *data) | ||||
| 	a callback function pointer (may be NULL) | ||||
| 
 | ||||
| 
 | ||||
| 4.2 struct capi_ctr | ||||
| 
 | ||||
| This structure describes an ISDN device (controller) handled by a Kernel CAPI | ||||
| driver. After registration via the attach_capi_ctr() function it is passed to | ||||
| all controller specific lower layer interface and callback functions to | ||||
| identify the controller to operate on. | ||||
| 
 | ||||
| It contains the following non-private fields: | ||||
| 
 | ||||
| - to be set by the driver before calling attach_capi_ctr(): | ||||
| 
 | ||||
| struct module *owner | ||||
| 	pointer to the driver module owning the device | ||||
| 
 | ||||
| void *driverdata | ||||
| 	an opaque pointer to driver specific data, not touched by Kernel CAPI | ||||
| 
 | ||||
| char name[32] | ||||
| 	the name of the controller, as a zero-terminated ASCII string | ||||
| 
 | ||||
| char *driver_name | ||||
| 	the name of the driver, as a zero-terminated ASCII string | ||||
| 
 | ||||
| int (*load_firmware)(struct capi_ctr *ctrlr, capiloaddata *ldata) | ||||
| 	(optional) pointer to a callback function for sending firmware and | ||||
| 	configuration data to the device | ||||
| 
 | ||||
| void (*reset_ctr)(struct capi_ctr *ctrlr) | ||||
| 	pointer to a callback function for performing a reset on the device, | ||||
| 	releasing all registered applications | ||||
| 
 | ||||
| void (*register_appl)(struct capi_ctr *ctrlr, u16 applid, | ||||
| 			capi_register_params *rparam) | ||||
| void (*release_appl)(struct capi_ctr *ctrlr, u16 applid) | ||||
| 	pointers to callback functions for registration and deregistration of | ||||
| 	applications with the device | ||||
| 
 | ||||
| u16  (*send_message)(struct capi_ctr *ctrlr, struct sk_buff *skb) | ||||
| 	pointer to a callback function for sending a CAPI message to the | ||||
| 	device | ||||
| 
 | ||||
| char *(*procinfo)(struct capi_ctr *ctrlr) | ||||
| 	pointer to a callback function returning the entry for the device in | ||||
| 	the CAPI controller info table, /proc/capi/controller | ||||
| 
 | ||||
| read_proc_t *ctr_read_proc | ||||
| 	pointer to the read_proc callback function for the device's proc file | ||||
| 	system entry, /proc/capi/controllers/<n>; will be called with a | ||||
| 	pointer to the device's capi_ctr structure as the last (data) argument | ||||
| 
 | ||||
| - to be filled in before calling capi_ctr_ready(): | ||||
| 
 | ||||
| u8 manu[CAPI_MANUFACTURER_LEN] | ||||
| 	value to return for CAPI_GET_MANUFACTURER | ||||
| 
 | ||||
| capi_version version | ||||
| 	value to return for CAPI_GET_VERSION | ||||
| 
 | ||||
| capi_profile profile | ||||
| 	value to return for CAPI_GET_PROFILE | ||||
| 
 | ||||
| u8 serial[CAPI_SERIAL_LEN] | ||||
| 	value to return for CAPI_GET_SERIAL | ||||
| 
 | ||||
| 
 | ||||
| 5. Lower Layer Interface Functions | ||||
| 
 | ||||
| (declared in <linux/isdn/capilli.h>) | ||||
| 
 | ||||
| void register_capi_driver(struct capi_driver *drvr) | ||||
| void unregister_capi_driver(struct capi_driver *drvr) | ||||
| 	register/unregister a driver with Kernel CAPI | ||||
| 
 | ||||
| int attach_capi_ctr(struct capi_ctr *ctrlr) | ||||
| int detach_capi_ctr(struct capi_ctr *ctrlr) | ||||
| 	register/unregister a device (controller) with Kernel CAPI | ||||
| 
 | ||||
| void capi_ctr_ready(struct capi_ctr *ctrlr) | ||||
| void capi_ctr_reseted(struct capi_ctr *ctrlr) | ||||
| 	signal controller ready/not ready | ||||
| 
 | ||||
| void capi_ctr_suspend_output(struct capi_ctr *ctrlr) | ||||
| void capi_ctr_resume_output(struct capi_ctr *ctrlr) | ||||
| 	signal suspend/resume | ||||
| 
 | ||||
| void capi_ctr_handle_message(struct capi_ctr * ctrlr, u16 applid, | ||||
| 				struct sk_buff *skb) | ||||
| 	pass a received CAPI message to Kernel CAPI | ||||
| 	for forwarding to the specified application | ||||
| 
 | ||||
| 
 | ||||
| 6. Helper Functions and Macros | ||||
| 
 | ||||
| Library functions (from <linux/isdn/capilli.h>): | ||||
| 
 | ||||
| void capilib_new_ncci(struct list_head *head, u16 applid, | ||||
| 			u32 ncci, u32 winsize) | ||||
| void capilib_free_ncci(struct list_head *head, u16 applid, u32 ncci) | ||||
| void capilib_release_appl(struct list_head *head, u16 applid) | ||||
| void capilib_release(struct list_head *head) | ||||
| void capilib_data_b3_conf(struct list_head *head, u16 applid, | ||||
| 			u32 ncci, u16 msgid) | ||||
| u16  capilib_data_b3_req(struct list_head *head, u16 applid, | ||||
| 			u32 ncci, u16 msgid) | ||||
| 
 | ||||
| 
 | ||||
| Macros to extract/set element values from/in a CAPI message header | ||||
| (from <linux/isdn/capiutil.h>): | ||||
| 
 | ||||
| Get Macro		Set Macro			Element (Type) | ||||
| 
 | ||||
| CAPIMSG_LEN(m)		CAPIMSG_SETLEN(m, len)		Total Length (u16) | ||||
| CAPIMSG_APPID(m)	CAPIMSG_SETAPPID(m, applid)	ApplID (u16) | ||||
| CAPIMSG_COMMAND(m)	CAPIMSG_SETCOMMAND(m,cmd)	Command (u8) | ||||
| CAPIMSG_SUBCOMMAND(m)	CAPIMSG_SETSUBCOMMAND(m, cmd)	Subcommand (u8) | ||||
| CAPIMSG_CMD(m)		-				Command*256 | ||||
| 							+ Subcommand (u16) | ||||
| CAPIMSG_MSGID(m)	CAPIMSG_SETMSGID(m, msgid)	Message Number (u16) | ||||
| 
 | ||||
| CAPIMSG_CONTROL(m)	CAPIMSG_SETCONTROL(m, contr)	Controller/PLCI/NCCI | ||||
| 							(u32) | ||||
| CAPIMSG_DATALEN(m)	CAPIMSG_SETDATALEN(m, len)	Data Length (u16) | ||||
| 
 | ||||
							
								
								
									
										4
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								Makefile
									
									
									
									
									
								
							| @ -1,8 +1,8 @@ | ||||
| VERSION = 2 | ||||
| PATCHLEVEL = 6 | ||||
| SUBLEVEL = 30 | ||||
| EXTRAVERSION = -rc3 | ||||
| NAME = Temporary Tasmanian Devil | ||||
| EXTRAVERSION = -rc4 | ||||
| NAME = Vindictive Armadillo | ||||
| 
 | ||||
| # *DOCUMENTATION*
 | ||||
| # To see a list of typical targets execute "make help"
 | ||||
|  | ||||
| @ -830,5 +830,6 @@ ia32_sys_call_table: | ||||
| 	.quad sys_inotify_init1
 | ||||
| 	.quad compat_sys_preadv
 | ||||
| 	.quad compat_sys_pwritev
 | ||||
| 	.quad compat_sys_rt_tgsigqueueinfo	/* 335 */ | ||||
| 	.quad sys_perf_counter_open
 | ||||
| ia32_syscall_end: | ||||
|  | ||||
| @ -340,7 +340,8 @@ | ||||
| #define __NR_inotify_init1	332 | ||||
| #define __NR_preadv		333 | ||||
| #define __NR_pwritev		334 | ||||
| #define __NR_perf_counter_open	333 | ||||
| #define __NR_rt_tgsigqueueinfo	335 | ||||
| #define __NR_perf_counter_open	336 | ||||
| 
 | ||||
| #ifdef __KERNEL__ | ||||
| 
 | ||||
|  | ||||
| @ -657,7 +657,9 @@ __SYSCALL(__NR_inotify_init1, sys_inotify_init1) | ||||
| __SYSCALL(__NR_preadv, sys_preadv) | ||||
| #define __NR_pwritev				296 | ||||
| __SYSCALL(__NR_pwritev, sys_pwritev) | ||||
| #define __NR_perf_counter_open		295 | ||||
| #define __NR_rt_tgsigqueueinfo			297 | ||||
| __SYSCALL(__NR_rt_tgsigqueueinfo, sys_rt_tgsigqueueinfo) | ||||
| #define __NR_perf_counter_open			298 | ||||
| __SYSCALL(__NR_perf_counter_open, sys_perf_counter_open) | ||||
| 
 | ||||
| #ifndef __NO_STUBS | ||||
|  | ||||
| @ -332,6 +332,7 @@ ENTRY(sys_call_table) | ||||
| 	.long sys_dup3			/* 330 */ | ||||
| 	.long sys_pipe2
 | ||||
| 	.long sys_inotify_init1
 | ||||
| 	.long sys_perf_counter_open
 | ||||
| 	.long sys_preadv
 | ||||
| 	.long sys_pwritev
 | ||||
| 	.long sys_rt_tgsigqueueinfo	/* 335 */ | ||||
| 	.long sys_perf_counter_open
 | ||||
|  | ||||
| @ -36,7 +36,7 @@ obj-$(CONFIG_FB_INTEL)          += video/intelfb/ | ||||
| 
 | ||||
| obj-y				+= serial/ | ||||
| obj-$(CONFIG_PARPORT)		+= parport/ | ||||
| obj-y				+= base/ block/ misc/ mfd/ media/ | ||||
| obj-y				+= base/ block/ misc/ mfd/ | ||||
| obj-$(CONFIG_NUBUS)		+= nubus/ | ||||
| obj-y				+= macintosh/ | ||||
| obj-$(CONFIG_IDE)		+= ide/ | ||||
| @ -71,7 +71,7 @@ obj-$(CONFIG_GAMEPORT)		+= input/gameport/ | ||||
| obj-$(CONFIG_INPUT)		+= input/ | ||||
| obj-$(CONFIG_I2O)		+= message/ | ||||
| obj-$(CONFIG_RTC_LIB)		+= rtc/ | ||||
| obj-y				+= i2c/ | ||||
| obj-y				+= i2c/ media/ | ||||
| obj-$(CONFIG_W1)		+= w1/ | ||||
| obj-$(CONFIG_POWER_SUPPLY)	+= power/ | ||||
| obj-$(CONFIG_HWMON)		+= hwmon/ | ||||
|  | ||||
| @ -270,6 +270,15 @@ static void recv_handler(struct work_struct *work) | ||||
| 	mutex_unlock(&ap->recv_mtx); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * capi_ctr_handle_message() - handle incoming CAPI message | ||||
|  * @card:	controller descriptor structure. | ||||
|  * @appl:	application ID. | ||||
|  * @skb:	message. | ||||
|  * | ||||
|  * Called by hardware driver to pass a CAPI message to the application. | ||||
|  */ | ||||
| 
 | ||||
| void capi_ctr_handle_message(struct capi_ctr * card, u16 appl, struct sk_buff *skb) | ||||
| { | ||||
| 	struct capi20_appl *ap; | ||||
| @ -348,6 +357,13 @@ error: | ||||
| 
 | ||||
| EXPORT_SYMBOL(capi_ctr_handle_message); | ||||
| 
 | ||||
| /**
 | ||||
|  * capi_ctr_ready() - signal CAPI controller ready | ||||
|  * @card:	controller descriptor structure. | ||||
|  * | ||||
|  * Called by hardware driver to signal that the controller is up and running. | ||||
|  */ | ||||
| 
 | ||||
| void capi_ctr_ready(struct capi_ctr * card) | ||||
| { | ||||
| 	card->cardstate = CARD_RUNNING; | ||||
| @ -360,6 +376,14 @@ void capi_ctr_ready(struct capi_ctr * card) | ||||
| 
 | ||||
| EXPORT_SYMBOL(capi_ctr_ready); | ||||
| 
 | ||||
| /**
 | ||||
|  * capi_ctr_reseted() - signal CAPI controller reset | ||||
|  * @card:	controller descriptor structure. | ||||
|  * | ||||
|  * Called by hardware driver to signal that the controller is down and | ||||
|  * unavailable for use. | ||||
|  */ | ||||
| 
 | ||||
| void capi_ctr_reseted(struct capi_ctr * card) | ||||
| { | ||||
| 	u16 appl; | ||||
| @ -391,6 +415,13 @@ void capi_ctr_reseted(struct capi_ctr * card) | ||||
| 
 | ||||
| EXPORT_SYMBOL(capi_ctr_reseted); | ||||
| 
 | ||||
| /**
 | ||||
|  * capi_ctr_suspend_output() - suspend controller | ||||
|  * @card:	controller descriptor structure. | ||||
|  * | ||||
|  * Called by hardware driver to stop data flow. | ||||
|  */ | ||||
| 
 | ||||
| void capi_ctr_suspend_output(struct capi_ctr *card) | ||||
| { | ||||
| 	if (!card->blocked) { | ||||
| @ -401,6 +432,13 @@ void capi_ctr_suspend_output(struct capi_ctr *card) | ||||
| 
 | ||||
| EXPORT_SYMBOL(capi_ctr_suspend_output); | ||||
| 
 | ||||
| /**
 | ||||
|  * capi_ctr_resume_output() - resume controller | ||||
|  * @card:	controller descriptor structure. | ||||
|  * | ||||
|  * Called by hardware driver to resume data flow. | ||||
|  */ | ||||
| 
 | ||||
| void capi_ctr_resume_output(struct capi_ctr *card) | ||||
| { | ||||
| 	if (card->blocked) { | ||||
| @ -413,6 +451,14 @@ EXPORT_SYMBOL(capi_ctr_resume_output); | ||||
| 
 | ||||
| /* ------------------------------------------------------------- */ | ||||
| 
 | ||||
| /**
 | ||||
|  * attach_capi_ctr() - register CAPI controller | ||||
|  * @card:	controller descriptor structure. | ||||
|  * | ||||
|  * Called by hardware driver to register a controller with the CAPI subsystem. | ||||
|  * Return value: 0 on success, error code < 0 on error | ||||
|  */ | ||||
| 
 | ||||
| int | ||||
| attach_capi_ctr(struct capi_ctr *card) | ||||
| { | ||||
| @ -459,6 +505,15 @@ attach_capi_ctr(struct capi_ctr *card) | ||||
| 
 | ||||
| EXPORT_SYMBOL(attach_capi_ctr); | ||||
| 
 | ||||
| /**
 | ||||
|  * detach_capi_ctr() - unregister CAPI controller | ||||
|  * @card:	controller descriptor structure. | ||||
|  * | ||||
|  * Called by hardware driver to remove the registration of a controller | ||||
|  * with the CAPI subsystem. | ||||
|  * Return value: 0 on success, error code < 0 on error | ||||
|  */ | ||||
| 
 | ||||
| int detach_capi_ctr(struct capi_ctr *card) | ||||
| { | ||||
|         if (card->cardstate != CARD_DETECTED) | ||||
| @ -479,6 +534,13 @@ int detach_capi_ctr(struct capi_ctr *card) | ||||
| 
 | ||||
| EXPORT_SYMBOL(detach_capi_ctr); | ||||
| 
 | ||||
| /**
 | ||||
|  * register_capi_driver() - register CAPI driver | ||||
|  * @driver:	driver descriptor structure. | ||||
|  * | ||||
|  * Called by hardware driver to register itself with the CAPI subsystem. | ||||
|  */ | ||||
| 
 | ||||
| void register_capi_driver(struct capi_driver *driver) | ||||
| { | ||||
| 	unsigned long flags; | ||||
| @ -490,6 +552,13 @@ void register_capi_driver(struct capi_driver *driver) | ||||
| 
 | ||||
| EXPORT_SYMBOL(register_capi_driver); | ||||
| 
 | ||||
| /**
 | ||||
|  * unregister_capi_driver() - unregister CAPI driver | ||||
|  * @driver:	driver descriptor structure. | ||||
|  * | ||||
|  * Called by hardware driver to unregister itself from the CAPI subsystem. | ||||
|  */ | ||||
| 
 | ||||
| void unregister_capi_driver(struct capi_driver *driver) | ||||
| { | ||||
| 	unsigned long flags; | ||||
| @ -505,6 +574,13 @@ EXPORT_SYMBOL(unregister_capi_driver); | ||||
| /* -------- CAPI2.0 Interface ---------------------------------- */ | ||||
| /* ------------------------------------------------------------- */ | ||||
| 
 | ||||
| /**
 | ||||
|  * capi20_isinstalled() - CAPI 2.0 operation CAPI_INSTALLED | ||||
|  * | ||||
|  * Return value: CAPI result code (CAPI_NOERROR if at least one ISDN controller | ||||
|  *	is ready for use, CAPI_REGNOTINSTALLED otherwise) | ||||
|  */ | ||||
| 
 | ||||
| u16 capi20_isinstalled(void) | ||||
| { | ||||
| 	int i; | ||||
| @ -517,6 +593,18 @@ u16 capi20_isinstalled(void) | ||||
| 
 | ||||
| EXPORT_SYMBOL(capi20_isinstalled); | ||||
| 
 | ||||
| /**
 | ||||
|  * capi20_register() - CAPI 2.0 operation CAPI_REGISTER | ||||
|  * @ap:		CAPI application descriptor structure. | ||||
|  * | ||||
|  * Register an application's presence with CAPI. | ||||
|  * A unique application ID is assigned and stored in @ap->applid. | ||||
|  * After this function returns successfully, the message receive | ||||
|  * callback function @ap->recv_message() may be called at any time | ||||
|  * until capi20_release() has been called for the same @ap. | ||||
|  * Return value: CAPI result code | ||||
|  */ | ||||
| 
 | ||||
| u16 capi20_register(struct capi20_appl *ap) | ||||
| { | ||||
| 	int i; | ||||
| @ -571,6 +659,16 @@ u16 capi20_register(struct capi20_appl *ap) | ||||
| 
 | ||||
| EXPORT_SYMBOL(capi20_register); | ||||
| 
 | ||||
| /**
 | ||||
|  * capi20_release() - CAPI 2.0 operation CAPI_RELEASE | ||||
|  * @ap:		CAPI application descriptor structure. | ||||
|  * | ||||
|  * Terminate an application's registration with CAPI. | ||||
|  * After this function returns successfully, the message receive | ||||
|  * callback function @ap->recv_message() will no longer be called. | ||||
|  * Return value: CAPI result code | ||||
|  */ | ||||
| 
 | ||||
| u16 capi20_release(struct capi20_appl *ap) | ||||
| { | ||||
| 	int i; | ||||
| @ -603,6 +701,15 @@ u16 capi20_release(struct capi20_appl *ap) | ||||
| 
 | ||||
| EXPORT_SYMBOL(capi20_release); | ||||
| 
 | ||||
| /**
 | ||||
|  * capi20_put_message() - CAPI 2.0 operation CAPI_PUT_MESSAGE | ||||
|  * @ap:		CAPI application descriptor structure. | ||||
|  * @skb:	CAPI message. | ||||
|  * | ||||
|  * Transfer a single message to CAPI. | ||||
|  * Return value: CAPI result code | ||||
|  */ | ||||
| 
 | ||||
| u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb) | ||||
| { | ||||
| 	struct capi_ctr *card; | ||||
| @ -668,6 +775,16 @@ u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb) | ||||
| 
 | ||||
| EXPORT_SYMBOL(capi20_put_message); | ||||
| 
 | ||||
| /**
 | ||||
|  * capi20_get_manufacturer() - CAPI 2.0 operation CAPI_GET_MANUFACTURER | ||||
|  * @contr:	controller number. | ||||
|  * @buf:	result buffer (64 bytes). | ||||
|  * | ||||
|  * Retrieve information about the manufacturer of the specified ISDN controller | ||||
|  * or (for @contr == 0) the driver itself. | ||||
|  * Return value: CAPI result code | ||||
|  */ | ||||
| 
 | ||||
| u16 capi20_get_manufacturer(u32 contr, u8 *buf) | ||||
| { | ||||
| 	struct capi_ctr *card; | ||||
| @ -685,6 +802,16 @@ u16 capi20_get_manufacturer(u32 contr, u8 *buf) | ||||
| 
 | ||||
| EXPORT_SYMBOL(capi20_get_manufacturer); | ||||
| 
 | ||||
| /**
 | ||||
|  * capi20_get_version() - CAPI 2.0 operation CAPI_GET_VERSION | ||||
|  * @contr:	controller number. | ||||
|  * @verp:	result structure. | ||||
|  * | ||||
|  * Retrieve version information for the specified ISDN controller | ||||
|  * or (for @contr == 0) the driver itself. | ||||
|  * Return value: CAPI result code | ||||
|  */ | ||||
| 
 | ||||
| u16 capi20_get_version(u32 contr, struct capi_version *verp) | ||||
| { | ||||
| 	struct capi_ctr *card; | ||||
| @ -703,6 +830,16 @@ u16 capi20_get_version(u32 contr, struct capi_version *verp) | ||||
| 
 | ||||
| EXPORT_SYMBOL(capi20_get_version); | ||||
| 
 | ||||
| /**
 | ||||
|  * capi20_get_serial() - CAPI 2.0 operation CAPI_GET_SERIAL_NUMBER | ||||
|  * @contr:	controller number. | ||||
|  * @serial:	result buffer (8 bytes). | ||||
|  * | ||||
|  * Retrieve the serial number of the specified ISDN controller | ||||
|  * or (for @contr == 0) the driver itself. | ||||
|  * Return value: CAPI result code | ||||
|  */ | ||||
| 
 | ||||
| u16 capi20_get_serial(u32 contr, u8 *serial) | ||||
| { | ||||
| 	struct capi_ctr *card; | ||||
| @ -721,6 +858,16 @@ u16 capi20_get_serial(u32 contr, u8 *serial) | ||||
| 
 | ||||
| EXPORT_SYMBOL(capi20_get_serial); | ||||
| 
 | ||||
| /**
 | ||||
|  * capi20_get_profile() - CAPI 2.0 operation CAPI_GET_PROFILE | ||||
|  * @contr:	controller number. | ||||
|  * @profp:	result structure. | ||||
|  * | ||||
|  * Retrieve capability information for the specified ISDN controller | ||||
|  * or (for @contr == 0) the number of installed controllers. | ||||
|  * Return value: CAPI result code | ||||
|  */ | ||||
| 
 | ||||
| u16 capi20_get_profile(u32 contr, struct capi_profile *profp) | ||||
| { | ||||
| 	struct capi_ctr *card; | ||||
| @ -903,6 +1050,15 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data) | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * capi20_manufacturer() - CAPI 2.0 operation CAPI_MANUFACTURER | ||||
|  * @cmd:	command. | ||||
|  * @data:	parameter. | ||||
|  * | ||||
|  * Perform manufacturer specific command. | ||||
|  * Return value: CAPI result code | ||||
|  */ | ||||
| 
 | ||||
| int capi20_manufacturer(unsigned int cmd, void __user *data) | ||||
| { | ||||
|         struct capi_ctr *card; | ||||
| @ -981,6 +1137,21 @@ int capi20_manufacturer(unsigned int cmd, void __user *data) | ||||
| EXPORT_SYMBOL(capi20_manufacturer); | ||||
| 
 | ||||
| /* temporary hack */ | ||||
| 
 | ||||
| /**
 | ||||
|  * capi20_set_callback() - set CAPI application notification callback function | ||||
|  * @ap:		CAPI application descriptor structure. | ||||
|  * @callback:	callback function (NULL to remove). | ||||
|  * | ||||
|  * If not NULL, the callback function will be called to notify the | ||||
|  * application of the addition or removal of a controller. | ||||
|  * The first argument (cmd) will tell whether the controller was added | ||||
|  * (KCI_CONTRUP) or removed (KCI_CONTRDOWN). | ||||
|  * The second argument (contr) will be the controller number. | ||||
|  * For cmd==KCI_CONTRUP the third argument (data) will be a pointer to the | ||||
|  * new controller's capability profile structure. | ||||
|  */ | ||||
| 
 | ||||
| void capi20_set_callback(struct capi20_appl *ap, | ||||
| 			 void (*callback) (unsigned int cmd, __u32 contr, void *data)) | ||||
| { | ||||
|  | ||||
| @ -192,8 +192,6 @@ static int au0828_usb_probe(struct usb_interface *interface, | ||||
| 	dev->usbdev = usbdev; | ||||
| 	dev->boardnr = id->driver_info; | ||||
| 
 | ||||
| 	usb_set_intfdata(interface, dev); | ||||
| 
 | ||||
| 	/* Create the v4l2_device */ | ||||
| 	retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev); | ||||
| 	if (retval) { | ||||
| @ -222,6 +220,10 @@ static int au0828_usb_probe(struct usb_interface *interface, | ||||
| 	/* Digital TV */ | ||||
| 	au0828_dvb_register(dev); | ||||
| 
 | ||||
| 	/* Store the pointer to the au0828_dev so it can be accessed in
 | ||||
| 	   au0828_usb_disconnect */ | ||||
| 	usb_set_intfdata(interface, dev); | ||||
| 
 | ||||
| 	printk(KERN_INFO "Registered device AU0828 [%s]\n", | ||||
| 		dev->board.name == NULL ? "Unset" : dev->board.name); | ||||
| 
 | ||||
|  | ||||
| @ -44,7 +44,7 @@ int cx18_audio_set_io(struct cx18 *cx) | ||||
| 
 | ||||
| 	/* handle muxer chips */ | ||||
| 	v4l2_subdev_call(cx->sd_extmux, audio, s_routing, | ||||
| 			in->audio_input, 0, 0); | ||||
| 			 (u32) in->muxer_input, 0, 0); | ||||
| 
 | ||||
| 	err = cx18_call_hw_err(cx, cx->card->hw_audio_ctrl, | ||||
| 			       audio, s_routing, in->audio_input, 0, 0); | ||||
|  | ||||
| @ -211,7 +211,7 @@ static struct i2c_algo_bit_data cx18_i2c_algo_template = { | ||||
| /* init + register i2c algo-bit adapter */ | ||||
| int init_cx18_i2c(struct cx18 *cx) | ||||
| { | ||||
| 	int i; | ||||
| 	int i, err; | ||||
| 	CX18_DEBUG_I2C("i2c init\n"); | ||||
| 
 | ||||
| 	for (i = 0; i < 2; i++) { | ||||
| @ -268,8 +268,18 @@ int init_cx18_i2c(struct cx18 *cx) | ||||
| 	cx18_call_hw(cx, CX18_HW_GPIO_RESET_CTRL, | ||||
| 		     core, reset, (u32) CX18_GPIO_RESET_I2C); | ||||
| 
 | ||||
| 	return i2c_bit_add_bus(&cx->i2c_adap[0]) || | ||||
| 		i2c_bit_add_bus(&cx->i2c_adap[1]); | ||||
| 	err = i2c_bit_add_bus(&cx->i2c_adap[0]); | ||||
| 	if (err) | ||||
| 		goto err; | ||||
| 	err = i2c_bit_add_bus(&cx->i2c_adap[1]); | ||||
| 	if (err) | ||||
| 		goto err_del_bus_0; | ||||
| 	return 0; | ||||
| 
 | ||||
|  err_del_bus_0: | ||||
| 	i2c_del_adapter(&cx->i2c_adap[0]); | ||||
|  err: | ||||
| 	return err; | ||||
| } | ||||
| 
 | ||||
| void exit_cx18_i2c(struct cx18 *cx) | ||||
|  | ||||
| @ -1,12 +1,11 @@ | ||||
| config VIDEO_CX231XX | ||||
|        tristate "Conexant cx231xx USB video capture support" | ||||
|        depends on VIDEO_DEV && I2C && INPUT | ||||
|        select VIDEO_TUNER | ||||
|        select VIDEO_TVEEPROM | ||||
|        select VIDEO_IR | ||||
|        select VIDEOBUF_VMALLOC | ||||
|        select VIDEO_CX25840 | ||||
|        select VIDEO_CX231XX_ALSA | ||||
| 	tristate "Conexant cx231xx USB video capture support" | ||||
| 	depends on VIDEO_DEV && I2C && INPUT | ||||
| 	select VIDEO_TUNER | ||||
| 	select VIDEO_TVEEPROM | ||||
| 	select VIDEO_IR | ||||
| 	select VIDEOBUF_VMALLOC | ||||
| 	select VIDEO_CX25840 | ||||
| 
 | ||||
| 	---help--- | ||||
| 	  This is a video4linux driver for Conexant 231xx USB based TV cards. | ||||
| @ -15,21 +14,22 @@ config VIDEO_CX231XX | ||||
| 	  module will be called cx231xx | ||||
| 
 | ||||
| config VIDEO_CX231XX_ALSA | ||||
|     tristate "Conexant Cx231xx ALSA audio module" | ||||
|        depends on VIDEO_CX231XX && SND | ||||
|        select SND_PCM | ||||
| 	tristate "Conexant Cx231xx ALSA audio module" | ||||
| 	depends on VIDEO_CX231XX && SND | ||||
| 	select SND_PCM | ||||
| 
 | ||||
|        ---help--- | ||||
| 	 This is an ALSA driver for Cx231xx USB based TV cards. | ||||
| 	---help--- | ||||
| 	  This is an ALSA driver for Cx231xx USB based TV cards. | ||||
| 
 | ||||
| 	 To compile this driver as a module, choose M here: the | ||||
| 	 module will be called cx231xx-alsa | ||||
| 	  To compile this driver as a module, choose M here: the | ||||
| 	  module will be called cx231xx-alsa | ||||
| 
 | ||||
| config VIDEO_CX231XX_DVB | ||||
|        tristate "DVB/ATSC Support for Cx231xx based TV cards" | ||||
|        depends on VIDEO_CX231XX && DVB_CORE | ||||
|        select VIDEOBUF_DVB | ||||
|        select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMISE | ||||
|        ---help--- | ||||
| 	 This adds support for DVB cards based on the | ||||
| 	 Conexant cx231xx chips. | ||||
| 	tristate "DVB/ATSC Support for Cx231xx based TV cards" | ||||
| 	depends on VIDEO_CX231XX && DVB_CORE | ||||
| 	select VIDEOBUF_DVB | ||||
| 	select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMISE | ||||
| 
 | ||||
| 	---help--- | ||||
| 	  This adds support for DVB cards based on the | ||||
| 	  Conexant cx231xx chips. | ||||
|  | ||||
| @ -441,9 +441,9 @@ int cx23885_tuner_callback(void *priv, int component, int command, int arg) | ||||
| 	case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: | ||||
| 		/* Two identical tuners on two different i2c buses,
 | ||||
| 		 * we need to reset the correct gpio. */ | ||||
| 		if (port->nr == 0) | ||||
| 		if (port->nr == 1) | ||||
| 			bitmask = 0x01; | ||||
| 		else if (port->nr == 1) | ||||
| 		else if (port->nr == 2) | ||||
| 			bitmask = 0x04; | ||||
| 		break; | ||||
| 	} | ||||
|  | ||||
| @ -314,6 +314,7 @@ static struct zl10353_config dvico_fusionhdtv_xc3028 = { | ||||
| 	.demod_address = 0x0f, | ||||
| 	.if2           = 45600, | ||||
| 	.no_tuner      = 1, | ||||
| 	.disable_i2c_gate_ctrl = 1, | ||||
| }; | ||||
| 
 | ||||
| static struct stv0900_config netup_stv0900_config = { | ||||
|  | ||||
| @ -1063,10 +1063,6 @@ static struct soc_camera_host_ops mx3_soc_camera_host_ops = { | ||||
| 	.owner		= THIS_MODULE, | ||||
| 	.add		= mx3_camera_add_device, | ||||
| 	.remove		= mx3_camera_remove_device, | ||||
| #ifdef CONFIG_PM | ||||
| 	.suspend	= mx3_camera_suspend, | ||||
| 	.resume		= mx3_camera_resume, | ||||
| #endif | ||||
| 	.set_crop	= mx3_camera_set_crop, | ||||
| 	.set_fmt	= mx3_camera_set_fmt, | ||||
| 	.try_fmt	= mx3_camera_try_fmt, | ||||
|  | ||||
| @ -1237,6 +1237,7 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, | ||||
| 	buffer[1] = (u32) chn_rev; | ||||
| 	buffer[2] = CMD_SET_MODE; | ||||
| 	memcpy(&buffer[3], &dev->mode[chn], sizeof(struct s2255_mode)); | ||||
| 	dev->setmode_ready[chn] = 0; | ||||
| 	res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512); | ||||
| 	if (debug) | ||||
| 		dump_verify_mode(dev, mode); | ||||
| @ -1245,7 +1246,6 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, | ||||
| 
 | ||||
| 	/* wait at least 3 frames before continuing */ | ||||
| 	if (mode->restart) { | ||||
| 		dev->setmode_ready[chn] = 0; | ||||
| 		wait_event_timeout(dev->wait_setmode[chn], | ||||
| 				   (dev->setmode_ready[chn] != 0), | ||||
| 				   msecs_to_jiffies(S2255_SETMODE_TIMEOUT)); | ||||
|  | ||||
| @ -1092,9 +1092,8 @@ static int saa5246a_probe(struct i2c_client *client, | ||||
| 	/* Register it */ | ||||
| 	err = video_register_device(t->vdev, VFL_TYPE_VTX, -1); | ||||
| 	if (err < 0) { | ||||
| 		kfree(t); | ||||
| 		video_device_release(t->vdev); | ||||
| 		t->vdev = NULL; | ||||
| 		kfree(t); | ||||
| 		return err; | ||||
| 	} | ||||
| 	return 0; | ||||
|  | ||||
| @ -598,6 +598,7 @@ static int saa5249_probe(struct i2c_client *client, | ||||
| 	/* Now create a video4linux device */ | ||||
| 	t->vdev = video_device_alloc(); | ||||
| 	if (t->vdev == NULL) { | ||||
| 		kfree(t); | ||||
| 		kfree(client); | ||||
| 		return -ENOMEM; | ||||
| 	} | ||||
| @ -617,9 +618,8 @@ static int saa5249_probe(struct i2c_client *client, | ||||
| 	/* Register it */ | ||||
| 	err = video_register_device(t->vdev, VFL_TYPE_VTX, -1); | ||||
| 	if (err < 0) { | ||||
| 		kfree(t); | ||||
| 		video_device_release(t->vdev); | ||||
| 		t->vdev = NULL; | ||||
| 		kfree(t); | ||||
| 		return err; | ||||
| 	} | ||||
| 	return 0; | ||||
|  | ||||
| @ -2728,7 +2728,7 @@ static void __devexit e100_remove(struct pci_dev *pdev) | ||||
| #define E100_82552_SMARTSPEED   0x14   /* SmartSpeed Ctrl register */ | ||||
| #define E100_82552_REV_ANEG     0x0200 /* Reverse auto-negotiation */ | ||||
| #define E100_82552_ANEG_NOW     0x0400 /* Auto-negotiate now */ | ||||
| static int e100_suspend(struct pci_dev *pdev, pm_message_t state) | ||||
| static void __e100_shutdown(struct pci_dev *pdev, bool *enable_wake) | ||||
| { | ||||
| 	struct net_device *netdev = pci_get_drvdata(pdev); | ||||
| 	struct nic *nic = netdev_priv(netdev); | ||||
| @ -2749,19 +2749,32 @@ static int e100_suspend(struct pci_dev *pdev, pm_message_t state) | ||||
| 			           E100_82552_SMARTSPEED, smartspeed | | ||||
| 			           E100_82552_REV_ANEG | E100_82552_ANEG_NOW); | ||||
| 		} | ||||
| 		if (pci_enable_wake(pdev, PCI_D3cold, true)) | ||||
| 			pci_enable_wake(pdev, PCI_D3hot, true); | ||||
| 		*enable_wake = true; | ||||
| 	} else { | ||||
| 		pci_enable_wake(pdev, PCI_D3hot, false); | ||||
| 		*enable_wake = false; | ||||
| 	} | ||||
| 
 | ||||
| 	pci_disable_device(pdev); | ||||
| 	pci_set_power_state(pdev, PCI_D3hot); | ||||
| } | ||||
| 
 | ||||
| 	return 0; | ||||
| static int __e100_power_off(struct pci_dev *pdev, bool wake) | ||||
| { | ||||
| 	if (wake) { | ||||
| 		return pci_prepare_to_sleep(pdev); | ||||
| 	} else { | ||||
| 		pci_wake_from_d3(pdev, false); | ||||
| 		return pci_set_power_state(pdev, PCI_D3hot); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| #ifdef CONFIG_PM | ||||
| static int e100_suspend(struct pci_dev *pdev, pm_message_t state) | ||||
| { | ||||
| 	bool wake; | ||||
| 	__e100_shutdown(pdev, &wake); | ||||
| 	return __e100_power_off(pdev, wake); | ||||
| } | ||||
| 
 | ||||
| static int e100_resume(struct pci_dev *pdev) | ||||
| { | ||||
| 	struct net_device *netdev = pci_get_drvdata(pdev); | ||||
| @ -2792,7 +2805,10 @@ static int e100_resume(struct pci_dev *pdev) | ||||
| 
 | ||||
| static void e100_shutdown(struct pci_dev *pdev) | ||||
| { | ||||
| 	e100_suspend(pdev, PMSG_SUSPEND); | ||||
| 	bool wake; | ||||
| 	__e100_shutdown(pdev, &wake); | ||||
| 	if (system_state == SYSTEM_POWER_OFF) | ||||
| 		__e100_power_off(pdev, wake); | ||||
| } | ||||
| 
 | ||||
| /* ------------------ PCI Error Recovery infrastructure  -------------- */ | ||||
|  | ||||
| @ -1880,6 +1880,7 @@ static void nv_init_tx(struct net_device *dev) | ||||
| 	np->tx_pkts_in_progress = 0; | ||||
| 	np->tx_change_owner = NULL; | ||||
| 	np->tx_end_flip = NULL; | ||||
| 	np->tx_stop = 0; | ||||
| 
 | ||||
| 	for (i = 0; i < np->tx_ring_size; i++) { | ||||
| 		if (!nv_optimized(np)) { | ||||
| @ -2530,6 +2531,8 @@ static void nv_tx_timeout(struct net_device *dev) | ||||
| 	struct fe_priv *np = netdev_priv(dev); | ||||
| 	u8 __iomem *base = get_hwbase(dev); | ||||
| 	u32 status; | ||||
| 	union ring_type put_tx; | ||||
| 	int saved_tx_limit; | ||||
| 
 | ||||
| 	if (np->msi_flags & NV_MSI_X_ENABLED) | ||||
| 		status = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQSTAT_MASK; | ||||
| @ -2589,24 +2592,32 @@ static void nv_tx_timeout(struct net_device *dev) | ||||
| 	/* 1) stop tx engine */ | ||||
| 	nv_stop_tx(dev); | ||||
| 
 | ||||
| 	/* 2) check that the packets were not sent already: */ | ||||
| 	/* 2) complete any outstanding tx and do not give HW any limited tx pkts */ | ||||
| 	saved_tx_limit = np->tx_limit; | ||||
| 	np->tx_limit = 0; /* prevent giving HW any limited pkts */ | ||||
| 	np->tx_stop = 0;  /* prevent waking tx queue */ | ||||
| 	if (!nv_optimized(np)) | ||||
| 		nv_tx_done(dev, np->tx_ring_size); | ||||
| 	else | ||||
| 		nv_tx_done_optimized(dev, np->tx_ring_size); | ||||
| 
 | ||||
| 	/* 3) if there are dead entries: clear everything */ | ||||
| 	if (np->get_tx_ctx != np->put_tx_ctx) { | ||||
| 		printk(KERN_DEBUG "%s: tx_timeout: dead entries!\n", dev->name); | ||||
| 		nv_drain_tx(dev); | ||||
| 		nv_init_tx(dev); | ||||
| 		setup_hw_rings(dev, NV_SETUP_TX_RING); | ||||
| 	} | ||||
| 	/* save current HW postion */ | ||||
| 	if (np->tx_change_owner) | ||||
| 		put_tx.ex = np->tx_change_owner->first_tx_desc; | ||||
| 	else | ||||
| 		put_tx = np->put_tx; | ||||
| 
 | ||||
| 	netif_wake_queue(dev); | ||||
| 	/* 3) clear all tx state */ | ||||
| 	nv_drain_tx(dev); | ||||
| 	nv_init_tx(dev); | ||||
| 
 | ||||
| 	/* 4) restart tx engine */ | ||||
| 	/* 4) restore state to current HW position */ | ||||
| 	np->get_tx = np->put_tx = put_tx; | ||||
| 	np->tx_limit = saved_tx_limit; | ||||
| 
 | ||||
| 	/* 5) restart tx engine */ | ||||
| 	nv_start_tx(dev); | ||||
| 	netif_wake_queue(dev); | ||||
| 	spin_unlock_irq(&np->lock); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -50,7 +50,6 @@ static u16 ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw); | ||||
| static void ixgbe_enable_rar(struct ixgbe_hw *hw, u32 index); | ||||
| static void ixgbe_disable_rar(struct ixgbe_hw *hw, u32 index); | ||||
| static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr); | ||||
| static void ixgbe_add_mc_addr(struct ixgbe_hw *hw, u8 *mc_addr); | ||||
| static void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq); | ||||
| 
 | ||||
| /**
 | ||||
| @ -1377,8 +1376,7 @@ s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list, | ||||
| 	 * Clear accounting of old secondary address list, | ||||
| 	 * don't count RAR[0] | ||||
| 	 */ | ||||
| 	uc_addr_in_use = hw->addr_ctrl.rar_used_count - | ||||
| 	                 hw->addr_ctrl.mc_addr_in_rar_count - 1; | ||||
| 	uc_addr_in_use = hw->addr_ctrl.rar_used_count - 1; | ||||
| 	hw->addr_ctrl.rar_used_count -= uc_addr_in_use; | ||||
| 	hw->addr_ctrl.overflow_promisc = 0; | ||||
| 
 | ||||
| @ -1492,40 +1490,6 @@ static void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr) | ||||
| 	IXGBE_WRITE_REG(hw, IXGBE_MTA(vector_reg), mta_reg); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  *  ixgbe_add_mc_addr - Adds a multicast address. | ||||
|  *  @hw: pointer to hardware structure | ||||
|  *  @mc_addr: new multicast address | ||||
|  * | ||||
|  *  Adds it to unused receive address register or to the multicast table. | ||||
|  **/ | ||||
| static void ixgbe_add_mc_addr(struct ixgbe_hw *hw, u8 *mc_addr) | ||||
| { | ||||
| 	u32 rar_entries = hw->mac.num_rar_entries; | ||||
| 	u32 rar; | ||||
| 
 | ||||
| 	hw_dbg(hw, " MC Addr =%.2X %.2X %.2X %.2X %.2X %.2X\n", | ||||
| 	       mc_addr[0], mc_addr[1], mc_addr[2], | ||||
| 	       mc_addr[3], mc_addr[4], mc_addr[5]); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Place this multicast address in the RAR if there is room, | ||||
| 	 * else put it in the MTA | ||||
| 	 */ | ||||
| 	if (hw->addr_ctrl.rar_used_count < rar_entries) { | ||||
| 		/* use RAR from the end up for multicast */ | ||||
| 		rar = rar_entries - hw->addr_ctrl.mc_addr_in_rar_count - 1; | ||||
| 		hw->mac.ops.set_rar(hw, rar, mc_addr, 0, IXGBE_RAH_AV); | ||||
| 		hw_dbg(hw, "Added a multicast address to RAR[%d]\n", rar); | ||||
| 		hw->addr_ctrl.rar_used_count++; | ||||
| 		hw->addr_ctrl.mc_addr_in_rar_count++; | ||||
| 	} else { | ||||
| 		ixgbe_set_mta(hw, mc_addr); | ||||
| 	} | ||||
| 
 | ||||
| 	hw_dbg(hw, "ixgbe_add_mc_addr Complete\n"); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  *  ixgbe_update_mc_addr_list_generic - Updates MAC list of multicast addresses | ||||
|  *  @hw: pointer to hardware structure | ||||
| @ -1542,7 +1506,6 @@ s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list, | ||||
|                                       u32 mc_addr_count, ixgbe_mc_addr_itr next) | ||||
| { | ||||
| 	u32 i; | ||||
| 	u32 rar_entries = hw->mac.num_rar_entries; | ||||
| 	u32 vmdq; | ||||
| 
 | ||||
| 	/*
 | ||||
| @ -1550,18 +1513,8 @@ s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list, | ||||
| 	 * use. | ||||
| 	 */ | ||||
| 	hw->addr_ctrl.num_mc_addrs = mc_addr_count; | ||||
| 	hw->addr_ctrl.rar_used_count -= hw->addr_ctrl.mc_addr_in_rar_count; | ||||
| 	hw->addr_ctrl.mc_addr_in_rar_count = 0; | ||||
| 	hw->addr_ctrl.mta_in_use = 0; | ||||
| 
 | ||||
| 	/* Zero out the other receive addresses. */ | ||||
| 	hw_dbg(hw, "Clearing RAR[%d-%d]\n", hw->addr_ctrl.rar_used_count, | ||||
| 	          rar_entries - 1); | ||||
| 	for (i = hw->addr_ctrl.rar_used_count; i < rar_entries; i++) { | ||||
| 		IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0); | ||||
| 		IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0); | ||||
| 	} | ||||
| 
 | ||||
| 	/* Clear the MTA */ | ||||
| 	hw_dbg(hw, " Clearing MTA\n"); | ||||
| 	for (i = 0; i < hw->mac.mcft_size; i++) | ||||
| @ -1570,7 +1523,7 @@ s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list, | ||||
| 	/* Add the new addresses */ | ||||
| 	for (i = 0; i < mc_addr_count; i++) { | ||||
| 		hw_dbg(hw, " Adding the multicast addresses:\n"); | ||||
| 		ixgbe_add_mc_addr(hw, next(hw, &mc_addr_list, &vmdq)); | ||||
| 		ixgbe_set_mta(hw, next(hw, &mc_addr_list, &vmdq)); | ||||
| 	} | ||||
| 
 | ||||
| 	/* Enable mta */ | ||||
|  | ||||
| @ -3646,6 +3646,8 @@ static int ixgbe_resume(struct pci_dev *pdev) | ||||
| 
 | ||||
| 	ixgbe_reset(adapter); | ||||
| 
 | ||||
| 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_WUS, ~0); | ||||
| 
 | ||||
| 	if (netif_running(netdev)) { | ||||
| 		err = ixgbe_open(adapter->netdev); | ||||
| 		if (err) | ||||
| @ -4575,7 +4577,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, | ||||
| 	const struct ixgbe_info *ii = ixgbe_info_tbl[ent->driver_data]; | ||||
| 	static int cards_found; | ||||
| 	int i, err, pci_using_dac; | ||||
| 	u16 pm_value = 0; | ||||
| 	u32 part_num, eec; | ||||
| 
 | ||||
| 	err = pci_enable_device(pdev); | ||||
| @ -4763,11 +4764,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, | ||||
| 
 | ||||
| 	switch (pdev->device) { | ||||
| 	case IXGBE_DEV_ID_82599_KX4: | ||||
| #define IXGBE_PCIE_PMCSR 0x44 | ||||
| 		adapter->wol = IXGBE_WUFC_MAG; | ||||
| 		pci_read_config_word(pdev, IXGBE_PCIE_PMCSR, &pm_value); | ||||
| 		pci_write_config_word(pdev, IXGBE_PCIE_PMCSR, | ||||
| 		                      (pm_value | (1 << 8))); | ||||
| 		adapter->wol = (IXGBE_WUFC_MAG | IXGBE_WUFC_EX | | ||||
| 		                IXGBE_WUFC_MC | IXGBE_WUFC_BC); | ||||
| 		break; | ||||
| 	default: | ||||
| 		adapter->wol = 0; | ||||
|  | ||||
| @ -583,7 +583,7 @@ int mlx4_en_start_port(struct net_device *dev) | ||||
| 		err = mlx4_en_activate_cq(priv, cq); | ||||
| 		if (err) { | ||||
| 			mlx4_err(mdev, "Failed activating Rx CQ\n"); | ||||
| 			goto rx_err; | ||||
| 			goto cq_err; | ||||
| 		} | ||||
| 		for (j = 0; j < cq->size; j++) | ||||
| 			cq->buf[j].owner_sr_opcode = MLX4_CQE_OWNER_MASK; | ||||
|  | ||||
| @ -610,6 +610,10 @@ static struct sk_buff *mlx4_en_rx_skb(struct mlx4_en_priv *priv, | ||||
| 		used_frags = mlx4_en_complete_rx_desc(priv, rx_desc, skb_frags, | ||||
| 						      skb_shinfo(skb)->frags, | ||||
| 						      page_alloc, length); | ||||
| 		if (unlikely(!used_frags)) { | ||||
| 			kfree_skb(skb); | ||||
| 			return NULL; | ||||
| 		} | ||||
| 		skb_shinfo(skb)->nr_frags = used_frags; | ||||
| 
 | ||||
| 		/* Copy headers into the skb linear buffer */ | ||||
|  | ||||
| @ -210,14 +210,11 @@ rx_drop: | ||||
| 
 | ||||
| static struct net_device_stats *veth_get_stats(struct net_device *dev) | ||||
| { | ||||
| 	struct veth_priv *priv; | ||||
| 	struct net_device_stats *dev_stats; | ||||
| 	int cpu; | ||||
| 	struct veth_priv *priv = netdev_priv(dev); | ||||
| 	struct net_device_stats *dev_stats = &dev->stats; | ||||
| 	unsigned int cpu; | ||||
| 	struct veth_net_stats *stats; | ||||
| 
 | ||||
| 	priv = netdev_priv(dev); | ||||
| 	dev_stats = &dev->stats; | ||||
| 
 | ||||
| 	dev_stats->rx_packets = 0; | ||||
| 	dev_stats->tx_packets = 0; | ||||
| 	dev_stats->rx_bytes = 0; | ||||
| @ -225,16 +222,17 @@ static struct net_device_stats *veth_get_stats(struct net_device *dev) | ||||
| 	dev_stats->tx_dropped = 0; | ||||
| 	dev_stats->rx_dropped = 0; | ||||
| 
 | ||||
| 	for_each_online_cpu(cpu) { | ||||
| 		stats = per_cpu_ptr(priv->stats, cpu); | ||||
| 	if (priv->stats) | ||||
| 		for_each_online_cpu(cpu) { | ||||
| 			stats = per_cpu_ptr(priv->stats, cpu); | ||||
| 
 | ||||
| 		dev_stats->rx_packets += stats->rx_packets; | ||||
| 		dev_stats->tx_packets += stats->tx_packets; | ||||
| 		dev_stats->rx_bytes += stats->rx_bytes; | ||||
| 		dev_stats->tx_bytes += stats->tx_bytes; | ||||
| 		dev_stats->tx_dropped += stats->tx_dropped; | ||||
| 		dev_stats->rx_dropped += stats->rx_dropped; | ||||
| 	} | ||||
| 			dev_stats->rx_packets += stats->rx_packets; | ||||
| 			dev_stats->tx_packets += stats->tx_packets; | ||||
| 			dev_stats->rx_bytes += stats->rx_bytes; | ||||
| 			dev_stats->tx_bytes += stats->tx_bytes; | ||||
| 			dev_stats->tx_dropped += stats->tx_dropped; | ||||
| 			dev_stats->rx_dropped += stats->rx_dropped; | ||||
| 		} | ||||
| 
 | ||||
| 	return dev_stats; | ||||
| } | ||||
| @ -261,6 +259,8 @@ static int veth_close(struct net_device *dev) | ||||
| 	netif_carrier_off(dev); | ||||
| 	netif_carrier_off(priv->peer); | ||||
| 
 | ||||
| 	free_percpu(priv->stats); | ||||
| 	priv->stats = NULL; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| @ -291,15 +291,6 @@ static int veth_dev_init(struct net_device *dev) | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static void veth_dev_free(struct net_device *dev) | ||||
| { | ||||
| 	struct veth_priv *priv; | ||||
| 
 | ||||
| 	priv = netdev_priv(dev); | ||||
| 	free_percpu(priv->stats); | ||||
| 	free_netdev(dev); | ||||
| } | ||||
| 
 | ||||
| static const struct net_device_ops veth_netdev_ops = { | ||||
| 	.ndo_init            = veth_dev_init, | ||||
| 	.ndo_open            = veth_open, | ||||
| @ -317,7 +308,7 @@ static void veth_setup(struct net_device *dev) | ||||
| 	dev->netdev_ops = &veth_netdev_ops; | ||||
| 	dev->ethtool_ops = &veth_ethtool_ops; | ||||
| 	dev->features |= NETIF_F_LLTX; | ||||
| 	dev->destructor = veth_dev_free; | ||||
| 	dev->destructor = free_netdev; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  | ||||
| @ -667,7 +667,7 @@ ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz) | ||||
| 	lower_buf = kmalloc(lower_bufsiz, GFP_KERNEL); | ||||
| 	if (lower_buf == NULL) { | ||||
| 		printk(KERN_ERR "%s: Out of memory whilst attempting to " | ||||
| 		       "kmalloc [%d] bytes\n", __func__, lower_bufsiz); | ||||
| 		       "kmalloc [%zd] bytes\n", __func__, lower_bufsiz); | ||||
| 		rc = -ENOMEM; | ||||
| 		goto out; | ||||
| 	} | ||||
| @ -690,7 +690,7 @@ ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz) | ||||
| 		} | ||||
| 		/* Check for bufsiz <= 0 done in sys_readlinkat() */ | ||||
| 		rc = copy_to_user(buf, plaintext_name, | ||||
| 				  min((unsigned) bufsiz, plaintext_name_size)); | ||||
| 				  min((size_t) bufsiz, plaintext_name_size)); | ||||
| 		if (rc) | ||||
| 			rc = -EFAULT; | ||||
| 		else | ||||
|  | ||||
| @ -222,6 +222,8 @@ int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from); | ||||
| int copy_siginfo_to_user32(struct compat_siginfo __user *to, siginfo_t *from); | ||||
| int get_compat_sigevent(struct sigevent *event, | ||||
| 		const struct compat_sigevent __user *u_event); | ||||
| long compat_sys_rt_tgsigqueueinfo(compat_pid_t tgid, compat_pid_t pid, int sig, | ||||
| 				  struct compat_siginfo __user *uinfo); | ||||
| 
 | ||||
| static inline int compat_timeval_compare(struct compat_timeval *lhs, | ||||
| 					struct compat_timeval *rhs) | ||||
|  | ||||
| @ -104,7 +104,7 @@ struct wireless_dev; | ||||
| # else | ||||
| #  define LL_MAX_HEADER 96 | ||||
| # endif | ||||
| #elif defined(CONFIG_TR) | ||||
| #elif defined(CONFIG_TR) || defined(CONFIG_TR_MODULE) | ||||
| # define LL_MAX_HEADER 48 | ||||
| #else | ||||
| # define LL_MAX_HEADER 32 | ||||
| @ -500,7 +500,7 @@ struct netdev_queue { | ||||
|  * | ||||
|  * int (*ndo_set_mac_address)(struct net_device *dev, void *addr); | ||||
|  *	This function  is called when the Media Access Control address | ||||
|  *	needs to be changed. If not this interface is not defined, the | ||||
|  *	needs to be changed. If this interface is not defined, the | ||||
|  *	mac address can not be changed. | ||||
|  * | ||||
|  * int (*ndo_validate_addr)(struct net_device *dev); | ||||
|  | ||||
| @ -100,6 +100,7 @@ enum ctattr_protoinfo_tcp { | ||||
| enum ctattr_protoinfo_dccp { | ||||
| 	CTA_PROTOINFO_DCCP_UNSPEC, | ||||
| 	CTA_PROTOINFO_DCCP_STATE, | ||||
| 	CTA_PROTOINFO_DCCP_ROLE, | ||||
| 	__CTA_PROTOINFO_DCCP_MAX, | ||||
| }; | ||||
| #define CTA_PROTOINFO_DCCP_MAX (__CTA_PROTOINFO_DCCP_MAX - 1) | ||||
|  | ||||
| @ -354,9 +354,6 @@ struct xt_table | ||||
| 	/* What hooks you will enter on */ | ||||
| 	unsigned int valid_hooks; | ||||
| 
 | ||||
| 	/* Lock for the curtain */ | ||||
| 	struct mutex lock; | ||||
| 
 | ||||
| 	/* Man behind the curtain... */ | ||||
| 	struct xt_table_info *private; | ||||
| 
 | ||||
| @ -434,8 +431,74 @@ extern void xt_proto_fini(struct net *net, u_int8_t af); | ||||
| 
 | ||||
| extern struct xt_table_info *xt_alloc_table_info(unsigned int size); | ||||
| extern void xt_free_table_info(struct xt_table_info *info); | ||||
| extern void xt_table_entry_swap_rcu(struct xt_table_info *old, | ||||
| 				    struct xt_table_info *new); | ||||
| 
 | ||||
| /*
 | ||||
|  * Per-CPU spinlock associated with per-cpu table entries, and | ||||
|  * with a counter for the "reading" side that allows a recursive | ||||
|  * reader to avoid taking the lock and deadlocking. | ||||
|  * | ||||
|  * "reading" is used by ip/arp/ip6 tables rule processing which runs per-cpu. | ||||
|  * It needs to ensure that the rules are not being changed while the packet | ||||
|  * is being processed. In some cases, the read lock will be acquired | ||||
|  * twice on the same CPU; this is okay because of the count. | ||||
|  * | ||||
|  * "writing" is used when reading counters. | ||||
|  *  During replace any readers that are using the old tables have to complete | ||||
|  *  before freeing the old table. This is handled by the write locking | ||||
|  *  necessary for reading the counters. | ||||
|  */ | ||||
| struct xt_info_lock { | ||||
| 	spinlock_t lock; | ||||
| 	unsigned char readers; | ||||
| }; | ||||
| DECLARE_PER_CPU(struct xt_info_lock, xt_info_locks); | ||||
| 
 | ||||
| /*
 | ||||
|  * Note: we need to ensure that preemption is disabled before acquiring | ||||
|  * the per-cpu-variable, so we do it as a two step process rather than | ||||
|  * using "spin_lock_bh()". | ||||
|  * | ||||
|  * We _also_ need to disable bottom half processing before updating our | ||||
|  * nesting count, to make sure that the only kind of re-entrancy is this | ||||
|  * code being called by itself: since the count+lock is not an atomic | ||||
|  * operation, we can allow no races. | ||||
|  * | ||||
|  * _Only_ that special combination of being per-cpu and never getting | ||||
|  * re-entered asynchronously means that the count is safe. | ||||
|  */ | ||||
| static inline void xt_info_rdlock_bh(void) | ||||
| { | ||||
| 	struct xt_info_lock *lock; | ||||
| 
 | ||||
| 	local_bh_disable(); | ||||
| 	lock = &__get_cpu_var(xt_info_locks); | ||||
| 	if (!lock->readers++) | ||||
| 		spin_lock(&lock->lock); | ||||
| } | ||||
| 
 | ||||
| static inline void xt_info_rdunlock_bh(void) | ||||
| { | ||||
| 	struct xt_info_lock *lock = &__get_cpu_var(xt_info_locks); | ||||
| 
 | ||||
| 	if (!--lock->readers) | ||||
| 		spin_unlock(&lock->lock); | ||||
| 	local_bh_enable(); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * The "writer" side needs to get exclusive access to the lock, | ||||
|  * regardless of readers.  This must be called with bottom half | ||||
|  * processing (and thus also preemption) disabled. | ||||
|  */ | ||||
| static inline void xt_info_wrlock(unsigned int cpu) | ||||
| { | ||||
| 	spin_lock(&per_cpu(xt_info_locks, cpu).lock); | ||||
| } | ||||
| 
 | ||||
| static inline void xt_info_wrunlock(unsigned int cpu) | ||||
| { | ||||
| 	spin_unlock(&per_cpu(xt_info_locks, cpu).lock); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * This helper is performance critical and must be inlined | ||||
|  | ||||
| @ -235,6 +235,8 @@ static inline int valid_signal(unsigned long sig) | ||||
| extern int next_signal(struct sigpending *pending, sigset_t *mask); | ||||
| extern int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p); | ||||
| extern int __group_send_sig_info(int, struct siginfo *, struct task_struct *); | ||||
| extern long do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, | ||||
| 				 siginfo_t *info); | ||||
| extern long do_sigpending(void __user *, unsigned long); | ||||
| extern int sigprocmask(int, sigset_t *, sigset_t *); | ||||
| extern int show_unhandled_signals; | ||||
|  | ||||
| @ -440,13 +440,15 @@ void abort_exclusive_wait(wait_queue_head_t *q, wait_queue_t *wait, | ||||
| int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key); | ||||
| int wake_bit_function(wait_queue_t *wait, unsigned mode, int sync, void *key); | ||||
| 
 | ||||
| #define DEFINE_WAIT(name)						\ | ||||
| #define DEFINE_WAIT_FUNC(name, function)				\ | ||||
| 	wait_queue_t name = {						\ | ||||
| 		.private	= current,				\ | ||||
| 		.func		= autoremove_wake_function,		\ | ||||
| 		.func		= function,				\ | ||||
| 		.task_list	= LIST_HEAD_INIT((name).task_list),	\ | ||||
| 	} | ||||
| 
 | ||||
| #define DEFINE_WAIT(name) DEFINE_WAIT_FUNC(name, autoremove_wake_function) | ||||
| 
 | ||||
| #define DEFINE_WAIT_BIT(name, word, bit)				\ | ||||
| 	struct wait_bit_queue name = {					\ | ||||
| 		.key = __WAIT_BIT_KEY_INITIALIZER(word, bit),		\ | ||||
|  | ||||
| @ -101,6 +101,7 @@ enum { | ||||
| /* HCI timeouts */ | ||||
| #define HCI_CONNECT_TIMEOUT	(40000)	/* 40 seconds */ | ||||
| #define HCI_DISCONN_TIMEOUT	(2000)	/* 2 seconds */ | ||||
| #define HCI_PAIRING_TIMEOUT	(60000)	/* 60 seconds */ | ||||
| #define HCI_IDLE_TIMEOUT	(6000)	/* 6 seconds */ | ||||
| #define HCI_INIT_TIMEOUT	(10000)	/* 10 seconds */ | ||||
| 
 | ||||
|  | ||||
| @ -171,6 +171,7 @@ struct hci_conn { | ||||
| 	__u8             auth_type; | ||||
| 	__u8             sec_level; | ||||
| 	__u8             power_save; | ||||
| 	__u16            disc_timeout; | ||||
| 	unsigned long	 pend; | ||||
| 
 | ||||
| 	unsigned int	 sent; | ||||
| @ -180,7 +181,8 @@ struct hci_conn { | ||||
| 	struct timer_list disc_timer; | ||||
| 	struct timer_list idle_timer; | ||||
| 
 | ||||
| 	struct work_struct work; | ||||
| 	struct work_struct work_add; | ||||
| 	struct work_struct work_del; | ||||
| 
 | ||||
| 	struct device	dev; | ||||
| 
 | ||||
| @ -348,9 +350,9 @@ static inline void hci_conn_put(struct hci_conn *conn) | ||||
| 		if (conn->type == ACL_LINK) { | ||||
| 			del_timer(&conn->idle_timer); | ||||
| 			if (conn->state == BT_CONNECTED) { | ||||
| 				timeo = msecs_to_jiffies(HCI_DISCONN_TIMEOUT); | ||||
| 				timeo = msecs_to_jiffies(conn->disc_timeout); | ||||
| 				if (!conn->out) | ||||
| 					timeo *= 5; | ||||
| 					timeo *= 2; | ||||
| 			} else | ||||
| 				timeo = msecs_to_jiffies(10); | ||||
| 		} else | ||||
|  | ||||
| @ -882,6 +882,17 @@ compat_sys_rt_sigtimedwait (compat_sigset_t __user *uthese, | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| asmlinkage long | ||||
| compat_sys_rt_tgsigqueueinfo(compat_pid_t tgid, compat_pid_t pid, int sig, | ||||
| 			     struct compat_siginfo __user *uinfo) | ||||
| { | ||||
| 	siginfo_t info; | ||||
| 
 | ||||
| 	if (copy_siginfo_from_user32(&info, uinfo)) | ||||
| 		return -EFAULT; | ||||
| 	return do_rt_tgsigqueueinfo(tgid, pid, sig, &info); | ||||
| } | ||||
| 
 | ||||
| #ifdef __ARCH_WANT_COMPAT_SYS_TIME | ||||
| 
 | ||||
| /* compat_time_t is a 32 bit "long" and needs to get converted. */ | ||||
|  | ||||
| @ -2278,24 +2278,17 @@ SYSCALL_DEFINE2(kill, pid_t, pid, int, sig) | ||||
| 	return kill_something_info(sig, &info, pid); | ||||
| } | ||||
| 
 | ||||
| static int do_tkill(pid_t tgid, pid_t pid, int sig) | ||||
| static int | ||||
| do_send_specific(pid_t tgid, pid_t pid, int sig, struct siginfo *info) | ||||
| { | ||||
| 	int error; | ||||
| 	struct siginfo info; | ||||
| 	struct task_struct *p; | ||||
| 	unsigned long flags; | ||||
| 
 | ||||
| 	error = -ESRCH; | ||||
| 	info.si_signo = sig; | ||||
| 	info.si_errno = 0; | ||||
| 	info.si_code = SI_TKILL; | ||||
| 	info.si_pid = task_tgid_vnr(current); | ||||
| 	info.si_uid = current_uid(); | ||||
| 	int error = -ESRCH; | ||||
| 
 | ||||
| 	rcu_read_lock(); | ||||
| 	p = find_task_by_vpid(pid); | ||||
| 	if (p && (tgid <= 0 || task_tgid_vnr(p) == tgid)) { | ||||
| 		error = check_kill_permission(sig, &info, p); | ||||
| 		error = check_kill_permission(sig, info, p); | ||||
| 		/*
 | ||||
| 		 * The null signal is a permissions and process existence | ||||
| 		 * probe.  No signal is actually delivered. | ||||
| @ -2305,7 +2298,7 @@ static int do_tkill(pid_t tgid, pid_t pid, int sig) | ||||
| 		 * signal is private anyway. | ||||
| 		 */ | ||||
| 		if (!error && sig && lock_task_sighand(p, &flags)) { | ||||
| 			error = specific_send_sig_info(sig, &info, p); | ||||
| 			error = specific_send_sig_info(sig, info, p); | ||||
| 			unlock_task_sighand(p, &flags); | ||||
| 		} | ||||
| 	} | ||||
| @ -2314,6 +2307,19 @@ static int do_tkill(pid_t tgid, pid_t pid, int sig) | ||||
| 	return error; | ||||
| } | ||||
| 
 | ||||
| static int do_tkill(pid_t tgid, pid_t pid, int sig) | ||||
| { | ||||
| 	struct siginfo info; | ||||
| 
 | ||||
| 	info.si_signo = sig; | ||||
| 	info.si_errno = 0; | ||||
| 	info.si_code = SI_TKILL; | ||||
| 	info.si_pid = task_tgid_vnr(current); | ||||
| 	info.si_uid = current_uid(); | ||||
| 
 | ||||
| 	return do_send_specific(tgid, pid, sig, &info); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  *  sys_tgkill - send signal to one specific thread | ||||
|  *  @tgid: the thread group ID of the thread | ||||
| @ -2363,6 +2369,32 @@ SYSCALL_DEFINE3(rt_sigqueueinfo, pid_t, pid, int, sig, | ||||
| 	return kill_proc_info(sig, &info, pid); | ||||
| } | ||||
| 
 | ||||
| long do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, siginfo_t *info) | ||||
| { | ||||
| 	/* This is only valid for single tasks */ | ||||
| 	if (pid <= 0 || tgid <= 0) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	/* Not even root can pretend to send signals from the kernel.
 | ||||
| 	   Nor can they impersonate a kill(), which adds source info.  */ | ||||
| 	if (info->si_code >= 0) | ||||
| 		return -EPERM; | ||||
| 	info->si_signo = sig; | ||||
| 
 | ||||
| 	return do_send_specific(tgid, pid, sig, info); | ||||
| } | ||||
| 
 | ||||
| SYSCALL_DEFINE4(rt_tgsigqueueinfo, pid_t, tgid, pid_t, pid, int, sig, | ||||
| 		siginfo_t __user *, uinfo) | ||||
| { | ||||
| 	siginfo_t info; | ||||
| 
 | ||||
| 	if (copy_from_user(&info, uinfo, sizeof(siginfo_t))) | ||||
| 		return -EFAULT; | ||||
| 
 | ||||
| 	return do_rt_tgsigqueueinfo(tgid, pid, sig, &info); | ||||
| } | ||||
| 
 | ||||
| int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact) | ||||
| { | ||||
| 	struct task_struct *t = current; | ||||
|  | ||||
| @ -492,6 +492,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, | ||||
| 				continue; | ||||
| 
 | ||||
| 			dev_change_flags(vlandev, flgs & ~IFF_UP); | ||||
| 			vlan_transfer_operstate(dev, vlandev); | ||||
| 		} | ||||
| 		break; | ||||
| 
 | ||||
| @ -507,6 +508,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, | ||||
| 				continue; | ||||
| 
 | ||||
| 			dev_change_flags(vlandev, flgs | IFF_UP); | ||||
| 			vlan_transfer_operstate(dev, vlandev); | ||||
| 		} | ||||
| 		break; | ||||
| 
 | ||||
|  | ||||
| @ -462,6 +462,7 @@ static int vlan_dev_open(struct net_device *dev) | ||||
| 	if (vlan->flags & VLAN_FLAG_GVRP) | ||||
| 		vlan_gvrp_request_join(dev); | ||||
| 
 | ||||
| 	netif_carrier_on(dev); | ||||
| 	return 0; | ||||
| 
 | ||||
| clear_allmulti: | ||||
| @ -471,6 +472,7 @@ del_unicast: | ||||
| 	if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) | ||||
| 		dev_unicast_delete(real_dev, dev->dev_addr, ETH_ALEN); | ||||
| out: | ||||
| 	netif_carrier_off(dev); | ||||
| 	return err; | ||||
| } | ||||
| 
 | ||||
| @ -492,6 +494,7 @@ static int vlan_dev_stop(struct net_device *dev) | ||||
| 	if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) | ||||
| 		dev_unicast_delete(real_dev, dev->dev_addr, dev->addr_len); | ||||
| 
 | ||||
| 	netif_carrier_off(dev); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| @ -612,6 +615,8 @@ static int vlan_dev_init(struct net_device *dev) | ||||
| 	struct net_device *real_dev = vlan_dev_info(dev)->real_dev; | ||||
| 	int subclass = 0; | ||||
| 
 | ||||
| 	netif_carrier_off(dev); | ||||
| 
 | ||||
| 	/* IFF_BROADCAST|IFF_MULTICAST; ??? */ | ||||
| 	dev->flags  = real_dev->flags & ~(IFF_UP | IFF_PROMISC | IFF_ALLMULTI); | ||||
| 	dev->iflink = real_dev->ifindex; | ||||
|  | ||||
| @ -215,6 +215,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) | ||||
| 	conn->state = BT_OPEN; | ||||
| 
 | ||||
| 	conn->power_save = 1; | ||||
| 	conn->disc_timeout = HCI_DISCONN_TIMEOUT; | ||||
| 
 | ||||
| 	switch (type) { | ||||
| 	case ACL_LINK: | ||||
| @ -424,12 +425,9 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) | ||||
| 	if (sec_level == BT_SECURITY_SDP) | ||||
| 		return 1; | ||||
| 
 | ||||
| 	if (sec_level == BT_SECURITY_LOW) { | ||||
| 		if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0) | ||||
| 			return hci_conn_auth(conn, sec_level, auth_type); | ||||
| 		else | ||||
| 			return 1; | ||||
| 	} | ||||
| 	if (sec_level == BT_SECURITY_LOW && | ||||
| 				(!conn->ssp_mode || !conn->hdev->ssp_mode)) | ||||
| 		return 1; | ||||
| 
 | ||||
| 	if (conn->link_mode & HCI_LM_ENCRYPT) | ||||
| 		return hci_conn_auth(conn, sec_level, auth_type); | ||||
|  | ||||
| @ -883,6 +883,7 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s | ||||
| 		if (conn->type == ACL_LINK) { | ||||
| 			conn->state = BT_CONFIG; | ||||
| 			hci_conn_hold(conn); | ||||
| 			conn->disc_timeout = HCI_DISCONN_TIMEOUT; | ||||
| 		} else | ||||
| 			conn->state = BT_CONNECTED; | ||||
| 
 | ||||
| @ -1063,9 +1064,14 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s | ||||
| 				hci_proto_connect_cfm(conn, ev->status); | ||||
| 				hci_conn_put(conn); | ||||
| 			} | ||||
| 		} else | ||||
| 		} else { | ||||
| 			hci_auth_cfm(conn, ev->status); | ||||
| 
 | ||||
| 			hci_conn_hold(conn); | ||||
| 			conn->disc_timeout = HCI_DISCONN_TIMEOUT; | ||||
| 			hci_conn_put(conn); | ||||
| 		} | ||||
| 
 | ||||
| 		if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) { | ||||
| 			if (!ev->status) { | ||||
| 				struct hci_cp_set_conn_encrypt cp; | ||||
| @ -1479,7 +1485,21 @@ static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb | ||||
| 
 | ||||
| static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||||
| { | ||||
| 	struct hci_ev_pin_code_req *ev = (void *) skb->data; | ||||
| 	struct hci_conn *conn; | ||||
| 
 | ||||
| 	BT_DBG("%s", hdev->name); | ||||
| 
 | ||||
| 	hci_dev_lock(hdev); | ||||
| 
 | ||||
| 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); | ||||
| 	if (conn) { | ||||
| 		hci_conn_hold(conn); | ||||
| 		conn->disc_timeout = HCI_PAIRING_TIMEOUT; | ||||
| 		hci_conn_put(conn); | ||||
| 	} | ||||
| 
 | ||||
| 	hci_dev_unlock(hdev); | ||||
| } | ||||
| 
 | ||||
| static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||||
| @ -1489,7 +1509,21 @@ static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff | ||||
| 
 | ||||
| static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||||
| { | ||||
| 	struct hci_ev_link_key_notify *ev = (void *) skb->data; | ||||
| 	struct hci_conn *conn; | ||||
| 
 | ||||
| 	BT_DBG("%s", hdev->name); | ||||
| 
 | ||||
| 	hci_dev_lock(hdev); | ||||
| 
 | ||||
| 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); | ||||
| 	if (conn) { | ||||
| 		hci_conn_hold(conn); | ||||
| 		conn->disc_timeout = HCI_DISCONN_TIMEOUT; | ||||
| 		hci_conn_put(conn); | ||||
| 	} | ||||
| 
 | ||||
| 	hci_dev_unlock(hdev); | ||||
| } | ||||
| 
 | ||||
| static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||||
|  | ||||
| @ -9,8 +9,7 @@ | ||||
| struct class *bt_class = NULL; | ||||
| EXPORT_SYMBOL_GPL(bt_class); | ||||
| 
 | ||||
| static struct workqueue_struct *btaddconn; | ||||
| static struct workqueue_struct *btdelconn; | ||||
| static struct workqueue_struct *bluetooth; | ||||
| 
 | ||||
| static inline char *link_typetostr(int type) | ||||
| { | ||||
| @ -88,9 +87,10 @@ static struct device_type bt_link = { | ||||
| 
 | ||||
| static void add_conn(struct work_struct *work) | ||||
| { | ||||
| 	struct hci_conn *conn = container_of(work, struct hci_conn, work); | ||||
| 	struct hci_conn *conn = container_of(work, struct hci_conn, work_add); | ||||
| 
 | ||||
| 	flush_workqueue(btdelconn); | ||||
| 	/* ensure previous add/del is complete */ | ||||
| 	flush_workqueue(bluetooth); | ||||
| 
 | ||||
| 	if (device_add(&conn->dev) < 0) { | ||||
| 		BT_ERR("Failed to register connection device"); | ||||
| @ -114,9 +114,9 @@ void hci_conn_add_sysfs(struct hci_conn *conn) | ||||
| 
 | ||||
| 	device_initialize(&conn->dev); | ||||
| 
 | ||||
| 	INIT_WORK(&conn->work, add_conn); | ||||
| 	INIT_WORK(&conn->work_add, add_conn); | ||||
| 
 | ||||
| 	queue_work(btaddconn, &conn->work); | ||||
| 	queue_work(bluetooth, &conn->work_add); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
| @ -131,9 +131,12 @@ static int __match_tty(struct device *dev, void *data) | ||||
| 
 | ||||
| static void del_conn(struct work_struct *work) | ||||
| { | ||||
| 	struct hci_conn *conn = container_of(work, struct hci_conn, work); | ||||
| 	struct hci_conn *conn = container_of(work, struct hci_conn, work_del); | ||||
| 	struct hci_dev *hdev = conn->hdev; | ||||
| 
 | ||||
| 	/* ensure previous add/del is complete */ | ||||
| 	flush_workqueue(bluetooth); | ||||
| 
 | ||||
| 	while (1) { | ||||
| 		struct device *dev; | ||||
| 
 | ||||
| @ -156,9 +159,9 @@ void hci_conn_del_sysfs(struct hci_conn *conn) | ||||
| 	if (!device_is_registered(&conn->dev)) | ||||
| 		return; | ||||
| 
 | ||||
| 	INIT_WORK(&conn->work, del_conn); | ||||
| 	INIT_WORK(&conn->work_del, del_conn); | ||||
| 
 | ||||
| 	queue_work(btdelconn, &conn->work); | ||||
| 	queue_work(bluetooth, &conn->work_del); | ||||
| } | ||||
| 
 | ||||
| static inline char *host_typetostr(int type) | ||||
| @ -435,20 +438,13 @@ void hci_unregister_sysfs(struct hci_dev *hdev) | ||||
| 
 | ||||
| int __init bt_sysfs_init(void) | ||||
| { | ||||
| 	btaddconn = create_singlethread_workqueue("btaddconn"); | ||||
| 	if (!btaddconn) | ||||
| 	bluetooth = create_singlethread_workqueue("bluetooth"); | ||||
| 	if (!bluetooth) | ||||
| 		return -ENOMEM; | ||||
| 
 | ||||
| 	btdelconn = create_singlethread_workqueue("btdelconn"); | ||||
| 	if (!btdelconn) { | ||||
| 		destroy_workqueue(btaddconn); | ||||
| 		return -ENOMEM; | ||||
| 	} | ||||
| 
 | ||||
| 	bt_class = class_create(THIS_MODULE, "bluetooth"); | ||||
| 	if (IS_ERR(bt_class)) { | ||||
| 		destroy_workqueue(btdelconn); | ||||
| 		destroy_workqueue(btaddconn); | ||||
| 		destroy_workqueue(bluetooth); | ||||
| 		return PTR_ERR(bt_class); | ||||
| 	} | ||||
| 
 | ||||
| @ -457,8 +453,7 @@ int __init bt_sysfs_init(void) | ||||
| 
 | ||||
| void bt_sysfs_cleanup(void) | ||||
| { | ||||
| 	destroy_workqueue(btaddconn); | ||||
| 	destroy_workqueue(btdelconn); | ||||
| 	destroy_workqueue(bluetooth); | ||||
| 
 | ||||
| 	class_destroy(bt_class); | ||||
| } | ||||
|  | ||||
| @ -788,15 +788,23 @@ static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff *skb, | ||||
| 	return NF_STOLEN; | ||||
| } | ||||
| 
 | ||||
| #if defined(CONFIG_NF_CONNTRACK_IPV4) || defined(CONFIG_NF_CONNTRACK_IPV4_MODULE) | ||||
| static int br_nf_dev_queue_xmit(struct sk_buff *skb) | ||||
| { | ||||
| 	if (skb->protocol == htons(ETH_P_IP) && | ||||
| 	if (skb->nfct != NULL && | ||||
| 	    (skb->protocol == htons(ETH_P_IP) || IS_VLAN_IP(skb)) && | ||||
| 	    skb->len > skb->dev->mtu && | ||||
| 	    !skb_is_gso(skb)) | ||||
| 		return ip_fragment(skb, br_dev_queue_push_xmit); | ||||
| 	else | ||||
| 		return br_dev_queue_push_xmit(skb); | ||||
| } | ||||
| #else | ||||
| static int br_nf_dev_queue_xmit(struct sk_buff *skb) | ||||
| { | ||||
|         return br_dev_queue_push_xmit(skb); | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| /* PF_BRIDGE/POST_ROUTING ********************************************/ | ||||
| static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff *skb, | ||||
|  | ||||
| @ -64,13 +64,25 @@ static inline int connection_based(struct sock *sk) | ||||
| 	return sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM; | ||||
| } | ||||
| 
 | ||||
| static int receiver_wake_function(wait_queue_t *wait, unsigned mode, int sync, | ||||
| 				  void *key) | ||||
| { | ||||
| 	unsigned long bits = (unsigned long)key; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Avoid a wakeup if event not interesting for us | ||||
| 	 */ | ||||
| 	if (bits && !(bits & (POLLIN | POLLERR))) | ||||
| 		return 0; | ||||
| 	return autoremove_wake_function(wait, mode, sync, key); | ||||
| } | ||||
| /*
 | ||||
|  * Wait for a packet.. | ||||
|  */ | ||||
| static int wait_for_packet(struct sock *sk, int *err, long *timeo_p) | ||||
| { | ||||
| 	int error; | ||||
| 	DEFINE_WAIT(wait); | ||||
| 	DEFINE_WAIT_FUNC(wait, receiver_wake_function); | ||||
| 
 | ||||
| 	prepare_to_wait_exclusive(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | ||||
| 
 | ||||
|  | ||||
| @ -253,9 +253,9 @@ unsigned int arpt_do_table(struct sk_buff *skb, | ||||
| 	indev = in ? in->name : nulldevname; | ||||
| 	outdev = out ? out->name : nulldevname; | ||||
| 
 | ||||
| 	rcu_read_lock_bh(); | ||||
| 	private = rcu_dereference(table->private); | ||||
| 	table_base = rcu_dereference(private->entries[smp_processor_id()]); | ||||
| 	xt_info_rdlock_bh(); | ||||
| 	private = table->private; | ||||
| 	table_base = private->entries[smp_processor_id()]; | ||||
| 
 | ||||
| 	e = get_entry(table_base, private->hook_entry[hook]); | ||||
| 	back = get_entry(table_base, private->underflow[hook]); | ||||
| @ -273,6 +273,7 @@ unsigned int arpt_do_table(struct sk_buff *skb, | ||||
| 
 | ||||
| 			hdr_len = sizeof(*arp) + (2 * sizeof(struct in_addr)) + | ||||
| 				(2 * skb->dev->addr_len); | ||||
| 
 | ||||
| 			ADD_COUNTER(e->counters, hdr_len, 1); | ||||
| 
 | ||||
| 			t = arpt_get_target(e); | ||||
| @ -328,8 +329,7 @@ unsigned int arpt_do_table(struct sk_buff *skb, | ||||
| 			e = (void *)e + e->next_offset; | ||||
| 		} | ||||
| 	} while (!hotdrop); | ||||
| 
 | ||||
| 	rcu_read_unlock_bh(); | ||||
| 	xt_info_rdunlock_bh(); | ||||
| 
 | ||||
| 	if (hotdrop) | ||||
| 		return NF_DROP; | ||||
| @ -711,9 +711,12 @@ static void get_counters(const struct xt_table_info *t, | ||||
| 	/* Instead of clearing (by a previous call to memset())
 | ||||
| 	 * the counters and using adds, we set the counters | ||||
| 	 * with data used by 'current' CPU | ||||
| 	 * We dont care about preemption here. | ||||
| 	 * | ||||
| 	 * Bottom half has to be disabled to prevent deadlock | ||||
| 	 * if new softirq were to run and call ipt_do_table | ||||
| 	 */ | ||||
| 	curcpu = raw_smp_processor_id(); | ||||
| 	local_bh_disable(); | ||||
| 	curcpu = smp_processor_id(); | ||||
| 
 | ||||
| 	i = 0; | ||||
| 	ARPT_ENTRY_ITERATE(t->entries[curcpu], | ||||
| @ -726,73 +729,22 @@ static void get_counters(const struct xt_table_info *t, | ||||
| 		if (cpu == curcpu) | ||||
| 			continue; | ||||
| 		i = 0; | ||||
| 		xt_info_wrlock(cpu); | ||||
| 		ARPT_ENTRY_ITERATE(t->entries[cpu], | ||||
| 				   t->size, | ||||
| 				   add_entry_to_counter, | ||||
| 				   counters, | ||||
| 				   &i); | ||||
| 		xt_info_wrunlock(cpu); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* We're lazy, and add to the first CPU; overflow works its fey magic
 | ||||
|  * and everything is OK. */ | ||||
| static int | ||||
| add_counter_to_entry(struct arpt_entry *e, | ||||
| 		     const struct xt_counters addme[], | ||||
| 		     unsigned int *i) | ||||
| { | ||||
| 	ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt); | ||||
| 
 | ||||
| 	(*i)++; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /* Take values from counters and add them back onto the current cpu */ | ||||
| static void put_counters(struct xt_table_info *t, | ||||
| 			 const struct xt_counters counters[]) | ||||
| { | ||||
| 	unsigned int i, cpu; | ||||
| 
 | ||||
| 	local_bh_disable(); | ||||
| 	cpu = smp_processor_id(); | ||||
| 	i = 0; | ||||
| 	ARPT_ENTRY_ITERATE(t->entries[cpu], | ||||
| 			  t->size, | ||||
| 			  add_counter_to_entry, | ||||
| 			  counters, | ||||
| 			  &i); | ||||
| 	local_bh_enable(); | ||||
| } | ||||
| 
 | ||||
| static inline int | ||||
| zero_entry_counter(struct arpt_entry *e, void *arg) | ||||
| { | ||||
| 	e->counters.bcnt = 0; | ||||
| 	e->counters.pcnt = 0; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| clone_counters(struct xt_table_info *newinfo, const struct xt_table_info *info) | ||||
| { | ||||
| 	unsigned int cpu; | ||||
| 	const void *loc_cpu_entry = info->entries[raw_smp_processor_id()]; | ||||
| 
 | ||||
| 	memcpy(newinfo, info, offsetof(struct xt_table_info, entries)); | ||||
| 	for_each_possible_cpu(cpu) { | ||||
| 		memcpy(newinfo->entries[cpu], loc_cpu_entry, info->size); | ||||
| 		ARPT_ENTRY_ITERATE(newinfo->entries[cpu], newinfo->size, | ||||
| 				  zero_entry_counter, NULL); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static struct xt_counters *alloc_counters(struct xt_table *table) | ||||
| { | ||||
| 	unsigned int countersize; | ||||
| 	struct xt_counters *counters; | ||||
| 	struct xt_table_info *private = table->private; | ||||
| 	struct xt_table_info *info; | ||||
| 
 | ||||
| 	/* We need atomic snapshot of counters: rest doesn't change
 | ||||
| 	 * (other than comefrom, which userspace doesn't care | ||||
| @ -802,30 +754,11 @@ static struct xt_counters *alloc_counters(struct xt_table *table) | ||||
| 	counters = vmalloc_node(countersize, numa_node_id()); | ||||
| 
 | ||||
| 	if (counters == NULL) | ||||
| 		goto nomem; | ||||
| 		return ERR_PTR(-ENOMEM); | ||||
| 
 | ||||
| 	info = xt_alloc_table_info(private->size); | ||||
| 	if (!info) | ||||
| 		goto free_counters; | ||||
| 
 | ||||
| 	clone_counters(info, private); | ||||
| 
 | ||||
| 	mutex_lock(&table->lock); | ||||
| 	xt_table_entry_swap_rcu(private, info); | ||||
| 	synchronize_net();	/* Wait until smoke has cleared */ | ||||
| 
 | ||||
| 	get_counters(info, counters); | ||||
| 	put_counters(private, counters); | ||||
| 	mutex_unlock(&table->lock); | ||||
| 
 | ||||
| 	xt_free_table_info(info); | ||||
| 	get_counters(private, counters); | ||||
| 
 | ||||
| 	return counters; | ||||
| 
 | ||||
|  free_counters: | ||||
| 	vfree(counters); | ||||
|  nomem: | ||||
| 	return ERR_PTR(-ENOMEM); | ||||
| } | ||||
| 
 | ||||
| static int copy_entries_to_user(unsigned int total_size, | ||||
| @ -1094,8 +1027,9 @@ static int __do_replace(struct net *net, const char *name, | ||||
| 	    (newinfo->number <= oldinfo->initial_entries)) | ||||
| 		module_put(t->me); | ||||
| 
 | ||||
| 	/* Get the old counters. */ | ||||
| 	/* Get the old counters, and synchronize with replace */ | ||||
| 	get_counters(oldinfo, counters); | ||||
| 
 | ||||
| 	/* Decrease module usage counts and free resource */ | ||||
| 	loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; | ||||
| 	ARPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry, | ||||
| @ -1165,10 +1099,23 @@ static int do_replace(struct net *net, void __user *user, unsigned int len) | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| /* We're lazy, and add to the first CPU; overflow works its fey magic
 | ||||
|  * and everything is OK. */ | ||||
| static int | ||||
| add_counter_to_entry(struct arpt_entry *e, | ||||
| 		     const struct xt_counters addme[], | ||||
| 		     unsigned int *i) | ||||
| { | ||||
| 	ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt); | ||||
| 
 | ||||
| 	(*i)++; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int do_add_counters(struct net *net, void __user *user, unsigned int len, | ||||
| 			   int compat) | ||||
| { | ||||
| 	unsigned int i; | ||||
| 	unsigned int i, curcpu; | ||||
| 	struct xt_counters_info tmp; | ||||
| 	struct xt_counters *paddc; | ||||
| 	unsigned int num_counters; | ||||
| @ -1224,26 +1171,26 @@ static int do_add_counters(struct net *net, void __user *user, unsigned int len, | ||||
| 		goto free; | ||||
| 	} | ||||
| 
 | ||||
| 	mutex_lock(&t->lock); | ||||
| 	local_bh_disable(); | ||||
| 	private = t->private; | ||||
| 	if (private->number != num_counters) { | ||||
| 		ret = -EINVAL; | ||||
| 		goto unlock_up_free; | ||||
| 	} | ||||
| 
 | ||||
| 	preempt_disable(); | ||||
| 	i = 0; | ||||
| 	/* Choose the copy that is on our node */ | ||||
| 	loc_cpu_entry = private->entries[smp_processor_id()]; | ||||
| 	curcpu = smp_processor_id(); | ||||
| 	loc_cpu_entry = private->entries[curcpu]; | ||||
| 	xt_info_wrlock(curcpu); | ||||
| 	ARPT_ENTRY_ITERATE(loc_cpu_entry, | ||||
| 			   private->size, | ||||
| 			   add_counter_to_entry, | ||||
| 			   paddc, | ||||
| 			   &i); | ||||
| 	preempt_enable(); | ||||
| 	xt_info_wrunlock(curcpu); | ||||
|  unlock_up_free: | ||||
| 	mutex_unlock(&t->lock); | ||||
| 
 | ||||
| 	local_bh_enable(); | ||||
| 	xt_table_unlock(t); | ||||
| 	module_put(t->me); | ||||
|  free: | ||||
|  | ||||
| @ -338,10 +338,9 @@ ipt_do_table(struct sk_buff *skb, | ||||
| 	tgpar.hooknum = hook; | ||||
| 
 | ||||
| 	IP_NF_ASSERT(table->valid_hooks & (1 << hook)); | ||||
| 
 | ||||
| 	rcu_read_lock_bh(); | ||||
| 	private = rcu_dereference(table->private); | ||||
| 	table_base = rcu_dereference(private->entries[smp_processor_id()]); | ||||
| 	xt_info_rdlock_bh(); | ||||
| 	private = table->private; | ||||
| 	table_base = private->entries[smp_processor_id()]; | ||||
| 
 | ||||
| 	e = get_entry(table_base, private->hook_entry[hook]); | ||||
| 
 | ||||
| @ -436,8 +435,7 @@ ipt_do_table(struct sk_buff *skb, | ||||
| 			e = (void *)e + e->next_offset; | ||||
| 		} | ||||
| 	} while (!hotdrop); | ||||
| 
 | ||||
| 	rcu_read_unlock_bh(); | ||||
| 	xt_info_rdunlock_bh(); | ||||
| 
 | ||||
| #ifdef DEBUG_ALLOW_ALL | ||||
| 	return NF_ACCEPT; | ||||
| @ -896,10 +894,13 @@ get_counters(const struct xt_table_info *t, | ||||
| 
 | ||||
| 	/* Instead of clearing (by a previous call to memset())
 | ||||
| 	 * the counters and using adds, we set the counters | ||||
| 	 * with data used by 'current' CPU | ||||
| 	 * We dont care about preemption here. | ||||
| 	 * with data used by 'current' CPU. | ||||
| 	 * | ||||
| 	 * Bottom half has to be disabled to prevent deadlock | ||||
| 	 * if new softirq were to run and call ipt_do_table | ||||
| 	 */ | ||||
| 	curcpu = raw_smp_processor_id(); | ||||
| 	local_bh_disable(); | ||||
| 	curcpu = smp_processor_id(); | ||||
| 
 | ||||
| 	i = 0; | ||||
| 	IPT_ENTRY_ITERATE(t->entries[curcpu], | ||||
| @ -912,74 +913,22 @@ get_counters(const struct xt_table_info *t, | ||||
| 		if (cpu == curcpu) | ||||
| 			continue; | ||||
| 		i = 0; | ||||
| 		xt_info_wrlock(cpu); | ||||
| 		IPT_ENTRY_ITERATE(t->entries[cpu], | ||||
| 				  t->size, | ||||
| 				  add_entry_to_counter, | ||||
| 				  counters, | ||||
| 				  &i); | ||||
| 		xt_info_wrunlock(cpu); | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| /* We're lazy, and add to the first CPU; overflow works its fey magic
 | ||||
|  * and everything is OK. */ | ||||
| static int | ||||
| add_counter_to_entry(struct ipt_entry *e, | ||||
| 		     const struct xt_counters addme[], | ||||
| 		     unsigned int *i) | ||||
| { | ||||
| 	ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt); | ||||
| 
 | ||||
| 	(*i)++; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /* Take values from counters and add them back onto the current cpu */ | ||||
| static void put_counters(struct xt_table_info *t, | ||||
| 			 const struct xt_counters counters[]) | ||||
| { | ||||
| 	unsigned int i, cpu; | ||||
| 
 | ||||
| 	local_bh_disable(); | ||||
| 	cpu = smp_processor_id(); | ||||
| 	i = 0; | ||||
| 	IPT_ENTRY_ITERATE(t->entries[cpu], | ||||
| 			  t->size, | ||||
| 			  add_counter_to_entry, | ||||
| 			  counters, | ||||
| 			  &i); | ||||
| 	local_bh_enable(); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static inline int | ||||
| zero_entry_counter(struct ipt_entry *e, void *arg) | ||||
| { | ||||
| 	e->counters.bcnt = 0; | ||||
| 	e->counters.pcnt = 0; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| clone_counters(struct xt_table_info *newinfo, const struct xt_table_info *info) | ||||
| { | ||||
| 	unsigned int cpu; | ||||
| 	const void *loc_cpu_entry = info->entries[raw_smp_processor_id()]; | ||||
| 
 | ||||
| 	memcpy(newinfo, info, offsetof(struct xt_table_info, entries)); | ||||
| 	for_each_possible_cpu(cpu) { | ||||
| 		memcpy(newinfo->entries[cpu], loc_cpu_entry, info->size); | ||||
| 		IPT_ENTRY_ITERATE(newinfo->entries[cpu], newinfo->size, | ||||
| 				  zero_entry_counter, NULL); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static struct xt_counters * alloc_counters(struct xt_table *table) | ||||
| { | ||||
| 	unsigned int countersize; | ||||
| 	struct xt_counters *counters; | ||||
| 	struct xt_table_info *private = table->private; | ||||
| 	struct xt_table_info *info; | ||||
| 
 | ||||
| 	/* We need atomic snapshot of counters: rest doesn't change
 | ||||
| 	   (other than comefrom, which userspace doesn't care | ||||
| @ -988,30 +937,11 @@ static struct xt_counters * alloc_counters(struct xt_table *table) | ||||
| 	counters = vmalloc_node(countersize, numa_node_id()); | ||||
| 
 | ||||
| 	if (counters == NULL) | ||||
| 		goto nomem; | ||||
| 		return ERR_PTR(-ENOMEM); | ||||
| 
 | ||||
| 	info = xt_alloc_table_info(private->size); | ||||
| 	if (!info) | ||||
| 		goto free_counters; | ||||
| 
 | ||||
| 	clone_counters(info, private); | ||||
| 
 | ||||
| 	mutex_lock(&table->lock); | ||||
| 	xt_table_entry_swap_rcu(private, info); | ||||
| 	synchronize_net();	/* Wait until smoke has cleared */ | ||||
| 
 | ||||
| 	get_counters(info, counters); | ||||
| 	put_counters(private, counters); | ||||
| 	mutex_unlock(&table->lock); | ||||
| 
 | ||||
| 	xt_free_table_info(info); | ||||
| 	get_counters(private, counters); | ||||
| 
 | ||||
| 	return counters; | ||||
| 
 | ||||
|  free_counters: | ||||
| 	vfree(counters); | ||||
|  nomem: | ||||
| 	return ERR_PTR(-ENOMEM); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| @ -1306,8 +1236,9 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks, | ||||
| 	    (newinfo->number <= oldinfo->initial_entries)) | ||||
| 		module_put(t->me); | ||||
| 
 | ||||
| 	/* Get the old counters. */ | ||||
| 	/* Get the old counters, and synchronize with replace */ | ||||
| 	get_counters(oldinfo, counters); | ||||
| 
 | ||||
| 	/* Decrease module usage counts and free resource */ | ||||
| 	loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; | ||||
| 	IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry, | ||||
| @ -1377,11 +1308,23 @@ do_replace(struct net *net, void __user *user, unsigned int len) | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| /* We're lazy, and add to the first CPU; overflow works its fey magic
 | ||||
|  * and everything is OK. */ | ||||
| static int | ||||
| add_counter_to_entry(struct ipt_entry *e, | ||||
| 		     const struct xt_counters addme[], | ||||
| 		     unsigned int *i) | ||||
| { | ||||
| 	ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt); | ||||
| 
 | ||||
| 	(*i)++; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| do_add_counters(struct net *net, void __user *user, unsigned int len, int compat) | ||||
| { | ||||
| 	unsigned int i; | ||||
| 	unsigned int i, curcpu; | ||||
| 	struct xt_counters_info tmp; | ||||
| 	struct xt_counters *paddc; | ||||
| 	unsigned int num_counters; | ||||
| @ -1437,25 +1380,26 @@ do_add_counters(struct net *net, void __user *user, unsigned int len, int compat | ||||
| 		goto free; | ||||
| 	} | ||||
| 
 | ||||
| 	mutex_lock(&t->lock); | ||||
| 	local_bh_disable(); | ||||
| 	private = t->private; | ||||
| 	if (private->number != num_counters) { | ||||
| 		ret = -EINVAL; | ||||
| 		goto unlock_up_free; | ||||
| 	} | ||||
| 
 | ||||
| 	preempt_disable(); | ||||
| 	i = 0; | ||||
| 	/* Choose the copy that is on our node */ | ||||
| 	loc_cpu_entry = private->entries[raw_smp_processor_id()]; | ||||
| 	curcpu = smp_processor_id(); | ||||
| 	loc_cpu_entry = private->entries[curcpu]; | ||||
| 	xt_info_wrlock(curcpu); | ||||
| 	IPT_ENTRY_ITERATE(loc_cpu_entry, | ||||
| 			  private->size, | ||||
| 			  add_counter_to_entry, | ||||
| 			  paddc, | ||||
| 			  &i); | ||||
| 	preempt_enable(); | ||||
| 	xt_info_wrunlock(curcpu); | ||||
|  unlock_up_free: | ||||
| 	mutex_unlock(&t->lock); | ||||
| 	local_bh_enable(); | ||||
| 	xt_table_unlock(t); | ||||
| 	module_put(t->me); | ||||
|  free: | ||||
|  | ||||
| @ -3397,7 +3397,7 @@ int __init ip_rt_init(void) | ||||
| 					0, | ||||
| 					&rt_hash_log, | ||||
| 					&rt_hash_mask, | ||||
| 					0); | ||||
| 					rhash_entries ? 0 : 512 * 1024); | ||||
| 	memset(rt_hash_table, 0, (rt_hash_mask + 1) * sizeof(struct rt_hash_bucket)); | ||||
| 	rt_hash_lock_init(); | ||||
| 
 | ||||
|  | ||||
| @ -365,9 +365,9 @@ ip6t_do_table(struct sk_buff *skb, | ||||
| 
 | ||||
| 	IP_NF_ASSERT(table->valid_hooks & (1 << hook)); | ||||
| 
 | ||||
| 	rcu_read_lock_bh(); | ||||
| 	private = rcu_dereference(table->private); | ||||
| 	table_base = rcu_dereference(private->entries[smp_processor_id()]); | ||||
| 	xt_info_rdlock_bh(); | ||||
| 	private = table->private; | ||||
| 	table_base = private->entries[smp_processor_id()]; | ||||
| 
 | ||||
| 	e = get_entry(table_base, private->hook_entry[hook]); | ||||
| 
 | ||||
| @ -466,7 +466,7 @@ ip6t_do_table(struct sk_buff *skb, | ||||
| #ifdef CONFIG_NETFILTER_DEBUG | ||||
| 	((struct ip6t_entry *)table_base)->comefrom = NETFILTER_LINK_POISON; | ||||
| #endif | ||||
| 	rcu_read_unlock_bh(); | ||||
| 	xt_info_rdunlock_bh(); | ||||
| 
 | ||||
| #ifdef DEBUG_ALLOW_ALL | ||||
| 	return NF_ACCEPT; | ||||
| @ -926,9 +926,12 @@ get_counters(const struct xt_table_info *t, | ||||
| 	/* Instead of clearing (by a previous call to memset())
 | ||||
| 	 * the counters and using adds, we set the counters | ||||
| 	 * with data used by 'current' CPU | ||||
| 	 * We dont care about preemption here. | ||||
| 	 * | ||||
| 	 * Bottom half has to be disabled to prevent deadlock | ||||
| 	 * if new softirq were to run and call ipt_do_table | ||||
| 	 */ | ||||
| 	curcpu = raw_smp_processor_id(); | ||||
| 	local_bh_disable(); | ||||
| 	curcpu = smp_processor_id(); | ||||
| 
 | ||||
| 	i = 0; | ||||
| 	IP6T_ENTRY_ITERATE(t->entries[curcpu], | ||||
| @ -941,72 +944,22 @@ get_counters(const struct xt_table_info *t, | ||||
| 		if (cpu == curcpu) | ||||
| 			continue; | ||||
| 		i = 0; | ||||
| 		xt_info_wrlock(cpu); | ||||
| 		IP6T_ENTRY_ITERATE(t->entries[cpu], | ||||
| 				  t->size, | ||||
| 				  add_entry_to_counter, | ||||
| 				  counters, | ||||
| 				  &i); | ||||
| 		xt_info_wrunlock(cpu); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /* We're lazy, and add to the first CPU; overflow works its fey magic
 | ||||
|  * and everything is OK. */ | ||||
| static int | ||||
| add_counter_to_entry(struct ip6t_entry *e, | ||||
| 		     const struct xt_counters addme[], | ||||
| 		     unsigned int *i) | ||||
| { | ||||
| 	ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt); | ||||
| 
 | ||||
| 	(*i)++; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /* Take values from counters and add them back onto the current cpu */ | ||||
| static void put_counters(struct xt_table_info *t, | ||||
| 			 const struct xt_counters counters[]) | ||||
| { | ||||
| 	unsigned int i, cpu; | ||||
| 
 | ||||
| 	local_bh_disable(); | ||||
| 	cpu = smp_processor_id(); | ||||
| 	i = 0; | ||||
| 	IP6T_ENTRY_ITERATE(t->entries[cpu], | ||||
| 			   t->size, | ||||
| 			   add_counter_to_entry, | ||||
| 			   counters, | ||||
| 			   &i); | ||||
| 	local_bh_enable(); | ||||
| } | ||||
| 
 | ||||
| static inline int | ||||
| zero_entry_counter(struct ip6t_entry *e, void *arg) | ||||
| { | ||||
| 	e->counters.bcnt = 0; | ||||
| 	e->counters.pcnt = 0; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| clone_counters(struct xt_table_info *newinfo, const struct xt_table_info *info) | ||||
| { | ||||
| 	unsigned int cpu; | ||||
| 	const void *loc_cpu_entry = info->entries[raw_smp_processor_id()]; | ||||
| 
 | ||||
| 	memcpy(newinfo, info, offsetof(struct xt_table_info, entries)); | ||||
| 	for_each_possible_cpu(cpu) { | ||||
| 		memcpy(newinfo->entries[cpu], loc_cpu_entry, info->size); | ||||
| 		IP6T_ENTRY_ITERATE(newinfo->entries[cpu], newinfo->size, | ||||
| 				   zero_entry_counter, NULL); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static struct xt_counters *alloc_counters(struct xt_table *table) | ||||
| { | ||||
| 	unsigned int countersize; | ||||
| 	struct xt_counters *counters; | ||||
| 	struct xt_table_info *private = table->private; | ||||
| 	struct xt_table_info *info; | ||||
| 
 | ||||
| 	/* We need atomic snapshot of counters: rest doesn't change
 | ||||
| 	   (other than comefrom, which userspace doesn't care | ||||
| @ -1015,30 +968,11 @@ static struct xt_counters *alloc_counters(struct xt_table *table) | ||||
| 	counters = vmalloc_node(countersize, numa_node_id()); | ||||
| 
 | ||||
| 	if (counters == NULL) | ||||
| 		goto nomem; | ||||
| 		return ERR_PTR(-ENOMEM); | ||||
| 
 | ||||
| 	info = xt_alloc_table_info(private->size); | ||||
| 	if (!info) | ||||
| 		goto free_counters; | ||||
| 
 | ||||
| 	clone_counters(info, private); | ||||
| 
 | ||||
| 	mutex_lock(&table->lock); | ||||
| 	xt_table_entry_swap_rcu(private, info); | ||||
| 	synchronize_net();	/* Wait until smoke has cleared */ | ||||
| 
 | ||||
| 	get_counters(info, counters); | ||||
| 	put_counters(private, counters); | ||||
| 	mutex_unlock(&table->lock); | ||||
| 
 | ||||
| 	xt_free_table_info(info); | ||||
| 	get_counters(private, counters); | ||||
| 
 | ||||
| 	return counters; | ||||
| 
 | ||||
|  free_counters: | ||||
| 	vfree(counters); | ||||
|  nomem: | ||||
| 	return ERR_PTR(-ENOMEM); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| @ -1334,8 +1268,9 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks, | ||||
| 	    (newinfo->number <= oldinfo->initial_entries)) | ||||
| 		module_put(t->me); | ||||
| 
 | ||||
| 	/* Get the old counters. */ | ||||
| 	/* Get the old counters, and synchronize with replace */ | ||||
| 	get_counters(oldinfo, counters); | ||||
| 
 | ||||
| 	/* Decrease module usage counts and free resource */ | ||||
| 	loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; | ||||
| 	IP6T_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry, | ||||
| @ -1405,11 +1340,24 @@ do_replace(struct net *net, void __user *user, unsigned int len) | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| /* We're lazy, and add to the first CPU; overflow works its fey magic
 | ||||
|  * and everything is OK. */ | ||||
| static int | ||||
| add_counter_to_entry(struct ip6t_entry *e, | ||||
| 		     const struct xt_counters addme[], | ||||
| 		     unsigned int *i) | ||||
| { | ||||
| 	ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt); | ||||
| 
 | ||||
| 	(*i)++; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| do_add_counters(struct net *net, void __user *user, unsigned int len, | ||||
| 		int compat) | ||||
| { | ||||
| 	unsigned int i; | ||||
| 	unsigned int i, curcpu; | ||||
| 	struct xt_counters_info tmp; | ||||
| 	struct xt_counters *paddc; | ||||
| 	unsigned int num_counters; | ||||
| @ -1465,25 +1413,28 @@ do_add_counters(struct net *net, void __user *user, unsigned int len, | ||||
| 		goto free; | ||||
| 	} | ||||
| 
 | ||||
| 	mutex_lock(&t->lock); | ||||
| 
 | ||||
| 	local_bh_disable(); | ||||
| 	private = t->private; | ||||
| 	if (private->number != num_counters) { | ||||
| 		ret = -EINVAL; | ||||
| 		goto unlock_up_free; | ||||
| 	} | ||||
| 
 | ||||
| 	preempt_disable(); | ||||
| 	i = 0; | ||||
| 	/* Choose the copy that is on our node */ | ||||
| 	loc_cpu_entry = private->entries[raw_smp_processor_id()]; | ||||
| 	curcpu = smp_processor_id(); | ||||
| 	xt_info_wrlock(curcpu); | ||||
| 	loc_cpu_entry = private->entries[curcpu]; | ||||
| 	IP6T_ENTRY_ITERATE(loc_cpu_entry, | ||||
| 			  private->size, | ||||
| 			  add_counter_to_entry, | ||||
| 			  paddc, | ||||
| 			  &i); | ||||
| 	preempt_enable(); | ||||
| 	xt_info_wrunlock(curcpu); | ||||
| 
 | ||||
|  unlock_up_free: | ||||
| 	mutex_unlock(&t->lock); | ||||
| 	local_bh_enable(); | ||||
| 	xt_table_unlock(t); | ||||
| 	module_put(t->me); | ||||
|  free: | ||||
|  | ||||
| @ -275,6 +275,8 @@ config NF_CT_NETLINK | ||||
| 	help | ||||
| 	  This option enables support for a netlink-based userspace interface | ||||
| 
 | ||||
| endif # NF_CONNTRACK | ||||
| 
 | ||||
| # transparent proxy support | ||||
| config NETFILTER_TPROXY | ||||
| 	tristate "Transparent proxying support (EXPERIMENTAL)" | ||||
| @ -290,8 +292,6 @@ config NETFILTER_TPROXY | ||||
| 
 | ||||
| 	  To compile it as a module, choose M here.  If unsure, say N. | ||||
| 
 | ||||
| endif # NF_CONNTRACK | ||||
| 
 | ||||
| config NETFILTER_XTABLES | ||||
| 	tristate "Netfilter Xtables support (required for ip_tables)" | ||||
| 	default m if NETFILTER_ADVANCED=n | ||||
|  | ||||
| @ -633,6 +633,8 @@ static int dccp_to_nlattr(struct sk_buff *skb, struct nlattr *nla, | ||||
| 	if (!nest_parms) | ||||
| 		goto nla_put_failure; | ||||
| 	NLA_PUT_U8(skb, CTA_PROTOINFO_DCCP_STATE, ct->proto.dccp.state); | ||||
| 	NLA_PUT_U8(skb, CTA_PROTOINFO_DCCP_ROLE, | ||||
| 		   ct->proto.dccp.role[IP_CT_DIR_ORIGINAL]); | ||||
| 	nla_nest_end(skb, nest_parms); | ||||
| 	read_unlock_bh(&dccp_lock); | ||||
| 	return 0; | ||||
| @ -644,6 +646,7 @@ nla_put_failure: | ||||
| 
 | ||||
| static const struct nla_policy dccp_nla_policy[CTA_PROTOINFO_DCCP_MAX + 1] = { | ||||
| 	[CTA_PROTOINFO_DCCP_STATE]	= { .type = NLA_U8 }, | ||||
| 	[CTA_PROTOINFO_DCCP_ROLE]	= { .type = NLA_U8 }, | ||||
| }; | ||||
| 
 | ||||
| static int nlattr_to_dccp(struct nlattr *cda[], struct nf_conn *ct) | ||||
| @ -661,11 +664,21 @@ static int nlattr_to_dccp(struct nlattr *cda[], struct nf_conn *ct) | ||||
| 		return err; | ||||
| 
 | ||||
| 	if (!tb[CTA_PROTOINFO_DCCP_STATE] || | ||||
| 	    nla_get_u8(tb[CTA_PROTOINFO_DCCP_STATE]) >= CT_DCCP_IGNORE) | ||||
| 	    !tb[CTA_PROTOINFO_DCCP_ROLE] || | ||||
| 	    nla_get_u8(tb[CTA_PROTOINFO_DCCP_ROLE]) > CT_DCCP_ROLE_MAX || | ||||
| 	    nla_get_u8(tb[CTA_PROTOINFO_DCCP_STATE]) >= CT_DCCP_IGNORE) { | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 
 | ||||
| 	write_lock_bh(&dccp_lock); | ||||
| 	ct->proto.dccp.state = nla_get_u8(tb[CTA_PROTOINFO_DCCP_STATE]); | ||||
| 	if (nla_get_u8(tb[CTA_PROTOINFO_DCCP_ROLE]) == CT_DCCP_ROLE_CLIENT) { | ||||
| 		ct->proto.dccp.role[IP_CT_DIR_ORIGINAL] = CT_DCCP_ROLE_CLIENT; | ||||
| 		ct->proto.dccp.role[IP_CT_DIR_REPLY] = CT_DCCP_ROLE_SERVER; | ||||
| 	} else { | ||||
| 		ct->proto.dccp.role[IP_CT_DIR_ORIGINAL] = CT_DCCP_ROLE_SERVER; | ||||
| 		ct->proto.dccp.role[IP_CT_DIR_REPLY] = CT_DCCP_ROLE_CLIENT; | ||||
| 	} | ||||
| 	write_unlock_bh(&dccp_lock); | ||||
| 	return 0; | ||||
| } | ||||
| @ -777,6 +790,7 @@ static struct nf_conntrack_l4proto dccp_proto6 __read_mostly = { | ||||
| 	.print_conntrack	= dccp_print_conntrack, | ||||
| #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | ||||
| 	.to_nlattr		= dccp_to_nlattr, | ||||
| 	.nlattr_size		= dccp_nlattr_size, | ||||
| 	.from_nlattr		= nlattr_to_dccp, | ||||
| 	.tuple_to_nlattr	= nf_ct_port_tuple_to_nlattr, | ||||
| 	.nlattr_tuple_size	= nf_ct_port_nlattr_tuple_size, | ||||
|  | ||||
| @ -204,6 +204,7 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 __read_mostly = | ||||
| 	.error			= udplite_error, | ||||
| #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | ||||
| 	.tuple_to_nlattr	= nf_ct_port_tuple_to_nlattr, | ||||
| 	.nlattr_tuple_size	= nf_ct_port_nlattr_tuple_size, | ||||
| 	.nlattr_to_tuple	= nf_ct_port_nlattr_to_tuple, | ||||
| 	.nla_policy		= nf_ct_port_nla_policy, | ||||
| #endif | ||||
|  | ||||
| @ -625,20 +625,6 @@ void xt_free_table_info(struct xt_table_info *info) | ||||
| } | ||||
| EXPORT_SYMBOL(xt_free_table_info); | ||||
| 
 | ||||
| void xt_table_entry_swap_rcu(struct xt_table_info *oldinfo, | ||||
| 			     struct xt_table_info *newinfo) | ||||
| { | ||||
| 	unsigned int cpu; | ||||
| 
 | ||||
| 	for_each_possible_cpu(cpu) { | ||||
| 		void *p = oldinfo->entries[cpu]; | ||||
| 		rcu_assign_pointer(oldinfo->entries[cpu], newinfo->entries[cpu]); | ||||
| 		newinfo->entries[cpu] = p; | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
| EXPORT_SYMBOL_GPL(xt_table_entry_swap_rcu); | ||||
| 
 | ||||
| /* Find table by name, grabs mutex & ref.  Returns ERR_PTR() on error. */ | ||||
| struct xt_table *xt_find_table_lock(struct net *net, u_int8_t af, | ||||
| 				    const char *name) | ||||
| @ -676,32 +662,43 @@ void xt_compat_unlock(u_int8_t af) | ||||
| EXPORT_SYMBOL_GPL(xt_compat_unlock); | ||||
| #endif | ||||
| 
 | ||||
| DEFINE_PER_CPU(struct xt_info_lock, xt_info_locks); | ||||
| EXPORT_PER_CPU_SYMBOL_GPL(xt_info_locks); | ||||
| 
 | ||||
| 
 | ||||
| struct xt_table_info * | ||||
| xt_replace_table(struct xt_table *table, | ||||
| 	      unsigned int num_counters, | ||||
| 	      struct xt_table_info *newinfo, | ||||
| 	      int *error) | ||||
| { | ||||
| 	struct xt_table_info *oldinfo, *private; | ||||
| 	struct xt_table_info *private; | ||||
| 
 | ||||
| 	/* Do the substitution. */ | ||||
| 	mutex_lock(&table->lock); | ||||
| 	local_bh_disable(); | ||||
| 	private = table->private; | ||||
| 
 | ||||
| 	/* Check inside lock: is the old number correct? */ | ||||
| 	if (num_counters != private->number) { | ||||
| 		duprintf("num_counters != table->private->number (%u/%u)\n", | ||||
| 			 num_counters, private->number); | ||||
| 		mutex_unlock(&table->lock); | ||||
| 		local_bh_enable(); | ||||
| 		*error = -EAGAIN; | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	oldinfo = private; | ||||
| 	rcu_assign_pointer(table->private, newinfo); | ||||
| 	newinfo->initial_entries = oldinfo->initial_entries; | ||||
| 	mutex_unlock(&table->lock); | ||||
| 
 | ||||
| 	synchronize_net(); | ||||
| 	return oldinfo; | ||||
| 	table->private = newinfo; | ||||
| 	newinfo->initial_entries = private->initial_entries; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Even though table entries have now been swapped, other CPU's | ||||
| 	 * may still be using the old entries. This is okay, because | ||||
| 	 * resynchronization happens because of the locking done | ||||
| 	 * during the get_counters() routine. | ||||
| 	 */ | ||||
| 	local_bh_enable(); | ||||
| 
 | ||||
| 	return private; | ||||
| } | ||||
| EXPORT_SYMBOL_GPL(xt_replace_table); | ||||
| 
 | ||||
| @ -734,7 +731,6 @@ struct xt_table *xt_register_table(struct net *net, struct xt_table *table, | ||||
| 
 | ||||
| 	/* Simplifies replace_table code. */ | ||||
| 	table->private = bootstrap; | ||||
| 	mutex_init(&table->lock); | ||||
| 
 | ||||
| 	if (!xt_replace_table(table, 0, newinfo, &ret)) | ||||
| 		goto unlock; | ||||
| @ -1147,7 +1143,14 @@ static struct pernet_operations xt_net_ops = { | ||||
| 
 | ||||
| static int __init xt_init(void) | ||||
| { | ||||
| 	int i, rv; | ||||
| 	unsigned int i; | ||||
| 	int rv; | ||||
| 
 | ||||
| 	for_each_possible_cpu(i) { | ||||
| 		struct xt_info_lock *lock = &per_cpu(xt_info_locks, i); | ||||
| 		spin_lock_init(&lock->lock); | ||||
| 		lock->readers = 0; | ||||
| 	} | ||||
| 
 | ||||
| 	xt = kmalloc(sizeof(struct xt_af) * NFPROTO_NUMPROTO, GFP_KERNEL); | ||||
| 	if (!xt) | ||||
|  | ||||
| @ -474,7 +474,7 @@ static ssize_t recent_old_proc_write(struct file *file, | ||||
| 	struct recent_table *t = pde->data; | ||||
| 	struct recent_entry *e; | ||||
| 	char buf[sizeof("+255.255.255.255")], *c = buf; | ||||
| 	__be32 addr; | ||||
| 	union nf_inet_addr addr = {}; | ||||
| 	int add; | ||||
| 
 | ||||
| 	if (size > sizeof(buf)) | ||||
| @ -506,14 +506,13 @@ static ssize_t recent_old_proc_write(struct file *file, | ||||
| 		add = 1; | ||||
| 		break; | ||||
| 	} | ||||
| 	addr = in_aton(c); | ||||
| 	addr.ip = in_aton(c); | ||||
| 
 | ||||
| 	spin_lock_bh(&recent_lock); | ||||
| 	e = recent_entry_lookup(t, (const void *)&addr, NFPROTO_IPV4, 0); | ||||
| 	e = recent_entry_lookup(t, &addr, NFPROTO_IPV4, 0); | ||||
| 	if (e == NULL) { | ||||
| 		if (add) | ||||
| 			recent_entry_init(t, (const void *)&addr, | ||||
| 					  NFPROTO_IPV4, 0); | ||||
| 			recent_entry_init(t, &addr, NFPROTO_IPV4, 0); | ||||
| 	} else { | ||||
| 		if (add) | ||||
| 			recent_entry_update(t, e); | ||||
|  | ||||
| @ -794,7 +794,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | ||||
| { | ||||
| 	static xfrm_address_t saddr_wildcard = { }; | ||||
| 	struct net *net = xp_net(pol); | ||||
| 	unsigned int h; | ||||
| 	unsigned int h, h_wildcard; | ||||
| 	struct hlist_node *entry; | ||||
| 	struct xfrm_state *x, *x0, *to_put; | ||||
| 	int acquire_in_progress = 0; | ||||
| @ -819,8 +819,8 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | ||||
| 	if (best) | ||||
| 		goto found; | ||||
| 
 | ||||
| 	h = xfrm_dst_hash(net, daddr, &saddr_wildcard, tmpl->reqid, family); | ||||
| 	hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) { | ||||
| 	h_wildcard = xfrm_dst_hash(net, daddr, &saddr_wildcard, tmpl->reqid, family); | ||||
| 	hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h_wildcard, bydst) { | ||||
| 		if (x->props.family == family && | ||||
| 		    x->props.reqid == tmpl->reqid && | ||||
| 		    !(x->props.flags & XFRM_STATE_WILDRECV) && | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user